thor 0.16.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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