thor 0.16.0 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTING.md +15 -0
  3. data/README.md +23 -6
  4. data/bin/thor +1 -1
  5. data/lib/thor/actions/create_file.rb +34 -35
  6. data/lib/thor/actions/create_link.rb +9 -5
  7. data/lib/thor/actions/directory.rb +33 -23
  8. data/lib/thor/actions/empty_directory.rb +75 -85
  9. data/lib/thor/actions/file_manipulation.rb +103 -36
  10. data/lib/thor/actions/inject_into_file.rb +46 -36
  11. data/lib/thor/actions.rb +90 -68
  12. data/lib/thor/base.rb +302 -244
  13. data/lib/thor/command.rb +142 -0
  14. data/lib/thor/core_ext/hash_with_indifferent_access.rb +52 -24
  15. data/lib/thor/error.rb +90 -10
  16. data/lib/thor/group.rb +70 -74
  17. data/lib/thor/invocation.rb +63 -55
  18. data/lib/thor/line_editor/basic.rb +37 -0
  19. data/lib/thor/line_editor/readline.rb +88 -0
  20. data/lib/thor/line_editor.rb +17 -0
  21. data/lib/thor/nested_context.rb +29 -0
  22. data/lib/thor/parser/argument.rb +24 -28
  23. data/lib/thor/parser/arguments.rb +110 -102
  24. data/lib/thor/parser/option.rb +53 -15
  25. data/lib/thor/parser/options.rb +174 -97
  26. data/lib/thor/parser.rb +4 -4
  27. data/lib/thor/rake_compat.rb +12 -11
  28. data/lib/thor/runner.rb +159 -155
  29. data/lib/thor/shell/basic.rb +216 -93
  30. data/lib/thor/shell/color.rb +53 -40
  31. data/lib/thor/shell/html.rb +61 -58
  32. data/lib/thor/shell.rb +29 -36
  33. data/lib/thor/util.rb +231 -213
  34. data/lib/thor/version.rb +1 -1
  35. data/lib/thor.rb +303 -166
  36. data/thor.gemspec +27 -24
  37. metadata +36 -226
  38. data/.gitignore +0 -44
  39. data/.rspec +0 -2
  40. data/.travis.yml +0 -7
  41. data/CHANGELOG.rdoc +0 -134
  42. data/Gemfile +0 -15
  43. data/Thorfile +0 -30
  44. data/bin/rake2thor +0 -86
  45. data/lib/thor/core_ext/dir_escape.rb +0 -0
  46. data/lib/thor/core_ext/file_binary_read.rb +0 -9
  47. data/lib/thor/core_ext/ordered_hash.rb +0 -100
  48. data/lib/thor/task.rb +0 -132
  49. data/spec/actions/create_file_spec.rb +0 -170
  50. data/spec/actions/create_link_spec.rb +0 -81
  51. data/spec/actions/directory_spec.rb +0 -149
  52. data/spec/actions/empty_directory_spec.rb +0 -130
  53. data/spec/actions/file_manipulation_spec.rb +0 -370
  54. data/spec/actions/inject_into_file_spec.rb +0 -135
  55. data/spec/actions_spec.rb +0 -331
  56. data/spec/base_spec.rb +0 -279
  57. data/spec/core_ext/hash_with_indifferent_access_spec.rb +0 -43
  58. data/spec/core_ext/ordered_hash_spec.rb +0 -115
  59. data/spec/exit_condition_spec.rb +0 -19
  60. data/spec/fixtures/application.rb +0 -2
  61. data/spec/fixtures/app{1}/README +0 -3
  62. data/spec/fixtures/bundle/execute.rb +0 -6
  63. data/spec/fixtures/bundle/main.thor +0 -1
  64. data/spec/fixtures/doc/%file_name%.rb.tt +0 -1
  65. data/spec/fixtures/doc/COMMENTER +0 -10
  66. data/spec/fixtures/doc/README +0 -3
  67. data/spec/fixtures/doc/block_helper.rb +0 -3
  68. data/spec/fixtures/doc/components/.empty_directory +0 -0
  69. data/spec/fixtures/doc/config.rb +0 -1
  70. data/spec/fixtures/doc/config.yaml.tt +0 -1
  71. data/spec/fixtures/enum.thor +0 -10
  72. data/spec/fixtures/group.thor +0 -114
  73. data/spec/fixtures/invoke.thor +0 -112
  74. data/spec/fixtures/path with spaces +0 -0
  75. data/spec/fixtures/script.thor +0 -190
  76. data/spec/fixtures/task.thor +0 -10
  77. data/spec/group_spec.rb +0 -216
  78. data/spec/invocation_spec.rb +0 -100
  79. data/spec/parser/argument_spec.rb +0 -53
  80. data/spec/parser/arguments_spec.rb +0 -66
  81. data/spec/parser/option_spec.rb +0 -202
  82. data/spec/parser/options_spec.rb +0 -330
  83. data/spec/rake_compat_spec.rb +0 -72
  84. data/spec/register_spec.rb +0 -135
  85. data/spec/runner_spec.rb +0 -241
  86. data/spec/shell/basic_spec.rb +0 -300
  87. data/spec/shell/color_spec.rb +0 -81
  88. data/spec/shell/html_spec.rb +0 -32
  89. data/spec/shell_spec.rb +0 -47
  90. data/spec/spec_helper.rb +0 -59
  91. data/spec/task_spec.rb +0 -80
  92. data/spec/thor_spec.rb +0 -418
  93. data/spec/util_spec.rb +0 -196
