Skip to content

Commit

Permalink
Add support for --[no]-thing explicit boolean flags.
Browse files Browse the repository at this point in the history
  • Loading branch information
ioquatix committed Mar 28, 2024
1 parent 22cdaf3 commit 566edec
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 24 deletions.
89 changes: 69 additions & 20 deletions lib/samovar/flags.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -21,20 +21,21 @@ 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
return @ordered.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
Expand All @@ -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
3 changes: 2 additions & 1 deletion lib/samovar/option.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 3 additions & 1 deletion lib/samovar/options.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 3 additions & 2 deletions lib/samovar/table.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
18 changes: 18 additions & 0 deletions test/samovar/command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class Top < Samovar::Command
option '-c/--configuration <name>', "Specify a specific build configuration.", default: 'TEAPOT_CONFIGURATION'
option '-i/--in/--root <path>', "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
Expand Down Expand Up @@ -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

0 comments on commit 566edec

Please sign in to comment.