Faça com que `Ctrl + W` e `Ctrl + Alt + H` no zsh se comportem da mesma forma que no bash

Faça com que `Ctrl + W` e `Ctrl + Alt + H` no zsh se comportem da mesma forma que no bash

No bash, o comportamento é assim:

  • Ctrl+ Wexclui a palavra atrás do cursor até o próximo espaço
  • Ctrl++ Altexclui Ha palavra atrás do cursor até o próximo caractere de separação como ., ,, -, /etc.

Em zsh+ e + + se comportam como o último Ctrlem .WCtrlAltHbash

Eu gostaria do mesmo comportamento que em bash.

Responder1

Isso faz o que você deseja, independentemente do que está em $WORDCHARS, e disponibiliza as palavras mortas para 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, eu lancei umplugin chamadozsh-edit, que vem com versões mais sofisticadas dessas combinações de teclas.

Responder2

Você pode definir os caracteres especiais que são considerados parte de uma palavra com a WORDCHARSvariável. Isso tem influência em como as palavras são excluídas por Ctrl + W:

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

No entanto, também tem influência sobre Ctrl + Alt + H. Queremos que esse comportamento se aplique apenas a arquivos Ctrl + W. Mas há um truque que podemos fazer. Deixe-me explicar:

Você pode vincular novamente as combinações de teclas a diferentes funções (consulte man zshzle). E existem 2 funções que na verdade têm o mesmo comportamento:

  • excluir palavra para trás
  • palavra de matar para trás

Você também pode redefinir essas funções com zle -N <func>. Não tenho muita certeza de como funciona, mas você tem uma ideia se ler o código, de qualquer forma, funciona.

Por padrão, ambos Ctrl + We Ctrl + Alt + Hsão mapeados para backward-kill-word. Portanto, podemos redefinir backward-delete-worde vincular isso 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

Sim, agora Ctrl + Wexclui palavras maiores que Ctrl + Alt + H!

Editar:

Infelizmente, agora estou descobrindo que essa abordagem carece de alguma funcionalidade. Quando você exclui uma palavra, ela não é puxada para o buffer de colagem (Ctrl + Y). Ainda não encontrei uma solução para isso..

Responder3

Finalmente encontrei meu comportamento desejado com estas ligações:

# 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

informação relacionada