thor_dleavitt 0.18.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/CHANGELOG.md +139 -0
  4. data/LICENSE.md +20 -0
  5. data/README.md +35 -0
  6. data/Thorfile +30 -0
  7. data/bin/thor_dleavitt +6 -0
  8. data/lib/thor/actions.rb +318 -0
  9. data/lib/thor/actions/create_file.rb +105 -0
  10. data/lib/thor/actions/create_link.rb +60 -0
  11. data/lib/thor/actions/directory.rb +119 -0
  12. data/lib/thor/actions/empty_directory.rb +137 -0
  13. data/lib/thor/actions/file_manipulation.rb +317 -0
  14. data/lib/thor/actions/inject_into_file.rb +109 -0
  15. data/lib/thor/base.rb +654 -0
  16. data/lib/thor/command.rb +136 -0
  17. data/lib/thor/core_ext/hash_with_indifferent_access.rb +80 -0
  18. data/lib/thor/core_ext/io_binary_read.rb +12 -0
  19. data/lib/thor/core_ext/ordered_hash.rb +100 -0
  20. data/lib/thor/error.rb +32 -0
  21. data/lib/thor/group.rb +282 -0
  22. data/lib/thor/invocation.rb +172 -0
  23. data/lib/thor/parser.rb +4 -0
  24. data/lib/thor/parser/argument.rb +74 -0
  25. data/lib/thor/parser/arguments.rb +171 -0
  26. data/lib/thor/parser/option.rb +121 -0
  27. data/lib/thor/parser/options.rb +218 -0
  28. data/lib/thor/rake_compat.rb +72 -0
  29. data/lib/thor/runner.rb +322 -0
  30. data/lib/thor/shell.rb +88 -0
  31. data/lib/thor/shell/basic.rb +422 -0
  32. data/lib/thor/shell/color.rb +148 -0
  33. data/lib/thor/shell/html.rb +127 -0
  34. data/lib/thor/util.rb +270 -0
  35. data/lib/thor/version.rb +3 -0
  36. data/lib/thor_dleavitt.rb +473 -0
  37. data/spec/actions/create_file_spec.rb +170 -0
  38. data/spec/actions/create_link_spec.rb +95 -0
  39. data/spec/actions/directory_spec.rb +169 -0
  40. data/spec/actions/empty_directory_spec.rb +129 -0
  41. data/spec/actions/file_manipulation_spec.rb +382 -0
  42. data/spec/actions/inject_into_file_spec.rb +135 -0
  43. data/spec/actions_spec.rb +331 -0
  44. data/spec/base_spec.rb +291 -0
  45. data/spec/command_spec.rb +80 -0
  46. data/spec/core_ext/hash_with_indifferent_access_spec.rb +48 -0
  47. data/spec/core_ext/ordered_hash_spec.rb +115 -0
  48. data/spec/exit_condition_spec.rb +19 -0
  49. data/spec/fixtures/application.rb +2 -0
  50. data/spec/fixtures/app{1}/README +3 -0
  51. data/spec/fixtures/bundle/execute.rb +6 -0
  52. data/spec/fixtures/bundle/main.thor +1 -0
  53. data/spec/fixtures/command.thor +10 -0
  54. data/spec/fixtures/doc/%file_name%.rb.tt +1 -0
  55. data/spec/fixtures/doc/COMMENTER +11 -0
  56. data/spec/fixtures/doc/README +3 -0
  57. data/spec/fixtures/doc/block_helper.rb +3 -0
  58. data/spec/fixtures/doc/config.rb +1 -0
  59. data/spec/fixtures/doc/config.yaml.tt +1 -0
  60. data/spec/fixtures/doc/excluding/%file_name%.rb.tt +1 -0
  61. data/spec/fixtures/enum.thor +10 -0
  62. data/spec/fixtures/group.thor +128 -0
  63. data/spec/fixtures/invoke.thor +118 -0
  64. data/spec/fixtures/path with spaces b/data/spec/fixtures/path with → spaces +0 -0
  65. data/spec/fixtures/preserve/script.sh +3 -0
  66. data/spec/fixtures/script.thor +220 -0
  67. data/spec/fixtures/subcommand.thor +17 -0
  68. data/spec/group_spec.rb +222 -0
  69. data/spec/helper.rb +67 -0
  70. data/spec/invocation_spec.rb +108 -0
  71. data/spec/parser/argument_spec.rb +53 -0
  72. data/spec/parser/arguments_spec.rb +66 -0
  73. data/spec/parser/option_spec.rb +202 -0
  74. data/spec/parser/options_spec.rb +400 -0
  75. data/spec/rake_compat_spec.rb +72 -0
  76. data/spec/register_spec.rb +197 -0
  77. data/spec/runner_spec.rb +241 -0
  78. data/spec/shell/basic_spec.rb +330 -0
  79. data/spec/shell/color_spec.rb +95 -0
  80. data/spec/shell/html_spec.rb +31 -0
  81. data/spec/shell_spec.rb +47 -0
  82. data/spec/subcommand_spec.rb +30 -0
  83. data/spec/thor_spec.rb +499 -0
  84. data/spec/util_spec.rb +196 -0
  85. data/thor.gemspec +24 -0
  86. metadata +191 -0
