🤜

Eclipseのテンプレート(補完)を自分で作る

2021/12/20に公開

目次

1. 概要

Eclipseではよく使うコーディングのパターンがテンプレートとして登録されており、ちょっと文字入れてCtrl+Spaceで補完することができる。
単純に入力してくれるだけでなく、Tabで入力部分をジャンプしたりできるので便利。

デフォルトでいろいろなテンプレートが用意されているが、自分で作ることもできるので作り方をまとめる。

2. テンプレート作成例

この例ではpublic static voidを打つのが面倒なのでそれをテンプレート化してみる。

  1. 設定で、Java/エディター/テンプレート→新規

  2. こんな感じで入力する。入力したらOK

    • 名前:psv
      この文字を入力して補完するとこのテンプレートが呼び出されることになる。
    • コンテキスト:Java
      どの場面でこのテンプレートを発動させるか。いろいろ選べるがひとまずJava
    • 自動的に挿入:オン
      チェックすると「候補がその1つのテンプレートしか無い場合に自動で挿入してくれる」というものらしい。今回のケースだとそういう状態にならないけどひとまずチェック。
    • 説明:説明書いておこう。
    • パターン:
      public static ${void} ${name}(${}){
          ${cursor}
      }
      実際に入力されるパターンを書く。固定の文字列を書くこともできるし、変数を使ってその状況に応じた値を入力させることもできる。ここの書き方は後述するので、ひとまず今回はこれを入力する。

  3. Javaソースファイル内でpsvと入力してからCtrl+Spaceを入力すると補完される。

3. パターンの書き方

3.1. 基本

変数を使わず、単純に文字列を書けばそれが補完時に入力されることになる。
例えば下記のような設定の時

補完するとこんな感じになる。
※一応名前は日本語を使うこともできる。

3.2. 変数についてのヘルプ

単純に文字列をパターンに使う以外にも、変数を使うことができる。EclipseヘルプのJava development user guide/Templates/Template variablesのところに一応説明がある。
Javaに関係なく使える一般的な変数と、Java特有の変数がある。
(ヘルプページ見にくいよお。なんでjspで作られてるん)
https://help.eclipse.org/latest/index.jsp

3.3. 一般的な変数

ヘルプにあった一般的な変数を、下記状況で使った場合にどうなるかをまとめた。
Sampleプロジェクト
Test.javaファイル
Testクラス
public static void main(String[] args)メソッド
2021/12/17
14:04:32

変数の書き方 補完結果
${date} 2021/12/17
${hoge:date('yyyy-MM-dd us')} 2021-12-17
${dollar} $
$$ $
${enclosing_method} main
${enclosing_method_arguments} args
${enclosing_package}
${enclosing_project} Sample
${enclosing_type} Test
${file} Test.Java
${line_selection}
${currentLine:line_selection(myStringVariable)} myStringVariable
${currentLine2:Line_selection('"A default text"')} currentLine2
${primary_type_name} Test
${return_type} void
${time} 14:04:32
${user} PCのユーザー名
${word_selection}
${hoge2:word_selection(myStringVariable)} myStringVariable
${hoge3:word_selection('"Press me"')} "Press me"
${year} 2021

3.3.1. ${任意の文字}

これは変数というよりプレースホルダって感じの使い方かしら…。
こう書いておくと、補完時にその任意の文字列を表示させつつ、キーを入力すればその文字列が消えて自由に入力できる。
かつ、入力した後にTabを押せば、次の変数に飛ぶことができる。
もし新規の文字列を入力せずにTabを押せば、元々あった任意の文字列が残ることになる。

このpublic static voidの例だと、${void}と${name}と一応${}がそれにあたる。

文字列をそのまま残すこともできるし、変更することもできる。

3.3.2. ${cursor}

これも${任意の文字列}と同じようにこの場所にTabで移動できるようになっていて、かつ文字列が存在しないものとなっている。それだけだと${}と同じかと思いきやちょっと違う。
この${cursor}のところで文字を入力した場合、次にTabを押しても他の変数に飛ばず、単純にTabが入力されることになる。
つまり「テンプレートの中で最終的にカーソルを移動させて入力をするところ」という意味を持つ。

3.3.3. ${line_selection}

これは複数行の選択された文章がここに入る。
この補完をするには、今までみたいな「文章を打ってからCtrl + Spaceを押す」というのではなく「文章を選択してからCtrl + Spaceを押す」という操作をする必要がある。

例えばこういうテンプレートを作成する。

それで文章を選択してからCtrl + Spaceでそのテンプレートを呼び出すと、選択した文章を囲んだ形でテンプレートが適用される。
Ctrl + Spaceでテンプレート呼び出すときに元の文章一回消えるから、このやり方で正解なのか不安になる。
※文章を複数行選択してないと、補完の候補に出てこない。

