Move __fish_git_prompt -> fish_git_prompt

This exposes it more, since it's quite an important function.

We should do the same with the other vcs functions.

We leave a compatibility shim in place for now.
This commit is contained in:
Fabian Homborg 2019-01-26 13:36:54 +01:00
parent 34fa8ef2d2
commit cb7762b7c0
4 changed files with 828 additions and 824 deletions

View File

@ -1,822 +1,4 @@
# based off of the git-prompt script that ships with git
#
# Written by Kevin Ballard <kevin@sb.org>
# Updated by Brian Gernhardt <brian@gernhardtsoftware.com>
#
# This is heavily based off of the git-prompt.bash script that ships with
# git, which is Copyright (C) 2006,2007 Shawn O. Pearce <spearce@spearce.org>.
# The act of porting the code, along with any new code, are Copyright (C) 2012
# Kevin Ballard <kevin@sb.org>.
#
# By virtue of being based on the git-prompt.bash script, this script is
# distributed under the GNU General Public License, version 2.0.
#
# This script vends a function __fish_git_prompt which takes a format string,
# exactly how the bash script works. This can be used in your fish_prompt
# function.
#
# The behavior of __fish_git_prompt is very heavily based off of the bash
# script's __git_ps1 function. As such, usage and customization is very
# similar, although some extra features are provided in this script.
# Due to differences between bash and fish, the PROMPT_COMMAND style where
# passing two or three arguments causes the fucnction to set PS1 is not
# supported. More information on the additional features is found after the
# bash-compatable documentation.
#
# The argument to __fish_git_prompt will be displayed only if you are currently
# in a git repository. The %s token will be the name of the branch.
#
# In addition, if you set __fish_git_prompt_showdirtystate to a nonempty value,
# unstaged (*) and staged (+) changes will be shown next to the branch name.
# You can configure this per-repository with the bash.showDirtyState variable,
# which defaults to true once __fish_git_prompt_showdirtystate is enabled. The
# choice to leave the variable as 'bash' instead of renaming to 'fish' is done
# to preserve compatibility with existing configured repositories.
#
# You can also see if currently something is stashed, by setting
# __fish_git_prompt_showstashstate to a nonempty value. If something is
# stashed, then a '$' will be shown next to the branch name.
#
# If you would like to see if there are untracked files, then you can set
# __fish_git_prompt_showuntrackedfiles to a nonempty value. If there are
# untracked files, then a '%' will be shown next to the branch name. Once you
# have set __fish_git_prompt_showuntrackedfiles, you can override it on a
# per-repository basis by setting the bash.showUntrackedFiles config variable.
# As before, this variable remains named 'bash' to preserve compatibility.
#
# If you would like to see the difference between HEAD and its upstream, set
# __fish_git_prompt_showupstream to 'auto'. A "<" indicates you are behind, ">"
# indicates you are ahead, "<>" indicates you have diverged and "=" indicates
# that there is no difference. You can further control behavior by setting
# __fish_git_prompt_showupstream to a space-separated list of values:
#
# verbose show number of commits ahead/behind (+/-) upstream
# name if verbose, then also show the upstream abbrev name
# informative similar to verbose, but shows nothing when equal (fish only)
# git always compare HEAD to @{upstream}
# svn always compare HEAD to your SVN upstream
# none disables (fish only, useful with show_informative_status)
#
# By default, __fish_git_prompt will compare HEAD to your SVN upstream if it
# can find one, or @{upstream} otherwise. Once you have set
# __fish_git_prompt_showupstream, you can override it on a per-repository basis
# by setting the bash.showUpstream config variable. As before, this variable
# remains named 'bash' to preserve compatibility.
#
# If you would like to see more information about the identity of commits
# checked out as a detached HEAD, set __fish_git_prompt_describe_style to
# one of the following values:
#
# contains relative to newer annotated tag (v1.6.3.2~35)
# branch relative to newer tag or branch (master~4)
# describe relative to older annotated tag (v1.6.3.1-13-gdd42c2f)
# default exactly matching tag
#
# If you would like a colored hint about the current dirty state, set
# __fish_git_prompt_showcolorhints. The default colors are
# based on the colored output of "git status -sb"
# __fish_git_prompt includes some additional features on top of the
# above-documented bash-compatible features:
#
#
# An "informative git prompt" mode similar to the scripts for bash and zsh
# can be activated by setting __fish_git_prompt_show_informative_status
# This works more like the "informative git prompt" scripts for bash and zsh,
# giving prompts like (master12|3456) where master is the current branch,
# you have 1 commit your upstream doesn't and it has 2 you don't, and you have
# 3 staged, 4 unmerged, 5 dirty, and 6 untracked files. If you have no
# changes, it displays (master|).
#
# Setting __fish_git_prompt_show_informative_status changes several defaults.
# The default mode for __fish_git_prompt_showupstream changes to informative
# and the following characters have their defaults changed. (The characters
# and colors can still be customized as described below.)
#
# upstream_prefix ()
# upstream_ahead ()
# upstream_behind ()
# stateseparator (|)
# dirtystate ()
# invalidstate ()
# stagedstate ()
# untrackedfiles ()
# cleanstate ()
#
#
# The color for each component of the prompt can specified using
# __fish_git_prompt_color_<name>, where <name> is one of the following and the
# values are specified as arguments to `set_color`. The variable
# __fish_git_prompt_color is used for any component that does not have an
# individual color set.
#
# prefix Anything before %s in the format string
# suffix Anything after %s in the format string
# bare Marker for a bare repository
# merging Current operation (|MERGING, |REBASE, etc.)
# branch Branch name
# flags Optional flags (see below)
# upstream Upstream name and flags (with showupstream)
#
#
# The following optional flags have both colors, as above, and custom
# characters via __fish_git_prompt_char_<name>. The default character is
# shown in parenthesis. The default color for these flags can be also be set
# via the __fish_git_prompt_color_flags variable.
#
# __fish_git_prompt_showdirtystate
# dirtystate unstaged changes (*)
# stagedstate staged changes (+)
# invalidstate HEAD invalid (#, colored as stagedstate)
#
# __fish_git_prompt_showstashstate
# stashstate stashed changes ($)
#
# __fish_git_prompt_showuntrackedfiles
# untrackedfiles untracked files (%)
#
# __fish_git_prompt_showupstream (all colored as upstream)
# upstream_equal Branch matches upstream (=)
# upstream_behind Upstream has more commits (<)
# upstream_ahead Branch has more commits (>)
# upstream_diverged Upstream and branch have new commits (<>)
#
# __fish_git_prompt_show_informative_status
# (see also the flags for showdirtystate and showuntrackedfiles, above)
# cleanstate Working directory has no changes ()
#
#
# The separator between the branch name and flags can also be customized via
# __fish_git_prompt_char_stateseparator. It can only be colored by
# __fish_git_prompt_color. It normally defaults to a space ( ) and defaults
# to a vertical bar (|) when __fish_git_prompt_show_informative_status is set.
#
# The separator before the upstream information can be customized via
# __fish_git_prompt_char_upstream_prefix. It is colored like the rest of
# the upstream information. It normally defaults to nothing () and defaults
# to a space ( ) when __fish_git_prompt_showupstream contains verbose.
#
#
# Turning on __fish_git_prompt_showcolorhints changes the colors as follows to
# more closely match the behavior in bash. Note that setting any of these
# colors manually will override these defaults.
#
# branch Defaults to green
# branch_detached New color, when head is detached, default red
# dirtystate Defaults to red
# stagedstate Defaults to green
# flags Defaults to --bold blue
#
#
# The branch name could be shorten via
# __fish_git_prompt_shorten_branch_len. Define the branch max len.
# __fish_git_prompt_shorten_branch_char_suffix. Customize suffixed char of shorten branch. Defaults to ().
function __fish_git_prompt_show_upstream --description "Helper function for __fish_git_prompt"
set -q __fish_git_prompt_showupstream
or set -l __fish_git_prompt_showupstream
set -l show_upstream $__fish_git_prompt_showupstream
set -l svn_prefix # For better SVN upstream information
set -l informative
set -l svn_url_pattern
set -l count
set -l upstream git
set -l verbose
set -l name
# Default to informative if __fish_git_prompt_show_informative_status is set
if set -q __fish_git_prompt_show_informative_status
set informative 1
end
set -l svn_remote
# get some config options from git-config
command git config -z --get-regexp '^(svn-remote\..*\.url|bash\.showupstream)$' 2>/dev/null | while read -lz key value
switch $key
case bash.showupstream
set show_upstream $value
test -n "$show_upstream"
or return
case svn-remote.'*'.url
set svn_remote $svn_remote $value
# Avoid adding \| to the beginning to avoid needing #?? later
if test -n "$svn_url_pattern"
set svn_url_pattern $svn_url_pattern"|$value"
else
set svn_url_pattern $value
end
set upstream svn+git # default upstream is SVN if available, else git
# Save the config key (without .url) for later use
set -l remote_prefix (string replace -r '\.url$' '' -- $key)
set svn_prefix $svn_prefix $remote_prefix
end
end
# parse configuration variables
# and clear informative default when needed
for option in $show_upstream
switch $option
case git svn
set upstream $option
set -e informative
case verbose
set verbose 1
set -e informative
case informative
set informative 1
case name
set name 1
case none
return
end
end
# Find our upstream
switch $upstream
case git
set upstream '@{upstream}'
case svn\*
# get the upstream from the 'git-svn-id: …' in a commit message
# (git-svn uses essentially the same procedure internally)
set -l svn_upstream (git log --first-parent -1 --grep="^git-svn-id: \($svn_url_pattern\)" 2>/dev/null)
if test (count $svn_upstream) -ne 0
echo $svn_upstream[-1] | read -l __ svn_upstream __
set svn_upstream (string replace -r '@.*' '' -- $svn_upstream)
set -l cur_prefix
for i in (seq (count $svn_remote))
set -l remote $svn_remote[$i]
set -l mod_upstream (string replace "$remote" "" -- $svn_upstream)
if test "$svn_upstream" != "$mod_upstream"
# we found a valid remote
set svn_upstream $mod_upstream
set cur_prefix $svn_prefix[$i]
break
end
end
if test -z "$svn_upstream"
# default branch name for checkouts with no layout:
if test -n "$GIT_SVN_ID"
set upstream $GIT_SVN_ID
else
set upstream git-svn
end
else
set upstream (string replace '/branches' '' -- $svn_upstream | string replace -a '/' '')
# Use fetch config to fix upstream
set -l fetch_val (command git config "$cur_prefix".fetch)
if test -n "$fetch_val"
string split -m1 : -- "$fetch_val" | read -l trunk pattern
set upstream (string replace -r -- "/$trunk\$" '' $pattern) /$upstream
end
end
else if test $upstream = svn+git
set upstream '@{upstream}'
end
end
# Find how many commits we are ahead/behind our upstream
set count (command git rev-list --count --left-right $upstream...HEAD 2>/dev/null)
# calculate the result
if test -n "$verbose"
# Verbose has a space by default
set -l prefix "$___fish_git_prompt_char_upstream_prefix"
# Using two underscore version to check if user explicitly set to nothing
if not set -q __fish_git_prompt_char_upstream_prefix
set -l prefix " "
end
echo $count | read -l behind ahead
switch "$count"
case '' # no upstream
case "0 0" # equal to upstream
echo "$prefix$___fish_git_prompt_char_upstream_equal"
case "0 *" # ahead of upstream
echo "$prefix$___fish_git_prompt_char_upstream_ahead$ahead"
case "* 0" # behind upstream
echo "$prefix$___fish_git_prompt_char_upstream_behind$behind"
case '*' # diverged from upstream
echo "$prefix$___fish_git_prompt_char_upstream_diverged$ahead-$behind"
end
if test -n "$count" -a -n "$name"
echo " "(command git rev-parse --abbrev-ref "$upstream" 2>/dev/null)
end
else if test -n "$informative"
echo $count | read -l behind ahead
switch "$count"
case '' # no upstream
case "0 0" # equal to upstream
case "0 *" # ahead of upstream
echo "$___fish_git_prompt_char_upstream_prefix$___fish_git_prompt_char_upstream_ahead$ahead"
case "* 0" # behind upstream
echo "$___fish_git_prompt_char_upstream_prefix$___fish_git_prompt_char_upstream_behind$behind"
case '*' # diverged from upstream
echo "$___fish_git_prompt_char_upstream_prefix$___fish_git_prompt_char_upstream_ahead$ahead$___fish_git_prompt_char_upstream_behind$behind"
end
else
switch "$count"
case '' # no upstream
case "0 0" # equal to upstream
echo "$___fish_git_prompt_char_upstream_prefix$___fish_git_prompt_char_upstream_equal"
case "0 *" # ahead of upstream
echo "$___fish_git_prompt_char_upstream_prefix$___fish_git_prompt_char_upstream_ahead"
case "* 0" # behind upstream
echo "$___fish_git_prompt_char_upstream_prefix$___fish_git_prompt_char_upstream_behind"
case '*' # diverged from upstream
echo "$___fish_git_prompt_char_upstream_prefix$___fish_git_prompt_char_upstream_diverged"
end
end
end
function __fish_git_prompt --description "Prompt function for Git"
# If git isn't installed, there's nothing we can do
# Return 1 so the calling prompt can deal with it
if not command -sq git
return 1
end
set -l repo_info (command git rev-parse --git-dir --is-inside-git-dir --is-bare-repository --is-inside-work-tree HEAD 2>/dev/null)
test -n "$repo_info"
or return
set -l git_dir $repo_info[1]
set -l inside_gitdir $repo_info[2]
set -l bare_repo $repo_info[3]
set -l inside_worktree $repo_info[4]
set -q repo_info[5]
and set -l sha $repo_info[5]
set -l rbc (__fish_git_prompt_operation_branch_bare $repo_info)
set -l r $rbc[1] # current operation
set -l b $rbc[2] # current branch
set -l detached $rbc[3]
set -l w #dirty working directory
set -l i #staged changes
set -l s #stashes
set -l u #untracked
set -l c $rbc[4] # bare repository
set -l p #upstream
set -l informative_status
if not set -q ___fish_git_prompt_init
# This takes a while, so it only needs to be done once,
# and then whenever the configuration changes.
__fish_git_prompt_validate_chars
__fish_git_prompt_validate_colors
set -g ___fish_git_prompt_init
end
set -l space "$___fish_git_prompt_color$___fish_git_prompt_char_stateseparator$___fish_git_prompt_color_done"
# Use our variables as defaults, but allow overrides via the local git config.
# That means if neither is set, this stays empty.
#
# So "!= true" or "!= false" are useful tests if you want to do something by default.
set -l informative (command git config --bool bash.showInformativeStatus)
set -l dirty (command git config --bool bash.showDirtyState)
if not set -q dirty[1]
set -q __fish_git_prompt_showdirtystate
and set dirty true
end
set -l untracked (command git config --bool bash.showUntrackedFiles)
if not set -q untracked[1]
set -q __fish_git_prompt_showuntrackedfiles
and set untracked true
end
if test "true" = $inside_worktree
# Use informative status if it has been enabled locally, or it has been
# enabled globally (via the fish variable) and dirty or untracked are not false.
#
# This is to allow overrides for the repository.
if test "$informative" = true
or begin
set -q __fish_git_prompt_show_informative_status
and test "$dirty" != false
and test "$untracked" != false
end
set informative_status "$space"(__fish_git_prompt_informative_status)
else
# This has to be set explicitly.
if test "$dirty" = true
set w (__fish_git_prompt_dirty)
set i (__fish_git_prompt_staged $sha)
end
if set -q __fish_git_prompt_showstashstate
and test -r $git_dir/refs/stash
set s $___fish_git_prompt_char_stashstate
end
if test "$untracked" != true
set u (__fish_git_prompt_untracked)
end
end
if set -q __fish_git_prompt_showupstream
or set -q __fish_git_prompt_show_informative_status
set p (__fish_git_prompt_show_upstream)
end
end
set -l branch_color $___fish_git_prompt_color_branch
set -l branch_done $___fish_git_prompt_color_branch_done
if set -q __fish_git_prompt_showcolorhints
if test $detached = yes
set branch_color $___fish_git_prompt_color_branch_detached
set branch_done $___fish_git_prompt_color_branch_detached_done
end
end
if test -n "$w"
set w "$___fish_git_prompt_color_dirtystate$w$___fish_git_prompt_color_dirtystate_done"
end
if test -n "$i"
set i "$___fish_git_prompt_color_stagedstate$i$___fish_git_prompt_color_stagedstate_done"
end
if test -n "$s"
set s "$___fish_git_prompt_color_stashstate$s$___fish_git_prompt_color_stashstate_done"
end
if test -n "$u"
set u "$___fish_git_prompt_color_untrackedfiles$u$___fish_git_prompt_color_untrackedfiles_done"
end
set b (string replace refs/heads/ '' -- $b)
set -q __fish_git_prompt_shorten_branch_char_suffix
or set -l __fish_git_prompt_shorten_branch_char_suffix "…"
if string match -qr '^\d+$' "$__fish_git_prompt_shorten_branch_len"; and test (string length "$b") -gt $__fish_git_prompt_shorten_branch_len
set b (string sub -l "$__fish_git_prompt_shorten_branch_len" "$b")"$__fish_git_prompt_shorten_branch_char_suffix"
end
if test -n "$b"
set b "$branch_color$b$branch_done"
end
if test -n "$c"
set c "$___fish_git_prompt_color_bare$c$___fish_git_prompt_color_bare_done"
end
if test -n "$r"
set r "$___fish_git_prompt_color_merging$r$___fish_git_prompt_color_merging_done"
end
if test -n "$p"
set p "$___fish_git_prompt_color_upstream$p$___fish_git_prompt_color_upstream_done"
end
# Formatting
set -l f "$w$i$s$u"
if test -n "$f"
set f "$space$f"
end
set -l format $argv[1]
if test -z "$format"
set format " (%s)"
end
printf "%s$format%s" "$___fish_git_prompt_color_prefix" "$___fish_git_prompt_color_prefix_done$c$b$f$r$p$informative_status$___fish_git_prompt_color_suffix" "$___fish_git_prompt_color_suffix_done"
end
### helper functions
function __fish_git_prompt_staged --description "__fish_git_prompt helper, tells whether or not the current branch has staged files"
set -l sha $argv[1]
set -l staged
if test -n "$sha"
command git diff-index --cached --quiet HEAD -- 2>/dev/null
or set staged $___fish_git_prompt_char_stagedstate
else
set staged $___fish_git_prompt_char_invalidstate
end
echo $staged
end
function __fish_git_prompt_untracked --description "__fish_git_prompt helper, tells whether or not the current repository has untracked files"
set -l untracked
if command git ls-files --others --exclude-standard --directory --no-empty-directory --error-unmatch -- :/ >/dev/null 2>&1
set untracked $___fish_git_prompt_char_untrackedfiles
end
echo $untracked
end
function __fish_git_prompt_dirty --description "__fish_git_prompt helper, tells whether or not the current branch has tracked, modified files"
set -l dirty
set -l os
command git diff --no-ext-diff --quiet --exit-code 2>/dev/null
set os $status
if test $os -ne 0
set dirty $___fish_git_prompt_char_dirtystate
end
echo $dirty
end
set -g ___fish_git_prompt_status_order stagedstate invalidstate dirtystate untrackedfiles
function __fish_git_prompt_informative_status
set -l changedFiles (command git diff --name-status 2>/dev/null | string match -r \\w)
set -l stagedFiles (command git diff --staged --name-status | string match -r \\w)
set -l x (count $changedFiles)
set -l y (count (string match -r "U" -- $changedFiles))
set -l dirtystate (math $x - $y)
set -l x (count $stagedFiles)
set -l invalidstate (count (string match -r "U" -- $stagedFiles))
set -l stagedstate (math $x - $invalidstate)
set -l untrackedfiles (command git ls-files --others --exclude-standard | wc -l | string trim)
set -l info
# If `math` fails for some reason, assume the state is clean - it's the simpler path
set -l state (math $dirtystate + $invalidstate + $stagedstate + $untrackedfiles 2>/dev/null)
if test -z "$state"
or test "$state" = 0
set info $___fish_git_prompt_color_cleanstate$___fish_git_prompt_char_cleanstate$___fish_git_prompt_color_cleanstate_done
else
for i in $___fish_git_prompt_status_order
if [ $$i != "0" ]
set -l color_var ___fish_git_prompt_color_$i
set -l color_done_var ___fish_git_prompt_color_{$i}_done
set -l symbol_var ___fish_git_prompt_char_$i
set -l color $$color_var
set -l color_done $$color_done_var
set -l symbol $$symbol_var
set -l count
if not set -q __fish_git_prompt_hide_$i
set count $$i
end
set info "$info$color$symbol$count$color_done"
end
end
end
echo $info
end
# Keeping these together avoids many duplicated checks
function __fish_git_prompt_operation_branch_bare --description "__fish_git_prompt helper, returns the current Git operation and branch"
# This function is passed the full repo_info array
set -l git_dir $argv[1]
set -l inside_gitdir $argv[2]
set -l bare_repo $argv[3]
set -q argv[5]
and set -l sha $argv[5]
set -l branch
set -l operation
set -l detached no
set -l bare
set -l step
set -l total
set -l os
if test -d $git_dir/rebase-merge
set branch (cat $git_dir/rebase-merge/head-name 2>/dev/null)
set step (cat $git_dir/rebase-merge/msgnum 2>/dev/null)
set total (cat $git_dir/rebase-merge/end 2>/dev/null)
if test -f $git_dir/rebase-merge/interactive
set operation "|REBASE-i"
else
set operation "|REBASE-m"
end
else
if test -d $git_dir/rebase-apply
set step (cat $git_dir/rebase-apply/next 2>/dev/null)
set total (cat $git_dir/rebase-apply/last 2>/dev/null)
if test -f $git_dir/rebase-apply/rebasing
set branch (cat $git_dir/rebase-apply/head-name 2>/dev/null)
set operation "|REBASE"
else if test -f $git_dir/rebase-apply/applying
set operation "|AM"
else
set operation "|AM/REBASE"
end
else if test -f $git_dir/MERGE_HEAD
set operation "|MERGING"
else if test -f $git_dir/CHERRY_PICK_HEAD
set operation "|CHERRY-PICKING"
else if test -f $git_dir/REVERT_HEAD
set operation "|REVERTING"
else if test -f $git_dir/BISECT_LOG
set operation "|BISECTING"
end
end
if test -n "$step" -a -n "$total"
set operation "$operation $step/$total"
end
if test -z "$branch"
set branch (command git symbolic-ref HEAD 2>/dev/null; set os $status)
if test $os -ne 0
set detached yes
set branch (switch "$__fish_git_prompt_describe_style"
case contains
command git describe --contains HEAD
case branch
command git describe --contains --all HEAD
case describe
command git describe HEAD
case default '*'
command git describe --tags --exact-match HEAD
end 2>/dev/null; set os $status)
if test $os -ne 0
# Shorten the sha ourselves to 8 characters - this should be good for most repositories,
# and even for large ones it should be good for most commits
if set -q sha
set branch (string match -r '^.{8}' -- $sha)
else
set branch unknown
end
end
set branch "($branch)"
end
end
if test "true" = $inside_gitdir
if test "true" = $bare_repo
set bare "BARE:"
else
# Let user know they're inside the git dir of a non-bare repo
set branch "GIT_DIR!"
end
end
echo $operation
echo $branch
echo $detached
echo $bare
end
function __fish_git_prompt_set_char
set -l user_variable_name "$argv[1]"
set -l char $argv[2]
set -l user_variable
if set -q $user_variable_name
set user_variable $$user_variable_name
end
if set -q argv[3]
and set -q __fish_git_prompt_show_informative_status
set char $argv[3]
end
set -l variable _$user_variable_name
set -l variable_done "$variable"_done
if not set -q $variable
set -g $variable (set -q $user_variable_name; and echo $user_variable; or echo $char)
end
end
function __fish_git_prompt_validate_chars --description "__fish_git_prompt helper, checks char variables"
__fish_git_prompt_set_char __fish_git_prompt_char_cleanstate '✔'
__fish_git_prompt_set_char __fish_git_prompt_char_dirtystate '*' '✚'
__fish_git_prompt_set_char __fish_git_prompt_char_invalidstate '#' '✖'
__fish_git_prompt_set_char __fish_git_prompt_char_stagedstate '+' '●'
__fish_git_prompt_set_char __fish_git_prompt_char_stashstate '$'
__fish_git_prompt_set_char __fish_git_prompt_char_stateseparator ' ' '|'
__fish_git_prompt_set_char __fish_git_prompt_char_untrackedfiles '%' '…'
__fish_git_prompt_set_char __fish_git_prompt_char_upstream_ahead '>' '↑'
__fish_git_prompt_set_char __fish_git_prompt_char_upstream_behind '<' '↓'
__fish_git_prompt_set_char __fish_git_prompt_char_upstream_diverged '<>'
__fish_git_prompt_set_char __fish_git_prompt_char_upstream_equal '='
__fish_git_prompt_set_char __fish_git_prompt_char_upstream_prefix ''
end
function __fish_git_prompt_set_color
set -l user_variable_name "$argv[1]"
set -l user_variable
if set -q $user_variable_name
set user_variable $$user_variable_name
end
set -l user_variable_bright
set -l default default_done
switch (count $argv)
case 1 # No defaults given, use prompt color
set default $___fish_git_prompt_color
set default_done $___fish_git_prompt_color_done
case 2 # One default given, use normal for done
set default "$argv[2]"
set default_done (set_color normal)
case 3 # Both defaults given
set default "$argv[2]"
set default_done "$argv[3]"
end
set -l variable _$user_variable_name
set -l variable_done "$variable"_done
if not set -q $variable
if test -n "$user_variable"
set -g $variable (set_color $user_variable)
set -g $variable_done (set_color normal)
else
set -g $variable $default
set -g $variable_done $default_done
end
end
end
function __fish_git_prompt_validate_colors --description "__fish_git_prompt helper, checks color variables"
# Base color defaults to nothing (must be done first)
__fish_git_prompt_set_color __fish_git_prompt_color '' ''
# Normal colors
__fish_git_prompt_set_color __fish_git_prompt_color_prefix
__fish_git_prompt_set_color __fish_git_prompt_color_suffix
__fish_git_prompt_set_color __fish_git_prompt_color_bare
__fish_git_prompt_set_color __fish_git_prompt_color_merging
__fish_git_prompt_set_color __fish_git_prompt_color_cleanstate
__fish_git_prompt_set_color __fish_git_prompt_color_invalidstate
__fish_git_prompt_set_color __fish_git_prompt_color_upstream
# Colors with defaults with showcolorhints
if set -q __fish_git_prompt_showcolorhints
__fish_git_prompt_set_color __fish_git_prompt_color_flags (set_color --bold blue)
__fish_git_prompt_set_color __fish_git_prompt_color_branch (set_color green)
__fish_git_prompt_set_color __fish_git_prompt_color_dirtystate (set_color red)
__fish_git_prompt_set_color __fish_git_prompt_color_stagedstate (set_color green)
else
__fish_git_prompt_set_color __fish_git_prompt_color_flags
__fish_git_prompt_set_color __fish_git_prompt_color_branch
__fish_git_prompt_set_color __fish_git_prompt_color_dirtystate $___fish_git_prompt_color_flags $___fish_git_prompt_color_flags_done
__fish_git_prompt_set_color __fish_git_prompt_color_stagedstate $___fish_git_prompt_color_flags $___fish_git_prompt_color_flags_done
end
# Branch_detached has a default, but is only used with showcolorhints
__fish_git_prompt_set_color __fish_git_prompt_color_branch_detached (set_color red)
# Colors that depend on flags color
__fish_git_prompt_set_color __fish_git_prompt_color_stashstate $___fish_git_prompt_color_flags $___fish_git_prompt_color_flags_done
__fish_git_prompt_set_color __fish_git_prompt_color_untrackedfiles $___fish_git_prompt_color_flags $___fish_git_prompt_color_flags_done
end
set -l varargs
for var in repaint describe_style show_informative_status showdirtystate showstashstate showuntrackedfiles showupstream
set -a varargs --on-variable __fish_git_prompt_$var
end
function __fish_git_prompt_repaint $varargs --description "Event handler, repaints prompt when functionality changes"
if status --is-interactive
if test $argv[3] = __fish_git_prompt_show_informative_status
# Clear characters that have different defaults with/without informative status
for name in cleanstate dirtystate invalidstate stagedstate stateseparator untrackedfiles upstream_ahead upstream_behind
set -e ___fish_git_prompt_char_$name
end
end
commandline -f repaint 2>/dev/null
end
end
set -l varargs
for var in '' _prefix _suffix _bare _merging _cleanstate _invalidstate _upstream _flags _branch _dirtystate _stagedstate _branch_detached _stashstate _untrackedfiles
set -a varargs --on-variable __fish_git_prompt_color$var
end
set -a varargs --on-variable __fish_git_prompt_showcolorhints
function __fish_git_prompt_repaint_color $varargs --description "Event handler, repaints prompt when any color changes"
if status --is-interactive
set -e ___fish_git_prompt_init
set -l var $argv[3]
set -e _$var
set -e _{$var}_done
if test $var = __fish_git_prompt_color -o $var = __fish_git_prompt_color_flags -o $var = __fish_git_prompt_showcolorhints
# reset all the other colors too
for name in prefix suffix bare merging branch dirtystate stagedstate invalidstate stashstate untrackedfiles upstream flags
set -e ___fish_git_prompt_color_$name
set -e ___fish_git_prompt_color_{$name}_done
end
end
commandline -f repaint 2>/dev/null
end
end
set -l varargs
for var in cleanstate dirtystate invalidstate stagedstate stashstate stateseparator untrackedfiles upstream_ahead upstream_behind upstream_diverged upstream_equal upstream_prefix
set -a varargs --on-variable __fish_git_prompt_char_$var
end
function __fish_git_prompt_repaint_char $varargs --description "Event handler, repaints prompt when any char changes"
if status --is-interactive
set -e ___fish_git_prompt_init
set -e _$argv[3]
commandline -f repaint 2>/dev/null
end
function __fish_git_prompt
# TODO: This name is deprecated, figure out a way to tell users.
fish_git_prompt $argv
end

