Search code examples
gitzsh

ZSH vcs_info: How to indicate if there are untracked files in Git


In my zsh configuration, I have the following settings for vcs_info:

zstyle ':vcs_info:*' enable git
zstyle ':vcs_info:*' check-for-changes true
zstyle ':vcs_info:*' unstagedstr '!'
zstyle ':vcs_info:*' stagedstr '+'
zstyle ':vcs_info:*' formats "%u%c"

Using these settings, when I am in a git repository that contains unstaged changes, a ! will be displayed in the prompt. When there are staged changes, a + will be displayed in the prompt.

This is all good, but how do I make zsh indicate, for example ?, when there are untracked files in the repository?

I could not find a built-in setting for this in the zsh manual. Is there a way to get an indication if there are untracked files in a Git repository?


Solution

  • In the source of zsh there is good example of showing T mark to prompt when there is untracked file: Misc/vcs_info_examples

    ### Display the existence of files not yet known to VCS
    
    ### git: Show marker (T) if there are untracked files in repository
    # Make sure you have added staged to your 'formats':  %c
    zstyle ':vcs_info:git*+set-message:*' hooks git-untracked
    
    +vi-git-untracked(){
        if [[ $(git rev-parse --is-inside-work-tree 2> /dev/null) == 'true' ]] && \
            git status --porcelain | grep '??' &> /dev/null ; then
            # This will show the marker if there are any untracked files in repo.
            # If instead you want to show the marker only if there are untracked
            # files in $PWD, use:
            #[[ -n $(git ls-files --others --exclude-standard) ]] ; then
            hook_com[staged]+='T'
        fi
    }
    

    You can just copy & paste from here, but I wrote a slight modification version which uses misc instead of adding character to staged.

    zstyle ':vcs_info:*' formats "%u%c%m"
    zstyle ':vcs_info:git*+set-message:*' hooks git-untracked
    
    +vi-git-untracked() {
      if [[ $(git rev-parse --is-inside-work-tree 2> /dev/null) == 'true' ]] && \
         git status --porcelain | grep -m 1 '^??' &>/dev/null
      then
        hook_com[misc]='?'
      fi
    }
    

    %m in format corresponds to character in hook_com[misc]. Also just grepping whole the output of git status --porcelain, instead it may be faster using grep -m 1 (depends on how the standard output is buffered or how git status --porcelain is implemented).