Haga que `Ctrl + W` y `Ctrl + Alt + H` en zsh se comporten igual que en bash

Haga que `Ctrl + W` y `Ctrl + Alt + H` en zsh se comporten igual que en bash

En bash el comportamiento es así:

  • Ctrl+ Welimina la palabra detrás del cursor hasta el siguiente espacio
  • Ctrl+ Alt+ Helimina la palabra detrás del cursor hasta el siguiente carácter de separación como ., ,, -, /etc.

zshTanto en Ctrl+ Wcomo Ctrlen Alt++ Hse comportan como este último en bash.

Me gustaría el mismo comportamiento que en bash.

Respuesta1

Esto hace lo que usted quiere, independientemente de lo que haya en $WORDCHARS, y pone las palabras eliminadas a disposición de 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

Alternativamente, he lanzado uncomplemento llamadozsh-edit, que viene con versiones más sofisticadas de estas combinaciones de teclas.

Respuesta2

Puede configurar los caracteres especiales que se consideran parte de una palabra con la WORDCHARSvariable. Esto influye en cómo se eliminan las palabras Ctrl + W:

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

Sin embargo, también influye Ctrl + Alt + H. Queremos que este comportamiento solo se aplique a Ctrl + W. Pero hay un truco que podemos hacer. Dejame explicar:

Puede volver a vincular las combinaciones de teclas a diferentes funciones (ver man zshzle). Y hay 2 funciones que en realidad tienen el mismo comportamiento:

  • borrar-palabra-hacia atrás
  • palabra-matar-hacia atrás

También puedes redefinir estas funciones con zle -N <func>. No estoy completamente seguro de cómo funciona, pero te darás una idea si lees el código; de todos modos, funciona.

De forma predeterminada, ambos Ctrl + Wy Ctrl + Alt + Hestán asignados a backward-kill-word. Entonces podemos redefinir backward-delete-wordy luego vincularlo a 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

Sí, ¡ahora Ctrl + Welimina palabras más grandes que Ctrl + Alt + H!

Editar:

Lamentablemente, ahora estoy descubriendo que este enfoque carece de algunas funciones: cuando eliminas una palabra, no se transfiere al búfer de pegado (Ctrl + Y). Aún no he encontrado una solución para eso.

Respuesta3

Finalmente encontré el comportamiento deseado con estos enlaces:

# 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

información relacionada