Skip to content

Instantly share code, notes, and snippets.

@andrewculver
Created December 6, 2012 16:26
Show Gist options
  • Save andrewculver/4225783 to your computer and use it in GitHub Desktop.
Save andrewculver/4225783 to your computer and use it in GitHub Desktop.
What's the best way to create a tool like this without misusing $stderr?

I like descriptive, sometimes long, branch names. However, typing them is annoying. So, I've created this script that I can inject in place of typing a branch name. It shows me a numbered list of current branches, and I select one using the number from the list.

Example:

andrewculver:~/Sites/sample-project (master)$ git branch -d `gb`
1. master
2. some-bugfix
3. some-new-feature
4. test
> 3
Deleted branch some-new-feature (was 80b10ce).
andrewculver:~/Sites/sample-project (master)$ git checkout `gb`
1. master
2. some-bugfix
3. test
> 2
Switched to branch 'some-bugfix'
andrewculver:~/Sites/sample-project (some-bugfix)$ 

However, in order to accomplish this, all of the user interaction is output to $stderr, and only the final result (e.g. the branch name) is output to $stdout.

It works fine, but it seems wrong. Is there a better way to write tools like this?

Here's the code for the script incase you're interested:

#!/usr/bin/env ruby

# Get a list of branches.
branches = `git branch`
branches = branches.split("\n").map { |b| b.gsub(/[ \*] /, '') }

# Present choices.
branches.each_index do |i|
  $stderr.puts "#{i + 1}. #{branches[i]}"
end
$stderr << "> "

# Gather input.
choice = gets.to_i

# Output branch selected, or an error.
if choice.is_a? Fixnum and branches[choice - 1].is_a? String
  puts branches[choice - 1]
else
  $stderr.puts "Invalid selection."
end
@zsiec
Copy link

zsiec commented Dec 6, 2012

This doesn't answer the question posed, but I've also had this problem and have had a good experience with using zsh and git-completion to tab complete my git commands.

http://zsh.git.sourceforge.net/git/gitweb.cgi?p=zsh/zsh;a=blob_plain;f=Completion/Unix/Command/_git;hb=HEAD

@zsiec
Copy link

zsiec commented Dec 6, 2012

You may enjoy using Thor for this

#!/usr/bin/env ruby
require "rubygems"
require "thor"

class GitBranch < Thor
  desc "branch", "Checks out the selected branch"
  def branch
    branches = `git branch`
    branches = branches.split("\n").map { |b| b.gsub(/[ \*] /, '') }

    branches.each_with_index do |branch, index|
      say "#{index}. #{branch}"
    end
    choice = (ask "> ").to_i

    if choice.is_a? Fixnum and branches[choice - 1].is_a? String
      puts branches[choice - 1]
    else
      return say("Invalid selection.")
    end

  end
end

GitBranch.start

@andrewculver
Copy link
Author

Awesome. I think you're right that tab-complete may be the right solution for the problem. I'll take your Thor implementation for a spin, too. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment