LoginSignup
0
0

More than 1 year has passed since last update.

Neovim内でのRSpec実行環境をneotermで簡単に導入する

Last updated at Posted at 2022-07-06

前書き

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コマンドのラッパープラグインなので導入・設定も簡単!
    fe459572-34b1-11e5-93c9-c3b6f3b44719.gif

本記事は、このneotermを活用して簡単にNeovim内でRSpec実行を完結させられるようにします

neotermのインストールと設定

早速インストールしましょう
といってもdeinでプラグインを管理している方はdein.tomlに下記をコピペして:call dein#install()したら終わりです
※ hook_add以下は.vimrcinit.vimに書いてもOKです、お好みで使い分けてください

dein.toml
[[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>
'''

はい終わり!とっても簡単✌️
20220706.gif
設定したキーマッピング<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=1g: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の場合はqrails consoleの場合はexitで終了するのを忘れずに

こんな感じでまだまだ結構色々な用途に使えそうです🤔
様子見つつオススメ見つけたらまた共有します

最後に

なんだかんだでVimに入門して半年以上経ちました!

だんだんと操作がVim内で完結してきたのでVim引きこもりがどんどん加速していってますねw
世間のVSCodeの波に負けずにこれからもVimに引きこもって開発していこうと思います

それではみなさん良きVimライフを😇😇😇

他のVim関連記事も良かったら見てみてください🙇‍♂️

Vimの複雑なコマンドを理解する
[VimとEmacsの共存] VimでEmacsキーバインドを使えるようにしてみた

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0