Zshで最後の引数を削除する便利なキーバインドを設定

Zshで最後の引数を削除するキーバインドを実装したので解説します。

挙動

キーバインドを入力していく毎に最後の引数をコマンドラインから削除してくれます。

Terminal window
foo --bar "a b c"
foo --bar
foo

削除後はfoo --barのように最後の空白は残したままです。そのためすぐに引数を入力できます

どんなときに便利なのか

引数が長いコマンドを修正する時に便利です。たとえば、履歴から取ってきたコマンドのURLやファイル名など修正するときに筆者は使っています。

Terminal window
# ↓履歴から取ってきたコマンド
pnpm exec vitest src/usecase/createFoo/CreateFooUseCase.test.ts
# ↓上記を書き換えたコマンド
pnpm exec vitest src/main.ts

実装の解説

先に実装の全体を載せます。次の項目から小分けにして解説します。

function delete_last_argument() {
# シェルのパースに基づいて配列化
# https://zsh.sourceforge.io/Doc/Release/Expansion.html#Parameter-Expansion-Flags:~:text=into%20words%20using%20shell%20parsing%20to%20find%20the%20words
local tokens=("${(z)BUFFER}")
if (( 2 <= ${#tokens} )); then
# 配列の取り出し
# https://zsh.sourceforge.io/Doc/Release/Expansion.html#Parameter-Expansion:~:text=%24%7Bname%3Aoffset%3Alength%7D
tokens=("${tokens:0:$#tokens-1}")
# 配列を半角スペースで結合
# https://zsh.sourceforge.io/Doc/Release/Expansion.html#Parameter-Expansion:~:text=the%20parenthesised%20group.-,j%3Astring%3A,-Join%20the%20words
BUFFER="${(j: :)tokens} "
fi
}
zle -N delete_last_argument
bindkey "^Xw" delete_last_argument

配列化

まずは入力を取得して配列にします。

local tokens=("${(z)BUFFER}")

BUFFERが入力内容を表す変数です。

${(z)name}で変数の文字列をシェルの構文解析を使って配列にします。

たとえば、BUFFERfoo --bar "a b c"なら次のような配列になります。

foo # 1番目の要素
--bar # 2番目の要素
"a b c" # 3番目の要素

公式ドキュメント:14.3.1 Parameter Expansion Flags

引数の数を確認

「コマンド名 + 引数が1つ以上」かどうか確認します。

if (( 2 <= ${#tokens} )); then

公式ドキュメント:14.3 Parameter Expansion

配列の取り出し

配列の最後の要素(=最後の引数)を削除します。

tokens=("${tokens:0:$#tokens-1}")

${name:offset:length}を書くことで、変数nameoffsetからoffset+lengthまでの値を取り出します。

公式ドキュメント:14.3 Parameter Expansion

配列の結合

配列を文字列として結合し、入力とします。

BUFFER="${(j: :)tokens} "

${(j:結合文字:)name}のように書くと、指定した結合文字で要素を結合できます。
今回は半角スペースで結合しています。

公式ドキュメント:14.3.1 Parameter Expansion Flags

キーバインドの設定

最後に、ZLEのウィジェットとして登録し、キーバインドを設定します。

zle -N delete_last_argument
bindkey "^Xw" delete_last_argument

今回は「Ctrl+xを入力後にwを入力」で設定しました。

現在のキーバインド割り当てを確認したい場合は次のコマンドを実行します。

Terminal window
bindkey

関連キーバインド

関連するキーバインド・ウィジェットも紹介します。

設定できるウィジェットの一覧は公式ドキュメントの18.6 Standard Widgetsに掲載されています。

単語ごとの削除

^wでカーソル前の単語を削除します。ZLEのウィジェット名はbackward-kill-wordです。

一文字削除

^Hでカーソル前の一文字を削除します。ZLEのウィジェット名backward-delete-charです。

全削除

ウィジェットbackward-kill-lineでカーソル前の文字列全部を削除します。

好きなテキストエディタで入力を編集

ウィジェットedit-command-lineを使うと、現在の入力内容をテキストエディタで編集できます。コマンドラインの修正が少し複雑になる時に便利です。

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

テキストエディタは環境変数EDITORで設定できます。

公式ドキュメント:26.7.1 Widgets


以上、最後の引数を削除する設定でした。短い記述でZshの変数や配列を操作できて面白いです。