thor-exclude_pattern 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/CHANGELOG.md +130 -0
  4. data/LICENSE.md +20 -0
  5. data/README.md +34 -0
  6. data/Thorfile +30 -0
  7. data/bin/rake2thor +86 -0
  8. data/bin/thor +6 -0
  9. data/lib/thor.rb +458 -0
  10. data/lib/thor/actions.rb +318 -0
  11. data/lib/thor/actions/create_file.rb +105 -0
  12. data/lib/thor/actions/create_link.rb +60 -0
  13. data/lib/thor/actions/directory.rb +119 -0
  14. data/lib/thor/actions/empty_directory.rb +153 -0
  15. data/lib/thor/actions/file_manipulation.rb +314 -0
  16. data/lib/thor/actions/inject_into_file.rb +109 -0
  17. data/lib/thor/base.rb +649 -0
  18. data/lib/thor/command.rb +136 -0
  19. data/lib/thor/core_ext/hash_with_indifferent_access.rb +80 -0
  20. data/lib/thor/core_ext/io_binary_read.rb +12 -0
  21. data/lib/thor/core_ext/ordered_hash.rb +100 -0
  22. data/lib/thor/error.rb +32 -0
  23. data/lib/thor/exclude_pattern/version.rb +5 -0
  24. data/lib/thor/group.rb +287 -0
  25. data/lib/thor/invocation.rb +172 -0
  26. data/lib/thor/parser.rb +4 -0
  27. data/lib/thor/parser/argument.rb +74 -0
  28. data/lib/thor/parser/arguments.rb +171 -0
  29. data/lib/thor/parser/option.rb +121 -0
  30. data/lib/thor/parser/options.rb +218 -0
  31. data/lib/thor/rake_compat.rb +72 -0
  32. data/lib/thor/runner.rb +322 -0
  33. data/lib/thor/shell.rb +88 -0
  34. data/lib/thor/shell/basic.rb +393 -0
  35. data/lib/thor/shell/color.rb +148 -0
  36. data/lib/thor/shell/html.rb +127 -0
  37. data/lib/thor/util.rb +270 -0
  38. data/lib/thor/version.rb +3 -0
  39. data/spec/actions/create_file_spec.rb +170 -0
  40. data/spec/actions/create_link_spec.rb +95 -0
  41. data/spec/actions/directory_spec.rb +169 -0
  42. data/spec/actions/empty_directory_spec.rb +130 -0
  43. data/spec/actions/file_manipulation_spec.rb +382 -0
  44. data/spec/actions/inject_into_file_spec.rb +135 -0
  45. data/spec/actions_spec.rb +331 -0
  46. data/spec/base_spec.rb +294 -0
  47. data/spec/command_spec.rb +80 -0
  48. data/spec/core_ext/hash_with_indifferent_access_spec.rb +48 -0
  49. data/spec/core_ext/ordered_hash_spec.rb +115 -0
  50. data/spec/exit_condition_spec.rb +19 -0
  51. data/spec/fixtures/application.rb +2 -0
  52. data/spec/fixtures/app{1}/README +3 -0
  53. data/spec/fixtures/bundle/execute.rb +6 -0
  54. data/spec/fixtures/bundle/main.thor +1 -0
  55. data/spec/fixtures/command.thor +10 -0
  56. data/spec/fixtures/doc/%file_name%.rb.tt +1 -0
  57. data/spec/fixtures/doc/COMMENTER +11 -0
  58. data/spec/fixtures/doc/README +3 -0
  59. data/spec/fixtures/doc/block_helper.rb +3 -0
  60. data/spec/fixtures/doc/config.rb +1 -0
  61. data/spec/fixtures/doc/config.yaml.tt +1 -0
  62. data/spec/fixtures/doc/excluding/%file_name%.rb.tt +1 -0
  63. data/spec/fixtures/enum.thor +10 -0
  64. data/spec/fixtures/group.thor +128 -0
  65. data/spec/fixtures/invoke.thor +112 -0
  66. data/spec/fixtures/path with spaces b/data/spec/fixtures/path with → spaces +0 -0
  67. data/spec/fixtures/preserve/script.sh +3 -0
  68. data/spec/fixtures/script.thor +199 -0
  69. data/spec/fixtures/subcommand.thor +17 -0
  70. data/spec/group_spec.rb +216 -0
  71. data/spec/helper.rb +67 -0
  72. data/spec/invocation_spec.rb +100 -0
  73. data/spec/parser/argument_spec.rb +53 -0
  74. data/spec/parser/arguments_spec.rb +66 -0
  75. data/spec/parser/option_spec.rb +202 -0
  76. data/spec/parser/options_spec.rb +400 -0
  77. data/spec/rake_compat_spec.rb +72 -0
  78. data/spec/register_spec.rb +197 -0
  79. data/spec/runner_spec.rb +241 -0
  80. data/spec/sandbox/application.rb +2 -0
  81. data/spec/sandbox/app{1}/README +3 -0
  82. data/spec/sandbox/bundle/execute.rb +6 -0
  83. data/spec/sandbox/bundle/main.thor +1 -0
  84. data/spec/sandbox/command.thor +10 -0
  85. data/spec/sandbox/doc/%file_name%.rb.tt +1 -0
  86. data/spec/sandbox/doc/COMMENTER +11 -0
  87. data/spec/sandbox/doc/README +4 -0
  88. data/spec/sandbox/doc/block_helper.rb +3 -0
  89. data/spec/sandbox/doc/config.rb +1 -0
  90. data/spec/sandbox/doc/config.yaml.tt +1 -0
  91. data/spec/sandbox/doc/excluding/%file_name%.rb.tt +1 -0
  92. data/spec/sandbox/enum.thor +10 -0
  93. data/spec/sandbox/group.thor +128 -0
  94. data/spec/sandbox/invoke.thor +112 -0
  95. data/spec/sandbox/path with spaces b/data/spec/sandbox/path with → spaces +0 -0
  96. data/spec/sandbox/preserve/script.sh +3 -0
  97. data/spec/sandbox/script.thor +199 -0
  98. data/spec/sandbox/subcommand.thor +17 -0
  99. data/spec/shell/basic_spec.rb +311 -0
  100. data/spec/shell/color_spec.rb +95 -0
  101. data/spec/shell/html_spec.rb +32 -0
  102. data/spec/shell_spec.rb +47 -0
  103. data/spec/subcommand_spec.rb +30 -0
  104. data/spec/thor_spec.rb +469 -0
  105. data/spec/util_spec.rb +196 -0
  106. data/thor.gemspec +24 -0
  107. metadata +232 -0
