如何使zsh的forward-word行为与bash/emacs相同

20

zsh 的 forward-word 和 bash/emacs 有些不同,我想要修改它的行为。

不想详细描述所有的差异,让我一步一步地展示 bash 的行为。我用 "^" 符号标记了光标的位置。

foo bar --non-needed-param --needed-param^

M-b

foo bar --non-needed-param --needed-^param

M-b

foo bar --non-needed-param --^needed-param

M-b

foo bar --non-needed-^param --needed-param

M-b

foo bar --non-^needed-param --needed-param

M-b
foo bar --^non-needed-param --needed-param

M-b

foo ^bar --non-needed-param --needed-param

M-f

foo bar^ --non-needed-param --needed-param

M-d

foo bar^-needed-param --needed-param

M-d

foo bar^-param --needed-param

M-d

foo bar^ --needed-param

这个算法能够在单词之间进行灵活移动并删除其中的一部分。此外,它是emacs中的,我很习惯使用它。我希望也能在zsh中看到它。谢谢。

2个回答

29
我在我的.zshrc文件中加入了以下内容,以达到这个目的:
# Bash-like navigation
autoload -U select-word-style
select-word-style bash

编辑:啊,我记得为了让所有东西都按照我想要的方式工作,还有一件事情需要完成。我还通过将以下内容放入$ZDOTDIR/functions/forward-word-match(假设您的$ZDOTDIR/functions目录在$fpath中;否则,请将其放入一个目录或修改$fpath数组)来覆盖forward-word-match

emulate -L zsh
setopt extendedglob

autoload match-words-by-style

local curcontext=":zle:$WIDGET" word
local -a matched_words
integer count=${NUMERIC:-1}

if (( count < 0 )); then
    (( NUMERIC = -count ))
    zle ${WIDGET/forward/backward}
    return
fi

while (( count-- )); do

    match-words-by-style

    # For some reason forward-word doesn't work like the other word
    # commands; it skips whitespace only after any matched word
    # characters.

    if [[ -n $matched_words[4] ]]; then
        # just skip the whitespace and the following word
  word=$matched_words[4]$matched_words[5]
    else
        # skip the word but not the trailing whitespace
  word=$matched_words[5]
    fi

    if [[ -n $word ]]; then
  (( CURSOR += ${#word} ))
    else
  return 1
    fi
done

return 0

谢谢!但它实际上与bash不同(我做错了什么吗?)。在这种情况下:“fo^ooo --bar”,如果您按“M-f”,它应该立即转到foooo的末尾,就像这样:“foooo^ --bar”,但是我按照您展示的启用了它,它会变成这样:“foooo --^bar”。实际上,这个插件看起来只是导出WORDCHARS=''。 - Konstantine Rybnikov
我的完整zsh配置按照您的要求工作 - 所以我想我做了比我的答案中所述更多的事情。尽管我无法理解它实际设置在哪里,但我的WORDCHARS包含相当多的字符:($WORDCHARS是*?_-. []〜=/&;!#$%^(){}<> - Moritz Bunkus
嗯。如果我选择 select-word-style bash 然后设置 WORDCHARS -- WORDCHARS 无关紧要。看起来 select-word-style bash 还有其他的配置参数。 - Konstantine Rybnikov
这太疯狂了!我不敢相信你没有25个赞。好使! - Emanuel Berg
2
如果我没有设置ZDOTDIR(则默认为$HOME),并且我使用oh-my-zsh,那么我该如何应用此解决方案? - Forethinker
显示剩余3条评论

5
为了得到符合您期望的Emacs键绑定行为,我所需要做的就是:
bindkey '\ef' emacs-forward-word

莫里茨·邦库斯的回答的这部分现在似乎已经自己运行正常了:

autoload -U select-word-style
select-word-style bash

在某些边缘情况下,它似乎表现得更好(例如,它将?视为单词分界线,而上述方法则不会。)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接