ZSH:按Enter键的行为

7

当我在终端中时,我会期望在空输入上按Enter键来运行ls或者在git仓库上运行git status.

我该如何实现这一点呢?我的意思是,在zsh中自定义Empty input -> Enter的行为?


编辑:感谢帮助。这是我的解决方案,使用preexec...

precmd() {
  echo $0;
  if ["${0}" -eq ""]; then
    if [ -d .git ]; then
      git status
    else
      ls
    fi;
  else
    $1
  fi;
}

尝试将[["$1" -eq ""]]更改为["$1" -eq ""],并将代码放入precmd而不是preexec - user12341234
谢谢。已更新。如果我使用$1,它总是为空的,如果我使用$0,我仍然会得到bad pattern: [zsh... - Augustin Riedinger
所以我回显了$0, $1$2的内容。这是我的输出preexec: $0=preexec, $1=ll, $2=ls --color=tty -lhprecmd: $0=zsh, $1=$2=""。另外需要注意的是:在按下空字符串时不调用preexec。并且precmd不知道先前的命令。不确定我能否在这里实现我想要的... - Augustin Riedinger
2个回答

7

在按下Enter键时,zsh会调用accept-line小部件,这将导致缓冲区作为命令执行。

您可以编写自己的小部件以实现所需的行为并重新绑定Enter键:

my-accept-line () {
    # check if the buffer does not contain any words
    if [ ${#${(z)BUFFER}} -eq 0 ]; then
        # put newline so that the output does not start next
        # to the prompt
        echo
        # check if inside git repository
        if git rev-parse --git-dir > /dev/null 2>&1 ; then
            # if so, execute `git status'
            git status
        else
            # else run `ls'
            ls
        fi
    fi
    # in any case run the `accept-line' widget
    zle accept-line
}
# create a widget from `my-accept-line' with the same name
zle -N my-accept-line
# rebind Enter, usually this is `^M'
bindkey '^M' my-accept-line

尽管只在实际存在命令的情况下运行zle accept-line就足够了,但是zsh不会在输出后放置一个新提示符。而如果使用多行提示符,则使用zle redisplay可能会覆盖输出的最后一行或几行。当然,也有解决方法,但没有什么比使用zle accept-line更简单的了。

警告:这将重新定义你的shell中(最?)重要的部分。这本质上并没有什么问题(否则我就不会在这里发布它了),但如果my-accept-line没有完美运行,它很有可能使你的shell无法使用。例如,如果缺少zle accept-line,则不能使用Enter确认任何命令(例如重新定义my-accept-line或启动编辑器)。因此,请在将其放入~/.zshrc之前进行测试。

另外,默认情况下,accept-line也绑定到Ctrl+J。我建议保留这种方式,以便有一种简便的方法来运行默认的accept-line


感谢您提供如此详细的答案。不幸的是,小部件似乎没有被执行:如果我手动调用zle -N my-accept-line,并在之前加上一些echo“test”,则不会显示它。调用my-accept-line可以执行,但在zle accept-line处失败,并显示widgets can only be called when ZLE is active(在进行了一些谷歌搜索后这是正常的)... - Augustin Riedinger
在这里找到了解决方案:http://sgeb.io/articles/zsh-zle-closer-look-custom-widgets/ 已更新您的答案。 - Augustin Riedinger
1
我在脚本的最后一行错误地绑定了 ^M 到原来的 accept-line,而不是 my-accept-line。这就是为什么它没有工作的原因。您提议的编辑(使用 zle .accept-line 而不是 zle accept-line 并使用 zle -N accept-line my-accept-line 覆盖 accept-line 而不是 zle -N my-accept-line)也可以工作。虽然它会防止使用 Ctrl+J 作为后备。 - Adaephon

0

谢谢。我现在在苦苦思索编写脚本的问题。你能检查一下我的更新吗? - Augustin Riedinger

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