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

Organizing snippets

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

スニペットの読み込み

スニペットの定義は、ファイルシステム上のファイルの中に格納されます。 よりシンプルな "bundle" バージョンを使っているのでなければ、それらのファイルは YASnippet が snippet table に読み込めるように配置されています。 トリガーメカニズム(Expanding snippets を参照)はこの snippet table を調べ、(望むらくは)あなたの意図するスニペットを展開します。

"bundle" 版でないバージョンの 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/new-snippet やその他の「Writing Snippets」で記述されているようなコマンド群を使うことができます。

この変数をリストにして、複数の値を格納することができます:

;; 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 という名前のサブディレクトリに置かれます。

ネストした構成

とあるモード向けのスニペットを含むディレクトリ階層の抜粋を以下に示します:

$ tree
.
`-- text-mode
    |-- cc-mode
    |   |-- c-mode
    |   |   `-- printf
    |   |-- for
    |   |-- java-mode
    |   |   `-- println
    |   `-- while
    |-- email
    |-- perl-mode
    |   |-- cperl-mode
    |   `-- for
    `-- time

親ディレクトリは、そのサブディレクトリすべての parent table の役割を果たしています。 これは、異なる Emacs メジャーモードがスニペットの定義を共有するための方法のひとつです。 上の例にあるように、c-modejava-mode は同じ親 cc-mode を共有しており、その while スニペットを共有しています。 また、すべてのモードは text-mode に由来する time スニペットを共有しています。

この仕組みは alias (別名)としても使えます。cperl-modeperl-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 という名前の空のプレインテキストファイル(訳注:矛盾してますね・・・)を置くと、 これらのサブディレクトリの名前はスニペットのグループの名前とみなされます。 これにより、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 変数を true に設定するか、または.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 を呼ぶ、というやり方です。

YASnippet では、リリースされているバンドルファイルは yas/compile-bundle によって生成されています。 バンドルは、スニペットを定義するために yas/define-snippets を使っています。 これにより、スニペットを読み込む際の I/O および構文解析のオーバヘッドを回避することができます。

もっと言ってしまうと、生成されたバンドルファイルは独立したファイルであり、yasnippet.el に依存していません。 YASnippet でリリースされているバンドルファイルは、すべてこのやり方で生成されています。

これらの機能に関する内部向けのドキュメントとしては以下をご覧ください:

カスタム可能な変数

yas/root-directory

各メジャーモードに対するスニペットを格納しているルートディレクトリ。

この変数を .emacs で定義する場合、複数のルートディレクトリを指定するために、文字列のリストとすることもできます。 リストにした場合、その最初の要素は常にユーザ作成スニペット用のディレクトリとなります。 それ以外の要素は、yas/reload-all での全スニペットの再読み込みの対象となります。

yas/ignore-filenames-as-triggers

nil で無い場合、ファイル名から tab trigger を派生させません。

これは、スニペットについて、tab trigger を指定する # key: ディレクティブが書かれていないものとみなすことを意味します。

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