Signed-off-by: Felipe Contreras <felipe.contreras@xxxxxxxxx> --- Notes: We could use Git's internap parseopt, but the resulting code in Ruby wouldn't look very good, and the complexity to bind it wouldn't be trivial either (I tried). Instead, let's use the advantage of Ruby blocks to set the variables to their right values and try to keep the code simple, and add more features as they are needed later on. git-rb-setup.rb | 75 ++++++++++++++++++++++++++++++++ t/t10000-ruby.sh | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 203 insertions(+) diff --git a/git-rb-setup.rb b/git-rb-setup.rb index 6f283da..cd2502f 100644 --- a/git-rb-setup.rb +++ b/git-rb-setup.rb @@ -32,3 +32,78 @@ class String return self[prefix.length..-1] end end + +class ParseOpt + attr_writer :usage + + class Option + attr_reader :short, :long, :help + + def initialize(short, long, help, &block) + @block = block + @short = short + @long = long + @help = help + end + + def call(v) + @block.call(v) + end + end + + def initialize + @list = {} + end + + def on(short = nil, long = nil, help: nil, &block) + opt = Option.new(short, long, help, &block) + @list[short] = opt if short + @list[long] = opt if long + end + + def parse + if ARGV.member?('-h') or ARGV.member?('--help') + usage + exit 0 + end + seen_dash = false + ARGV.delete_if do |cur| + opt = val = nil + next false if cur[0] != '-' or seen_dash + case cur + when '--' + seen_dash = true + next true + when /^--no-(.+)$/ + opt = @list[$1] + val = false + when /^-([^-])(.+)?$/, /^--(.+?)(?:=(.+))?$/ + opt = @list[$1] + val = $2 || true + end + if opt + opt.call(val) + true + else + usage + exit 1 + end + end + end + + def usage + def fmt(prefix, str) + return str ? prefix + str : nil + end + puts 'usage: %s' % @usage + @list.values.uniq.each do |opt| + s = ' ' + s << '' + s << [fmt('-', opt.short), fmt('--', opt.long)].compact.join(', ') + s << '' + s << '%*s%s' % [26 - s.size, '', opt.help] if opt.help + puts s + end + end + +end diff --git a/t/t10000-ruby.sh b/t/t10000-ruby.sh index e5a397c..a365849 100755 --- a/t/t10000-ruby.sh +++ b/t/t10000-ruby.sh @@ -102,4 +102,132 @@ test_expect_success 'test Commit' ' test_cmp expected actual ' +test_expect_success 'test ParseOpt' ' + cat > parse-script <<"EOF" + $str = "default" + $num = 0 + $bool = false + + opts = ParseOpt.new + opts.usage = "git foo" + + opts.on("b", "bool", help: "Boolean") do |v| + $bool = v + end + + opts.on("s", "string", help: "String") do |v| + $str = v + end + + opts.on("n", "number", help: "Number") do |v| + $num = v.to_i + end + + opts.parse + + p(ARGV) + p({ :bool => $bool, :str => $str, :num => $num }) + EOF + + git ruby parse-script > actual && + cat > expected <<-EOF && + [] + {:bool=>false, :str=>"default", :num=>0} + EOF + test_cmp expected actual && + + git ruby parse-script --bool > actual && + cat > expected <<-EOF && + [] + {:bool=>true, :str=>"default", :num=>0} + EOF + test_cmp expected actual && + + git ruby parse-script -b > actual && + cat > expected <<-EOF && + [] + {:bool=>true, :str=>"default", :num=>0} + EOF + test_cmp expected actual && + + git ruby parse-script --string=foo > actual && + cat > expected <<-EOF && + [] + {:bool=>false, :str=>"foo", :num=>0} + EOF + test_cmp expected actual && + + git ruby parse-script -sfoo > actual && + cat > expected <<-EOF && + [] + {:bool=>false, :str=>"foo", :num=>0} + EOF + test_cmp expected actual && + + git ruby parse-script --number=10 > actual && + cat > expected <<-EOF && + [] + {:bool=>false, :str=>"default", :num=>10} + EOF + test_cmp expected actual && + + git ruby parse-script --bool --string=bar --number=-20 > actual && + cat > expected <<-EOF && + [] + {:bool=>true, :str=>"bar", :num=>-20} + EOF + test_cmp expected actual && + + git ruby parse-script --help > actual && + cat > expected <<-EOF && + usage: git foo + -b, --bool Boolean + -s, --string String + -n, --number Number + EOF + test_cmp expected actual && + + git ruby parse-script --help > actual && + cat > expected <<-EOF && + usage: git foo + -b, --bool Boolean + -s, --string String + -n, --number Number + EOF + test_cmp expected actual && + + test_must_fail git ruby parse-script --bad > actual && + cat > expected <<-EOF && + usage: git foo + -b, --bool Boolean + -s, --string String + -n, --number Number + EOF + test_cmp expected actual && + + git ruby parse-script one --bool two --string=bar three --number=-20 mambo > actual && + cat > expected <<-EOF && + ["one", "two", "three", "mambo"] + {:bool=>true, :str=>"bar", :num=>-20} + EOF + test_cmp expected actual && + + git ruby parse-script one --bool two -- --three four > actual && + cat > expected <<-EOF && + ["one", "two", "--three", "four"] + {:bool=>true, :str=>"default", :num=>0} + EOF + test_cmp expected actual && + + git ruby parse-script one --bool --no-bool > actual && + cat > expected <<-EOF && + ["one"] + {:bool=>false, :str=>"default", :num=>0} + EOF + cat actual + test_cmp expected actual && + + true +' + test_done -- 1.8.4-fc -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html