diff options
Diffstat (limited to 'Completion/Unix/Command/_git')
-rw-r--r-- | Completion/Unix/Command/_git | 312 |
1 files changed, 179 insertions, 133 deletions
diff --git a/Completion/Unix/Command/_git b/Completion/Unix/Command/_git index b8edc109e..0d705a9da 100644 --- a/Completion/Unix/Command/_git +++ b/Completion/Unix/Command/_git @@ -132,7 +132,7 @@ _git-archive () { declare -a backend_args - if (( words[(I)--format=*] > 0 && words[(I)--format=*] < CURRENT )); then + if (( words[(b:CURRENT-1:I)--format=*] )); then case ${words[$words[(I)--format=*]]#--format=} in (zip) backend_args=( @@ -442,7 +442,7 @@ _git-checkout () { '(-b -B -t --track --patch --detach)--orphan[create a new orphan branch based at given commit]: :__git_branch_names' \ '--ignore-skip-worktree-bits[ignores patterns and adds back any files in <paths>]' \ '(-q --quiet -f --force -m --merge --conflict --patch)'{-m,--merge}'[3way merge current branch, working tree and new branch]' \ - '(-q --quiet -f --force -m --merge --patch)--conflict[same as --merge, using given merge style]:style:(merge diff3)' \ + '(-q --quiet -f --force -m --merge --patch)--conflict=[same as --merge, using given merge style]:style:(merge diff3)' \ '(-)'{-p,--patch}'[interactively select hunks in diff between given tree-ish and working tree]' \ '(-)--[start file arguments]' \ '*:: :->branch-or-tree-ish-or-file' && ret=0 @@ -456,14 +456,13 @@ _git-checkout () { [[ $line[CURRENT] = -* ]] && return if (( CURRENT == 1 )) && [[ -z $opt_args[(I)--] ]]; then # TODO: Allow A...B - local branch_arg='branches::__git_revisions' \ + local branch_arg='' \ remote_branch_noprefix_arg='remote branches::__git_remote_branch_names_noprefix' \ tree_ish_arg='tree-ishs::__git_tree_ishs' \ file_arg='modified-files::__git_modified_files' if [[ -n ${opt_args[(I)-b|-B|--orphan|--detach]} ]]; then remote_branch_noprefix_arg= - tree_ish_arg= file_arg= elif [[ -n $opt_args[(I)--track] ]]; then branch_arg='remote-branches::__git_remote_branch_names' @@ -471,7 +470,6 @@ _git-checkout () { tree_ish_arg= file_arg= elif [[ -n ${opt_args[(I)--ours|--theirs|-m|--conflict|--patch]} ]]; then - branch_arg= remote_branch_noprefix_arg= fi @@ -924,7 +922,7 @@ _git-grep () { # TODO: Need to implement -<num> as a shorthand for -C<num> _arguments -C -A '-*' \ '(-O --open-files-in-pager --no-index)--cached[search blobs registered in index file instead of working tree]' \ - '(--cached)--no-index[search files in current directory, not just treacked files]' \ + '(--cached)--no-index[search files in current directory, not just tracked files]' \ '(--exclude-standard)--no-exclude-standard[also search in ignored files]' \ '(--no-exclude-standard)--exclude-standard[exclude files standard ignore mechanisms]' \ '--untracked[search in untracked files]' \ @@ -950,7 +948,7 @@ _git-grep () { '(-z --null)'{-z,--null}'[output \0 after filenames]' \ '(-c --count)'{-c,--count}'[show number of matching lines in files]' \ '( --no-color)--color=-[color matches]:: :__git_color_whens' \ - '(--color )---no-color[do not color matches]' \ + '(--color )--no-color[do not color matches]' \ '--break[prefix the line number to matching lines]' \ '--heading[show the filename above the matches]' \ '(-A --after-context)'{-A,--after-context=}'[show <num> trailing lines, and separate groups of matches]: :__git_guard_number lines' \ @@ -1089,33 +1087,36 @@ _git-log () { $revision_options \ '-L+[trace the evolution of a line range or regex within a file]:range' \ '(-)--[start file arguments]' \ - '*:: :->commit-range-or-file' && ret=0 + '1: :->first-commit-ranges-or-files' \ + '*: :->commit-ranges-or-files' && ret=0 case $state in - (commit-range-or-file) - case $CURRENT in - (1) - if [[ -n ${opt_args[(I)--]} ]]; then - __git_cached_files && ret=0 - else - _alternative \ - 'commit-ranges::__git_commit_ranges' \ - 'cached-files::__git_cached_files' && ret=0 - fi - ;; - (*) - # TODO: Write a wrapper function that checks whether we have a - # committish range or comittish and calls __git_tree_files - # appropriately. - if __git_is_committish_range $line[1]; then - __git_tree_files ${PREFIX:-.} $(__git_committish_range_last $line[1]) && ret=0 - elif __git_is_committish $line[1]; then - __git_tree_files ${PREFIX:-.} $line[1] && ret=0 - else - __git_cached_files && ret=0 - fi - ;; - esac + (first-commit-ranges-or-files) + if [[ -n ${opt_args[(I)--]} ]]; then + __git_tree_files ${PREFIX:-.} HEAD && ret=0 + else + _alternative \ + 'commit-ranges::__git_commit_ranges' \ + 'cached-files::__git_tree_files ${PREFIX:-.} HEAD' && ret=0 + fi + ;; + (commit-ranges-or-files) + # Multiple revspecs are permitted. + if [[ -z ${opt_args[(I)--]} ]]; then + __git_commit_ranges "$@" && ret=0 + fi + + # TODO: Write a wrapper function that checks whether we have a + # committish range or comittish and calls __git_tree_files + # appropriately. + if __git_is_committish_range $line[1]; then + __git_tree_files ${PREFIX:-.} $(__git_committish_range_last $line[1]) && ret=0 + elif __git_is_committish $line[1]; then + __git_tree_files ${PREFIX:-.} $line[1] && ret=0 + else + __git_tree_files ${PREFIX:-.} HEAD && ret=0 + fi + ;; esac return ret @@ -1287,7 +1288,7 @@ _git-push () { '(--verify)--no-verify[bybass the pre-push hook]' \ '--recurse-submodules=[submodule handling]:submodule handling:((check\:"refuse pushing of supermodule if submodule commit cannot be found on the remote" on-demand\:"push all changed submodules"))' \ - ':: :__git_any_repositories' \ + ': :__git_any_repositories' \ '*: :__git_ref_specs' && ret=0 case $state in @@ -2925,7 +2926,6 @@ _git-config () { (*) # TODO: Do we need to set up a _requested/_next_label? declare -a action - local expl _description values expl "$parts[2]" eval "action=($parts[4])" "$action[1]" "$expl[@]" "${(@)action[2,-1]}" && ret=0 @@ -4976,8 +4976,8 @@ __git_is_treeish () { (( $+functions[__git_is_committish_range] )) || __git_is_committish_range () { [[ $1 == *..(.|)* ]] || return 1 - local first=$(__git_committish_range_first $1) - local last=$(__git_committish_range_last $1) + local first="$(__git_committish_range_first $1)" + local last="$(__git_committish_range_last $1)" [[ $first != *..* && $last != *..* ]] && \ __git_is_committish $first && \ __git_is_committish $last @@ -5025,7 +5025,16 @@ __git_ignore_line_inside_arguments () { (( $+functions[_git_commands] )) || _git_commands () { - local -a main_porcelain_commands + local -a cmdtypes + cmdtypes=( main_porcelain_commands user_commands + third_party_commands ancillary_manipulator_commands + ancillary_interrogator_commands interaction_commands + plumbing_manipulator_commands plumbing_interrogator_commands + plumbing_sync_commands plumbing_sync_helper_commands + plumbing_internal_helper_commands + ) + local -a $cmdtypes + main_porcelain_commands=( add:'add file contents to index' am:'apply patches from a mailbox' @@ -5064,7 +5073,6 @@ _git_commands () { submodule:'initialize, update, or inspect submodules' tag:'create, list, delete or verify tag object signed with GPG') - local -a ancillary_manipulator_commands ancillary_manipulator_commands=( config:'get and set repository or global options' fast-export:'data exporter' @@ -5079,7 +5087,6 @@ _git_commands () { repack:'pack unpacked objects in a repository' replace:'create, list, delete refs to replace objects') - local -a ancillary_interrogator_commands ancillary_interrogator_commands=( blame:'show what revision and author last modified each line of a file' cherry:'find commits not merged upstream' @@ -5097,7 +5104,6 @@ _git_commands () { verify-tag:'check GPG signature of tags' whatchanged:'show commit-logs and differences they introduce') - local -a interaction_commands interaction_commands=( archimport:'import an Arch repository into git' cvsexportcommit:'export a single commit to a CVS checkout' @@ -5109,7 +5115,6 @@ _git_commands () { send-email:'send collection of patches as emails' svn:'bidirectional operation between a Subversion repository and git') - local -a plumbing_manipulator_commands plumbing_manipulator_commands=( apply:'apply patch to files and/or to index' checkout-index:'copy files from index to working directory' @@ -5129,7 +5134,6 @@ _git_commands () { update-ref:'update object name stored in a reference safely' write-tree:'create tree from the current index') - local -a plumbing_interrogator_commands plumbing_interrogator_commands=( cat-file:'provide content or type information for repository objects' diff-files:'compare files in working tree and index' @@ -5149,7 +5153,6 @@ _git_commands () { var:'show git logical variable' verify-pack:'validate packed git archive files') - local -a plumbing_sync_commands plumbing_sync_commands=( daemon:'run a really simple server for git repositories' fetch-pack:'receive missing objects from another repository' @@ -5157,7 +5160,6 @@ _git_commands () { send-pack:'push objects over git protocol to another repository' update-server-info:'update auxiliary information file to help dumb servers') - local -a plumbing_sync_helper_commands plumbing_sync_helper_commands=( http-fetch:'download from remote git repository via HTTP' http-push:'push objects over HTTP/DAV to another repository' @@ -5167,7 +5169,6 @@ _git_commands () { upload-archive:'send archive back to git-archive' upload-pack:'send objects packed back to git fetch-pack') - local -a plumbing_internal_helper_commands plumbing_internal_helper_commands=( check-attr:'display gitattributes information' check-ignore:'debug gitignore/exclude files' @@ -5180,91 +5181,41 @@ _git_commands () { patch-id:'compute unique ID for a patch' stripspace:'filter out empty lines') - local -a user_commands zstyle -a :completion:$curcontext: user-commands user_commands - local -a third_party_commands local command for command in $_git_third_party_commands; do (( $+commands[git-${command%%:*}] )) && third_party_commands+=$command done - local -a aliases unique_aliases + local -a aliases __git_extract_aliases - local alias - for alias in $aliases; do - local name=${alias%%:*} - (( main_porcelain_commands[(I)$name:*] || - user_commands[(I)$name:*] || - third_party_commands[(I)$name:*] || - ancillary_manipulator_commands[(I)$name:*] || - ancillary_interrogator_commands[(I)$name:*] || - interaction_commands[(I)$name:*] || - plumbing_manipulator_commands[(I)$name:*] || - plumbing_interrogator_commands[(I)$name:*] || - plumbing_sync_commands[(I)$name:*] || - plumbing_sync_helper_commands[(I)$name:*] || - plumbing_internal_helper_commands[(I)$name:*] )) || unique_aliases+=$alias + local cmdtype len dup sep + local -a allcmds allmatching alts disp expl + + zstyle -s ":completion:${curcontext}:" list-separator sep || sep=-- + for cmdtype in $cmdtypes aliases; do + if [[ $cmdtype = aliases ]]; then + for dup in ${${aliases%:*}:*allcmds}; do + aliases=( ${aliases:#$dup:*} ) + done + fi + local -a ${cmdtype}_m + set -A ${cmdtype}_m ${(P)cmdtype%%:*} + allcmds+=( ${(P)${:-${cmdtype}_m}} ) done - - integer ret=1 - - _tags \ - aliases \ - main-porcelain-commands \ - user-commands \ - third-party-commands \ - ancillary-manipulator-commands \ - ancillary-interrogator-commands \ - interaction-commands \ - plumbing-manipulator-commands \ - plumbing-interrogator-commands \ - plumbing-sync-commands \ - plumbing-sync-helper-commands \ - plumbing-internal-helper-commands - - while _tags; do - - _requested aliases && \ - _describe -t aliases 'alias' unique_aliases && ret=0 - - _requested main-porcelain-commands && \ - _describe -t main-porcelain-commands 'main porcelain command' main_porcelain_commands && ret=0 - - _requested user-commands && \ - _describe -t user-commands 'user command' user_commands && ret=0 - - _requested third-party-commands && \ - _describe -t third-party-commands 'third-party command' third_party_commands && ret=0 - - _requested ancillary-manipulator-commands && \ - _describe -t ancillary-manipulator-commands 'ancillary manipulator command' ancillary_manipulator_commands && ret=0 - - _requested ancillary-interrogator-commands && \ - _describe -t ancillary-interrogator-commands 'ancillary interrogator command' ancillary_interrogator_commands && ret=0 - - _requested interaction-commands && \ - _describe -t interaction-commands 'interaction command' interaction_commands && ret=0 - - _requested plumbing-manipulator-commands && \ - _describe -t plumbing-manipulator-commands 'plumbing manipulator command' plumbing_manipulator_commands && ret=0 - - _requested plumbing-interrogator-commands && \ - _describe -t plumbing-interrogator-commands 'plumbing interrogator command' plumbing_interrogator_commands && ret=0 - - _requested plumbing-sync-commands && \ - _describe -t plumbing-sync-commands 'plumbing sync command' plumbing_sync_commands && ret=0 - - _requested plumbing-sync-helper-commands && \ - _describe -t plumbing-sync-helper-commands 'plumbing sync helper command' plumbing_sync_helper_commands && ret=0 - - _requested plumbing-internal-helper-commands && \ - _describe -t plumbing-internal-helper-commands 'plumbing internal helper command' plumbing_internal_helper_commands && ret=0 - - (( ret )) || break + zstyle -T ":completion:${curcontext}:" verbose && disp=(-ld '${cmdtype}_d') + _description '' expl '' # get applicable matchers + compadd "$expl[@]" -O allmatching -a allcmds + len=${#${(O)allmatching//?/.}[1]} # length of longest match + for cmdtype in aliases $cmdtypes; do + local -a ${cmdtype}_d + (( $#disp )) && set -A ${cmdtype}_d \ + ${${(Pr.COLUMNS-4.)cmdtype/(#s)(#m)[^:]##:/${(r.len.)MATCH[1,-2]} $sep }%% #} + alts+=( "${cmdtype//_/-}:${${cmdtype//_/ }%%(e|)s}:compadd ${(e)disp} -a ${cmdtype}_m" ) done - return ret + _alternative $alts } (( $+functions[__git_aliases] )) || @@ -5789,7 +5740,11 @@ __git_tree_ishs () { __git_objects () { compset -P '*:' if [[ -n $IPREFIX ]]; then - __git_tree_files "$PREFIX" "${IPREFIX%:}" + if compset -P ./ ; then + __git_tree_files "$PREFIX" "${IPREFIX%:./}" + else + __git_tree_files --root-relative "$PREFIX" "${IPREFIX%:}" + fi else _alternative \ 'revisions::__git_revisions' \ @@ -6034,12 +5989,23 @@ __git_changed_files () { 'changed-in-working-tree-files::__git_changed-in-working-tree_files' } +# __git_tree_files [--root-relative] FSPATH TREEISH [TREEISH...] [COMPADD OPTIONS] +# +# Complete [presently: a single level of] repository files under FSPATH. +# FSPATH is interpreted as a directory path within each TREEISH. +# FSPATH is relative to cwd, unless --root-relative is specified, in +# which case it is relative to the repository root. (( $+functions[__git_tree_files] )) || __git_tree_files () { local multi_parts_opts local tree Path integer at_least_one_tree_added local -a tree_files compadd_opts + local -a extra_args + + if [[ $1 == --root-relative ]]; then + extra_args+=(--full-tree) + fi zparseopts -D -E -a compadd_opts V: J: 1 2 n f X: M: P: S: r: R: q F: @@ -6047,7 +6013,7 @@ __git_tree_files () { shift (( at_least_one_tree_added = 0 )) for tree in $*; do - tree_files+=(${(ps:\0:)"$(_call_program tree-files git ls-tree --name-only -z $tree $Path 2>/dev/null)"}) + tree_files+=(${(ps:\0:)"$(_call_program tree-files git ls-tree $extra_args --name-only -z $tree $Path 2>/dev/null)"}) __git_command_successful $pipestatus && (( at_least_one_tree_added = 1 )) done @@ -6271,6 +6237,95 @@ __git_setup_diff_stage_options () { ) } +(( $+functions[__git_format_placeholders] )) || +__git_format_placeholders() { + local sep + local -a disp names placeholders expl + if compset -P 'format:'; then + compset -P '(%[^acgCG]|%?[^%]|[^%])#' + if compset -P '%C'; then + _wanted colors expl color compadd reset red green blue + return + fi + if [[ -prefix %G ]]; then + placeholders=( + 'GG:raw verification message' + 'G?:indicate [G]ood, [B]ad, [U]ntrusted or [N]o signature' + 'GS:name of signer' + 'GK:signing key' + ) + disp=( -l ) + elif [[ -prefix %g ]]; then + placeholders=( + gD:'reflog selector' + gd:'short reflog selector' + gn:'reflog identity' + gs:'reflog subject' + ) + disp=( -l ) + elif [[ $PREFIX = (#b)%([ac]) ]]; then + placeholders=( + n:'name' + N:'name (use .mailmap)' + e:'email' + E:'email (use .mailmap)' + d:'date' + D:'date, RFC2822 style' + r:'date, relative' + t:'date, UNIX timestamp' + i:'date, like ISO 8601' + I:'date, strict ISO 8601' + ) + placeholders=( $match[1]$^placeholders ) + else + placeholders=( + H:commit\ hash + h:'abbreviated commit hash' + T:'tree hash' + t:'abbreviated tree hash' + P:'parent hash' + p:'abbreviated parent hash' + a:'author details' + c:'committer details' + d:'ref name in brackets' + D:'ref name' + e:encoding + s:subject + f:'sanitized subject' + g:reflog + b:body + B:'raw body' + N:notes + G:GPG\ details + C:color + m:mark + n:newline + %:raw\ % + x:'hex code' + w:'switch line wrapping' + ) + fi + names=( ${placeholders%%:*} ) + if zstyle -T ":completion:${curcontext}:" verbose; then + zstyle -s ":completion:${curcontext}:" list-separator sep || sep=-- + zformat -a placeholders " $sep " $placeholders + disp+=(-d placeholders) + else + disp=() + fi + _wanted placeholders expl placeholder \ + compadd -p % -S '' "$disp[@]" "$@" - "$names[@]" + else + _describe -t formats format '( oneline:"commit-ids and subject of messages" + short:"few headers and only subject of messages" + medium:"most parts of messages" + full:"all parts of commit messages" + fuller:"like full and includes dates" + email:"use email headers like From and Subject" + raw:"the raw commits" )' -- '( format:"specify own format" )' -S ':' + fi +} + (( $+functions[__git_setup_revision_options] )) || __git_setup_revision_options () { local -a diff_options @@ -6278,16 +6333,7 @@ __git_setup_revision_options () { revision_options=( $diff_options - # TODO: format pretty print format is a lot more advanced than this. - # TODO: You can't actually specify --format without a format. - '(-v --header)'{--pretty=-,--format=-}'[pretty print commit messages]::format:((oneline\:"commit-ids and subject of messages" - short\:"few headers and only subject of messages" - medium\:"most parts of messages" - full\:"all parts of commit messages" - fuller\:"like full and includes dates" - email\:"use email headers like From and Subject" - raw\:"the raw commits" - format\:"specify own format"))' + '(-v --header)'{--pretty=-,--format=-}'[pretty print commit messages]::format:__git_format_placeholders' '(--abbrev-commit --no-abbrev-commit)--abbrev-commit[show only partial prefixes of commit object names]' '(--abbrev-commit --no-abbrev-commit)--no-abbrev-commit[show the full 40-byte hexadecimal commit object name]' '(--abbrev --no-abbrev)--abbrev=[set minimum SHA1 display-length (for use with --abbrev-commit)]: :__git_guard_number length' @@ -6329,8 +6375,8 @@ __git_setup_revision_options () { '*--not[reverses meaning of ^ prefix for revisions that follow]' '--all[show all commits from refs]' '--branches=-[show all commits from refs/heads]::pattern' - '--tags=[-show all commits from refs/tags]::pattern' - '--remotes=[-show all commits from refs/remotes]::pattern' + '--tags=-[show all commits from refs/tags]::pattern' + '--remotes=-[show all commits from refs/remotes]::pattern' '--glob=[show all commits from refs matching glob]:pattern' '--exclude=[do not include refs matching glob]:pattern' '--exclude=[do not include refs matching glob]:pattern' |