View File

@ -1,5 +1,5 @@
function __fish_vcs_prompt --description "Print the prompts for all available vcsen"
__fish_git_prompt
fish_git_prompt
__fish_hg_prompt
__fish_svn_prompt
end

View File

@ -0,0 +1,822 @@
# based off of the git-prompt script that ships with git
#
# Written by Kevin Ballard <kevin@sb.org>
# Updated by Brian Gernhardt <brian@gernhardtsoftware.com>
#
# This is heavily based off of the git-prompt.bash script that ships with
# git, which is Copyright (C) 2006,2007 Shawn O. Pearce <spearce@spearce.org>.
# The act of porting the code, along with any new code, are Copyright (C) 2012
# Kevin Ballard <kevin@sb.org>.
#
# By virtue of being based on the git-prompt.bash script, this script is
# distributed under the GNU General Public License, version 2.0.
#
# This script includes a function fish_git_prompt which takes a format string,
# exactly how the bash script works. This can be used in your fish_prompt
# function.
#
# The behavior of fish_git_prompt is very heavily based off of the bash
# script's __git_ps1 function. As such, usage and customization is very
# similar, although some extra features are provided in this script.
# Due to differences between bash and fish, the PROMPT_COMMAND style where
# passing two or three arguments causes the fucnction to set PS1 is not
# supported. More information on the additional features is found after the
# bash-compatable documentation.
#
# The argument to fish_git_prompt will be displayed only if you are currently
# in a git repository. The %s token will be the name of the branch.
#
# In addition, if you set __fish_git_prompt_showdirtystate to a nonempty value,
# unstaged (*) and staged (+) changes will be shown next to the branch name.
# You can configure this per-repository with the bash.showDirtyState variable,
# which defaults to true once __fish_git_prompt_showdirtystate is enabled. The
# choice to leave the variable as 'bash' instead of renaming to 'fish' is done
# to preserve compatibility with existing configured repositories.
#
# You can also see if currently something is stashed, by setting
# __fish_git_prompt_showstashstate to a nonempty value. If something is
# stashed, then a '$' will be shown next to the branch name.
#
# If you would like to see if there are untracked files, then you can set
# __fish_git_prompt_showuntrackedfiles to a nonempty value. If there are
# untracked files, then a '%' will be shown next to the branch name. Once you
# have set __fish_git_prompt_showuntrackedfiles, you can override it on a
# per-repository basis by setting the bash.showUntrackedFiles config variable.
# As before, this variable remains named 'bash' to preserve compatibility.
#
# If you would like to see the difference between HEAD and its upstream, set
# __fish_git_prompt_showupstream to 'auto'. A "<" indicates you are behind, ">"
# indicates you are ahead, "<>" indicates you have diverged and "=" indicates
# that there is no difference. You can further control behavior by setting
# __fish_git_prompt_showupstream to a space-separated list of values:
#
# verbose show number of commits ahead/behind (+/-) upstream
# name if verbose, then also show the upstream abbrev name
# informative similar to verbose, but shows nothing when equal (fish only)
# git always compare HEAD to @{upstream}
# svn always compare HEAD to your SVN upstream
# none disables (fish only, useful with show_informative_status)
#
# By default, fish_git_prompt will compare HEAD to your SVN upstream if it
# can find one, or @{upstream} otherwise. Once you have set
# __fish_git_prompt_showupstream, you can override it on a per-repository basis
# by setting the bash.showUpstream config variable. As before, this variable
# remains named 'bash' to preserve compatibility.
#
# If you would like to see more information about the identity of commits
# checked out as a detached HEAD, set __fish_git_prompt_describe_style to
# one of the following values:
#
# contains relative to newer annotated tag (v1.6.3.2~35)
# branch relative to newer tag or branch (master~4)
# describe relative to older annotated tag (v1.6.3.1-13-gdd42c2f)
# default exactly matching tag
#
# If you would like a colored hint about the current dirty state, set
# __fish_git_prompt_showcolorhints. The default colors are
# based on the colored output of "git status -sb"
# fish_git_prompt includes some additional features on top of the
# above-documented bash-compatible features:
#
#
# An "informative git prompt" mode similar to the scripts for bash and zsh
# can be activated by setting __fish_git_prompt_show_informative_status
# This works more like the "informative git prompt" scripts for bash and zsh,
# giving prompts like (master12|3456) where master is the current branch,
# you have 1 commit your upstream doesn't and it has 2 you don't, and you have
# 3 staged, 4 unmerged, 5 dirty, and 6 untracked files. If you have no
# changes, it displays (master|).
#
# Setting __fish_git_prompt_show_informative_status changes several defaults.
# The default mode for __fish_git_prompt_showupstream changes to informative
# and the following characters have their defaults changed. (The characters
# and colors can still be customized as described below.)
#
# upstream_prefix ()
# upstream_ahead ()
# upstream_behind ()
# stateseparator (|)
# dirtystate ()
# invalidstate ()
# stagedstate ()
# untrackedfiles ()
# cleanstate ()
#
#
# The color for each component of the prompt can specified using
# __fish_git_prompt_color_<name>, where <name> is one of the following and the
# values are specified as arguments to `set_color`. The variable
# __fish_git_prompt_color is used for any component that does not have an
# individual color set.
#
# prefix Anything before %s in the format string
# suffix Anything after %s in the format string
# bare Marker for a bare repository
# merging Current operation (|MERGING, |REBASE, etc.)
# branch Branch name
# flags Optional flags (see below)
# upstream Upstream name and flags (with showupstream)
#
#
# The following optional flags have both colors, as above, and custom
# characters via __fish_git_prompt_char_<name>. The default character is
# shown in parenthesis. The default color for these flags can be also be set
# via the __fish_git_prompt_color_flags variable.
#
# __fish_git_prompt_showdirtystate
# dirtystate unstaged changes (*)
# stagedstate staged changes (+)
# invalidstate HEAD invalid (#, colored as stagedstate)
#
# __fish_git_prompt_showstashstate
# stashstate stashed changes ($)
#
# __fish_git_prompt_showuntrackedfiles
# untrackedfiles untracked files (%)
#
# __fish_git_prompt_showupstream (all colored as upstream)
# upstream_equal Branch matches upstream (=)
# upstream_behind Upstream has more commits (<)
# upstream_ahead Branch has more commits (>)
# upstream_diverged Upstream and branch have new commits (<>)
#
# __fish_git_prompt_show_informative_status
# (see also the flags for showdirtystate and showuntrackedfiles, above)
# cleanstate Working directory has no changes ()
#
#
# The separator between the branch name and flags can also be customized via
# __fish_git_prompt_char_stateseparator. It can only be colored by
# __fish_git_prompt_color. It normally defaults to a space ( ) and defaults
# to a vertical bar (|) when __fish_git_prompt_show_informative_status is set.
#
# The separator before the upstream information can be customized via
# __fish_git_prompt_char_upstream_prefix. It is colored like the rest of
# the upstream information. It normally defaults to nothing () and defaults
# to a space ( ) when __fish_git_prompt_showupstream contains verbose.
#
#
# Turning on __fish_git_prompt_showcolorhints changes the colors as follows to
# more closely match the behavior in bash. Note that setting any of these
# colors manually will override these defaults.
#
# branch Defaults to green
# branch_detached New color, when head is detached, default red
# dirtystate Defaults to red
# stagedstate Defaults to green
# flags Defaults to --bold blue
#
#
# The branch name could be shorten via
# __fish_git_prompt_shorten_branch_len. Define the branch max len.
# __fish_git_prompt_shorten_branch_char_suffix. Customize suffixed char of shorten branch. Defaults to ().
function __fish_git_prompt_show_upstream --description "Helper function for fish_git_prompt"
set -q __fish_git_prompt_showupstream
or set -l __fish_git_prompt_showupstream
set -l show_upstream $__fish_git_prompt_showupstream
set -l svn_prefix # For better SVN upstream information
set -l informative
set -l svn_url_pattern
set -l count
set -l upstream git
set -l verbose
set -l name
# Default to informative if __fish_git_prompt_show_informative_status is set
if set -q __fish_git_prompt_show_informative_status
set informative 1
end
set -l svn_remote
# get some config options from git-config
command git config -z --get-regexp '^(svn-remote\..*\.url|bash\.showupstream)$' 2>/dev/null | while read -lz key value
switch $key
case bash.showupstream
set show_upstream $value
test -n "$show_upstream"
or return
case svn-remote.'*'.url
set svn_remote $svn_remote $value
# Avoid adding \| to the beginning to avoid needing #?? later
if test -n "$svn_url_pattern"
set svn_url_pattern $svn_url_pattern"|$value"
else
set svn_url_pattern $value
end
set upstream svn+git # default upstream is SVN if available, else git
# Save the config key (without .url) for later use
set -l remote_prefix (string replace -r '\.url$' '' -- $key)
set svn_prefix $svn_prefix $remote_prefix
end
end
# parse configuration variables
# and clear informative default when needed
for option in $show_upstream
switch $option
case git svn
set upstream $option
set -e informative
case verbose
set verbose 1
set -e informative
case informative
set informative 1
case name
set name 1
case none
return
end
end
# Find our upstream
switch $upstream
case git
set upstream '@{upstream}'
case svn\*
# get the upstream from the 'git-svn-id: …' in a commit message
# (git-svn uses essentially the same procedure internally)
set -l svn_upstream (git log --first-parent -1 --grep="^git-svn-id: \($svn_url_pattern\)" 2>/dev/null)
if test (count $svn_upstream) -ne 0
echo $svn_upstream[-1] | read -l __ svn_upstream __
set svn_upstream (string replace -r '@.*' '' -- $svn_upstream)
set -l cur_prefix
for i in (seq (count $svn_remote))
set -l remote $svn_remote[$i]
set -l mod_upstream (string replace "$remote" "" -- $svn_upstream)
if test "$svn_upstream" != "$mod_upstream"
# we found a valid remote
set svn_upstream $mod_upstream
set cur_prefix $svn_prefix[$i]
break
end
end
if test -z "$svn_upstream"
# default branch name for checkouts with no layout:
if test -n "$GIT_SVN_ID"
set upstream $GIT_SVN_ID
else
set upstream git-svn
end
else
set upstream (string replace '/branches' '' -- $svn_upstream | string replace -a '/' '')
# Use fetch config to fix upstream
set -l fetch_val (command git config "$cur_prefix".fetch)
if test -n "$fetch_val"
string split -m1 : -- "$fetch_val" | read -l trunk pattern
set upstream (string replace -r -- "/$trunk\$" '' $pattern) /$upstream
end
end
else if test $upstream = svn+git
set upstream '@{upstream}'
end
end
# Find how many commits we are ahead/behind our upstream
set count (command git rev-list --count --left-right $upstream...HEAD 2>/dev/null)
# calculate the result
if test -n "$verbose"
# Verbose has a space by default
set -l prefix "$___fish_git_prompt_char_upstream_prefix"
# Using two underscore version to check if user explicitly set to nothing
if not set -q __fish_git_prompt_char_upstream_prefix
set -l prefix " "
end
echo $count | read -l behind ahead
switch "$count"
case '' # no upstream
case "0 0" # equal to upstream
echo "$prefix$___fish_git_prompt_char_upstream_equal"
case "0 *" # ahead of upstream
echo "$prefix$___fish_git_prompt_char_upstream_ahead$ahead"
case "* 0" # behind upstream
echo "$prefix$___fish_git_prompt_char_upstream_behind$behind"
case '*' # diverged from upstream
echo "$prefix$___fish_git_prompt_char_upstream_diverged$ahead-$behind"
end
if test -n "$count" -a -n "$name"
echo " "(command git rev-parse --abbrev-ref "$upstream" 2>/dev/null)
end
else if test -n "$informative"
echo $count | read -l behind ahead
switch "$count"
case '' # no upstream
case "0 0" # equal to upstream
case "0 *" # ahead of upstream
echo "$___fish_git_prompt_char_upstream_prefix$___fish_git_prompt_char_upstream_ahead$ahead"
case "* 0" # behind upstream
echo "$___fish_git_prompt_char_upstream_prefix$___fish_git_prompt_char_upstream_behind$behind"
case '*' # diverged from upstream
echo "$___fish_git_prompt_char_upstream_prefix$___fish_git_prompt_char_upstream_ahead$ahead$___fish_git_prompt_char_upstream_behind$behind"
end
else
switch "$count"
case '' # no upstream
case "0 0" # equal to upstream
echo "$___fish_git_prompt_char_upstream_prefix$___fish_git_prompt_char_upstream_equal"
case "0 *" # ahead of upstream
echo "$___fish_git_prompt_char_upstream_prefix$___fish_git_prompt_char_upstream_ahead"
case "* 0" # behind upstream
echo "$___fish_git_prompt_char_upstream_prefix$___fish_git_prompt_char_upstream_behind"
case '*' # diverged from upstream
echo "$___fish_git_prompt_char_upstream_prefix$___fish_git_prompt_char_upstream_diverged"
end
end
end
function fish_git_prompt --description "Prompt function for Git"
# If git isn't installed, there's nothing we can do
# Return 1 so the calling prompt can deal with it
if not command -sq git
return 1
end
set -l repo_info (command git rev-parse --git-dir --is-inside-git-dir --is-bare-repository --is-inside-work-tree HEAD 2>/dev/null)
test -n "$repo_info"
or return
set -l git_dir $repo_info[1]
set -l inside_gitdir $repo_info[2]
set -l bare_repo $repo_info[3]
set -l inside_worktree $repo_info[4]
set -q repo_info[5]
and set -l sha $repo_info[5]
set -l rbc (__fish_git_prompt_operation_branch_bare $repo_info)
set -l r $rbc[1] # current operation
set -l b $rbc[2] # current branch
set -l detached $rbc[3]
set -l w #dirty working directory
set -l i #staged changes
set -l s #stashes
set -l u #untracked
set -l c $rbc[4] # bare repository
set -l p #upstream
set -l informative_status
if not set -q ___fish_git_prompt_init
# This takes a while, so it only needs to be done once,
# and then whenever the configuration changes.
__fish_git_prompt_validate_chars
__fish_git_prompt_validate_colors
set -g ___fish_git_prompt_init
end
set -l space "$___fish_git_prompt_color$___fish_git_prompt_char_stateseparator$___fish_git_prompt_color_done"
# Use our variables as defaults, but allow overrides via the local git config.
# That means if neither is set, this stays empty.
#
# So "!= true" or "!= false" are useful tests if you want to do something by default.
set -l informative (command git config --bool bash.showInformativeStatus)
set -l dirty (command git config --bool bash.showDirtyState)
if not set -q dirty[1]
set -q __fish_git_prompt_showdirtystate
and set dirty true
end
set -l untracked (command git config --bool bash.showUntrackedFiles)
if not set -q untracked[1]
set -q __fish_git_prompt_showuntrackedfiles
and set untracked true
end
if test "true" = $inside_worktree
# Use informative status if it has been enabled locally, or it has been
# enabled globally (via the fish variable) and dirty or untracked are not false.
#
# This is to allow overrides for the repository.
if test "$informative" = true
or begin
set -q __fish_git_prompt_show_informative_status
and test "$dirty" != false
and test "$untracked" != false
end
set informative_status "$space"(__fish_git_prompt_informative_status)
else
# This has to be set explicitly.
if test "$dirty" = true
set w (__fish_git_prompt_dirty)
set i (__fish_git_prompt_staged $sha)
end
if set -q __fish_git_prompt_showstashstate
and test -r $git_dir/refs/stash
set s $___fish_git_prompt_char_stashstate
end
if test "$untracked" != true
set u (__fish_git_prompt_untracked)
end
end
if set -q __fish_git_prompt_showupstream
or set -q __fish_git_prompt_show_informative_status
set p (__fish_git_prompt_show_upstream)
end
end
set -l branch_color $___fish_git_prompt_color_branch
set -l branch_done $___fish_git_prompt_color_branch_done
if set -q __fish_git_prompt_showcolorhints
if test $detached = yes
set branch_color $___fish_git_prompt_color_branch_detached
set branch_done $___fish_git_prompt_color_branch_detached_done
end
end
if test -n "$w"
set w "$___fish_git_prompt_color_dirtystate$w$___fish_git_prompt_color_dirtystate_done"
end
if test -n "$i"
set i "$___fish_git_prompt_color_stagedstate$i$___fish_git_prompt_color_stagedstate_done"
end
if test -n "$s"
set s "$___fish_git_prompt_color_stashstate$s$___fish_git_prompt_color_stashstate_done"
end
if test -n "$u"
set u "$___fish_git_prompt_color_untrackedfiles$u$___fish_git_prompt_color_untrackedfiles_done"
end
set b (string replace refs/heads/ '' -- $b)
set -q __fish_git_prompt_shorten_branch_char_suffix
or set -l __fish_git_prompt_shorten_branch_char_suffix "…"
if string match -qr '^\d+$' "$__fish_git_prompt_shorten_branch_len"; and test (string length "$b") -gt $__fish_git_prompt_shorten_branch_len
set b (string sub -l "$__fish_git_prompt_shorten_branch_len" "$b")"$__fish_git_prompt_shorten_branch_char_suffix"
end
if test -n "$b"
set b "$branch_color$b$branch_done"
end
if test -n "$c"
set c "$___fish_git_prompt_color_bare$c$___fish_git_prompt_color_bare_done"
end
if test -n "$r"
set r "$___fish_git_prompt_color_merging$r$___fish_git_prompt_color_merging_done"
end
if test -n "$p"
set p "$___fish_git_prompt_color_upstream$p$___fish_git_prompt_color_upstream_done"
end
# Formatting
set -l f "$w$i$s$u"
if test -n "$f"
set f "$space$f"
end
set -l format $argv[1]
if test -z "$format"
set format " (%s)"
end
printf "%s$format%s" "$___fish_git_prompt_color_prefix" "$___fish_git_prompt_color_prefix_done$c$b$f$r$p$informative_status$___fish_git_prompt_color_suffix" "$___fish_git_prompt_color_suffix_done"
end
### helper functions
function __fish_git_prompt_staged --description "fish_git_prompt helper, tells whether or not the current branch has staged files"
set -l sha $argv[1]
set -l staged
if test -n "$sha"
command git diff-index --cached --quiet HEAD -- 2>/dev/null
or set staged $___fish_git_prompt_char_stagedstate
else
set staged $___fish_git_prompt_char_invalidstate
end
echo $staged
end
function __fish_git_prompt_untracked --description "fish_git_prompt helper, tells whether or not the current repository has untracked files"
set -l untracked
if command git ls-files --others --exclude-standard --directory --no-empty-directory --error-unmatch -- :/ >/dev/null 2>&1
set untracked $___fish_git_prompt_char_untrackedfiles
end
echo $untracked
end
function __fish_git_prompt_dirty --description "fish_git_prompt helper, tells whether or not the current branch has tracked, modified files"
set -l dirty
set -l os
command git diff --no-ext-diff --quiet --exit-code 2>/dev/null
set os $status
if test $os -ne 0
set dirty $___fish_git_prompt_char_dirtystate
end
echo $dirty
end
set -g ___fish_git_prompt_status_order stagedstate invalidstate dirtystate untrackedfiles
function __fish_git_prompt_informative_status
set -l changedFiles (command git diff --name-status 2>/dev/null | string match -r \\w)
set -l stagedFiles (command git diff --staged --name-status | string match -r \\w)
set -l x (count $changedFiles)
set -l y (count (string match -r "U" -- $changedFiles))
set -l dirtystate (math $x - $y)
set -l x (count $stagedFiles)
set -l invalidstate (count (string match -r "U" -- $stagedFiles))
set -l stagedstate (math $x - $invalidstate)
set -l untrackedfiles (command git ls-files --others --exclude-standard | wc -l | string trim)
set -l info
# If `math` fails for some reason, assume the state is clean - it's the simpler path
set -l state (math $dirtystate + $invalidstate + $stagedstate + $untrackedfiles 2>/dev/null)
if test -z "$state"
or test "$state" = 0
set info $___fish_git_prompt_color_cleanstate$___fish_git_prompt_char_cleanstate$___fish_git_prompt_color_cleanstate_done
else
for i in $___fish_git_prompt_status_order
if [ $$i != "0" ]
set -l color_var ___fish_git_prompt_color_$i
set -l color_done_var ___fish_git_prompt_color_{$i}_done
set -l symbol_var ___fish_git_prompt_char_$i
set -l color $$color_var
set -l color_done $$color_done_var
set -l symbol $$symbol_var
set -l count
if not set -q __fish_git_prompt_hide_$i
set count $$i
end
set info "$info$color$symbol$count$color_done"
end
end
end
echo $info
end
# Keeping these together avoids many duplicated checks
function __fish_git_prompt_operation_branch_bare --description "fish_git_prompt helper, returns the current Git operation and branch"
# This function is passed the full repo_info array
set -l git_dir $argv[1]
set -l inside_gitdir $argv[2]
set -l bare_repo $argv[3]
set -q argv[5]
and set -l sha $argv[5]
set -l branch
set -l operation
set -l detached no
set -l bare
set -l step
set -l total
set -l os
if test -d $git_dir/rebase-merge
set branch (cat $git_dir/rebase-merge/head-name 2>/dev/null)
set step (cat $git_dir/rebase-merge/msgnum 2>/dev/null)
set total (cat $git_dir/rebase-merge/end 2>/dev/null)
if test -f $git_dir/rebase-merge/interactive
set operation "|REBASE-i"
else
set operation "|REBASE-m"
end
else
if test -d $git_dir/rebase-apply
set step (cat $git_dir/rebase-apply/next 2>/dev/null)
set total (cat $git_dir/rebase-apply/last 2>/dev/null)
if test -f $git_dir/rebase-apply/rebasing
set branch (cat $git_dir/rebase-apply/head-name 2>/dev/null)
set operation "|REBASE"
else if test -f $git_dir/rebase-apply/applying
set operation "|AM"
else
set operation "|AM/REBASE"
end
else if test -f $git_dir/MERGE_HEAD
set operation "|MERGING"
else if test -f $git_dir/CHERRY_PICK_HEAD
set operation "|CHERRY-PICKING"
else if test -f $git_dir/REVERT_HEAD
set operation "|REVERTING"
else if test -f $git_dir/BISECT_LOG
set operation "|BISECTING"
end
end
if test -n "$step" -a -n "$total"
set operation "$operation $step/$total"
end
if test -z "$branch"
set branch (command git symbolic-ref HEAD 2>/dev/null; set os $status)
if test $os -ne 0
set detached yes
set branch (switch "$__fish_git_prompt_describe_style"
case contains
command git describe --contains HEAD
case branch
command git describe --contains --all HEAD
case describe
command git describe HEAD
case default '*'
command git describe --tags --exact-match HEAD
end 2>/dev/null; set os $status)
if test $os -ne 0
# Shorten the sha ourselves to 8 characters - this should be good for most repositories,
# and even for large ones it should be good for most commits
if set -q sha
set branch (string match -r '^.{8}' -- $sha)
else
set branch unknown
end
end
set branch "($branch)"
end
end
if test "true" = $inside_gitdir
if test "true" = $bare_repo
set bare "BARE:"
else
# Let user know they're inside the git dir of a non-bare repo
set branch "GIT_DIR!"
end
end
echo $operation
echo $branch
echo $detached
echo $bare
end
function __fish_git_prompt_set_char
set -l user_variable_name "$argv[1]"
set -l char $argv[2]
set -l user_variable
if set -q $user_variable_name
set user_variable $$user_variable_name
end
if set -q argv[3]
and set -q __fish_git_prompt_show_informative_status
set char $argv[3]
end
set -l variable _$user_variable_name
set -l variable_done "$variable"_done
if not set -q $variable
set -g $variable (set -q $user_variable_name; and echo $user_variable; or echo $char)
end
end
function __fish_git_prompt_validate_chars --description "fish_git_prompt helper, checks char variables"
__fish_git_prompt_set_char __fish_git_prompt_char_cleanstate '✔'
__fish_git_prompt_set_char __fish_git_prompt_char_dirtystate '*' '✚'
__fish_git_prompt_set_char __fish_git_prompt_char_invalidstate '#' '✖'
__fish_git_prompt_set_char __fish_git_prompt_char_stagedstate '+' '●'
__fish_git_prompt_set_char __fish_git_prompt_char_stashstate '$'
__fish_git_prompt_set_char __fish_git_prompt_char_stateseparator ' ' '|'
__fish_git_prompt_set_char __fish_git_prompt_char_untrackedfiles '%' '…'
__fish_git_prompt_set_char __fish_git_prompt_char_upstream_ahead '>' '↑'
__fish_git_prompt_set_char __fish_git_prompt_char_upstream_behind '<' '↓'
__fish_git_prompt_set_char __fish_git_prompt_char_upstream_diverged '<>'
__fish_git_prompt_set_char __fish_git_prompt_char_upstream_equal '='
__fish_git_prompt_set_char __fish_git_prompt_char_upstream_prefix ''
end
function __fish_git_prompt_set_color
set -l user_variable_name "$argv[1]"
set -l user_variable
if set -q $user_variable_name
set user_variable $$user_variable_name
end
set -l user_variable_bright
set -l default default_done
switch (count $argv)
case 1 # No defaults given, use prompt color
set default $___fish_git_prompt_color
set default_done $___fish_git_prompt_color_done
case 2 # One default given, use normal for done
set default "$argv[2]"
set default_done (set_color normal)
case 3 # Both defaults given
set default "$argv[2]"
set default_done "$argv[3]"
end
set -l variable _$user_variable_name
set -l variable_done "$variable"_done
if not set -q $variable
if test -n "$user_variable"
set -g $variable (set_color $user_variable)
set -g $variable_done (set_color normal)
else
set -g $variable $default
set -g $variable_done $default_done
end
end
end
function __fish_git_prompt_validate_colors --description "fish_git_prompt helper, checks color variables"
# Base color defaults to nothing (must be done first)
__fish_git_prompt_set_color __fish_git_prompt_color '' ''
# Normal colors
__fish_git_prompt_set_color __fish_git_prompt_color_prefix
__fish_git_prompt_set_color __fish_git_prompt_color_suffix
__fish_git_prompt_set_color __fish_git_prompt_color_bare
__fish_git_prompt_set_color __fish_git_prompt_color_merging
__fish_git_prompt_set_color __fish_git_prompt_color_cleanstate
__fish_git_prompt_set_color __fish_git_prompt_color_invalidstate
__fish_git_prompt_set_color __fish_git_prompt_color_upstream
# Colors with defaults with showcolorhints
if set -q __fish_git_prompt_showcolorhints
__fish_git_prompt_set_color __fish_git_prompt_color_flags (set_color --bold blue)
__fish_git_prompt_set_color __fish_git_prompt_color_branch (set_color green)
__fish_git_prompt_set_color __fish_git_prompt_color_dirtystate (set_color red)
__fish_git_prompt_set_color __fish_git_prompt_color_stagedstate (set_color green)
else
__fish_git_prompt_set_color __fish_git_prompt_color_flags
__fish_git_prompt_set_color __fish_git_prompt_color_branch
__fish_git_prompt_set_color __fish_git_prompt_color_dirtystate $___fish_git_prompt_color_flags $___fish_git_prompt_color_flags_done
__fish_git_prompt_set_color __fish_git_prompt_color_stagedstate $___fish_git_prompt_color_flags $___fish_git_prompt_color_flags_done
end
# Branch_detached has a default, but is only used with showcolorhints
__fish_git_prompt_set_color __fish_git_prompt_color_branch_detached (set_color red)
# Colors that depend on flags color
__fish_git_prompt_set_color __fish_git_prompt_color_stashstate $___fish_git_prompt_color_flags $___fish_git_prompt_color_flags_done
__fish_git_prompt_set_color __fish_git_prompt_color_untrackedfiles $___fish_git_prompt_color_flags $___fish_git_prompt_color_flags_done
end
set -l varargs
for var in repaint describe_style show_informative_status showdirtystate showstashstate showuntrackedfiles showupstream
set -a varargs --on-variable __fish_git_prompt_$var
end
function __fish_git_prompt_repaint $varargs --description "Event handler, repaints prompt when functionality changes"
if status --is-interactive
if test $argv[3] = __fish_git_prompt_show_informative_status
# Clear characters that have different defaults with/without informative status
for name in cleanstate dirtystate invalidstate stagedstate stateseparator untrackedfiles upstream_ahead upstream_behind
set -e ___fish_git_prompt_char_$name
end
end
commandline -f repaint 2>/dev/null
end
end
set -l varargs
for var in '' _prefix _suffix _bare _merging _cleanstate _invalidstate _upstream _flags _branch _dirtystate _stagedstate _branch_detached _stashstate _untrackedfiles
set -a varargs --on-variable __fish_git_prompt_color$var
end
set -a varargs --on-variable __fish_git_prompt_showcolorhints
function __fish_git_prompt_repaint_color $varargs --description "Event handler, repaints prompt when any color changes"
if status --is-interactive
set -e ___fish_git_prompt_init
set -l var $argv[3]
set -e _$var
set -e _{$var}_done
if test $var = __fish_git_prompt_color -o $var = __fish_git_prompt_color_flags -o $var = __fish_git_prompt_showcolorhints
# reset all the other colors too
for name in prefix suffix bare merging branch dirtystate stagedstate invalidstate stashstate untrackedfiles upstream flags
set -e ___fish_git_prompt_color_$name
set -e ___fish_git_prompt_color_{$name}_done
end
end
commandline -f repaint 2>/dev/null
end
end
set -l varargs
for var in cleanstate dirtystate invalidstate stagedstate stashstate stateseparator untrackedfiles upstream_ahead upstream_behind upstream_diverged upstream_equal upstream_prefix
set -a varargs --on-variable __fish_git_prompt_char_$var
end
function __fish_git_prompt_repaint_char $varargs --description "Event handler, repaints prompt when any char changes"
if status --is-interactive
set -e ___fish_git_prompt_init
set -e _$argv[3]
commandline -f repaint 2>/dev/null
end
end

View File

@ -10,7 +10,7 @@ function fish_prompt
# - the current path (with prompt_pwd)
# - date +%X
# - the current virtual environment, if any
# - the current git status, if any, with __fish_git_prompt
# - the current git status, if any, with fish_git_prompt
# - the current battery state, if any, and if your power cable is unplugged, and if you have "acpi"
# - current background jobs, if any
@ -79,7 +79,7 @@ function fish_prompt
and _nim_prompt_wrapper $retc V (basename "$VIRTUAL_ENV")
# git
set prompt_git (__fish_git_prompt | string trim -c ' ()')
set prompt_git (fish_git_prompt | string trim -c ' ()')
test -n "$prompt_git"
and _nim_prompt_wrapper $retc G $prompt_git