Coder Social home page Coder Social logo

git-prompt.zsh's Introduction

A fast, customizable, pure-shell, asynchronous Git prompt for Zsh. It is heavily inspired by Olivier Verdier's zsh-git-prompt and very similar to the "Informative VCS" prompt of fish shell.

Prompt Structure

The structure of the prompt (in the default configuration) is the following:

[<branch_name><upstream><tracking_status>|<local_status>]
  • branch_name: Name of the current branch or commit hash if HEAD is detached. When in 'detached HEAD' state, the branch_name will be prefixed with a colon : to indicate that it is actually a hash and not a branch name.
  • upstream: Name of the remote branch if it exist. Must be enabled explicitly (see Enable remote branch info).
  • tracking_status:
    • ↑n: ahead of remote by n commits
    • ↓n: behind remote by n commits
    • ↓m↑n: branches diverged; other by m commits, yours by n commits
  • local_status:
    • : repository is clean
    • ✖n: there are n unmerged files
    • ●n: there are n staged files
    • ✚n: there are n unstaged and changed files
    • …n: there are n untracked files
    • ⚑n: there are n entries on the stash (disabled by default)

Installation

Dependencies

  • Git with --porcelain=v2 support, which is available since version 2.11.0. You can check if your installation is compatible by executing git status --branch --porcelain=v2 inside a Git repository.
  • awk, which is most certainly preinstalled on any *nix system

Manual installation

Clone this repo or download the git-prompt.zsh file. Then source it in your .zshrc. For example:

mkdir -p ~/.zsh
git clone --depth=1 https://github.com/woefe/git-prompt.zsh ~/.zsh/git-prompt.zsh
echo "source ~/.zsh/git-prompt.zsh/git-prompt.zsh" >> .zshrc

# Optional: install an example configuration
echo "source ~/.zsh/git-prompt.zsh/examples/pure.zsh" >> .zshrc

Either install the default prompt (see Examples section below) with

# Installs the "default" example
zplug "woefe/git-prompt.zsh"

or choose an example prompt with

# Installs the "multiline" example
zplug "woefe/git-prompt.zsh", use:"{git-prompt.zsh,examples/multiline.zsh}"
zplugin ice atload'!_zsh_git_prompt_precmd_hook' lucid
zplugin load woefe/git-prompt.zsh

Note that this method does not work if you want to disable the asynchronous rendering.

Arch Linux

Install git-prompt.zsh or git-prompt.zsh-git from the AUR. Maintained by Felixoid.

FreeBSD

Install the git-prompt.zsh package with

pkg install git-prompt.zsh

Customization

Unlike other popular prompts this prompt does not use promptinit, which gives you the flexibility to build your own prompt from scratch. You can build a custom prompt by setting the PROMPT variable in your .zshrc after souring the git-prompt.zsh. And you should use '$(gitprompt)' in your PROMPT to get the Git prompt. You must set your PROMPT with single quotes, not double quotes, otherwise the Git prompt will not update properly. Some example PROMPT configurations are given below. You can find more information on how to configure the PROMPT in Zsh's online documentation or the zshmisc manpage, section "SIMPLE PROMPT ESCAPES".

Examples

See examples/README.md for more details.

Enable secondary prompt

The prompt comes with a secondary function that shows the tags that HEAD points to. Enabling this will execute another Git command every time a new prompt is shown! To use the secondary prompt you have to enable it and add the 'gitprompt_secondary' function to your PROMPT or RPROMPT variables. You enable the secondary prompt by adding the following line to your .zshrc:

ZSH_GIT_PROMPT_ENABLE_SECONDARY=1

The secondary prompt uses the label emoji by default. If you encounter problems with the label character, change it (see below) or install a font that can display it, for example Unifont or twemoji.

Appearance

The appearance of the prompt can be adjusted by changing the variables that start with ZSH_THEME_GIT_PROMPT_. Note that some of them are named differently than in the original Git prompt by Olivier Verdier.

You can preview your configuration by setting the ZSH_THEME_GIT_PROMPT_* variables in a running shell. But remember to save them in your .zshrc after you tweaked them to your liking! Example snippet from .zshrc:

