For example with following:

prompt_git() {
  () {
  local ref mode repo_path
  repo_path=$(git rev-parse --git-dir 2>/dev/null)

  if $(git rev-parse --is-inside-work-tree >/dev/null 2>&1); then
    ref=$(git symbolic-ref HEAD 2> /dev/null) || ref="➦ $(git rev-parse --short HEAD 2> /dev/null)"

    if [[ -e "${repo_path}/BISECT_LOG" ]]; then
      mode=" <B>"
    elif [[ -e "${repo_path}/MERGE_HEAD" ]]; then
      mode=" >M<"
    elif [[ -e "${repo_path}/rebase" || -e "${repo_path}/rebase-apply" || -e "${repo_path}/rebase-merge" || -e "${repo_path}/../.dotest" ]]; then
      mode=" >R>"

    setopt promptsubst
    autoload -Uz vcs_info

    zstyle ':vcs_info:*' enable git
    zstyle ':vcs_info:*' get-revision true
    zstyle ':vcs_info:*' check-for-changes true
    zstyle ':vcs_info:*' stagedstr '✚'
    zstyle ':vcs_info:*' unstagedstr '●'
    zstyle ':vcs_info:*' formats ' %u%c'
    zstyle ':vcs_info:*' actionformats ' %u%c'
    echo -n "${ref/refs\/heads\//$PL_BRANCH_CHAR }${vcs_info_msg_0_%% }${mode} "

build_prompt() {


it doesn't react if I change directory

to update git stats I need exec "${SHELL}" "$@"

how to react on directory change automatically?

thank you


with PROMPT="…$(build_prompt)", you're running build_prompt at the time of the assignment, i.e. when your .zshrc is read, and using the result of that one run as the prompt.

To run build_prompt each time the prompt is displayed, include the string $(build_prompt) directly in the value of the PROMPT variable. This requires turning on the prompt_subst option.

setopt prompt_subst

Alternatively, run the prompt-setting code in a precmd hook.

set_prompt () {
  PROMPT="%{%f%b%k%}${ref/refs\/heads\//$PL_BRANCH_CHAR }${vcs_info_msg_0_%% }${mode} "

Also note that the code that runs setopt, zstyle and autoload doesn't belong in a function. It kind of works but it'll prevent from changing these settings later. This is code that needs to run only once, so put it in your .zshrc outside of any function.

To answer the question you asked, to run code on a directory change, put it in a chpwd hook. But this isn't what you want: you need to update the prompt not only on a directory change but also on a git state change, so the update code needs to run every time the prompt is displayed.

  • strange but setopt prompt_subst doesn't work – cnd Jul 23 '16 at 7:46
  • [[ -z $precmd_functions ]] && precmd_functions=() precmd_functions=($precmd_functions prompt) - works – cnd Jul 23 '16 at 8:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.