Flux
Flux

Reputation: 10930

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?

Upvotes: 8

Views: 6036

Answers (2)

Alex Norman
Alex Norman

Reputation: 11

The post by ymonad is a neat solution, but I'm posting an answer because of the lighbulb it prompted in me.

I found it helps to remember that a .zshrc file is just a shell script - you can treat it like the terminal. So, read man git to see what's available to you to gather the information you need. You can then simply query git in a function or the like in your .zshrc. Like so:

zstyle ':vcs_info:*' formats "%u%c%m"
zstyle ':vcs_info:git*+set-message:*' hooks untracked-git

+vi-untracked() {
  if [[ -n "$(git ls-files --others --exclude-standard)" ]]; then
      hook_com[misc]='?'
  else
      hook_com[misc]=''
  fi
}

When I realised that I could treat the .zshrc file like a shell script (duh), I realised I could just copy over what had worked for me in bash. So, the above is exactly the same if statement I have in my .bashrc to look for the presence of untracked files.

Upvotes: 1

ymonad
ymonad

Reputation: 12100

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).

Upvotes: 9

Related Questions