VSCodeでスニペットを作成する
VSCodeでよく使う文があるならスニペットを使用するのが便利です。
標準で用意されていたり拡張機能をインストールすることで使用できますが、
ユーザー独自でもスニペットを作成できるのでそれについての説明をしていきます。
スニペットファイルを用意する。
VSCode左下の歯車アイコンからユーザースニペットを選択し、スニペットを登録したい言語のjsonファイルを選択すると初期では以下のようなファイルが開かれます。
{
// Place your snippets for cpp here. Each snippet is defined under a snippet name and has a prefix, body and
// description. The prefix is what is used to trigger the snippet and the body will be expanded and inserted. Possible variables are:
// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders. Placeholders with the
// same ids are connected.
// Example:
// "Print to console": {
// "prefix": "log",
// "body": [
// "console.log('$1');",
// "$2"
// ],
// "description": "Log output to console"
// }
}
サンプルも記載あるのでサンプルのコメントを外して実際のファイルでどんなふうに動くか確認してみます。
{
"Print to console": {
"prefix": "log",
"body": [
"console.log('$1');",
"$2"
],
"description": "Log output to console"
}
}
コメントアウトして保存しjavascriptのファイルでlog
と入力しtabキーを押せば以下のようになります。
console.log('');
また展開後のカーソルの位置はjsonファイルで記入した$1
の位置に移動します。
文字入力後tabキーを押せば$2
の位置に移動します。
スニペットが便利なのはテンプレート文を入力するだけでなく入力位置にカーソルが移動してくれたり、ファイル名や日付を変数を利用して入力したり、正規表現を利用して文字列を加工したりできることです。
構文
"スニペット名":{
"prefix": "短縮語", // 複数の場合は["a", "b"]のように入力
"body": "展開するコード", // 複数行に展開したい場合は["1行目", "2行目", "3行目"...]
"description": "説明文" // オプション。なくても構わない。
}
スニペット名は一意の名称を設定します。
サンプルと見比べてみればわかりやすいかもしれません。
スニペットや短縮語、説明文はとくに説明することはありません。
短縮語は複数登録することができるくらいです。
展開するコードについていろいろ機能があるので説明していきます。
基本的な展開
大体のスニペットは基本的な展開でこと足ります。
サンプルを少し改造して以下のようにしてみます。
"Print to console2": {
"prefix": "log2",
"body": [
"console.log('$1');",
"console.log('$2');",
"$0"
],
"description": "2回ログを表示する"
}
$1
,$2
はスニペット展開後のカーソルの位置です。
$1
の位置で入力後、またtabを押せば次の$2
に移動します。
$0
は特別で一番最後の位置となります。
この$N
のことをタブストップといいます。
タブストップについて
タブストップについて機能がいろいろついています。
デフォルト値や選択肢、ファイル名などの変数、正規表現などです。
プレースホルダー
タブストップにはデフォルト値を設定することができます。
${N:デフォルト値}
のように記載します。
"for loop":{
"prefix": "for2",
"body": [
"for(${1: size_t} ${2: index} = 0; $2 < ${3: size}; ++$2){",
" $0"
"}"
],
"description": "C++のforループ"
}
上記サンプルで$2
が複数あることに気づいたでしょうか?
タブストップは同じ番号が複数あってもかまいません。
また最初の$2
だけデフォルト値のindexを記載していますが、展開した場合残りの$2
もデフォルト値のindexが入力されています。
//for2 -> tab
for( size_t index = 0; index < size; ++ index){
}
選択肢
タブストップは選択肢から選ぶ形にすることも可能です。
${N|option1,option2,...optionN|}
のように記載します。
"tmplate class": {
"prefix": "tmpc",
"body": [
"template<${1|typename, class|} T>",
"class ${2:tmp_class}{",
" $0",
"};"
]
},
展開例
変数
ファイル名や現在の日付を入力したい場合変数を使用することも可能です。
$変数名
のように記載します。
変数名一覧は以下のようになります。
-
TM_SELECTED_TEXT
現在選択しているテキスト -
TM_CURRENT_LINE
現在の行の内容 -
TM_CURRENT_WORD
現在のカーソル位置の単語(もしくは空白) -
TM_LINE_INDEX
最初の行を0行目としたときの現在の行番号 -
TM_LINE_NUMBER
最初の行を1行目としたときの現在の行番号 -
TM_FILENAME
現在のドキュメントのファイル名 -
TM_FILENAME_BASE
現在のドキュメントのファイル名(拡張子なし) -
TM_DIRECTORY
現在のドキュメントのディレクトリ -
TM_FILEPATH
現在のドキュメントのフルのファイルパス -
RELATIVE_FILEPATH
現在のドキュメントの相対(開いているワークスペースやフォルダに対する)ファイルパス -
CLIPBOARD
クリップボードの内容 -
WORKSPACE_NAME
開いているワークスペースまたはフォルダーの名前 -
WORKSPACE_FOLDER
開いているワークスペースまたはフォルダーのパス -
CURRENT_YEAR
現在の年 -
CURRENT_YEAR_SHORT
現在の年の下2桁 -
CURRENT_MONTH
2桁の月 (例 '02') -
CURRENT_MONTH_NAME
月の正式名称(例:'July') -
CURRENT_MONTH_NAME_SHORT
月の略称(例:'Jul')。 -
CURRENT_DATE
2桁の日付(例:'08') -
CURRENT_DAY_NAME
曜日名 (例: 'Monday') -
CURRENT_DAY_NAME_SHORT
曜日の略称(例:'Mon') -
CURRENT_HOUR
24時間表示での現在時刻 -
CURRENT_MINUTE
現在の分を2桁で表示 -
CURRENT_SECOND
現在の秒を2桁で表示 -
CURRENT_SECONDS_UNIX
Unixエポックからの秒数 -
RANDOM
10進数6桁の乱数 -
RANDOM_HEX
16進数6桁の乱数 -
UUID
バージョン4のUUID -
BLOCK_COMMENT_START
出力例:C++の場合/*
またはHTMLの場合<!--
-
BLOCK_COMMENT_END
出力例:C++の場合*/
またはHTMLの場合-->
-
LINE_COMMENT
出力例:C++の場合//
-
1
~9
タブストップ$1
~$9
の内容 -
CURSOR_INDEX
マルチカーソルの最初の選択を0とした番号 -
CURSOR_NUMBER
マルチカーソルの最初の選択を1とした番号
"day":{
"prefix": "day",
"body": "$CURRENT_YEAR/$CURRENT_MONTH/$CURRENT_DATE-$CURRENT_HOUR:$CURRENT_MINUTE:$CURRENT_SECOND",
"description": "YYYY/MM/DD-HH:MM:SS"
}
2022/03/13-16:57:11
正規表現
変数に対して正規表現で加工することが可能です。
${変数/正規表現/置換/正規表現オプション}
"#name": {
"prefix": "#name",
"body": "${TM_FILENAME/(?:(\\w+)(\\.)?)/${1:/upcase}${2:+_}/gi}"
}
HEADER_SAMPLE_HPP
header.sample.hppのファイルで上記スニペットを展開した場合
正規表現及び正規表現オプションはjavascript
の正規表現を確認してください。
スニペット独自の機能として置換後の$1...
などに大文字化などのオプションがあります。
上記サンプルで${1: /upcase}
としている部分の/upcase
がオプションです。
置換項目のオプション一覧
-
/upcase
大文字にする -
/downcase
小文字にする -
/capitalize
文字の先頭を大文字にする -
/camelcase
キャメルケースにする -
/pascalcase
パスカルケースにする -
+ string
正規表現でキャプチャした部分が空白でなければstring -
? A: B
正規表現でキャプチャした部分が空白でなければA,空白ならB -
- string
正規表現でキャプチャした部分が空白であればstring -
string
正規表現でキャプチャした部分が空白であればstring
キャピタライズなどについて
/capitalize
の変換は最初の一文字しか変換しません・・・キャピタライズとは・・・?
/camelcase
,/pascalcase
は空白や記号などを削除はしてくれますが最初の文字以外、大文字を小文字にすることはないようです。
一旦/downcase
で全て小文字にしてからキャメル/パスカルケースにした方が思った通りの変換するかも
複数の変換をかけないのでスニペットは長く見づらくなりますが・・・
ショートカットキーなど
変数一覧に現在の選択範囲があったのを覚えていますか?
選択範囲に対してスニペットを適用する場合は短縮名を入力では対応できません。
コマンドパレットから選択
選択範囲に対してスニペットを適用する方法は2通りあり一つはコマンドパレットからスニペットの挿入を選ぶ方法です。
Ctrl+Shift+P
→スニペットの挿入→該当のスニペットを選択
ショートカットキーによる適用
もうひとつはショートカットキーに割り当ててしまう方法です。
こちらは先程のjsonファイルとは異なるjsonファイルに記載します。
ファイル→ユーザー設定→キーボードショートカット→右上のキーボードショートカットを開くのアイコンをクリック
すると以下のようなjsonファイルが開くきます。
// 既定値を上書きするには、このファイル内にキー バインドを挿入します
[]
そこにショートカットキーとして追加していきます。
[{
"key": "cmd+k 1",
"command": "editor.action.insertSnippet",
"when": "editorTextFocus",
"args": {
"snippet": "`$TM_SELECTED_TEXT`"
}
}]
すでに言語のjsonファイルでスニペットを登録しており、それを呼び出すだけの場合以下のようにします。
[{
"key": "cmd+k 1",
"command": "editor.action.insertSnippet",
"when": "editorTextFocus",
"args": {
"langId": "cpp",
"name": "tmplate class"
}
}]
cpp.jsonで定義されたtemplate classという名前のスニペットをショートカットキーcmd+k、1で挿入します。
ワークスペースのみで使用するスニペットの場合
現在のプロジェクトだけ使用したいスニペットとかもあるでしょう。
そんな場合は以下のようにフォルダ名
の新しいスニペットファイルを選択して適当な名前で保存します。
ファイル→ユーザー設定→ユーザースニペット
ファイル名は何でも構いません
sampleという名前で作成するとフォルダの直下に.vscodeフォルダが作成されそこにsample.code-snippetsというファイルができます。
内容はほとんど同じですがjsonファイルのサンプルにscopeという項目が増えています。
scope
はスニペットを適用する言語を指定します。
{
// Place your Sample ワークスペース snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and
// description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope
// is left empty or omitted, the snippet gets applied to all languages. The prefix is what is
// used to trigger the snippet and the body will be expanded and inserted. Possible variables are:
// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders.
// Placeholders with the same ids are connected.
// Example:
// "Print to console": {
// "scope": "javascript,typescript",
// "prefix": "log",
// "body": [
// "console.log('$1');",
// "$2"
// ],
// "description": "Log output to console"
// }
}
コメントアウトして保存すればjavascript及びtypescriptのファイルでlog→tabで展開されます。
ちなみにscopeを設定しない場合はワークスペース内のすべてのファイルでスニペットを使用できます。
ファイルテンプレート
スニペットのプロパティにisFileTemplate
という項目が追加されていました。
このプロパティをtrue
に設定するとそのスニペットがファイルテンプレートとなり、
コマンドパレットのファイルをスニペットで満たすから選択することが出来ます。
既存の何か書いているファイルでこのスニペットを呼び出した場合、書いている項目は全部消えます。
ファイルテンプレートのスニペットにprefix
を設定するとうっかり呼び出してしまう可能性があるので設定しない方がいいでしょう。
その他
説明がまとまってない情報に関してはスクラップに投稿しています。
整理できれば記事にしたい
Discussion