zsh の `Ctrl + W` と `Ctrl + Alt + H` を bash と同じように動作させる

zsh の `Ctrl + W` と `Ctrl + Alt + H` を bash と同じように動作させる

bash での動作は次のようになります。

  • Ctrl+Wカーソルの後ろの単語を次のスペースまで削除します
  • Ctrl+ Alt+ は、、、などのH次の区切り文字までのカーソルの後ろの単語を削除します。.,-/

+と+ +はzshどちらも、 の後者のように動作します。CtrlWCtrlAltHbash

と同じ動作を希望しますbash

答え1

これは、 の内容に関係なく、必要なことを実行し$WORDCHARS、削除された単語を で使用できるようにしますyank

# Create a new widget.
zle -N backward-kill-space-word
backward-kill-space-word() {
  # Inform the line editor that this widget will kill text.
  zle -f kill

  # Set $WORDCHARS for this command only. 
  WORDCHARS='*?_-.[]~=/&;!#$%^(){}<>' zle .backward-kill-word
}

# See comments above.
zle -N backward-kill-bash-word
backward-kill-bash-word() {
  zle -f kill
  WORDCHARS='' zle .backward-kill-word
}

# Bind the widgets to keys.
bindkey   '^W' backward-kill-space-word
bindkey '^[^H' backward-kill-bash-word

あるいは、私はプラグインと呼ばれるzsh-editには、これらのキーバインドのより洗練されたバージョンが付属しています。

答え2

変数を使用して、単語の一部とみなされる特殊文字を設定できますWORDCHARS。これは、次の方法で単語が削除される方法に影響しますCtrl + W

WORDCHARS='~!#$%^&*(){}[]<>?.+;-_/\|=@`'

しかし、 にも影響がありますCtrl + Alt + H。この動作を にの​​み適用したいのですCtrl + Wが、できるトリックがあります。説明しましょう:

キーの組み合わせを別の機能に再バインドできます (を参照man zshzle)。実際に同じ動作をする機能が 2 つあります。

  • 後方削除単語
  • 後方削除単語

これらの関数を を使用して再定義することもできますzle -N <func>。どのように動作するかは完全にはわかりませんが、コードを読めば概要はわかります。とにかく、これでうまくいきます。

デフォルトでは、Ctrl + Wとは両方ともCtrl + Alt + Hにマップされますbackward-kill-word。したがって、 を再定義してbackward-delete-wordにバインドすることができますCtrl + W

# Make `Ctrl + W` behave like it does in Bash, deleting words separated by
# spaces. We do this by redefining the `backward-delete-word` function and bind
# that to `Ctrl + W`.
SPACE_WORDCHARS='~!#$%^&*(){}[]<>?.+;-_/\|=@`'
backward-delete-word() WORDCHARS=$SPACE_WORDCHARS zle .$WIDGET
zle -N backward-delete-word
bindkey "^W" backward-delete-word

はい、今度はCtrl + Wより大きい単語を削除しますCtrl + Alt + H

編集:

非常に残念なことに、この方法にはいくつかの機能が欠けていることがわかりました。単語を削除しても、貼り付けバッファ (Ctrl + Y) にコピーされません。まだ解決策は見つかっていません。

答え3

最終的に、次のバインディングで目的の動作が見つかりました。

# Configures bindings for jumping/deleting full and sub-words, similar to
# the keybindings in bash.

# Jumping:
# Alt + B                Backward sub-word
# Ctrl + Alt + B         Backward full-word
# Alt + F                Forward sub-word
# Ctrl + Alt + F         Forward full-word

# Deleting:
# Ctrl + W               Backward delete full-word
# Ctrl + Alt + H         Backward delete sub-word
# Alt + D                Forward delete sub-word
# Ctrl + Alt + D         Forward delete full-word

# Which characters, besides letters and numbers, that are jumped over by a
# full-word jump:
FULLWORDCHARS="*?_-.,[]~=/&:;!#$%^(){}<>'\""

backward-full-word() { WORDCHARS=$FULLWORDCHARS zle .backward-word ; }
backward-sub-word() { WORDCHARS="" zle .backward-word ; }
forward-full-word() { WORDCHARS=$FULLWORDCHARS zle .forward-word ; }
backward-kill-full-word() { WORDCHARS=$FULLWORDCHARS zle .backward-kill-word ; }
backward-kill-sub-word() { WORDCHARS="" zle .backward-kill-word ; }
forward-kill-full-word() { WORDCHARS=$FULLWORDCHARS zle .kill-word ; }
forward-kill-sub-word() { WORDCHARS="" zle .kill-word ; }

zle -N backward-full-word
zle -N backward-sub-word
zle -N forward-full-word
zle -N backward-kill-full-word
zle -N backward-kill-sub-word
zle -N forward-kill-full-word
zle -N forward-kill-sub-word

# For `forward-sub-word` we use the built-in `emacs-forward-word` widget,
# because that simulates bash behavior.
zle -A emacs-forward-word forward-sub-word

bindkey "^[b" backward-sub-word
bindkey "^[^b" backward-full-word
bindkey "^[f" forward-sub-word
bindkey "^[^f" forward-full-word
bindkey "^[^h" backward-kill-sub-word
bindkey "^w" backward-kill-full-word
bindkey "^[d" forward-kill-sub-word
bindkey "^[^d" forward-kill-full-word

関連情報