thor 0.12.0 → 0.13.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.
- data/CHANGELOG.rdoc +5 -5
- data/README.rdoc +65 -2
- data/Thorfile +15 -9
- data/bin/thor +1 -0
- data/lib/thor/actions/create_file.rb +2 -2
- data/lib/thor/actions/directory.rb +2 -4
- data/lib/thor/actions/file_manipulation.rb +10 -6
- data/lib/thor/actions/inject_into_file.rb +10 -7
- data/lib/thor/actions.rb +6 -5
- data/lib/thor/base.rb +45 -32
- data/lib/thor/core_ext/file_binary_read.rb +9 -0
- data/lib/thor/group.rb +46 -37
- data/lib/thor/runner.rb +49 -42
- data/lib/thor/shell/basic.rb +49 -29
- data/lib/thor/shell/color.rb +1 -1
- data/lib/thor/shell.rb +1 -1
- data/lib/thor/task.rb +27 -38
- data/lib/thor/util.rb +4 -22
- data/lib/thor/version.rb +1 -1
- data/lib/thor.rb +43 -45
- data/spec/actions/create_file_spec.rb +7 -7
- data/spec/actions/directory_spec.rb +5 -4
- data/spec/actions/file_manipulation_spec.rb +29 -16
- data/spec/actions/inject_into_file_spec.rb +29 -0
- data/spec/actions_spec.rb +14 -13
- data/spec/base_spec.rb +16 -1
- data/spec/fixtures/bundle/main.thor +1 -0
- data/spec/fixtures/doc/%file_name%.rb.tt +1 -0
- data/spec/fixtures/doc/README +3 -0
- data/spec/fixtures/group.thor +83 -0
- data/spec/fixtures/invoke.thor +112 -0
- data/spec/fixtures/script.thor +134 -0
- data/spec/fixtures/task.thor +10 -0
- data/spec/group_spec.rb +1 -7
- data/spec/runner_spec.rb +35 -39
- data/spec/shell/basic_spec.rb +56 -62
- data/spec/shell/color_spec.rb +6 -6
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +5 -4
- data/spec/task_spec.rb +14 -32
- data/spec/thor_spec.rb +21 -22
- data/spec/util_spec.rb +7 -31
- metadata +28 -19
|
@@ -29,23 +29,23 @@ describe Thor::Actions do
|
|
|
29
29
|
|
|
30
30
|
describe "#chmod" do
|
|
31
31
|
it "executes the command given" do
|
|
32
|
-
|
|
32
|
+
FileUtils.should_receive(:chmod_R).with(0755, file)
|
|
33
33
|
action :chmod, "foo", 0755
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
it "does not execute the command if pretending given" do
|
|
37
|
-
|
|
37
|
+
FileUtils.should_not_receive(:chmod_R)
|
|
38
38
|
runner(:pretend => true)
|
|
39
39
|
action :chmod, "foo", 0755
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
it "logs status" do
|
|
43
|
-
|
|
43
|
+
FileUtils.should_receive(:chmod_R).with(0755, file)
|
|
44
44
|
action(:chmod, "foo", 0755).must == " chmod foo\n"
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
it "does not log status if required" do
|
|
48
|
-
|
|
48
|
+
FileUtils.should_receive(:chmod_R).with(0755, file)
|
|
49
49
|
action(:chmod, "foo", 0755, :verbose => false).must be_empty
|
|
50
50
|
end
|
|
51
51
|
end
|
|
@@ -65,13 +65,19 @@ describe Thor::Actions do
|
|
|
65
65
|
runner.inside("doc") do
|
|
66
66
|
action :copy_file, "README"
|
|
67
67
|
end
|
|
68
|
-
|
|
69
68
|
exists_and_identical?("doc/README", "doc/README")
|
|
70
69
|
end
|
|
71
70
|
|
|
72
71
|
it "logs status" do
|
|
73
72
|
action(:copy_file, "task.thor").must == " create task.thor\n"
|
|
74
73
|
end
|
|
74
|
+
|
|
75
|
+
it "accepts a block to change output" do
|
|
76
|
+
action :copy_file, "task.thor" do |content|
|
|
77
|
+
"OMG" + content
|
|
78
|
+
end
|
|
79
|
+
File.read(File.join(destination_root, "task.thor")).must =~ /^OMG/
|
|
80
|
+
end
|
|
75
81
|
end
|
|
76
82
|
|
|
77
83
|
describe "#get" do
|
|
@@ -117,7 +123,7 @@ describe Thor::Actions do
|
|
|
117
123
|
end
|
|
118
124
|
|
|
119
125
|
it "converts enconded instructions" do
|
|
120
|
-
|
|
126
|
+
runner.should_receive(:file_name).and_return("rdoc")
|
|
121
127
|
action :template, "doc/%file_name%.rb.tt"
|
|
122
128
|
file = File.join(destination_root, "doc/rdoc.rb.tt")
|
|
123
129
|
File.exists?(file).must be_true
|
|
@@ -126,6 +132,13 @@ describe Thor::Actions do
|
|
|
126
132
|
it "logs status" do
|
|
127
133
|
capture(:stdout){ runner.template("doc/config.rb") }.must == " create doc/config.rb\n"
|
|
128
134
|
end
|
|
135
|
+
|
|
136
|
+
it "accepts a block to change output" do
|
|
137
|
+
action :template, "doc/config.rb" do |content|
|
|
138
|
+
"OMG" + content
|
|
139
|
+
end
|
|
140
|
+
File.read(File.join(destination_root, "doc/config.rb")).must =~ /^OMG/
|
|
141
|
+
end
|
|
129
142
|
end
|
|
130
143
|
|
|
131
144
|
describe "when changing existent files" do
|
|
@@ -166,18 +179,18 @@ describe Thor::Actions do
|
|
|
166
179
|
describe "#gsub_file" do
|
|
167
180
|
it "replaces the content in the file" do
|
|
168
181
|
action :gsub_file, "doc/README", "__start__", "START"
|
|
169
|
-
File.
|
|
182
|
+
File.binread(file).must == "START\nREADME\n__end__\n"
|
|
170
183
|
end
|
|
171
184
|
|
|
172
185
|
it "does not replace if pretending" do
|
|
173
186
|
runner(:pretend => true)
|
|
174
187
|
action :gsub_file, "doc/README", "__start__", "START"
|
|
175
|
-
File.
|
|
188
|
+
File.binread(file).must == "__start__\nREADME\n__end__\n"
|
|
176
189
|
end
|
|
177
190
|
|
|
178
191
|
it "accepts a block" do
|
|
179
192
|
action(:gsub_file, "doc/README", "__start__"){ |match| match.gsub('__', '').upcase }
|
|
180
|
-
File.
|
|
193
|
+
File.binread(file).must == "START\nREADME\n__end__\n"
|
|
181
194
|
end
|
|
182
195
|
|
|
183
196
|
it "logs status" do
|
|
@@ -192,12 +205,12 @@ describe Thor::Actions do
|
|
|
192
205
|
describe "#append_file" do
|
|
193
206
|
it "appends content to the file" do
|
|
194
207
|
action :append_file, "doc/README", "END\n"
|
|
195
|
-
File.
|
|
208
|
+
File.binread(file).must == "__start__\nREADME\n__end__\nEND\n"
|
|
196
209
|
end
|
|
197
210
|
|
|
198
211
|
it "accepts a block" do
|
|
199
212
|
action(:append_file, "doc/README"){ "END\n" }
|
|
200
|
-
File.
|
|
213
|
+
File.binread(file).must == "__start__\nREADME\n__end__\nEND\n"
|
|
201
214
|
end
|
|
202
215
|
|
|
203
216
|
it "logs status" do
|
|
@@ -208,12 +221,12 @@ describe Thor::Actions do
|
|
|
208
221
|
describe "#prepend_file" do
|
|
209
222
|
it "prepends content to the file" do
|
|
210
223
|
action :prepend_file, "doc/README", "START\n"
|
|
211
|
-
File.
|
|
224
|
+
File.binread(file).must == "START\n__start__\nREADME\n__end__\n"
|
|
212
225
|
end
|
|
213
226
|
|
|
214
227
|
it "accepts a block" do
|
|
215
228
|
action(:prepend_file, "doc/README"){ "START\n" }
|
|
216
|
-
File.
|
|
229
|
+
File.binread(file).must == "START\n__start__\nREADME\n__end__\n"
|
|
217
230
|
end
|
|
218
231
|
|
|
219
232
|
it "logs status" do
|
|
@@ -228,12 +241,12 @@ describe Thor::Actions do
|
|
|
228
241
|
|
|
229
242
|
it "appends content to a class" do
|
|
230
243
|
action :inject_into_class, "application.rb", Application, " filter_parameters :password\n"
|
|
231
|
-
File.
|
|
244
|
+
File.binread(file).must == "class Application < Base\n filter_parameters :password\nend\n"
|
|
232
245
|
end
|
|
233
246
|
|
|
234
247
|
it "accepts a block" do
|
|
235
248
|
action(:inject_into_class, "application.rb", Application){ " filter_parameters :password\n" }
|
|
236
|
-
File.
|
|
249
|
+
File.binread(file).must == "class Application < Base\n filter_parameters :password\nend\n"
|
|
237
250
|
end
|
|
238
251
|
|
|
239
252
|
it "logs status" do
|
|
@@ -242,7 +255,7 @@ describe Thor::Actions do
|
|
|
242
255
|
|
|
243
256
|
it "does not append if class name does not match" do
|
|
244
257
|
action :inject_into_class, "application.rb", "App", " filter_parameters :password\n"
|
|
245
|
-
File.
|
|
258
|
+
File.binread(file).must == "class Application < Base\nend\n"
|
|
246
259
|
end
|
|
247
260
|
end
|
|
248
261
|
end
|
|
@@ -55,6 +55,35 @@ describe Thor::Actions::InjectIntoFile do
|
|
|
55
55
|
invoke! "doc/README", "\nmore content", :after => "__start__"
|
|
56
56
|
File.read(file).must == "__start__\nREADME\n__end__\n"
|
|
57
57
|
end
|
|
58
|
+
|
|
59
|
+
it "does not change the file if already include content" do
|
|
60
|
+
invoke! "doc/README", :before => "__end__" do
|
|
61
|
+
"more content\n"
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
File.read(file).must == "__start__\nREADME\nmore content\n__end__\n"
|
|
65
|
+
|
|
66
|
+
invoke! "doc/README", :before => "__end__" do
|
|
67
|
+
"more content\n"
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
File.read(file).must == "__start__\nREADME\nmore content\n__end__\n"
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it "does change the file if already include content and :force == true" do
|
|
74
|
+
invoke! "doc/README", :before => "__end__" do
|
|
75
|
+
"more content\n"
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
File.read(file).must == "__start__\nREADME\nmore content\n__end__\n"
|
|
79
|
+
|
|
80
|
+
invoke! "doc/README", :before => "__end__", :force => true do
|
|
81
|
+
"more content\n"
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
File.read(file).must == "__start__\nREADME\nmore content\nmore content\n__end__\n"
|
|
85
|
+
end
|
|
86
|
+
|
|
58
87
|
end
|
|
59
88
|
|
|
60
89
|
describe "#revoke!" do
|
data/spec/actions_spec.rb
CHANGED
|
@@ -55,9 +55,10 @@ describe Thor::Actions do
|
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
it "does not use the current directory if one is given" do
|
|
58
|
+
root = File.expand_path("/")
|
|
58
59
|
base = MyCounter.new([1])
|
|
59
|
-
base.destination_root =
|
|
60
|
-
base.destination_root.must ==
|
|
60
|
+
base.destination_root = root
|
|
61
|
+
base.destination_root.must == root
|
|
61
62
|
end
|
|
62
63
|
|
|
63
64
|
it "uses the current directory if none is given" do
|
|
@@ -194,7 +195,7 @@ describe Thor::Actions do
|
|
|
194
195
|
@template.instance_eval "def read; self; end" # Make the string respond to read
|
|
195
196
|
|
|
196
197
|
@file = "http://gist.github.com/103208.txt"
|
|
197
|
-
|
|
198
|
+
runner.should_receive(:open).and_return(@template)
|
|
198
199
|
end
|
|
199
200
|
|
|
200
201
|
it "opens a file and executes its content in the instance binding" do
|
|
@@ -219,7 +220,7 @@ describe Thor::Actions do
|
|
|
219
220
|
|
|
220
221
|
describe "#run" do
|
|
221
222
|
before(:each) do
|
|
222
|
-
|
|
223
|
+
runner.should_receive(:system).with("ls")
|
|
223
224
|
end
|
|
224
225
|
|
|
225
226
|
it "executes the command given" do
|
|
@@ -235,15 +236,15 @@ describe Thor::Actions do
|
|
|
235
236
|
end
|
|
236
237
|
|
|
237
238
|
it "accepts a color as status" do
|
|
238
|
-
|
|
239
|
+
runner.shell.should_receive(:say_status).with(:run, 'ls from "."', :yellow)
|
|
239
240
|
action :run, "ls", :verbose => :yellow
|
|
240
241
|
end
|
|
241
242
|
end
|
|
242
243
|
|
|
243
244
|
describe "#run_ruby_script" do
|
|
244
245
|
before(:each) do
|
|
245
|
-
|
|
246
|
-
|
|
246
|
+
Thor::Util.stub!(:ruby_command).and_return("/opt/jruby")
|
|
247
|
+
runner.should_receive(:system).with("/opt/jruby script.rb")
|
|
247
248
|
end
|
|
248
249
|
|
|
249
250
|
it "executes the ruby script" do
|
|
@@ -261,30 +262,30 @@ describe Thor::Actions do
|
|
|
261
262
|
|
|
262
263
|
describe "#thor" do
|
|
263
264
|
it "executes the thor command" do
|
|
264
|
-
|
|
265
|
+
runner.should_receive(:system).with("thor list")
|
|
265
266
|
action :thor, :list, :verbose => true
|
|
266
267
|
end
|
|
267
268
|
|
|
268
269
|
it "converts extra arguments to command arguments" do
|
|
269
|
-
|
|
270
|
+
runner.should_receive(:system).with("thor list foo bar")
|
|
270
271
|
action :thor, :list, "foo", "bar"
|
|
271
272
|
end
|
|
272
273
|
|
|
273
274
|
it "converts options hash to switches" do
|
|
274
|
-
|
|
275
|
+
runner.should_receive(:system).with("thor list foo bar --foo")
|
|
275
276
|
action :thor, :list, "foo", "bar", :foo => true
|
|
276
277
|
|
|
277
|
-
|
|
278
|
+
runner.should_receive(:system).with("thor list --foo 1 2 3")
|
|
278
279
|
action :thor, :list, :foo => [1,2,3]
|
|
279
280
|
end
|
|
280
281
|
|
|
281
282
|
it "logs status" do
|
|
282
|
-
|
|
283
|
+
runner.should_receive(:system).with("thor list")
|
|
283
284
|
action(:thor, :list).must == " run thor list from \".\"\n"
|
|
284
285
|
end
|
|
285
286
|
|
|
286
287
|
it "does not log status if required" do
|
|
287
|
-
|
|
288
|
+
runner.should_receive(:system).with("thor list --foo 1 2 3")
|
|
288
289
|
action(:thor, :list, :foo => [1,2,3], :verbose => false).must be_empty
|
|
289
290
|
end
|
|
290
291
|
end
|
data/spec/base_spec.rb
CHANGED
|
@@ -134,7 +134,7 @@ describe Thor::Base do
|
|
|
134
134
|
it "allows extra options to be given" do
|
|
135
135
|
hash = { "Foo" => B.class_options.values }
|
|
136
136
|
|
|
137
|
-
content = capture(:stdout) { MyCounter.send(:class_options_help, Thor::Base.shell.new,
|
|
137
|
+
content = capture(:stdout) { MyCounter.send(:class_options_help, Thor::Base.shell.new, hash) }
|
|
138
138
|
content.must =~ /Foo options\:/
|
|
139
139
|
content.must =~ /--last-name=LAST_NAME/
|
|
140
140
|
end
|
|
@@ -233,4 +233,19 @@ describe Thor::Base do
|
|
|
233
233
|
}.must raise_error(Thor::UndefinedTaskError, /the 'what' task of MyScript is private/)
|
|
234
234
|
end
|
|
235
235
|
end
|
|
236
|
+
|
|
237
|
+
describe "attr_*" do
|
|
238
|
+
it "should not add attr_reader as a task" do
|
|
239
|
+
capture(:stderr){ MyScript.start(["another_attribute"]) }.must =~ /could not find/
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
it "should not add attr_writer as a task" do
|
|
243
|
+
capture(:stderr){ MyScript.start(["another_attribute=", "foo"]) }.must =~ /could not find/
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
it "should not add attr_accessor as a task" do
|
|
247
|
+
capture(:stderr){ MyScript.start(["some_attribute"]) }.must =~ /could not find/
|
|
248
|
+
capture(:stderr){ MyScript.start(["some_attribute=", "foo"]) }.must =~ /could not find/
|
|
249
|
+
end
|
|
250
|
+
end
|
|
236
251
|
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'execute')
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
FOO = <%= "FOO" %>
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
class MyCounter < Thor::Group
|
|
2
|
+
include Thor::Actions
|
|
3
|
+
add_runtime_options!
|
|
4
|
+
|
|
5
|
+
def self.get_from_super
|
|
6
|
+
from_superclass(:get_from_super, 13)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def self.source_root
|
|
10
|
+
File.expand_path(File.dirname(__FILE__))
|
|
11
|
+
end
|
|
12
|
+
source_paths << File.expand_path("broken", File.dirname(__FILE__))
|
|
13
|
+
|
|
14
|
+
argument :first, :type => :numeric
|
|
15
|
+
argument :second, :type => :numeric, :default => 2
|
|
16
|
+
|
|
17
|
+
class_option :third, :type => :numeric, :desc => "The third argument", :default => 3,
|
|
18
|
+
:banner => "THREE", :aliases => "-t"
|
|
19
|
+
class_option :fourth, :type => :numeric, :desc => "The fourth argument"
|
|
20
|
+
|
|
21
|
+
desc <<-FOO
|
|
22
|
+
Description:
|
|
23
|
+
This generator run three tasks: one, two and three.
|
|
24
|
+
FOO
|
|
25
|
+
|
|
26
|
+
def one
|
|
27
|
+
first
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def two
|
|
31
|
+
second
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def three
|
|
35
|
+
options[:third]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def self.inherited(base)
|
|
39
|
+
super
|
|
40
|
+
base.source_paths.unshift(File.expand_path(File.join(File.dirname(__FILE__), "doc")))
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
class ClearCounter < MyCounter
|
|
45
|
+
remove_argument :first, :second, :undefine => true
|
|
46
|
+
remove_class_option :third
|
|
47
|
+
|
|
48
|
+
def self.source_root
|
|
49
|
+
File.expand_path(File.join(File.dirname(__FILE__), "bundle"))
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
class BrokenCounter < MyCounter
|
|
54
|
+
namespace "app:broken:counter"
|
|
55
|
+
class_option :fail, :type => :boolean, :default => false
|
|
56
|
+
|
|
57
|
+
class << self
|
|
58
|
+
undef_method :source_root
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def one
|
|
62
|
+
options[:first]
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def four
|
|
66
|
+
respond_to?(:fail)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def five
|
|
70
|
+
options[:fail] ? this_method_does_not_exist : 5
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
class WhinyGenerator < Thor::Group
|
|
75
|
+
include Thor::Actions
|
|
76
|
+
|
|
77
|
+
def self.source_root
|
|
78
|
+
File.expand_path(File.dirname(__FILE__))
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def wrong_arity(required)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
class A < Thor
|
|
2
|
+
include Thor::Actions
|
|
3
|
+
|
|
4
|
+
desc "one", "invoke one"
|
|
5
|
+
def one
|
|
6
|
+
p 1
|
|
7
|
+
invoke :two
|
|
8
|
+
invoke :three
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
desc "two", "invoke two"
|
|
12
|
+
def two
|
|
13
|
+
p 2
|
|
14
|
+
invoke :three
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
desc "three", "invoke three"
|
|
18
|
+
def three
|
|
19
|
+
p 3
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
desc "four", "invoke four"
|
|
23
|
+
def four
|
|
24
|
+
p 4
|
|
25
|
+
invoke "defined:five"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
desc "five N", "check if number is equal 5"
|
|
29
|
+
def five(number)
|
|
30
|
+
number == 5
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
desc "invoker", "invoke a b task"
|
|
34
|
+
def invoker(*args)
|
|
35
|
+
invoke :b, :one, ["Jose"]
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
class B < Thor
|
|
40
|
+
class_option :last_name, :type => :string
|
|
41
|
+
|
|
42
|
+
desc "one FIRST_NAME", "invoke one"
|
|
43
|
+
def one(first_name)
|
|
44
|
+
"#{options.last_name}, #{first_name}"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
desc "two", "invoke two"
|
|
48
|
+
def two
|
|
49
|
+
options
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
desc "three", "invoke three"
|
|
53
|
+
def three
|
|
54
|
+
self
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
class C < Thor::Group
|
|
59
|
+
include Thor::Actions
|
|
60
|
+
|
|
61
|
+
def one
|
|
62
|
+
p 1
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def two
|
|
66
|
+
p 2
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def three
|
|
70
|
+
p 3
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
class Defined < Thor::Group
|
|
75
|
+
class_option :unused, :type => :boolean, :desc => "This option has no use"
|
|
76
|
+
|
|
77
|
+
def one
|
|
78
|
+
p 1
|
|
79
|
+
invoke "a:two"
|
|
80
|
+
invoke "a:three"
|
|
81
|
+
invoke "a:four"
|
|
82
|
+
invoke "defined:five"
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def five
|
|
86
|
+
p 5
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def print_status
|
|
90
|
+
say_status :finished, :counting
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
class E < Thor::Group
|
|
95
|
+
invoke Defined
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
class F < Thor::Group
|
|
99
|
+
invoke "b:one" do |instance, klass, task|
|
|
100
|
+
instance.invoke klass, task, [ "Jose" ], :last_name => "Valim"
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
class G < Thor::Group
|
|
105
|
+
class_option :invoked, :type => :string, :default => "defined"
|
|
106
|
+
invoke_from_option :invoked
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
class H < Thor::Group
|
|
110
|
+
class_option :defined, :type => :boolean, :default => true
|
|
111
|
+
invoke_from_option :defined
|
|
112
|
+
end
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
class MyScript < Thor
|
|
2
|
+
attr_accessor :some_attribute
|
|
3
|
+
attr_writer :another_attribute
|
|
4
|
+
attr_reader :another_attribute
|
|
5
|
+
|
|
6
|
+
group :script
|
|
7
|
+
default_task :example_default_task
|
|
8
|
+
|
|
9
|
+
map "-T" => :animal, ["-f", "--foo"] => :foo
|
|
10
|
+
|
|
11
|
+
desc "zoo", "zoo around"
|
|
12
|
+
def zoo
|
|
13
|
+
true
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
desc "animal TYPE", "horse around"
|
|
17
|
+
|
|
18
|
+
no_tasks do
|
|
19
|
+
def this_is_not_a_task
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def animal(type)
|
|
24
|
+
[type]
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
desc "foo BAR", <<END
|
|
28
|
+
do some fooing
|
|
29
|
+
This is more info!
|
|
30
|
+
Everyone likes more info!
|
|
31
|
+
END
|
|
32
|
+
method_option :force, :type => :boolean, :desc => "Force to do some fooing"
|
|
33
|
+
def foo(bar)
|
|
34
|
+
[bar, options]
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
desc "example_default_task", "example!"
|
|
38
|
+
def example_default_task
|
|
39
|
+
options.empty? ? "default task" : options
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
desc "call_myself_with_wrong_arity", "get the right error"
|
|
43
|
+
def call_myself_with_wrong_arity
|
|
44
|
+
call_myself_with_wrong_arity(4)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
desc "call_unexistent_method", "Call unexistent method inside a task"
|
|
48
|
+
def call_unexistent_method
|
|
49
|
+
boom!
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
desc "long_description", "a" * 80
|
|
53
|
+
def long_description
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
method_options :all => :boolean
|
|
57
|
+
desc "with_optional NAME", "invoke with optional name"
|
|
58
|
+
def with_optional(name=nil)
|
|
59
|
+
[ name, options ]
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
class AnotherScript < Thor
|
|
63
|
+
desc "baz", "do some bazing"
|
|
64
|
+
def baz
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
private
|
|
69
|
+
|
|
70
|
+
def method_missing(meth, *args)
|
|
71
|
+
if meth == :boom!
|
|
72
|
+
super
|
|
73
|
+
else
|
|
74
|
+
[meth, args]
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
desc "what", "what"
|
|
79
|
+
def what
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
class MyChildScript < MyScript
|
|
84
|
+
remove_task :bar
|
|
85
|
+
|
|
86
|
+
method_options :force => :boolean, :param => :numeric
|
|
87
|
+
def initialize(*args)
|
|
88
|
+
super
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
desc "zoo", "zoo around"
|
|
92
|
+
method_options :param => :required
|
|
93
|
+
def zoo
|
|
94
|
+
options
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
desc "animal TYPE", "horse around"
|
|
98
|
+
def animal(type)
|
|
99
|
+
[type, options]
|
|
100
|
+
end
|
|
101
|
+
method_option :other, :type => :string, :default => "method default", :for => :animal
|
|
102
|
+
desc "animal KIND", "fish around", :for => :animal
|
|
103
|
+
|
|
104
|
+
desc "boom", "explodes everything"
|
|
105
|
+
def boom
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
remove_task :boom, :undefine => true
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
module Scripts
|
|
112
|
+
class MyScript < MyChildScript
|
|
113
|
+
argument :accessor, :type => :string
|
|
114
|
+
class_options :force => :boolean
|
|
115
|
+
method_option :new_option, :type => :string, :for => :example_default_task
|
|
116
|
+
|
|
117
|
+
def zoo
|
|
118
|
+
self.accessor
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
class MyDefaults < Thor
|
|
123
|
+
namespace :default
|
|
124
|
+
desc "test", "prints 'test'"
|
|
125
|
+
def test
|
|
126
|
+
puts "test"
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
class ChildDefault < Thor
|
|
131
|
+
namespace "default:child"
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
data/spec/group_spec.rb
CHANGED
|
@@ -29,7 +29,7 @@ describe Thor::Group do
|
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
it "invokes help message if any of the shortcuts is given" do
|
|
32
|
-
|
|
32
|
+
MyCounter.should_receive(:help)
|
|
33
33
|
MyCounter.start(["-h"])
|
|
34
34
|
end
|
|
35
35
|
end
|
|
@@ -66,12 +66,6 @@ describe Thor::Group do
|
|
|
66
66
|
@content.must =~ /Options/
|
|
67
67
|
@content.must =~ /\[\-\-third=THREE\]/
|
|
68
68
|
end
|
|
69
|
-
|
|
70
|
-
it "shows only usage if a short help is required" do
|
|
71
|
-
content = capture(:stdout){ MyCounter.help(Thor::Base.shell.new, :short => true) }
|
|
72
|
-
content.must =~ /my_counter N \[N\]/
|
|
73
|
-
content.must_not =~ /Options/
|
|
74
|
-
end
|
|
75
69
|
end
|
|
76
70
|
|
|
77
71
|
describe "#invoke" do
|