Yappli Tech Blog

株式会社ヤプリの開発メンバーによるブログです。最新の技術情報からチーム・働き方に関するテーマまで、日々の熱い想いを持って発信していきます。

生産性を高めるために行なっているVSCodeのカスタマイズ設定

はじめに

こんにちは。サーバサイドエンジニアの中川(@tkdev0728)です。
日々コードを書くエンジニアにとって欠かせないのがエディタですよね? 自分はVSCodeを使っているのですが、使いづらいと感じたときに色々設定を変更しているので今回は個人的に便利な設定を紹介していきます。 VSCodeを使っているのであくまでVSCodeの設定として紹介しますが、今時VSCodeでできることは他のエディタでも設定できると思うのでVSCodeユーザー以外の方も参考になれば幸いです。
また、自分はMacを使って開発しているのでショートカットキーなどはMacとして紹介しますが、Windowsユーザーの方は適宜読み替えていただければと思います。
自分はこういう設定しているだったり、他にこういう設定が便利等あればコメントいただけると嬉しいです。

今回話すこと

ヤプリではいくつかのリポジトリを跨いで開発することが多く、職種によっては複数の言語を開発する場合もあります。 そのためいくつか言語ごとに設定を変えている部分もあります。
ショートカット、スニペット、拡張機能の順で紹介しようと思います。

環境

  • OS: macOS Ventura 13.6.2 Apple M2 Max
  • VSCode Version: 1.87.2
  • JISキーボード(BAROCCO MD770 JP)

ショートカット

VSCodeはいくつか便利なショートカットがあるのですが、みなさんどんなショートカットがあるのかご存知でしょうか? よく使うショートカット以外は知らないという方はぜひ一覧でみることをおすすめします。 Help->Keyboards Shortcuts Reference もしくは ⌘ + k ⌘ + r にて確認できます。

ショートカットが一覧で出てくると思うのですが、デフォルト設定だと使いづらいと感じる設定もあると思います。 ⌘ + k ⌘ + s で一覧を開き、対象のショートカットにホバーして表示される鉛筆マークをクリックし、上書きしたいショートカットキーを選択するとショートカットキーを上書きもできます。 設定はjsonで上書きすることで変更することもできます。 ⌘ + shift + p でコマンドパレットを開き、shortcutと入力してPreference Open Keyboard Shortcuts (JSON)を開くとショートカットのjsonファイルが開きます。 今回は自分がデフォルト設定を上書きしている設定を keybindings.json にコピペで使えるようにjson形式でいくつか紹介します。

// カーソルを左に移動
{
  "key": "ctrl+b",
  "command": "cursorLeft",
  "when": "editorTextFocus"
},

こちらは基本中の基本ですね。自分はmacのデフォルト設定に合わせてpnbfで上下左右に移動したいのですが、左に移動するショートカットのみデフォルト設定が違うので変更しています。
移動するショートカットキーは人によってこだわりがあると思うのでこの辺は自分の使いやすいキーに合わせて適宜変更するのがいいかなと思います。

// 選択範囲を上に拡大
{
    "key": "ctrl+shift+p",
    "command": "cursorUpSelect",
    "when": "textInputFocus"
},
// 選択範囲を下に拡大
{
    "key": "ctrl+shift+n",
    "command": "cursorDownSelect",
    "when": "textInputFocus"
},
// 選択範囲を左に拡大
{
    "key": "ctrl+shift+b",
    "command": "cursorLeftSelect",
    "when": "textInputFocus"
},
// 選択範囲を右に拡大
{
    "key": "ctrl+shift+f",
    "command": "cursorRightSelect",
    "When": "textInputFocus"
}

コードを書いている時に選択範囲を必要に応じて拡大したい場面はあるかと思います。そういう場合にshift + 矢印キー だとホームポジションが離れてしまうのが嫌なのと、覚えるコストを減らすために移動の時と極力同じショートカットで選択したいので ctrl + shift + pnfd のいずれかで選択範囲を拡大できるようにしています。

// 先頭文字を大文字に変換する
{
    "key": "ctrl+i",
    "command": "editor.action.transformToTitlecase"
},
// 単語を全て大文字にする
{
    "key": "ctrl+u",
    "command": "editor.action.transformToUppercase"
},
// 単語を全て小文字にする
{
    "key": "ctrl+l",
    "command": "editor.action.transformToLowercase"
},

キャメルケースに変更するショートカットとスネークケースに変更する方法は⌘ + shift + pでコマンドパレットを表示し、 Transform to Camel(Snake) Case と入力すれば変更できますが、例えば定数を定義するときなど単語を全て大文字で入力したかったり先頭のみ大文字を入力したい場合があり、それらの変換はデフォルトでは設定されていなかったので上記の定義を追加しています。

