Vim から VS Code へ覚悟を持って移行する

Vim から VS Code へ覚悟を持って移行する・・・!

前提

  • Vim と言いつつも、非 Vimmer が読んでも最低限分かる配慮はする
  • 普段から Vim を使っているが、 そろそろちゃんとしたレールに乗らねば と思っている
  • プラグインのアップデートに自分が追いつけなくなりつつある
  • mouse / trackpad を使ったら負け

移行前に知るべきこと

そもそも VS Code をもっと知らないといけない。 VS Code の基本的な知識が足りないので以下を押さえます。

  • 公式はとりあえず全部読む
  • 左上 Explorer, Search, VCS/Git, Debug, Extensions の5つがメイン機能
  • それ以外の便利機能、エラー表示、ターミナル表示、コマンドパレット(vscode 上のコマンド)がある
  • コマンドパレットから shell command で探すと、 code コマンドのインストールができる
    • CLI からは code . という立ち上げ方が一般的
  • プロジェクトごとの設定は、 .vscode ディレクトリが生成されて、その中に設定ファイルが置かれる

Explorer

Explorer は今のディレクトリ配下のファイルをツリー形式で表示してくれます。 Shift + Command + E で開くことができます。

Search は現在のディレクトリ配下を基準にして、横断的にファイル検索をしてくれます。 Shift + Command + F で開くことができます。

  • 検索に引っかかったファイル、場所をそれぞれ出してくれる

VCS/Git

VS Code 上では SCM (Source Control Manager?) となっているようですが、 VCS/Git (Version Control System / Git) は Git を始めとしたバージョン管理ツールが利用できます。 Shift + Control + G で開くことができます。

  • 変更されたファイルのリストが表示され、コミットメッセージを書いてそのまま commit できる
  • Shift + Command + G ではない、 find/grep に割り当てられている模様
  • これとは別に、コマンドパレットに Git コマンドが統合されており、左メニューから add, commit などが可能

Debug

Debug はエディタ上でデバッグ実行したり、外部のデバッグツールと連携して実行してくれたりします。 Shift + Command + D で開くことができます。

  • ステップ実行やブレークポイントを設定できたりする
  • .vscode/launch.json を編集することで Debug のカスタマイズが可能 -

Extensions

Extensions は VS Code が提供している拡張機能をインストールなどすることができます。 Shift + Command + X で開くことができますが、そんなに頻繁にやる行為じゃないので覚えなくてもいいかも。

PROBLEMS Panel

PROBLEMS Panel はエラー表示や警告表示をしてくれます。 Shift + Command + M で開くことができます。

OUTPUT Panel

実行時の出力などの表示をしてくれます。 Shift + Command + U で開くことができます。

DEBUG CONSOLE Panel

デバッグ用のコンソール表示をしてくれます。 Shift + Command + Y で開くことができますが、自分で開かなくても良いかもしれません。

TERMINAL Panel

