thor 0.19.1 → 0.19.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +24 -0
  3. data/CONTRIBUTING.md +15 -0
  4. data/README.md +7 -1
  5. data/lib/thor.rb +31 -23
  6. data/lib/thor/actions.rb +21 -22
  7. data/lib/thor/actions/create_file.rb +1 -1
  8. data/lib/thor/actions/create_link.rb +1 -1
  9. data/lib/thor/actions/directory.rb +2 -2
  10. data/lib/thor/actions/empty_directory.rb +8 -8
  11. data/lib/thor/actions/file_manipulation.rb +23 -12
  12. data/lib/thor/actions/inject_into_file.rb +10 -14
  13. data/lib/thor/base.rb +33 -33
  14. data/lib/thor/command.rb +9 -9
  15. data/lib/thor/core_ext/hash_with_indifferent_access.rb +9 -1
  16. data/lib/thor/core_ext/io_binary_read.rb +7 -5
  17. data/lib/thor/core_ext/ordered_hash.rb +94 -63
  18. data/lib/thor/error.rb +3 -3
  19. data/lib/thor/group.rb +12 -12
  20. data/lib/thor/invocation.rb +4 -5
  21. data/lib/thor/parser/argument.rb +4 -7
  22. data/lib/thor/parser/arguments.rb +16 -16
  23. data/lib/thor/parser/option.rb +39 -19
  24. data/lib/thor/parser/options.rb +7 -5
  25. data/lib/thor/runner.rb +25 -25
  26. data/lib/thor/shell.rb +1 -1
  27. data/lib/thor/shell/basic.rb +41 -26
  28. data/lib/thor/shell/color.rb +1 -1
  29. data/lib/thor/shell/html.rb +4 -4
  30. data/lib/thor/util.rb +8 -7
  31. data/lib/thor/version.rb +1 -1
  32. data/thor.gemspec +6 -9
  33. metadata +6 -148
  34. data/Thorfile +0 -29
  35. data/spec/actions/create_file_spec.rb +0 -168
  36. data/spec/actions/create_link_spec.rb +0 -96
  37. data/spec/actions/directory_spec.rb +0 -169
  38. data/spec/actions/empty_directory_spec.rb +0 -129
  39. data/spec/actions/file_manipulation_spec.rb +0 -392
  40. data/spec/actions/inject_into_file_spec.rb +0 -135
  41. data/spec/actions_spec.rb +0 -331
  42. data/spec/base_spec.rb +0 -298
  43. data/spec/command_spec.rb +0 -79
  44. data/spec/core_ext/hash_with_indifferent_access_spec.rb +0 -48
  45. data/spec/core_ext/ordered_hash_spec.rb +0 -115
  46. data/spec/exit_condition_spec.rb +0 -19
  47. data/spec/fixtures/application.rb +0 -2
  48. data/spec/fixtures/app{1}/README +0 -3
  49. data/spec/fixtures/bundle/execute.rb +0 -6
  50. data/spec/fixtures/bundle/main.thor +0 -1
  51. data/spec/fixtures/command.thor +0 -10
  52. data/spec/fixtures/doc/%file_name%.rb.tt +0 -1
  53. data/spec/fixtures/doc/COMMENTER +0 -11
  54. data/spec/fixtures/doc/README +0 -3
  55. data/spec/fixtures/doc/block_helper.rb +0 -3
  56. data/spec/fixtures/doc/config.rb +0 -1
  57. data/spec/fixtures/doc/config.yaml.tt +0 -1
  58. data/spec/fixtures/doc/excluding/%file_name%.rb.tt +0 -1
  59. data/spec/fixtures/enum.thor +0 -10
  60. data/spec/fixtures/group.thor +0 -128
  61. data/spec/fixtures/invoke.thor +0 -131
  62. data/spec/fixtures/path with spaces b/data/spec/fixtures/path with → spaces +0 -0
  63. data/spec/fixtures/preserve/script.sh +0 -3
  64. data/spec/fixtures/script.thor +0 -220
  65. data/spec/fixtures/subcommand.thor +0 -17
  66. data/spec/group_spec.rb +0 -222
  67. data/spec/helper.rb +0 -80
  68. data/spec/invocation_spec.rb +0 -120
  69. data/spec/line_editor/basic_spec.rb +0 -28
  70. data/spec/line_editor/readline_spec.rb +0 -69
  71. data/spec/line_editor_spec.rb +0 -43
  72. data/spec/parser/argument_spec.rb +0 -53
  73. data/spec/parser/arguments_spec.rb +0 -66
  74. data/spec/parser/option_spec.rb +0 -210
  75. data/spec/parser/options_spec.rb +0 -414
  76. data/spec/quality_spec.rb +0 -75
  77. data/spec/rake_compat_spec.rb +0 -72
  78. data/spec/register_spec.rb +0 -227
  79. data/spec/runner_spec.rb +0 -246
  80. data/spec/sandbox/application.rb +0 -2
  81. data/spec/sandbox/app{1}/README +0 -3
  82. data/spec/sandbox/bundle/execute.rb +0 -6
  83. data/spec/sandbox/bundle/main.thor +0 -1
  84. data/spec/sandbox/command.thor +0 -10
  85. data/spec/sandbox/doc/%file_name%.rb.tt +0 -1
  86. data/spec/sandbox/doc/COMMENTER +0 -11
  87. data/spec/sandbox/doc/README +0 -3
  88. data/spec/sandbox/doc/block_helper.rb +0 -3
  89. data/spec/sandbox/doc/config.rb +0 -1
  90. data/spec/sandbox/doc/config.yaml.tt +0 -1
  91. data/spec/sandbox/doc/excluding/%file_name%.rb.tt +0 -1
  92. data/spec/sandbox/enum.thor +0 -10
  93. data/spec/sandbox/group.thor +0 -128
  94. data/spec/sandbox/invoke.thor +0 -131
  95. data/spec/sandbox/path with spaces b/data/spec/sandbox/path with → spaces +0 -0
  96. data/spec/sandbox/preserve/script.sh +0 -3
  97. data/spec/sandbox/script.thor +0 -220
  98. data/spec/sandbox/subcommand.thor +0 -17
  99. data/spec/shell/basic_spec.rb +0 -337
  100. data/spec/shell/color_spec.rb +0 -119
  101. data/spec/shell/html_spec.rb +0 -31
  102. data/spec/shell_spec.rb +0 -47
  103. data/spec/subcommand_spec.rb +0 -48
  104. data/spec/thor_spec.rb +0 -505
  105. data/spec/util_spec.rb +0 -196
