yasnippetでコードのスニペットを登録して爆速でプログラミングする

2023年4月21日
thumbnail
Emacsには補完をサポートするパッケージがあり、最も有名なのはcompanyです。他にはlspを使うことで、プログラミング言語別に入力のサポートをしてくれます。
yasnippetは入力補完の1つで、予め定義したスニペットを使うととで、コードを展開できます。展開にはショートカットキーを使い、高速でプログラミングができる様になります。
例えば、javascriptの変数宣言は大体こんな感じでしょう。
const name = "alice"
yasnippetで、予め変数宣言のスニペットを定義して、 キーにconstを登録しておきます。
const ${1:name} = ${2:initial};
すると、javascriptコード上でconstと打ち込むだけで、簡単に雛形が展開されてコードを書くことができます。
こちらが完成済みのyasnippet設定コードです。
(use-package yasnippet
  :ensure t
  :custom-face
  (yas-field-highlight-face ((t (:inherit nil))))
  :bind (:map yas-minor-mode-map
              ;; バインドが使いづらいので解除
              ("C-c & C-n" . nil)
              ("C-c & C-s" . nil)
              ("C-c & C-v" . nil)
              ;; よく使うコマンドをバインド
              ("C-x y n" . yas-new-snippet)
              ("C-x y i" . yas-insert-snippet)
              ("C-x y v" . yas-visit-snippet-file)
              ("C-x y l" . yas-describe-tables)
              ("C-x y r" . yas-reload-all))
  :init
  (yas-global-mode)
  :config
  (setq yas-prompt-functions '(yas-ido-prompt))
  ;; pythonのインデントバグを修正する関数
  (defun yasnippet-snippets--fixed-indent ()
    "Set `yas-indent-line' to `fixed'."
    (set (make-local-variable 'yas-indent-line) 'fixed))
  (add-hook 'python-mode-hook #'yasnippet-snippets--fixed-indent))

スニペットの登録

スニペットは現在開いているメジャーモードに紐づいて作成されます。 js-modeで.jsファイルを開いている時に、スニペットを作成すると、js-modeでのみでトリガーするスニペットが作成されます。
適当にindex.jsファイルを作り、それを開いて、スニペットを作ってみましょう。js-modeでスニペットを作ってみます。
article image
"C-x y n" yas-new-snippetでスニペット用のバッファを用意します。
article image
javascriptのconstのスニペットを作ってみましょう。 $0はカーソルの最後の終着点です。
# -*- mode: snippet -*-
# name: const
# key: const
# --
const ${1:name} = ${2:initial}
$0
記述したらC-x C-sで保存します。エコーエリアにファイルの保存場所が表示されるので、ファイル名をconstにしてエンターを押します。
article image
ここで表示されるjs-modeフォルダがスニペットのトリガー切り分けになります。js-mode フォルダに保存されたスニペットはjs-modeでしか発動しません。
constスニペットが登録されました。

スニペットの展開

index.jsに戻って、constと打ち込みます。
article image
TABをタイプすると、スニペットが展開されます。
変数名の部分にカーソルが当たるので、messageとか入力し、もう一度TABを押します。今度は値のところにカーソルが移動するので"alice"を入力します。最後にTABを叩くと改行されます。
article image
今のはキーが分かっている状態でスニペットを使用しました。 スニペットが増えてくるとどのキーが利用できるかわからなくなってきます。 "C-x y i" yas-insert-snippetはエコーエリアで対話的にスニペット挿入をサポートしてくれます。今は1つしかスニペットを登録していないので、constスニペットがそのまま挿入されます。候補が増えてくると絞り込みからの選択でスニペットを挿入できます。 下の画像はifスニペットとconstスニペットがある場合の挙動です。
article image

スニペットの編集

作成したconstスニペットは~/.emacs.d/snippets/js-mode/constに保存されているので、それを直接開いて、編集することもできます。 面倒な場合は"C-x y v" yas-visit-snippet-fileを実行します。候補が複数ある場合は、エコーエリアで対象のスニペットを選びます。
article image
スニペットファイルが開くので、編集が可能になります。

利用できるスニペットをざっくり見る

"C-x y l" yas-describe-tablesは現在のメジャーモードで使えるスニペットのテーブルを表示します。何が使えて、どのようなキーが割り振られているかを確認するにはこれがベストです。
article image

スニペットのサンプル

最初からスニペットを自作するのは大変だと思うので、こちらのサンプルを参考にして用意すると良いと思います。ほとんどのプログラミング言語に向けたスニペットが用意されています。

スニペットの自作

私は大体rubypythonjavascriptで開発をおこなっているので、それぞれの言語で以下のようなスニペットを作っています。
キーをそれぞれの言語毎に違うものにしてしまうと、覚えるのが大変になるので、共通にしています。それと、キーが同じメジャーモードで被らない限りは1文字で展開できる様にしています。
ここでは代表してpythonのスニペットを紹介します。

変数宣言

vをキーにしてどの言語も大体こんな感じで展開します。
# -*- mode: snippet -*-
# name: variable
# key: v
# --
${1:name} = ${2:initial}
$0

関数宣言

fをキーにしてそれぞれの言語で関数の雛形を展開します。
 # -*- mode: snippet -*-
 # name: function
 # key: f
 # --
 def ${1:name}(${2:arg}):
   $0

if文

ifをキーにして条件式を展開します。
# -*- mode: snippet -*-
# name: if
# key: if
# --
if ${1:cond}:
  $0
ifeをキーにしてif-else条件式を展開します。
# -*- mode: snippet -*-
# name: if-else
# key: ife
# --
if $1:
    $2
else:
    $0
elifをキーに移してif-elifの複数条件式を展開します。
# -*- mode: snippet -*-
# name: if-elif
# key: elif
# --
if ${1: cond}:
  ${2:code}
elif ${3: cond}:
  $0
sanをキーにして三項演算子を展開します。
# -*- mode: snippet -*-
# name: sankouenzanshi
# key: san
# --
${1:variable} = ${2:true_value} if ${3:cond} else ${4:false_value}

ループ

wをキーにしてwhile文を展開します。
# -*- mode: snippet -*-
# name: while
# key: w
# --
while ${1:condition}:
  $0

デバッグ

デバッグ用のキーは好みもあると思います。私は癖でlogのlを使っていたのでそれを割り当てています。
# -*- mode: snippet -*-
# name: debug
# key: l
# --
print(${1:value})

まとめ

スニペットはあればあるほど、コーディングが早くなるので、よく使うなぁって気づいたら積極的に登録して使い倒しましょう。 また、いくつかのプログラム言語を使っているとちょっとしたif文でも書き方が分からなくなったりするのでそういう思い出すためのコストを下げる意味でもスニペットは役に立ちます。
profile image
Ted
大学でコンセンサスアルゴリズムを研究。卒業後ベンチャー企業に入社してフルスタックでWebサービスを開発。現在は大手IT企業に転職し、プログラミングを行っている。AIにプログラマーの仕事を奪って欲しいと願っている。