
おすすめスニペットツール - espanso と LuaSnip の使い分け
スニペットツールとして、以下の2つを使い分けています。
- espanso — システム全体で使えるテキストエクスパンダー
- LuaSnip — Neovim用のスニペットエンジン
どちらも外部スクリプト(Python等)を実行できるという点が気に入っています。
使い分けの方針
| 用途 | ツール | 理由 |
|---|---|---|
| コーディング | LuaSnip | ファイルタイプ別に設定できる |
| それ以外全般 | espanso | どのアプリでも使える |
espanso の使用例
- メールの挨拶文
- 住所・連絡先
- よく使うフレーズ
- ミーティング候補日の生成
LuaSnip の使用例
- 関数テンプレート
- ボイラープレートコード
- 言語固有のイディオム
- テストコードの雛形
espanso
Rust製のテキストエクスパンダーです。macOS、Windows、Linuxで動作します。
基本的な設定
~/.config/espanso/match/base.yml:
matches:
# 静的なスニペット
- trigger: ";;mail"
replace: "example@example.com"
- trigger: ";;addr"
replace: |
〒100-0001
東京都千代田区...
# 動的なスニペット(日付)
- trigger: ";;today"
replace: "{{date}}"
vars:
- name: date
type: date
params:
format: "%Y/%m/%d"
外部スクリプトの実行
espansoの強力な機能のひとつが、外部スクリプトの実行です。
例として、;;sche で直近1週間のミーティング候補日を動的に出力する設定:
matches:
- trigger: ";;sche"
replace: "{{output}}"
vars:
- name: output
type: script
params:
args:
- python3
- /path/to/scripts/schedule.py
# schedule.py
from datetime import datetime, timedelta
def generate_schedule():
today = datetime.now()
lines = ["ミーティング候補日:", ""]
for i in range(7):
date = today + timedelta(days=i)
weekday = ["月", "火", "水", "木", "金", "土", "日"][date.weekday()]
lines.append(f"- {date.month}/{date.day}({weekday}) 10:00-18:00")
return "\n".join(lines)
print(generate_schedule())
これで ;;sche と入力すると、以下のような文字列が展開されます:
ミーティング候補日:
- 12/9(月) 10:00-18:00
- 12/10(火) 10:00-18:00
- 12/11(水) 10:00-18:00
...
毎回手で書く必要がなくなって、かなり楽になりました。
LuaSnip
Neovim用の高機能スニペットエンジンです。
ファイルタイプ別設定
LuaSnipの強みは、ファイルタイプごとにスニペットを定義できること。
-- lua/snippets/typescript.lua
local ls = require("luasnip")
local s = ls.snippet
local t = ls.text_node
local i = ls.insert_node
return {
-- 関数テンプレート
s("fn", {
t("function "),
i(1, "name"),
t("("),
i(2),
t(") {"),
t({"", " "}),
i(0),
t({"", "}"}),
}),
-- アロー関数
s("af", {
t("const "),
i(1, "name"),
t(" = ("),
i(2),
t(") => {"),
t({"", " "}),
i(0),
t({"", "}"}),
}),
}
TypeScriptファイルでのみ fn や af が展開される、といった使い分けができます。
外部スクリプトの実行
LuaSnipでも外部スクリプトを実行できます。
local ls = require("luasnip")
local s = ls.snippet
local f = ls.function_node
s("uuid", {
f(function()
local handle = io.popen("uuidgen")
local result = handle:read("*a"):gsub("%s+$", "")
handle:close()
return result
end),
}),
uuid と入力すると、動的にUUIDが生成されます。
espanso の改善:入力ミス対策
espansoを使っていて、どうしても改善したかった点がありました。
長いトリガーを入力間違えてしまうと発火しない
例えば ;;schedule というトリガーを設定していて、;;schedle(lが抜けた)と入力してしまうと、何も起こりません。
入力を消してやり直すのが地味にストレスでした。
Better Touch Tool を使った解決策
これを改善するために、Better Touch Tool と組み合わせる設定を行いました。
仕組み
- 発火させたいトリガー(例:
;;sche)をクリップボードにコピー - 任意の場所で
Ctrl+Shift+;を押す - クリップボードの内容が「入力」され、espansoが発火
Better Touch Tool の設定
- Better Touch Tool を開く
- キーボードショートカットを追加
Ctrl+Shift+;にキーマップを設定- アクションとして「テキストを入力(Insert / Type Custom Text)」を選択
- 入力内容に
{clipboard}を設定
重要: 「入力してテキストを挿入する(Type text)」オプションを選択すること。
espansoはテキスト入力を監視して発火するため、単なるペーストではなく「キーボードからの入力」として扱わせる必要があります。
使い方
1. トリガー文字列をコピー(例:;;sche をコピー)
2. 展開したい場所にカーソルを移動
3. Ctrl+Shift+; を押す
4. espanso がトリガーを検知して展開
これで入力ミスを気にせず、確実にスニペットを展開できるようになりました。
よく使うトリガーの管理
この方法を活用して、よく使うトリガーをテキストファイルで管理しています。
# ~/snippets.txt
;;sche - ミーティング候補日
;;mail - メールアドレス
;;addr - 住所
;;thanks - お礼メール
;;mtg - 議事録テンプレート
このファイルから必要なトリガーをコピーして Ctrl+Shift+; で展開。
トリガー名を覚えていなくても大丈夫です。
まとめ
スニペットツールの使い分け:
| ツール | 用途 | 特徴 |
|---|---|---|
| espanso | システム全体 | どのアプリでも使える、外部スクリプト実行可能 |
| LuaSnip | Neovim | ファイルタイプ別設定、プレースホルダー移動 |
共通して気に入っている点:
- 外部スクリプト実行 — 動的なコンテンツ生成が可能
- 設定ファイルで管理 — バージョン管理できる、dotfilesに含められる
espansoの入力ミス対策:
- Better Touch Tool と連携
- トリガーをコピー →
Ctrl+Shift+;で確実に展開 - 長いトリガー名でも安心
スニペットは一度設定すると長く使えるので、時間をかけて整備する価値があります。