data/spec/thor_spec.rb DELETED
@@ -1,418 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_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
- options.should == { "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
- options.should == {}
15
- end
16
-
17
- it "sets a default that can be overridden for strings" do
18
- arg, options = MyScript.start(["with_optional", "--lazy"])
19
- options.should == { "lazy" => "yes" }
20
-
21
- arg, options = MyScript.start(["with_optional", "--lazy", "yesyes!"])
22
- options.should == { "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
- options.should == { "lazy_numeric" => 42 }
28
-
29
- arg, options = MyScript.start(["with_optional", "--lazy-numeric", 20000])
30
- options.should == { "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
- options.should == { "lazy_array" => %w[eat at joes] }
36
-
37
- arg, options = MyScript.start(["with_optional", "--lazy-array", "hello", "there"])
38
- options.should == { "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
- options.should == { "lazy_hash" => {'swedish' => 'meatballs'} }
44
-
45
- arg, options = MyScript.start(["with_optional", "--lazy-hash", "polish:sausage"])
46
- options.should == { "lazy_hash" => {'polish' => 'sausage'} }
47
- end
48
- end
49
-
50
- describe "when :for is supplied" do
51
- it "updates an already defined task" do
52
- args, options = MyChildScript.start(["animal", "horse", "--other=fish"])
53
- options[:other].should == "fish"
54
- end
55
-
56
- describe "and the target is on the parent class" do
57
- it "updates an already defined task" do
58
- args = ["example_default_task", "my_param", "--new-option=verified"]
59
- options = Scripts::MyScript.start(args)
60
- options[:new_option].should == "verified"
61
- end
62
-
63
- it "adds a task to the tasks list if the updated task is on the parent class" do
64
- Scripts::MyScript.tasks["example_default_task"].should be
65
- end
66
-
67
- it "clones the parent task" do
68
- Scripts::MyScript.tasks["example_default_task"].should_not == MyChildScript.tasks["example_default_task"]
69
- end
70
- end
71
- end
72
- end
73
-
74
- describe "#default_task" do
75
- it "sets a default task" do
76
- MyScript.default_task.should == "example_default_task"
77
- end
78
-
79
- it "invokes the default task if no command is specified" do
80
- MyScript.start([]).should == "default task"
81
- end
82
-
83
- it "invokes the default task if no command is specified even if switches are given" do
84
- MyScript.start(["--with", "option"]).should == {"with"=>"option"}
85
- end
86
-
87
- it "inherits the default task from parent" do
88
- MyChildScript.default_task.should == "example_default_task"
89
- end
90
- end
91
-
92
- describe "#map" do
93
- it "calls the alias of a method if one is provided" do
94
- MyScript.start(["-T", "fish"]).should == ["fish"]
95
- end
96
-
97
- it "calls the alias of a method if several are provided via .map" do
98
- MyScript.start(["-f", "fish"]).should == ["fish", {}]
99
- MyScript.start(["--foo", "fish"]).should == ["fish", {}]
100
- end
101
-
102
- it "inherits all mappings from parent" do
103
- MyChildScript.default_task.should == "example_default_task"
104
- end
105
- end
106
-
107
- describe "#desc" do
108
- it "provides description for a task" do
109
- content = capture(:stdout) { MyScript.start(["help"]) }
110
- content.should =~ /thor my_script:zoo\s+# zoo around/m
111
- end
112
-
113
- it "provides no namespace if $thor_runner is false" do
114
- begin
115
- $thor_runner = false
116
- content = capture(:stdout) { MyScript.start(["help"]) }
117
- content.should =~ /thor zoo\s+# zoo around/m
118
- ensure
119
- $thor_runner = true
120
- end
121
- end
122
-
123
- describe "when :for is supplied" do
124
- it "overwrites a previous defined task" do
125
- capture(:stdout) { MyChildScript.start(["help"]) }.should =~ /animal KIND \s+# fish around/m
126
- end
127
- end
128
-
129
- describe "when :hide is supplied" do
130
- it "does not show the task in help" do
131
- capture(:stdout) { MyScript.start(["help"]) }.should_not =~ /this is hidden/m
132
- end
133
-
134
- it "but the task is still invokcable not show the task in help" do
135
- MyScript.start(["hidden", "yesyes"]).should == ["yesyes"]
136
- end
137
- end
138
- end
139
-
140
- describe "#method_options" do
141
- it "sets default options if called before an initializer" do
142
- options = MyChildScript.class_options
143
- options[:force].type.should == :boolean
144
- options[:param].type.should == :numeric
145
- end
146
-
147
- it "overwrites default options if called on the method scope" do
148
- args = ["zoo", "--force", "--param", "feathers"]
149
- options = MyChildScript.start(args)
150
- options.should == { "force" => true, "param" => "feathers" }
151
- end
152
-
153
- it "allows default options to be merged with method options" do
154
- args = ["animal", "bird", "--force", "--param", "1.0", "--other", "tweets"]
155
- arg, options = MyChildScript.start(args)
156
- arg.should == 'bird'
157
- options.should == { "force"=>true, "param"=>1.0, "other"=>"tweets" }
158
- end
159
- end
160
-
161
- describe "#start" do
162
- it "calls a no-param method when no params are passed" do
163
- MyScript.start(["zoo"]).should == true
164
- end
165
-
166
- it "calls a single-param method when a single param is passed" do
167
- MyScript.start(["animal", "fish"]).should == ["fish"]
168
- end
169
-
170
- it "does not set options in attributes" do
171
- MyScript.start(["with_optional", "--all"]).should == [nil, { "all" => true }, []]
172
- end
173
-
174
- it "raises an error if a required param is not provided" do
175
- capture(:stderr) { MyScript.start(["animal"]) }.strip.should == 'thor animal requires at least 1 argument: "thor my_script:animal TYPE".'
176
- end
177
-
178
- it "raises an error if the invoked task does not exist" do
179
- capture(:stderr) { Amazing.start(["animal"]) }.strip.should == 'Could not find task "animal" in "amazing" namespace.'
180
- end
181
-
182
- it "calls method_missing if an unknown method is passed in" do
183
- MyScript.start(["unk", "hello"]).should == [:unk, ["hello"]]
184
- end
185
-
186
- it "does not call a private method no matter what" do
187
- capture(:stderr) { MyScript.start(["what"]) }.strip.should == 'Could not find task "what" in "my_script" namespace.'
188
- end
189
-
190
- it "uses task default options" do
191
- options = MyChildScript.start(["animal", "fish"]).last
192
- options.should == { "other" => "method default" }
193
- end
194
-
195
- it "raises when an exception happens within the task call" do
196
- lambda { MyScript.start(["call_myself_with_wrong_arity"]) }.should raise_error(ArgumentError)
197
- end
198
-
199
- context "when the user enters an unambiguous substring of a command" do
200
- it "should invoke a command" do
201
- MyScript.start(["z"]).should == MyScript.start(["zoo"])
202
- end
203
-
204
- it "should invoke a command, even when there's an alias the resolves to the same command" do
205
- MyScript.start(["hi"]).should == MyScript.start(["hidden"])
206
- end
207
-
208
- it "should invoke an alias" do
209
- MyScript.start(["animal_pri"]).should == MyScript.start(["zoo"])
210
- end
211
- end
212
-
213
- context "when the user enters an ambiguous substring of a command" do
214
- it "should raise an exception that explains the ambiguity" do
215
- lambda { MyScript.start(["call"]) }.should raise_error(ArgumentError, 'Ambiguous task call matches [call_myself_with_wrong_arity, call_unexistent_method]')
216
- end
217
-
218
- it "should raise an exception when there is an alias" do
219
- lambda { MyScript.start(["f"]) }.should raise_error(ArgumentError, 'Ambiguous task f matches [foo, fu]')
220
- end
221
- end
222
-
223
- end
224
-
225
- describe "#subcommand" do
226
- it "maps a given subcommand to another Thor subclass" do
227
- barn_help = capture(:stdout){ Scripts::MyDefaults.start(["barn"]) }
228
- barn_help.should include("barn help [COMMAND] # Describe subcommands or one specific subcommand")
229
- end
230
-
231
- it "passes commands to subcommand classes" do
232
- capture(:stdout){ Scripts::MyDefaults.start(["barn", "open"]) }.strip.should == "Open sesame!"
233
- end
234
-
235
- it "passes arguments to subcommand classes" do
236
- capture(:stdout){ Scripts::MyDefaults.start(["barn", "open", "shotgun"]) }.strip.should == "That's going to leave a mark."
237
- end
238
-
239
- it "ignores unknown options (the subcommand class will handle them)" do
240
- capture(:stdout){ Scripts::MyDefaults.start(["barn", "paint", "blue", "--coats", "4"])}.strip.should == "4 coats of blue paint"
241
- end
242
- end
243
-
244
- describe "#help" do
245
- def shell
246
- @shell ||= Thor::Base.shell.new
247
- end
248
-
249
- describe "on general" do
250
- before do
251
- @content = capture(:stdout){ MyScript.help(shell) }
252
- end
253
-
254
- it "provides useful help info for the help method itself" do
255
- @content.should =~ /help \[TASK\]\s+# Describe available tasks/
256
- end
257
-
258
- it "provides useful help info for a method with params" do
259
- @content.should =~ /animal TYPE\s+# horse around/
260
- end
261
-
262
- it "uses the maximum terminal size to show tasks" do
263
- @shell.should_receive(:terminal_width).and_return(80)
264
- content = capture(:stdout){ MyScript.help(shell) }
265
- content.should =~ /aaa\.\.\.$/
266
- end
267
-
268
- it "provides description for tasks from classes in the same namespace" do
269
- @content.should =~ /baz\s+# do some bazing/
270
- end
271
-
272
- it "shows superclass tasks" do
273
- content = capture(:stdout){ MyChildScript.help(shell) }
274
- content.should =~ /foo BAR \s+# do some fooing/
275
- end
276
-
277
- it "shows class options information" do
278
- content = capture(:stdout){ MyChildScript.help(shell) }
279
- content.should =~ /Options\:/
280
- content.should =~ /\[\-\-param=N\]/
281
- end
282
-
283
- it "injects class arguments into default usage" do
284
- content = capture(:stdout){ Scripts::MyScript.help(shell) }
285
- content.should =~ /zoo ACCESSOR \-\-param\=PARAM/
286
- end
287
- end
288
-
289
- describe "for a specific task" do
290
- it "provides full help info when talking about a specific task" do
291
- capture(:stdout) { MyScript.task_help(shell, "foo") }.should == <<-END
292
- Usage:
293
- thor my_script:foo BAR
294
-
295
- Options:
296
- [--force] # Force to do some fooing
297
-
298
- do some fooing
299
- This is more info!
300
- Everyone likes more info!
301
- END
302
- end
303
-
304
- it "raises an error if the task can't be found" do
305
- lambda {
306
- MyScript.task_help(shell, "unknown")
307
- }.should raise_error(Thor::UndefinedTaskError, 'Could not find task "unknown" in "my_script" namespace.')
308
- end
309
-
310
- it "normalizes names before claiming they don't exist" do
311
- capture(:stdout) { MyScript.task_help(shell, "name-with-dashes") }.should =~ /thor my_script:name-with-dashes/
312
- end
313
-
314
- it "uses the long description if it exists" do
315
- capture(:stdout) { MyScript.task_help(shell, "long_description") }.should == <<-HELP
316
- Usage:
317
- thor my_script:long_description
318
-
319
- Description:
320
- This is a really really really long description. Here you go. So very long.
321
-
322
- It even has two paragraphs.
323
- HELP
324
- end
325
-
326
- it "doesn't assign the long description to the next task without one" do
327
- capture(:stdout) do
328
- MyScript.task_help(shell, "name_with_dashes")
329
- end.should_not =~ /so very long/i
330
- end
331
- end
332
-
333
- describe "instance method" do
334
- it "calls the class method" do
335
- capture(:stdout){ MyScript.start(["help"]) }.should =~ /Tasks:/
336
- end
337
-
338
- it "calls the class method" do
339
- capture(:stdout){ MyScript.start(["help", "foo"]) }.should =~ /Usage:/
340
- end
341
- end
342
- end
343
-
344
- describe "when creating tasks" do
345
- it "prints a warning if a public method is created without description or usage" do
346
- capture(:stdout) {
347
- klass = Class.new(Thor)
348
- klass.class_eval "def hello_from_thor; end"
349
- }.should =~ /\[WARNING\] Attempted to create task "hello_from_thor" without usage or description/
350
- end
351
-
352
- it "does not print if overwriting a previous task" do
353
- capture(:stdout) {
354
- klass = Class.new(Thor)
355
- klass.class_eval "def help; end"
356
- }.should be_empty
357
- end
358
- end
359
-
360
- describe "edge-cases" do
361
- it "can handle boolean options followed by arguments" do
362
- klass = Class.new(Thor) do
363
- method_option :loud, :type => :boolean
364
- desc "hi NAME", "say hi to name"
365
- def hi(name)
366
- name.upcase! if options[:loud]
367
- "Hi #{name}"
368
- end
369
- end
370
-
371
- klass.start(["hi", "jose"]).should == "Hi jose"
372
- klass.start(["hi", "jose", "--loud"]).should == "Hi JOSE"
373
- klass.start(["hi", "--loud", "jose"]).should == "Hi JOSE"
374
- end
375
-
376
- it "passes through unknown options" do
377
- klass = Class.new(Thor) do
378
- desc "unknown", "passing unknown options"
379
- def unknown(*args)
380
- args
381
- end
382
- end
383
-
384
- klass.start(["unknown", "foo", "--bar", "baz", "bat", "--bam"]).should == ["foo", "--bar", "baz", "bat", "--bam"]
385
- klass.start(["unknown", "--bar", "baz"]).should == ["--bar", "baz"]
386
- end
387
-
388
- it "does not pass through unknown options with strict args" do
389
- klass = Class.new(Thor) do
390
- strict_args_position!
391
-
392
- desc "unknown", "passing unknown options"
393
- def unknown(*args)
394
- args
395
- end
396
- end
397
-
398
- klass.start(["unknown", "--bar", "baz"]).should == []
399
- klass.start(["unknown", "foo", "--bar", "baz"]).should == ["foo"]
400
- end
401
-
402
- it "strict args works in the inheritance chain" do
403
- parent = Class.new(Thor) do
404
- strict_args_position!
405
- end
406
-
407
- klass = Class.new(parent) do
408
- desc "unknown", "passing unknown options"
409
- def unknown(*args)
410
- args
411
- end
412
- end
413
-
414
- klass.start(["unknown", "--bar", "baz"]).should == []
415
- klass.start(["unknown", "foo", "--bar", "baz"]).should == ["foo"]
416
- end
417
- end
418
- end
data/spec/util_spec.rb DELETED
@@ -1,196 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
-
3
- module Thor::Util
4
- def self.clear_user_home!
5
- @@user_home = nil
6
- end
7
- end
8
-
9
- describe Thor::Util do
10
- describe "#find_by_namespace" do
11
- it "returns 'default' if no namespace is given" do
12
- Thor::Util.find_by_namespace('').should == Scripts::MyDefaults
13
- end
14
-
15
- it "adds 'default' if namespace starts with :" do
16
- Thor::Util.find_by_namespace(':child').should == Scripts::ChildDefault
17
- end
18
-
19
- it "returns nil if the namespace can't be found" do
20
- Thor::Util.find_by_namespace('thor:core_ext:ordered_hash').should be_nil
21
- end
22
-
23
- it "returns a class if it matches the namespace" do
24
- Thor::Util.find_by_namespace('app:broken:counter').should == BrokenCounter
25
- end
26
-
27
- it "matches classes default namespace" do
28
- Thor::Util.find_by_namespace('scripts:my_script').should == Scripts::MyScript
29
- end
30
- end
31
-
32
- describe "#namespace_from_thor_class" do
33
- it "replaces constant nesting with task namespacing" do
34
- Thor::Util.namespace_from_thor_class("Foo::Bar::Baz").should == "foo:bar:baz"
35
- end
36
-
37
- it "snake-cases component strings" do
38
- Thor::Util.namespace_from_thor_class("FooBar::BarBaz::BazBoom").should == "foo_bar:bar_baz:baz_boom"
39
- end
40
-
41
- it "accepts class and module objects" do
42
- Thor::Util.namespace_from_thor_class(Thor::CoreExt::OrderedHash).should == "thor:core_ext:ordered_hash"
43
- Thor::Util.namespace_from_thor_class(Thor::Util).should == "thor:util"
44
- end
45
-
46
- it "removes Thor::Sandbox namespace" do
47
- Thor::Util.namespace_from_thor_class("Thor::Sandbox::Package").should == "package"
48
- end
49
- end
50
-
51
- describe "#namespaces_in_content" do
52
- it "returns an array of names of constants defined in the string" do
53
- list = Thor::Util.namespaces_in_content("class Foo; class Bar < Thor; end; end; class Baz; class Bat; end; end")
54
- list.should include("foo:bar")
55
- list.should_not include("bar:bat")
56
- end
57
-
58
- it "doesn't put the newly-defined constants in the enclosing namespace" do
59
- Thor::Util.namespaces_in_content("class Blat; end")
60
- defined?(Blat).should_not be
61
- defined?(Thor::Sandbox::Blat).should be
62
- end
63
- end
64
-
65
- describe "#snake_case" do
66
- it "preserves no-cap strings" do
67
- Thor::Util.snake_case("foo").should == "foo"
68
- Thor::Util.snake_case("foo_bar").should == "foo_bar"
69
- end
70
-
71
- it "downcases all-caps strings" do
72
- Thor::Util.snake_case("FOO").should == "foo"
73
- Thor::Util.snake_case("FOO_BAR").should == "foo_bar"
74
- end
75
-
76
- it "downcases initial-cap strings" do
77
- Thor::Util.snake_case("Foo").should == "foo"
78
- end
79
-
80
- it "replaces camel-casing with underscores" do
81
- Thor::Util.snake_case("FooBarBaz").should == "foo_bar_baz"
82
- Thor::Util.snake_case("Foo_BarBaz").should == "foo_bar_baz"
83
- end
84
-
85
- it "places underscores between multiple capitals" do
86
- Thor::Util.snake_case("ABClass").should == "a_b_class"
87
- end
88
- end
89
-
90
- describe "#find_class_and_task_by_namespace" do
91
- it "returns a Thor::Group class if full namespace matches" do
92
- Thor::Util.find_class_and_task_by_namespace("my_counter").should == [MyCounter, nil]
93
- end
94
-
95
- it "returns a Thor class if full namespace matches" do
96
- Thor::Util.find_class_and_task_by_namespace("thor").should == [Thor, nil]
97
- end
98
-
99
- it "returns a Thor class and the task name" do
100
- Thor::Util.find_class_and_task_by_namespace("thor:help").should == [Thor, "help"]
101
- end
102
-
103
- it "falls back in the namespace:task look up even if a full namespace does not match" do
104
- Thor.const_set(:Help, Module.new)
105
- Thor::Util.find_class_and_task_by_namespace("thor:help").should == [Thor, "help"]
106
- Thor.send :remove_const, :Help
107
- end
108
-
109
- it "falls back on the default namespace class if nothing else matches" do
110
- Thor::Util.find_class_and_task_by_namespace("test").should == [Scripts::MyDefaults, "test"]
111
- end
112
- end
113
-
114
- describe "#thor_classes_in" do
115
- it "returns thor classes inside the given class" do
116
- Thor::Util.thor_classes_in(MyScript).should == [MyScript::AnotherScript]
117
- Thor::Util.thor_classes_in(MyScript::AnotherScript).should be_empty
118
- end
119
- end
120
-
121
- describe "#user_home" do
122
- before do
123
- ENV.stub!(:[])
124
- Thor::Util.clear_user_home!
125
- end
126
-
127
- it "returns the user path if none variable is set on the environment" do
128
- Thor::Util.user_home.should == File.expand_path("~")
129
- end
130
-
131
- it "returns the *unix system path if file cannot be expanded and separator does not exist" do
132
- File.should_receive(:expand_path).with("~").and_raise(RuntimeError)
133
- previous_value = File::ALT_SEPARATOR
134
- capture(:stderr){ File.const_set(:ALT_SEPARATOR, false) }
135
- Thor::Util.user_home.should == "/"
136
- capture(:stderr){ File.const_set(:ALT_SEPARATOR, previous_value) }
137
- end
138
-
139
- it "returns the windows system path if file cannot be expanded and a separator exists" do
140
- File.should_receive(:expand_path).with("~").and_raise(RuntimeError)
141
- previous_value = File::ALT_SEPARATOR
142
- capture(:stderr){ File.const_set(:ALT_SEPARATOR, true) }
143
- Thor::Util.user_home.should == "C:/"
144
- capture(:stderr){ File.const_set(:ALT_SEPARATOR, previous_value) }
145
- end
146
-
147
- it "returns HOME/.thor if set" do
148
- ENV.stub!(:[]).with("HOME").and_return("/home/user/")
149
- Thor::Util.user_home.should == "/home/user/"
150
- end
151
-
152
- it "returns path with HOMEDRIVE and HOMEPATH if set" do
153
- ENV.stub!(:[]).with("HOMEDRIVE").and_return("D:/")
154
- ENV.stub!(:[]).with("HOMEPATH").and_return("Documents and Settings/James")
155
- Thor::Util.user_home.should == "D:/Documents and Settings/James"
156
- end
157
-
158
- it "returns APPDATA/.thor if set" do
159
- ENV.stub!(:[]).with("APPDATA").and_return("/home/user/")
160
- Thor::Util.user_home.should == "/home/user/"
161
- end
162
- end
163
-
164
- describe "#thor_root_glob" do
165
- before do
166
- ENV.stub!(:[])
167
- Thor::Util.clear_user_home!
168
- end
169
-
170
- it "escapes globs in path" do
171
- ENV.stub!(:[]).with("HOME").and_return("/home/user{1}/")
172
- Dir.should_receive(:[]).with("/home/user\\{1\\}/.thor/*").and_return([])
173
- Thor::Util.thor_root_glob.should == []
174
- end
175
- end
176
-
177
- describe "#globs_for" do
178
- it "escapes globs in path" do
179
- Thor::Util.globs_for("/home/apps{1}").should == [
180
- "/home/apps\\{1\\}/Thorfile",
181
- "/home/apps\\{1\\}/*.thor",
182
- "/home/apps\\{1\\}/tasks/*.thor",
183
- "/home/apps\\{1\\}/lib/tasks/*.thor"
184
- ]
185
- end
186
- end
187
-
188
- describe "#escape_globs" do
189
- it "escapes ? * { } [ ] glob characters" do
190
- Thor::Util.escape_globs("apps?").should == "apps\\?"
191
- Thor::Util.escape_globs("apps*").should == "apps\\*"
192
- Thor::Util.escape_globs("apps {1}").should == "apps \\{1\\}"
193
- Thor::Util.escape_globs("apps [1]").should == "apps \\[1\\]"
194
- end
195
- end
196
- end