Qual é o equivalente ZSH do $ PROMPT_COMMAND do BASH?

16

O BASH suporta uma variável de ambiente $PROMPT_COMMAND que define um comando a ser executado antes de qualquer prompt interativo de primeiro nível. Estou procurando por um equilíbrio de ZSH.

A documentação diz que há uma função precmd que eu posso definir para achá-la; no entanto, não tenho ideia de como defini-lo a partir de uma variável de ambiente.

Eu considerei passar uma variável de ambiente que faria o ZSH ler um arquivo contendo a definição dessa função, mas ZSH não parecem suportar tais coisas : ele lê apenas arquivos globais e, em seguida, arquivos por usuário. Eu posso substituí-los, mas não posso adicioná-los sem modificar os arquivos, o que não posso fazer.

Então, como defino um gancho pré-prompt no ZSH por meio de uma variável de ambiente, como eu faria usando $PROMPT_COMMAND no BASH?

    
por Shnatsel 31.03.2014 / 04:13

2 respostas

15

A abordagem mais simples para emular o $PROMPT_COMMAND do bash que me vem à mente é usar o precmd hook, como você já descobriu. Defina-o como

precmd() { eval "$PROMPT_COMMAND" }

e você pode fazer algo assim:

$ 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     
$

Observe as aspas simples nesse exemplo, caso contrário, $(date) será expandido muito cedo, ou seja, quando definir $PROMPT_COMMAND e não quando chamado antes do prompt.

Se você quiser preservar (e não quiser alterar) a definição existente, use essa abordagem:

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

Com isso, as funções prmptcmd são executadas após a função precmd() existente.

Finalmente, aqui está uma maneira que é adequada para uso em um pacote de programas, que não deve modificar os arquivos do usuário ou do sistema, nem pode inserir os comandos interativos.

Um exemplo para gerar uma sessão bash poderia ser

PROMPT_COMMAND="echo foo" bash

Para gerar o zsh, você pode usar

ZDOTDIR=/program/dir zsh

que faz com que /program/dir/.zshrc seja originado. Neste arquivo, o gancho precmd() pode ser definido como explicado acima. Se você quiser que as configurações do usuário além incluam source $HOME/.zshrc etc. no .zshrc do programa, também. Esta configuração é sustentável, pois nenhum arquivo fora do diretório do programa é modificado.

Como último acréscimo, aqui está uma prova de conceito de como manter o novo usuário bem-vindo também. Use o seguinte código no seu arquivo de configuração /program/dir/.zshenv rc:

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
    
por 31.03.2014 / 19:11
3

Como @mypy afirma, precmd de Zsh funciona de forma semelhante ao PROMPT_COMMAND de Bash.

Veja um exemplo que funciona para Bash ou Zsh e não usa 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
}

Executar a partir de scripts de inicialização de shell:

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

e:

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

Os prompts aqui são apenas exemplos. Pode-se definitivamente fazer coisas muito mais complicadas.

Para detalhes sobre a configuração das funções de prompt, consulte: link e link .

Para obter detalhes sobre expansões de prompts, consulte link e link .

    
por 07.10.2014 / 22:29