# Theming variables for primary prompt
ZSH_THEME_GIT_PROMPT_PREFIX="["
ZSH_THEME_GIT_PROMPT_SUFFIX="] "
ZSH_THEME_GIT_PROMPT_SEPARATOR="|"
ZSH_THEME_GIT_PROMPT_DETACHED="%{$fg_bold[cyan]%}:"
ZSH_THEME_GIT_PROMPT_BRANCH="%{$fg_bold[magenta]%}"
ZSH_THEME_GIT_PROMPT_UPSTREAM_SYMBOL="%{$fg_bold[yellow]%}⟳ "
ZSH_THEME_GIT_PROMPT_UPSTREAM_NO_TRACKING="%{$fg_bold[red]%}!"
ZSH_THEME_GIT_PROMPT_UPSTREAM_PREFIX="%{$fg[red]%}(%{$fg[yellow]%}"
ZSH_THEME_GIT_PROMPT_UPSTREAM_SUFFIX="%{$fg[red]%})"
ZSH_THEME_GIT_PROMPT_BEHIND=""
ZSH_THEME_GIT_PROMPT_AHEAD=""
ZSH_THEME_GIT_PROMPT_UNMERGED="%{$fg[red]%}✖"
ZSH_THEME_GIT_PROMPT_STAGED="%{$fg[green]%}●"
ZSH_THEME_GIT_PROMPT_UNSTAGED="%{$fg[red]%}✚"
ZSH_THEME_GIT_PROMPT_UNTRACKED=""
ZSH_THEME_GIT_PROMPT_STASHED="%{$fg[blue]%}⚑"
ZSH_THEME_GIT_PROMPT_CLEAN="%{$fg_bold[green]%}✔"

# Theming variables for the secondary prompt
ZSH_THEME_GIT_PROMPT_SECONDARY_PREFIX=""
ZSH_THEME_GIT_PROMPT_SECONDARY_SUFFIX=""
ZSH_THEME_GIT_PROMPT_TAGS_SEPARATOR=", "
ZSH_THEME_GIT_PROMPT_TAGS_PREFIX="🏷 "
ZSH_THEME_GIT_PROMPT_TAGS_SUFFIX=""
ZSH_THEME_GIT_PROMPT_TAG="%{$fg_bold[magenta]%}"
source path/to/git-prompt.zsh

Enable remote branch info

The prompt will show information about the remote branch, if ZSH_GIT_PROMPT_SHOW_UPSTREAM is set to full or symbol. The full option will print the full remote branch name enclosed by ZSH_THEME_GIT_PROMPT_UPSTREAM_PREFIX and ZSH_THEME_GIT_PROMPT_UPSTREAM_SUFFIX. The symbol option prints only ZSH_THEME_GIT_PROMPT_UPSTREAM_SYMBOL.

Furthermore, a warning symbol can be configured through ZSH_THEME_GIT_PROMPT_UPSTREAM_NO_TRACKING for the case where no remote is available. ZSH_THEME_GIT_PROMPT_UPSTREAM_NO_TRACKING can be set independently of ZSH_GIT_PROMPT_SHOW_UPSTREAM.

Show stash entries

If ZSH_GIT_PROMPT_SHOW_STASH is set, the prompt will display a symbol and the number of stash entries when there are entries in the stash. On Git versions older than 2.35.0 this will execute another Git command every time a new prompt is shown! To enable stash entries add the following line to your .zshrc:

ZSH_GIT_PROMPT_SHOW_STASH=1

Disable display of numbers

By default, the prompt will show counts for each item in the tracking status and local status sections (see Prompt Structure for details about these sections). However, you can disable the display of counts for either or both sections of the prompt using ZSH_GIT_PROMPT_SHOW_TRACKING_COUNTS and ZSH_GIT_PROMPT_SHOW_LOCAL_COUNTS. If you unset these variables or set them to 0, then only the symbols will be shown but not the counts. For example, a prompt such as [master|✚2] will become [master|✚] instead.

Force blank

Since the prompt is asynchronous by default, the Git status updates slightly delayed. This has the benefit that the prompt will always be responsive even if the repository is huge and/or your disk is slow. But it also means that the old status will be displayed for some time. You can force the prompt to blank out instead of displaying a potentially outdated status, but be warned that this will probably increase flickering. Set the following variable in your .zshrc to enable this behavior:

ZSH_GIT_PROMPT_FORCE_BLANK=1

Disable async

If you are not happy with the asynchronous behavior, you can disable it altogether. But be warned that this can make your shell painfully slow if you enter large repositories or if your disk is slow. Set the following variable in your .zshrc before sourcing the git-prompt.zsh to enable this behavior.

ZSH_GIT_PROMPT_NO_ASYNC=1

ZSH_GIT_PROMPT_NO_ASYNC cannot be adjusted in a running shell, but only in your .zshrc.

Change the awk implementation

