diff options
Diffstat (limited to 'plugins/gitfast')
| -rw-r--r-- | plugins/gitfast/_git | 163 | ||||
| -rw-r--r-- | plugins/gitfast/git-completion.bash | 301 | ||||
| -rw-r--r-- | plugins/gitfast/git-prompt.sh | 334 | 
3 files changed, 435 insertions, 363 deletions
| diff --git a/plugins/gitfast/_git b/plugins/gitfast/_git index cf8116d47..fac5e711e 100644 --- a/plugins/gitfast/_git +++ b/plugins/gitfast/_git @@ -2,18 +2,19 @@  # zsh completion wrapper for git  # -# You need git's bash completion script installed somewhere, by default on the -# same directory as this script. +# Copyright (c) 2012-2013 Felipe Contreras <felipe.contreras@gmail.com>  # -# If your script is on ~/.git-completion.sh instead, you can configure it on -# your ~/.zshrc: +# You need git's bash completion script installed somewhere, by default it +# would be the location bash-completion uses. +# +# If your script is somewhere else, you can configure it on your ~/.zshrc:  #  #  zstyle ':completion:*:*:git:*' script ~/.git-completion.sh  # -# The recommended way to install this script is to copy to -# '~/.zsh/completion/_git', and then add the following to your ~/.zshrc file: +# The recommended way to install this script is to copy to '~/.zsh/_git', and +# then add the following to your ~/.zshrc file:  # -#  fpath=(~/.zsh/completion $fpath) +#  fpath=(~/.zsh $fpath)  complete ()  { @@ -21,8 +22,23 @@ complete ()  	return 0  } +zstyle -T ':completion:*:*:git:*' tag-order && \ +	zstyle ':completion:*:*:git:*' tag-order 'common-commands' +  zstyle -s ":completion:*:*:git:*" script script -test -z "$script" && script="$(dirname ${funcsourcetrace[1]%:*})"/git-completion.bash +if [ -z "$script" ]; then +	local -a locations +	local e +	locations=( +		'/etc/bash_completion.d/git' # fedora, old debian +		'/usr/share/bash-completion/completions/git' # arch, ubuntu, new debian +		'/usr/share/bash-completion/git' # gentoo +		$(dirname ${funcsourcetrace[1]%:*})/git-completion.bash +		) +	for e in $locations; do +		test -f $e && script="$e" && break +	done +fi  ZSH_VERSION='' . "$script"  __gitcomp () @@ -69,18 +85,131 @@ __gitcomp_file ()  	compadd -Q -p "${2-}" -f -- ${=1} && _ret=0  } +__git_zsh_bash_func () +{ +	emulate -L ksh + +	local command=$1 + +	local completion_func="_git_${command//-/_}" +	declare -f $completion_func >/dev/null && $completion_func && return + +	local expansion=$(__git_aliased_command "$command") +	if [ -n "$expansion" ]; then +		completion_func="_git_${expansion//-/_}" +		declare -f $completion_func >/dev/null && $completion_func +	fi +} + +__git_zsh_cmd_common () +{ +	local -a list +	list=( +	add:'add file contents to the index' +	bisect:'find by binary search the change that introduced a bug' +	branch:'list, create, or delete branches' +	checkout:'checkout a branch or paths to the working tree' +	clone:'clone a repository into a new directory' +	commit:'record changes to the repository' +	diff:'show changes between commits, commit and working tree, etc' +	fetch:'download objects and refs from another repository' +	grep:'print lines matching a pattern' +	init:'create an empty Git repository or reinitialize an existing one' +	log:'show commit logs' +	merge:'join two or more development histories together' +	mv:'move or rename a file, a directory, or a symlink' +	pull:'fetch from and merge with another repository or a local branch' +	push:'update remote refs along with associated objects' +	rebase:'forward-port local commits to the updated upstream head' +	reset:'reset current HEAD to the specified state' +	rm:'remove files from the working tree and from the index' +	show:'show various types of objects' +	status:'show the working tree status' +	tag:'create, list, delete or verify a tag object signed with GPG') +	_describe -t common-commands 'common commands' list && _ret=0 +} + +__git_zsh_cmd_alias () +{ +	local -a list +	list=(${${${(0)"$(git config -z --get-regexp '^alias\.')"}#alias.}%$'\n'*}) +	_describe -t alias-commands 'aliases' list $* && _ret=0 +} + +__git_zsh_cmd_all () +{ +	local -a list +	emulate ksh -c __git_compute_all_commands +	list=( ${=__git_all_commands} ) +	_describe -t all-commands 'all commands' list && _ret=0 +} + +__git_zsh_main () +{ +	local curcontext="$curcontext" state state_descr line +	typeset -A opt_args +	local -a orig_words + +	orig_words=( ${words[@]} ) + +	_arguments -C \ +		'(-p --paginate --no-pager)'{-p,--paginate}'[pipe all output into ''less'']' \ +		'(-p --paginate)--no-pager[do not pipe git output into a pager]' \ +		'--git-dir=-[set the path to the repository]: :_directories' \ +		'--bare[treat the repository as a bare repository]' \ +		'(- :)--version[prints the git suite version]' \ +		'--exec-path=-[path to where your core git programs are installed]:: :_directories' \ +		'--html-path[print the path where git''s HTML documentation is installed]' \ +		'--info-path[print the path where the Info files are installed]' \ +		'--man-path[print the manpath (see `man(1)`) for the man pages]' \ +		'--work-tree=-[set the path to the working tree]: :_directories' \ +		'--namespace=-[set the git namespace]' \ +		'--no-replace-objects[do not use replacement refs to replace git objects]' \ +		'(- :)--help[prints the synopsis and a list of the most commonly used commands]: :->arg' \ +		'(-): :->command' \ +		'(-)*:: :->arg' && return + +	case $state in +	(command) +		_alternative \ +                         'alias-commands:alias:__git_zsh_cmd_alias' \ +                         'common-commands:common:__git_zsh_cmd_common' \ +                         'all-commands:all:__git_zsh_cmd_all' && _ret=0 +		;; +	(arg) +		local command="${words[1]}" __git_dir + +		if (( $+opt_args[--bare] )); then +			__git_dir='.' +		else +			__git_dir=${opt_args[--git-dir]} +		fi + +		(( $+opt_args[--help] )) && command='help' + +		words=( ${orig_words[@]} ) + +		__git_zsh_bash_func $command +		;; +	esac +} +  _git ()  {  	local _ret=1 -	() { -		emulate -L ksh -		local cur cword prev -		cur=${words[CURRENT-1]} -		prev=${words[CURRENT-2]} -		let cword=CURRENT-1 -		__${service}_main -	} -	let _ret && _default -S '' && _ret=0 +	local cur cword prev + +	cur=${words[CURRENT]} +	prev=${words[CURRENT-1]} +	let cword=CURRENT-1 + +	if (( $+functions[__${service}_zsh_main] )); then +		__${service}_zsh_main +	else +		emulate ksh -c __${service}_main +	fi + +	let _ret && _default && _ret=0  	return _ret  } diff --git a/plugins/gitfast/git-completion.bash b/plugins/gitfast/git-completion.bash index 93eba4675..5da920ecd 100644 --- a/plugins/gitfast/git-completion.bash +++ b/plugins/gitfast/git-completion.bash @@ -33,8 +33,6 @@ esac  # returns location of .git repo  __gitdir ()  { -	# Note: this function is duplicated in git-prompt.sh -	# When updating it, make sure you update the other one to match.  	if [ -z "${1-}" ]; then  		if [ -n "${__git_dir-}" ]; then  			echo "$__git_dir" @@ -53,19 +51,6 @@ __gitdir ()  	fi  } -__gitcomp_1 () -{ -	local c IFS=$' \t\n' -	for c in $1; do -		c="$c$2" -		case $c in -		--*=*|*.) ;; -		*) c="$c " ;; -		esac -		printf '%s\n' "$c" -	done -} -  # The following function is based on code from:  #  #   bash_completion - programmable completion functions for bash 3.2+ @@ -195,8 +180,18 @@ _get_comp_words_by_ref ()  }  fi -# Generates completion reply with compgen, appending a space to possible -# completion words, if necessary. +__gitcompadd () +{ +	local i=0 +	for x in $1; do +		if [[ "$x" == "$3"* ]]; then +			COMPREPLY[i++]="$2$x$4" +		fi +	done +} + +# Generates completion reply, appending a space to possible completion words, +# if necessary.  # It accepts 1 to 4 arguments:  # 1: List of possible completion words.  # 2: A prefix to be added to each possible completion word (optional). @@ -208,19 +203,25 @@ __gitcomp ()  	case "$cur_" in  	--*=) -		COMPREPLY=()  		;;  	*) -		local IFS=$'\n' -		COMPREPLY=($(compgen -P "${2-}" \ -			-W "$(__gitcomp_1 "${1-}" "${4-}")" \ -			-- "$cur_")) +		local c i=0 IFS=$' \t\n' +		for c in $1; do +			c="$c${4-}" +			if [[ $c == "$cur_"* ]]; then +				case $c in +				--*=*|*.) ;; +				*) c="$c " ;; +				esac +				COMPREPLY[i++]="${2-}$c" +			fi +		done  		;;  	esac  } -# Generates completion reply with compgen from newline-separated possible -# completion words by appending a space to all of them. +# Generates completion reply from newline-separated possible completion words +# by appending a space to all of them.  # It accepts 1 to 4 arguments:  # 1: List of possible completion words, separated by a single newline.  # 2: A prefix to be added to each possible completion word (optional). @@ -231,7 +232,7 @@ __gitcomp ()  __gitcomp_nl ()  {  	local IFS=$'\n' -	COMPREPLY=($(compgen -P "${2-}" -S "${4- }" -W "$1" -- "${3-$cur}")) +	__gitcompadd "$1" "${2-}" "${3-$cur}" "${4- }"  }  # Generates completion reply with compgen from newline-separated possible @@ -249,106 +250,50 @@ __gitcomp_file ()  	# since tilde expansion is not applied.  	# This means that COMPREPLY will be empty and Bash default  	# completion will be used. -	COMPREPLY=($(compgen -P "${2-}" -W "$1" -- "${3-$cur}")) - -	# Tell Bash that compspec generates filenames. -	compopt -o filenames 2>/dev/null -} - -__git_index_file_list_filter_compat () -{ -	local path +	__gitcompadd "$1" "${2-}" "${3-$cur}" "" -	while read -r path; do -		case "$path" in -		?*/*) echo "${path%%/*}/" ;; -		*) echo "$path" ;; -		esac -	done +	# use a hack to enable file mode in bash < 4 +	compopt -o filenames +o nospace 2>/dev/null || +	compgen -f /non-existing-dir/ > /dev/null  } -__git_index_file_list_filter_bash () -{ -	local path - -	while read -r path; do -		case "$path" in -		?*/*) -			# XXX if we append a slash to directory names when using -			# `compopt -o filenames`, Bash will append another slash. -			# This is pretty stupid, and this the reason why we have to -			# define a compatible version for this function. -			echo "${path%%/*}" ;; -		*) -			echo "$path" ;; -		esac -	done -} - -# Process path list returned by "ls-files" and "diff-index --name-only" -# commands, in order to list only file names relative to a specified -# directory, and append a slash to directory names. -__git_index_file_list_filter () -{ -	# Default to Bash >= 4.x -	__git_index_file_list_filter_bash -} - -# Execute git ls-files, returning paths relative to the directory -# specified in the first argument, and using the options specified in -# the second argument. +# Execute 'git ls-files', unless the --committable option is specified, in +# which case it runs 'git diff-index' to find out the files that can be +# committed.  It return paths relative to the directory specified in the first +# argument, and using the options specified in the second argument.  __git_ls_files_helper ()  {  	(  		test -n "${CDPATH+set}" && unset CDPATH -		# NOTE: $2 is not quoted in order to support multiple options -		cd "$1" && git ls-files --exclude-standard $2 +		cd "$1" +		if [ "$2" == "--committable" ]; then +			git diff-index --name-only --relative HEAD +		else +			# NOTE: $2 is not quoted in order to support multiple options +			git ls-files --exclude-standard $2 +		fi  	) 2>/dev/null  } -# Execute git diff-index, returning paths relative to the directory -# specified in the first argument, and using the tree object id -# specified in the second argument. -__git_diff_index_helper () -{ -	( -		test -n "${CDPATH+set}" && unset CDPATH -		cd "$1" && git diff-index --name-only --relative "$2" -	) 2>/dev/null -} -  # __git_index_files accepts 1 or 2 arguments:  # 1: Options to pass to ls-files (required). -#    Supported options are --cached, --modified, --deleted, --others, -#    and --directory.  # 2: A directory path (optional).  #    If provided, only files within the specified directory are listed.  #    Sub directories are never recursed.  Path must have a trailing  #    slash.  __git_index_files ()  { -	local dir="$(__gitdir)" root="${2-.}" +	local dir="$(__gitdir)" root="${2-.}" file  	if [ -d "$dir" ]; then -		__git_ls_files_helper "$root" "$1" | __git_index_file_list_filter | -			sort | uniq -	fi -} - -# __git_diff_index_files accepts 1 or 2 arguments: -# 1) The id of a tree object. -# 2) A directory path (optional). -#    If provided, only files within the specified directory are listed. -#    Sub directories are never recursed.  Path must have a trailing -#    slash. -__git_diff_index_files () -{ -	local dir="$(__gitdir)" root="${2-.}" - -	if [ -d "$dir" ]; then -		__git_diff_index_helper "$root" "$1" | __git_index_file_list_filter | -			sort | uniq +		__git_ls_files_helper "$root" "$1" | +		while read -r file; do +			case "$file" in +			?*/*) echo "${file%%/*}" ;; +			*) echo "$file" ;; +			esac +		done | sort | uniq  	fi  } @@ -424,14 +369,8 @@ __git_refs ()  		done  		;;  	*) -		git ls-remote "$dir" HEAD ORIG_HEAD 'refs/tags/*' 'refs/heads/*' 'refs/remotes/*' 2>/dev/null | \ -		while read -r hash i; do -			case "$i" in -			*^{}) ;; -			refs/*) echo "${i#refs/*/}" ;; -			*) echo "$i" ;; -			esac -		done +		echo "HEAD" +		git for-each-ref --format="%(refname:short)" -- "refs/remotes/$dir/" | sed -e "s#^$dir/##"  		;;  	esac  } @@ -549,44 +488,23 @@ __git_complete_revlist_file ()  } -# __git_complete_index_file requires 1 argument: the options to pass to -# ls-file +# __git_complete_index_file requires 1 argument: +# 1: the options to pass to ls-file +# +# The exception is --committable, which finds the files appropriate commit.  __git_complete_index_file ()  { -	local pfx cur_="$cur" +	local pfx="" cur_="$cur"  	case "$cur_" in  	?*/*)  		pfx="${cur_%/*}"  		cur_="${cur_##*/}"  		pfx="${pfx}/" - -		__gitcomp_file "$(__git_index_files "$1" "$pfx")" "$pfx" "$cur_" -		;; -	*) -		__gitcomp_file "$(__git_index_files "$1")" "" "$cur_"  		;;  	esac -} - -# __git_complete_diff_index_file requires 1 argument: the id of a tree -# object -__git_complete_diff_index_file () -{ -	local pfx cur_="$cur" -	case "$cur_" in -	?*/*) -		pfx="${cur_%/*}" -		cur_="${cur_##*/}" -		pfx="${pfx}/" - -		__gitcomp_file "$(__git_diff_index_files "$1" "$pfx")" "$pfx" "$cur_" -		;; -	*) -		__gitcomp_file "$(__git_diff_index_files "$1")" "" "$cur_" -		;; -	esac +	__gitcomp_file "$(__git_index_files "$1" "$pfx")" "$pfx" "$cur_"  }  __git_complete_file () @@ -614,7 +532,6 @@ __git_complete_remote_or_refspec ()  			case "$cmd" in  			push) no_complete_refspec=1 ;;  			fetch) -				COMPREPLY=()  				return  				;;  			*) ;; @@ -630,7 +547,6 @@ __git_complete_remote_or_refspec ()  		return  	fi  	if [ $no_complete_refspec = 1 ]; then -		COMPREPLY=()  		return  	fi  	[ "$remote" = "." ] && remote= @@ -732,6 +648,7 @@ __git_list_porcelain_commands ()  		cat-file)         : plumbing;;  		check-attr)       : plumbing;;  		check-ignore)     : plumbing;; +		check-mailmap)    : plumbing;;  		check-ref-format) : plumbing;;  		checkout-index)   : plumbing;;  		commit-tree)      : plumbing;; @@ -951,7 +868,6 @@ _git_am ()  			"  		return  	esac -	COMPREPLY=()  }  _git_apply () @@ -971,7 +887,6 @@ _git_apply ()  			"  		return  	esac -	COMPREPLY=()  }  _git_add () @@ -1031,7 +946,6 @@ _git_bisect ()  		__gitcomp_nl "$(__git_refs)"  		;;  	*) -		COMPREPLY=()  		;;  	esac  } @@ -1124,9 +1038,14 @@ _git_cherry ()  _git_cherry_pick ()  { +	local dir="$(__gitdir)" +	if [ -f "$dir"/CHERRY_PICK_HEAD ]; then +		__gitcomp "--continue --quit --abort" +		return +	fi  	case "$cur" in  	--*) -		__gitcomp "--edit --no-commit" +		__gitcomp "--edit --no-commit --signoff --strategy= --mainline"  		;;  	*)  		__gitcomp_nl "$(__git_refs)" @@ -1170,7 +1089,6 @@ _git_clone ()  		return  		;;  	esac -	COMPREPLY=()  }  _git_commit () @@ -1182,13 +1100,6 @@ _git_commit ()  		;;  	esac -	case "$prev" in -	-c|-C) -		__gitcomp_nl "$(__git_refs)" "" "${cur}" -		return -		;; -	esac -  	case "$cur" in  	--cleanup=*)  		__gitcomp "default strip verbatim whitespace @@ -1218,7 +1129,7 @@ _git_commit ()  	esac  	if git rev-parse --verify --quiet HEAD >/dev/null; then -		__git_complete_diff_index_file "HEAD" +		__git_complete_index_file "--committable"  	else  		# This is the first commit  		__git_complete_index_file "--cached" @@ -1251,7 +1162,7 @@ __git_diff_common_options="--stat --numstat --shortstat --summary  			--no-prefix --src-prefix= --dst-prefix=  			--inter-hunk-context=  			--patience --histogram --minimal -			--raw +			--raw --word-diff  			--dirstat --dirstat= --dirstat-by-file  			--dirstat-by-file= --cumulative  			--diff-algorithm= @@ -1299,7 +1210,7 @@ _git_difftool ()  		return  		;;  	esac -	__git_complete_file +	__git_complete_revlist_file  }  __git_fetch_options=" @@ -1319,11 +1230,12 @@ _git_fetch ()  }  __git_format_patch_options=" -	--stdout --attach --no-attach --thread --thread= --output-directory +	--stdout --attach --no-attach --thread --thread= --no-thread  	--numbered --start-number --numbered-files --keep-subject --signoff  	--signature --no-signature --in-reply-to= --cc= --full-index --binary  	--not --all --cover-letter --no-prefix --src-prefix= --dst-prefix=  	--inline --suffix= --ignore-if-in-upstream --subject-prefix= +	--output-directory --reroll-count --to= --quiet --notes  "  _git_format_patch () @@ -1354,7 +1266,6 @@ _git_fsck ()  		return  		;;  	esac -	COMPREPLY=()  }  _git_gc () @@ -1365,7 +1276,6 @@ _git_gc ()  		return  		;;  	esac -	COMPREPLY=()  }  _git_gitk () @@ -1442,7 +1352,6 @@ _git_init ()  		return  		;;  	esac -	COMPREPLY=()  }  _git_ls_files () @@ -1578,7 +1487,6 @@ _git_mergetool ()  		return  		;;  	esac -	COMPREPLY=()  }  _git_merge_base () @@ -1819,7 +1727,7 @@ __git_config_get_set_variables ()  _git_config ()  {  	case "$prev" in -	branch.*.remote) +	branch.*.remote|branch.*.pushremote)  		__gitcomp_nl "$(__git_remotes)"  		return  		;; @@ -1827,11 +1735,19 @@ _git_config ()  		__gitcomp_nl "$(__git_refs)"  		return  		;; +	branch.*.rebase) +		__gitcomp "false true" +		return +		;; +	remote.pushdefault) +		__gitcomp_nl "$(__git_remotes)" +		return +		;;  	remote.*.fetch)  		local remote="${prev#remote.}"  		remote="${remote%.fetch}"  		if [ -z "$cur" ]; then -			COMPREPLY=("refs/heads/") +			__gitcomp_nl "refs/heads/" "" "" ""  			return  		fi  		__gitcomp_nl "$(__git_refs_remotes "$remote")" @@ -1866,6 +1782,10 @@ _git_config ()  			"  		return  		;; +	diff.submodule) +		__gitcomp "log short" +		return +		;;  	help.format)  		__gitcomp "man info web html"  		return @@ -1891,7 +1811,6 @@ _git_config ()  		return  		;;  	*.*) -		COMPREPLY=()  		return  		;;  	esac @@ -1908,7 +1827,7 @@ _git_config ()  		;;  	branch.*.*)  		local pfx="${cur%.*}." cur_="${cur##*.}" -		__gitcomp "remote merge mergeoptions rebase" "$pfx" "$cur_" +		__gitcomp "remote pushremote merge mergeoptions rebase" "$pfx" "$cur_"  		return  		;;  	branch.*) @@ -2039,7 +1958,6 @@ _git_config ()  		core.fileMode  		core.fsyncobjectfiles  		core.gitProxy -		core.ignoreCygwinFSTricks  		core.ignoreStat  		core.ignorecase  		core.logAllRefUpdates @@ -2061,13 +1979,14 @@ _git_config ()  		core.whitespace  		core.worktree  		diff.autorefreshindex -		diff.statGraphWidth  		diff.external  		diff.ignoreSubmodules  		diff.mnemonicprefix  		diff.noprefix  		diff.renameLimit  		diff.renames +		diff.statGraphWidth +		diff.submodule  		diff.suppressBlankEmpty  		diff.tool  		diff.wordRegex @@ -2202,6 +2121,7 @@ _git_config ()  		receive.fsckObjects  		receive.unpackLimit  		receive.updateserverinfo +		remote.pushdefault  		remotes.  		repack.usedeltabaseoffset  		rerere.autoupdate @@ -2272,7 +2192,6 @@ _git_remote ()  		__gitcomp "$c"  		;;  	*) -		COMPREPLY=()  		;;  	esac  } @@ -2356,7 +2275,7 @@ _git_show ()  		return  		;;  	esac -	__git_complete_file +	__git_complete_revlist_file  }  _git_show_branch () @@ -2388,8 +2307,6 @@ _git_stash ()  		*)  			if [ -z "$(__git_find_on_cmdline "$save_opts")" ]; then  				__gitcomp "$subcommands" -			else -				COMPREPLY=()  			fi  			;;  		esac @@ -2402,14 +2319,12 @@ _git_stash ()  			__gitcomp "--index --quiet"  			;;  		show,--*|drop,--*|branch,--*) -			COMPREPLY=()  			;;  		show,*|apply,*|drop,*|pop,*|branch,*)  			__gitcomp_nl "$(git --git-dir="$(__gitdir)" stash list \  					| sed -n -e 's/:.*//p')"  			;;  		*) -			COMPREPLY=()  			;;  		esac  	fi @@ -2419,7 +2334,7 @@ _git_submodule ()  {  	__git_has_doubledash && return -	local subcommands="add status init update summary foreach sync" +	local subcommands="add status init deinit update summary foreach sync"  	if [ -z "$(__git_find_on_cmdline "$subcommands")" ]; then  		case "$cur" in  		--*) @@ -2451,7 +2366,7 @@ _git_svn ()  			--no-metadata --use-svm-props --use-svnsync-props  			--log-window-size= --no-checkout --quiet  			--repack-flags --use-log-author --localtime -			--ignore-paths= $remote_opts +			--ignore-paths= --include-paths= $remote_opts  			"  		local init_opts="  			--template= --shared= --trunk= --tags= @@ -2526,7 +2441,6 @@ _git_svn ()  			__gitcomp "--revision= --parent"  			;;  		*) -			COMPREPLY=()  			;;  		esac  	fi @@ -2551,13 +2465,10 @@ _git_tag ()  	case "$prev" in  	-m|-F) -		COMPREPLY=()  		;;  	-*|tag)  		if [ $f = 1 ]; then  			__gitcomp_nl "$(__git_tags)" -		else -			COMPREPLY=()  		fi  		;;  	*) @@ -2579,9 +2490,10 @@ __git_main ()  		i="${words[c]}"  		case "$i" in  		--git-dir=*) __git_dir="${i#--git-dir=}" ;; +		--git-dir)   ((c++)) ; __git_dir="${words[c]}" ;;  		--bare)      __git_dir="." ;;  		--help) command="help"; break ;; -		-c) c=$((++c)) ;; +		-c|--work-tree|--namespace) ((c++)) ;;  		-*) ;;  		*) command="$i"; break ;;  		esac @@ -2599,6 +2511,7 @@ __git_main ()  			--exec-path  			--exec-path=  			--html-path +			--man-path  			--info-path  			--work-tree=  			--namespace= @@ -2693,35 +2606,19 @@ if [[ -n ${ZSH_VERSION-} ]]; then  		compadd -Q -p "${2-}" -f -- ${=1} && _ret=0  	} -	__git_zsh_helper () -	{ -		emulate -L ksh -		local cur cword prev -		cur=${words[CURRENT-1]} -		prev=${words[CURRENT-2]} -		let cword=CURRENT-1 -		__${service}_main -	} -  	_git ()  	{ -		emulate -L zsh -		local _ret=1 -		__git_zsh_helper -		let _ret && _default -S '' && _ret=0 +		local _ret=1 cur cword prev +		cur=${words[CURRENT]} +		prev=${words[CURRENT-1]} +		let cword=CURRENT-1 +		emulate ksh -c __${service}_main +		let _ret && _default && _ret=0  		return _ret  	}  	compdef _git git gitk  	return -elif [[ -n ${BASH_VERSION-} ]]; then -	if ((${BASH_VERSINFO[0]} < 4)); then -		# compopt is not supported -		__git_index_file_list_filter () -		{ -			__git_index_file_list_filter_compat -		} -	fi  fi  __git_func_wrap () diff --git a/plugins/gitfast/git-prompt.sh b/plugins/gitfast/git-prompt.sh index 65f8368f1..a81ef5a48 100644 --- a/plugins/gitfast/git-prompt.sh +++ b/plugins/gitfast/git-prompt.sh @@ -3,7 +3,7 @@  # Copyright (C) 2006,2007 Shawn O. Pearce <spearce@spearce.org>  # Distributed under the GNU General Public License, version 2.0.  # -# This script allows you to see the current branch in your prompt. +# This script allows you to see repository status in your prompt.  #  # To enable:  # @@ -13,23 +13,27 @@  #    3a) Change your PS1 to call __git_ps1 as  #        command-substitution:  #        Bash: PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ ' -#        ZSH:  PS1='[%n@%m %c$(__git_ps1 " (%s)")]\$ ' +#        ZSH:  setopt PROMPT_SUBST ; PS1='[%n@%m %c$(__git_ps1 " (%s)")]\$ '  #        the optional argument will be used as format string. -#    3b) Alternatively, if you are using bash, __git_ps1 can be -#        used for PROMPT_COMMAND with two parameters, <pre> and -#        <post>, which are strings you would put in $PS1 before -#        and after the status string generated by the git-prompt -#        machinery.  e.g. -#           PROMPT_COMMAND='__git_ps1 "\u@\h:\w" "\\\$ "' -#        will show username, at-sign, host, colon, cwd, then -#        various status string, followed by dollar and SP, as -#        your prompt. +#    3b) Alternatively, for a slightly faster prompt, __git_ps1 can +#        be used for PROMPT_COMMAND in Bash or for precmd() in Zsh +#        with two parameters, <pre> and <post>, which are strings +#        you would put in $PS1 before and after the status string +#        generated by the git-prompt machinery.  e.g. +#        Bash: PROMPT_COMMAND='__git_ps1 "\u@\h:\w" "\\\$ "' +#          will show username, at-sign, host, colon, cwd, then +#          various status string, followed by dollar and SP, as +#          your prompt. +#        ZSH:  precmd () { __git_ps1 "%n" ":%~$ " "|%s" } +#          will show username, pipe, then various status string, +#          followed by colon, cwd, dollar and SP, as your prompt.  #        Optionally, you can supply a third argument with a printf  #        format string to finetune the output of the branch status  # -# The argument to __git_ps1 will be displayed only if you are currently -# in a git repository.  The %s token will be the name of the current -# branch. +# The repository status will be displayed only if you are currently in a +# git repository. The %s token is the placeholder for the shown status. +# +# The prompt status always includes the current branch name.  #  # In addition, if you set GIT_PS1_SHOWDIRTYSTATE to a nonempty value,  # unstaged (*) and staged (+) changes will be shown next to the branch @@ -77,31 +81,8 @@  #  # If you would like a colored hint about the current dirty state, set  # GIT_PS1_SHOWCOLORHINTS to a nonempty value. The colors are based on -# the colored output of "git status -sb". - -# __gitdir accepts 0 or 1 arguments (i.e., location) -# returns location of .git repo -__gitdir () -{ -	# Note: this function is duplicated in git-completion.bash -	# When updating it, make sure you update the other one to match. -	if [ -z "${1-}" ]; then -		if [ -n "${__git_dir-}" ]; then -			echo "$__git_dir" -		elif [ -n "${GIT_DIR-}" ]; then -			test -d "${GIT_DIR-}" || return 1 -			echo "$GIT_DIR" -		elif [ -d .git ]; then -			echo .git -		else -			git rev-parse --git-dir 2>/dev/null -		fi -	elif [ -d "$1/.git" ]; then -		echo "$1/.git" -	else -		echo "$1" -	fi -} +# the colored output of "git status -sb" and are available only when +# using __git_ps1 for PROMPT_COMMAND or precmd.  # stores the divergence from upstream in $p  # used by GIT_PS1_SHOWUPSTREAM @@ -124,7 +105,7 @@ __git_ps1_show_upstream ()  			fi  			;;  		svn-remote.*.url) -			svn_remote[ $((${#svn_remote[@]} + 1)) ]="$value" +			svn_remote[$((${#svn_remote[@]} + 1))]="$value"  			svn_url_pattern+="\\|$value"  			upstream=svn+git # default upstream is SVN if available, else git  			;; @@ -146,10 +127,11 @@ __git_ps1_show_upstream ()  	svn*)  		# get the upstream from the "git-svn-id: ..." in a commit message  		# (git-svn uses essentially the same procedure internally) -		local svn_upstream=($(git log --first-parent -1 \ +		local -a svn_upstream +		svn_upstream=($(git log --first-parent -1 \  					--grep="^git-svn-id: \(${svn_url_pattern#??}\)" 2>/dev/null))  		if [[ 0 -ne ${#svn_upstream[@]} ]]; then -			svn_upstream=${svn_upstream[ ${#svn_upstream[@]} - 2 ]} +			svn_upstream=${svn_upstream[${#svn_upstream[@]} - 2]}  			svn_upstream=${svn_upstream%@*}  			local n_stop="${#svn_remote[@]}"  			for ((n=1; n <= n_stop; n++)); do @@ -222,6 +204,51 @@ __git_ps1_show_upstream ()  } +# Helper function that is meant to be called from __git_ps1.  It +# injects color codes into the appropriate gitstring variables used +# to build a gitstring. +__git_ps1_colorize_gitstring () +{ +	if [[ -n ${ZSH_VERSION-} ]]; then +		local c_red='%F{red}' +		local c_green='%F{green}' +		local c_lblue='%F{blue}' +		local c_clear='%f' +	else +		# Using \[ and \] around colors is necessary to prevent +		# issues with command line editing/browsing/completion! +		local c_red='\[\e[31m\]' +		local c_green='\[\e[32m\]' +		local c_lblue='\[\e[1;34m\]' +		local c_clear='\[\e[0m\]' +	fi +	local bad_color=$c_red +	local ok_color=$c_green +	local flags_color="$c_lblue" + +	local branch_color="" +	if [ $detached = no ]; then +		branch_color="$ok_color" +	else +		branch_color="$bad_color" +	fi +	c="$branch_color$c" + +	z="$c_clear$z" +	if [ "$w" = "*" ]; then +		w="$bad_color$w" +	fi +	if [ -n "$i" ]; then +		i="$ok_color$i" +	fi +	if [ -n "$s" ]; then +		s="$flags_color$s" +	fi +	if [ -n "$u" ]; then +		u="$bad_color$u" +	fi +	r="$c_clear$r" +}  # __git_ps1 accepts 0 or 1 arguments (i.e., format string)  # when called from PS1 using command substitution @@ -254,39 +281,83 @@ __git_ps1 ()  		;;  	esac -	local g="$(__gitdir)" -	if [ -z "$g" ]; then +	local repo_info rev_parse_exit_code +	repo_info="$(git rev-parse --git-dir --is-inside-git-dir \ +		--is-bare-repository --is-inside-work-tree \ +		--short HEAD 2>/dev/null)" +	rev_parse_exit_code="$?" + +	if [ -z "$repo_info" ]; then  		if [ $pcmode = yes ]; then  			#In PC mode PS1 always needs to be set  			PS1="$ps1pc_start$ps1pc_end"  		fi -	else -		local r="" -		local b="" +		return +	fi + +	local short_sha +	if [ "$rev_parse_exit_code" = "0" ]; then +		short_sha="${repo_info##*$'\n'}" +		repo_info="${repo_info%$'\n'*}" +	fi +	local inside_worktree="${repo_info##*$'\n'}" +	repo_info="${repo_info%$'\n'*}" +	local bare_repo="${repo_info##*$'\n'}" +	repo_info="${repo_info%$'\n'*}" +	local inside_gitdir="${repo_info##*$'\n'}" +	local g="${repo_info%$'\n'*}" + +	local r="" +	local b="" +	local step="" +	local total="" +	if [ -d "$g/rebase-merge" ]; then +		read b 2>/dev/null <"$g/rebase-merge/head-name" +		read step 2>/dev/null <"$g/rebase-merge/msgnum" +		read total 2>/dev/null <"$g/rebase-merge/end"  		if [ -f "$g/rebase-merge/interactive" ]; then  			r="|REBASE-i" -			b="$(cat "$g/rebase-merge/head-name")" -		elif [ -d "$g/rebase-merge" ]; then +		else  			r="|REBASE-m" -			b="$(cat "$g/rebase-merge/head-name")" +		fi +	else +		if [ -d "$g/rebase-apply" ]; then +			read step 2>/dev/null <"$g/rebase-apply/next" +			read total 2>/dev/null <"$g/rebase-apply/last" +			if [ -f "$g/rebase-apply/rebasing" ]; then +				read b 2>/dev/null <"$g/rebase-apply/head-name" +				r="|REBASE" +			elif [ -f "$g/rebase-apply/applying" ]; then +				r="|AM" +			else +				r="|AM/REBASE" +			fi +		elif [ -f "$g/MERGE_HEAD" ]; then +			r="|MERGING" +		elif [ -f "$g/CHERRY_PICK_HEAD" ]; then +			r="|CHERRY-PICKING" +		elif [ -f "$g/REVERT_HEAD" ]; then +			r="|REVERTING" +		elif [ -f "$g/BISECT_LOG" ]; then +			r="|BISECTING" +		fi + +		if [ -n "$b" ]; then +			: +		elif [ -h "$g/HEAD" ]; then +			# symlink symbolic ref +			b="$(git symbolic-ref HEAD 2>/dev/null)"  		else -			if [ -d "$g/rebase-apply" ]; then -				if [ -f "$g/rebase-apply/rebasing" ]; then -					r="|REBASE" -				elif [ -f "$g/rebase-apply/applying" ]; then -					r="|AM" -				else -					r="|AM/REBASE" +			local head="" +			if ! read head 2>/dev/null <"$g/HEAD"; then +				if [ $pcmode = yes ]; then +					PS1="$ps1pc_start$ps1pc_end"  				fi -			elif [ -f "$g/MERGE_HEAD" ]; then -				r="|MERGING" -			elif [ -f "$g/CHERRY_PICK_HEAD" ]; then -				r="|CHERRY-PICKING" -			elif [ -f "$g/BISECT_LOG" ]; then -				r="|BISECTING" +				return  			fi - -			b="$(git symbolic-ref HEAD 2>/dev/null)" || { +			# is it a symbolic ref? +			b="${head#ref: }" +			if [ "$head" = "$b" ]; then  				detached=yes  				b="$(  				case "${GIT_PS1_DESCRIBE_STYLE-}" in @@ -300,100 +371,75 @@ __git_ps1 ()  					git describe --tags --exact-match HEAD ;;  				esac 2>/dev/null)" || -				b="$(cut -c1-7 "$g/HEAD" 2>/dev/null)..." || -				b="unknown" +				b="$short_sha..."  				b="($b)" -			} +			fi  		fi +	fi + +	if [ -n "$step" ] && [ -n "$total" ]; then +		r="$r $step/$total" +	fi -		local w="" -		local i="" -		local s="" -		local u="" -		local c="" -		local p="" +	local w="" +	local i="" +	local s="" +	local u="" +	local c="" +	local p="" -		if [ "true" = "$(git rev-parse --is-inside-git-dir 2>/dev/null)" ]; then -			if [ "true" = "$(git rev-parse --is-bare-repository 2>/dev/null)" ]; then -				c="BARE:" +	if [ "true" = "$inside_gitdir" ]; then +		if [ "true" = "$bare_repo" ]; then +			c="BARE:" +		else +			b="GIT_DIR!" +		fi +	elif [ "true" = "$inside_worktree" ]; then +		if [ -n "${GIT_PS1_SHOWDIRTYSTATE-}" ] && +		   [ "$(git config --bool bash.showDirtyState)" != "false" ] +		then +			git diff --no-ext-diff --quiet --exit-code || w="*" +			if [ -n "$short_sha" ]; then +				git diff-index --cached --quiet HEAD -- || i="+"  			else -				b="GIT_DIR!" -			fi -		elif [ "true" = "$(git rev-parse --is-inside-work-tree 2>/dev/null)" ]; then -			if [ -n "${GIT_PS1_SHOWDIRTYSTATE-}" ] && -			   [ "$(git config --bool bash.showDirtyState)" != "false" ] -			then -				git diff --no-ext-diff --quiet --exit-code || w="*" -				if git rev-parse --quiet --verify HEAD >/dev/null; then -					git diff-index --cached --quiet HEAD -- || i="+" -				else -					i="#" -				fi -			fi -			if [ -n "${GIT_PS1_SHOWSTASHSTATE-}" ]; then -				git rev-parse --verify refs/stash >/dev/null 2>&1 && s="$" +				i="#"  			fi +		fi +		if [ -n "${GIT_PS1_SHOWSTASHSTATE-}" ] && +		   [ -r "$g/refs/stash" ]; then +			s="$" +		fi -			if [ -n "${GIT_PS1_SHOWUNTRACKEDFILES-}" ] && -			   [ "$(git config --bool bash.showUntrackedFiles)" != "false" ] && -			   [ -n "$(git ls-files --others --exclude-standard)" ] -			then -				u="%%" -			fi +		if [ -n "${GIT_PS1_SHOWUNTRACKEDFILES-}" ] && +		   [ "$(git config --bool bash.showUntrackedFiles)" != "false" ] && +		   git ls-files --others --exclude-standard --error-unmatch -- '*' >/dev/null 2>/dev/null +		then +			u="%${ZSH_VERSION+%}" +		fi -			if [ -n "${GIT_PS1_SHOWUPSTREAM-}" ]; then -				__git_ps1_show_upstream -			fi +		if [ -n "${GIT_PS1_SHOWUPSTREAM-}" ]; then +			__git_ps1_show_upstream  		fi +	fi -		local f="$w$i$s$u" -		if [ $pcmode = yes ]; then -			local gitstring= -			if [ -n "${GIT_PS1_SHOWCOLORHINTS-}" ]; then -				local c_red='\e[31m' -				local c_green='\e[32m' -				local c_lblue='\e[1;34m' -				local c_clear='\e[0m' -				local bad_color=$c_red -				local ok_color=$c_green -				local branch_color="$c_clear" -				local flags_color="$c_lblue" -				local branchstring="$c${b##refs/heads/}" +	local z="${GIT_PS1_STATESEPARATOR-" "}" -				if [ $detached = no ]; then -					branch_color="$ok_color" -				else -					branch_color="$bad_color" -				fi +	# NO color option unless in PROMPT_COMMAND mode +	if [ $pcmode = yes ] && [ -n "${GIT_PS1_SHOWCOLORHINTS-}" ]; then +		__git_ps1_colorize_gitstring +	fi -				# Setting gitstring directly with \[ and \] around colors -				# is necessary to prevent wrapping issues! -				gitstring="\[$branch_color\]$branchstring\[$c_clear\]" +	local f="$w$i$s$u" +	local gitstring="$c${b##refs/heads/}${f:+$z$f}$r$p" -				if [ -n "$w$i$s$u$r$p" ]; then -					gitstring="$gitstring " -				fi -				if [ "$w" = "*" ]; then -					gitstring="$gitstring\[$bad_color\]$w" -				fi -				if [ -n "$i" ]; then -					gitstring="$gitstring\[$ok_color\]$i" -				fi -				if [ -n "$s" ]; then -					gitstring="$gitstring\[$flags_color\]$s" -				fi -				if [ -n "$u" ]; then -					gitstring="$gitstring\[$bad_color\]$u" -				fi -				gitstring="$gitstring\[$c_clear\]$r$p" -			else -				gitstring="$c${b##refs/heads/}${f:+ $f}$r$p" -			fi +	if [ $pcmode = yes ]; then +		if [[ -n ${ZSH_VERSION-} ]]; then  			gitstring=$(printf -- "$printf_format" "$gitstring") -			PS1="$ps1pc_start$gitstring$ps1pc_end"  		else -			# NO color option unless in PROMPT_COMMAND mode -			printf -- "$printf_format" "$c${b##refs/heads/}${f:+ $f}$r$p" +			printf -v gitstring -- "$printf_format" "$gitstring"  		fi +		PS1="$ps1pc_start$gitstring$ps1pc_end" +	else +		printf -- "$printf_format" "$gitstring"  	fi  } | 
