前書き
Vim(Neovim)で開発をしている方、RSpecの実行どうしてますか?
参考までに私の試行錯誤遍歴を🙇♂️
-
iterm2の画面分割で常にRSpec用の画面を確保しておいてRSpec実行時にウインドウ移動
常に画面領域を圧迫して邪魔(他にログ表示用やrails console用の領域を使いたいならなおさら)
VSCodeみたいに使いたいときにだけ表示したい! -
C-z
でVimから抜けてターミナルでRSpecを実行する
一応使いたい時だけ表示することになるので画面は圧迫しないが都度Vimから抜けるのはストレス
再度Vimに戻った後にRSpecの実行結果をまた見たい時はまたC-z
しないと見れないのが面倒 -
Neovimのターミナルモードを使う
Neovimだと:terminal
コマンドでターミナルモードに入れるのでVSCodeに近い感じには出来るが、どうも操作性が悪い
設定を結構ゴニョゴニョしないと使い物にはならないなという印象(設定弄る前に次に紹介するneotermを知ってしまった) -
neotermを使う
色々試して行き着いたのがkassio/neotermです
これは上記の他の案の欠点をカバー出来る上、中身は:terminal
コマンドのラッパープラグインなので導入・設定も簡単!
本記事は、このneotermを活用して簡単にNeovim内でRSpec実行を完結させられるようにします
neotermのインストールと設定
早速インストールしましょう
といってもdeinでプラグインを管理している方はdein.toml
に下記をコピペして:call dein#install()
したら終わりです
※ hook_add以下は.vimrc
やinit.vim
に書いてもOKです、お好みで使い分けてください
[[plugins]]
repo = 'kassio/neoterm'
hook_add = '''
let g:neoterm_default_mod='belowright'
let g:neoterm_size=25
let g:neoterm_autoscroll=1
let g:neoterm_rspec_cmd='bundle exec rspec'
function! RSpecFile()
let l:filename = expand('%')
call neoterm#do({ 'cmd': join([g:neoterm_rspec_cmd, l:filename]) })
endfunction
function! RSpecLine()
let l:filename = expand('%')
let l:opt = join([l:filename, line('.')], ':')
call neoterm#do({ 'cmd': join([g:neoterm_rspec_cmd, l:opt]) })
endfunction
command! RSpecAll call neoterm#do({ 'cmd': g:neoterm_rspec_cmd })
command! RSpecFile call RSpecFile()
command! RSpecLine call RSpecLine()
nnoremap <silent> <C-t><C-t> :Ttoggle<CR>zz
tnoremap <silent> <C-t><C-t> <C-\><C-n>:Ttoggle<CR>zz
tnoremap <silent> <C-w> <C-\><C-n>
nnoremap <silent> <C-t>a :Topen<CR><C-w><C-j>i<C-l><C-\><C-n><C-w><C-k>:RSpecAll<CR>
nnoremap <silent> <C-t>f :Topen<CR><C-w><C-j>i<C-l><C-\><C-n><C-w><C-k>:RSpecFile<CR>
nnoremap <silent> <C-t>l :Topen<CR><C-w><C-j>i<C-l><C-\><C-n><C-w><C-k>:RSpecLine<CR>
'''
はい終わり!とっても簡単✌️
設定したキーマッピング<C-t>l
で:RSpecLine
を実行して現在行のRSpecを実行してます(Spec超適当ですみません🙏)
オプション等の細かい説明は次の項目で解説します
解説
オプション
let g:neoterm_default_mod='belowright'
ターミナルウインドウの表示位置を下部表示(水平分割)にする設定
これを指定しないとターミナルウインドウは新しいバッファで開いてしまうので必須です
※ 右に表示(垂直分割)の場合は'vertical belowright'
let g:neoterm_size=25
ターミナルウインドウの表示サイズを設定
私は使う時だけの表示できればいい用途なのでそこそこ大きい数字に設定してます
常時表示したいとかでもっと狭いスペースで良かったら10
にするとか各自調節してください
let g:neoterm_autoscroll=1
ターミナルの自動スクロール設定
テストログが流れてくRSpec実行には必須ですね
let g:neoterm_rspec_cmd='bundle exec rspec'
オプションではないですが下記のRSpecスクリプト関連で必要な設定
デフォルトのrspec
コマンドを設定します
各自の環境に合わせて設定してください
[補足]
私は無くて平気でしたが、環境によっては
let g:neoterm_shell='$SHELL -l'
で起動するshellの指定が必要かも
動かなかったら試してみてください
スクリプト&コマンド
function! RSpecFile()
〜
command! RSpecLine call RSpecLine()
までがRSpec関連のスクリプトやらコマンドです
スクリプトは uji/neoterm-rspec.vim を参考に必要な機能だけ頂戴して少しだけカスタマイズしました
もっと楽するためにコマンドは下記でキーマッピングに割り当てます
キーマッピング
nnoremap <silent> <C-t><C-t> :Ttoggle<CR>zz
tnoremap <silent> <C-t><C-t> <C-\><C-n>:Ttoggle<CR>zz
ターミナルの開閉のキーマッピング
最後にzz
としてるのはターミナル開閉時に元ウインドウのカーソル位置が真ん中に来なくて気持ち悪かったのでカーソル位置の中央表示をするようにしてます
tnoremap <silent> <C-w> <C-\><C-n>
ターミナルモードから抜ける際のキーマッピングです
いちいち<C-\><C-n>
なんて打たなくて良くなります
※ ターミナルモードから抜ける?って概念については後ほど ターミナルモードの操作について で説明します
ネット上ではこのキーマッピングを<ESC>
にしてる人が多いように感じましたが、私はターミナルモードから抜ける時はウインドウ移動したいことが多いので<C-w>
にしてます
つまりターミナルモード中にウインドウ移動したいときは<C-w><C-w><C-w>
でいけてわかりやすい(好み分かれるとは思いますが)
nnoremap <silent> <C-t>a :Topen<CR><C-w><C-j>i<C-l><C-\><C-n><C-w><C-k>:RSpecAll<CR>
nnoremap <silent> <C-t>f :Topen<CR><C-w><C-j>i<C-l><C-\><C-n><C-w><C-k>:RSpecFile<CR>
nnoremap <silent> <C-t>l :Topen<CR><C-w><C-j>i<C-l><C-\><C-n><C-w><C-k>:RSpecLine<CR>
RSpecスクリプト実行用のキーマップです
コマンド実行前に色々ごちゃごちゃ書いてるので一応解説します
:Topen<CR>
ターミナルウインドウを表示(表示してたらそのまま)
<C-w><C-j>i
ターミナルウインドウに移動してターミナルモードへ
<C-l><C-\><C-n>
ターミナルをクリアしてターミナルモードから抜ける(:Tclear
意図しない動作になったためこのようにしてます)
<C-w><C-k>
元のSpecファイルのウインドウへ戻る
:RSpecAll<CR>
RSpecスクリプト実行
なぜこんなことしてるのかと言うと、
RSpec実行時に
1)ターミナルウインドウを(表示してなかったら)自動で開いて
2)ターミナルをクリアして(テスト実行ログがわかりやすいように)
3)アクティブウインドウはSpecファイルのウインドウのままにして実行
という一連の動作をしたいからです
わざわざウインドウ移動してコマンド打たなくても
let g:neoterm_autoinsert=1
かg:neoterm_autojump=1
オプションを設定していれば
ターミナルを開いたら自動でターミナルウインドウに移動してくれます
ただ、これを設定するとターミナル開閉のキーマップ時にもウインドウ移動してしまうのです
私は実行したいターミナルコマンドがあったら:T hogehoge
とそのままノーマルモードで実行しています(番外編参照)
ターミナルウインドウ開閉をする時はターミナルウインドウをチラっと確認したいだけの場合が多いのでこの方が都合良いのです
他のオプションが知りたかったら:h neoterm
コマンドでヘルプが引けます
細かい設定オプションがいっぱいあるので見てみると楽しいですよ
ターミナルモードの操作について
Newvimのターミナルモードの操作はちょっとクセがあります
通常のVim操作と同じくモードの概念があるので最初は少し戸惑うかもしれません
-
ノーマルモード
最初の状態
通常のNORMALモードと同じくVISUALモードへの移行や文字列のヤンクも出来ます
当然ですが編集(INSERTモードへの移行)は出来ません -
ターミナルモード
INSERTモードに移行できない代わりにi
キーを押すとターミナルモードに移行します
ターミナルモードになって初めてターミナル操作が出来るようになります(分かりづらいッ)
さらにややこしいのはターミナルモードからノーマルモードに戻る時のコマンド
<C-\><C-n>
です(使いづらいのでさきほどキーマッピングしましたね)
通常のターミナルと違ってモードの概念があるので最初は面食らうと思います
まあでも慣れるので頑張って操作して慣れましょう
Vimから抜けなくて良くなるリターンの方が遥かに大きいです!!
特に<C-t>f
と<C-t>l
にマッピングした:RSpecFile
と:RSpecLine
の威力は絶大です
おかげで今開いてるSpecファイル名を気にしたり何行目か目視で確認する手間が省けました
控えめに言って最高です
番外編
ターミナルウインドウに移動しなくても:T hogehoge
でそのまま実行できます
もしよくコマンドだったらキーマップ割り当てるのもアリです
例1)
nnoremap <silent> <C-t>t :Topen<CR>:T tig<CR><C-w>j<C-w>_i
tig
はターミナル上で使えるgitのGUIです( jonas/tig )
私はコミットやプッシュ、差分確認などは大体これを使ってます(これについても今度記事書きたい)
tig
は全画面で操作出来た方が見やすいので画面最大化(<C-w>_
)するように設定してます
またtig
を起動する時は操作したい時なのでi
でそのままターミナルモードに移行するようにしてます
例2)
nnoremap <silent> <C-t>c :T rails c<CR>:Topen<CR><C-w>ji
rails console
を開きます
これも起動する時はすぐに操作したいのでそのままターミナルモードに移行するようにしてます
RSpec実行と違って自動的に終了しないので上記2つを開いたままRSpecキーマップを実行するとちゃんと動作しないので注意!
使い終わったらtig
の場合はq
、rails console
の場合はexit
で終了するのを忘れずに
こんな感じでまだまだ結構色々な用途に使えそうです🤔
様子見つつオススメ見つけたらまた共有します
最後に
なんだかんだでVimに入門して半年以上経ちました!
だんだんと操作がVim内で完結してきたのでVim引きこもりがどんどん加速していってますねw
世間のVSCodeの波に負けずにこれからもVimに引きこもって開発していこうと思います
それではみなさん良きVimライフを😇😇😇