@@ -0,0 +1,400 @@
1
+ require 'helper'
2
+ require 'thor/parser'
3
+
4
+ describe Thor::Options do
5
+ def create(opts, defaults={}, stop_on_unknown=false)
6
+ opts.each do |key, value|
7
+ opts[key] = Thor::Option.parse(key, value) unless value.is_a?(Thor::Option)
8
+ end
9
+
10
+ @opt = Thor::Options.new(opts, defaults, stop_on_unknown)
11
+ end
12
+
13
+ def parse(*args)
14
+ @opt.parse(args.flatten)
15
+ end
16
+
17
+ def check_unknown!
18
+ @opt.check_unknown!
19
+ end
20
+
21
+ def remaining
22
+ @opt.remaining
23
+ end
24
+
25
+ describe "#to_switches" do
26
+ it "turns true values into a flag" do
27
+ expect(Thor::Options.to_switches(:color => true)).to eq("--color")
28
+ end
29
+
30
+ it "ignores nil" do
31
+ expect(Thor::Options.to_switches(:color => nil)).to eq("")
32
+ end
33
+
34
+ it "ignores false" do
35
+ expect(Thor::Options.to_switches(:color => false)).to eq("")
36
+ end
37
+
38
+ it "writes --name value for anything else" do
39
+ expect(Thor::Options.to_switches(:format => "specdoc")).to eq('--format "specdoc"')
40
+ end
41
+
42
+ it "joins several values" do
43
+ switches = Thor::Options.to_switches(:color => true, :foo => "bar").split(' ').sort
44
+ expect(switches).to eq(['"bar"', "--color", "--foo"])
45
+ end
46
+
47
+ it "accepts arrays" do
48
+ expect(Thor::Options.to_switches(:count => [1,2,3])).to eq("--count 1 2 3")
49
+ end
50
+
51
+ it "accepts hashes" do
52
+ expect(Thor::Options.to_switches(:count => {:a => :b})).to eq("--count a:b")
53
+ end
54
+
55
+ it "accepts underscored options" do
56
+ expect(Thor::Options.to_switches(:under_score_option => "foo bar")).to eq('--under_score_option "foo bar"')
57
+ end
58
+
59
+ end
60
+
61
+ describe "#parse" do
62
+ it "allows multiple aliases for a given switch" do
63
+ create ["--foo", "--bar", "--baz"] => :string
64
+ expect(parse("--foo", "12")["foo"]).to eq("12")
65
+ expect(parse("--bar", "12")["foo"]).to eq("12")
66
+ expect(parse("--baz", "12")["foo"]).to eq("12")
67
+ end
68
+
69
+ it "allows custom short names" do
70
+ create "-f" => :string
71
+ expect(parse("-f", "12")).to eq({"f" => "12"})
72
+ end
73
+
74
+ it "allows custom short-name aliases" do
75
+ create ["--bar", "-f"] => :string
76
+ expect(parse("-f", "12")).to eq({"bar" => "12"})
77
+ end
78
+
79
+ it "accepts conjoined short switches" do
80
+ create ["--foo", "-f"] => true, ["--bar", "-b"] => true, ["--app", "-a"] => true
81
+ opts = parse("-fba")
82
+ expect(opts["foo"]).to be_true
83
+ expect(opts["bar"]).to be_true
84
+ expect(opts["app"]).to be_true
85
+ end
86
+
87
+ it "accepts conjoined short switches with input" do
88
+ create ["--foo", "-f"] => true, ["--bar", "-b"] => true, ["--app", "-a"] => :required
89
+ opts = parse "-fba", "12"
90
+ expect(opts["foo"]).to be_true
91
+ expect(opts["bar"]).to be_true
92
+ expect(opts["app"]).to eq("12")
93
+ end
94
+
95
+ it "returns the default value if none is provided" do
96
+ create :foo => "baz", :bar => :required
97
+ expect(parse("--bar", "boom")["foo"]).to eq("baz")
98
+ end
99
+
100
+ it "returns the default value from defaults hash to required arguments" do
101
+ create Hash[:bar => :required], Hash[:bar => "baz"]
102
+ expect(parse["bar"]).to eq("baz")
103
+ end
104
+
105
+ it "gives higher priority to defaults given in the hash" do
106
+ create Hash[:bar => true], Hash[:bar => false]
107
+ expect(parse["bar"]).to eq(false)
108
+ end
109
+
110
+ it "raises an error for unknown switches" do
111
+ create :foo => "baz", :bar => :required
112
+ parse("--bar", "baz", "--baz", "unknown")
113
+ expect{ check_unknown! }.to raise_error(Thor::UnknownArgumentError, "Unknown switches '--baz'")
114
+ end
115
+
116
+ it "skips leading non-switches" do
117
+ create(:foo => "baz")
118
+
119
+ expect(parse("asdf", "--foo", "bar")).to eq({"foo" => "bar"})
120
+ end
121
+
122
+ it "correctly recognizes things that look kind of like options, but aren't, as not options" do
123
+ create(:foo => "baz")
124
+ expect(parse("--asdf---asdf", "baz", "--foo", "--asdf---dsf--asdf")).to eq({"foo" => "--asdf---dsf--asdf"})
125
+ check_unknown!
126
+ end
127
+
128
+ it "accepts underscores in commandline args hash for boolean" do
129
+ create :foo_bar => :boolean
130
+ expect(parse("--foo_bar")["foo_bar"]).to eq(true)
131
+ expect(parse("--no_foo_bar")["foo_bar"]).to eq(false)
132
+ end
133
+
134
+ it "accepts underscores in commandline args hash for strings" do
135
+ create :foo_bar => :string, :baz_foo => :string
136
+ expect(parse("--foo_bar", "baz")["foo_bar"]).to eq("baz")
137
+ expect(parse("--baz_foo", "foo bar")["baz_foo"]).to eq("foo bar")
138
+ end
139
+
140
+ it "interprets everything after -- as args instead of options" do
141
+ create(:foo => :string, :bar => :required)
142
+ expect(parse(%w[--bar abc moo -- --foo def -a])).to eq({"bar" => "abc"})
143
+ expect(remaining).to eq(%w[moo --foo def -a])
144
+ end
145
+
146
+ it "ignores -- when looking for single option values" do
147
+ create(:foo => :string, :bar => :required)
148
+ expect(parse(%w[--bar -- --foo def -a])).to eq({"bar" => "--foo"})
149
+ expect(remaining).to eq(%w[def -a])
150
+ end
151
+
152
+ it "ignores -- when looking for array option values" do
153
+ create(:foo => :array)
154
+ expect(parse(%w[--foo a b -- c d -e])).to eq({"foo" => %w[a b c d -e]})
155
+ expect(remaining).to eq([])
156
+ end
157
+
158
+ it "ignores -- when looking for hash option values" do
159
+ create(:foo => :hash)
160
+ expect(parse(%w[--foo a:b -- c:d -e])).to eq({"foo" => {'a' => 'b', 'c' => 'd'}})
161
+ expect(remaining).to eq(%w[-e])
162
+ end
163
+
164
+ it "ignores trailing --" do
165
+ create(:foo => :string)
166
+ expect(parse(%w[--foo --])).to eq({"foo" => nil})
167
+ expect(remaining).to eq([])
168
+ end
169
+
170
+ describe "with no input" do
171
+ it "and no switches returns an empty hash" do
172
+ create({})
173
+ expect(parse).to eq({})
174
+ end
175
+
176
+ it "and several switches returns an empty hash" do
177
+ create "--foo" => :boolean, "--bar" => :string
178
+ expect(parse).to eq({})
179
+ end
180
+
181
+ it "and a required switch raises an error" do
182
+ create "--foo" => :required
183
+ expect{ parse }.to raise_error(Thor::RequiredArgumentMissingError, "No value provided for required options '--foo'")
184
+ end
185
+ end
186
+
187
+ describe "with one required and one optional switch" do
188
+ before do
189
+ create "--foo" => :required, "--bar" => :boolean
190
+ end
191
+
192
+ it "raises an error if the required switch has no argument" do
193
+ expect{ parse("--foo") }.to raise_error(Thor::MalformattedArgumentError)
194
+ end
195
+
196
+ it "raises an error if the required switch isn't given" do
197
+ expect{ parse("--bar") }.to raise_error(Thor::RequiredArgumentMissingError)
198
+ end
199
+
200
+ it "raises an error if the required switch is set to nil" do
201
+ expect{ parse("--no-foo") }.to raise_error(Thor::RequiredArgumentMissingError)
202
+ end
203
+
204
+ it "does not raises an error if the required option has a default value" do
205
+ options = {:required => true, :type => :string, :default => "baz"}
206
+ create :foo => Thor::Option.new("foo", options), :bar => :boolean
207
+ expect{ parse("--bar") }.not_to raise_error
208
+ end
209
+ end
210
+
211
+ context "when stop_on_unknown is true" do
212
+ before do
213
+ create({:foo => :string, :verbose => :boolean}, {}, true)
214
+ end
215
+
216
+ it "stops parsing on first non-option" do
217
+ expect(parse(%w[foo --verbose])).to eq({})
218
+ expect(remaining).to eq(["foo", "--verbose"])
219
+ end
220
+
221
+ it "stops parsing on unknown option" do
222
+ expect(parse(%w[--bar --verbose])).to eq({})
223
+ expect(remaining).to eq(["--bar", "--verbose"])
224
+ end
225
+
226
+ it "retains -- after it has stopped parsing" do
227
+ expect(parse(%w[--bar -- whatever])).to eq({})
228
+ expect(remaining).to eq(["--bar", "--", "whatever"])
229
+ end
230
+
231
+ it "still accepts options that are given before non-options" do
232
+ expect(parse(%w[--verbose foo])).to eq({"verbose" => true})
233
+ expect(remaining).to eq(["foo"])
234
+ end
235
+
236
+ it "still accepts options that require a value" do
237
+ expect(parse(%w[--foo bar baz])).to eq({"foo" => "bar"})
238
+ expect(remaining).to eq(["baz"])
239
+ end
240
+
241
+ it "still interprets everything after -- as args instead of options" do
242
+ expect(parse(%w[-- --verbose])).to eq({})
243
+ expect(remaining).to eq(["--verbose"])
244
+ end
245
+ end
246
+
247
+ describe "with :string type" do
248
+ before do
249
+ create ["--foo", "-f"] => :required
250
+ end
251
+
252
+ it "accepts a switch <value> assignment" do
253
+ expect(parse("--foo", "12")["foo"]).to eq("12")
254
+ end
255
+
256
+ it "accepts a switch=<value> assignment" do
257
+ expect(parse("-f=12")["foo"]).to eq("12")
258
+ expect(parse("--foo=12")["foo"]).to eq("12")
259
+ expect(parse("--foo=bar=baz")["foo"]).to eq("bar=baz")
260
+ end
261
+
262
+ it "must accept underscores switch=value assignment" do
263
+ create :foo_bar => :required
264
+ expect(parse("--foo_bar=http://example.com/under_score/")["foo_bar"]).to eq("http://example.com/under_score/")
265
+ end
266
+
267
+ it "accepts a --no-switch format" do
268
+ create "--foo" => "bar"
269
+ expect(parse("--no-foo")["foo"]).to be_nil
270
+ end
271
+
272
+ it "does not consume an argument for --no-switch format" do
273
+ create "--cheese" => :string
274
+ expect(parse('burger', '--no-cheese', 'fries')["cheese"]).to be_nil
275
+ end
276
+
277
+ it "accepts a --switch format on non required types" do
278
+ create "--foo" => :string
279
+ expect(parse("--foo")["foo"]).to eq("foo")
280
+ end
281
+
282
+ it "accepts a --switch format on non required types with default values" do
283
+ create "--baz" => :string, "--foo" => "bar"
284
+ expect(parse("--baz", "bang", "--foo")["foo"]).to eq("bar")
285
+ end
286
+
287
+ it "overwrites earlier values with later values" do
288
+ expect(parse("--foo=bar", "--foo", "12")["foo"]).to eq("12")
289
+ expect(parse("--foo", "12", "--foo", "13")["foo"]).to eq("13")
290
+ end
291
+ end
292
+
293
+ describe "with :boolean type" do
294
+ before do
295
+ create "--foo" => false
296
+ end
297
+
298
+ it "accepts --opt assignment" do
299
+ expect(parse("--foo")["foo"]).to eq(true)
300
+ expect(parse("--foo", "--bar")["foo"]).to eq(true)
301
+ end
302
+
303
+ it "uses the default value if no switch is given" do
304
+ expect(parse("")["foo"]).to eq(false)
305
+ end
306
+
307
+ it "accepts --opt=value assignment" do
308
+ expect(parse("--foo=true")["foo"]).to eq(true)
309
+ expect(parse("--foo=false")["foo"]).to eq(false)
310
+ end
311
+
312
+ it "accepts --[no-]opt variant, setting false for value" do
313
+ expect(parse("--no-foo")["foo"]).to eq(false)
314
+ end
315
+
316
+ it "accepts --[skip-]opt variant, setting false for value" do
317
+ expect(parse("--skip-foo")["foo"]).to eq(false)
318
+ end
319
+
320
+ it "will prefer 'no-opt' variant over inverting 'opt' if explicitly set" do
321
+ create "--no-foo" => true
322
+ expect(parse("--no-foo")["no-foo"]).to eq(true)
323
+ end
324
+
325
+ it "will prefer 'skip-opt' variant over inverting 'opt' if explicitly set" do
326
+ create "--skip-foo" => true
327
+ expect(parse("--skip-foo")["skip-foo"]).to eq(true)
328
+ end
329
+
330
+ it "accepts inputs in the human name format" do
331
+ create :foo_bar => :boolean
332
+ expect(parse("--foo-bar")["foo_bar"]).to eq(true)
333
+ expect(parse("--no-foo-bar")["foo_bar"]).to eq(false)
334
+ expect(parse("--skip-foo-bar")["foo_bar"]).to eq(false)
335
+ end
336
+
337
+ it "doesn't eat the next part of the param" do
338
+ create :foo => :boolean
339
+ expect(parse("--foo", "bar")).to eq({"foo" => true})
340
+ expect(@opt.remaining).to eq(["bar"])
341
+ end
342
+ end
343
+
344
+ describe "with :hash type" do
345
+ before do
346
+ create "--attributes" => :hash
347
+ end
348
+
349
+ it "accepts a switch=<value> assignment" do
350
+ expect(parse("--attributes=name:string", "age:integer")["attributes"]).to eq({"name" => "string", "age" => "integer"})
351
+ end
352
+
353
+ it "accepts a switch <value> assignment" do
354
+ expect(parse("--attributes", "name:string", "age:integer")["attributes"]).to eq({"name" => "string", "age" => "integer"})
355
+ end
356
+
357
+ it "must not mix values with other switches" do
358
+ expect(parse("--attributes", "name:string", "age:integer", "--baz", "cool")["attributes"]).to eq({"name" => "string", "age" => "integer"})
359
+ end
360
+ end
361
+
362
+ describe "with :array type" do
363
+ before do
364
+ create "--attributes" => :array
365
+ end
366
+
367
+ it "accepts a switch=<value> assignment" do
368
+ expect(parse("--attributes=a", "b", "c")["attributes"]).to eq(["a", "b", "c"])
369
+ end
370
+
371
+ it "accepts a switch <value> assignment" do
372
+ expect(parse("--attributes", "a", "b", "c")["attributes"]).to eq(["a", "b", "c"])
373
+ end
374
+
375
+ it "must not mix values with other switches" do
376
+ expect(parse("--attributes", "a", "b", "c", "--baz", "cool")["attributes"]).to eq(["a", "b", "c"])
377
+ end
378
+ end
379
+
380
+ describe "with :numeric type" do
381
+ before do
382
+ create "n" => :numeric, "m" => 5
383
+ end
384
+
385
+ it "accepts a -nXY assignment" do
386
+ expect(parse("-n12")["n"]).to eq(12)
387
+ end
388
+
389
+ it "converts values to numeric types" do
390
+ expect(parse("-n", "3", "-m", ".5")).to eq({"n" => 3, "m" => 0.5})
391
+ end
392
+
393
+ it "raises error when value isn't numeric" do
394
+ expect{ parse("-n", "foo") }.to raise_error(Thor::MalformattedArgumentError,
395
+ "Expected numeric value for '-n'; got \"foo\"")
396
+ end
397
+ end
398
+
399
+ end
400
+ end
@@ -0,0 +1,72 @@
1
+ require 'helper'
2
+ require 'thor/rake_compat'
3
+ require 'rake/tasklib'
4
+
5
+ $main = self
6
+
7
+ class RakeTask < Rake::TaskLib
8
+ def initialize
9
+ define
10
+ end
11
+
12
+ def define
13
+ $main.instance_eval do
14
+ desc "Say it's cool"
15
+ task :cool do
16
+ puts "COOL"
17
+ end
18
+
19
+ namespace :hiper_mega do
20
+ task :super do
21
+ puts "HIPER MEGA SUPER"
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ class ThorTask < Thor
29
+ include Thor::RakeCompat
30
+ RakeTask.new
31
+ end
32
+
33
+ describe Thor::RakeCompat do
34
+ it "sets the rakefile application" do
35
+ expect(["rake_compat_spec.rb", "Thorfile"]).to include(Rake.application.rakefile)
36
+ end
37
+
38
+ it "adds rake tasks to thor classes too" do
39
+ task = ThorTask.tasks["cool"]
40
+ expect(task).to be
41
+ end
42
+
43
+ it "uses rake tasks descriptions on thor" do
44
+ expect(ThorTask.tasks["cool"].description).to eq("Say it's cool")
45
+ end
46
+
47
+ it "gets usage from rake tasks name" do
48
+ expect(ThorTask.tasks["cool"].usage).to eq("cool")
49
+ end
50
+
51
+ it "uses non namespaced name as description if non is available" do
52
+ expect(ThorTask::HiperMega.tasks["super"].description).to eq("super")
53
+ end
54
+
55
+ it "converts namespaces to classes" do
56
+ expect(ThorTask.const_get(:HiperMega)).to eq(ThorTask::HiperMega)
57
+ end
58
+
59
+ it "does not add tasks from higher namespaces in lowers namespaces" do
60
+ expect(ThorTask.tasks["super"]).not_to be
61
+ end
62
+
63
+ it "invoking the thor task invokes the rake task" do
64
+ expect(capture(:stdout) {
65
+ ThorTask.start ["cool"]
66
+ }).to eq("COOL\n")
67
+
68
+ expect(capture(:stdout) {
69
+ ThorTask::HiperMega.start ["super"]
70
+ }).to eq("HIPER MEGA SUPER\n")
71
+ end
72
+ end