ターミナル表示をしてくれます。 Control + ` で開くことができます。

  • 既存のターミナルウィンドウと統合されている
  • code [filename] で VS Code でファイル開いてみたら、見事に別ウィンドウで VS Code が立ち上がった

Command Palette

コマンドパレット を開いて、 VS Code 上の様々な機能を呼び出せます。かなりよく使いそうです。 Shift + Command + P で開くことができます。

  • コマンドパレットから色々設定可能
    • ショートカットキーの設定 (Open Keyboard Shortcuts)
    • 個人設定 (Open User Settings)
    • 言語ごとの設定 (Configure language specific settings)

その他補完など

移行リスト

ようやく目次。

  • 全体的に Vim にする
  • コロン (:) とセミコロン (;) 入れ替える
  • yank (copy), paste でシームレスにコピペ
  • relativenumber
  • ノーマルモードで enter を押すと改行される
  • 行末、行頭の間をスムーズに移動できる
  • 行末の余分な space なんとかする
  • tab / space の適切な表示
  • 単語単位の移動に対する適切な区切り
  • mouse / trackpad を触らない移動

ここから先は、各項目でそれぞれ設定ができるように見ていきます。

全体的に Vim にする

一通り知ったところで、以下の拡張機能をインストールしていきます。 これがないと息ができない ので入れます。

インストールすると以下がすでに使えるらしいです。 すごい。

コロン (:) とセミコロン (;) 入れ替える

まずこれは、 US キーボード配列の Vimmer だったら分かると思うのですが、 US キーボード配列だと、コロン (:) とセミコロン (;) は同じ位置にあって、 保存など Vim のコマンドを入力するときは :wq という形で高頻度でコロンを入力します。

Command + S も使える環境ではあるのですが、 Vim にも VS Code にも両方ある機能は、 Vim のキーバインドでさくっと呼び出せるように設定していきたいです。

長くなりましたが以下。

  • エディタ上常に入れ替えたいわけではない、 VS Code の責務ではなく、 VSCodeVim の責務
  • 入力モードのときはコロンのまま、それ以外のコマンド入力するときはコロン・セミコロンを入れ替える
  • vim-sneak などでコマンドモード時に ; を入力するものは、代わりに : を入力できる

解決法: 個人設定ファイルである settings.json に設定追記する

Extension の設定ではあるものの、追記すべきなのは個人設定ファイルに対してでした。

Shift + Command + P で Command Palette を開き、 open settings と入力して Preferences: Open Settings (JSON) と表示されている項目を選ぶと、 勝手に settings.json ファイルが開かれます。

ちなみに手動だと MacOS では $HOME/Library/Application Support/Code/User/settings.json にあるようです。

"vim.normalModeKeyBindingsNonRecursive": [
	{
		"before": [
			";"
		],
		"after": [
			":"
		]
	},
	{
		"before": [
			":"
		],
		"after": [
			";"
		]
	}
],
"vim.visualModeKeyBindingsNonRecursive": [
	{
		"before": [
			";"
		],
		"after": [
			":"
		]
	},
	{
		"before": [
			":"
		],
		"after": [
			";"
		]
	}
	],

"vim.normalModeKeyBindingsNonRecursive" とあるように、 vim. という prefix をつけることで、 VSCodeVim の拡張機能から読み取って使うようです。

上記のようにコロン、セミコロンを入れ替える設定を追記していきます。

ちなみに "vim.normalModeKeyBindings", "vim.visualModeKeyBindings" という設定も別にあって、 こちらは上書きしてつぶしてしまうので、セミコロンをコロンにしたあと、コロンをセミコロンにすると、 片方が潰れて使えなくなります。ご注意ください。

yank (copy), paste でシームレスにコピペ

厳密に言えば Vim ではないので、もう yank とは言わないのですが、 copy のアクションが y に割り振ってあって yank と呼ぶ というのは、 Vim 界隈では超有名な話です。

この yank / paste とは別に、 Command + C, Command + V の通常のコピペも存在しており、 これらは最初の状態では別物扱いされてます。 これを解消します。

  • yank して別アプリケーションにペーストできる
  • 別アプリケーションでコピーしたものを paste できる

解決法: 個人設定ファイルである settings.json に設定追記する

これも Extension の設定ではあるものの、追記すべきなのは個人設定ファイルです。

これも Shift + Command + P で Command Palette を開き、 open settings と入力して Preferences: Open Settings (JSON) を選ぶか、 あるいは Preferences: Open User Settings を選んで GUI で設定するかのどちらかです。

settings.json を直接編集する場合は以下を追記します。

"vim.useSystemClipboard": true

GUI からやりたい場合は、 Vim: Use System Clipboard という項目を探してチェックを入れます。 上にインクリメンタルサーチ用のテキストボックスがあるので、適当に vim とか clipboard とか入れると良いです。

relativenumber

Vim には set number という設定項目があって、行番号を表示するかしないかが設定できるのですが、 さらに set relativenumber という設定項目だと、行番号を相対的に表示してくれます。

相対的に表示すると何が良いかというと、 何行上に移動したいかが瞬時に数値として分かるので、行きたい行に一瞬で移動できる ことが大きなメリットです!

Vimのset relativenumberで、あの子のハートを狙い撃ち! - ばうあーろぐ

これは欲しい!というか慣れていて使えなくなるとストレスでしかないので、正しく設定しておきたいところ!

解決法: VS Code の設定を変更する

これはもうすでに VSCodeVim の拡張機能レベルの話ではなく、大元のエディタの VS Code が用意してくれてました。

以下のいずれかです。

  • settings.json を開き、 "editor.lineNumbers": "relative" を追記する
  • GUI の Preferences: Open User Settings を開き、 Editor: Line Numbers の項目を relative にする

ノーマルモードで enter を押すと改行される

Vim では、ノーマルモードでも改行だけしたいときに、 enter キーを押すだけで改行だけ挿入できるようにしていました。

Vim の設定でいうとこんな感じです。

nnoremap <CR> o<ESC>

もしかすると、ノーマルモードの enter に別の意味を持たせる可能性も今後あるのですが、 一旦前のままノーマルモードでそのまま改行が入るようにしてみます。

解決法: 個人設定ファイルである settings.json に設定追記する

コロン、セミコロンの入れ替えと同様の解決法なのですが、 after の代わりに command 実行が行えるので、それを活用して改行を挿入してみます。

"vim.normalModeKeyBindingsNonRecursive": [
	{
		"before": [
			"<Enter>"
		],
		"commands": [
			"editor.action.insertLineAfter"
		]
	}
],

"editor.action.insertLineAfter" で改行追加できるなら、他にどんなアクションがあるか気になりますよね。 それが以下の URL にまとめてみるので、独自にカスタマイズしたいときはこの辺参考にしてみると良いかもです。

https://code.visualstudio.com/docs/getstarted/keybindings

行末、行頭の間をスムーズに移動できる

Vim では、初期設定を正しくしないと以下のことができなかったりします。

  • 行末からさらに右に移動すると、次の行の先頭に移動する
  • 行頭からさらに左に移動すると、前の行の末尾に移動する
set whichwrap=h,l,<,>,[,]

普通のエディタでは当たり前に出来ていることなので、 あまり意識はしないのですが、 VSCodeVim においても、ノーマルモードでは同様のことが起こります。

なんとかしたいですね。

解決法: 個人設定ファイルである settings.json に設定追記する

  • settings.json を開き、 "vim.whichwrap": "h,l,<,>,[,]" などを追記する
  • GUI の Preferences: Open User Settings を開き、 Vim: Whichwrap の項目を h,l,<,>,[,] などにする

行末の余分な space なんとかする

これ、意外と無頓着な人が多くて、エディタでちゃんと表示して見えるようにするなり、自動で削除されるようにするなりして、 自分が意図してない行末の余分な space が入らないように心がけないといけないと思うのですが、 この辺の設定をしてみます。

ちなみに Vim だとこんな感じにやってました。

" highlight end of line spaces
function! s:EOLSpaceHighlights()
  syntax match EOLSpace "\s\+$" display containedin=ALL
  highlight EOLSpace ctermfg=15 ctermbg=167 guifg=#ffffff guibg=#e74c3c
endf

ちなみに markdown などは、行末の2つの空白を入れることで <br /> タグを挿入するという仕様があって、 無条件に行末の space を消しに行ってしまうと問題が起きると思って、 Vim 上ではハイライトするだけにしておき、自己判断で消すかどうか考える、みたいな落とし所にしてました。

https://markdown-guide.readthedocs.io/en/latest/basics.html#line-return

ちなみに上の vimrc は、末尾の space を赤っぽくハイライトするだけの設定です。

解決法: 容赦無く VS Code で設定して削除してしまう

もう Code Formatting の時代だし、エディタ側が一定フォーマットを保つっていう考え方はやって良いと思います。

そもそも markdown の末尾に 2 spaces 入れるっていう仕様がちょっとどうかと思うし、 表示側で markdown 読み取って文章的に改行されてたら改行入れるみたいな考え方もあるし、 この辺はもう妥協していこうと思います。

  • settings.json を開いて "files.trimTrailingWhitespace": true を追記する
  • GUI の Preferences: Open User Settings から Files: Trim Trailing Whitespace を探してチェックいれる

このどちらかをやります。

ってことで、自動で削除されるなら、そもそもハイライトする意味もないので、 vimrc の設定はお役御免です。 今までありがとう!

tab / space の適切な表示

これも無頓着な人がいるんだよなあ・・・。

現状では、インデント表示されている部分に tab が入っているのか、 space が入っているのかが見た目で判断できません。 この辺りの話はハードタブ(tab キー入力したら実際に tab が入力される)・ソフトタブ(tab キー入力したら space が設定された数入ってくる)みたいな話も絡んでくるのですが、 そもそも混ざっているのにそれが表示上で認識出来ないのはダメだと思います。

解決法: VS Code の設定を変更する

これは Vim レベルの話ではなく、エディタレベルの設定の話なので、当然 VS Code 上に設定項目があります。

  • settings.json を開いて "editor.renderWhitespace": "all" を追記する
  • GUI の Preferences: Open User Settings から Editor: Render Whitespace を探して all を選ぶ

これはほぼ必須の項目だと思うんだけど、なぜ default になってないんだろう。

1文字違ったら別ファイルなのでちゃんと設定しておきます。

単語単位の移動に対する適切な区切り

使ってて気づきましたが、 Vim だと w, e, b などの単語間の移動で漢字だけ、ひらがなだけ、全角カッコなど、 日本語の区切りになってるところで適切に単語として移動できるのですが、 VSCodeVim を導入しただけではそれが出来ません。

ちなみに Vim においてはこんな意味です。

  • w: 次の単語の先頭にカーソル位置を移動する
  • e: 今の単語の最後にカーソル位置を移動する、今の位置が最後なら、次の単語
  • b: 前の単語の先頭にカーソル位置を移動する

そもそも普通のエディタには word という概念がないので、当然っちゃあ当然なのですが、 普通に Vim 感覚で触っていると、行きすぎてしまったりするケースが度々起こり、それなりにストレスになります。

解決法: Extensions: Japanese Word Handler を入れて個人設定ファイルに追記する(ただし課題あり)

色々試してみたけど、完全な解決は現状難しそうでした。

まず日本語の単語単位での移動に対応した Extension が公開されていたので、 これを入れて w, e, b にそれぞれ紐づければ良さそうです。

https://marketplace.visualstudio.com/items?itemName=sgryjp.japanese-word-handler

これをインストールするだけで、以下のショートカットが有効になるようです。(すべて MacOS )

  • Option + Right: 次の単語へ移動
  • Option + Left: 前の単語へ移動
  • Shift + Option + Right: 次の単語まで選択
  • Shift + Option + Left: 前の単語まで選択

これを、 w, b と組み合わせますが、 e については割り当てがないようなので、擬似的に w と同じにしておきます。

なお、 Extension の外から見えるコマンドについては、 実際にソースコードを見てみると分かるのですが、 vscode.commands.registerCommand の第一引数に指定してある名前がそのまま使えるようなので、 今回で言うと extension.cursorNextWordEndJa, extension.cursorPrevWordStartJa の2つが使えそうです。

https://github.com/sgryjp/japanese-word-handler/blob/master/src/extension.ts

個人設定ファイルへの割り当て方はだいたいこんな感じです。

"vim.normalModeKeyBindingsNonRecursive": [
	{
		"before": [
			"w"
		],
		"commands": [
			"extension.cursorNextWordEndJa"
		]
	},
	{
		"before": [
			"e"
		],
		"commands": [
			"extension.cursorNextWordEndJa"
		]
	},
	{
		"before": [
			"b"
		],
		"commands": [
			"extension.cursorPrevWordStartJa"
		]
	}
]

とまあ、ここまでのカスタマイズが一旦の限界っぽい感じです。

移動に関してはこれで良いのですが、 選択に関してはもう少しカスタマイズが必要 で、少し課題が残ります。

mouse / trackpad を触らない移動

これ、実は1つじゃなくて複数あります。

  • Editor 内移動、 Editor 間移動
  • Side Bar と Editor 間の移動
    • Explorer は Quick Open (Command + P) で代用できるのでいらないかもしれない・・・
    • Git 周りは commit 以外に何ができるのかが不明、 Terminal でやっちゃえばいいのかも・・・
    • そう考えると Search, Debug 以外ではほとんど使わない?
  • Panel と Editor 間の移動
    • 特に Terminal との移動はスムーズにやりたい
    • 本来の責務は tmux で pane 移動がそれにあたる

それぞれで移動方法を細かく設定していきます。

Editor 内移動、 Editor 間移動

まずここだけは他の人とキーバインドが異なるだろうと思って、理解した上で使っているのですが、 Vim 上での tabpage の移動は Ctrl + H, Ctrl + L を使っていました。

Ctrl + L に関しては Terminal の clear コマンドをかぶるところはありますが、 tabpage の左右移動はものすごくよく使うので、あえてそこは潰して使っています。 実際 iTerm2 上で Vim が立ち上がっている状態なので、 clear コマンドは実質使わないんですけども。

ちなみになぜ H, L に割り振ってあるかというと、 Vim において hjkl がそれぞれ左、下、上、右を指し、左右移動は hl を使うのが直感的だからです。

解決法: キーマッピングの個人設定ファイルである keybindings.json に設定追記する

設定の追記の話をする前に、そもそもキーマッピングの設定がどのようにされているかに触れたいと思います。

{
	"key": "down",
	"command": "cursorDown",
	"when": "textInputFocus"
},

これは Default Keybindings の設定から抜粋したものです。

  • key: キーマッピングの指定
  • command: そのキーを押したときに何を行うか、用意されているコマンドを指定する
  • when: (オプション)そのキーマッピングが有効になるときの条件

key に対応する command を指定することで、個人のキーマッピングが追加できます。

追加先は他のファイルと同様に CLI, GUI の2種類のやり方があります。

  • Command Pelette から Preferences: Open Keyboard Shortcuts (JSON) を選び、 keybindings.json を開いて編集する
  • Command Pelette から Preferences: Open Keyboard Shortcuts を選び、対応する項目を探し、編集する

どちらでも良いのですが、キーマッピングに関して言えば、 CLI の方が若干設定しやすい感はあるのかもしれないですね。

仮に CLI で keybindings.json を開いたとして、以下を追記していきます。

// Editor 内移動
{
	"key": "ctrl+h",
	"command": "workbench.action.previousEditor"
},
{
	"key": "ctrl+l",
	"command": "workbench.action.nextEditor"
},

今回は入力モードに限らず左右移動してほしいので、 VS Code のレベルで keybindings.json に追記しています。

  • "workbench.action.previousEditor": 複数ある Editor の前のものを開く
  • "workbench.action.nextEditor": 複数ある Editor の次のものを開く

これ追記するだけでだいぶ違ってきますねー。 分割してあるエディタであっても、前後の定義がされているらしく、 Ctrl + H, Ctrl + L で貫通して前後に移動が出来ます。 素晴らしい。

正直なところ、 Side Bar をどう上手く活用していったらいいのかがまだ掴めていないです・・・。

  • File Open は Command + P で済みそう
  • Git 系コマンドは TERMINAL Panel でそのまま入力すれば事足りそう
  • Explorer 内にもいくつか他に機能があって、まだ全貌が掴めない・・・

一旦保留・・・

もう少し使い方慣れてからかなー?

Panel と Editor 間の移動

この辺りは tmux にだいぶ近くなってくると思います。

tmux だと、自分の好きなように window, pane 分割して、 どれかの pane で Vim を立ち上げつつ、別の pane でビルド環境を動かしたり、 あるいはまた別の pane で git commit したりと、それらのレイアウトを自由に変更できていました。

  • tmux 上で Vim を大部分使っていたとしても、すぐに pane 分割して Terminal が使えるようになる
  • 要らなくなったらすぐに pane 閉じられる

tmux + Vim の良いところはこの辺りだと思います。 出来るだけこの辺りの良さを残しつつ、 VS Code のレールに乗っていければと思います。

解決法: キーマッピングの個人設定ファイルである keybindings.json に設定追記する

keybindings.json に以下を追加します。

// Panel と Editor 間の移動
{
	"key": "ctrl+k",
	"command": "workbench.action.terminal.toggleTerminal",
	"when": "editorTextFocus"
},
{
	"key": "ctrl+k",
	"command": "workbench.action.focusActiveEditorGroup",
	"when": "terminalFocus"
}

本当は tmux の prefix と同じものが割り当てられると良かったのですが、 (個人設定で tmux の prefix key を Ctrl + B から Ctrl + J に割り当て直してある) どうも全く同じにするのは難しいため、気軽に上下移動しやすいであろう Ctrl + K を連続回押すことで、 交互に上下移動が出来るような設定にしてみました。

まとめ

長くなったんで、一旦基本的なところはこの辺で締めたいと思います。

このブログ記事も VS Code でだいたい書けたので、やりたいことは概ね出来ている感じですが、 もしこの先さらに設定など溜まっていくようでしたら、別にブログ記事を書きたいと思います。

出来たこと

  • 細かな Vim の操作感は再現出来た!
  • 概ねキーボードでの移動が出来た!
  • 移行できた!

これから頑張る

  • VS Code で使えるようになった機能(主に Side Bar)の掘り下げた使い方
  • Side Bar の中のキーマッピングが分からない問題

参考 URL

もし記事内に誤りなどございましたら、 @girigiribauer までご一報いただけると助かります。