3.3.4. ${word_selection}

${line_selection}の1行版というか文字列版。これは${line_selection}とは逆に、複数行選択した場合は補完候補に出てこない。

こういうテンプレートを作成する。

こういう挙動になる。

3.4. Java固有の変数

いろいろあるが、これを試す気力がないのでひとまずヘルプの内容をそのまま転記する。

The Java context additionally defines the following variables. Note: In the table below, id is a user-chosen name of a new variable.

Variable Description
${id:field(type[,type]*)} Evaluates to a field in the current scope that is a subtype of any of the given types. If no type is specified, any non-primitive field matches. Example:
${count:field(int)}
${id:var(type[,type]*)} Evaluates to a field, local variable or parameter visible in the current scope that is a subtype of any of the given types. If no type is specified, any non-primitive variable matches. Example:
${container:var(java.util.List, 'java.lang.Object[]')}
${id:localVar(type[,type]*)} Evaluates to a local variable or parameter visible in the current scope that is a subtype of any of the given type. If no type is specified, any non-primitive local variable matches. ${array} is a shortcut for ${array:localVar('java.lang.Object[]')}, but also matches arrays of primitive types.
${collection} is a shortcut for ${collection:localVar(java.util.Collection)}.
${iterable} is a shortcut for ${iterable:localVar(java.lang.Iterable)}, but also matches arrays.
${id:argType(variable, n)} Evaluates to the nth type argument of the referenced template variable. The reference should be the name of another template variable. Resolves to java.lang.Object if the referenced variable cannot be found or is not a parameterized type. Example:
${type:argType(vector, 0)} ${first:name(type)} = ${vector:var(java.util.Vector)}.get(0)
${id:elemType(variable)} Evaluates to the element type of the referenced template variable. The reference should be the name of another template variable that resolves to an array or an instance of java.lang.Iterable. The elemType variable type is similar to ${id:argType(reference,0)}, the difference being that it also resolves the element type of an array. ${array_type} is a shortcut for ${array_type:elemType(array)}.
${iterable_type} is a shortcut for ${iterable_type:elemType(iterable)}.
${id:newName(reference)} Evaluates to a non-conflicting name for a new local variable of the type specified by the reference. The reference may either be a Java type name or the name of another template variable. The generated name respects the code style settings. ${index} is a shortcut for ${index:newName(int)}.
${iterator} is a shortcut for ${iterator:newName(java.util.Iterator)}.
${array_element} is a shortcut for ${array_element:newName(array)}.
${iterable_element} is a shortcut for ${iterable_element:newName(iterable)}.
${id:newType(qualifiedTypeName)} Evaluates to a type name given the fully qualified Java type name. Evaluates to a simple type name and an import if no conflicting type exists. Evaluates to a fully qualified type name otherwise. Example:
${type:newType(java.util.Iterator)}
${:import(type[,type]*)} Adds an import statement for each type. Does nothing if the import already exists. Does nothing if a conflicting import exists. Evaluates to nothing. Example:
${:import(java.util.List, java.util.Collection)}
${:importStatic([qualifiedName[,qualifiedName]*])} Adds a static import statement for each qualified name that is not already imported. The qualifiedName is the fully qualified name of a static field or method, or it is the qualified name of a type plus a .* suffix, enclosed in single quotes ''. Does nothing if a conflicting import exists. Evaluates to nothing. Example:
${is:importStatic(java.util.Collections.EMPTY_SET, 'java.lang.System.*')}
${id:link(proposal[,proposal]*)} Evaluates to id if the list of proposals is empty, evaluates to the first proposal otherwise. The evaluated value is put into linked mode. A proposal window shows all the given proposals. Example:
java.util.Collections.${kind:link(EMPTY_SET, EMPTY_LIST, EMPTY_MAP)}
${array} Evaluates to a proposal for an array visible in the current scope.
${array_element} Evaluates to a name for a new local variable for an element of the ${array} variable match.
${array_type} Evaluates to the element type of the ${array} variable match.
${collection} Evaluates to a proposal for a collection visible in the current scope.
${exception_variable_name} Exception variable name in catch blocks.
${index} Evaluates to a proposal for an undeclared array index.
${iterator} Evaluates to an unused name for a new local variable of type java.util.Iterator.
${iterable} Evaluates to a proposal for an iterable or array visible in the current scope.
${iterable_element} Evaluates to a name for a new local variable for an element of the ${iterable} variable match.
${iterable_type} Evaluates to the element type of the ${iterable} variable match.
${todo} Evaluates to a proposal for the currently specified default task tag.

Discussion