20

私は現在、IntelliJ プラグインを作成しようとしています。一連のタブを保存/復元して、異なるタブセッションを切り替えることができるようにしたい ( Session ManagerSession Buddyなどのブラウザープラグインに匹敵する)。

したがって、基本的に3種類のアクションが必要です。

  1. 開いているタブを読む (どのファイルとエディターが使用されているか?)
  2. その情報をタブ セッションとして永続的に保存する
  3. 選択したセッションのタブを開き、他のすべてを閉じます

利用可能なアクションを調べました: IdeActions.java - 探しているものがないようです。しかし、多分私は間違った場所を見ています。私が達成しようとしていることが可能かどうかを誰かに教えてもらえますか?正しい方向への指針を教えてください。

アップデート

プラグインの作成に成功し、Github で入手できます: http://alp82.github.com/idea-tabsession/

公式のプラグイン リポジトリで利用できます: Tab Session

更新 2

分割されたウィンドウに関するフォローアップの質問は次のとおりです。分割ウィンドウ設定の取得と設定

4

1 に答える 1

24

2017年更新

IDEA はすでにこの機能をサポートしているため、このプラグインのサポートを中止します。ここに示すように、コンテキストを簡単に保存およびロードできます: https://github.com/alp82/idea-tabsession#discontinued

アップデート

プラグインは準備ができており、IDEA -> 設定 -> プラグインでダウンロードできます。ソース コードはhttps://github.com/alp82/idea-tabsessionで入手できます。

簡潔な答え

現在どのタブが開いているかを読み取るには、EditorFactoryおよびFileDocumentManagerSingletonsを使用します。

    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);
    }

タブを開くには、FileEditorManagerシングルトン (files正規パスの文字列配列) を使用します。

    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);
    }

長い答え

前提条件

  1. Plugin Development、Groovy、および UI Designer プラグインをアクティブ化します。
  2. 新しいプロジェクト -> IntelliJ IDEA プラグイン
  3. IDEA Community Edition ソースを任意のフォルダーにチェックアウトします。

    git clone git://git.jetbrains.org/idea/community.git idea
    
  4. IDEA SDK の構成とプラグインの作成

プラグインの構造

プラグインを作成したら、META-INF フォルダーにある plugin.xml を編集する必要があります。idnameおよび を変更しdescriptionます。

永続ストレージ用の構成ファイルが必要です。mystorage.xmlフォルダーにファイルを作成しsrcます。必要なファイルを作成します。

SessionComponent.java (Add Project Componentウィザードを使用して作成し、必要な xml 設定を自動的に作成します):

@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();
    }

}

ストレージ クラスも必要です。

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;
    }
}

コンポーネント クラスには、次のような plugin.xml のエントリが必要です。

<project-components>
  <component>
    <implementation-class>my.package.SessionComponent</implementation-class>
  </component>
</project-components>

コンポーネント クラスは必要なすべての機能を提供しますが、使用されることはありません。したがって、読み込みと保存を実行するためのアクションが必要です。

保存.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);
    }

}

Load.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);
    }

}

ああ、そして... アクション!

最後に必要なのは、これらのアクションを選択するためのユーザー インターフェイスです。これをあなたのに入れるだけ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>

プラグインの展開

基本的な機能は揃っています。このプラグインをデプロイしてオープンソース コミュニティにリリースする前に、複数のセッションやその他の優れた機能のサポートを追加します。リンクは、オンラインになったときにここに掲載されます。

于 2013-03-30T13:19:51.823 に答える