VSCode Vimでは/から検索する際、デフォルトでは大文字小文字が考慮されます。そこで、大文字小文字を区別しないようにしたい場合の設定方法を紹介します。 vim.ignorecaseを有効にする …
VSCodeのVim拡張と言えば、青色のロゴのvscodevimが定番でした。そんな中でVim拡張で下剋上を成し遂げるほどのポテンシャルで成長しているNeo Vim拡張を紹介したいと思います。
VSCode Vimには問題が多かった
いち早くVSCodeでVimエミュレータとして登場して活躍していたVSCode Vim拡張機能ですが、もっさりしていたり、応答が返ってこない、アップデートすると不具合がぽろぽろ出るなど、安定しているとは言えませんでした。
また、VSCode上でVimを再現しているためVimの設定ファイル .vimrc
の読み込みに試験対応しているものの完全ではなく、もちろんvim用に作成されたプラグインも使えませんでした。
Neo Vim (VSCode Neovim)
Neovimはプロジェクトの思想から、外部プロセスからNeovimへアクセスするためのAPIが豊富に揃っています。
VSCodeのNeo Vim拡張は、VSCode上でVimをエミュレートするのではなくNeovimを直接参照することで高速・安定・豊富なプラグインをそのまま
使用してVSCode上でVimを実現する拡張機能です。
1年以上VSCodeVimを使用している筆者が1日で乗り換えを決める程、圧倒的なポテンシャルを秘めています。
ただし、InsertModeやWindow操作などの一部はVSCode上で実装されるなど、100%互換があるとは言えません。
実行にも別途Neovimをセットアップする必要があり、プラグイン等も通常のVimと同じようにPackageManagerでセットアップする必要があるので、環境構築に少々時間が掛かります。
VSCode Neo Vim インストール
拡張機能からインストール
拡張機能 (Ctrl+Shift+X) からNeo Vim
をインストールします。
Neovimをインストール
Neovimの0.5.0 nightly以上が必要なので、ダウンロードして配置します。
安定版ではなくプレリリースのnightlyが必要なので、よく確認しましょう。
neovim Release
https://github.com/neovim/neovim/releases
※パッケージ管理ツールのscoopでも公開されています。
scoop bucket add versions
scoop install neovim-nightly
VSCode Neovimのパスをセット
基本設定 (Ctrl+,)からNeovimのnvim.exe
のパスをセットします。
"vscode-neovim.neovimExecutablePaths.win32": "C:\\Users\\****\\scoop\\shims\\nvim.exe"
※WindowsOSの場合の設定例です。OS種ごとに設定値が分かれています。
※パスはNeovimのインストールディレクトリに書き換えてください
ここまで終えれば、動作に必要な最低限の設定は完了です。
VSCodeを再起動するとお馴染みのNormal, Insert, VisualといったVimの入力モードで編集が行える状態となります。
設定ファイル init.vim (.vimrc)
neovimの設定ファイルinit.vim
を作成します。
vimで言うと.vimrcのことです。
ファイルの作成場所は以下のユーザーディレクトリにinit.vim
を作成します。
C:\Users\****\AppData\Local\nvim\init.vim
パスのデフォルトはAppData以下ですが、環境変数$XDG_CONFIG_HOME
でセットしたパスの以下の構成で参照されるため、環境変数を書き換えることでディレクトリは移動できます。
$XDG_CONFIG_HOME/nvim/init.vim
インサートモードを抜けたら日本語IMEをオフにする
インサートモートでIMEを日本語入力に変更した状態でノーマルモードへ戻ると、「っっっっ」などと日本語入力になるため手作業で毎回IMEを英数に切り替えなければなりません。
gvimでは<Ctrl-^>で入力切替が出来たりしましたが、NeoVimでは対応されていないので、インサートモードを抜けるタイミングで別アプリをキックしてIMEを制御します。
zenhanをインストール
Windows向けになりますが、c++で実装されたアプリケーションで、
引数に0を与えるとIMEが無効
引数に1を与えるとIMEが有効になります。
元々VSCode VimのimSelectの代替として用意されたものですが、IME制御という点で問題ないのでそのまま使用させて頂きます。
ダウンロードして任意の場所に保存し、環境変数からexeがある場所のパスを追加します。
zenhan
https://github.com/iuchim/zenhan
scoopからもダウンロード可能です。
scoop install zenhan
ターミナルでzenhan 0
と入力するとIMEがオフ、zenhan 1
と入力するとIMEがオンになることを確認します。
init.vimにInsertLeave時に実行処理を定義
init.vimにインサートモードから抜けるタイミングで任意のコマンドを自動的に実行するようにセットします。
InsertLeaveイベント発生時にzenhanを呼ぶことで、インサートモードからノーマルモードへ移行したタイミングでIMEが自動的にオフになります。
ついでにCmdLineLeaveイベント発生時にも呼んでおくと、Search後にIMEがオフになるので便利です。
" ime off
if executable('zenhan')
autocmd InsertLeave * :call system('zenhan 0')
autocmd CmdlineLeave * :call system('zenhan 0')
endif
プラグインの追加
プラグイン管理ツールのvim-plugを使用する方法です。
Windowsの場合はPowerShellから以下を実行します。
vim-plugがNeoVimのautoloadディレクトリにダウンロードされます。
iwr -useb https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim |`
ni "$env:LOCALAPPDATA/nvim-data/site/autoload/plug.vim" -Force
vim-plugの使い方
有名な文字列を囲うsurround
を使用する場合の手順です。
init.vimにプラグインの開始(begin)から終了(end)を宣言し、間にインストールするプラグインを指定します。
指定方法はgithubのURLや短縮してユーザー/リポジトリだけでも可能です。
call plug#begin('~/.vim/plugged')
Plug 'tpope/vim-surround'
call plug#end()
PlugInstall
init.vimに使用するプラグインを記載しただけでは使用できません。
初回にPlugInstall
からプラグインをインストールする必要があります。
PlugInstallはEXコマンドに入力して実行しますが、VSCode NeoVimでは正しく実行されないようなので、NeoVimを直接起動して実行します。
プラグインのインストールが開始されます。
完了後にVSCodeを再起動してプラグインが有効になっていることを確認します。
EasyMotion等も正常に動かないため、VSCode NeoVim作者自身がEasyMotionをForkして動作するように変更したものをリリースしています。
VSCodeのコマンドをマップするには
VSCode自体のコマンドはcall VSCodeNotify()
からコールすることでマッピング可能です。
nnoremap :call VSCodeNotify('workbench.action.closeOtherEditors')
nnoremap :call VSCodeNotify('workbench.action.toggleSidebarVisibility')
コマンドIDはキーボートショートカットの設定から右クリック「コマンドIDのコピー」から取得できます。
ファイル保存であれば2のように指定します。
1. nmap <leader>w :w<cr>
2. nmap <leader>w <cmd>call VSCodeNotify(‘workbench.action.files.save’)<cr>
一見、どちらも同じことをしているように見えますが、1の方法で実行していると稀に(1日1回ぐらい)VSCode Neovimがバグります。
何かキーを押すと勝手にEXコマンド入力欄が出たり、カーソルが動かないといった状態になり、VSCodeを再起動しないと直りません。
2の方法で実行すると理由は分かりませんが私の環境ではバグって変な動きになる事がほとんどなくなりました。
NeovimはVSCodeをキックするだけなので余計なトラブルが起きづらいのかもしれません。
init.vim設定例
私のinit.vimを記載しておきます。
Neovimで使用していたプラグインからLSPや補完、デバッグなどのVSCodeで賄えるものを除外すると半分以下になりました。
call plug#begin(stdpath('data') . '/plugged') " ヤンクした箇所をハイライト Plug 'machakann/vim-highlightedyank' " vim-docを日本語化 Plug 'vim-jp/vimdoc-ja' " コード内ジャンプ Plug 'easymotion/vim-easymotion' " 文字列を括弧等で囲む Plug 'machakann/vim-sandwich' " カーソル位置の単語で検索 Plug 'thinca/vim-visualstar' " ヤンクしている内容で置換 Plug 'vim-scripts/ReplaceWithRegister' " *モーション拡張 Plug 'haya14busa/vim-asterisk' " テキストオブジェクト拡張 Plug 'wellle/targets.vim' " カーソルをエッジへ移動 Plug 'haya14busa/vim-edgemotion' " f拡張 Plug 'rhysd/clever-f.vim' call plug#end() " ====== key ====== let mapleader = "\<Space>" " leave insert inoremap jk <esc> " focus explorer nmap <leader>e <cmd>call VSCodeNotify('workbench.view.explorer')<cr> nmap <leader>E <cmd>call VSCodeNotify('workbench.action.toggleSidebarVisibility')<cr> " symbol nmap <Leader>o <Cmd>call VSCodeNotify('workbench.action.gotoSymbol')<CR> nmap <Leader>t <Cmd>call VSCodeNotify('workbench.action.showAllSymbols')<CR> " tab move nmap <Leader>> <Cmd>call VSCodeNotify('workbench.action.moveEditorRightInGroup')<CR> nmap <Leader><lt> <Cmd>call VSCodeNotify('workbench.action.moveEditorLeftInGroup')<CR> " diagnotics jump nmap ]d <cmd>call VSCodeNotify('editor.action.marker.nextInFiles')<cr> nmap [d <cmd>call VSCodeNotify('editor.action.marker.prevInFiles')<cr> " search jump nmap ]s <cmd>call VSCodeNotify('editor.action.nextMatchFindAction')<cr> nmap [s <cmd>call VSCodeNotify('editor.action.previousMatchFindAction')<cr> " change jump nmap ]c <cmd>call VSCodeNotify('editor.action.dirtydiff.next')<cr> nmap [c <cmd>call VSCodeNotify('editor.action.dirtydiff.previous')<cr> " reference jump nmap ]r <cmd>call VSCodeNotify('search.action.focusNextSearchResult')<cr> nmap [r <cmd>call VSCodeNotify('search.action.focusPreviousSearchResult')<cr> " save file nmap <leader>w <cmd>call VSCodeNotify('workbench.action.files.save')<cr> " close file nmap <leader>d <cmd>call VSCodeNotify('workbench.action.closeActiveEditor')<cr> " tab move nmap <C-h> <cmd>call VSCodeNotify('workbench.action.previousEditor')<cr> nmap <C-l> <cmd>call VSCodeNotify('workbench.action.nextEditor')<cr> " tab only nmap <C-w><C-o> <cmd>call VSCodeNotify('workbench.action.closeOtherEditors')<cr> " cursor move nnoremap <S-j> 5j nnoremap <S-k> 5k vnoremap <S-j> 5j vnoremap <S-k> 5k nnoremap 0 ^ nnoremap ^ 0 vnoremap 0 ^ vnoremap ^ 0 " highlight off nnoremap gq <cmd>nohlsearch<cr> " yank nnoremap Y y$ " paste nnoremap p ]p xnoremap p ]p " comment xmap gc <Plug>VSCodeCommentary nmap gc <Plug>VSCodeCommentary omap gc <Plug>VSCodeCommentary nmap gcc <Plug>VSCodeCommentaryLine " ====== options ======" set ignorecase set smartcase set clipboard+=unnamedplus " ====== autocmd ======" " ------- FIX: Keep autoindent enabled for all filetypes all the time ----- " autocmd BufEnter * silent! set autoindent smartindent " input method disable if executable('zenhan') autocmd InsertLeave * :call system('zenhan 0') autocmd CmdlineLeave * :call system('zenhan 0') endif " ====== plugins setting ======" " vim asterisk" let g:asterisk#keeppos = 1 map g* <Plug>(asterisk-z*) map g# <Plug>(asterisk-z#) map * <Plug>(asterisk-gz*) " easymotion map <Leader>f <Plug>(easymotion-bd-f) map <Leader>k <Plug>(easymotion-k) map <Leader>j <Plug>(easymotion-j) "edgemotion nmap gj <Plug>(edgemotion-j) nmap gk <Plug>(edgemotion-k) vmap gj <Plug>(edgemotion-j) vmap gk <Plug>(edgemotion-k) "highlightedyank let g:highlightedyank_highlight_duration = 150
コメントを書く