Skip to content

Commit

Permalink
Change hash conversion to work with non-string values
Browse files Browse the repository at this point in the history
  • Loading branch information
piotrmurach committed Dec 28, 2022
1 parent 49096ed commit 33b874c
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 11 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Expand Up @@ -5,7 +5,7 @@
### Changed
* Change permit setting to work with parameters converted to an array or a hash
* Change formatting of a hash value in parameter validation error message
* Change array conversion to work with non-string values
* Change array and hash conversions to work with non-string values

### Fixed
* Fix argument check against permitted values to allow nil value when optional
Expand Down
15 changes: 7 additions & 8 deletions lib/tty/option/conversions.rb
Expand Up @@ -88,16 +88,15 @@ module Conversions

convert :map, :hash do |val|
next Const::Undefined if val.nil?
next val if val.is_a?(Hash)

values = val.respond_to?(:each) ? val : val.to_s.split(/[& ]/)
values = val.respond_to?(:split) ? val.split(/[& ]/) : Array(val)
values.each_with_object({}) do |pair, pairs|
key, value = pair.split(/[=:]/, 2)
if (current = pairs[key.to_sym])
pairs[key.to_sym] = Array(current) << value
else
pairs[key.to_sym] = value
end
pairs
is_string = pair.respond_to?(:split)
key, value = is_string ? pair.split(/[=:]/, 2) : pair
new_key = is_string ? key.to_sym : key
current = pairs[new_key]
pairs[new_key] = current ? Array(current) << value : value
end
end

Expand Down
15 changes: 13 additions & 2 deletions spec/unit/conversions_spec.rb
Expand Up @@ -207,14 +207,20 @@
context ":map" do
{
"" => {},
"a" => {a: nil},
:a => {a: nil},
1 => {1 => nil},
true => {true => nil},
"a=1" => {a: "1"},
"a=1&b=2" => {a: "1", b: "2"},
"a=&b=2" => {a: "", b: "2"},
"a=1&b=2&a=3" => {a: %w[1 3], b: "2"},
"a:1 b:2" => {a: "1", b: "2"},
"a:1 b:2 a:3" => {a: %w[1 3], b: "2"},
%w[a:1 b:2 c:3] => {a: "1", b: "2", c: "3"},
%w[a=1 b=2 c=3] => {a: "1", b: "2", c: "3"}
%w[a=1 b=2 c=3] => {a: "1", b: "2", c: "3"},
{a: :a, b: 1, c: true} => {a: :a, b: 1, c: true},
{"a" => :a, "b" => 1, "c" => true} => {"a" => :a, "b" => 1, "c" => true}
}.each do |input, obj|
it "converts #{input.inspect} to #{obj.inspect}" do
expect(described_class[:map].(input)).to eq(obj)
Expand All @@ -227,10 +233,15 @@

{
[:int_map, "a:1 b:2 c:3"] => {a: 1, b: 2, c: 3},
[:int_map, {a: "1",b: "2",c: "3"}] => {a: 1, b: 2, c: 3},
[:float_map, "a:1 b:2 c:3"] => {a: 1.0, b: 2.0, c: 3.0},
[:float_map, {a: "1",b: "2", c: "3"}] => {a: 1.0, b: 2.0, c: 3.0},
[:bool_map, "a:t b:f c:t"] => {a: true, b: false, c: true},
[:bool_map, {a: "t",b: "f", c: "t"}] => {a: true, b: false, c: true},
[:symbol_map, "a:t b:f c:t"] => {a: :t, b: :f, c: :t},
[:regexp_map, "a:t b:f c:t"] => {a: /t/, b: /f/, c: /t/}
[:symbol_map, {a: "t", b: "f", c: "t"}] => {a: :t, b: :f, c: :t},
[:regexp_map, "a:t b:f c:t"] => {a: /t/, b: /f/, c: /t/},
[:regexp_map, {a: "t", b: "f", c: "t"}] => {a: /t/, b: /f/, c: /t/}
}.each do |(type, input), obj|
it "converts #{input.inspect} to #{obj.inspect}" do
expect(described_class[type].(input)).to eq(obj)
Expand Down
28 changes: 28 additions & 0 deletions spec/unit/parse_spec.rb
Expand Up @@ -621,6 +621,34 @@

expect(cmd.params[:foo]).to eq([1, 2, 3])
end

it "defaults a string to a hash with integer values" do
cmd = new_command do
option :foo do
long "--foo VAL"
convert :int_map
default "a:1 b:2 c:3"
end
end

cmd.parse([])

expect(cmd.params[:foo]).to eq({a: 1, b: 2, c: 3})
end

it "defaults to a hash with integer values" do
cmd = new_command do
option :foo do
long "--foo VAL"
convert :int_map
default({"a" => 1, "b" => 2, "c" => 3})
end
end

cmd.parse([])

expect(cmd.params[:foo]).to eq({"a" => 1, "b" => 2, "c" => 3})
end
end

context "convert" do
Expand Down

0 comments on commit 33b874c

Please sign in to comment.