// ()を入力して、()内を選択状態にする
{
    "key": "ctrl+8",
    "command": "editor.action.insertSnippet",
    "when": "textInputFocus",
    "args": {
        "snippet": "($0)"
    }
},
// {}を入力して、{}内を選択状態にする
{
    "key": "ctrl+[",
    "command": "editor.action.insertSnippet",
    "when": "textInputFocus",
    "args": {
        "snippet": "{$0}"
    }
},
// ""を入力して、""内を選択状態にする
{
    "key": "ctrl+2",
    "command": "editor.action.insertSnippet",
    "when": "textInputFocus",
    "args": {
        "snippet": "\"$0\""
    }
},
// ''を入力して、''内を選択状態にする
{
    "key": "ctrl+7",
    "command": "editor.action.insertSnippet",
    "when": "textInputFocus",
    "args": {
        "snippet": "'$0'"
    }
},
// ``を入力して、``内を選択状態にする
{
    "key": "ctrl+[BracketLeft]",
    "command": "editor.action.insertSnippet",
    "when": "textInputFocus",
    "args": {
        "snippet": "`$0`"
    }
},

自分は今はJISキーボードを使っており、shiftキーは右側を使うことが多いです。
コードを書いていて上記の記号を入力するときにshiftキーを押すために一度ホームポジションから離れることがストレスだったので、shiftキーの代わりにctrlキーを割り当てて記号入力に使っています。

// 今開いているファイルを垂直分割して右側に表示
{
    "key": "cmd+[IntlYen]",
    "command": "workbench.action.splitEditor"
},
// 今開いているファイルを水平分割して下に表示
{
    "key": "cmd+[Equal]",
    "command": "workbench.action.splitEditorOrthogonal"
},

同じファイルの別の部分を比較するために垂直(水平)分割することはあると思います。 そのショートカットがデフォルトだと使いづらいと感じたので上記の設定に変更しています。

スニペット

ショートカットとは別に、よく使う処理をひとまとめにしてスニペットに登録していたりします。
⌘ + shift + pでコマンドパレットを開いて Snippets: Configure User Snippets と入力するとスニペットの設定ができます。
スニペットの設定はプロジェクト共通で使えるグローバルな設定と、プロジェクトごとにも設定できます。
スニペットには変数も設定でき、例えば$CLIPBOARDでクリップボードの内容を展開してくれますし、$1、$2、...と指定しておけばtabキーを押すごとにカーソルが移動するので可変になる部分を続けて入力することもできます。 自分はフロントとサーバーのプロジェクトで設定を分けているのでそれぞれ紹介しようと思います。
設定したい内容をsnipet-generatorに入力すればコピペするだけで使えるのでぜひご自身がよく使う設定があれば登録してみてください。

フロント (JavaScript, TypeScript, vue)

// クリップボードの変数をデバッグ
"Print to console": {
    "scope": "javascript,typescript, Vue",
    "prefix": "clog",
    "body": [
        "console.log($CLIPBOARD);"
    ],
    "description": "Log output to console"
},
// 処理がどこまで通ってるか確認 
"debug hoge log": {
    "scope": "javascript,typescript, Vue",
    "prefix": "hl",
    "body": [   
        "console.log(\"hoge\");"
    ],
    "description": "Log output to console"
},
// 特殊な命名規則 getHogeMethod → AGetHogeMethodPayload 
"action payload": {
    "scope": "typescript",
    "prefix": "apa",
    "body": [
        "$CLIPBOARD: A${CLIPBOARD/(.)/${1:/upcase}/}Payload;"
    ],
    "description": "action payload"
},
// 特殊な命名規則 getHogeMethod → MGetHogeMethodPayload 
"mutation payload": {
    "scope": "typescript",
    "prefix": "mpa",
    "body": [
        "$CLIPBOARD: M${CLIPBOARD/(.)/${1:/upcase}/}Payload;"
    ],
    "description": "mutation payload"
},
// computed で基本型の変数を宣言する
"computed": {
  "scope": "typescript, Vue",
    "prefix": "cc",
    "body": [
        "const $1 = computed<${2|string,number,boolean|}>(() => {",
        "  $3",
        "});"
    ],
    "description": "computed"
},
// computedで宣言した変数にvalueを使ってアクセスしたい時 
"variable.value": {
    "prefix": "val",
    "body": [
        "$CLIPBOARD.value"
    ],
    "description": "variable.value"
},
// compositon API でmethodを宣言する 
"method": {
    "scope": "javascript,typescript, Vue",
    "prefix": "cm",
    "body": [
        "const $1 = ($2) => {",
        "  $0",
        "};"
    ],
    "description": "method"
},
// constな変数宣言 
"variable": {
    "scope": "javascript,typescript, Vue",
    "prefix": "cv",
    "body": [
        "const $1 = $2"
    ],
    "description": "method"
},
// 引数を宣言する時に型も指定する 
"arg": {
    "prefix": "arg",
    "body": [
        "$1: $2"
    ],
    "description": "argument"
},
"if": {
    "prefix": "if",
    "body": [
        "if ($1) {",
        "  $2",
        "}$0"
    ],
    "description": "if"
},
"el": {
    "prefix": "el",
    "body": [
        "else {",
        "  $2",
        "}$0"
    ],
    "description": "else"
},
"else if": {
    "prefix": "elif",
    "body": [
        "else if ($1) {",
        "  $2",
        "}$0"
    ],
    "description": "else if"
},
"foreach (value)": {
    "prefix": "fore",
    "body": [
        "forEach($1 => {",
        "  $2",
        "});$0"
    ],
    "description": "foreach (value)"
},
"foreach (value, index)": {
    "prefix": "forei",
    "body": [
        "forEach((${1:value}, ${2:index}) => {",
        "  $3",
        "});$0"
    ],
    "description": "foreach (value, index)"
},
// array key でark 
"array['']": {
    "prefix": "ark",
    "body": [
        "$CLIPBOARD['$1'] = $2;$0"
    ],
    "description": "array['']"
},
// add object key でadobk 
"object.key": {
    "prefix": "adobk",
    "body": [
        "$CLIPBOARD.$1 = $2;$0"
    ],
    "description": "add object.key"
},
"describe": {
    "prefix": "desc",
    "body": [
        "describe('$1', () => {",
        "  it('$2', () => {",
        "    $0",
        "  });",
        "});",
 ],
    "description": "describe"
},
"!== undefined": {
    "prefix": "unde",
    "body": [
        "!== undefined"
    ],
    "description": "!== undefined"
},
"===": {
    "prefix": "equ",
    "body": [
        "=== "
    ],
    "description": "==="
}

 サーバー(Go)

