※原文: http://yasnippet.googlecode.com/svn/trunk/doc/snippet-expansion.html

Expanding snippets

重要: このドキュメントは YASnippet の SVN trunk に対して適用されるものです。 SVN trunk はこちらから取得できます。 他のバージョンに対するドキュメントはこちらで見られます。

展開のトリガ

YASnippet でスニペットを展開するのにさまざまなやり方があります:

Trigger key

yas/minor-mode が有効になると、yas/trigger-key で与えられたキーバインドが有効になります。

yas/trigger-keyyas/expand を呼び出します。これは、スニペット省略形(snippet key とも呼ばれます)をカーソル位置の前に展開しようとします。

デフォルトのキーは "TAB" ですが、自由にほかのキーに設定することができます。

すべてのバッファで YASnippet マイナーモードを有効にするには、yas/global-mode コマンドを使います。

yas/global-mode を使っているが、あるバッファでは YASnippet を無効化したい、というときには、そのバッファのモードのフックでバッファローカル変数 yas/dont-active を設定してください。

yas/trigger-key の利用とその理解にまつわるトラブルは、YASnippet でもっとも話題になりやすいものです。 FAQ を参照してください。

万一の時のふるまい

yas/fallback-behaviour は設定可能な変数で、デフォルトでは 'call-other-command に束縛されています。 展開すべきスニペットを yas/expand が見つけられなかった場合、マイナーモードを一時的に無効にして、yas/trigger-key に束縛されている他のコマンドがないか探します。

もし他のコマンドが見つかった場合、その見つかったコマンドが呼ばれます。 たいていの場合、この仕組みはとてもうまく機能します。 スニペットがあったらそれを展開し、そうでなければ trigger key にもともと割りつけられていたコマンドを呼ぶ、というわけです。

また一方で、変数 yas/fallback-behavior をカスタマイズすることで、この挙動を変えることができます。 この変数の値を 'return-nil に設定すると、スニペットが見つからなかったときにもともとのコマンドを呼ぶ代わりに、nil を返すようになります。

カーソル位置への挿入

コマンド M-x yas/insert-snippet は、現在のメジャーモードにしたがって、スニペットをカーソル位置に挿入できるようにしてくれます。 このコマンドを実行すると、最初に snippet key (訳注:スニペット省略形)の入力をうながします。 同じ snippet key に対して複数のテンプレートがある場合、続けてスニペットテンプレートの入力をうながします。

条件判断システムにしたがって、カーソル位置に挿入可能なスニペットからなるリストが表示されます。 現在のメジャーモードに対して適用可能なすべてのスニペットを見たいときには、コマンドの前に C-u を付けてください。

入力をうながすメソッドもまた、yas/prompt-functions によって制御されています。

スニペットのキーバインド

"Writing Snippets" の章# binding: ディレクティブの記述を参照してください。

メニューからの展開

"the YASnippet Menu" の章を参照してください。

hippie-expand での展開

時には、Emacs-Lisp コードから直接スニペットを展開したいことがあるかもしれません。 そんなときは yas/expand の代わりに yas/expand-snippet を呼ぶようにしてください。

メニューバーから展開するのと同様に、条件判断システムおよび複数候補は展開に影響しなくなります。 実際、the YASnippet menu からの展開は、以下のコードの評価とまったく同じ効果を持っています:

(yas/expand-snippet template)

もっと情報が必要な場合は yas/expand-snippet の内部ドキュメントを参照してください。

展開の制御

資格のあるスニペット

現在のカーソル位置に展開できるスニペットはどれか、を見つけ出すために、YASnippet はきわめてわずかなフィルタリングしかしません。

具体的に言うと、以下のものが重要です:

The condition system

次のシナリオを考えてみてください: あなたはベテランの Emacs ハッカーです。 あなたは省略表記を好んでいて、yas/trigger-key に "SPC" を設定しています。 また一方では、(たとえば python-mode などで)コメントブロックや文字列の中でタイプした "if" はスニペットとして展開してほしくありません。

# condition : ディレクティブ("Writing Snippets" の章を参照)を使っている場合、 if に対して (not (python-in-string/comment)) という条件を指定するだけで済みます。 しかし、whilefor などについてはどうでしょう? すべてのスニペットに対して同じ条件を書くのは本当にうんざりするでしょう。 そんなわけで、バッファローカル変数 yas/buffer-local-condition があります。 python-mode-hook の中で、この変数に (not (python-in-string/comment)) を設定すればよいのです。

次に、ある特定のスニペットだけはコメントの中でも展開できるようにしたいと思ったら、どうしたらよいでしょう? これも実現可能です! でも、話を進めるのを止めて、以下のルールについて見てください:

ここで述べられているシナリオでは、yas/buffer-local-condition を以下のように設定してください:

(add-hook 'python-mode-hook
          '(lambda ()
             (setq yas/buffer-local-condition
                   '(if (python-in-string/comment)
                        '(require-snippet-condition . force-in-comment)
                      t))))

・・・・また、コメントの中でも展開されてほしいスニペットの # condition: ディレクティブは、シンボル force-in-comment と評価されるようにしてください。 こうすると、if のような他のスニペットはコメントの中では展開されないままで、あなたが展開したいスニペットは展開できるようになります。

同じキーに割り当てられた複数のスニペット

上のほうで概要を述べたルールは、現在のカーソル位置に展開可能なスニペットを複数返すことがありえます。

複数の候補が見つかったとき、YASnippet はあなたにひとつ選ばせるでしょう。 複数の候補を選択するためのユーザインタフェースは、yas/prompt-functions を通じてカスタマイズすることができます。 これは、スニペットに対する指示を入力するときにあなたが使いたいメソッドを定義するためのものです。

これをカスタマイズするには、M-x customize-variable RET yas/prompt-functions RET としてください。 他のやり方として、あなたの emacs 設定ファイルに以下のコードを書いてください:

(setq yas/prompt-functions '(yas/x-prompt yas/dropdown-prompt))

現在、YASnippet にはほかの代替手段もあります。

X windo system を使う

関数 yas/x-prompt は、なにかを選ぶためにポップアップメニューを表示するのに使えます。 このメニューはあなたの環境のネイティブなウインドウシステムの部品 (widget) です。 つまり:

ミニバッファでのプロンプト

昔ながらの emacs の補完メソッドのためには関数 yas/completing-prompt が使えます。 これよりずっと見た目のよいメソッドとしては yas/ido-prompt が使えます。 実際に試してみるのが一番いいです。 この機能はターミナル上でも使えます。

dropdown-menu.el を使う

関数 yas/dropdown-promptyas/prompt-functions リストに含めることができます。

これはウインドウシステム上でもターミナル上でも機能し、カスタマイズ可能で、C-nC-p で操作でき、 q で quit でき、6番目の候補を選択するのに 6 を押すこともできます。

自作する

変数 yas/prompt-functions のドキュメントを参照してください。

カスタマイズ可能な変数

(日本語訳: Seaoak, 2010/Dec/15)