問(wèn)題描述
我目前正在編寫(xiě)一個(gè) IntelliJ 插件.我希望能夠存儲(chǔ)/恢復(fù)一組選項(xiàng)卡以在不同的選項(xiàng)卡會(huì)話(huà)之間切換(類(lèi)似于 會(huì)話(huà)管理器 或 會(huì)話(huà)好友).
I am currently at the move to write an IntelliJ plugin. I want to be able to store/restore a set of tabs to switch between different tab sessions (comparable to browser plugins like Session Manager or Session Buddy).
因此我基本上需要三種類(lèi)型的動(dòng)作:
Therefore i need basically three types of actions:
- 讀取打開(kāi)的選項(xiàng)卡(使用哪個(gè)文件和編輯器?)
- 將該信息永久存儲(chǔ)為選項(xiàng)卡會(huì)話(huà)
- 打開(kāi)選定會(huì)話(huà)的標(biāo)簽并關(guān)閉所有其他標(biāo)簽
我查看了可用的操作:IdeActions.java - 似乎沒(méi)有我正在尋找的東西.但也許我看錯(cuò)了地方.誰(shuí)能告訴我我想要實(shí)現(xiàn)的目標(biāo)是否可行,并給我一些正確方向的指點(diǎn)?
I looked at the available actions: IdeActions.java - it seems that there is not what i am searching for. But maybe i am looking at the wrong place. Can anyone tell me if what's i am trying to achieve is possible and give me some pointers in the right direction?
我成功創(chuàng)建了插件,它可以在 Github 上找到:http://alp82.github.com/idea-tabsession/
I succesfully created the plugin and it's available at Github: http://alp82.github.com/idea-tabsession/
它在官方插件庫(kù)中可用:Tab Session.
It is available in the official plugin repository: Tab Session.
這是關(guān)于拆分窗口的后續(xù)問(wèn)題:檢索和設(shè)置拆分窗口設(shè)置
Here is a follow-up question regarding splitted windows: Retrieving and setting split window settings
推薦答案
2017年更新
我停止支持此插件,因?yàn)?IDEA 已經(jīng)支持該功能.您可以輕松地保存和加載上下文,如下所示:https://github.com/alp82/idea-tabsession#discontinued
插件已準(zhǔn)備就緒,可以在 IDEA -> 設(shè)置 -> 插件中下載.源代碼位于:https://github.com/alp82/idea-tabsession
The plugin is up and ready and can be downloaded in IDEA -> Settings -> Plugins. Source code is available at: https://github.com/alp82/idea-tabsession
要讀取當(dāng)前打開(kāi)的選項(xiàng)卡,請(qǐng)使用 EditorFactory
和 FileDocumentManager
單例:
To read which tabs are open right now, use the EditorFactory
and FileDocumentManager
Singletons:
Editor[] editors = EditorFactory.getInstance().getAllEditors();
FileDocumentManager fileDocManager = FileDocumentManager.getInstance();
for(Editor editor : editors) {
VirtualFile vf = fileDocManager.getFile(editor.getDocument());
String path = vf.getCanonicalPath();
System.out.println("path = " + path);
}
要打開(kāi)選項(xiàng)卡,請(qǐng)使用 FileEditorManager
單例(files
是規(guī)范路徑的字符串?dāng)?shù)組):
To open tabs use the FileEditorManager
singleton (files
being a String Array of canonical paths):
FileEditorManager fileEditorManager = FileEditorManager.getInstance(project);
for(String path : files) {
System.out.println("path = " + path);
VirtualFile vf = LocalFileSystem.getInstance().findFileByPath(path);
fileEditorManager.openFile(vf, true, true);
}
長(zhǎng)答案
先決條件
- 激活插件開(kāi)發(fā)、Groovy 和 UI Designer 插件
- 新建項(xiàng)目 -> IntelliJ IDEA 插件
簽出 IDEA Community Edition 源代碼到任何文件夾:
git clone git://git.jetbrains.org/idea/community.git idea
配置 IDEA SDK 和創(chuàng)建插件
插件結(jié)構(gòu)
創(chuàng)建插件后,您需要編輯位于 META-INF 文件夾中的 plugin.xml.修改id
、name
和description
.
我們需要一個(gè)用于持久存儲(chǔ)的配置文件.在 src
文件夾中創(chuàng)建一個(gè) mystorage.xml
文件.現(xiàn)在是時(shí)候創(chuàng)建所需的文件了:
We need a configuration file for persistant storage. Create a mystorage.xml
file in your src
folder. It's now time to create the needed files:
SessionComponent.java(使用Add Project Component
向?qū)?chuàng)建它以自動(dòng)創(chuàng)建所需的xml設(shè)置):
SessionComponent.java (create it with the Add Project Component
wizard to automatically create the needed xml settings):
@State(
name = "SessionComponent",
storages = {
@Storage(id = "default", file = StoragePathMacros.PROJECT_FILE),
@Storage(id = "dir", file = StoragePathMacros.PROJECT_CONFIG_DIR + "/mystorage.xml", scheme = StorageScheme.DIRECTORY_BASED)
}
)
public class SessionComponent implements ProjectComponent, PersistentStateComponent<SessionState> {
Project project;
SessionState sessionState;
public SessionComponent(Project project) {
this.project = project;
sessionState = new SessionState();
}
public void initComponent() {
// TODO: insert component initialization logic here
}
@Override
public void loadState(SessionState sessionState) {
System.out.println("load sessionState = " + sessionState);
this.sessionState = sessionState;
}
public void projectOpened() {
// called when project is opened
}
public void projectClosed() {
// called when project is being closed
}
@Nullable
@Override
public SessionState getState() {
System.out.println("save sessionState = " + sessionState);
return sessionState;
}
public void disposeComponent() {
// TODO: insert component disposal logic here
}
@NotNull
public String getComponentName() {
return "SessionComponent";
}
public int saveCurrentTabs() {
Editor[] editors = getOpenEditors();
FileEditorManager fileEditorManager = FileEditorManager.getInstance(project);
VirtualFile[] selectedFiles = fileEditorManager.getSelectedFiles();
FileDocumentManager fileDocManager = FileDocumentManager.getInstance();
sessionState.files = new String[editors.length];
int i = 0;
for(Editor editor : editors) {
VirtualFile vf = fileDocManager.getFile(editor.getDocument());
String path = vf.getCanonicalPath();
System.out.println("path = " + path);
if(path.equals(selectedFiles[0].getCanonicalPath())) {
sessionState.focusedFile = path;
}
sessionState.files[i] = path;
i++;
}
return editors.length;
}
public int loadSession() {
closeCurrentTabs();
FileEditorManager fileEditorManager = FileEditorManager.getInstance(project);
for(String path : sessionState.files) {
System.out.println("path = " + path);
VirtualFile vf = LocalFileSystem.getInstance().findFileByPath(path);
fileEditorManager.openFile(vf, true, true);
}
return sessionState.files.length;
}
public void closeCurrentTabs() {
Editor[] editors = getOpenEditors();
FileEditorManager fileEditorManager = FileEditorManager.getInstance(project);
FileDocumentManager fileDocManager = FileDocumentManager.getInstance();
for(Editor editor : editors) {
System.out.println("editor = " + editor);
VirtualFile vf = fileDocManager.getFile(editor.getDocument());
fileEditorManager.closeFile(vf);
}
}
public void showMessage(String htmlText) {
StatusBar statusBar = WindowManager.getInstance().getStatusBar(project);
JBPopupFactory.getInstance()
.createHtmlTextBalloonBuilder(htmlText, MessageType.INFO, null)
.setFadeoutTime(7500)
.createBalloon()
.show(RelativePoint.getCenterOf(statusBar.getComponent()), Balloon.Position.atRight);
}
private Editor[] getOpenEditors() {
return EditorFactory.getInstance().getAllEditors();
}
}
我們還需要存儲(chǔ)類(lèi):
public class SessionState {
public String[] files = new String[0];
public String focusedFile = "";
public String toString() {
String result = "";
for (String file : files) {
result += file + ", ";
}
result += "selected: " + focusedFile;
return result;
}
}
組件類(lèi)應(yīng)該在你的 plugin.xml 中有一個(gè)像這樣的條目:
The component class should have an entry in your plugin.xml like this one:
<project-components>
<component>
<implementation-class>my.package.SessionComponent</implementation-class>
</component>
</project-components>
組件類(lèi)提供了所有需要的功能,但從未使用過(guò).因此,我們需要執(zhí)行加載和保存操作:
The component class offers all needed functionality, but is never be used. Therefore, we need actions to perform loading and saving:
保存.java:
public class Save extends AnAction {
public Save() {
super();
}
public void actionPerformed(AnActionEvent event) {
Project project = event.getData(PlatformDataKeys.PROJECT);
SessionComponent sessionComponent = project.getComponent(SessionComponent.class);
int tabCount = sessionComponent.saveCurrentTabs();
String htmlText = "Saved " + String.valueOf(tabCount) + " tabs";
sessionComponent.showMessage(htmlText);
}
}
加載.java:
public class Load extends AnAction {
public Load() {
super();
}
public void actionPerformed(AnActionEvent event) {
Project project = event.getData(PlatformDataKeys.PROJECT);
SessionComponent sessionComponent = project.getComponent(SessionComponent.class);
int tabCount = sessionComponent.loadSession();
String htmlText = "Loaded " + String.valueOf(tabCount) + " tabs";
sessionComponent.showMessage(htmlText);
}
}
Aaand...行動(dòng)!
我們需要的最后一件事是選擇這些操作的用戶(hù)界面.只需將其放在您的 plugin.xml
中:
<actions>
<!-- Add your actions here -->
<group id="MyPlugin.SampleMenu" text="_Sample Menu" description="Sample menu">
<add-to-group group-id="MainMenu" anchor="last" />
<action id="MyPlugin.Save" class="my.package.Save" text="_Save" description="A test menu item" />
<action id="MyPlugin.Load" class="my.package.Load" text="_Load" description="A test menu item" />
</group>
</actions>
插件部署
基本功能已準(zhǔn)備就緒.在部署此插件并將其發(fā)布到開(kāi)源社區(qū)之前,我將添加對(duì)多個(gè)會(huì)話(huà)和其他一些簡(jiǎn)潔內(nèi)容的支持.鏈接將在此處發(fā)布,當(dāng)它在線時(shí).
Plugin Deployment
The basic functionality is ready. I will add support for multiple sessions and some other neat stuff before deploying this plugin and releasing it to the open-source community. Link will be posted here, when it's online.
這篇關(guān)于IntelliJ IDEA 插件開(kāi)發(fā):保存選項(xiàng)卡組,持久保存并在用戶(hù)請(qǐng)求時(shí)重新加載一組選項(xiàng)卡的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,也希望大家多多支持html5模板網(wǎng)!