おそらくVSCodeでGoを開発している方であれば誰でもいれているであろう拡張機能のスニペット が幅広くサポートしてくれており、あまり特別な設定はしていないです。 あえて言うならエラーハンドリングとログ出力くらいです。

"if err != nil": {
  "prefix": "ierr",
  "body": [
    "if err != nil {",
    "  $1",
    "}"
  ],
  "description": "if err != nil"
},
"if err != nil with errors.WithStack": {
  "prefix": "iew",
  "body": [
    "if err != nil {",
    "  return nil, errors.WithStack(err)",
    "}"
  ],
  "description": "if err != nil with errors.WithStack"
},
"errors.WithStack": {
  "prefix": "ew",
  "body": "errors.WithStack(err)",
  "description": "errors.WithStack"
},
"log.Infof": {
  "prefix": "li",
  "body": [
    "log.Infof(ctx, \"%v\", $1)",
  ],
  "description": "log.Infof"
},
"log.Warnf": {
  "prefix": "lw",
  "body": [
    "log.Warnf(ctx, \"%v\", err)",
  ],
  "description": "log.Warnf"
},
"log.Errorf": {
  "prefix": "le",
  "body": [
    "log.Errorf(ctx, \"%v\", err)",
  ],
  "description": "log.Errorf"
}

拡張機能

本当はここに紹介する以外にも色々な拡張機能を入れているのですが、全部紹介しようとするときりがないので抜粋して紹介します。

Auto Rename Tag

主にフロントのコーディングをしていてHTMLのタグ名を変更するときに開きタグと閉じタグのセットを同じタグに変えてくれます。
変え忘れも防げますし、いちいちフォーカスを当てる必要もないので便利です。

Bracket Select

この拡張機能は個人的に一番推したい拡張機能です。alt+ aのショートカットで(), {}, [], "", ''などで囲まれている中を全て選択してくれます。 単語選択用のショートカットはいくつかありますが、条件式などを丸々コピーする際にはデフォルトのショートカットだとできないのでこちらの拡張機能を入れておくとドット区切りなどの単語も全て選択状態にできます。

hightlight-selections-VSCode

同じ単語を全て強調表示してくれます。typoなどしていたときに確認できます。

Path Autocomplete, Path Intellisense

importするときなどにコードのパス補完をしてくれる拡張機能と、ファイル名を自動補完してくれる拡張機能です。 importするときにパスを思い出す必要がないので便利です。

まとめ

自分がよく使っているVSCodeの設定や拡張機能について紹介しました!
こうやって書いたものの、実は設定した後あまり使わずに設定したことを忘れていてこの記事を書く時に思いつくこともありましたw
そのためショートカットやスニペットを設定する上で登録したキーを忘れないようにすることが何よりも大事ですねw 最近ではGithub Copilotなどが普及しているので使えるものはうまく使って生産性爆上げしていきたいですね!

参考

https://code.visualstudio.com/api/references/when-clause-contexts