From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 22604 invoked by alias); 3 Jun 2016 20:40:53 -0000 Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Workers List List-Post: List-Help: X-Seq: 38592 Received: (qmail 17878 invoked from network); 3 Jun 2016 20:40:51 -0000 X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.1 Date: Fri, 03 Jun 2016 20:40:49 +0000 From: Daniel Shahaf To: zsh-workers@zsh.org Cc: Nils Luxton Subject: [PATCH] New completion tag: __git_recent_branches Message-ID: <20160603204049.GA22304@tarsus.local2> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit User-Agent: Mutt/1.5.23 (2014-03-12) Nils and I have been looking into a "recent branches" completion function for git; it provides the following functionality: [[[ % () { for i; git checkout -b br$i && git commit --allow-empty -m "Commit $i" } foo{1..3} Switched to a new branch 'brfoo1' [brfoo1 2499cbf] Commit foo1 Switched to a new branch 'brfoo2' [brfoo2 15b3dfd] Commit foo2 Switched to a new branch 'brfoo3' [brfoo3 371fa70] Commit foo3 % compdef __git_recent_branches f % f > recent branches brfoo2 - Commit foo2 brfoo1 - Commit foo1 master - Initial import ]]] The code is attached (history at [1,2]). I'd like to add these two functions to _git. I don't plan to have _git call these two functions yet. The "2" in the function name will go away. The hardcoded "-1000" is precedented elsewhere in _git (won't be hard to make it configureable). Cheers, Daniel [1] https://github.com/ascii-soup/zsh-git-recent-branches [2] https://github.com/danielshahaf/zsh-git-recent-branches # This function returns in $reply recently-checked-out refs' names, in order # from most to least recent. __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 } __git_recent_branches2() { 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. # ### Let's hope the user is well-stocked on cutlery. 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 }