しおしお

IntelliJ IDEAのことなんかを書いてます

ConsoleのURLをリンクにするpluginの実装

plugin.xml

Consoleへの出力内容をカスタマイズしたいので、拡張ポイントにconsoleFilterProviderを指定して、implementationにその実装クラス名を指定してあげる。

  <extensions defaultExtensionNs="com.intellij">
    <consoleFilterProvider
        implementation="siosio.ConsoleLinkFilterProvider" />
  </extensions>

siosio.ConsoleLinkFilterProvider

plugin.xmlに設定したconsoleFilterProviderの実装クラスがこれ。
xmlに設定したのと同じ名前のインタフェース(ConsoleFilterProvider)を実装する。
このインタフェースでは、getDefaultFiltersを実装して上げる必要があって、そこではこのProviderが提供するFilterの実装クラスの配列を返してあげる。
今回は、URLをリンクにするFilterだけが必要なのでそのインスタンスを返してます。

public class ConsoleLinkFilterProvider implements ConsoleFilterProvider {

    @NotNull
    @Override
    public Filter[] getDefaultFilters(@NotNull Project project) {
        Filter filter = new ConsoleLinkFilter();
        return new Filter[]{filter};
    }
}

siosio.ConsoleLinkFilter

ConsoleLinkFilterProviderで指定した、Filterの実装クラス。このクラスが、URLのリンクを実現してます。
やってることは単純で、URLの正規表現にマッチした部分をOpenUrlHyperlinkInfoとしてResultにつめてあげているだけです。
これだけで、Consoleに出力時に良い感じにリンクとして出力してくれます。
ただ、この実装には問題があって1行の中にURLが複数あっても最初のURLしかリンクにならないのです。

public class ConsoleLinkFilter implements Filter {

    private static final Pattern URL_PATTERN = Pattern.compile(
            "(https?://[-_.!~*\\\\'()a-zA-Z0-9;\\\\/?:\\\\@&=+\\\\$,%#]+)");

    @Override
    public Result applyFilter(String s, int endPoint) {
        int startPoint = endPoint - s.length();
        Matcher matcher = URL_PATTERN.matcher(s);
        if (matcher.find()) {
            return new Result(startPoint + matcher.start(),
                    startPoint + matcher.end(),
                            new OpenUrlHyperlinkInfo(matcher.group(1)));
        } else {
            return new Result(startPoint, endPoint, null, new TextAttributes());
        }
    }
}

実は、これで実装が正しいかよくわかってないという・・・
plugin.xmlへの指定とかも補完してみたらそれっぽいのが出てきたので、これでいいんじゃねと思ってこうしているだけで・・・。
それなりに動いているし、多分そんな間違っていないとは思うけど・・・。
多少、怪しい動きしても誰も困らないプラグインだし問題ないよね?