Zshで最後の引数を削除する便利なキーバインドを設定
Zshで最後の引数を削除するキーバインドを実装したので解説します。
挙動
キーバインドを入力していく毎に最後の引数をコマンドラインから削除してくれます。
foo --bar "a b c"foo --barfoo
削除後はfoo --bar
のように最後の空白は残したままです。そのためすぐに引数を入力できます。
どんなときに便利なのか
引数が長いコマンドを修正する時に便利です。たとえば、履歴から取ってきたコマンドのURLやファイル名など修正するときに筆者は使っています。
# ↓履歴から取ってきたコマンド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_argumentbindkey "^Xw" delete_last_argument
配列化
まずは入力を取得して配列にします。
local tokens=("${(z)BUFFER}")
BUFFER
が入力内容を表す変数です。
${(z)name}
で変数の文字列をシェルの構文解析を使って配列にします。
たとえば、BUFFER
がfoo --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}
を書くことで、変数name
のoffset
からoffset+length
までの値を取り出します。
公式ドキュメント:14.3 Parameter Expansion
配列の結合
配列を文字列として結合し、入力とします。
BUFFER="${(j: :)tokens} "
${(j:結合文字:)name}
のように書くと、指定した結合文字
で要素を結合できます。
今回は半角スペースで結合しています。
公式ドキュメント:14.3.1 Parameter Expansion Flags
キーバインドの設定
最後に、ZLEのウィジェットとして登録し、キーバインドを設定します。
zle -N delete_last_argumentbindkey "^Xw" delete_last_argument
今回は「Ctrl+xを入力後にwを入力」で設定しました。
現在のキーバインド割り当てを確認したい場合は次のコマンドを実行します。
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-linezle -N edit-command-linebindkey "^O" edit-command-line
テキストエディタは環境変数EDITOR
で設定できます。
公式ドキュメント:26.7.1 Widgets
以上、最後の引数を削除する設定でした。短い記述でZshの変数や配列を操作できて面白いです。