# (C) 2011-2021 magicant

# Completion script for the "git" command.
# Supports Git 2.9.2.

function completion/git {

	typeset OPTIONS ARGOPT PREFIX
	OPTIONS=( #>#
	"C:; specify a directory to operate in"
	"c:; specify a configuration parameter"
	"--bare; treat the repository as a bare repository"
	"--exec-path::; specify or print the directory containing core git executables"
	"--git-dir:; specify the repository directory"
	"--glob-pathspecs; enable globbing on all path-specs"
	"--html-path; print the directory where HTML documentation is installed"
	"--icase-pathspecs; treat path-specs case-insensitively"
	"--info-path; print the directory where info manuals are installed"
	"--literal-pathspecs; treat path-specs literally"
	"--man-path; print the directory where manual pages are installed"
	"--namespace:; specify a namespace"
	"--noglob-pathspecs; disable globbing on all path-specs"
	"p --paginate; run a pager to view Git's output"
	"--no-pager; don't run a pager to view Git's output"
	"--no-replace-objects; don't use replacement refs"
	"--work-tree:; specify the working tree directory"
	"--help"
	"--version"
	) #<#

	# convert "--help" to "help"
	typeset i=2
	while [ $i -le ${WORDS[#]} ]; do
		case ${WORDS[i]} in
		(-c|--git-dir|--work-tree)
			i=$((i+1))
			;;
		(--help)
			WORDS=("${WORDS[1,i-1]}" "help" "${WORDS[i+1,-1]}")
			;;
		(-?*)
			;;
		(*)
			break
			;;
		esac
		i=$((i+1))
	done

	command -f completion//parseoptions -n
	case $ARGOPT in
		(-)
			command -f completion//completeoptions
			;;
		(c)
			if command -vf completion//git::completeoptionname >/dev/null 2>&1 ||
					. -AL completion/git-config; then
				command -f completion//git::completeoptionname =
			fi
			;;
		(C|--exec-path|--git-dir|--work-tree)
			complete -P "$PREFIX" -S / -T -d
			;;
		('')
			# find first non-option argument and
			# parse some global options
			typeset OPTIND=2 gitcmd=
			while [ $OPTIND -le ${WORDS[#]} ]; do
				case ${WORDS[OPTIND]} in
					(-[Cc])
						OPTIND=$((OPTIND+1))
						;;
					(--exec-path=*)
						typeset -x GIT_EXEC_PATH="${WORDS[OPTIND]#*=}"
						;;
					(--git-dir)
						OPTIND=$((OPTIND+1))
						typeset -x GIT_DIR="${WORDS[OPTIND]}"
						;;
					(--git-dir=*)
						typeset -x GIT_DIR="${WORDS[OPTIND]#*=}"
						;;
					(--namespace)
						OPTIND=$((OPTIND+1))
						typeset -x GIT_NAMESPACE="${WORDS[OPTIND]}"
						;;
					(--namespace=*)
						typeset -x GIT_NAMESPACE="${WORDS[OPTIND]#*=}"
						;;
					(--work-tree)
						OPTIND=$((OPTIND+1))
						typeset -x GIT_WORK_TREE="${WORDS[OPTIND]}"
						;;
					(--work-tree=*)
						typeset -x GIT_WORK_TREE="${WORDS[OPTIND]#*=}"
						;;
					(-?*)
						;;
					(*)
						gitcmd=${WORDS[OPTIND]}
						break
						;;
				esac
				OPTIND=$((OPTIND+1))
			done

			if [ $OPTIND -le ${WORDS[#]} ]; then
				# resolve command alias
				typeset alias
				if alias="$(git config --get alias."$gitcmd")" 2>/dev/null; then
					case $alias in
					(!*)
						WORDS=(${alias#!} "${WORDS[OPTIND+1,-1]}")
						command -f completion//reexecute
						return
						;;
					(?*)
						WORDS=("${WORDS[1,OPTIND-1]}" \
							$alias "${WORDS[OPTIND+1,-1]}")
						gitcmd=${alias%%[[:space:]]*}
						;;
					esac
				fi
				OPTIND=$((OPTIND+1))

				# complete command argument
				typeset OLDWORDS
				OLDWORDS=("$WORDS")
				WORDS=("${WORDS[1]}" "${WORDS[OPTIND,-1]}")
				if [ ${WORDS[#]} -le 1 ]; then
					case $TARGETWORD in (-*)
						complete -- --help
					esac
				fi
				if { command -vf "completion/git::$gitcmd:arg" ||
						. -AL "completion/git-$gitcmd"; } >/dev/null 2>&1; then
					command -f "completion/git::$gitcmd:arg" 
				else
					complete -P "$PREFIX" -f
				fi
			else
				# complete command name
				command -f completion/git::completecmd
				command -f completion/git::completealias
			fi
			;;
	esac

}

function completion/git::completecmd { #>>#
	complete -P "$PREFIX" -D "add files to the index" add
	complete -P "$PREFIX" -D "apply patches from a mailbox" am
	complete -P "$PREFIX" -D "show a file with commit info" annotate blame
	complete -P "$PREFIX" -D "apply patches" apply
	complete -P "$PREFIX" -D "import an Arch repository" archimport
	complete -P "$PREFIX" -D "create an archive of file tree" archive
	complete -P "$PREFIX" -D "binary-search for a change that introduced a bug" bisect
	complete -P "$PREFIX" -D "list, create, or remove branches" branch
	complete -P "$PREFIX" -D "move objects and refs by archive" bundle
	complete -P "$PREFIX" -D "print info about object or files" cat-file
	# discouraged: complete -P "$PREFIX" -D "" check-attr
	# discouraged: complete -P "$PREFIX" -D "" check-ref-format
	complete -P "$PREFIX" -D "check out a branch to the working tree" checkout
	complete -P "$PREFIX" -D "copy files from the index to the working tree" checkout-index
	complete -P "$PREFIX" -D "list common commits between branches" cherry
	complete -P "$PREFIX" -D "apply the changes in existing commits" cherry-pick
	complete -P "$PREFIX" -D "commit using a GUI tool" citool
	complete -P "$PREFIX" -D "remove untracked files from the working tree" clean
	complete -P "$PREFIX" -D "copy a repository into a new directory" clone
	complete -P "$PREFIX" -D "record changes to the repository" commit
	complete -P "$PREFIX" -D "create a new commit object" commit-tree
	complete -P "$PREFIX" -D "show or set options" config
	complete -P "$PREFIX" -D "count unpacked objects and its disk consumption" count-objects
	complete -P "$PREFIX" -D "export a commit to a CVS checkout" cvsexportcommit
	complete -P "$PREFIX" -D "import a CVS repository" cvsimport
	complete -P "$PREFIX" -D "emulate a CVS server" cvsserver
	complete -P "$PREFIX" -D "simple TCP server" daemon
	complete -P "$PREFIX" -D "show the most recent tag reachable from a commit" describe
	complete -P "$PREFIX" -D "show differences between commits and files" diff
	complete -P "$PREFIX" -D "compare files in the index and working tree" diff-files
	complete -P "$PREFIX" -D "compare files in the index and a commit" diff-index
	complete -P "$PREFIX" -D "compare files in two tree object" diff-tree
	complete -P "$PREFIX" -D "run tools to view commit diff" difftool
	complete -P "$PREFIX" -D "dump objects in a text format" fast-export
	complete -P "$PREFIX" -D "import objects" fast-import
	complete -P "$PREFIX" -D "obtain objects and refs from another repository" fetch
	complete -P "$PREFIX" -D "fetch missing objects from another repository" fetch-pack
	complete -P "$PREFIX" -D "rewrite branches using shell commands" filter-branch
	# discouraged: complete -P "$PREFIX" -D "" fmt-merge-msg
	complete -P "$PREFIX" -D "run a command for each ref" for-each-ref
	complete -P "$PREFIX" -D "prepare patches for email submission" format-patch
	complete -P "$PREFIX" -D "verify integrity of the repository database" fsck
	complete -P "$PREFIX" -D "clean up and optimize the repository" gc
	complete -P "$PREFIX" -D "show the commit ID of a tar archive" get-tar-commit-id
	complete -P "$PREFIX" -D "search files using regular expressions" grep
	complete -P "$PREFIX" -D "GUI front end" gui
	complete -P "$PREFIX" -D "compute object IDs for files" hash-object
	complete -P "$PREFIX" -D "show help" help
	complete -P "$PREFIX" -D "server-side program for Git over HTTP" http-backend
	# discouraged: complete -P "$PREFIX" -D "" http-fetch
	# discouraged: complete -P "$PREFIX" -D "" http-push
	complete -P "$PREFIX" -D "send patches to an IMAP folder" imap-send
	complete -P "$PREFIX" -D "build a pack index file" index-pack
	complete -P "$PREFIX" -D "make a new empty repository" init
	complete -P "$PREFIX" -D "set up gitweb for browsing the repository" instaweb
	complete -P "$PREFIX" -D "show commit logs" log
	# deprecated: complete -P "$PREFIX" -D "recover lost refs" lost-found
	complete -P "$PREFIX" -D "show info on files in the index and working tree" ls-files
	complete -P "$PREFIX" -D "list remote refs" ls-remote
	complete -P "$PREFIX" -D "list files in a tree object" ls-tree
	# discouraged: complete -P "$PREFIX" -D "" mailinfo
	# discouraged: complete -P "$PREFIX" -D "" mailsplit
	complete -P "$PREFIX" -D "merge branches" merge
	complete -P "$PREFIX" -D "find a good common ancestor for a merge" merge-base
	complete -P "$PREFIX" -D "perform 3-way merge" merge-file
	complete -P "$PREFIX" -D "run a merge program" merge-index
	# discouraged: complete -P "$PREFIX" -D "" merge-one-file
	complete -P "$PREFIX" -D "show results of a 3-way merge" merge-tree
	complete -P "$PREFIX" -D "run tools to resolve merge conflicts" mergetool
	complete -P "$PREFIX" -D "create a tag object" mktag
	complete -P "$PREFIX" -D "create a tree object" mktree
	complete -P "$PREFIX" -D "move files" mv
	complete -P "$PREFIX" -D "show a symbolic name for a commit" name-rev
	complete -P "$PREFIX" -D "manipulate object notes" notes
	complete -P "$PREFIX" -D "pack objects into an archive" pack-objects
	complete -P "$PREFIX" -D "find redundant packs" pack-redundant
	complete -P "$PREFIX" -D "pack refs into a single file for performance" pack-refs
	# discouraged: complete -P "$PREFIX" -D "" parse-remote
	# discouraged: complete -P "$PREFIX" -D "" patch-id
	# deprecated: complete -P "$PREFIX" -D "" peek-remote
	# discouraged: complete -P "$PREFIX" -D "" prune
	complete -P "$PREFIX" -D "remove redundant objects that are already packed" prune-packed
	complete -P "$PREFIX" -D "fetch and merge remote branches" pull
	complete -P "$PREFIX" -D "send objects and update remote refs" push
	complete -P "$PREFIX" -D "apply a quilt patch set" quiltimport
	complete -P "$PREFIX" -D "read a tree into the index" read-tree
	complete -P "$PREFIX" -D "change the branching point of a branch" rebase
	# discouraged: complete -P "$PREFIX" -D "" receive-pack
	complete -P "$PREFIX" -D "manipulate logs of revs" reflog
	complete -P "$PREFIX" -D "hard-link common objects in local repositories" relink
	complete -P "$PREFIX" -D "manage remote repository settings" remote
	complete -P "$PREFIX" -D "pack unpacked objects" repack
	complete -P "$PREFIX" -D "manipulate object replacements" replace
	# deprecated: complete -P "$PREFIX" -D "" repo-config
	complete -P "$PREFIX" -D "print a message that helps a pull request" request-pull
	# discouraged: complete -P "$PREFIX" -D "" rerere
	complete -P "$PREFIX" -D "restore the index and working tree" reset
	complete -P "$PREFIX" -D "list commit objects" rev-list
	complete -P "$PREFIX" -D "parse git command arguments" rev-parse
	complete -P "$PREFIX" -D "undo some commits" revert
	complete -P "$PREFIX" -D "remove files" rm
	complete -P "$PREFIX" -D "send patches as emails" send-email
	complete -P "$PREFIX" -D "send objects to another repository" send-pack
	# discouraged: complete -P "$PREFIX" -D "" sh-setup
	# discouraged: complete -P "$PREFIX" -D "" shell
	complete -P "$PREFIX" -D "print a summary of commit logs" shortlog
	complete -P "$PREFIX" -D "show objects" show
	complete -P "$PREFIX" -D "list branches and their commits" show-branch
	complete -P "$PREFIX" -D "show packed archive index" show-index
	complete -P "$PREFIX" -D "list refs in the repository" show-ref
	complete -P "$PREFIX" -D "manipulate stashes" stash
	complete -P "$PREFIX" -D "show the status of the working tree" status
	# discouraged: complete -P "$PREFIX" -D "" stripspace
	complete -P "$PREFIX" -D "manipulate submodules" submodule
	complete -P "$PREFIX" -D "operate with a Subversion repository" svn
	complete -P "$PREFIX" -D "make or resolve a symbolic ref" symbolic-ref
	complete -P "$PREFIX" -D "manipulate tags" tag
	# deprecated: complete -P "$PREFIX" -D "" tar-tree
	complete -P "$PREFIX" -D "create a temporary file for a blob" unpack-file
	complete -P "$PREFIX" -D "unpack objects from an archive" unpack-objects
	complete -P "$PREFIX" -D "register file contents in the working tree to the index" update-index
	complete -P "$PREFIX" -D "modify a ref's target safely" update-ref
	complete -P "$PREFIX" -D "update auxiliary files for dumb servers" update-server-info
	# discouraged: complete -P "$PREFIX" -D "" upload-archive
	# discouraged: complete -P "$PREFIX" -D "" upload-pack
	complete -P "$PREFIX" -D "show a git logical variable" var
	complete -P "$PREFIX" -D "check integrity of packed objects" verify-pack
	complete -P "$PREFIX" -D "check the GPG signature of tags" verify-tag
	complete -P "$PREFIX" -D "show logs and differences between commits" whatchanged
	complete -P "$PREFIX" -D "manage additional working trees" worktree
	complete -P "$PREFIX" -D "create a tree object from the index" write-tree
	#<<#
	typeset cmd
	while read -r cmd; do
		cmd=${cmd##*/}
		complete -P "$PREFIX" -- "${cmd#git-}"
	done 2>/dev/null <(command -f completion//allcommands 'git-*')
}

function completion/git::completealias {
	typeset usesuffix= suffix
	if [ $# -gt 0 ]; then
		usesuffix=true suffix=$1
	fi

	typeset name value
	while read -r name value; do
		complete -P "$PREFIX" -D "= $value" ${usesuffix:+-S "$suffix" -T} \
			-- "${name#alias.}"
	done 2>/dev/null <(git config --get-regexp 'alias\..*')
}

function completion/git::completeref {

	typeset abbrprefixes completefull=true range usesuffix= suffix
	abbrprefixes=(refs/ refs/tags/ refs/heads/ refs/remotes/)
	while [ $# -gt 0 ]; do
		case $1 in
		(abbrprefixes=*)
			abbrprefixes=(${1#abbrprefixes=})
			;;
		(dontcompletefull=*)
			completefull=
			;;
		(suffix=*)
			usesuffix=true suffix=${1#suffix=}
			;;
		(range=*)
			typeset word="${TARGETWORD#"$PREFIX"}"
			case $word in (-*)
				complete -P "$PREFIX" -D "exclude following commits" -- --not
			esac
			word=${word##*..}
			typeset PREFIX="${TARGETWORD%"$word"}"
			;;
		(*)
			break
			;;
		esac
		shift
	done

	typeset targetword="${TARGETWORD#"$PREFIX"}"
	if [ $# -eq 0 ]; then
		complete -P "$PREFIX" ${usesuffix:+-S "$suffix" -T} -A '*HEAD' \
			-- $( (ls -- "$(git rev-parse --git-dir)") 2>/dev/null)
		set -- --all

		# complete commit ID
		if grep -Eq '^[[:xdigit:]]*$' <<<"$targetword" 2>/dev/null; then
			typeset id message
			while read -r id message; do
				complete -P "$PREFIX" -D "$message" \
					${usesuffix:+-S "$suffix" -T} -- "$id"
			done 2>/dev/null \
				<(git rev-list --all --oneline --date-order |
				grep "^$targetword" | head)
		fi
	fi

	# complete symbolic ref
	typeset fullref ref abbr
	typeset word="${targetword##*/}"
	typeset prefix="${targetword%"$word"}"
	while read -r fullref; do
		for abbr in ${completefull:+""} "$abbrprefixes"; do
			ref=${fullref#"$abbr"}
			case $ref in ("$targetword"*)
				ref="${ref#"$prefix"}"
				case $ref in
				(*/*)
					complete -P "$PREFIX$prefix" -S / -T -- "${ref%%/*}"
					;;
				(*)
					complete -P "$PREFIX$prefix" \
						${usesuffix:+-S "$suffix" -T} -- "$ref"
					;;
				esac
			esac
		done
	done 2>/dev/null <(git rev-parse --symbolic "$@")

}

# $1 = remote name
function completion/git::completeremoteref {
	typeset word="${TARGETWORD#"$PREFIX"}"
	case $word in
		(refs/heads/*)
			word=${word#refs/heads/}
			PREFIX=${TARGETWORD%"$word"}
			;;
		(*)
			# We don't have info about remote non-branch refs,
			# so complete local refs for tags. "--branches" is
			# specified so that "refs/heads/" can be a candidate.
			command -f completion/git::completeref \
				abbrprefixes= --symbolic-full-name \
				--branches --tags
			;;
	esac
	# complete remote tracking branches
	command -f completion/git::completeref \
		dontcompletefull=true abbrprefixes="refs/remotes/$1/" \
		--symbolic-full-name --remotes="$1"
}

function completion/git::completepath {

	if ! git rev-parse --git-dir >/dev/null 2>&1; then
		return 1
	fi

	typeset opt OPTIND=1 type=auto
	while getopts ar opt; do
		case $opt in
			(a) type=abs ;;
			(r) type=rel ;;
		esac
	done
	shift $((OPTIND-1))

	typeset tree="${1-HEAD}" targetpath="${TARGETWORD#"$PREFIX"}" lspath prefixpath
	if [ "$type" = auto ]; then
		case $targetpath in
			(./*|../*) type=rel ;;
			(*)        type=abs ;;
		esac
	fi
	case $type in
		(abs)
			lspath=${targetpath}
			;;
		(rel)
			lspath=$(git rev-parse --show-prefix)${targetpath}
			;;
	esac
	case $lspath in
		(*/*) lspath=${lspath%/*}/ ;;
		(*)   lspath= ;;
	esac
	case $targetpath in
		(*/*) prefixpath=${targetpath%/*}/ ;;
		(*)   prefixpath= ;;
	esac

	typeset PREFIX="$PREFIX$prefixpath"
	typeset mode type id path
	while read -r mode type id path; do
		case $type in
			(tree) opt='-S / -T' ;;
			(*)    opt= ;;
		esac
		complete -P "$PREFIX" $opt -- "${path##*/}"
	done 2>/dev/null <(git ls-tree --full-tree "$tree" -- "${lspath:-.}")

}

function completion/git::completerefpath {

	typeset i=2 hyphenhyphen=false treeish=HEAD
	while [ $i -le ${WORDS[#]} ]; do
		case "${WORDS[i]}" in
			(--)
				hyphenhyphen=true
				break
				;;
			(-*)
				;;
			(*)
				treeish=${WORDS[i]}
				;;
		esac
		i=$((i+1))
	done

	if ! $hyphenhyphen; then
		command -f completion/git::completeref "$@"
	fi

	if ! git show "$treeish^{tree}" >/dev/null 2>&1; then
		treeish=HEAD
	fi
	command -f completion/git::completepath -r "$treeish"

}

# $1 = regex to select paths
# $2... = options for "git status"
# not supporting $PREFIX
function completion/git::completefilteredpath {

	typeset dir="$(dirname -- "${TARGETWORD}X")"

	if ! (  typeset CDPATH= &&
		d1=$(                   git rev-parse --show-toplevel) &&
		d2=$(cd -P -- "$dir" && git rev-parse --show-toplevel) &&
		test "$d1" = "$d2") 2>/dev/null
	then
		# don't complete paths in submodule
		return
	fi

	typeset pathprefix="$({
		typeset CDPATH= && cd -P -- "$dir" &&
		git rev-parse --show-prefix
	} 2>/dev/null)"

	typeset prefix="${TARGETWORD%"${TARGETWORD##*/}"}"

	typeset file
	while read -r file; do
		file=${file#"$pathprefix"}
		case $file in
			(*/*)
				complete -P "$prefix" -S / -T -- "${file%%/*}"
				;;
			(*)
				complete -P "$prefix" -- "$file"
				;;
		esac
	done 2>/dev/null <(
		if [ "$#" -eq 0 ]; then
			git diff --name-only HEAD \
				${pathprefix:+-- "$pathprefix"}
		else
			git status --porcelain "${@[2,-1]}" -- "$dir/" |
			grep "${1-}" |
			cut -c 4- |
			sed 's/^.* -> //'
		fi
	)

}

function completion/git::completeobject {

	typeset targetword="${TARGETWORD#"$PREFIX"}"
	typeset t="$(sed 's;[@^]{[^}]*};;g' <<<"$targetword")"
	case $t in
		(*:*)
			typeset path="${t#*:}"
			typeset treeish="${targetword%":$path"}"
			typeset PREFIX="$PREFIX$treeish:"
			command -f completion/git::completepath "${treeish:-HEAD}"
			# XXX empty treeish should fall back to the current index rather than HEAD
			;;
		(*)
			command -f completion/git::completeref
			;;
	esac

}

function completion/git::completeremote {
	# XXX should complete on the basis of git-config
	typeset remote
	while read -r remote; do
		complete -P "$PREFIX" -- "$remote" # XXX description
	done 2>/dev/null <(
		gitdir=$(git rev-parse --git-dir) || exit
		git remote
		typeset CDPATH=
		(cd -P -- "$gitdir/remotes" && ls -A)
		(cd -P -- "$gitdir/branches" && ls -A)
	)
}

function completion/git::getorderopts {
	OPTIONS=("$OPTIONS" #>#
	"--author-date-order; sort commits by author date while keeping children before parent"
	"--date-order; sort commits by commit date while keeping children before parent"
	"--topo-order; show in topological order"
	) #<#
}

function completion/git::getprettyopts {
	OPTIONS=("$OPTIONS" #>#
	"--abbrev-commit; abbreviate commit IDs"
	"--encoding::; specify an output encoding"
	"--format:; specify an output format"
	"--no-abbrev-commit; print full commit IDs"
	"--no-notes --no-standard-notes; don't print notes"
	"--notes:: --standard-notes --show-notes::; print notes"
	"--oneline; like --format=oneline --abbrev-commit"
	"--pretty::; print in a human-friendly format"
	) #<#
}

function completion/git::completeprettyopts {
	case $ARGOPT in
		(--encoding)
			#TODO
			;;
		(--format|--pretty)
			command -f completion/git::--format:arg
			;;
		(--notes|--standard-notes|--show-notes)
			command -f completion/git::completeref abbrprefixes=refs/notes/ --glob=refs/notes
			;;
		(*)
			return 1
			;;
	esac
}

function completion/git::getrefselectopts {
	OPTIONS=("$OPTIONS" #>#
	"--all; print all commits reachable from any refs"
	"--branches::; print all (or specified) branches"
	"--exclude:; ignore refs that match the specified pattern"
	"--glob:; show refs that match the specified pattern"
	"--remotes::; print all (or specified) remote refs"
	"--tags::; print all (or specified) tags"
	) #<#
}

function completion/git::completerefselectopts
	case $ARGOPT in
		(--branches)
			command -f completion/git::completeref --branches
			;;
		(--exclude|--glob)
			command -f completion/git::completeref
			;;
		(--remotes)
			command -f completion/git::completeref --remotes
			;;
		(--tags)
			command -f completion/git::completeref --tags
			;;
		(*)
			return 1
			;;
	esac

function completion/git::--author:arg {
	typeset author
	while read -r author; do
		complete -P "$PREFIX" -- "$author"
	done 2>/dev/null <(git log --all --format=format:%an | uniq)
}

function completion/git::--color:arg { #>>#
	complete -P "$PREFIX" -D "always print in color" always
	complete -P "$PREFIX" -D "print in color if output is terminal" auto
	complete -P "$PREFIX" -D "don't print in color" never
} #<<#

function completion/git::--column:arg { #>>#
	complete -P "$PREFIX" -D "always print in columns" always
	complete -P "$PREFIX" -D "print in columns if output is terminal" auto
	complete -P "$PREFIX" -D "fill columns before rows" column
	complete -P "$PREFIX" -D "make columns as narrow as possible" dense
	complete -P "$PREFIX" -D "don't print in columns" never
	complete -P "$PREFIX" -D "keep all columns same-sized" nodense
	complete -P "$PREFIX" -D "print in one column" plain
	complete -P "$PREFIX" -D "fill rows before columns" row
} #<<#

function completion/git::--date:arg { #>>#
	complete -P "$PREFIX" -D "print relative time like \"2 hours ago\"" relative
	complete -P "$PREFIX" -D "print in original timezone" default
	complete -P "$PREFIX" -D "print in customized ISO 8601 format" iso8601
	complete -P "$PREFIX" -D "print in strict ISO 8601 format" iso8601-strict
	complete -P "$PREFIX" -D "print in RFC 2822 format" rfc2822
	complete -P "$PREFIX" -D "print in YYYY-MM-DD format" short
	complete -P "$PREFIX" -D "print the raw timestamp value" raw
	complete -P "$PREFIX" local relative-local default-local iso8601-local \
		iso8601-strict-local rfc2822-local short-local raw-local
	complete -P "$PREFIX" -D "specify a format" -T format:
} #<<#
# TODO --date=format:...%

function completion/git::--format:arg {
	typeset word="${TARGETWORD#"$PREFIX"}"
	word=${word//%%}
	case $word in
	(format:*%*|tformat:*%*)
		word=%${word##*%}
		typeset PREFIX="${TARGETWORD%"$word"}" #>>#
		complete -T -P "$PREFIX" -D "full commit ID" '%H'
		complete -T -P "$PREFIX" -D "abbreviated commit ID" '%h'
		complete -T -P "$PREFIX" -D "full tree ID" '%T'
		complete -T -P "$PREFIX" -D "abbreviated tree ID" '%t'
		complete -T -P "$PREFIX" -D "full parent IDs" '%P'
		complete -T -P "$PREFIX" -D "abbreviated parent IDs" '%p'
		complete -T -P "$PREFIX" -D "author name respecting .mailmap" '%aN'
		complete -T -P "$PREFIX" -D "author name" '%an'
		complete -T -P "$PREFIX" -D "author email respecting .mailmap" '%aE'
		complete -T -P "$PREFIX" -D "author email" '%ae'
		complete -T -P "$PREFIX" -D "author date in the RFC 2822 format" '%aD'
		complete -T -P "$PREFIX" -D "author date (relative)" '%ar'
		complete -T -P "$PREFIX" -D "author timestamp" '%at'
		complete -T -P "$PREFIX" -D "author date in the ISO 8601 format" '%ai'
		complete -T -P "$PREFIX" -D "committer name respecting .mailmap" '%cN'
		complete -T -P "$PREFIX" -D "committer name" '%cn'
		complete -T -P "$PREFIX" -D "committer email respecting .mailmap" '%cE'
		complete -T -P "$PREFIX" -D "committer email" '%ce'
		complete -T -P "$PREFIX" -D "committer date in the RFC 2822 format" '%cD'
		complete -T -P "$PREFIX" -D "committer date (relative)" '%cr'
		complete -T -P "$PREFIX" -D "committer timestamp" '%ct'
		complete -T -P "$PREFIX" -D "committer date in the ISO 8601 format" '%ci'
		complete -T -P "$PREFIX" -D "encoding" '%e'
		complete -T -P "$PREFIX" -D "subject" '%s'
		complete -T -P "$PREFIX" -D "subject (suitable for a filename)" '%f'
		complete -T -P "$PREFIX" -D "body" '%b'
		complete -T -P "$PREFIX" -D "raw body" '%B'
		complete -T -P "$PREFIX" -D "commit notes" '%N'
		complete -T -P "$PREFIX" -D "full reflog selector" '%gD'
		complete -T -P "$PREFIX" -D "abbreviated reflog selector" '%gd'
		complete -T -P "$PREFIX" -D "reflog subject" '%gs'
		complete -T -P "$PREFIX" -D "switch color to red" '%Cred'
		complete -T -P "$PREFIX" -D "switch color to green" '%Cgreen'
		complete -T -P "$PREFIX" -D "switch color to blue" '%Cblue'
		complete -T -P "$PREFIX" -D "reset color" '%Creset'
		complete -T -P "$PREFIX" -D "left, right, or boundary mark" '%m'
		complete -T -P "$PREFIX" -D "newline" '%n'
		# complete -T -P "$PREFIX" -D "" '%x'
		complete -T -P "$PREFIX" -D "enable line wrapping" '%w'
		complete -T -P "$PREFIX" -D "%" '%%'
		;; #<<#
	(*:*)
		;;
	(*) #>>#
		complete -P "$PREFIX" -D "commit ID and title" oneline
		complete -P "$PREFIX" -D "commit ID, author, and title" short
		complete -P "$PREFIX" -D "commit ID, author, date, and full log message" medium
		complete -P "$PREFIX" -D "commit ID, author, committer, and full log message" full
		complete -P "$PREFIX" -D "commit ID, author, date, committer, date, and full log message" fuller
		complete -P "$PREFIX" -D "imitate email" email
		complete -P "$PREFIX" -D "raw commit object" raw
		complete -P "$PREFIX" -D "specify a format (newline-separated)" -T format:
		complete -P "$PREFIX" -D "specify a format (newline-terminated)" -T tformat:
		#<<#
		typeset name value
		while read -r name value; do
			complete -P "$PREFIX" -D "= $value" -- "${name#pretty.}"
		done 2>/dev/null <(git config --get-regexp 'pretty\..*')
	esac
}

function completion/git::--ignore-submodules:arg { #>>#
	complete -P "$PREFIX" -D "ignore all changes in submodules" all
	complete -P "$PREFIX" -D "ignore uncommitted changes in submodules" dirty
	complete -P "$PREFIX" -D "show all changes in submodules" none
	complete -P "$PREFIX" -D "ignore untracked files in submodules" untracked
} #<<#

function completion/git::--pretty:arg {
	command -f completion/git::--format:arg "$@"
}

function completion/git::--receive-pack:arg {
	complete -P "$PREFIX" -S / -T -d
	# XXX should complete available remote commands
}

function completion/git::--recurse-submodules:arg { #>>#
	complete -P "$PREFIX" no
	complete -P "$PREFIX" -D "update a submodule when the superproject has been changed" on-demand
	complete -P "$PREFIX" yes
} #<<#

function completion/git::--untracked-files:arg { #>>#
	complete -P "$PREFIX" -D "print all individual files in untracked directories" all
	complete -P "$PREFIX" -D "print untracked files and directories" normal
	complete -P "$PREFIX" -D "don't print untracked files" no
} #<<#

function completion/git::--upload-pack:arg {
	complete -P "$PREFIX" -S / -T -d
	# XXX should complete available remote commands
}


# vim: set ft=sh ts=8 sts=8 sw=8 noet:
