diff --git a/lib/samovar/flags.rb b/lib/samovar/flags.rb index fbb3250..2a01e1e 100644 --- a/lib/samovar/flags.rb +++ b/lib/samovar/flags.rb @@ -8,7 +8,7 @@ class Flags def initialize(text) @text = text - @ordered = text.split(/\s+\|\s+/).map{|part| Flag.new(part)} + @ordered = text.split(/\s+\|\s+/).map{|part| Flag.parse(part)} end def each(&block) @@ -21,7 +21,7 @@ def first # Whether or not this flag should have a true/false value if not specified otherwise. def boolean? - @ordered.count == 1 and @ordered.first.value.nil? + @ordered.count == 1 and @ordered.first.boolean? end def count @@ -29,12 +29,13 @@ def count end def to_s - '[' + @ordered.join(' | ') + ']' + "[#{@ordered.join(' | ')}]" end def parse(input) @ordered.each do |flag| - if result = flag.parse(input) + result = flag.parse(input) + if result != nil return result end end @@ -44,45 +45,93 @@ def parse(input) end class Flag - def initialize(text) - @text = text - + def self.parse(text) if text =~ /(.*?)\s(\<.*?\>)/ - @prefix = $1 - @value = $2 + ValueFlag.new(text, $1, $2) + elsif text =~ /--\[no\]-(.*?)$/ + BooleanFlag.new(text, "--#{$1}") else - @prefix = @text - @value = nil + ValueFlag.new(text, text, nil) end - - *@alternatives, @prefix = @prefix.split('/') + end + + def initialize(text, prefix, alternatives = nil) + @text = text + @prefix = prefix + @alternatives = alternatives end attr :text attr :prefix attr :alternatives - attr :value def to_s @text end - def prefix?(token) - @prefix == token or @alternatives.include?(token) - end - def key @key ||= @prefix.sub(/^-*/, '').gsub('-', '_').to_sym end + def boolean? + false + end + end + + class ValueFlag < Flag + def initialize(text, prefix, value) + super(text, prefix) + + @value = value + + *@alternatives, @prefix = @prefix.split('/') + end + + attr :alternatives + attr :value + + def boolean? + @value.nil? + end + + def prefix?(token) + @prefix == token or @alternatives.include?(token) + end + def parse(input) if prefix?(input.first) if @value - input.shift(2).last + return input.shift(2).last else - input.shift; key + input.shift + return key end end end end + + class BooleanFlag < Flag + def initialize(text, prefix, value = nil) + super(text, prefix) + + @value = value + + @negated = @prefix.sub(/^--/, '--no-') + @alternatives = [@negated] + end + + def prefix?(token) + @prefix == token or @negated == token + end + + def parse(input) + if input.first == @prefix + input.shift + return true + elsif input.first == @negated + input.shift + return false + end + end + end end diff --git a/lib/samovar/option.rb b/lib/samovar/option.rb index 6a60e39..9a083f9 100644 --- a/lib/samovar/option.rb +++ b/lib/samovar/option.rb @@ -66,7 +66,8 @@ def coerce(result) end def parse(input, parent = nil, default = nil) - if result = @flags.parse(input) + result = @flags.parse(input) + if result != nil @value.nil? ? coerce(result) : @value elsif default ||= @default return default diff --git a/lib/samovar/options.rb b/lib/samovar/options.rb index 98d6d92..6f0a523 100644 --- a/lib/samovar/options.rb +++ b/lib/samovar/options.rb @@ -90,7 +90,9 @@ def parse(input, parent = nil, default = nil) values = (default || @defaults).dup while option = @keyed[input.first] - if result = option.parse(input) + prefix = input.first + result = option.parse(input) + if result != nil values[option.key] = result end end diff --git a/lib/samovar/table.rb b/lib/samovar/table.rb index d476fd9..91b24ba 100644 --- a/lib/samovar/table.rb +++ b/lib/samovar/table.rb @@ -76,8 +76,9 @@ def parse(input, parent) current = parent.send(key) - if result = row.parse(input, parent, current) - parent.send("#{row.key}=", result) + result = row.parse(input, parent, current) + if result != nil + parent.public_send("#{row.key}=", result) end end end diff --git a/test/samovar/command.rb b/test/samovar/command.rb index d9bf528..980551c 100644 --- a/test/samovar/command.rb +++ b/test/samovar/command.rb @@ -20,6 +20,7 @@ class Top < Samovar::Command option '-c/--configuration ', "Specify a specific build configuration.", default: 'TEAPOT_CONFIGURATION' option '-i/--in/--root ', "Work in the given root directory." option '--verbose | --quiet', "Verbosity of output for debugging.", key: :logging + option '--[no]-color', "Enable or disable color output.", default: true option '-h/--help', "Print out help information." option '-v/--version', "Print out the application version." end @@ -81,4 +82,21 @@ class Top < Samovar::Command expect(buffer.string).to be(:include?, Top.description) end end + + with '--[no]-color flag' do + it "should use default color output if unspecified" do + top = Top[] + expect(top.options[:color]).to be == true + end + + it "should enable color output" do + top = Top['--color'] + expect(top.options[:color]).to be == true + end + + it "should disable color output" do + top = Top['--no-color'] + expect(top.options[:color]).to be == false + end + end end