Some awk implementations are faster than others. By default, the prompt checks for nawk and then mawk and then falls back to the system's default awk. You can override this behavior by setting ZSH_GIT_PROMPT_AWK_CMD to the awk implementation of you liking before sourcing the git-prompt.zsh. ZSH_GIT_PROMPT_AWK_CMD cannot be adjusted in a running shell, but only in your .zshrc.

To benchmark an awk implementation you can use the following command.

# This example tests the default awk. You should change it to something else.
time ZSH_GIT_PROMPT_AWK_CMD=awk zsh -f -c '
    source path/to/git-prompt.zsh
    for i in $(seq 1000); do
        print -P $(_zsh_git_prompt_git_status)
    done'

Features / Non-Features

  • A pure shell implementation using awk; no Python, no Haskell required
  • Only the Git status. This prompt basically only gives you the gitprompt function, which you can use to build your own prompt. If you are looking for something more complete and blazing fast, I can recommend powerlevel10k.
  • Uses standard Git, no external Git status daemon (like gitstatus) required
  • Fast; Git command is invoked only once and asynchronously when a new prompt is drawn
  • No caching feature, because it breaks reliable detection of untracked files

Known issues

  • If the current working directory is not a Git repository and some external application initializes a new repository in the same directory, the Git prompt will not be shown immediately. Also, updates made by external programs or another shell do not show up immediately. Executing any command or simply pressing enter to draw a new prompt will fix the issue.
  • In large repositories the prompt might slow down, because Git has to find untracked files. See man git-status, Section --untracked-files for possible options to speed things up.

git-prompt.zsh's People

Contributors

jehops avatar jerrywdlee avatar mcornella avatar telemachus avatar woefe avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

git-prompt.zsh's Issues

Do you accept new themes?

Hi!

This is not really an issue. I'm coming from bash-git-prompt. I'm starting in zsh and i was missing this feature and, finally, i found this amazing plugin. With some changes, i've converted the multiline theme into something similar to bash-git-prompt.

~/Sites/myproject [master ⟳ ↓2↑4+1|✔]
09:53 $

Are you interested to add this as an example?

Thanks in advance!

A new release?

Hello. It looks like it is worth spinning a new release, there's been some useful changes since 2.3.0

Optional async for functions zle-line-init and zle-keymap-select

Hey, Wolfgang.

After the recent update of the plugin to v2.0.0 the $(gitprompt) has stopped working after the command execution. It works only after vim mode switching. That's a screenshot of what do I mean:
screen_2019-05-19_13-16-37_window

Here is my functions

Maybe is it still would be an option to disable async? Or do you have an idea about how to handle it properly in my case?

upd: I've already tried to replace GIT_STATUS with gitprompt in PS1, didn't help:

diff --git a/tag-zsh/zshrc b/tag-zsh/zshrc
index d3785db..a6342b4 100644
--- a/tag-zsh/zshrc
+++ b/tag-zsh/zshrc
@@ -25,6 +25,10 @@ if [ -r ~/.config/zsh/git-prompt.zsh ]; then
   source ~/.config/zsh/git-prompt.zsh
   _GIT_PROMPT_ENABLED=true
   ZSH_GIT_PROMPT_SHOW_STASH=true
+else
+  gitprompt() {
+    :
+  }
 fi
 
 function zle-line-init zle-keymap-select {
@@ -37,12 +41,11 @@ function zle-line-init zle-keymap-select {
     local USER_PROMPT="%F{$USER_FG}%n%f@%F{$HOST_FG}%m%f"
     [ "${SSH_CLIENT}" ] && local SSH_PROMPT="%F{yellow}[ssh from ${SSH_CLIENT%% *}]%f "
     [ "${VIRTUAL_ENV}" ] && local VENV="%F{green}venv=($(basename $VIRTUAL_ENV))%f "
-    [ "${_GIT_PROMPT_ENABLED}" ] && local GIT_STATUS="$(gitprompt) "
     case $KEYMAP in
       viins|main) local VI="%F{2}%(!.#.>)$(prompt_char)>%f" ;;
       vicmd)      local VI="%F{3}<$(prompt_char)%(!.#.<)%f" ;;
     esac