@@ -0,0 +1,47 @@
1
+ require 'helper'
2
+
3
+ describe Thor::Shell do
4
+ def shell
5
+ @shell ||= Thor::Base.shell.new
6
+ end
7
+
8
+ describe "#initialize" do
9
+ it "sets shell value" do
10
+ base = MyCounter.new [1, 2], { }, :shell => shell
11
+ expect(base.shell).to eq(shell)
12
+ end
13
+
14
+ it "sets the base value on the shell if an accessor is available" do
15
+ base = MyCounter.new [1, 2], { }, :shell => shell
16
+ expect(shell.base).to eq(base)
17
+ end
18
+ end
19
+
20
+ describe "#shell" do
21
+ it "returns the shell in use" do
22
+ expect(MyCounter.new([1,2]).shell).to be_kind_of(Thor::Base.shell)
23
+ end
24
+
25
+ it "uses $THOR_SHELL" do
26
+ class Thor::Shell::TestShell < Thor::Shell::Basic; end
27
+
28
+ expect(Thor::Base.shell).to eq(shell.class)
29
+ ENV['THOR_SHELL'] = 'TestShell'
30
+ Thor::Base.shell = nil
31
+ expect(Thor::Base.shell).to eq(Thor::Shell::TestShell)
32
+ ENV['THOR_SHELL'] = ''
33
+ Thor::Base.shell = shell.class
34
+ expect(Thor::Base.shell).to eq(shell.class)
35
+ end
36
+ end
37
+
38
+ describe "with_padding" do
39
+ it "uses padding for inside block outputs" do
40
+ base = MyCounter.new([1,2])
41
+ base.with_padding do
42
+ expect(capture(:stdout) { base.say_status :padding, "cool" }.strip).to eq("padding cool")
43
+ end
44
+ end
45
+ end
46
+
47
+ end
@@ -0,0 +1,30 @@
1
+ require 'helper'
2
+
3
+ describe Thor do
4
+
5
+ describe "#subcommand" do
6
+
7
+ it "maps a given subcommand to another Thor subclass" do
8
+ barn_help = capture(:stdout) { Scripts::MyDefaults.start(%w[barn]) }
9
+ expect(barn_help).to include("barn help [COMMAND] # Describe subcommands or one specific subcommand")
10
+ end
11
+
12
+ it "passes commands to subcommand classes" do
13
+ expect(capture(:stdout) { Scripts::MyDefaults.start(%w[barn open]) }.strip).to eq("Open sesame!")
14
+ end
15
+
16
+ it "passes arguments to subcommand classes" do
17
+ expect(capture(:stdout) { Scripts::MyDefaults.start(%w[barn open shotgun]) }.strip).to eq("That's going to leave a mark.")
18
+ end
19
+
20
+ it "ignores unknown options (the subcommand class will handle them)" do
21
+ expect(capture(:stdout) { Scripts::MyDefaults.start(%w[barn paint blue --coats 4])}.strip).to eq("4 coats of blue paint")
22
+ end
23
+
24
+ it "passes parsed options to subcommands" do
25
+ output = capture(:stdout) { TestSubcommands::Parent.start(%w[sub print_opt --opt output]) }
26
+ expect(output).to eq("output")
27
+ end
28
+ end
29
+
30
+ end
data/spec/thor_spec.rb ADDED
@@ -0,0 +1,469 @@
1
+ require 'helper'
2
+
3
+ describe Thor do
4
+ describe "#method_option" do
5
+ it "sets options to the next method to be invoked" do
6
+ args = ["foo", "bar", "--force"]
7
+ arg, options = MyScript.start(args)
8
+ expect(options).to eq({ "force" => true })
9
+ end
10
+
11
+ describe ":lazy_default" do
12
+ it "is absent when option is not specified" do
13
+ arg, options = MyScript.start(["with_optional"])
14
+ expect(options).to eq({})
15
+ end
16
+
17
+ it "sets a default that can be overridden for strings" do
18
+ arg, options = MyScript.start(["with_optional", "--lazy"])
19
+ expect(options).to eq({ "lazy" => "yes" })
20
+
21
+ arg, options = MyScript.start(["with_optional", "--lazy", "yesyes!"])
22
+ expect(options).to eq({ "lazy" => "yesyes!" })
23
+ end
24
+
25
+ it "sets a default that can be overridden for numerics" do
26
+ arg, options = MyScript.start(["with_optional", "--lazy-numeric"])
27
+ expect(options).to eq({ "lazy_numeric" => 42 })
28
+
29
+ arg, options = MyScript.start(["with_optional", "--lazy-numeric", 20000])
30
+ expect(options).to eq({ "lazy_numeric" => 20000 })
31
+ end
32
+
33
+ it "sets a default that can be overridden for arrays" do
34
+ arg, options = MyScript.start(["with_optional", "--lazy-array"])
35
+ expect(options).to eq({ "lazy_array" => %w[eat at joes] })
36
+
37
+ arg, options = MyScript.start(["with_optional", "--lazy-array", "hello", "there"])
38
+ expect(options).to eq({ "lazy_array" => %w[hello there] })
39
+ end
40
+
41
+ it "sets a default that can be overridden for hashes" do
42
+ arg, options = MyScript.start(["with_optional", "--lazy-hash"])
43
+ expect(options).to eq({ "lazy_hash" => {'swedish' => 'meatballs'} })
44
+
45
+ arg, options = MyScript.start(["with_optional", "--lazy-hash", "polish:sausage"])
46
+ expect(options).to eq({ "lazy_hash" => {'polish' => 'sausage'} })
47
+ end
48
+ end
49
+
50
+ describe "when :for is supplied" do
51
+ it "updates an already defined command" do
52
+ args, options = MyChildScript.start(["animal", "horse", "--other=fish"])
53
+ expect(options[:other]).to eq("fish")
54
+ end
55
+
56
+ describe "and the target is on the parent class" do
57
+ it "updates an already defined command" do
58
+ args = ["example_default_command", "my_param", "--new-option=verified"]
59
+ options = Scripts::MyScript.start(args)
60
+ expect(options[:new_option]).to eq("verified")
61
+ end
62
+
63
+ it "adds a command to the command list if the updated command is on the parent class" do
64
+ expect(Scripts::MyScript.commands["example_default_command"]).to be
65
+ end
66
+
67
+ it "clones the parent command" do
68
+ expect(Scripts::MyScript.commands["example_default_command"]).not_to eq(MyChildScript.commands["example_default_command"])
69
+ end
70
+ end
71
+ end
72
+ end
73
+
74
+ describe "#default_command" do
75
+ it "sets a default command" do
76
+ expect(MyScript.default_command).to eq("example_default_command")
77
+ end
78
+
79
+ it "invokes the default command if no command is specified" do
80
+ expect(MyScript.start([])).to eq("default command")
81
+ end
82
+
83
+ it "invokes the default command if no command is specified even if switches are given" do
84
+ expect(MyScript.start(["--with", "option"])).to eq({"with"=>"option"})
85
+ end
86
+
87
+ it "inherits the default command from parent" do
88
+ expect(MyChildScript.default_command).to eq("example_default_command")
89
+ end
90
+ end
91
+
92
+ describe "#stop_on_unknown_option!" do
93
+ my_script = Class.new(Thor) do
94
+ class_option "verbose", :type => :boolean
95
+ class_option "mode", :type => :string
96
+
97
+ stop_on_unknown_option! :exec
98
+
99
+ desc "exec", "Run a command"
100
+ def exec(*args)
101
+ return options, args
102
+ end
103
+
104
+ desc "boring", "An ordinary command"
105
+ def boring(*args)
106
+ return options, args
107
+ end
108
+ end
109
+
110
+ it "passes remaining args to command when it encounters a non-option" do
111
+ expect(my_script.start(%w[exec command --verbose])).to eq [{}, ["command", "--verbose"]]
112
+ end
113
+
114
+ it "passes remaining args to command when it encounters an unknown option" do
115
+ expect(my_script.start(%w[exec --foo command --bar])).to eq [{}, ["--foo", "command", "--bar"]]
116
+ end
117
+
118
+ it "still accepts options that are given before non-options" do
119
+ expect(my_script.start(%w[exec --verbose command --foo])).to eq [{"verbose" => true}, ["command", "--foo"]]
120
+ end
121
+
122
+ it "still accepts options that require a value" do
123
+ expect(my_script.start(%w[exec --mode rashly command])).to eq [{"mode" => "rashly"}, ["command"]]
124
+ end
125
+
126
+ it "still passes everything after -- to command" do
127
+ expect(my_script.start(%w[exec -- --verbose])).to eq [{}, ["--verbose"]]
128
+ end
129
+
130
+ it "does not affect ordinary commands" do
131
+ expect(my_script.start(%w[boring command --verbose])).to eq [{"verbose" => true}, ["command"]]
132
+ end
133
+
134
+ context "when provided with multiple command names" do
135
+ klass = Class.new(Thor) do
136
+ stop_on_unknown_option! :foo, :bar
137
+ end
138
+ it "affects all specified commands" do
139
+ expect(klass.stop_on_unknown_option?(mock :name => "foo")).to be_true
140
+ expect(klass.stop_on_unknown_option?(mock :name => "bar")).to be_true
141
+ expect(klass.stop_on_unknown_option?(mock :name => "baz")).to be_false
142
+ end
143
+ end
144
+
145
+ context "when invoked several times" do
146
+ klass = Class.new(Thor) do
147
+ stop_on_unknown_option! :foo
148
+ stop_on_unknown_option! :bar
149
+ end
150
+ it "affects all specified commands" do
151
+ expect(klass.stop_on_unknown_option?(mock :name => "foo")).to be_true
152
+ expect(klass.stop_on_unknown_option?(mock :name => "bar")).to be_true
153
+ expect(klass.stop_on_unknown_option?(mock :name => "baz")).to be_false
154
+ end
155
+ end
156
+ end
157
+
158
+ describe "#map" do
159
+ it "calls the alias of a method if one is provided" do
160
+ expect(MyScript.start(["-T", "fish"])).to eq(["fish"])
161
+ end
162
+
163
+ it "calls the alias of a method if several are provided via .map" do
164
+ expect(MyScript.start(["-f", "fish"])).to eq(["fish", {}])
165
+ expect(MyScript.start(["--foo", "fish"])).to eq(["fish", {}])
166
+ end
167
+
168
+ it "inherits all mappings from parent" do
169
+ expect(MyChildScript.default_command).to eq("example_default_command")
170
+ end
171
+ end
172
+
173
+ describe "#desc" do
174
+ it "provides description for a command" do
175
+ content = capture(:stdout) { MyScript.start(["help"]) }
176
+ expect(content).to match(/thor my_script:zoo\s+# zoo around/m)
177
+ end
178
+
179
+ it "provides no namespace if $thor_runner is false" do
180
+ begin
181
+ $thor_runner = false
182
+ content = capture(:stdout) { MyScript.start(["help"]) }
183
+ expect(content).to match(/thor zoo\s+# zoo around/m)
184
+ ensure
185
+ $thor_runner = true
186
+ end
187
+ end
188
+
189
+ describe "when :for is supplied" do
190
+ it "overwrites a previous defined command" do
191
+ expect(capture(:stdout) { MyChildScript.start(["help"]) }).to match(/animal KIND \s+# fish around/m)
192
+ end
193
+ end
194
+
195
+ describe "when :hide is supplied" do
196
+ it "does not show the command in help" do
197
+ expect(capture(:stdout) { MyScript.start(["help"]) }).not_to match(/this is hidden/m)
198
+ end
199
+
200
+ it "but the command is still invokcable not show the command in help" do
201
+ expect(MyScript.start(["hidden", "yesyes"])).to eq(["yesyes"])
202
+ end
203
+ end
204
+ end
205
+
206
+ describe "#method_options" do
207
+ it "sets default options if called before an initializer" do
208
+ options = MyChildScript.class_options
209
+ expect(options[:force].type).to eq(:boolean)
210
+ expect(options[:param].type).to eq(:numeric)
211
+ end
212
+
213
+ it "overwrites default options if called on the method scope" do
214
+ args = ["zoo", "--force", "--param", "feathers"]
215
+ options = MyChildScript.start(args)
216
+ expect(options).to eq({ "force" => true, "param" => "feathers" })
217
+ end
218
+
219
+ it "allows default options to be merged with method options" do
220
+ args = ["animal", "bird", "--force", "--param", "1.0", "--other", "tweets"]
221
+ arg, options = MyChildScript.start(args)
222
+ expect(arg).to eq('bird')
223
+ expect(options).to eq({ "force"=>true, "param"=>1.0, "other"=>"tweets" })
224
+ end
225
+ end
226
+
227
+ describe "#start" do
228
+ it "calls a no-param method when no params are passed" do
229
+ expect(MyScript.start(["zoo"])).to eq(true)
230
+ end
231
+
232
+ it "calls a single-param method when a single param is passed" do
233
+ expect(MyScript.start(["animal", "fish"])).to eq(["fish"])
234
+ end
235
+
236
+ it "does not set options in attributes" do
237
+ expect(MyScript.start(["with_optional", "--all"])).to eq([nil, { "all" => true }, []])
238
+ end
239
+
240
+ it "raises an error if a required param is not provided" do
241
+ expect(capture(:stderr) { MyScript.start(["animal"]) }.strip).to eq('thor animal requires at least 1 argument: "thor my_script:animal TYPE".')
242
+ end
243
+
244
+ it "raises an error if the invoked command does not exist" do
245
+ expect(capture(:stderr) { Amazing.start(["animal"]) }.strip).to eq('Could not find command "animal" in "amazing" namespace.')
246
+ end
247
+
248
+ it "calls method_missing if an unknown method is passed in" do
249
+ expect(MyScript.start(["unk", "hello"])).to eq([:unk, ["hello"]])
250
+ end
251
+
252
+ it "does not call a private method no matter what" do
253
+ expect(capture(:stderr) { MyScript.start(["what"]) }.strip).to eq('Could not find command "what" in "my_script" namespace.')
254
+ end
255
+
256
+ it "uses command default options" do
257
+ options = MyChildScript.start(["animal", "fish"]).last
258
+ expect(options).to eq({ "other" => "method default" })
259
+ end
260
+
261
+ it "raises when an exception happens within the command call" do
262
+ expect{ MyScript.start(["call_myself_with_wrong_arity"]) }.to raise_error(ArgumentError)
263
+ end
264
+
265
+ context "when the user enters an unambiguous substring of a command" do
266
+ it "invokes a command" do
267
+ expect(MyScript.start(["z"])).to eq(MyScript.start(["zoo"]))
268
+ end
269
+
270
+ it "invokes a command, even when there's an alias it resolves to the same command" do
271
+ expect(MyScript.start(["hi", "arg"])).to eq(MyScript.start(["hidden", "arg"]))
272
+ end
273
+
274
+ it "invokes an alias" do
275
+ expect(MyScript.start(["animal_pri"])).to eq(MyScript.start(["zoo"]))
276
+ end
277
+ end
278
+
279
+ context "when the user enters an ambiguous substring of a command" do
280
+ it "raises an exception that explains the ambiguity" do
281
+ expect{ MyScript.start(["call"]) }.to raise_error(ArgumentError, 'Ambiguous command call matches [call_myself_with_wrong_arity, call_unexistent_method]')
282
+ end
283
+
284
+ it "raises an exception when there is an alias" do
285
+ expect{ MyScript.start(["f"]) }.to raise_error(ArgumentError, 'Ambiguous command f matches [foo, fu]')
286
+ end
287
+ end
288
+
289
+ end
290
+
291
+ describe "#help" do
292
+ def shell
293
+ @shell ||= Thor::Base.shell.new
294
+ end
295
+
296
+ describe "on general" do
297
+ before do
298
+ @content = capture(:stdout) { MyScript.help(shell) }
299
+ end
300
+
301
+ it "provides useful help info for the help method itself" do
302
+ expect(@content).to match(/help \[COMMAND\]\s+# Describe available commands/)
303
+ end
304
+
305
+ it "provides useful help info for a method with params" do
306
+ expect(@content).to match(/animal TYPE\s+# horse around/)
307
+ end
308
+
309
+ it "uses the maximum terminal size to show commands" do
310
+ @shell.should_receive(:terminal_width).and_return(80)
311
+ content = capture(:stdout) { MyScript.help(shell) }
312
+ expect(content).to match(/aaa\.\.\.$/)
313
+ end
314
+
315
+ it "provides description for commands from classes in the same namespace" do
316
+ expect(@content).to match(/baz\s+# do some bazing/)
317
+ end
318
+
319
+ it "shows superclass commands" do
320
+ content = capture(:stdout) { MyChildScript.help(shell) }
321
+ expect(content).to match(/foo BAR \s+# do some fooing/)
322
+ end
323
+
324
+ it "shows class options information" do
325
+ content = capture(:stdout) { MyChildScript.help(shell) }
326
+ expect(content).to match(/Options\:/)
327
+ expect(content).to match(/\[\-\-param=N\]/)
328
+ end
329
+
330
+ it "injects class arguments into default usage" do
331
+ content = capture(:stdout) { Scripts::MyScript.help(shell) }
332
+ expect(content).to match(/zoo ACCESSOR \-\-param\=PARAM/)
333
+ end
334
+ end
335
+
336
+ describe "for a specific command" do
337
+ it "provides full help info when talking about a specific command" do
338
+ expect(capture(:stdout) { MyScript.command_help(shell, "foo") }).to eq(<<-END)
339
+ Usage:
340
+ thor my_script:foo BAR
341
+
342
+ Options:
343
+ [--force] # Force to do some fooing
344
+
345
+ do some fooing
346
+ This is more info!
347
+ Everyone likes more info!
348
+ END
349
+ end
350
+
351
+ it "raises an error if the command can't be found" do
352
+ expect {
353
+ MyScript.command_help(shell, "unknown")
354
+ }.to raise_error(Thor::UndefinedCommandError, 'Could not find command "unknown" in "my_script" namespace.')
355
+ end
356
+
357
+ it "normalizes names before claiming they don't exist" do
358
+ expect(capture(:stdout) { MyScript.command_help(shell, "name-with-dashes") }).to match(/thor my_script:name-with-dashes/)
359
+ end
360
+
361
+ it "uses the long description if it exists" do
362
+ expect(capture(:stdout) { MyScript.command_help(shell, "long_description") }).to eq(<<-HELP)
363
+ Usage:
364
+ thor my_script:long_description
365
+
366
+ Description:
367
+ This is a really really really long description. Here you go. So very long.
368
+
369
+ It even has two paragraphs.
370
+ HELP
371
+ end
372
+
373
+ it "doesn't assign the long description to the next command without one" do
374
+ expect(capture(:stdout) {
375
+ MyScript.command_help(shell, "name_with_dashes")
376
+ }).not_to match(/so very long/i)
377
+ end
378
+ end
379
+
380
+ describe "instance method" do
381
+ it "calls the class method" do
382
+ expect(capture(:stdout) { MyScript.start(["help"]) }).to match(/Commands:/)
383
+ end
384
+
385
+ it "calls the class method" do
386
+ expect(capture(:stdout) { MyScript.start(["help", "foo"]) }).to match(/Usage:/)
387
+ end
388
+ end
389
+ end
390
+
391
+ describe "when creating commands" do
392
+ it "prints a warning if a public method is created without description or usage" do
393
+ expect(capture(:stdout) {
394
+ klass = Class.new(Thor)
395
+ klass.class_eval "def hello_from_thor; end"
396
+ }).to match(/\[WARNING\] Attempted to create command "hello_from_thor" without usage or description/)
397
+ end
398
+
399
+ it "does not print if overwriting a previous command" do
400
+ expect(capture(:stdout) {
401
+ klass = Class.new(Thor)
402
+ klass.class_eval "def help; end"
403
+ }).to be_empty
404
+ end
405
+ end
406
+
407
+ describe "edge-cases" do
408
+ it "can handle boolean options followed by arguments" do
409
+ klass = Class.new(Thor) do
410
+ method_option :loud, :type => :boolean
411
+ desc "hi NAME", "say hi to name"
412
+ def hi(name)
413
+ name.upcase! if options[:loud]
414
+ "Hi #{name}"
415
+ end
416
+ end
417
+
418
+ expect(klass.start(["hi", "jose"])).to eq("Hi jose")
419
+ expect(klass.start(["hi", "jose", "--loud"])).to eq("Hi JOSE")
420
+ expect(klass.start(["hi", "--loud", "jose"])).to eq("Hi JOSE")
421
+ end
422
+
423
+ it "passes through unknown options" do
424
+ klass = Class.new(Thor) do
425
+ desc "unknown", "passing unknown options"
426
+ def unknown(*args)
427
+ args
428
+ end
429
+ end
430
+
431
+ expect(klass.start(["unknown", "foo", "--bar", "baz", "bat", "--bam"])).to eq(["foo", "--bar", "baz", "bat", "--bam"])
432
+ expect(klass.start(["unknown", "--bar", "baz"])).to eq(["--bar", "baz"])
433
+ end
434
+
435
+ it "does not pass through unknown options with strict args" do
436
+ klass = Class.new(Thor) do
437
+ strict_args_position!
438
+
439
+ desc "unknown", "passing unknown options"
440
+ def unknown(*args)
441
+ args
442
+ end
443
+ end
444
+
445
+ expect(klass.start(["unknown", "--bar", "baz"])).to eq([])
446
+ expect(klass.start(["unknown", "foo", "--bar", "baz"])).to eq(["foo"])
447
+ end
448
+
449
+ it "strict args works in the inheritance chain" do
450
+ parent = Class.new(Thor) do
451
+ strict_args_position!
452
+ end
453
+
454
+ klass = Class.new(parent) do
455
+ desc "unknown", "passing unknown options"
456
+ def unknown(*args)
457
+ args
458
+ end
459
+ end
460
+
461
+ expect(klass.start(["unknown", "--bar", "baz"])).to eq([])
462
+ expect(klass.start(["unknown", "foo", "--bar", "baz"])).to eq(["foo"])
463
+ end
464
+
465
+ it "send as a command name" do
466
+ expect(MyScript.start(["send"])).to eq(true)
467
+ end
468
+ end
469
+ end