@@ -1,69 +0,0 @@
1
- require "helper"
2
-
3
- describe Thor::LineEditor::Readline do
4
- before do
5
- unless defined? ::Readline
6
- ::Readline = double("Readline")
7
- allow(::Readline).to receive(:completion_append_character=).with(nil)
8
- end
9
- end
10
-
11
- describe ".available?" do
12
- it "returns true when ::Readline exists" do
13
- allow(Object).to receive(:const_defined?).with(:Readline).and_return(true)
14
- expect(described_class).to be_available
15
- end
16
-
17
- it "returns false when ::Readline does not exist" do
18
- allow(Object).to receive(:const_defined?).with(:Readline).and_return(false)
19
- expect(described_class).not_to be_available
20
- end
21
- end
22
-
23
- describe "#readline" do
24
- it "invokes the readline library" do
25
- expect(::Readline).to receive(:readline).with("> ", true).and_return("foo")
26
- expect(::Readline).not_to receive(:completion_proc=)
27
- editor = Thor::LineEditor::Readline.new("> ", {})
28
- expect(editor.readline).to eq("foo")
29
- end
30
-
31
- it "supports the add_to_history option" do
32
- expect(::Readline).to receive(:readline).with("> ", false).and_return("foo")
33
- expect(::Readline).not_to receive(:completion_proc=)
34
- editor = Thor::LineEditor::Readline.new("> ", :add_to_history => false)
35
- expect(editor.readline).to eq("foo")
36
- end
37
-
38
- it "provides tab completion when given a limited_to option" do
39
- expect(::Readline).to receive(:readline)
40
- expect(::Readline).to receive(:completion_proc=) do |proc|
41
- expect(proc.call("")).to eq %w[Apples Chicken Chocolate]
42
- expect(proc.call("Ch")).to eq %w[Chicken Chocolate]
43
- expect(proc.call("Chi")).to eq ["Chicken"]
44
- end
45
-
46
- editor = Thor::LineEditor::Readline.new("Best food: ", :limited_to => %w[Apples Chicken Chocolate])
47
- editor.readline
48
- end
49
-
50
- it "provides path tab completion when given the path option" do
51
- expect(::Readline).to receive(:readline)
52
- expect(::Readline).to receive(:completion_proc=) do |proc|
53
- expect(proc.call("../line_ed").sort).to eq ["../line_editor/", "../line_editor_spec.rb"].sort
54
- end
55
-
56
- editor = Thor::LineEditor::Readline.new("Path to file: ", :path => true)
57
- Dir.chdir(File.dirname(__FILE__)) { editor.readline }
58
- end
59
-
60
- it "uses STDIN when asked not to echo input" do
61
- expect($stdout).to receive(:print).with("Password: ")
62
- noecho_stdin = double("noecho_stdin")
63
- expect(noecho_stdin).to receive(:gets).and_return("secret")
64
- expect($stdin).to receive(:noecho).and_yield(noecho_stdin)
65
- editor = Thor::LineEditor::Readline.new("Password: ", :echo => false)
66
- expect(editor.readline).to eq("secret")
67
- end
68
- end
69
- end
@@ -1,43 +0,0 @@
1
- require "helper"
2
-
3
- describe Thor::LineEditor, "on a system with Readline support" do
4
- before do
5
- @original_readline = ::Readline if defined? ::Readline
6
- silence_warnings { ::Readline = double("Readline") }
7
- end
8
-
9
- after do
10
- silence_warnings { ::Readline = @original_readline }
11
- end
12
-
13
- describe ".readline" do
14
- it "uses the Readline line editor" do
15
- editor = double("Readline")
16
- expect(Thor::LineEditor::Readline).to receive(:new).with("Enter your name ", :default => "Brian").and_return(editor)
17
- expect(editor).to receive(:readline).and_return("George")
18
- expect(Thor::LineEditor.readline("Enter your name ", :default => "Brian")).to eq("George")
19
- end
20
- end
21
- end
22
-
23
- describe Thor::LineEditor, "on a system without Readline support" do
24
- before do
25
- if defined? ::Readline
26
- @original_readline = ::Readline
27
- Object.send(:remove_const, :Readline)
28
- end
29
- end
30
-
31
- after do
32
- silence_warnings { ::Readline = @original_readline }
33
- end
34
-
35
- describe ".readline" do
36
- it "uses the Basic line editor" do
37
- editor = double("Basic")
38
- expect(Thor::LineEditor::Basic).to receive(:new).with("Enter your name ", :default => "Brian").and_return(editor)
39
- expect(editor).to receive(:readline).and_return("George")
40
- expect(Thor::LineEditor.readline("Enter your name ", :default => "Brian")).to eq("George")
41
- end
42
- end
43
- end
@@ -1,53 +0,0 @@
1
- require "helper"
2
- require "thor/parser"
3
-
4
- describe Thor::Argument do
5
-
6
- def argument(name, options = {})
7
- @argument ||= Thor::Argument.new(name, options)
8
- end
9
-
10
- describe "errors" do
11
- it "raises an error if name is not supplied" do
12
- expect do
13
- argument(nil)
14
- end.to raise_error(ArgumentError, "Argument name can't be nil.")
15
- end
16
-
17
- it "raises an error if type is unknown" do
18
- expect do
19
- argument(:command, :type => :unknown)
20
- end.to raise_error(ArgumentError, "Type :unknown is not valid for arguments.")
21
- end
22
-
23
- it "raises an error if argument is required and has default values" do
24
- expect do
25
- argument(:command, :type => :string, :default => "bar", :required => true)
26
- end.to raise_error(ArgumentError, "An argument cannot be required and have default value.")
27
- end
28
-
29
- it "raises an error if enum isn't an array" do
30
- expect do
31
- argument(:command, :type => :string, :enum => "bar")
32
- end.to raise_error(ArgumentError, "An argument cannot have an enum other than an array.")
33
- end
34
- end
35
-
36
- describe "#usage" do
37
- it "returns usage for string types" do
38
- expect(argument(:foo, :type => :string).usage).to eq("FOO")
39
- end
40
-
41
- it "returns usage for numeric types" do
42
- expect(argument(:foo, :type => :numeric).usage).to eq("N")
43
- end
44
-
45
- it "returns usage for array types" do
46
- expect(argument(:foo, :type => :array).usage).to eq("one two three")
47
- end
48
-
49
- it "returns usage for hash types" do
50
- expect(argument(:foo, :type => :hash).usage).to eq("key:value")
51
- end
52
- end
53
- end
@@ -1,66 +0,0 @@
1
- require "helper"
2
- require "thor/parser"
3
-
4
- describe Thor::Arguments do
5
- def create(opts = {})
6
- arguments = opts.map do |type, default|
7
- options = {:required => default.nil?, :type => type, :default => default}
8
- Thor::Argument.new(type.to_s, options)
9
- end
10
-
11
- arguments.sort! { |a, b| b.name <=> a.name }
12
- @opt = Thor::Arguments.new(arguments)
13
- end
14
-
15
- def parse(*args)
16
- @opt.parse(args)
17
- end
18
-
19
- describe "#parse" do
20
- it "parses arguments in the given order" do
21
- create :string => nil, :numeric => nil
22
- expect(parse("name", "13")["string"]).to eq("name")
23
- expect(parse("name", "13")["numeric"]).to eq(13)
24
- end
25
-
26
- it "accepts hashes" do
27
- create :string => nil, :hash => nil
28
- expect(parse("product", "title:string", "age:integer")["string"]).to eq("product")
29
- expect(parse("product", "title:string", "age:integer")["hash"]).to eq("title" => "string", "age" => "integer")
30
- expect(parse("product", "url:http://www.amazon.com/gp/product/123")["hash"]).to eq("url" => "http://www.amazon.com/gp/product/123")
31
- end
32
-
33
- it "accepts arrays" do
34
- create :string => nil, :array => nil
35
- expect(parse("product", "title", "age")["string"]).to eq("product")
36
- expect(parse("product", "title", "age")["array"]).to eq(%w[title age])
37
- end
38
-
39
- describe "with no inputs" do
40
- it "and no arguments returns an empty hash" do
41
- create
42
- expect(parse).to eq({})
43
- end
44
-
45
- it "and required arguments raises an error" do
46
- create :string => nil, :numeric => nil
47
- expect { parse }.to raise_error(Thor::RequiredArgumentMissingError, "No value provided for required arguments 'string', 'numeric'")
48
- end
49
-
50
- it "and default arguments returns default values" do
51
- create :string => "name", :numeric => 13
52
- expect(parse).to eq("string" => "name", "numeric" => 13)
53
- end
54
- end
55
-
56
- it "returns the input if it's already parsed" do
57
- create :string => nil, :hash => nil, :array => nil, :numeric => nil
58
- expect(parse("", 0, {}, [])).to eq("string" => "", "numeric" => 0, "hash" => {}, "array" => [])
59
- end
60
-
61
- it "returns the default value if none is provided" do
62
- create :string => "foo", :numeric => 3.0
63
- expect(parse("bar")).to eq("string" => "bar", "numeric" => 3.0)
64
- end
65
- end
66
- end
@@ -1,210 +0,0 @@
1
- require "helper"
2
- require "thor/parser"
3
-
4
- describe Thor::Option do
5
- def parse(key, value)
6
- Thor::Option.parse(key, value)
7
- end
8
-
9
- def option(name, options = {})
10
- @option ||= Thor::Option.new(name, options)
11
- end
12
-
13
- describe "#parse" do
14
-
15
- describe "with value as a symbol" do
16
- describe "and symbol is a valid type" do
17
- it "has type equals to the symbol" do
18
- expect(parse(:foo, :string).type).to eq(:string)
19
- expect(parse(:foo, :numeric).type).to eq(:numeric)
20
- end
21
-
22
- it "has no default value" do
23
- expect(parse(:foo, :string).default).to be nil
24
- expect(parse(:foo, :numeric).default).to be nil
25
- end
26
- end
27
-
28
- describe "equals to :required" do
29
- it "has type equals to :string" do
30
- expect(parse(:foo, :required).type).to eq(:string)
31
- end
32
-
33
- it "has no default value" do
34
- expect(parse(:foo, :required).default).to be nil
35
- end
36
- end
37
-
38
- describe "and symbol is not a reserved key" do
39
- it "has type equal to :string" do
40
- expect(parse(:foo, :bar).type).to eq(:string)
41
- end
42
-
43
- it "has no default value" do
44
- expect(parse(:foo, :bar).default).to be nil
45
- end
46
- end
47
- end
48
-
49
- describe "with value as hash" do
50
- it "has default type :hash" do
51
- expect(parse(:foo, :a => :b).type).to eq(:hash)
52
- end
53
-
54
- it "has default value equal to the hash" do
55
- expect(parse(:foo, :a => :b).default).to eq(:a => :b)
56
- end
57
- end
58
-
59
- describe "with value as array" do
60
- it "has default type :array" do
61
- expect(parse(:foo, [:a, :b]).type).to eq(:array)
62
- end
63
-
64
- it "has default value equal to the array" do
65
- expect(parse(:foo, [:a, :b]).default).to eq([:a, :b])
66
- end
67
- end
68
-
69
- describe "with value as string" do
70
- it "has default type :string" do
71
- expect(parse(:foo, "bar").type).to eq(:string)
72
- end
73
-
74
- it "has default value equal to the string" do
75
- expect(parse(:foo, "bar").default).to eq("bar")
76
- end
77
- end
78
-
79
- describe "with value as numeric" do
80
- it "has default type :numeric" do
81
- expect(parse(:foo, 2.0).type).to eq(:numeric)
82
- end
83
-
84
- it "has default value equal to the numeric" do
85
- expect(parse(:foo, 2.0).default).to eq(2.0)
86
- end
87
- end
88
-
89
- describe "with value as boolean" do
90
- it "has default type :boolean" do
91
- expect(parse(:foo, true).type).to eq(:boolean)
92
- expect(parse(:foo, false).type).to eq(:boolean)
93
- end
94
-
95
- it "has default value equal to the boolean" do
96
- expect(parse(:foo, true).default).to eq(true)
97
- expect(parse(:foo, false).default).to eq(false)
98
- end
99
- end
100
-
101
- describe "with key as a symbol" do
102
- it "sets the name equal to the key" do
103
- expect(parse(:foo, true).name).to eq("foo")
104
- end
105
- end
106
-
107
- describe "with key as an array" do
108
- it "sets the first items in the array to the name" do
109
- expect(parse([:foo, :bar, :baz], true).name).to eq("foo")
110
- end
111
-
112
- it "sets all other items as aliases" do
113
- expect(parse([:foo, :bar, :baz], true).aliases).to eq([:bar, :baz])
114
- end
115
- end
116
- end
117
-
118
- it "returns the switch name" do
119
- expect(option("foo").switch_name).to eq("--foo")
120
- expect(option("--foo").switch_name).to eq("--foo")
121
- end
122
-
123
- it "returns the human name" do
124
- expect(option("foo").human_name).to eq("foo")
125
- expect(option("--foo").human_name).to eq("foo")
126
- end
127
-
128
- it "converts underscores to dashes" do
129
- expect(option("foo_bar").switch_name).to eq("--foo-bar")
130
- end
131
-
132
- it "can be required and have default values" do
133
- option = option("foo", :required => true, :type => :string, :default => "bar")
134
- expect(option.default).to eq("bar")
135
- expect(option).to be_required
136
- end
137
-
138
- it "boolean options cannot be required" do
139
- expect do
140
- option("foo", :required => true, :type => :boolean)
141
- end.to raise_error(ArgumentError, "An option cannot be boolean and required.")
142
- end
143
-
144
- it "allows type predicates" do
145
- expect(parse(:foo, :string)).to be_string
146
- expect(parse(:foo, :boolean)).to be_boolean
147
- expect(parse(:foo, :numeric)).to be_numeric
148
- end
149
-
150
- it "raises an error on method missing" do
151
- expect do
152
- parse(:foo, :string).unknown?
153
- end.to raise_error(NoMethodError)
154
- end
155
-
156
- describe "#usage" do
157
-
158
- it "returns usage for string types" do
159
- expect(parse(:foo, :string).usage).to eq("[--foo=FOO]")
160
- end
161
-
162
- it "returns usage for numeric types" do
163
- expect(parse(:foo, :numeric).usage).to eq("[--foo=N]")
164
- end
165
-
166
- it "returns usage for array types" do
167
- expect(parse(:foo, :array).usage).to eq("[--foo=one two three]")
168
- end
169
-
170
- it "returns usage for hash types" do
171
- expect(parse(:foo, :hash).usage).to eq("[--foo=key:value]")
172
- end
173
-
174
- it "returns usage for boolean types" do
175
- expect(parse(:foo, :boolean).usage).to eq("[--foo], [--no-foo]")
176
- end
177
-
178
- it "does not use padding when no aliases are given" do
179
- expect(parse(:foo, :boolean).usage).to eq("[--foo], [--no-foo]")
180
- end
181
-
182
- it "documents a negative option when boolean" do
183
- expect(parse(:foo, :boolean).usage).to include("[--no-foo]")
184
- end
185
-
186
- it "uses banner when supplied" do
187
- expect(option(:foo, :required => false, :type => :string, :banner => "BAR").usage).to eq("[--foo=BAR]")
188
- end
189
-
190
- it "checks when banner is an empty string" do
191
- expect(option(:foo, :required => false, :type => :string, :banner => "").usage).to eq("[--foo]")
192
- end
193
-
194
- describe "with required values" do
195
- it "does not show the usage between brackets" do
196
- expect(parse(:foo, :required).usage).to eq("--foo=FOO")
197
- end
198
- end
199
-
200
- describe "with aliases" do
201
- it "does not show the usage between brackets" do
202
- expect(parse([:foo, "-f", "-b"], :required).usage).to eq("-f, -b, --foo=FOO")
203
- end
204
-
205
- it "does not negate the aliases" do
206
- expect(parse([:foo, "-f", "-b"], :boolean).usage).to eq("-f, -b, [--foo], [--no-foo]")
207
- end
208
- end
209
- end
210
- end
@@ -1,414 +0,0 @@
1
- require "helper"
2
- require "thor/parser"
3
-
4
- describe Thor::Options do
5
- def create(opts, defaults = {}, stop_on_unknown = false)
6
- opts.each do |key, value|
7
- opts[key] = Thor::Option.parse(key, value) unless value.is_a?(Thor::Option)
8
- end
9
-
10
- @opt = Thor::Options.new(opts, defaults, stop_on_unknown)
11
- end
12
-
13
- def parse(*args)
14
- @opt.parse(args.flatten)
15
- end
16
-
17
- def check_unknown!
18
- @opt.check_unknown!
19
- end
20
-
21
- def remaining
22
- @opt.remaining
23
- end
24
-
25
- describe "#to_switches" do
26
- it "turns true values into a flag" do
27
- expect(Thor::Options.to_switches(:color => true)).to eq("--color")
28
- end
29
-
30
- it "ignores nil" do
31
- expect(Thor::Options.to_switches(:color => nil)).to eq("")
32
- end
33
-
34
- it "ignores false" do
35
- expect(Thor::Options.to_switches(:color => false)).to eq("")
36
- end
37
-
38
- it "writes --name value for anything else" do
39
- expect(Thor::Options.to_switches(:format => "specdoc")).to eq('--format "specdoc"')
40
- end
41
-
42
- it "joins several values" do
43
- switches = Thor::Options.to_switches(:color => true, :foo => "bar").split(" ").sort
44
- expect(switches).to eq(%w["bar" --color --foo])
45
- end
46
-
47
- it "accepts arrays" do
48
- expect(Thor::Options.to_switches(:count => [1, 2, 3])).to eq("--count 1 2 3")
49
- end
50
-
51
- it "accepts hashes" do
52
- expect(Thor::Options.to_switches(:count => {:a => :b})).to eq("--count a:b")
53
- end
54
-
55
- it "accepts underscored options" do
56
- expect(Thor::Options.to_switches(:under_score_option => "foo bar")).to eq('--under_score_option "foo bar"')
57
- end
58
-
59
- end
60
-
61
- describe "#parse" do
62
- it "allows multiple aliases for a given switch" do
63
- create %w[--foo --bar --baz] => :string
64
- expect(parse("--foo", "12")["foo"]).to eq("12")
65
- expect(parse("--bar", "12")["foo"]).to eq("12")
66
- expect(parse("--baz", "12")["foo"]).to eq("12")
67
- end
68
-
69
- it "allows custom short names" do
70
- create "-f" => :string
71
- expect(parse("-f", "12")).to eq("f" => "12")
72
- end
73
-
74
- it "allows custom short-name aliases" do
75
- create %w[--bar -f] => :string
76
- expect(parse("-f", "12")).to eq("bar" => "12")
77
- end
78
-
79
- it "accepts conjoined short switches" do
80
- create %w[--foo -f] => true, %w[--bar -b] => true, %w[--app -a] => true
81
- opts = parse("-fba")
82
- expect(opts["foo"]).to be true
83
- expect(opts["bar"]).to be true
84
- expect(opts["app"]).to be true
85
- end
86
-
87
- it "accepts conjoined short switches with input" do
88
- create %w[--foo -f] => true, %w[--bar -b] => true, %w[--app -a] => :required
89
- opts = parse "-fba", "12"
90
- expect(opts["foo"]).to be true
91
- expect(opts["bar"]).to be true
92
- expect(opts["app"]).to eq("12")
93
- end
94
-
95
- it "returns the default value if none is provided" do
96
- create :foo => "baz", :bar => :required
97
- expect(parse("--bar", "boom")["foo"]).to eq("baz")
98
- end
99
-
100
- it "returns the default value from defaults hash to required arguments" do
101
- create Hash[:bar => :required], Hash[:bar => "baz"]
102
- expect(parse["bar"]).to eq("baz")
103
- end
104
-
105
- it "gives higher priority to defaults given in the hash" do
106
- create Hash[:bar => true], Hash[:bar => false]
107
- expect(parse["bar"]).to eq(false)
108
- end
109
-
110
- it "raises an error for unknown switches" do
111
- create :foo => "baz", :bar => :required
112
- parse("--bar", "baz", "--baz", "unknown")
113
- expect { check_unknown! }.to raise_error(Thor::UnknownArgumentError, "Unknown switches '--baz'")
114
- end
115
-
116
- it "skips leading non-switches" do
117
- create(:foo => "baz")
118
-
119
- expect(parse("asdf", "--foo", "bar")).to eq("foo" => "bar")
120
- end
121
-
122
- it "correctly recognizes things that look kind of like options, but aren't, as not options" do
123
- create(:foo => "baz")
124
- expect(parse("--asdf---asdf", "baz", "--foo", "--asdf---dsf--asdf")).to eq("foo" => "--asdf---dsf--asdf")
125
- check_unknown!
126
- end
127
-
128
- it "accepts underscores in commandline args hash for boolean" do
129
- create :foo_bar => :boolean
130
- expect(parse("--foo_bar")["foo_bar"]).to eq(true)
131
- expect(parse("--no_foo_bar")["foo_bar"]).to eq(false)
132
- end
133
-
134
- it "accepts underscores in commandline args hash for strings" do
135
- create :foo_bar => :string, :baz_foo => :string
136
- expect(parse("--foo_bar", "baz")["foo_bar"]).to eq("baz")
137
- expect(parse("--baz_foo", "foo bar")["baz_foo"]).to eq("foo bar")
138
- end
139
-
140
- it "interprets everything after -- as args instead of options" do
141
- create(:foo => :string, :bar => :required)
142
- expect(parse(%w[--bar abc moo -- --foo def -a])).to eq("bar" => "abc")
143
- expect(remaining).to eq(%w[moo --foo def -a])
144
- end
145
-
146
- it "ignores -- when looking for single option values" do
147
- create(:foo => :string, :bar => :required)
148
- expect(parse(%w[--bar -- --foo def -a])).to eq("bar" => "--foo")
149
- expect(remaining).to eq(%w[def -a])
150
- end
151
-
152
- it "ignores -- when looking for array option values" do
153
- create(:foo => :array)
154
- expect(parse(%w[--foo a b -- c d -e])).to eq("foo" => %w[a b c d -e])
155
- expect(remaining).to eq([])
156
- end
157
-
158
- it "ignores -- when looking for hash option values" do
159
- create(:foo => :hash)
160
- expect(parse(%w[--foo a:b -- c:d -e])).to eq("foo" => {"a" => "b", "c" => "d"})
161
- expect(remaining).to eq(%w[-e])
162
- end
163
-
164
- it "ignores trailing --" do
165
- create(:foo => :string)
166
- expect(parse(%w[--foo --])).to eq("foo" => nil)
167
- expect(remaining).to eq([])
168
- end
169
-
170
- describe "with no input" do
171
- it "and no switches returns an empty hash" do
172
- create({})
173
- expect(parse).to eq({})
174
- end
175
-
176
- it "and several switches returns an empty hash" do
177
- create "--foo" => :boolean, "--bar" => :string
178
- expect(parse).to eq({})
179
- end
180
-
181
- it "and a required switch raises an error" do
182
- create "--foo" => :required
183
- expect { parse }.to raise_error(Thor::RequiredArgumentMissingError, "No value provided for required options '--foo'")
184
- end
185
- end
186
-
187
- describe "with one required and one optional switch" do
188
- before do
189
- create "--foo" => :required, "--bar" => :boolean
190
- end
191
-
192
- it "raises an error if the required switch has no argument" do
193
- expect { parse("--foo") }.to raise_error(Thor::MalformattedArgumentError)
194
- end
195
-
196
- it "raises an error if the required switch isn't given" do
197
- expect { parse("--bar") }.to raise_error(Thor::RequiredArgumentMissingError)
198
- end
199
-
200
- it "raises an error if the required switch is set to nil" do
201
- expect { parse("--no-foo") }.to raise_error(Thor::RequiredArgumentMissingError)
202
- end
203
-
204
- it "does not raises an error if the required option has a default value" do
205
- options = {:required => true, :type => :string, :default => "baz"}
206
- create :foo => Thor::Option.new("foo", options), :bar => :boolean
207
- expect { parse("--bar") }.not_to raise_error
208
- end
209
- end
210
-
211
- context "when stop_on_unknown is true" do
212
- before do
213
- create({:foo => :string, :verbose => :boolean}, {}, true)
214
- end
215
-
216
- it "stops parsing on first non-option" do
217
- expect(parse(%w[foo --verbose])).to eq({})
218
- expect(remaining).to eq(%w[foo --verbose])
219
- end
220
-
221
- it "stops parsing on unknown option" do
222
- expect(parse(%w[--bar --verbose])).to eq({})
223
- expect(remaining).to eq(%w[--bar --verbose])
224
- end
225
-
226
- it "retains -- after it has stopped parsing" do
227
- expect(parse(%w[--bar -- whatever])).to eq({})
228
- expect(remaining).to eq(%w[--bar -- whatever])
229
- end
230
-
231
- it "still accepts options that are given before non-options" do
232
- expect(parse(%w[--verbose foo])).to eq("verbose" => true)
233
- expect(remaining).to eq(%w[foo])
234
- end
235
-
236
- it "still accepts options that require a value" do
237
- expect(parse(%w[--foo bar baz])).to eq("foo" => "bar")
238
- expect(remaining).to eq(%w[baz])
239
- end
240
-
241
- it "still interprets everything after -- as args instead of options" do
242
- expect(parse(%w[-- --verbose])).to eq({})
243
- expect(remaining).to eq(%w[--verbose])
244
- end
245
- end
246
-
247
- describe "with :string type" do
248
- before do
249
- create %w[--foo -f] => :required
250
- end
251
-
252
- it "accepts a switch <value> assignment" do
253
- expect(parse("--foo", "12")["foo"]).to eq("12")
254
- end
255
-
256
- it "accepts a switch=<value> assignment" do
257
- expect(parse("-f=12")["foo"]).to eq("12")
258
- expect(parse("--foo=12")["foo"]).to eq("12")
259
- expect(parse("--foo=bar=baz")["foo"]).to eq("bar=baz")
260
- end
261
-
262
- it "must accept underscores switch=value assignment" do
263
- create :foo_bar => :required
264
- expect(parse("--foo_bar=http://example.com/under_score/")["foo_bar"]).to eq("http://example.com/under_score/")
265
- end
266
-
267
- it "accepts a --no-switch format" do
268
- create "--foo" => "bar"
269
- expect(parse("--no-foo")["foo"]).to be nil
270
- end
271
-
272
- it "does not consume an argument for --no-switch format" do
273
- create "--cheese" => :string
274
- expect(parse("burger", "--no-cheese", "fries")["cheese"]).to be nil
275
- end
276
-
277
- it "accepts a --switch format on non required types" do
278
- create "--foo" => :string
279
- expect(parse("--foo")["foo"]).to eq("foo")
280
- end
281
-
282
- it "accepts a --switch format on non required types with default values" do
283
- create "--baz" => :string, "--foo" => "bar"
284
- expect(parse("--baz", "bang", "--foo")["foo"]).to eq("bar")
285
- end
286
-
287
- it "overwrites earlier values with later values" do
288
- expect(parse("--foo=bar", "--foo", "12")["foo"]).to eq("12")
289
- expect(parse("--foo", "12", "--foo", "13")["foo"]).to eq("13")
290
- end
291
-
292
- it "raises error when value isn't in enum" do
293
- enum = %w[apple banana]
294
- create :fruit => Thor::Option.new("fruit", :type => :string, :enum => enum)
295
- expect { parse("--fruit", "orange") }.to raise_error(Thor::MalformattedArgumentError,
296
- "Expected '--fruit' to be one of #{enum.join(', ')}; got orange")
297
- end
298
- end
299
-
300
- describe "with :boolean type" do
301
- before do
302
- create "--foo" => false
303
- end
304
-
305
- it "accepts --opt assignment" do
306
- expect(parse("--foo")["foo"]).to eq(true)
307
- expect(parse("--foo", "--bar")["foo"]).to eq(true)
308
- end
309
-
310
- it "uses the default value if no switch is given" do
311
- expect(parse("")["foo"]).to eq(false)
312
- end
313
-
314
- it "accepts --opt=value assignment" do
315
- expect(parse("--foo=true")["foo"]).to eq(true)
316
- expect(parse("--foo=false")["foo"]).to eq(false)
317
- end
318
-
319
- it "accepts --[no-]opt variant, setting false for value" do
320
- expect(parse("--no-foo")["foo"]).to eq(false)
321
- end
322
-
323
- it "accepts --[skip-]opt variant, setting false for value" do
324
- expect(parse("--skip-foo")["foo"]).to eq(false)
325
- end
326
-
327
- it "will prefer 'no-opt' variant over inverting 'opt' if explicitly set" do
328
- create "--no-foo" => true
329
- expect(parse("--no-foo")["no-foo"]).to eq(true)
330
- end
331
-
332
- it "will prefer 'skip-opt' variant over inverting 'opt' if explicitly set" do
333
- create "--skip-foo" => true
334
- expect(parse("--skip-foo")["skip-foo"]).to eq(true)
335
- end
336
-
337
- it "accepts inputs in the human name format" do
338
- create :foo_bar => :boolean
339
- expect(parse("--foo-bar")["foo_bar"]).to eq(true)
340
- expect(parse("--no-foo-bar")["foo_bar"]).to eq(false)
341
- expect(parse("--skip-foo-bar")["foo_bar"]).to eq(false)
342
- end
343
-
344
- it "doesn't eat the next part of the param" do
345
- create :foo => :boolean
346
- expect(parse("--foo", "bar")).to eq("foo" => true)
347
- expect(@opt.remaining).to eq(%w[bar])
348
- end
349
- end
350
-
351
- describe "with :hash type" do
352
- before do
353
- create "--attributes" => :hash
354
- end
355
-
356
- it "accepts a switch=<value> assignment" do
357
- expect(parse("--attributes=name:string", "age:integer")["attributes"]).to eq("name" => "string", "age" => "integer")
358
- end
359
-
360
- it "accepts a switch <value> assignment" do
361
- expect(parse("--attributes", "name:string", "age:integer")["attributes"]).to eq("name" => "string", "age" => "integer")
362
- end
363
-
364
- it "must not mix values with other switches" do
365
- expect(parse("--attributes", "name:string", "age:integer", "--baz", "cool")["attributes"]).to eq("name" => "string", "age" => "integer")
366
- end
367
- end
368
-
369
- describe "with :array type" do
370
- before do
371
- create "--attributes" => :array
372
- end
373
-
374
- it "accepts a switch=<value> assignment" do
375
- expect(parse("--attributes=a", "b", "c")["attributes"]).to eq(%w[a b c])
376
- end
377
-
378
- it "accepts a switch <value> assignment" do
379
- expect(parse("--attributes", "a", "b", "c")["attributes"]).to eq(%w[a b c])
380
- end
381
-
382
- it "must not mix values with other switches" do
383
- expect(parse("--attributes", "a", "b", "c", "--baz", "cool")["attributes"]).to eq(%w[a b c])
384
- end
385
- end
386
-
387
- describe "with :numeric type" do
388
- before do
389
- create "n" => :numeric, "m" => 5
390
- end
391
-
392
- it "accepts a -nXY assignment" do
393
- expect(parse("-n12")["n"]).to eq(12)
394
- end
395
-
396
- it "converts values to numeric types" do
397
- expect(parse("-n", "3", "-m", ".5")).to eq("n" => 3, "m" => 0.5)
398
- end
399
-
400
- it "raises error when value isn't numeric" do
401
- expect { parse("-n", "foo") }.to raise_error(Thor::MalformattedArgumentError,
402
- "Expected numeric value for '-n'; got \"foo\"")
403
- end
404
-
405
- it "raises error when value isn't in enum" do
406
- enum = [1, 2]
407
- create :limit => Thor::Option.new("limit", :type => :numeric, :enum => enum)
408
- expect { parse("--limit", "3") }.to raise_error(Thor::MalformattedArgumentError,
409
- "Expected '--limit' to be one of #{enum.join(', ')}; got 3")
410
- end
411
- end
412
-
413
- end
414
- end