-    export PS1="┌%(?..%F{1})[%D{%H:%M:%S}]%f %(!.${ROOT_PROMPT}.${USER_PROMPT}):%~ ${VENV}${SSH_PROMPT}${GIT_STATUS}"$'\n'"└${VI} "
+    export PS1="┌%(?..%F{1})[%D{%H:%M:%S}]%f %(!.${ROOT_PROMPT}.${USER_PROMPT}):%~ ${VENV}${SSH_PROMPT}$(gitprompt)"$'\n'"└${VI} "
     RPROMPT="%(?..%F{1}[e:%?]%f)"
     zle reset-prompt
     # this line fixes the issue with errasing last line in vim mode by Alt+A or Alt+I

stopped working after async

It sounds great that you are adding async functionality!

Unfortunately, after I upgrade to latest, my git prompt disappears. The gitprompt command no longer gives any output.

If do a git reset --hard v1.0.0 then everything starts working again. It is specifically commit 31d715d that breaks it for me.

I figured out that I'm supposed to install zsh-async, and I have done so, but it does not repair the problem.

So something in the latest commits broke it for me.

Is there anything I can do to troubleshoot it?

I don't think it is relevant, but I install both zsh-async and git-prompt using zplug, like so:

zplug "mafredri/zsh-async", from:"github", use:"async.zsh"
zplug "woefe/git-prompt.zsh", from:github, as:plugin, use:git-prompt.zsh

zpty gives some output:

 > zpty
(73376) git_prompt_worker: _async_worker -p 72994

I've tried to analyze what happens with echo statements and it looks like neither _zsh_git_prompt_git_status nor _zsh_git_prompt_callback is ever called.

Calling _zsh_git_prompt_git_status manually results in an output that looks like a correct prompt.

$_ZSH_GIT_PROMPT_STATUS_OUTPUT is never set.

I'm on macOS Mojave 10.14.3, zsh 5.7.1, git hash a1221c of git-prompt.zsh

Ctrl+C doesn't move to a new line until I type.

I assume that this is probably a matter of changing a setting that I'm missing, but here's the issue:
In a standard terminal, if I hit Ctrl+C 5 times, it will make 5 new lines like it does when enter is pressed. With this prompt, there is no change until I type again, and then I only get 1 new line. I assumed it was an async thing, but changing ZSH_GIT_PROMPT_NO_ASYNC had no effect on that. Is there a way to change this behavior?

Tag name

This is an idea for a potential feature enhancement.

Sometimes I have a tag checked out which results in a prompt like

[:ab18db6|✔] ❯

Running git tag --points-at shows

  foo-3.8.1-CR1
  foo-3.8.1-CR2

Now this would completely clutter the left hand prompt if it was placed there so one possibility is an optional extra feature that would enable e.g. gitrprompt which would return the list of tags (if any) suitable for embedding inside the RPROMPT.
For example - as a non-async example:

        function git_tag_display()
        {
            local tags="$([[ -d .git ]] && git tag --points-at | awk '{ printf("%s", NR == 1 ? $0 : ","$0); }')"
            [[ -n "$tags" ]] && echo "%{$fg_bold[magenta]%}$ZSH_THEME_GIT_PROMPT_PREFIX$tags$ZSH_THEME_GIT_PROMPT_SUFFIX"
        }

Which I then use inside

function prompt_updater ()
        {
            # Prompt turns red if the previous command didn't exit with 0
            PROMPT="$(gitprompt)$PROMPT_JAVA$PROMPT_EXTRA $PROMPT_HAT%(?.%B%F{magenta}.%F{red})${PROMPT_SYMBOL}%f%b "
            RPROMPT="%{"$'\e[0;35m'"%}$((( ${+VIRTUAL_ENV} )) && basename $VIRTUAL_ENV)$(git_tag_display)%{"$'\e[00m%}'" %T"
        }

Obviously it would be better if git_tag_display was async and integrated into the tool :-)

Question: a global option not to show counts?

First and foremost, thank you. This is an outstanding prompt and very easy to work with.

Now my question: would you consider a pull request that adds a global option to disable showing counts? (I'm thinking something like ZSH_GIT_PROMPT_DISABLE_COUNTS, but I'm happy to take suggestions about names.) The idea is that if the option is turned on, then things like staged, unstaged, and untracked would show their symbol but not a count.

Prompt cursor moved to the left

This problem is similar to #8

But tmux is not necessary. This happens when I SSH into a Raspberry PI.

When I let the git status show in RPROMPT, and it shows a unicode character, the prompt cursor is moved two steps to the left, so that it overlaps the left prompt.

Workaround is to replace the unicode characters with ordinary characters.

alias echo breaks git prompt

putting alias echo="something else" in your aliasrc breaks git-prompt. It shouldn't be doing alias expansion...

Test case:
Install plan9port
alias echo="9 echo"

