简体   繁体   中英

make zsh prompt update each time a command is executed

TLDR;

I need a way for .zshrc to automatically be sourced each time a command is executed. PROMPT needs to be updated each time a command is executed in order to show relevant information in the prompt.

Reason

I use Watson cli for tracking time. On my previous bash setup, I prepended my prompt ( $PS1 ) with a symbol that indicates whether the timer is running or not (red/green). I have mimicked this functionality with Oh My Zsh, as follows (in the theme file):

WATSON_DIR="$HOME/Library/Application Support/watson"
watson_status() {
    local txtred="${fg_bold[red]}"
    local txtgrn="${fg_bold[green]}"
    local txtrst="${reset_color}"

    # Started
    local status_color="$txtgrn"

    # Stopped
    if [[ $(cat "$WATSON_DIR/state") == '{}' ]]; then
        status_color="$txtred"
    fi
    echo -e "$status_color""◉""$txtrst"
}

PROMPT="╭── %{$(watson_status) $fg_bold[green]%}%~%{$reset_color%}$(git_prompt_info) ⌚ %{$FG[130]%}%*%{$reset_color%}
╰─➤ $ "

Current issue

The icon will indicate the color of the state at the time that .zshrc was executed. For example, if the timer is running and the icon is properly indicating green, stopping the timer will not cause the icon to turn red. In order to see the icon change color, I have to source .zshrc.

This indicates that the function watson_status() needs to be run each time a command is executed, to give the latest status at the time of the command

I recently ported some prompt code from bash to zsh - on OSX Big Sur - and these were the two big "things to know" for me:

  • add setopt PROMPT_SUBST to your .zshrc. This "allows for functions in the prompt"
  • use single quotes when defining your PS1 / PROMPT. If you use double quotes, then the whole string will be evaluated once when the terminal starts, and then that evaluated value is "re-executed" every time the command changes. But you want the functions to be re-evaluated, not the output of the function at the time when the terminal is created.

Easiest example I used to confirm I had it working:

# print_epoch() { date '+%s' }

# this is what you want
# export PS1='$(print_epoch) > '

# this is not what you want
# export PS1="$(print_epoch) > "

Also worth noting PS1 and PROMPT are interchangeable

Extra:

While we are sharing here is my fairly minimal echo my user, directory, and git branch PROMPT with some colors and a pretty leaf:

parse_git_branch() {
  git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/'
}

setopt PROMPT_SUBST
autoload -U colors && colors
export PROMPT='%n %~ %F{blue}🌿$(parse_git_branch)%f > '

noting that:

  • %n prints name
  • %~ prints directory relative to home
  • %F{blue} changes text to blue
  • %f resets color

Documentation: http://zsh.sourceforge.net/Doc/Release/Prompt-Expansion.html#Visual-effects

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM