From 6e834587eb3ade36241f5803daa7aa0148e324fc Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Sat, 4 Jun 2016 09:19:54 +0000 Subject: 38592 (plus tweak): _git: New recent branches completion, unused. (Joint with Nils Luxton) --- Completion/Unix/Command/_git | 60 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) (limited to 'Completion') diff --git a/Completion/Unix/Command/_git b/Completion/Unix/Command/_git index 1dca28802..9e572e25d 100644 --- a/Completion/Unix/Command/_git +++ b/Completion/Unix/Command/_git @@ -5640,6 +5640,66 @@ __git_commit_objects_prefer_recent () { __git_recent_commits $argument_array_names || __git_commit_objects } +# This function returns in $reply recently-checked-out refs' names, in order +# from most to least recent. +(( $+functions[__git_recent_branches__names] )) || +__git_recent_branches__names() +{ + local -a reflog + local reflog_subject + local new_head + local -A seen + reply=() + + reflog=(${(ps:\0:)"$(_call_program reflog git reflog -1000 -z --grep-reflog='\^checkout:\ moving\ from\ ' --pretty='%gs' 2>/dev/null)"}) + for reflog_subject in $reflog; do + new_head=${${=reflog_subject}[4]} + + # Skip values added in previous iterations. + if (( ${+seen[$new_head]} )); then + continue + fi + seen[$new_head]="" # value is ignored + + # Filter out hashes, to leave only ref names. + if [[ $new_head =~ '^[0-9a-f]{40}$' ]]; then + continue + fi + + # All checks passed. Add it. + reply+=( $new_head ) + done +} + +(( $+functions[__git_recent_branches] )) || +__git_recent_branches() { + local -a branches descriptions + local branch description + local -a reply + + __git_recent_branches__names \ + ; for branch in $reply + do + # ### We'd want to convert all $reply to $descriptions in one shot, + # ### with this: + # ### array=("${(ps:\0:)"$(_call_program descriptions git --no-pager log --no-walk=unsorted -z --pretty=%s ${(q)reply} --)"}") + # ### , but git croaks if any of the positional arguments is a ref name + # ### that has been deleted. (So does 'git rev-parse'.) + # ### Hence, we resort to fetching the descriptions one-by-one. + # ### This would be costly if fork() is expensive. + description="$(_call_program description git --no-pager log --no-walk=unsorted --pretty=%s ${(q)branch} --)" + + # If the ref has been deleted, $description would be empty. + if [[ -n "$description" ]]; then + branches+=$branch + descriptions+="${branch//:/\:}:${description}" + fi + done + + _describe -V -t recent-branches "recent branches" descriptions branches +} + + (( $+functions[__git_commits] )) || __git_commits () { local -a argument_array_names -- cgit 1.4.1