Sorgen Sie dafür, dass sich `Strg + W` und `Strg + Alt + H` in zsh genauso verhalten wie in bash

Sorgen Sie dafür, dass sich `Strg + W` und `Strg + Alt + H` in zsh genauso verhalten wie in bash

In Bash sieht das Verhalten so aus:

  • Ctrl+ Wlöscht das Wort hinter dem Cursor bis zum nächsten Leerzeichen
  • Ctrl+ Alt+ Hlöscht das Wort hinter dem Cursor bis zum nächsten Trennzeichen wie ., ,, -, /usw.

zshSowohl in Ctrl+ Wals auch Ctrlin + verhalten sich Alt+ Hwie letzteres in bash.

Ich hätte gerne das gleiche Verhalten wie in bash.

Antwort1

Dies bewirkt, was Sie möchten, unabhängig vom Inhalt $WORDCHARS, und macht die entfernten Wörter verfügbar für 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

Alternativ habe ich einePlugin namenszsh-edit, das mit ausgefeilteren Versionen dieser Tastenkombinationen ausgestattet ist.

Antwort2

Mit der Variable können Sie die Sonderzeichen festlegen, die als Teil eines Wortes betrachtet werden WORDCHARS. Dies hat Einfluss darauf, wie Wörter gelöscht werden durch Ctrl + W:

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

Es hat jedoch auch Einfluss auf Ctrl + Alt + H. Wir möchten, dass dieses Verhalten nur für gilt Ctrl + W. Aber es gibt einen Trick, den wir anwenden können. Lassen Sie es mich erklären:

Sie können die Tastenkombinationen verschiedenen Funktionen zuordnen (siehe man zshzle). Und es gibt 2 Funktionen, die tatsächlich das gleiche Verhalten haben:

  • Wort rückwärts löschen
  • Rückwärts-Kill-Wort

Sie können diese Funktionen auch mit neu definieren zle -N <func>. Ich bin mir nicht ganz sicher, wie das funktioniert, aber Sie bekommen eine Vorstellung davon, wenn Sie den Code lesen. Jedenfalls funktioniert es.

Standardmäßig sind sowohl Ctrl + Wals auch Ctrl + Alt + Hauf abgebildet backward-kill-word. Wir können es also neu definieren backward-delete-wordund dann an binden 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

Ja, Ctrl + Wlöscht jetzt größere Wörter als Ctrl + Alt + H!

Bearbeiten:

Leider stelle ich jetzt fest, dass dieser Ansatz einige Funktionen vermissen lässt. Wenn man ein Wort löscht, wird es nicht in den Einfügepuffer gezogen (Strg + Y). Ich habe dafür noch keine Lösung gefunden.

Antwort3

Mit diesen Bindungen habe ich letztendlich das gewünschte Verhalten gefunden:

# 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

verwandte Informationen