Skip to content
Shane Sveller edited this page Nov 18, 2024 · 3 revisions

Adding jj information to the shell prompt

Tip

Fish shell users or Starship prompt users should review those pages instead as they have more specific advice. Note that Starship is a tool that supports multiple shell engines, including Bash and ZSH.

Some users like to have information about the current repository status printed out with every shell prompt. The following is example code that defines a shell function to check for the presence of a jj or Git repository, prints useful information about the repository, and adds the function to the PS1 prompt in bash or zsh.

# Dedicated to the Public Domain under the Unlicense: https://unlicense.org/UNLICENSE

# Print Git or jj repository information
jjgit_prompt()
{
  pwd_in_jjgit() # echo "jj" or "git" if either is found in $PWD or its parent directories
  { # using the shell is much faster than `git rev-parse --git-dir` or `jj root`
    local D="/$PWD"
    while test -n "$D" ; do
      test -e "$D/.jj" && { echo jj ; return; }
      test -e "$D/.git" && { echo git ; return; }
      D="${D%/*}"
    done
  }
  local jjgit="`pwd_in_jjgit`"  # results in "jj", "git" or ""
  if test "$jjgit" = jj ; then
    # --ignore-working-copy: avoid inspecting $PWD and concurrent snapshotting which could create divergent commits
    jj --ignore-working-copy --no-pager log --no-graph --color=always -r @ -T \
       ' "jj:[@ " ++ concat( separate(" ", format_short_change_id_with_hidden_and_divergent_info(self), format_short_commit_id(commit_id),
       				   bookmarks, if(conflict, label("conflict", "conflict")) ) ) ++ "]\n" ' 2>/dev/null
  elif test "$jjgit" = git ; then
    # --no-pager: never use a pager for the prompt, regardless of user config
    local gitprompt=$(git --no-pager log -1 --color=always
		      --pretty='%C(auto)%h ꜓%C(auto)%(decorate:prefix=,suffix=,tag=,pointer=→,separator= )' 2>/dev/null)
    echo "git:[${gitprompt/HEAD/}]"
  fi
}

# Add jjgit_prompt to PS1
test -n "$precmd_functions" && { # zsh
  ps1_jjgit_prompt() { PS1="`jjgit_prompt`"$'\n'"$PS1"; }
  precmd_functions=("${precmd_functions[@]/jjgit_prompt}") # remove old version
  precmd_functions+=(ps1_jjgit_prompt) # add new prompt function
} || { # bash
  [[ $PS1 == *'$(jjgit_prompt)'* ]] ||
    PS1='$(jjgit_prompt)\n'"$PS1"
}

To convert a Git repository into a jj repository, use jj git init --colocate.

Clone this wiki locally