zshで入力中のコマンドをすぐにNeovimで編集する方法

長いコマンドを書く時や以前実行したコマンドを修正する時に便利な方法を紹介します。
2022.12.02

どうも。CX事業本部Delivery部のえーたん(@eetann092)です。

筆者はコマンド入力中に「長いコマンドをちょっと修正するためのカーソル移動が面倒だな」「Aは全部Bに置換したいな」と思うことがよくあります。 そんな時にZLE(Zsh Line Editor)のedit-command-lineが便利なので紹介します。

以下は、コマンド入力中にCtrl + oを押してコマンドの文字列をNeovimで編集した例です。

コマンドの文字列を編集後、保存すると反映されます。実行まではされません。あくまでも文字列の編集です。

設定方法

以下が.zshrcに書いた設定です。

autoload -Uz edit-command-line
zle -N edit-command-line
bindkey "^O" edit-command-line

1行ずつ説明します。

まず、autoloadを使って、関数edit-command-lineを読み込んでいます。

autoload -Uz edit-command-line

フラグUで、自分の.zshrcで設定したエイリアスを展開しないようにします。

フラグzで、zshスタイルで読み込むように指定しています。フラグzをつけず、オプションKSH_AUTOLOADやフラグkのkshスタイルが指定されていると、読み込みたい関数にkshのautoloadの動作が追加されてしまうようです。

autoloadには他にもたくさんフラグがあるので、詳しくはman 1 zshbuiltinsautoloadで確認してください。

次に、zle -Nで関数edit-command-lineをウィジェットとして割り当てています。

zle -N edit-command-line

最後に、bindkeyで登録したウィジェットedit-command-lineCtrl + oに割り当てています。

bindkey "^O" edit-command-line

どのキーバインドが余っているか知りたい場合は、bindkeyを引数無しで実行し、現在の割り当てを確認すると良いでしょう。

ちなみに筆者の環境では最初の2行を書かずにbindkeyの設定のみで動作しました。調べたところ、筆者が使っているプラグインOh My Zshによってすでに設定されていたためでした。Oh My Zshの実装を見ると、Ctrl + xCtrl + eedit-command-lineを割り当てています。

Neovimでnowrapにしています

筆者は普段vim.opt.wrap = false(折り返しなし)で生活しています。しかし、edit-command-lineで長いコマンドを編集する時は、全体をすぐに見渡せるように折り返しありにしています。

vim.api.nvim_create_autocmd({ "BufRead" }, {
	group = group_name,
	pattern = { "/tmp/*" },
	callback = function()
		vim.opt_local.wrap = true
	end,
})

おまけ。テトリスのウィジェットや関数がある

man 1 zshallでマニュアルを漁っていたところ、テトリスを2つ発見しました。

以下のコマンドを実行すると、Ctrl + oでテトリスができます。

autoload -U tetris
zle -N tetris
bindkey "^O" tetris

また、ウィジェットだけではなく、関数としても使えるようです。以下のコマンドを実行してもテトリスができます。

autoload -U tetriscurses
tetriscurses

ウィジェット版は操作方法が書かれていますが、関数版にはありません。 逆に、関数版には次の形が表示されますが、ウィジェット版にはありません。