It breaks by printing colour codes literally, with the test case.

Release the soft

Hello Wolfgang.

Thank you for an awesome pure-shell solution! It works very well and allows to make portable solutions like Felixoid/dotfiles@151d343.

Btw, I've maintained a git version of a package for Arch linux user repository and would like to create a normal one as well. I'll appreciate if you create release tags, which is necessary for the usual package.

Cannot run git commands whilst prompt is being generated

Running a git command whilst the prompt is still being generated in the background can lead to errors such as "fatal: Unable to create '.../.git/index.lock': File exists."

Is there a possibility to terminate the background process as soon as a command is run, or to solve this in some other way?

A lot of the benefit of this lovely prompt is lost if you have to remember not to run any git commands until the prompt has been generated.

Support for plugin managers and streamline installation

Disclaimer: I do not use a plugin manager for Zsh myself and have no idea how they handle plugins. Do they require a special directory layout etc? Let me know below what has to be done for the plugin manager of you choice. Also, PRs are welcome

Space in prompt

Hello. Can you consider an option to disable the space at the end of the prompt?

move away from zsh-async

Some issues came up with the current async implementation:

  • The async worker seems to crash sometimes:
    async_job:zpty:12: no such pty command: git_prompt_worker
    
  • Adds a dependency to zsh-async. The external dependency is harder to package (e.g. in an AUR package)
  • Might not work on every platform or in every scenario

zsh-users/zsh-autosuggestions uses an implementation without zpty and zsh-async.

Add remote branch name

If there is demand for it, the name of the remote and branch could be added to the prompt. E.g. [ remote/remotebranchname localbranchname ↓2↑3| ...]

Implementing this should be fairly straightforward, because git status already outputs this information. It is just a matter of parsing it and adding code to optionally show it.

Extra space added after prompt when using tmux

Hello Wolfgang,

With this simple recipe, an extra space is added after the prompt when a tmux session is attached and $PWD is a Git repository. This is with an empty tmux configuration and only these two lines in ~/.zshrc.

>  cat ~/.zshrc
source /usr/local/share/git-prompt.zsh/git-prompt.zsh
PROMPT='$(gitprompt)> '
  1. start terminal application (prompt has one space after >)
  2. cd some_git_repo (prompt shows git status and still one space after >)
  3. cd ~/
  4. tmux (prompt still shows one space after > )
  5. cd some_git_repo (prompt now shows two spaces after >)
> uname -a
FreeBSD phe.ftfl.ca 12.0-RELEASE-p3 FreeBSD 12.0-RELEASE-p3 GENERIC  amd64

> pkg info -q | grep '^zsh-[0-9]\|^git-[0-9]' 
git-2.21.0
zsh-5.7.1

Thanks for creating git-prompt.zsh. The asynchronous Git status is nice.

100% CPU load when async is on

Hi,

I've noticed that every zsh process currently displaying a prompt is at 100% CPU load when using git-prompt. This does not happen when setting ZSH_GIT_PROMPT_NO_ASYNC=1

I'm using master (5d4d63d) and zsh 5.0.2

Only right side status is needed

I would like to show only git status at the right side of prompt line, but it overrides original prompt also. It seems following part of the script overrides PROMPT. Is it possible to add new option to choose whether override PROMPT or not?

# Override PROMPT if it does not use the gitprompt function
[[ "$PROMPT" != *gitprompt* && "$RPROMPT" != *gitprompt* ]] \
    && PROMPT='%B%40<..<%~ %b$(gitprompt)' \
    && PROMPT+='%(?.%(!.%F{white}❯%F{yellow}❯%F{red}.%F{blue}❯%F{cyan}❯%F{g    reen})❯.%F{red}❯❯❯)%f '

Branch info does't show

after install, the Branch info does't show under the git repo

git version 2.11.0
zsh 5.3.1 (x86_64-debian-linux-gnu)

image

Add option to change awk implementation

Some awk implementations are faster than others. There should be an option to change the implementation used by the prompt.

# with GNU awk
time zsh -f -c 'source git-prompt.zsh; for i in $(seq 1000); do print -P $(_zsh_git_prompt_git_status); done'
zsh -f -c   4.62s user 2.01s system 143% cpu 4.620 total

# And with nawk quite a bit faster
time zsh -f -c 'source git-prompt.zsh; for i in $(seq 1000); do print -P $(_zsh_git_prompt_git_status); done'
zsh -f -c   2.80s user 1.25s system 151% cpu 2.682 total

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.