Open6

VSCode Snippetいろいろ

yg_siroyg_siro

EBNFは以下の通り

any         ::= tabstop | placeholder | choice | variable | text
tabstop     ::= '$' int
                | '${' int '}'
                | '${' int  transform '}'
placeholder ::= '${' int ':' any '}'
choice      ::= '${' int '|' text (',' text)* '|}'
variable    ::= '$' var | '${' var '}'
                | '${' var ':' any '}'
                | '${' var transform '}'
transform   ::= '/' regex '/' (format | text)+ '/' options
format      ::= '$' int | '${' int '}'
                | '${' int ':' '/upcase' | '/downcase' | '/capitalize' | '/camelcase' | '/pascalcase' '}'
                | '${' int ':+' if '}'
                | '${' int ':?' if ':' else '}'
                | '${' int ':-' else '}' | '${' int ':' else '}'
regex       ::= JavaScript Regular Expression value (ctor-string)
options     ::= JavaScript Regular Expression option (ctor-options)
var         ::= [_a-zA-Z] [_a-zA-Z0-9]*
int         ::= [0-9]+
text        ::= .*

VSCodeのスニペットのページで説明されていない項目がたくさんある。

yg_siroyg_siro

正規表現の変数はタブストップの内容も指定できるらしい。

以下のスニペットはC++の関数を作成するスニペットで戻り値の型がvoidのときのみreturn文を省略するスニペットです。

  "C++ function template": {
    "prefix": "func",
    "body": [
      "${1:void} ${2:funcName}($0){",
      "  ${1/void$|(.+)/${1:+return {\\};}/}",
      "}"
    ],
    "description": "voidの場合return文は不要です。"
  }

1行目はなんの変哲もないスニペットの構文です。
2行目が正規表現の構文${変数/正規表現/置換/正規表現オプション}を使用していろいろしています。

${1/void$|(.+)/${1:+return {\\};}/}を分解すると

変数が1(タブストップ$1の内容を参照)。

正規表現がvoid$|(.+)。voidのときだけキャプチャしない。

置換が${1:+return {\\};}
これは${int:+ if}の構文を使用しています。
キャプチャグループ1の内容が空でなければif(つまり今回の例で言えばreturn {\\};)を挿入しています。

今回正規表現のオプションは無しです。

yg_siroyg_siro

スニペットのデフォルト値に変数を使用することも可能だし、正規表現を使用することも可能。

例えば以下のようなC++のインクルードガードのスニペットを作成する。

FILENAME_EXTはファイル名を大文字にして._に変更する。

#ifndef FILENAME_EXT
#defien FILENAME_EXT

#endif // FILENAME_EXT

作成する。

cpp.json
{
"#inc-g": {
    "prefix": "#hdr",
    "body": [
      "#ifndef ${1:${TM_FILENAME/(?:(\\w+)(\\.)?)/${1:/upcase}${2:+_}/gi}}",
      "#define $1",
      "$0",
      "#endif // $1"
    ],
    "description": "include guards."
  },
}

このスニペットを展開すると以下のように展開されるはず

math.hpp
#ifndef MATH_HPP
#define MATH_HPP

#endif MATH_HPP

$1のデフォルト値に${TM_FILENAME/(?:(\\w+)(\\.)?)/${1:/upcase}${2:+_}/gi}を設定しています。

${TM_FILENAME/(?:(\\w+)(\\.)?)/${1:/upcase}${2:+_}/gi}はファイル名を大文字、._に変更する正規表現です。

正規表現の説明

+(?:~)…キャプチャしないグループ化
+(\\w+)…文字のみの繰り返し
+(\\.)?.が0or1個

ファイル名がabc.def.hppの場合
(abc)(.)にマッチ→${1:/upcase}1つ目のマッチ(abc)を大文字に、${2:+_}2つ目のマッチが空白でないので_に→ABC_

正規表現オプションのgがあるので次のマッチを探します。

(def)(.)にマッチ→${1:/upcase}1つ目のマッチ(def)を大文字に、${2:+_}2つ目のマッチが空白でないので_に→DEF_

(hpp)()にマッチ→${1:/upcase}1つ目のマッチ(hpp)を大文字に、${2:+_}2つ目のマッチが空白なので何も出力しない→HPP

結果はABC_DEF_HPPと変換されます。

yg_siroyg_siro

VS Code 1.66で変数が追加された。
$CURSOR_NUMBERCURSOR_INDEXの2つ。

マルチカーソルの順番で以下の順で数字が挿入される。
$CURSOR_NUMBERは1,2,3,...Nのように1から始まる順番
$CURSOR_INDEXは0,1,2,...Nのように0から始まる順番

リリースノートのサンプルではMarkdownのorder listのサンプルになっている。

{
  "ordered_list": {
    "scope": "markdown",
    "prefix": "ol",
    "body": [
      "$CURSOR_NUMBER. $0"
    ],
    "description": "Add ordered list"
  }
}

動作サンプル。Ctrl+Alt+↓で複数行マルチカーソル状態に。