yasnippet.elを256倍にパワーアップ!連続展開と条件分岐テンプレートを使おう
動機
yasnippetの展開機能はなかなか強力ですが、「次の」テンプレート展開の準備や条件分岐ができない弱点があります。
連続展開の例は、プログラミングにおけるドメイン特化言語を記述する場合です。 この場合は、パターンが決まっているので、次のテンプレート展開の準備をするテンプレートを記述すればすんなり記述できるのです。 そして、テンプレート展開後に、次のテンプレートを展開していきます。
条件分岐テンプレートの例は、新規ファイル作成時に文章のテンプレートを選んで展開するケースです。 僕のブログの場合、「自作Emacs Lispリリーステンプレート」、「Emacs Lispを使ってみたテンプレート」、「EmacsのTipsテンプレート」などがあります。
記憶力のいい人ならば、テンプレート名を覚えて普通に展開すると思います。 僕の場合はテンプレート名はおろか、テンプレートを作ったこと自体忘れてしまうのです。 ならば、テンプレート展開の準備をしておけばよいことになります。
それらの弱点は わずか10行足らずのコードで克服することができます。
必要なもの
- Emacs23
- yasnippet.el
設定
以下の設定を.emacsに加えてください。
;;; [2010/07/13] (defun yas/expand-link (key) "Hyperlink function for yasnippet expansion." (delete-region (point-at-bol) (1+ (point-at-eol))) (insert key) (yas/expand)) ;;; [2010/12/02] (defun yas/expand-link-choice (&rest keys) "Hyperlink to select yasnippet template." (yas/expand-link (completing-read "Select template: " keys nil t))) ;; (yas/expand-link-choice "defgp" "defcm")
使い方
テンプレートを準備するには、yas/expand-linkやyas/expand-link-choice関数をテンプレートに記述するだけです。
準備されたテンプレートを展開するには、それらの関数の行にてC-e C-x C-eを押すだけです。 なぜなら、yas/expand-linkは現在行を消し、指定されたテンプレートを展開する関数だからです。
使用例
ここだけだとわかりづらいので具体例を出します。
yas/expand-linkで次に展開されるべきテンプレートを準備する
たとえば、以下のコード(Rubyスクリプト)は、Expectationsブロックの中に複数のexpectブロックが存在します。
require 'rubygems' require 'expectations' Expectations do expect 2 do 1+1 end expect "foobar" do "foo"+"bar" end end
この場合、expectationsというテンプレートに1つのexpectブロックを記述することもできますが、2つ目以降のexpectブロックは手書きする必要があります。 必要な分だけexpectブロックを楽に入力したいのです。
この場合、次のようにexpectationsとexpectations.expectテンプレートを設定します。
#name : expectations # -- require 'rubygems' require 'expectations' Expectations do # (yas/expand-link "expectations.expect")$0 end
# -*- mode: snippet -*- # name: expect # -- expect $1 do $0 end # (yas/expand-link "expectations.expect")
双方に含まれている「# (yas/expand-link "expectations.expect")」という行がミソです。 この行は、expectations.expectテンプレートを展開する関数なので、展開すれたびに次のexpectations.expectテンプレートの準備ができている状態になります。
expectations
↓ Tab
require 'rubygems' require 'expectations' Expectations do # (yas/expand-link "expectations.expect") end
↓ 即座に展開され、yas/expand-linkの行の末尾にカーソルがあるので、C-x C-e
require 'rubygems' require 'expectations' Expectations do expect do end # (yas/expand-link "expectations.expect") end
↓ 展開を完了させる
require 'rubygems' require 'expectations' Expectations do expect 2 do 1+1 end # (yas/expand-link "expectations.expect") end
↓ 次の yas/expand-link の行にてC-e C-x C-eを押し、展開を完了させる
require 'rubygems' require 'expectations' Expectations do expect 2 do 1+1 end expect "foobar" do "foo"+"bar" end # (yas/expand-link "expectations.expect") end
展開が終わると、最後にyas/expand-linkの行が残ります。 将来expectブロックを増やすことを考えたら残しておくべきです。
yas/expand-link-choiceで条件分岐をする
僕は、ブログの原稿の初期テンプレートを設定しています。
以下の設定により ~/memo/hatena/*.org を新規作成するとき、 ~/emacs/insert/org2hatena.insert が挿入されます。
(setq auto-insert-directory "~/emacs/insert/")
(auto-insert-mode 1)
(add-to-list 'auto-insert-alist '("memo/hatena/.+org$" . "org2hatena.insert"))
そして、 org2hatena.insert の内容は以下のようになっています。
# (yas/expand-link "org2hatenakeywords") # (yas/expand-link-choice "hatena.emacs.release" "hatena.emacs.tips" "hatena.emacs.use")
2行目が yas/expand-link-choice 関数による条件分岐テンプレートです。 C-e C-x C-eで評価すると、hatena.emacs.release、hatena.emacs.tips、hatena.emacs.useのうち、どれかをミニバッファで選択してテンプレート展開します。
ここでは autoinsert.el による初期テンプレートの設定ですが、プログラミングの際にも使えます。 要は、次に展開すべきテンプレートの準備をしておくことが肝要です。