thor 0.19.1 → 0.19.2
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 +4 -4
- data/CHANGELOG.md +24 -0
- data/CONTRIBUTING.md +15 -0
- data/README.md +7 -1
- data/lib/thor.rb +31 -23
- data/lib/thor/actions.rb +21 -22
- data/lib/thor/actions/create_file.rb +1 -1
- data/lib/thor/actions/create_link.rb +1 -1
- data/lib/thor/actions/directory.rb +2 -2
- data/lib/thor/actions/empty_directory.rb +8 -8
- data/lib/thor/actions/file_manipulation.rb +23 -12
- data/lib/thor/actions/inject_into_file.rb +10 -14
- data/lib/thor/base.rb +33 -33
- data/lib/thor/command.rb +9 -9
- data/lib/thor/core_ext/hash_with_indifferent_access.rb +9 -1
- data/lib/thor/core_ext/io_binary_read.rb +7 -5
- data/lib/thor/core_ext/ordered_hash.rb +94 -63
- data/lib/thor/error.rb +3 -3
- data/lib/thor/group.rb +12 -12
- data/lib/thor/invocation.rb +4 -5
- data/lib/thor/parser/argument.rb +4 -7
- data/lib/thor/parser/arguments.rb +16 -16
- data/lib/thor/parser/option.rb +39 -19
- data/lib/thor/parser/options.rb +7 -5
- data/lib/thor/runner.rb +25 -25
- data/lib/thor/shell.rb +1 -1
- data/lib/thor/shell/basic.rb +41 -26
- data/lib/thor/shell/color.rb +1 -1
- data/lib/thor/shell/html.rb +4 -4
- data/lib/thor/util.rb +8 -7
- data/lib/thor/version.rb +1 -1
- data/thor.gemspec +6 -9
- metadata +6 -148
- data/Thorfile +0 -29
- data/spec/actions/create_file_spec.rb +0 -168
- data/spec/actions/create_link_spec.rb +0 -96
- data/spec/actions/directory_spec.rb +0 -169
- data/spec/actions/empty_directory_spec.rb +0 -129
- data/spec/actions/file_manipulation_spec.rb +0 -392
- data/spec/actions/inject_into_file_spec.rb +0 -135
- data/spec/actions_spec.rb +0 -331
- data/spec/base_spec.rb +0 -298
- data/spec/command_spec.rb +0 -79
- data/spec/core_ext/hash_with_indifferent_access_spec.rb +0 -48
- data/spec/core_ext/ordered_hash_spec.rb +0 -115
- data/spec/exit_condition_spec.rb +0 -19
- data/spec/fixtures/application.rb +0 -2
- data/spec/fixtures/app{1}/README +0 -3
- data/spec/fixtures/bundle/execute.rb +0 -6
- data/spec/fixtures/bundle/main.thor +0 -1
- data/spec/fixtures/command.thor +0 -10
- data/spec/fixtures/doc/%file_name%.rb.tt +0 -1
- data/spec/fixtures/doc/COMMENTER +0 -11
- data/spec/fixtures/doc/README +0 -3
- data/spec/fixtures/doc/block_helper.rb +0 -3
- data/spec/fixtures/doc/config.rb +0 -1
- data/spec/fixtures/doc/config.yaml.tt +0 -1
- data/spec/fixtures/doc/excluding/%file_name%.rb.tt +0 -1
- data/spec/fixtures/enum.thor +0 -10
- data/spec/fixtures/group.thor +0 -128
- data/spec/fixtures/invoke.thor +0 -131
- data/spec/fixtures/path with spaces b/data/spec/fixtures/path with → spaces +0 -0
- data/spec/fixtures/preserve/script.sh +0 -3
- data/spec/fixtures/script.thor +0 -220
- data/spec/fixtures/subcommand.thor +0 -17
- data/spec/group_spec.rb +0 -222
- data/spec/helper.rb +0 -80
- data/spec/invocation_spec.rb +0 -120
- data/spec/line_editor/basic_spec.rb +0 -28
- data/spec/line_editor/readline_spec.rb +0 -69
- data/spec/line_editor_spec.rb +0 -43
- data/spec/parser/argument_spec.rb +0 -53
- data/spec/parser/arguments_spec.rb +0 -66
- data/spec/parser/option_spec.rb +0 -210
- data/spec/parser/options_spec.rb +0 -414
- data/spec/quality_spec.rb +0 -75
- data/spec/rake_compat_spec.rb +0 -72
- data/spec/register_spec.rb +0 -227
- data/spec/runner_spec.rb +0 -246
- data/spec/sandbox/application.rb +0 -2
- data/spec/sandbox/app{1}/README +0 -3
- data/spec/sandbox/bundle/execute.rb +0 -6
- data/spec/sandbox/bundle/main.thor +0 -1
- data/spec/sandbox/command.thor +0 -10
- data/spec/sandbox/doc/%file_name%.rb.tt +0 -1
- data/spec/sandbox/doc/COMMENTER +0 -11
- data/spec/sandbox/doc/README +0 -3
- data/spec/sandbox/doc/block_helper.rb +0 -3
- data/spec/sandbox/doc/config.rb +0 -1
- data/spec/sandbox/doc/config.yaml.tt +0 -1
- data/spec/sandbox/doc/excluding/%file_name%.rb.tt +0 -1
- data/spec/sandbox/enum.thor +0 -10
- data/spec/sandbox/group.thor +0 -128
- data/spec/sandbox/invoke.thor +0 -131
- data/spec/sandbox/path with spaces b/data/spec/sandbox/path with → spaces +0 -0
- data/spec/sandbox/preserve/script.sh +0 -3
- data/spec/sandbox/script.thor +0 -220
- data/spec/sandbox/subcommand.thor +0 -17
- data/spec/shell/basic_spec.rb +0 -337
- data/spec/shell/color_spec.rb +0 -119
- data/spec/shell/html_spec.rb +0 -31
- data/spec/shell_spec.rb +0 -47
- data/spec/subcommand_spec.rb +0 -48
- data/spec/thor_spec.rb +0 -505
- data/spec/util_spec.rb +0 -196
data/spec/shell/html_spec.rb
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
require "helper"
|
2
|
-
|
3
|
-
describe Thor::Shell::HTML do
|
4
|
-
def shell
|
5
|
-
@shell ||= Thor::Shell::HTML.new
|
6
|
-
end
|
7
|
-
|
8
|
-
describe "#say" do
|
9
|
-
it "sets the color if specified" do
|
10
|
-
out = capture(:stdout) { shell.say "Wow! Now we have colors!", :green }
|
11
|
-
expect(out.chomp).to eq('<span style="color: green;">Wow! Now we have colors!</span>')
|
12
|
-
end
|
13
|
-
|
14
|
-
it "sets bold if specified" do
|
15
|
-
out = capture(:stdout) { shell.say "Wow! Now we have colors *and* bold!", [:green, :bold] }
|
16
|
-
expect(out.chomp).to eq('<span style="color: green; font-weight: bold;">Wow! Now we have colors *and* bold!</span>')
|
17
|
-
end
|
18
|
-
|
19
|
-
it "does not use a new line even with colors" do
|
20
|
-
out = capture(:stdout) { shell.say "Wow! Now we have colors! ", :green }
|
21
|
-
expect(out.chomp).to eq('<span style="color: green;">Wow! Now we have colors! </span>')
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
describe "#say_status" do
|
26
|
-
it "uses color to say status" do
|
27
|
-
expect($stdout).to receive(:print).with("<span style=\"color: red; font-weight: bold;\"> conflict</span> README\n")
|
28
|
-
shell.say_status :conflict, "README", :red
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
data/spec/shell_spec.rb
DELETED
@@ -1,47 +0,0 @@
|
|
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
|
data/spec/subcommand_spec.rb
DELETED
@@ -1,48 +0,0 @@
|
|
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
|
-
|
29
|
-
it "accepts the help switch and calls the help command on the subcommand" do
|
30
|
-
output = capture(:stdout) { TestSubcommands::Parent.start(%w[sub print_opt --help]) }
|
31
|
-
sub_help = capture(:stdout) { TestSubcommands::Parent.start(%w[sub help print_opt]) }
|
32
|
-
expect(output).to eq(sub_help)
|
33
|
-
end
|
34
|
-
|
35
|
-
it "accepts the help short switch and calls the help command on the subcommand" do
|
36
|
-
output = capture(:stdout) { TestSubcommands::Parent.start(%w[sub print_opt -h]) }
|
37
|
-
sub_help = capture(:stdout) { TestSubcommands::Parent.start(%w[sub help print_opt]) }
|
38
|
-
expect(output).to eq(sub_help)
|
39
|
-
end
|
40
|
-
|
41
|
-
it "the help command on the subcommand and after it should result in the same output" do
|
42
|
-
output = capture(:stdout) { TestSubcommands::Parent.start(%w[sub help])}
|
43
|
-
sub_help = capture(:stdout) { TestSubcommands::Parent.start(%w[help sub])}
|
44
|
-
expect(output).to eq(sub_help)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
end
|
data/spec/thor_spec.rb
DELETED
@@ -1,505 +0,0 @@
|
|
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 = %w[foo bar --force]
|
7
|
-
_, 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
|
-
_, options = MyScript.start(%w[with_optional])
|
14
|
-
expect(options).to eq({})
|
15
|
-
end
|
16
|
-
|
17
|
-
it "sets a default that can be overridden for strings" do
|
18
|
-
_, options = MyScript.start(%w[with_optional --lazy])
|
19
|
-
expect(options).to eq("lazy" => "yes")
|
20
|
-
|
21
|
-
_, options = MyScript.start(%w[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
|
-
_, options = MyScript.start(%w[with_optional --lazy-numeric])
|
27
|
-
expect(options).to eq("lazy_numeric" => 42)
|
28
|
-
|
29
|
-
_, options = MyScript.start(%w[with_optional --lazy-numeric 20000])
|
30
|
-
expect(options).to eq("lazy_numeric" => 20_000)
|
31
|
-
end
|
32
|
-
|
33
|
-
it "sets a default that can be overridden for arrays" do
|
34
|
-
_, options = MyScript.start(%w[with_optional --lazy-array])
|
35
|
-
expect(options).to eq("lazy_array" => %w[eat at joes])
|
36
|
-
|
37
|
-
_, options = MyScript.start(%w[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
|
-
_, options = MyScript.start(%w[with_optional --lazy-hash])
|
43
|
-
expect(options).to eq("lazy_hash" => {"swedish" => "meatballs"})
|
44
|
-
|
45
|
-
_, options = MyScript.start(%w[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
|
-
_, options = MyChildScript.start(%w[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 = %w[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(%w[--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
|
-
[options, args]
|
102
|
-
end
|
103
|
-
|
104
|
-
desc "boring", "An ordinary command"
|
105
|
-
def boring(*args)
|
106
|
-
[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 [{}, %w[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 [{}, %w[--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}, %w[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"}, %w[command]]
|
124
|
-
end
|
125
|
-
|
126
|
-
it "still passes everything after -- to command" do
|
127
|
-
expect(my_script.start(%w[exec -- --verbose])).to eq [{}, %w[--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}, %w[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?(double(:name => "foo"))).to be true
|
140
|
-
expect(klass.stop_on_unknown_option?(double(:name => "bar"))).to be true
|
141
|
-
expect(klass.stop_on_unknown_option?(double(: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?(double(:name => "foo"))).to be true
|
152
|
-
expect(klass.stop_on_unknown_option?(double(:name => "bar"))).to be true
|
153
|
-
expect(klass.stop_on_unknown_option?(double(:name => "baz"))).to be false
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
it "doesn't break new" do
|
158
|
-
expect(my_script.new).to be_a(Thor)
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
describe "#map" do
|
163
|
-
it "calls the alias of a method if one is provided" do
|
164
|
-
expect(MyScript.start(%w[-T fish])).to eq(%w[fish])
|
165
|
-
end
|
166
|
-
|
167
|
-
it "calls the alias of a method if several are provided via #map" do
|
168
|
-
expect(MyScript.start(%w[-f fish])).to eq(["fish", {}])
|
169
|
-
expect(MyScript.start(%w[--foo fish])).to eq(["fish", {}])
|
170
|
-
end
|
171
|
-
|
172
|
-
it "inherits all mappings from parent" do
|
173
|
-
expect(MyChildScript.default_command).to eq("example_default_command")
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
describe "#package_name" do
|
178
|
-
it "provides a proper description for a command when the package_name is assigned" do
|
179
|
-
content = capture(:stdout) { PackageNameScript.start(%w[help]) }
|
180
|
-
expect(content).to match(/Baboon commands:/m)
|
181
|
-
end
|
182
|
-
|
183
|
-
# TODO: remove this, might be redundant, just wanted to prove full coverage
|
184
|
-
it "provides a proper description for a command when the package_name is NOT assigned" do
|
185
|
-
content = capture(:stdout) { MyScript.start(%w[help]) }
|
186
|
-
expect(content).to match(/Commands:/m)
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
|
-
describe "#desc" do
|
191
|
-
it "provides description for a command" do
|
192
|
-
content = capture(:stdout) { MyScript.start(%w[help]) }
|
193
|
-
expect(content).to match(/thor my_script:zoo\s+# zoo around/m)
|
194
|
-
end
|
195
|
-
|
196
|
-
it "provides no namespace if $thor_runner is false" do
|
197
|
-
begin
|
198
|
-
$thor_runner = false
|
199
|
-
content = capture(:stdout) { MyScript.start(%w[help]) }
|
200
|
-
expect(content).to match(/thor zoo\s+# zoo around/m)
|
201
|
-
ensure
|
202
|
-
$thor_runner = true
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
|
-
describe "when :for is supplied" do
|
207
|
-
it "overwrites a previous defined command" do
|
208
|
-
expect(capture(:stdout) { MyChildScript.start(%w[help]) }).to match(/animal KIND \s+# fish around/m)
|
209
|
-
end
|
210
|
-
end
|
211
|
-
|
212
|
-
describe "when :hide is supplied" do
|
213
|
-
it "does not show the command in help" do
|
214
|
-
expect(capture(:stdout) { MyScript.start(%w[help]) }).not_to match(/this is hidden/m)
|
215
|
-
end
|
216
|
-
|
217
|
-
it "but the command is still invokable, does not show the command in help" do
|
218
|
-
expect(MyScript.start(%w[hidden yesyes])).to eq(%w[yesyes])
|
219
|
-
end
|
220
|
-
end
|
221
|
-
end
|
222
|
-
|
223
|
-
describe "#method_options" do
|
224
|
-
it "sets default options if called before an initializer" do
|
225
|
-
options = MyChildScript.class_options
|
226
|
-
expect(options[:force].type).to eq(:boolean)
|
227
|
-
expect(options[:param].type).to eq(:numeric)
|
228
|
-
end
|
229
|
-
|
230
|
-
it "overwrites default options if called on the method scope" do
|
231
|
-
args = %w[zoo --force --param feathers]
|
232
|
-
options = MyChildScript.start(args)
|
233
|
-
expect(options).to eq("force" => true, "param" => "feathers")
|
234
|
-
end
|
235
|
-
|
236
|
-
it "allows default options to be merged with method options" do
|
237
|
-
args = %w[animal bird --force --param 1.0 --other tweets]
|
238
|
-
arg, options = MyChildScript.start(args)
|
239
|
-
expect(arg).to eq("bird")
|
240
|
-
expect(options).to eq("force" => true, "param" => 1.0, "other" => "tweets")
|
241
|
-
end
|
242
|
-
end
|
243
|
-
|
244
|
-
describe "#start" do
|
245
|
-
it "calls a no-param method when no params are passed" do
|
246
|
-
expect(MyScript.start(%w[zoo])).to eq(true)
|
247
|
-
end
|
248
|
-
|
249
|
-
it "calls a single-param method when a single param is passed" do
|
250
|
-
expect(MyScript.start(%w[animal fish])).to eq(%w[fish])
|
251
|
-
end
|
252
|
-
|
253
|
-
it "does not set options in attributes" do
|
254
|
-
expect(MyScript.start(%w[with_optional --all])).to eq([nil, {"all" => true}, []])
|
255
|
-
end
|
256
|
-
|
257
|
-
it "raises an error if the wrong number of params are provided" do
|
258
|
-
arity_asserter = lambda do |args, msg|
|
259
|
-
stderr = capture(:stderr) { Scripts::Arities.start(args) }
|
260
|
-
expect(stderr.strip).to eq(msg)
|
261
|
-
end
|
262
|
-
arity_asserter.call %w[zero_args one], %Q(ERROR: "thor zero_args" was called with arguments ["one"]
|
263
|
-
Usage: "thor scripts:arities:zero_args")
|
264
|
-
arity_asserter.call %w[one_arg], %Q(ERROR: "thor one_arg" was called with no arguments
|
265
|
-
Usage: "thor scripts:arities:one_arg ARG")
|
266
|
-
arity_asserter.call %w[one_arg one two], %Q(ERROR: "thor one_arg" was called with arguments ["one", "two"]
|
267
|
-
Usage: "thor scripts:arities:one_arg ARG")
|
268
|
-
arity_asserter.call %w[one_arg one two], %Q(ERROR: "thor one_arg" was called with arguments ["one", "two"]
|
269
|
-
Usage: "thor scripts:arities:one_arg ARG")
|
270
|
-
arity_asserter.call %w[two_args one], %Q(ERROR: "thor two_args" was called with arguments ["one"]
|
271
|
-
Usage: "thor scripts:arities:two_args ARG1 ARG2")
|
272
|
-
arity_asserter.call %w[optional_arg one two], %Q(ERROR: "thor optional_arg" was called with arguments ["one", "two"]
|
273
|
-
Usage: "thor scripts:arities:optional_arg [ARG]")
|
274
|
-
end
|
275
|
-
|
276
|
-
it "raises an error if the invoked command does not exist" do
|
277
|
-
expect(capture(:stderr) { Amazing.start(%w[animal]) }.strip).to eq('Could not find command "animal" in "amazing" namespace.')
|
278
|
-
end
|
279
|
-
|
280
|
-
it "calls method_missing if an unknown method is passed in" do
|
281
|
-
expect(MyScript.start(%w[unk hello])).to eq([:unk, %w[hello]])
|
282
|
-
end
|
283
|
-
|
284
|
-
it "does not call a private method no matter what" do
|
285
|
-
expect(capture(:stderr) { MyScript.start(%w[what]) }.strip).to eq('Could not find command "what" in "my_script" namespace.')
|
286
|
-
end
|
287
|
-
|
288
|
-
it "uses command default options" do
|
289
|
-
options = MyChildScript.start(%w[animal fish]).last
|
290
|
-
expect(options).to eq("other" => "method default")
|
291
|
-
end
|
292
|
-
|
293
|
-
it "raises when an exception happens within the command call" do
|
294
|
-
expect { MyScript.start(%w[call_myself_with_wrong_arity]) }.to raise_error(ArgumentError)
|
295
|
-
end
|
296
|
-
|
297
|
-
context "when the user enters an unambiguous substring of a command" do
|
298
|
-
it "invokes a command" do
|
299
|
-
expect(MyScript.start(%w[z])).to eq(MyScript.start(%w[zoo]))
|
300
|
-
end
|
301
|
-
|
302
|
-
it "invokes a command, even when there's an alias it resolves to the same command" do
|
303
|
-
expect(MyScript.start(%w[hi arg])).to eq(MyScript.start(%w[hidden arg]))
|
304
|
-
end
|
305
|
-
|
306
|
-
it "invokes an alias" do
|
307
|
-
expect(MyScript.start(%w[animal_pri])).to eq(MyScript.start(%w[zoo]))
|
308
|
-
end
|
309
|
-
end
|
310
|
-
|
311
|
-
context "when the user enters an ambiguous substring of a command" do
|
312
|
-
it "raises an exception and displays a message that explains the ambiguity" do
|
313
|
-
shell = Thor::Base.shell.new
|
314
|
-
expect(shell).to receive(:error).with("Ambiguous command call matches [call_myself_with_wrong_arity, call_unexistent_method]")
|
315
|
-
MyScript.start(%w[call], :shell => shell)
|
316
|
-
end
|
317
|
-
|
318
|
-
it "raises an exception when there is an alias" do
|
319
|
-
shell = Thor::Base.shell.new
|
320
|
-
expect(shell).to receive(:error).with("Ambiguous command f matches [foo, fu]")
|
321
|
-
MyScript.start(%w[f], :shell => shell)
|
322
|
-
end
|
323
|
-
end
|
324
|
-
|
325
|
-
end
|
326
|
-
|
327
|
-
describe "#help" do
|
328
|
-
def shell
|
329
|
-
@shell ||= Thor::Base.shell.new
|
330
|
-
end
|
331
|
-
|
332
|
-
describe "on general" do
|
333
|
-
before do
|
334
|
-
@content = capture(:stdout) { MyScript.help(shell) }
|
335
|
-
end
|
336
|
-
|
337
|
-
it "provides useful help info for the help method itself" do
|
338
|
-
expect(@content).to match(/help \[COMMAND\]\s+# Describe available commands/)
|
339
|
-
end
|
340
|
-
|
341
|
-
it "provides useful help info for a method with params" do
|
342
|
-
expect(@content).to match(/animal TYPE\s+# horse around/)
|
343
|
-
end
|
344
|
-
|
345
|
-
it "uses the maximum terminal size to show commands" do
|
346
|
-
expect(@shell).to receive(:terminal_width).and_return(80)
|
347
|
-
content = capture(:stdout) { MyScript.help(shell) }
|
348
|
-
expect(content).to match(/aaa\.\.\.$/)
|
349
|
-
end
|
350
|
-
|
351
|
-
it "provides description for commands from classes in the same namespace" do
|
352
|
-
expect(@content).to match(/baz\s+# do some bazing/)
|
353
|
-
end
|
354
|
-
|
355
|
-
it "shows superclass commands" do
|
356
|
-
content = capture(:stdout) { MyChildScript.help(shell) }
|
357
|
-
expect(content).to match(/foo BAR \s+# do some fooing/)
|
358
|
-
end
|
359
|
-
|
360
|
-
it "shows class options information" do
|
361
|
-
content = capture(:stdout) { MyChildScript.help(shell) }
|
362
|
-
expect(content).to match(/Options\:/)
|
363
|
-
expect(content).to match(/\[\-\-param=N\]/)
|
364
|
-
end
|
365
|
-
|
366
|
-
it "injects class arguments into default usage" do
|
367
|
-
content = capture(:stdout) { Scripts::MyScript.help(shell) }
|
368
|
-
expect(content).to match(/zoo ACCESSOR \-\-param\=PARAM/)
|
369
|
-
end
|
370
|
-
end
|
371
|
-
|
372
|
-
describe "for a specific command" do
|
373
|
-
it "provides full help info when talking about a specific command" do
|
374
|
-
expect(capture(:stdout) { MyScript.command_help(shell, "foo") }).to eq(<<-END)
|
375
|
-
Usage:
|
376
|
-
thor my_script:foo BAR
|
377
|
-
|
378
|
-
Options:
|
379
|
-
[--force] # Force to do some fooing
|
380
|
-
|
381
|
-
do some fooing
|
382
|
-
This is more info!
|
383
|
-
Everyone likes more info!
|
384
|
-
END
|
385
|
-
end
|
386
|
-
|
387
|
-
it "raises an error if the command can't be found" do
|
388
|
-
expect do
|
389
|
-
MyScript.command_help(shell, "unknown")
|
390
|
-
end.to raise_error(Thor::UndefinedCommandError, 'Could not find command "unknown" in "my_script" namespace.')
|
391
|
-
end
|
392
|
-
|
393
|
-
it "normalizes names before claiming they don't exist" do
|
394
|
-
expect(capture(:stdout) { MyScript.command_help(shell, "name-with-dashes") }).to match(/thor my_script:name-with-dashes/)
|
395
|
-
end
|
396
|
-
|
397
|
-
it "uses the long description if it exists" do
|
398
|
-
expect(capture(:stdout) { MyScript.command_help(shell, "long_description") }).to eq(<<-HELP)
|
399
|
-
Usage:
|
400
|
-
thor my_script:long_description
|
401
|
-
|
402
|
-
Description:
|
403
|
-
This is a really really really long description. Here you go. So very long.
|
404
|
-
|
405
|
-
It even has two paragraphs.
|
406
|
-
HELP
|
407
|
-
end
|
408
|
-
|
409
|
-
it "doesn't assign the long description to the next command without one" do
|
410
|
-
expect(capture(:stdout) do
|
411
|
-
MyScript.command_help(shell, "name_with_dashes")
|
412
|
-
end).not_to match(/so very long/i)
|
413
|
-
end
|
414
|
-
end
|
415
|
-
|
416
|
-
describe "instance method" do
|
417
|
-
it "calls the class method" do
|
418
|
-
expect(capture(:stdout) { MyScript.start(%w[help]) }).to match(/Commands:/)
|
419
|
-
end
|
420
|
-
|
421
|
-
it "calls the class method" do
|
422
|
-
expect(capture(:stdout) { MyScript.start(%w[help foo]) }).to match(/Usage:/)
|
423
|
-
end
|
424
|
-
end
|
425
|
-
end
|
426
|
-
|
427
|
-
describe "when creating commands" do
|
428
|
-
it "prints a warning if a public method is created without description or usage" do
|
429
|
-
expect(capture(:stdout) do
|
430
|
-
klass = Class.new(Thor)
|
431
|
-
klass.class_eval "def hello_from_thor; end"
|
432
|
-
end).to match(/\[WARNING\] Attempted to create command "hello_from_thor" without usage or description/)
|
433
|
-
end
|
434
|
-
|
435
|
-
it "does not print if overwriting a previous command" do
|
436
|
-
expect(capture(:stdout) do
|
437
|
-
klass = Class.new(Thor)
|
438
|
-
klass.class_eval "def help; end"
|
439
|
-
end).to be_empty
|
440
|
-
end
|
441
|
-
end
|
442
|
-
|
443
|
-
describe "edge-cases" do
|
444
|
-
it "can handle boolean options followed by arguments" do
|
445
|
-
klass = Class.new(Thor) do
|
446
|
-
method_option :loud, :type => :boolean
|
447
|
-
desc "hi NAME", "say hi to name"
|
448
|
-
def hi(name)
|
449
|
-
name.upcase! if options[:loud]
|
450
|
-
"Hi #{name}"
|
451
|
-
end
|
452
|
-
end
|
453
|
-
|
454
|
-
expect(klass.start(%w[hi jose])).to eq("Hi jose")
|
455
|
-
expect(klass.start(%w[hi jose --loud])).to eq("Hi JOSE")
|
456
|
-
expect(klass.start(%w[hi --loud jose])).to eq("Hi JOSE")
|
457
|
-
end
|
458
|
-
|
459
|
-
it "passes through unknown options" do
|
460
|
-
klass = Class.new(Thor) do
|
461
|
-
desc "unknown", "passing unknown options"
|
462
|
-
def unknown(*args)
|
463
|
-
args
|
464
|
-
end
|
465
|
-
end
|
466
|
-
|
467
|
-
expect(klass.start(%w[unknown foo --bar baz bat --bam])).to eq(%w[foo --bar baz bat --bam])
|
468
|
-
expect(klass.start(%w[unknown --bar baz])).to eq(%w[--bar baz])
|
469
|
-
end
|
470
|
-
|
471
|
-
it "does not pass through unknown options with strict args" do
|
472
|
-
klass = Class.new(Thor) do
|
473
|
-
strict_args_position!
|
474
|
-
|
475
|
-
desc "unknown", "passing unknown options"
|
476
|
-
def unknown(*args)
|
477
|
-
args
|
478
|
-
end
|
479
|
-
end
|
480
|
-
|
481
|
-
expect(klass.start(%w[unknown --bar baz])).to eq([])
|
482
|
-
expect(klass.start(%w[unknown foo --bar baz])).to eq(%w[foo])
|
483
|
-
end
|
484
|
-
|
485
|
-
it "strict args works in the inheritance chain" do
|
486
|
-
parent = Class.new(Thor) do
|
487
|
-
strict_args_position!
|
488
|
-
end
|
489
|
-
|
490
|
-
klass = Class.new(parent) do
|
491
|
-
desc "unknown", "passing unknown options"
|
492
|
-
def unknown(*args)
|
493
|
-
args
|
494
|
-
end
|
495
|
-
end
|
496
|
-
|
497
|
-
expect(klass.start(%w[unknown --bar baz])).to eq([])
|
498
|
-
expect(klass.start(%w[unknown foo --bar baz])).to eq(%w[foo])
|
499
|
-
end
|
500
|
-
|
501
|
-
it "send as a command name" do
|
502
|
-
expect(MyScript.start(%w[send])).to eq(true)
|
503
|
-
end
|
504
|
-
end
|
505
|
-
end
|