原文: http://yasnippet.googlecode.com/svn/trunk/doc/snippet-organization.html (translated on 2010/Dec/21) ⇒ editor's room
〔重要〕 このドキュメントは YASnippet の SVN trunk に対して適用されるものです。 SVN trunk はこちらから取得できます。 他のバージョンに対するドキュメントはこちらで見られます。
スニペットの定義は、ファイルシステム上のファイルの中に格納されます。 よりシンプルな "bundle" バージョンを使っているのでなければ、それらのファイルは、YASnippet が snippet table に読み込めるように配置されています。 トリガーメカニズム(Expanding snippets の章を参照)はこの snippet table を調べ、(望むらくは)あなたの意図するスニペットを展開します。
"normal" バージョンの YASnippet のアーカイブは、それを展開(解凍)した時点で、完全なディレクトリ構成を備えています。 あなたはそれをどこにでも好きなところにコピーして使うことができます。 また、他にもディレクトリを作ったりダウンロードしたりすることができます。
これらのディレクトリ群を適当な場所に置いたら、その場所を yas/root-directory
変数で参照できるようにしてください。
また、それらのディレクトリ群は関数 yas/load-directory
で読み込むようにしてください。
;; Develop and keep personal snippets under ~/emacs.d/mysnippets
(setq yas/root-directory "~/emacs.d/mysnippets")
;; Load the snippets
(yas/load-directory yas/root-directory)
ディレクトリ名を yas/load-directory
に直接渡さずに yas/root-directory
を介すのは、
"~/emacs.d/mysnippets
" をスニペットの開発のための場所として使うためです。
yas/root-directory
を介すことで、yas/new-snippet
などの「Writing Snippets」で記述されているようなコマンド群を使うことができるようになります。
この変数 yas/load-directory
は、リストにすることができます。リストにすると、複数の値を格納できます。
;; Develop in ~/emacs.d/mysnippets, but also
;; try out snippets in ~/Downloads/interesting-snippets
(setq yas/root-directory '("~/emacs.d/mysnippets"
"~/Downloads/interesting-snippets"))
;; Map `yas/load-directory' to every element
(mapc 'yas/load-directory yas/root-directory)
すぐ上の例では、すべてのディレクトリが読み込まれ、そこにあるスニペットは展開すべきものとみなされます。
それでいながら、開発は依然として最初の要素である "~/emacs.d/mysnippets
" で行うことができます。
yas/root-directory
の設定ができたら、そこで指定したディレクトリのサブディレクトリにスニペットを格納することができます。
スニペットの定義はプレインテキストファイルに置かれます。 それらのファイルはサブディレクトリに配置されます。 snippet table にはこれらのディレクトリの名前がつけられます。
snippet table の名前は、あなたがスニペット展開を行わせたい Emacs モードと同じにします。
たとえば、c-mode
に対するスニペットは、"c-mode
" という名前のサブディレクトリに置きます。
スニペットが置かれたディレクトリを丸ごと無視して、代わりに
「バンドル」を使うこともできます(YASnippet bundle の節を参照)。
いくつかのモード向けのスニペットを含むディレクトリ階層の抜粋を以下に示します:
$ tree
.
`-- text-mode
|-- cc-mode
| |-- c-mode
| | `-- printf
| |-- for
| |-- java-mode
| | `-- println
| `-- while
|-- email
|-- perl-mode
| |-- cperl-mode
| `-- for
`-- time
親ディレクトリは、そのサブディレクトリすべての parent table の役割を果たしています。
これは、異なる Emacs メジャーモードがスニペットの定義を共有するための方法のひとつです。
上の例にあるように、c-mode
と java-mode
は同じ親 cc-mode
を共有しており、cc-mode
向けに定義されている while
スニペットを共有しています。
また、すべてのモードは text-mode
に由来する time
スニペットを共有しています。
この仕組みは alias (別名)としても使えます。上の例で、cperl-mode
は perl-mode
を親とする空のディレクトリです。
.yas-parents
ファイルparent table を設定するもうひとつの(より好ましい)方法は、サブディレクトリのひとつに .yas-parents
という名前のプレインテキストファイルを置くことです。
こうすると、ディレクトリがネストして複雑になってしまうのを避けることができます。
.yas-parents
ファイルの中には、モード名を空白で区切って書くだけです。
このしくみは、スニペットの階層を柔軟に、読みやすくしてくれます。
$ tree
.
|-- c-mode
| |-- .yas-parents # contains "cc-mode text-mode"
| `-- printf
|-- cc-mode
| |-- for
| `-- while
|-- java-mode
| |-- .yas-parents # contains "cc-mode text-mode"
| `-- println
`-- text-mode
|-- email
`-- time
.yas-make-groups
ファイル各モードのディレクトリのひとつに .yas-make-groups
という名前の空のプレインテキストファイル(訳注:矛盾してますね・・・【空の Excel ファイルというものが存在すると考えると、矛盾しない気もします。 2010/12/24 IKKI】)を置くと、
これらのサブディレクトリは「スニペットのグループ」とみなされます。
これにより、The YASnippet Menu をとてもわかりやすく整理することができます(右の画像のように)。
同じことをするためのもうひとつの方法は、# group:
ディレクティブをスニペット定義の中に書くことです。
Writing Snippets の章を参照してください。
$ tree ruby-mode/
ruby-mode/
|-- .yas-make-groups
|-- collections
| |-- each
| `-- ...
|-- control structure
| |-- forin
| `-- ...
|-- definitions
| `-- ...
`-- general
`-- ...
通常、ファイル名はスニペット展開の省略形として使われます。(「省略形」は "snippet key" または "snippet trigger" とも呼ばれます ‥‥ Expanding Snippets の章を参照)
また一方で、変数 yas/ignore-filenames-as-triggers
を non-nil に設定するか、または、
.yas-ignore-filename-triggers
という名前の空のファイルを置くか、どちらかをすると、
ずっと説明的なファイル名を使えるようになります。
ひとつのモードに対するたくさんのスニペットが同じ trigger key を共有しているような場合にこの仕組みは役に立ちます。
$ tree rails-mode/
rails-mode/
|-- .yas-make-groups
|-- .yas-ignore-filename-triggers
|-- Insert ERb's <% __ %> or <%= __ %>.yasnippet
|-- asserts
| |-- assert(var = assigns(%3Avar)).yasnippet
| |-- assert_difference.yasnippet
| |-- assert_no_difference.yasnippet
| |-- assert_redirected_to (nested path plural).yasnippet
| |-- assert_redirected_to (nested path).yasnippet
| |-- assert_redirected_to (path plural).yasnippet
| |-- assert_redirected_to (path).yasnippet
| |-- assert_rjs.yasnippet
| `-- assert_select.yasnippet
YASnippet 向けのスニペットを定義するもっとも便利な方法は、そのスニペットを使いたいモードに基づいてディレクトリ階層中にスニペット定義を置いて、
yas/load-directory
でそれらを読み込むことです。
しかし、たくさんのスニペットがある場合、この方法だと Emacs の起動スピードが遅くなるかもしれません。
ひとつの Emacs-lisp ファイルの中で特定のモードに対するスニペットをたくさん定義するためには、yas/define-snippets
を使うことができます。
このやり方はメンテナンスが大変なので、もっといい方法があります。
ディレクトリ階層の中でスニペットを定義しておいて、
そのスニペットを変更したら M-x yas/compile-bundle
を呼んでスニペット定義をバンドルファイルにコンパイルする、というやり方です。
リリースされているバンドルファイルは、yas/compile-bundle
によって生成されています。
これらのバンドルは、スニペットを定義するために yas/define-snippets
を使っています。
これにより、スニペットを読み込む際の I/O および構文解析のオーバヘッドを回避することができます。
もっと言ってしまうと、生成されたバンドルファイルは独立したファイルであり、yasnippet.el
に依存していません。
リリースされているバンドルファイルは、すべてこのやり方で生成されています。
これらの機能に関する内部ドキュメントとしては以下をご覧ください:
M-x describe-function RET yas/define-snippets RET
M-x describe-function RET yas/compile-bundle RET
yas/root-directory
各メジャーモードに対するスニペットを格納しているルートディレクトリ。
この変数を .emacs
で定義する場合、複数のルートディレクトリを指定するために、文字列のリストとすることもできます。
リストにした場合、その最初の要素は常にユーザ作成スニペット用のディレクトリとなります。
それ以外の要素は、yas/reload-all
での全スニペットの再読み込みの対象となります。
yas/ignore-filenames-as-triggers
nil で無い場合、ファイル名から trigger key を生成しません。
このことは、# key:
ディレクティブの書かれていないスニペットは trigger key を持たない、ということを意味します。