[git completions] Complete branches faster

This saves one `git branch` invocation and improves the descriptions.
This commit is contained in:
Fabian Homborg 2018-01-31 21:47:13 +01:00
parent 0ab437be26
commit 18e21a0992

View file

@ -18,19 +18,14 @@ function __fish_git_recent_commits
| string replace -r '(.{73}).+' '$1…'
end
function __fish_git_local_branches
command git branch --no-color | string trim -c ' *'
end
function __fish_git_remote_branches
command git branch --no-color --remote | string trim -c ' *'
end
function __fish_git_branches
# In some cases, git can end up on no branch - e.g. with a detached head
# This will result in output like `* (no branch)` or a localized `* (HEAD detached at SHA)`
# The first `string match -v` filters it out because it's not useful as a branch argument
command git branch --no-color -a $argv ^/dev/null | string match -v '\* (*)' | string match -r -v ' -> ' | string trim -c "* " | string replace -r "^remotes/" ""
command git branch --no-color -a --format='%(refname)' $argv ^/dev/null \
# Filter out anything that's not in "refs/" notation -
# this happens mostly with a detached head ("(HEAD detached at SOMESHA)", localized).
| string replace -rf '^refs/' '' \
# We assume anything that's not remote is a local branch.
| string replace -r '^(?!remotes/)[^/]+/(.*)' '$1\tLocal Branch' \
| string replace -r "^remotes/(.*)" '$1\tRemote Branch'
end
function __fish_git_unique_remote_branches
@ -184,7 +179,8 @@ function __fish_git_ranges
end
set -l to (set -q both[2]; and echo $both[2])
for from_ref in (__fish_git_refs | string match "$from")
# Remove description from the from-ref, not the to-ref.
for from_ref in (__fish_git_refs | string match "$from" | string replace -r \t'.*$' '')
for to_ref in (__fish_git_refs | string match "*$to*") # if $to is empty, this correctly matches everything
printf "%s..%s\n" $from_ref $to_ref
end
@ -383,7 +379,7 @@ complete -f -c git -n '__fish_git_using_command log show diff-tree rev-list' -l
complete -f -c git -n '__fish_git_needs_command' -a fetch -d 'Download objects and refs from another repository'
# Suggest "repository", then "refspec" - this also applies to e.g. push/pull
complete -f -c git -n '__fish_git_using_command fetch; and not __fish_git_branch_for_remote' -a '(__fish_git_remotes)' -d 'Remote'
complete -f -c git -n '__fish_git_using_command fetch; and __fish_git_branch_for_remote' -a '(__fish_git_branch_for_remote)' -d 'Branch'
complete -f -c git -n '__fish_git_using_command fetch; and __fish_git_branch_for_remote' -a '(__fish_git_branch_for_remote)'
complete -f -c git -n '__fish_git_using_command fetch' -s q -l quiet -d 'Be quiet'
complete -f -c git -n '__fish_git_using_command fetch' -s v -l verbose -d 'Be verbose'
complete -f -c git -n '__fish_git_using_command fetch' -s a -l append -d 'Append ref names and object names'
@ -433,7 +429,7 @@ complete -f -c git -n "__fish_git_using_command remote; and __fish_seen_subcomma
### show
complete -f -c git -n '__fish_git_needs_command' -a show -d 'Shows the last commit of a branch'
complete -f -c git -n '__fish_git_using_command show' -a '(__fish_git_branches)' -d 'Branch'
complete -f -c git -n '__fish_git_using_command show' -a '(__fish_git_branches)'
complete -f -c git -n '__fish_git_using_command show' -a '(__fish_git_unique_remote_branches)' -d 'Remote branch'
complete -f -c git -n '__fish_git_using_command show' -a '(__fish_git_tags)' -d 'Tag'
complete -f -c git -n '__fish_git_using_command show' -a '(__fish_git_commits)'
@ -466,8 +462,7 @@ complete -f -c git -n '__fish_git_using_command add' -a '(__fish_git_files modif
### checkout
complete -f -c git -n '__fish_git_needs_command' -a checkout -d 'Checkout and switch to a branch'
complete -k -f -c git -n '__fish_git_using_command checkout' -a '(__fish_git_local_branches)' -d 'Local Branch'
complete -k -f -c git -n '__fish_git_using_command checkout' -a '(__fish_git_remote_branches)' -d 'Remote Branch'
complete -k -f -c git -n '__fish_git_using_command checkout' -a '(__fish_git_branches)'
complete -k -f -c git -n '__fish_git_using_command checkout' -a '(__fish_git_heads)' -d 'Head'
complete -k -f -c git -n '__fish_git_using_command checkout' -a '(__fish_git_unique_remote_branches)' -d 'Remote branch'
complete -k -f -c git -n '__fish_git_using_command checkout' -a '(__fish_git_tags)' -d 'Tag'
@ -492,7 +487,7 @@ complete -f -c git -n '__fish_git_needs_command' -a bisect -d 'Find the change t
### branch
complete -f -c git -n '__fish_git_needs_command' -a branch -d 'List, create, or delete branches'
complete -f -c git -n '__fish_git_using_command branch' -a '(__fish_git_branches)' -d 'Branch'
complete -f -c git -n '__fish_git_using_command branch' -a '(__fish_git_branches)'
complete -f -c git -n '__fish_git_using_command branch' -s d -d 'Delete branch'
complete -f -c git -n '__fish_git_using_command branch' -s D -d 'Force deletion of branch'
complete -f -c git -n '__fish_git_using_command branch' -s m -d 'Rename branch'
@ -506,7 +501,7 @@ complete -f -c git -n '__fish_git_using_command branch' -l no-merged -d 'List br
### cherry-pick
complete -f -c git -n '__fish_git_needs_command' -a cherry-pick -d 'Apply the change introduced by an existing commit'
complete -f -c git -n '__fish_git_using_command cherry-pick' -a '(__fish_git_branches --no-merged)' -d 'Branch'
complete -f -c git -n '__fish_git_using_command cherry-pick' -a '(__fish_git_branches --no-merged)'
complete -f -c git -n '__fish_git_using_command cherry-pick' -a '(__fish_git_unique_remote_branches --no-merged)' -d 'Remote branch'
# TODO: Filter further
complete -f -c git -n '__fish_git_using_command cherry-pick; and __fish_git_possible_commithash' -a '(__fish_git_commits)'
@ -539,7 +534,7 @@ complete -f -c git -n '__fish_git_using_command commit; and __fish_contains_opt
### diff
complete -c git -n '__fish_git_needs_command' -a diff -d 'Show changes between commits, commit and working tree, etc'
complete -c git -n '__fish_git_using_command diff' -a '(__fish_git_ranges)' -d 'Branch'
complete -c git -n '__fish_git_using_command diff' -a '(__fish_git_ranges)'
complete -c git -n '__fish_git_using_command diff' -l cached -d 'Show diff of changes in the index'
complete -c git -n '__fish_git_using_command diff' -l no-index -d 'Compare two paths on the filesystem'
complete -f -c git -n '__fish_git_using_command diff' -a '(__fish_git_files modified deleted)'
@ -547,7 +542,7 @@ complete -f -c git -n '__fish_git_using_command diff' -a '(__fish_git_files modi
### difftool
complete -c git -n '__fish_git_needs_command' -a difftool -d 'Open diffs in a visual tool'
complete -c git -n '__fish_git_using_command difftool' -a '(__fish_git_ranges)' -d 'Branch'
complete -c git -n '__fish_git_using_command difftool' -a '(__fish_git_ranges)'
complete -c git -n '__fish_git_using_command difftool' -l cached -d 'Visually show diff of changes in the index'
complete -f -c git -n '__fish_git_using_command difftool' -a '(__fish_git_files modified deleted)'
# TODO options
@ -564,7 +559,7 @@ complete -f -c git -n '__fish_git_needs_command' -a init -d 'Create an empty git
### log
complete -c git -n '__fish_git_needs_command' -a shortlog -d 'Show commit shortlog'
complete -c git -n '__fish_git_needs_command' -a log -d 'Show commit logs'
complete -c git -n '__fish_git_using_command log' -a '(__fish_git_refs) (__fish_git_ranges)' -d 'Branch'
complete -c git -n '__fish_git_using_command log' -a '(__fish_git_refs) (__fish_git_ranges)'
complete -c git -n '__fish_git_using_command log' -l follow -d 'Continue listing file history beyond renames'
complete -c git -n '__fish_git_using_command log' -l no-decorate -d 'Don\'t print ref names'
@ -765,7 +760,7 @@ complete -c git -n '__fish_git_using_command log' -l ita-invisible-in-index
### merge
complete -f -c git -n '__fish_git_needs_command' -a merge -d 'Join two or more development histories together'
complete -f -c git -n '__fish_git_using_command merge' -a '(__fish_git_branches)' -d 'Branch'
complete -f -c git -n '__fish_git_using_command merge' -a '(__fish_git_branches)'
complete -f -c git -n '__fish_git_using_command merge' -a '(__fish_git_unique_remote_branches)' -d 'Remote branch'
complete -f -c git -n '__fish_git_using_command merge' -l commit -d "Autocommit the merge"
complete -f -c git -n '__fish_git_using_command merge' -l no-commit -d "Don't autocommit the merge"
@ -826,13 +821,13 @@ complete -f -c git -n '__fish_git_using_command pull' -l no-tags -d 'Disable aut
# TODO --upload-pack
complete -f -c git -n '__fish_git_using_command pull' -l progress -d 'Force progress status'
complete -f -c git -n '__fish_git_using_command pull; and not __fish_git_branch_for_remote' -a '(__fish_git_remotes)' -d 'Remote alias'
complete -f -c git -n '__fish_git_using_command pull; and __fish_git_branch_for_remote' -a '(__fish_git_branch_for_remote)' -d 'Branch'
complete -f -c git -n '__fish_git_using_command pull; and __fish_git_branch_for_remote' -a '(__fish_git_branch_for_remote)'
# TODO other options
### push
complete -f -c git -n '__fish_git_needs_command' -a push -d 'Update remote refs along with associated objects'
complete -f -c git -n '__fish_git_using_command push; and not __fish_git_branch_for_remote' -a '(__fish_git_remotes)' -d 'Remote alias'
complete -f -c git -n '__fish_git_using_command push; and __fish_git_branch_for_remote' -a '(__fish_git_branches)' -d 'Branch'
complete -f -c git -n '__fish_git_using_command push; and __fish_git_branch_for_remote' -a '(__fish_git_branches)'
# The "refspec" here is an optional "+" to signify a force-push
complete -f -c git -n '__fish_git_using_command push; and __fish_git_branch_for_remote; and string match -q "+*" -- (commandline -ct)' -a '+(__fish_git_branches)' -d 'Force-push branch'
# git push REMOTE :BRANCH deletes BRANCH on remote REMOTE
@ -859,7 +854,7 @@ complete -f -c git -n '__fish_git_using_command push' -l progress -d 'Force prog
### rebase
complete -f -c git -n '__fish_git_needs_command' -a rebase -d 'Forward-port local commits to the updated upstream head'
complete -f -c git -n '__fish_git_using_command rebase' -a '(__fish_git_remotes)' -d 'Remote alias'
complete -f -c git -n '__fish_git_using_command rebase' -a '(__fish_git_branches)' -d 'Branch'
complete -f -c git -n '__fish_git_using_command rebase' -a '(__fish_git_branches)'
complete -f -c git -n '__fish_git_using_command rebase' -a '(__fish_git_heads)' -d 'Head'
complete -f -c git -n '__fish_git_using_command rebase' -a '(__fish_git_tags)' -d 'Tag'
complete -f -c git -n '__fish_git_using_command rebase' -l continue -d 'Restart the rebasing process'
@ -884,7 +879,7 @@ complete -f -c git -n '__fish_git_using_command rebase' -l no-ff -d 'No fast-for
### reset
complete -c git -n '__fish_git_needs_command' -a reset -d 'Reset current HEAD to the specified state'
complete -f -c git -n '__fish_git_using_command reset' -l hard -d 'Reset files in working directory'
complete -c git -n '__fish_git_using_command reset' -a '(__fish_git_branches)' -d 'Branch'
complete -c git -n '__fish_git_using_command reset' -a '(__fish_git_branches)'
# reset can either undo changes to versioned modified files,
# or remove files from the staging area.
# TODO: Deleted files seem to need a "--" separator.
@ -920,7 +915,7 @@ complete -f -c git -n '__fish_git_using_command status' -l ignore-submodules -x
### tag
complete -f -c git -n '__fish_git_needs_command' -a tag -d 'Create, list, delete or verify a tag object signed with GPG'
complete -f -c git -n '__fish_git_using_command tag; and __fish_not_contain_opt -s d; and __fish_not_contain_opt -s v; and test (count (commandline -opc | string match -r -v \'^-\')) -eq 3' -a '(__fish_git_branches)' -d 'Branch'
complete -f -c git -n '__fish_git_using_command tag; and __fish_not_contain_opt -s d; and __fish_not_contain_opt -s v; and test (count (commandline -opc | string match -r -v \'^-\')) -eq 3' -a '(__fish_git_branches)'
complete -f -c git -n '__fish_git_using_command tag' -s a -l annotate -d 'Make an unsigned, annotated tag object'
complete -f -c git -n '__fish_git_using_command tag' -s s -l sign -d 'Make a GPG-signed tag'
complete -f -c git -n '__fish_git_using_command tag' -s d -l delete -d 'Remove a tag'
@ -956,7 +951,7 @@ complete -f -c git -n '__fish_git_needs_command' -a config -d 'Set and read git
### format-patch
complete -f -c git -n '__fish_git_needs_command' -a format-patch -d 'Generate patch series to send upstream'
complete -f -c git -n '__fish_git_using_command format-patch' -a '(__fish_git_branches)' -d 'Branch'
complete -f -c git -n '__fish_git_using_command format-patch' -a '(__fish_git_branches)'
complete -f -c git -n '__fish_git_using_command format-patch' -s p -l no-stat -d "Generate plain patches without diffstat"
complete -f -c git -n '__fish_git_using_command format-patch' -s s -l no-patch -d "Suppress diff output"
complete -f -c git -n '__fish_git_using_command format-patch' -l minimal -d "Spend more time to create smaller diffs"