Vim から VS Code へ覚悟を持って移行する
この記事は書かれてから1年以上が経過しており、最新の情報とは異なる可能性があります
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 .
という立ち上げ方が一般的
- CLI からは
- プロジェクトごとの設定は、
.vscode
ディレクトリが生成されて、その中に設定ファイルが置かれる
Explorer
Explorer は今のディレクトリ配下のファイルをツリー形式で表示してくれます。
Shift + Command + E
で開くことができます。
- 別で Quick Open の仕組みが用意されている、
Command + P
でファイル名入力
Search
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
で開くことができます。
- PROBLEMS や TERMINAL を始めとした Panel は、同じショートカットを2回入力すると、再び閉じた状態となる
- https://code.visualstudio.com/docs/editor/editingevolved#_errors-warnings
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)
その他補完など
- Emmet: HTML を展開できるやつ
Tab
- IntelliSense: 賢く補完してくれる、 Vim でいう Omni 補完的なやつ
Control + Space
- Rename Refactoring: まとめて名前を置き換えてくれるやつ
移行リスト
ようやく目次。
- 全体的に Vim にする
- コロン (
:
) とセミコロン (;
) 入れ替える - yank (copy), paste でシームレスにコピペ
- relativenumber
- ノーマルモードで
enter
を押すと改行される - 行末、行頭の間をスムーズに移動できる
- 行末の余分な space なんとかする
- tab / space の適切な表示
- 単語単位の移動に対する適切な区切り
- mouse / trackpad を触らない移動
ここから先は、各項目でそれぞれ設定ができるように見ていきます。
全体的に Vim にする
一通り知ったところで、以下の拡張機能をインストールしていきます。 これがないと息ができない ので入れます。
- Vim emulator for Visual Studio Code
インストールすると以下がすでに使えるらしいです。 すごい。
- vim-airline
- 入力モードでステータスバーの色を変えられるやつ
- https://github.com/vim-airline/vim-airline
- vim-easymotion
- 画面内の特定箇所に瞬時にジャンプするやつ
- キーの移動先にインデックスをつけてくれるので、それが表示されたらそのキーを押す仕組み
- https://github.com/easymotion/vim-easymotion
- vim-surround
- 囲む部分をさっと入力したり囲んでる部分だけを削除したり
- 超使ってるのでありがたい
- https://github.com/tpope/vim-surround
- vim-commentary
- コメントがさっと指定できるやつ
- https://github.com/tpope/vim-commentary
- vim-indent-object
- vim-surround で囲みづらい Python や Markdown のリストインデントなどで役立つ
- 1段下のインデント上で
vai
を押すと、1〜2段目のリストが選択できる - https://github.com/michaeljsmith/vim-indent-object
- vim-sneak
- easymotion に近いが、 prefix の後に続けて2文字を指定して
;
や,
で次々に探していくやつ - https://github.com/justinmk/vim-sneak
- easymotion に近いが、 prefix の後に続けて2文字を指定して
コロン (:
) とセミコロン (;
) 入れ替える
まずこれは、 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 間移動
- VS Code 上では Tabs 、 Vim 上では tabpage とそれぞれ呼ばれている
- https://code.visualstudio.com/docs/getstarted/userinterface#_tabs
- https://code.visualstudio.com/docs/getstarted/userinterface#_editor-groups
- Side Bar と Editor 間の移動
- Explorer は Quick Open (
Command + P
) で代用できるのでいらないかもしれない・・・ - Git 周りは commit 以外に何ができるのかが不明、 Terminal でやっちゃえばいいのかも・・・
- そう考えると Search, Debug 以外ではほとんど使わない?
- Explorer は Quick Open (
- 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 と Editor 間の移動
正直なところ、 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
この記事は書かれてから1年以上が経過しており、最新の情報とは異なる可能性があります