Vimからシェルコマンドを実行する方法(:! と :terminal)
ちょっとgitのステータスを確認したいだけなのに、Vimを一度サスペンドしてシェルに戻り、またvimで開き直す、という無駄な往復をしていた時期があります。Vimの中から直接コマンドを実行する方法を覚えれば、その往復はいらなくなります。
1行だけ実行する::!
:!{コマンド}
コマンドラインモードで!から始めると、続く文字列をOSコマンドとして実行できます。LinuxやMacでは実行結果がVimの中に表示され、Windowsではコマンドプロンプトが別途起動します。単発のコマンドをさっと実行して結果だけ確認したいときに向いています。
ターミナルとして使う::terminal
:terminal
:terminal {コマンド}
Vim 8.1で追加された機能で、Vimのウィンドウの中に端末エミュレータを開けます。:!が単発のコマンド実行に向いているのに対し、:terminalはシェルセッションそのものをウィンドウとして持てるので、複数のコマンドを連続で打ちたいときや、ビルドプロセスを流しながら別のウィンドウでコードを編集したいときに向いています。ウィンドウの分割・移動は通常のVimのウィンドウ操作とまったく同じ感覚で扱えます。
言語処理系を直接呼び出す
特定の言語のインタプリタが有効になっていれば、その言語のコードを直接実行することもできます。
:python3 {コード}
:ruby {コード}
:perl {コード}
Vim scriptの中でちょっとした計算をPython側に任せたいときなど、ごく限定的な場面で使う機能です。日常的な用途というよりは、プラグイン開発や高度なカスタマイズをする人向けの選択肢と考えられます。
選択範囲をコマンドに渡す
ビジュアルモードで範囲を選択した状態で:!を実行すると、選択範囲をコマンドへの入力として渡し、その出力で選択範囲を置き換えることができます。
banana
apple
cherry
:'<,'>!sortapple banana cherry
選択した行をsortコマンドに通して並べ替えた例です。Vimの中で完結させたい単純な並べ替えなら:sortコマンドでも足りますが、シェルの豊富なテキスト処理コマンド(uniqやawkなど)をそのまま使いたいときは、この方法が手っ取り早くなります。
使い分けの目安
| 状況 | おすすめ |
|---|---|
| 1回だけコマンドを実行して結果を見たい | :! |
| 複数コマンドを対話的に実行したい | :terminal |
| コマンドの出力をバッファに取り込みたい | :r!(別記事) |
:terminalを知る前は、ビルドの実行結果を見るためだけにウィンドウを切り替えていました。ウィンドウ分割の中にターミナルを1枚常駐させる運用に変えてからは、エディタとターミナルを行き来する手間そのものが消えて、地味ですが積み重なると大きい時間短縮になりました。
まとめ
単発の確認なら:!、対話的な作業なら:terminalと使い分ければ、Vimを閉じずに済む場面が大きく増えます。コマンド出力をバッファに取り込みたい場合は別記事を参照してください。端末ウインドウ側の話(2つのモードの切り替え、ジョブが動いているときの終了、'termwinkey'の衝突)は:terminalの使い方にまとめてあります。実行結果をバッファに取り込んで加工したいときは、:read !のほうが扱いやすくなります。