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.
- checksums.yaml +7 -0
- data/.document +5 -0
- data/CHANGELOG.md +130 -0
- data/LICENSE.md +20 -0
- data/README.md +34 -0
- data/Thorfile +30 -0
- data/bin/rake2thor +86 -0
- data/bin/thor +6 -0
- data/lib/thor.rb +458 -0
- data/lib/thor/actions.rb +318 -0
- data/lib/thor/actions/create_file.rb +105 -0
- data/lib/thor/actions/create_link.rb +60 -0
- data/lib/thor/actions/directory.rb +119 -0
- data/lib/thor/actions/empty_directory.rb +153 -0
- data/lib/thor/actions/file_manipulation.rb +314 -0
- data/lib/thor/actions/inject_into_file.rb +109 -0
- data/lib/thor/base.rb +649 -0
- data/lib/thor/command.rb +136 -0
- data/lib/thor/core_ext/hash_with_indifferent_access.rb +80 -0
- data/lib/thor/core_ext/io_binary_read.rb +12 -0
- data/lib/thor/core_ext/ordered_hash.rb +100 -0
- data/lib/thor/error.rb +32 -0
- data/lib/thor/exclude_pattern/version.rb +5 -0
- data/lib/thor/group.rb +287 -0
- data/lib/thor/invocation.rb +172 -0
- data/lib/thor/parser.rb +4 -0
- data/lib/thor/parser/argument.rb +74 -0
- data/lib/thor/parser/arguments.rb +171 -0
- data/lib/thor/parser/option.rb +121 -0
- data/lib/thor/parser/options.rb +218 -0
- data/lib/thor/rake_compat.rb +72 -0
- data/lib/thor/runner.rb +322 -0
- data/lib/thor/shell.rb +88 -0
- data/lib/thor/shell/basic.rb +393 -0
- data/lib/thor/shell/color.rb +148 -0
- data/lib/thor/shell/html.rb +127 -0
- data/lib/thor/util.rb +270 -0
- data/lib/thor/version.rb +3 -0
- data/spec/actions/create_file_spec.rb +170 -0
- data/spec/actions/create_link_spec.rb +95 -0
- data/spec/actions/directory_spec.rb +169 -0
- data/spec/actions/empty_directory_spec.rb +130 -0
- data/spec/actions/file_manipulation_spec.rb +382 -0
- data/spec/actions/inject_into_file_spec.rb +135 -0
- data/spec/actions_spec.rb +331 -0
- data/spec/base_spec.rb +294 -0
- data/spec/command_spec.rb +80 -0
- data/spec/core_ext/hash_with_indifferent_access_spec.rb +48 -0
- data/spec/core_ext/ordered_hash_spec.rb +115 -0
- data/spec/exit_condition_spec.rb +19 -0
- data/spec/fixtures/application.rb +2 -0
- data/spec/fixtures/app{1}/README +3 -0
- data/spec/fixtures/bundle/execute.rb +6 -0
- data/spec/fixtures/bundle/main.thor +1 -0
- data/spec/fixtures/command.thor +10 -0
- data/spec/fixtures/doc/%file_name%.rb.tt +1 -0
- data/spec/fixtures/doc/COMMENTER +11 -0
- data/spec/fixtures/doc/README +3 -0
- data/spec/fixtures/doc/block_helper.rb +3 -0
- data/spec/fixtures/doc/config.rb +1 -0
- data/spec/fixtures/doc/config.yaml.tt +1 -0
- data/spec/fixtures/doc/excluding/%file_name%.rb.tt +1 -0
- data/spec/fixtures/enum.thor +10 -0
- data/spec/fixtures/group.thor +128 -0
- data/spec/fixtures/invoke.thor +112 -0
- data/spec/fixtures/path with spaces b/data/spec/fixtures/path with → spaces +0 -0
- data/spec/fixtures/preserve/script.sh +3 -0
- data/spec/fixtures/script.thor +199 -0
- data/spec/fixtures/subcommand.thor +17 -0
- data/spec/group_spec.rb +216 -0
- data/spec/helper.rb +67 -0
- data/spec/invocation_spec.rb +100 -0
- data/spec/parser/argument_spec.rb +53 -0
- data/spec/parser/arguments_spec.rb +66 -0
- data/spec/parser/option_spec.rb +202 -0
- data/spec/parser/options_spec.rb +400 -0
- data/spec/rake_compat_spec.rb +72 -0
- data/spec/register_spec.rb +197 -0
- data/spec/runner_spec.rb +241 -0
- data/spec/sandbox/application.rb +2 -0
- data/spec/sandbox/app{1}/README +3 -0
- data/spec/sandbox/bundle/execute.rb +6 -0
- data/spec/sandbox/bundle/main.thor +1 -0
- data/spec/sandbox/command.thor +10 -0
- data/spec/sandbox/doc/%file_name%.rb.tt +1 -0
- data/spec/sandbox/doc/COMMENTER +11 -0
- data/spec/sandbox/doc/README +4 -0
- data/spec/sandbox/doc/block_helper.rb +3 -0
- data/spec/sandbox/doc/config.rb +1 -0
- data/spec/sandbox/doc/config.yaml.tt +1 -0
- data/spec/sandbox/doc/excluding/%file_name%.rb.tt +1 -0
- data/spec/sandbox/enum.thor +10 -0
- data/spec/sandbox/group.thor +128 -0
- data/spec/sandbox/invoke.thor +112 -0
- data/spec/sandbox/path with spaces b/data/spec/sandbox/path with → spaces +0 -0
- data/spec/sandbox/preserve/script.sh +3 -0
- data/spec/sandbox/script.thor +199 -0
- data/spec/sandbox/subcommand.thor +17 -0
- data/spec/shell/basic_spec.rb +311 -0
- data/spec/shell/color_spec.rb +95 -0
- data/spec/shell/html_spec.rb +32 -0
- data/spec/shell_spec.rb +47 -0
- data/spec/subcommand_spec.rb +30 -0
- data/spec/thor_spec.rb +469 -0
- data/spec/util_spec.rb +196 -0
- data/thor.gemspec +24 -0
- metadata +232 -0
data/spec/shell_spec.rb
ADDED
@@ -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
|