🐙

Kotlin + GitHub Template ではじめる、初めての IntelliJ IDEA プラグイン開発

2021/10/16に公開

初めて IntelliJ IDEA のプラグインを作ってみたので、その紹介も兼ねて GitHub Template と Kotlin での IntelliJ IDEA のプラグインの作り方をまとめてみます。

作ってみたもの 📋

GitHub や GitLab 上のコードリンクを手軽にコピーできるプラグインを作りました。
Markdown 形式のリンクとしてコピーすることもできます。

https://plugins.jetbrains.com/plugin/17756-copy-git-link

https://www.youtube.com/watch?v=cqcjaXt_BJs

標準の機能でも、コンテキストメニュー > Open in > GitHub でコードリンクをブラウザで開くことは出来るのですが、自分のユースケースとしてはコードリンクを何か別の文書に貼り付けたいがために使っていることが多いです。その時に、いちいち開かれたブラウザのアドレスバーからリンクをコピーするのが面倒だったので、純粋にコードリンクのコピーだけが行えるものがほしいと思い開発しました。

開発コードは GitHub にあげています(3 年ぶりに Kotlin 書いたのでコード的にはアレです)。

https://github.com/kawamataryo/copy-git-link

IntelliJ IDEA プラグインの作り方 🛠

どのようにプラグインを作るのか簡単に解説します。

1. GitHub Templateからリポジトリの作成

IntelliJ Platform Plugin Template のリポジトリにアクセスし、Use this template からリポジトリを作成してください。

https://github.com/JetBrains/intellij-platform-plugin-template

このリポジトリがなかなか高機能でリポジトリの作成が完了すると GitHub Actions が起動し、リポジトリ名を元にテンプレートコードの初期化が行われ、直ぐプラグインを開発できる状態となります(README も自動で書き換えられます)。

2. Actionの実装

サンプルとして、コンテキストメニューのCopy Pathボタンを押すと今のファイルのパスをクリップボードに保存するプラグインを作ってみます。

Template リポジトリから作成したリポジトリをクローンして、src/main/kotlin/com/github/<ユーザー名>/<リポジトリ名>のディレクトリに、CopyPathAction.ktを作成してください。

package com.github.kawamataryo.intellijpluginsandbox

import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.CommonDataKeys
import com.intellij.openapi.ide.CopyPasteManager
import java.awt.datatransfer.StringSelection


class CopyPathAction : AnAction() {
    override fun actionPerformed(e: AnActionEvent) {
        val virtualFile = e.getRequiredData(CommonDataKeys.VIRTUAL_FILE)
        val project = e.getRequiredData(CommonDataKeys.PROJECT)

        // pathの取得
        val absolutePath = virtualFile.path
        val basePath = project.basePath ?: ""
        val pathFromRoot = absolutePath.replace("$basePath/", "")

        // clipboardへのコピー
        CopyPasteManager.getInstance().setContents(StringSelection(pathFromRoot))
    }
}

Action は、プラグインの実装です。AnActionクラスを継承して作成します。オーバーライドしているactionPerformedメソッドが、何らかのトリガーにより Action が実行された際に動作するメソッドです。actionPerformedが引数として受け取るAnActionEventのインスタンスから File やプロジェクトの情報を取得できます。今回はそこで Root からファイルまでのパスを取得し、clipboard へコピーしています。

3. Actionの登録

次に作成した Action のコンテキストメニューへの紐付けを行います。紐付けは、プラグインの設定ファイルである src/main/resources/META-INF/plugin.xml で行います。

<idea-plugin>内部に<actions>タグを切り、Action を定義します。

<idea-plugin>
  <!-- ... -->
  <actions>
    <!-- copy path -->
    <action id="com.github.kawamataryo.intellijpluginsandbox.CopyPathAction"
      class="com.github.kawamataryo.intellijpluginsandbox.CopyPathAction"
      text="Copy Path From Root"
      description="Copy path from project root"
      icon="AllIcons.Actions.Copy"
    >
      <keyboard-shortcut keymap="$default" first-keystroke="control alt C"/>
      <add-to-group group-id="EditorPopupMenu" anchor="first"/>
    </action>
  </actions>
</idea-plugin>

<action>の属性で、先程定義したCopyPathActionを設定します。またtextでメニューのタイトル文字列、iconで表示されるアイコンを設定しています。アイコンは icons_list から IntelliJ 組み込みのアイコンを選択できます。または、独自の画像ファイルを設定することもできます。詳細はドキュメントを確認ください。

https://plugins.jetbrains.com/docs/intellij/work-with-icons-and-images.html

<keyboard-shortcut>はその名の通り Action を実行するキーボードショートカットです。
<add-to-group>はこの Action をどのメニューに表示するかを定義します。今回はエディタのコンテキストメニューに表示したいので、group-idEditorPopupMenuとしています。anchor属性はそのメニュー内の表示位置です。

4. プラグインの動作確認

これでプラグインの実装は出来たので、実際に動作を確認してみます。
動作確認もとても簡単で、Gradle で定義されているRun Pluginのスクリプトを実行するだけです。

するとプラグインがインストールされた状態の別の IntelliJ が起動します。適当なファイルにて、コンテキストメニューを開くと先程定義したCopy Path From Rootが表示されます。

クリックすると該当ファイルのパスがクリップボードにコピーされるはずです。

5. 公開情報の設定

実際にプラグインを公開する場合は、gradle.propertiesにバージョン情報や、対応プラットフォームを設定します。この設定が、Gradle でのビルド時に読み込まれプラグインの jar ファイルに組み込まれます。

# IntelliJ Platform Artifacts Repositories
# -> https://plugins.jetbrains.com/docs/intellij/intellij-artifacts.html

pluginGroup = com.github.kawamataryo.intellijpluginsandbox
pluginName = intellij-plugin-sandbox
pluginVersion = 0.0.1

# See https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
# for insight into build numbers and IntelliJ Platform versions.
pluginSinceBuild = 203
pluginUntilBuild = 212.*

# Plugin Verifier integration -> https://github.com/JetBrains/gradle-intellij-plugin#plugin-verifier-dsl
# See https://jb.gg/intellij-platform-builds-list for available build versions.
pluginVerifierIdeVersions = 2020.3.4, 2021.1.3, 2021.2.1

platformType = IC
platformVersion = 2020.3.4
platformDownloadSources = true

# ...

また、プラグインのインストール画面やマーケットプレイスで表示されるプラグインの概要は、README.md の<!-- Plugin description -->以下に書くことができます。
これも Gradle でのビルド時に自動的に読み込まれます。README の記述をそのまま使えるのは二重管理とならず良いですよね。

README.md
<!-- Plugin description -->

ここに機能概要や使い方を記載する

<!-- Plugin description end -->

6. 公開

マーケットプレイスに公開する場合は、リモートリポジトリに変更をプッシュした場合に実行される GitHub Actions から jar ファイルを取得します。

JetBrains Marketplace にアカウント登録し、Upload pluginから先程の jar ファイルをアップロードすれば公開は完了です。2〜3 日の審査期間を経て公開されます。

https://plugins.jetbrains.com/

他、GitHub の tag を push することで、公開済みのプラグインのバージョンアップを行う GitHub Actions もあります。

おわりに

エディタのプラグインは難しそうと思っていたのですが、作ってみると思いの他簡単に出来て感動です。流石 JetBrains。

今後も何かちょこちょこ自分の開発を便利にするプラグインを作っていきたいです。

参考

https://plugins.jetbrains.com/docs/intellij/welcome.html

Discussion