BASH的$ PROMPT_COMMAND的ZSH等价于什么?


24

BASH支持$PROMPT_COMMAND环境变量,该变量定义在任何第一级交互式提示之前要执行的命令。我正在寻找与之等效的ZSH。

文档说,有一个precmd我可以定义的功能可以实现。但是,我不知道如何从环境变量中定义它。

我曾经考虑过传递一个环境变量,该变量将使ZSH读取包含该函数定义的文件,但是ZSH 似乎不支持这种情况:它仅读取全局文件,然后读取每个用户的文件。我可以替换它们,但不能在不修改文件的情况下添加它们,这是我不能做的。

那么,如何像我$PROMPT_COMMAND在BASH中使用的那样,通过环境变量在ZSH中定义预提示挂钩?


说实话,我需要一个交互式命令执行后挂钩,但是没有一个shell提供一个挂钩,所以我不得不求助于预提示挂钩-它们似乎尽可能地接近我。
Shnatsel 2014年

1
嗯,我想知道,交互式命令执行后预提示之间有什么区别。除了概念上的差异外,您实际在哪里观察到差异。(让我们省略了命令exitexec,OK ;)
MPY

@mpy在运行后台作业时有所不同,因为后台作业独立于提示顺序。
Shnatsel 2014年

1
好吧,我明白了。那么,这样的事情怎么样:start() { eval "$@"; echo post-command-code }然后使用zle-binding执行带start前缀的命令行?
mpy 2014年

1
DEBUG陷阱是一个很好找,但是你仍然有问题,如何定义它。我再次扩展了答案,但请您自己编写有关DEBUG陷阱解决方案的答案。:)
mpy

Answers:


24

$PROMPT_COMMAND我想到的最简单的模仿bash的方法是使用precmd钩子,正如您已经意识到的那样。定义为

precmd() { eval "$PROMPT_COMMAND" }

您可以执行以下操作:

$ PROMPT_COMMAND='echo Hello, it is now $(date)'
Hello, it is now Mon, Mar 31, 2014 7:08:00 PM
$ whoami      
user
Hello, it is now Mon, Mar 31, 2014 7:08:21 PM     
$

请注意该示例中的单引号,否则$(date)将被过早扩展,即在定义$PROMPT_COMMAND时已经扩展,而不是在提示之前被调用。


如果要保留(而不希望更改)现有定义,则可以使用该方法:

$ prmptcmd() { eval "$PROMPT_COMMAND" }
$ precmd_functions=(prmptcmd)

这样,prmptcmd功能将在现有precmd()功能之后执行。


最后,这是一种适合在程序包中使用的方法,该程序包既不应修改用户或系统文件,也不能交互输入命令。

生成bash会话的示例可能是

PROMPT_COMMAND="echo foo" bash

要生成zsh,您可以使用

ZDOTDIR=/program/dir zsh

导致/program/dir/.zshrc来源。在该文件中,precmd()可以如上所述定义钩子。如果您还希望用户的设置source $HOME/.zshrc程序的.zshrc中也包括etc。此设置是可维护的,因为程序目录之外的任何文件都不会被修改。


最后,这是一个概念证明,也是如何保持新用户的欢迎。在/program/dir/.zshenvrc配置文件中使用以下代码:

echo define precmd, traps, etc.

autoload -Uz zsh-newuser-install

if [[ ! -e "$HOME/.zshrc" ]]; then
  zsh-newuser-install -f
  mv $ZDOTDIR/.zshrc $HOME/.zshrc
else
  builtin source $HOME/.zshrc
fi

我想得那么多。问题是-如何通过环境变量定义precmd挂钩?有没有添加钩子或代码而不修改文件的机制?或者,至少在不写入全局和用户全局“ .zprofile”以及类似文件的情况下,我该如何做?像,我可以添加自己的.zprofile来代替现有的吗?
Shnatsel 2014年

1
同样,您在此处使用precmd钩子将替换任何现有的precmd钩子;zsh docs提到我可以制作一系列可以共存的函数,但是我不知道该怎么做。
Shnatsel 2014年

1
(1)我如何通过环境变量定义precmd钩子是什么意思我介绍的示例像bash机制一样恕我直言。(2)您可以通过命令行添加钩子,但是它不是永久的。您的修改有什么问题.zshrc?(3)的一个例子:foo() { echo foo }; bar() { echo bar }; precmd_functions=(foo bar)该执行foo()bar() precmd()
mpy 2014年

2
好的,这澄清了很多-那么bash的一个最小示例就是PROMPT_COMMAND="echo foo" bash,对吧?这是产生zsh:的可能性吗ZDOTDIR=/program/dir zsh?然后/program/dir/.zshrc在启动时提供源代码,您可以在其中定义precmd()挂钩。如果您希望用户的另外包含source $HOME/.zshrc等在程序的zshrc中。这应该易于维护,因为程序目录之外的任何文件都不会被修改。
mpy 2014年

1
@Shnatsel:我扩大了答案。也许您还可以编辑问题以包含评论中的其他信息。
mpy

5

如@mypy所述,Zsh的precmd工作方式与Bash的类似PROMPT_COMMAND

这是一个适用于Bash或Zsh且不使用的示例eval

## ~/myprompt.sh

# 'ZSH_VERSION' only defined in Zsh
# 'precmd' is a special function name known to Zsh

[ ${ZSH_VERSION} ] && precmd() { myprompt; }

# 'BASH_VERSION' only defined in Bash
# 'PROMPT_COMMAND' is a special environment variable name known to Bash

[ ${BASH_VERSION} ] && PROMPT_COMMAND=myprompt

# function called every time shell is about to draw prompt
myprompt() {
  if [ ${ZSH_VERSION} ]; then
    # Zsh prompt expansion syntax
    PS1='%{%F{red}%}%n%{%f%}@%{%F{red}%}%m %{%F{cyan}%}%~ %{%F{white}%}%# %{%f%}'
  elif [ ${BASH_VERSION} ]; then
    # Bash prompt expansion syntax
    PS1='\[\e[31m\]\u\[\e[0m\]@\[\e[31m\]\h \[\e[36m\]\w \[\e[37m\]\$ \[\e[0m\]'
  fi
}

从shell初始化脚本运行:

## ~/.bashrc
. ~/myprompt.sh

和:

## ~/.zshrc
. ~/myprompt.sh

这里的提示只是示例。绝对可以做很多棘手的事情。

有关设置提示功能的详细信息,请参见:http : //zsh.sourceforge.net/Doc/Release/Functions.html#index-precmdhttp://www.gnu.org/software/bash/manual/bashref.html #Printing-a-Prompt

有关即时扩展的详细信息,请参见http://zsh.sourceforge.net/Doc/Release/Prompt-Expansion.htmlhttp://www.gnu.org/software/bash/manual/bashref.html#Printing-a -提示

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.