在 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
)。有两个函数实际上具有相同的行为:
- 向后删除单词
- 向后杀字
您还可以使用 重新定义这些函数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