Show Git State in ZSH Prompt via vcs_info
zsh has excellent capabilities of supporting different version control systems, like git in its command line prompt. Setup is pretty convoluted and I’ll try to guide you through it to give you basic understanding of all the building blocks. You’ll be able to craft your own one.
I’ll show evolution of a command line prompt after each modification in .zshrc
. I’ll assume ~/.git
exists and has changes on the master branch. Current directory is set to ~/.ssh
.
zsh has very extensive documentation. Two particularly useful pages are: zsh Prompt Expansion and zsh Version Control Information. You do not need to read them through, but they will be extremely useful when you’ll try to add some special flavor into your own prompt command.
Quickstart
You can set reasonable defaults from the zsh vcs_info Quickstart (don’t forget to add autoload -Uz vcs_info
) and try to understand what does it mean later.
Show current user and directory in the command prompt
timothy@home:~/.ssh>
zsh supports username %n
, short hostname %m
and directory %~
in prompt (other supported symbols):
- Let’s show
user@host:dir>
prompt:PROMPT='%n@%m:%~> '
It’s pretty basic, but that’s only a beginning.
Show git (or any other version management system) info in the prompt
timothy@home: (git)-[master]->
- Allow dynamic command prompt:
setopt prompt_subst
- Make sure that
vcs_info
function is available:autoload -Uz vcs_info
- Update each time new prompt is rendered:
function precmd() { vcs_info }
- Show git info in the prompt:
PROMPT='%n@%m:${vcs_info_msg_0_}> '
Now we can see that we’re within git repository.
Add repository path and path within repository to the prompt
timothy@home:/Users/timothy/(master).ssh>
- Show full path when outside of git:
zstyle ':vcs_info:*' nvcsformats '%~'
- Show base (.git) directory, current branch and path within a repo:
zstyle ':vcs_info:*' formats '%R/(%b)%S'
All the information about available options check zsh vcs_info Configuration. It’s particularly useful to check for all expansion parameters available in different contexts.
That’s much better, we got back information about our current directory
Add information about uncommitted changes
timothy@home:/Users/timothy/(master).ssh!>
- Show “unsubmitted changes” mark:
zstyle ':vcs_info:*' check-for-changes true
- Add
!
for unstaged changes:zstyle ':vcs_info:*' unstagedstr '!'
- Add
+
for staged changes:zstyle ':vcs_info:*' stagedstr '+'
- Render both marks if they are present:
zstyle ':vcs_info:*' formats '%R/(%b)%S
%u%c'
Good, we see !
as we have uncommitted changes, as expected.
Supporting merge and other special states
timothy@home:~/(rebase|20eeb6f... (3 applied)).ssh!>
When git is in a special state (rebase or merge for git), branch %b
information should be replaced with “current state” %a
information. Also it’s a separate configuration string, actionformats
instead of familiar formats
one.
- Support special state:
zstyle ':vcs_info:*'
actionformats
'%R/(
%a
)%S%u%c'
- Add miscellaneous data in a special state:
zstyle ':vcs_info:*' actionformats '%R/(%a
|%m
)%S%u%c'
In git miscellaneous data is formatted as either %p (%n applied)
or no patch applied
(see /usr/share/zsh/$ZSH_VERSION/functions/VCS_INFO_get_data_git
). Where %p
is your full revision number e.g. 20eeb6fffcbb7260601af5181a6b4d5e46395c86
, which is too long for the command line prompt. To shorten it in zsh to only 7 digits of hash I use %10>...>%p%<<
instead, which roughly translates to: output %p
, no longer than 10 symbols, shorten with ...
string on the right side. %<<
at the end is a marker for a string that should be 10 symbols long. See Conditional Substrings in Prompts for more details.
- Shorten revision number during rebase:
zstyle ':vcs_info:git:*' patch-format '%10>...>%p%<< (%n applied)'
Use ~
for the home directory once again
timothy@home:~/(master).ssh!>
When we switched from zsh’s default %~
to git-specific %R
we lost support for showing ~
instead of a home directory, let’s get it back!
zstyle ':vcs_info:*+set-message:*' hooks home-path
function +vi-home-path() {
autoload -U regexp-replace
hook_com[base]="${hook_com[base]/$HOME/~}"
}
Making it look nicer!
timothy@home:~/(master).ssh●⟫
zsh supports colors, of course, but they are very verbose: %{
%F{red}
%} red text %{
%f
%}
. Other colors: black
, red
, green
, yellow
, blue
, magenta
, cyan
and white
. Bold text is also supported: %{
%B
%} bold text %{
%b
%}
. It’s recommended to use %{
%E
%}
to reset colors right before the end of your prompt. Check Visual Effects for more info.
And, almost certainly UTF-8 is supported on your terminal so feel free to use Unicode symbols as well.
- Example of
stagedstr
after making it nicer:zstyle ':vcs_info:*' stagedstr '%{
%F{green}%B%}
●
%{
%b%f%}
.
That’s it! Now you know everything you have to know to craft your own vcs_info
-based prompt.
Good luck!