thor 0.19.1 → 0.19.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +24 -0
  3. data/CONTRIBUTING.md +15 -0
  4. data/README.md +7 -1
  5. data/lib/thor.rb +31 -23
  6. data/lib/thor/actions.rb +21 -22
  7. data/lib/thor/actions/create_file.rb +1 -1
  8. data/lib/thor/actions/create_link.rb +1 -1
  9. data/lib/thor/actions/directory.rb +2 -2
  10. data/lib/thor/actions/empty_directory.rb +8 -8
  11. data/lib/thor/actions/file_manipulation.rb +23 -12
  12. data/lib/thor/actions/inject_into_file.rb +10 -14
  13. data/lib/thor/base.rb +33 -33
  14. data/lib/thor/command.rb +9 -9
  15. data/lib/thor/core_ext/hash_with_indifferent_access.rb +9 -1
  16. data/lib/thor/core_ext/io_binary_read.rb +7 -5
  17. data/lib/thor/core_ext/ordered_hash.rb +94 -63
  18. data/lib/thor/error.rb +3 -3
  19. data/lib/thor/group.rb +12 -12
  20. data/lib/thor/invocation.rb +4 -5
  21. data/lib/thor/parser/argument.rb +4 -7
  22. data/lib/thor/parser/arguments.rb +16 -16
  23. data/lib/thor/parser/option.rb +39 -19
  24. data/lib/thor/parser/options.rb +7 -5
  25. data/lib/thor/runner.rb +25 -25
  26. data/lib/thor/shell.rb +1 -1
  27. data/lib/thor/shell/basic.rb +41 -26
  28. data/lib/thor/shell/color.rb +1 -1
  29. data/lib/thor/shell/html.rb +4 -4
  30. data/lib/thor/util.rb +8 -7
  31. data/lib/thor/version.rb +1 -1
  32. data/thor.gemspec +6 -9
  33. metadata +6 -148
  34. data/Thorfile +0 -29
  35. data/spec/actions/create_file_spec.rb +0 -168
  36. data/spec/actions/create_link_spec.rb +0 -96
  37. data/spec/actions/directory_spec.rb +0 -169
  38. data/spec/actions/empty_directory_spec.rb +0 -129
  39. data/spec/actions/file_manipulation_spec.rb +0 -392
  40. data/spec/actions/inject_into_file_spec.rb +0 -135
  41. data/spec/actions_spec.rb +0 -331
  42. data/spec/base_spec.rb +0 -298
  43. data/spec/command_spec.rb +0 -79
  44. data/spec/core_ext/hash_with_indifferent_access_spec.rb +0 -48
  45. data/spec/core_ext/ordered_hash_spec.rb +0 -115
  46. data/spec/exit_condition_spec.rb +0 -19
  47. data/spec/fixtures/application.rb +0 -2
  48. data/spec/fixtures/app{1}/README +0 -3
  49. data/spec/fixtures/bundle/execute.rb +0 -6
  50. data/spec/fixtures/bundle/main.thor +0 -1
  51. data/spec/fixtures/command.thor +0 -10
  52. data/spec/fixtures/doc/%file_name%.rb.tt +0 -1
  53. data/spec/fixtures/doc/COMMENTER +0 -11
  54. data/spec/fixtures/doc/README +0 -3
  55. data/spec/fixtures/doc/block_helper.rb +0 -3
  56. data/spec/fixtures/doc/config.rb +0 -1
  57. data/spec/fixtures/doc/config.yaml.tt +0 -1
  58. data/spec/fixtures/doc/excluding/%file_name%.rb.tt +0 -1
  59. data/spec/fixtures/enum.thor +0 -10
  60. data/spec/fixtures/group.thor +0 -128
  61. data/spec/fixtures/invoke.thor +0 -131
  62. data/spec/fixtures/path with spaces b/data/spec/fixtures/path with → spaces +0 -0
  63. data/spec/fixtures/preserve/script.sh +0 -3
  64. data/spec/fixtures/script.thor +0 -220
  65. data/spec/fixtures/subcommand.thor +0 -17
  66. data/spec/group_spec.rb +0 -222
  67. data/spec/helper.rb +0 -80
  68. data/spec/invocation_spec.rb +0 -120
  69. data/spec/line_editor/basic_spec.rb +0 -28
  70. data/spec/line_editor/readline_spec.rb +0 -69
  71. data/spec/line_editor_spec.rb +0 -43
  72. data/spec/parser/argument_spec.rb +0 -53
  73. data/spec/parser/arguments_spec.rb +0 -66
  74. data/spec/parser/option_spec.rb +0 -210
  75. data/spec/parser/options_spec.rb +0 -414
  76. data/spec/quality_spec.rb +0 -75
  77. data/spec/rake_compat_spec.rb +0 -72
  78. data/spec/register_spec.rb +0 -227
  79. data/spec/runner_spec.rb +0 -246
  80. data/spec/sandbox/application.rb +0 -2
  81. data/spec/sandbox/app{1}/README +0 -3
  82. data/spec/sandbox/bundle/execute.rb +0 -6
  83. data/spec/sandbox/bundle/main.thor +0 -1
  84. data/spec/sandbox/command.thor +0 -10
  85. data/spec/sandbox/doc/%file_name%.rb.tt +0 -1
  86. data/spec/sandbox/doc/COMMENTER +0 -11
  87. data/spec/sandbox/doc/README +0 -3
  88. data/spec/sandbox/doc/block_helper.rb +0 -3
  89. data/spec/sandbox/doc/config.rb +0 -1
  90. data/spec/sandbox/doc/config.yaml.tt +0 -1
  91. data/spec/sandbox/doc/excluding/%file_name%.rb.tt +0 -1
  92. data/spec/sandbox/enum.thor +0 -10
  93. data/spec/sandbox/group.thor +0 -128
  94. data/spec/sandbox/invoke.thor +0 -131
  95. data/spec/sandbox/path with spaces b/data/spec/sandbox/path with → spaces +0 -0
  96. data/spec/sandbox/preserve/script.sh +0 -3
  97. data/spec/sandbox/script.thor +0 -220
  98. data/spec/sandbox/subcommand.thor +0 -17
  99. data/spec/shell/basic_spec.rb +0 -337
  100. data/spec/shell/color_spec.rb +0 -119
  101. data/spec/shell/html_spec.rb +0 -31
  102. data/spec/shell_spec.rb +0 -47
  103. data/spec/subcommand_spec.rb +0 -48
  104. data/spec/thor_spec.rb +0 -505
  105. data/spec/util_spec.rb +0 -196
@@ -1,135 +0,0 @@
1
- require "helper"
2
- require "thor/actions"
3
-
4
- describe Thor::Actions::InjectIntoFile do
5
- before do
6
- ::FileUtils.rm_rf(destination_root)
7
- ::FileUtils.cp_r(source_root, destination_root)
8
- end
9
-
10
- def invoker(options = {})
11
- @invoker ||= MyCounter.new([1, 2], options, :destination_root => destination_root)
12
- end
13
-
14
- def revoker
15
- @revoker ||= MyCounter.new([1, 2], {}, :destination_root => destination_root, :behavior => :revoke)
16
- end
17
-
18
- def invoke!(*args, &block)
19
- capture(:stdout) { invoker.insert_into_file(*args, &block) }
20
- end
21
-
22
- def revoke!(*args, &block)
23
- capture(:stdout) { revoker.insert_into_file(*args, &block) }
24
- end
25
-
26
- def file
27
- File.join(destination_root, "doc/README")
28
- end
29
-
30
- describe "#invoke!" do
31
- it "changes the file adding content after the flag" do
32
- invoke! "doc/README", "\nmore content", :after => "__start__"
33
- expect(File.read(file)).to eq("__start__\nmore content\nREADME\n__end__\n")
34
- end
35
-
36
- it "changes the file adding content before the flag" do
37
- invoke! "doc/README", "more content\n", :before => "__end__"
38
- expect(File.read(file)).to eq("__start__\nREADME\nmore content\n__end__\n")
39
- end
40
-
41
- it "accepts data as a block" do
42
- invoke! "doc/README", :before => "__end__" do
43
- "more content\n"
44
- end
45
-
46
- expect(File.read(file)).to eq("__start__\nREADME\nmore content\n__end__\n")
47
- end
48
-
49
- it "logs status" do
50
- expect(invoke!("doc/README", "\nmore content", :after => "__start__")).to eq(" insert doc/README\n")
51
- end
52
-
53
- it "does not change the file if pretending" do
54
- invoker :pretend => true
55
- invoke! "doc/README", "\nmore content", :after => "__start__"
56
- expect(File.read(file)).to eq("__start__\nREADME\n__end__\n")
57
- end
58
-
59
- it "does not change the file if already includes content" do
60
- invoke! "doc/README", :before => "__end__" do
61
- "more content\n"
62
- end
63
-
64
- expect(File.read(file)).to eq("__start__\nREADME\nmore content\n__end__\n")
65
-
66
- invoke! "doc/README", :before => "__end__" do
67
- "more content\n"
68
- end
69
-
70
- expect(File.read(file)).to eq("__start__\nREADME\nmore content\n__end__\n")
71
- end
72
-
73
- it "does change the file if already includes content and :force is true" do
74
- invoke! "doc/README", :before => "__end__" do
75
- "more content\n"
76
- end
77
-
78
- expect(File.read(file)).to eq("__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
- expect(File.read(file)).to eq("__start__\nREADME\nmore content\nmore content\n__end__\n")
85
- end
86
-
87
- end
88
-
89
- describe "#revoke!" do
90
- it "subtracts the destination file after injection" do
91
- invoke! "doc/README", "\nmore content", :after => "__start__"
92
- revoke! "doc/README", "\nmore content", :after => "__start__"
93
- expect(File.read(file)).to eq("__start__\nREADME\n__end__\n")
94
- end
95
-
96
- it "subtracts the destination file before injection" do
97
- invoke! "doc/README", "more content\n", :before => "__start__"
98
- revoke! "doc/README", "more content\n", :before => "__start__"
99
- expect(File.read(file)).to eq("__start__\nREADME\n__end__\n")
100
- end
101
-
102
- it "subtracts even with double after injection" do
103
- invoke! "doc/README", "\nmore content", :after => "__start__"
104
- invoke! "doc/README", "\nanother stuff", :after => "__start__"
105
- revoke! "doc/README", "\nmore content", :after => "__start__"
106
- expect(File.read(file)).to eq("__start__\nanother stuff\nREADME\n__end__\n")
107
- end
108
-
109
- it "subtracts even with double before injection" do
110
- invoke! "doc/README", "more content\n", :before => "__start__"
111
- invoke! "doc/README", "another stuff\n", :before => "__start__"
112
- revoke! "doc/README", "more content\n", :before => "__start__"
113
- expect(File.read(file)).to eq("another stuff\n__start__\nREADME\n__end__\n")
114
- end
115
-
116
- it "subtracts when prepending" do
117
- invoke! "doc/README", "more content\n", :after => /\A/
118
- invoke! "doc/README", "another stuff\n", :after => /\A/
119
- revoke! "doc/README", "more content\n", :after => /\A/
120
- expect(File.read(file)).to eq("another stuff\n__start__\nREADME\n__end__\n")
121
- end
122
-
123
- it "subtracts when appending" do
124
- invoke! "doc/README", "more content\n", :before => /\z/
125
- invoke! "doc/README", "another stuff\n", :before => /\z/
126
- revoke! "doc/README", "more content\n", :before => /\z/
127
- expect(File.read(file)).to eq("__start__\nREADME\n__end__\nanother stuff\n")
128
- end
129
-
130
- it "shows progress information to the user" do
131
- invoke!("doc/README", "\nmore content", :after => "__start__")
132
- expect(revoke!("doc/README", "\nmore content", :after => "__start__")).to eq(" subtract doc/README\n")
133
- end
134
- end
135
- end
@@ -1,331 +0,0 @@
1
- require "helper"
2
-
3
- describe Thor::Actions do
4
- def runner(options = {})
5
- @runner ||= MyCounter.new([1], options, :destination_root => destination_root)
6
- end
7
-
8
- def action(*args, &block)
9
- capture(:stdout) { runner.send(*args, &block) }
10
- end
11
-
12
- def file
13
- File.join(destination_root, "foo")
14
- end
15
-
16
- describe "on include" do
17
- it "adds runtime options to the base class" do
18
- expect(MyCounter.class_options.keys).to include(:pretend)
19
- expect(MyCounter.class_options.keys).to include(:force)
20
- expect(MyCounter.class_options.keys).to include(:quiet)
21
- expect(MyCounter.class_options.keys).to include(:skip)
22
- end
23
- end
24
-
25
- describe "#initialize" do
26
- it "has default behavior invoke" do
27
- expect(runner.behavior).to eq(:invoke)
28
- end
29
-
30
- it "can have behavior revoke" do
31
- expect(MyCounter.new([1], {}, :behavior => :revoke).behavior).to eq(:revoke)
32
- end
33
-
34
- it "when behavior is set to force, overwrite options" do
35
- runner = MyCounter.new([1], {:force => false, :skip => true}, :behavior => :force)
36
- expect(runner.behavior).to eq(:invoke)
37
- expect(runner.options.force).to be true
38
- expect(runner.options.skip).not_to be true
39
- end
40
-
41
- it "when behavior is set to skip, overwrite options" do
42
- runner = MyCounter.new([1], %w[--force], :behavior => :skip)
43
- expect(runner.behavior).to eq(:invoke)
44
- expect(runner.options.force).not_to be true
45
- expect(runner.options.skip).to be true
46
- end
47
- end
48
-
49
- describe "accessors" do
50
- describe "#destination_root=" do
51
- it "gets the current directory and expands the path to set the root" do
52
- base = MyCounter.new([1])
53
- base.destination_root = "here"
54
- expect(base.destination_root).to eq(File.expand_path(File.join(File.dirname(__FILE__), "..", "here")))
55
- end
56
-
57
- it "does not use the current directory if one is given" do
58
- root = File.expand_path("/")
59
- base = MyCounter.new([1])
60
- base.destination_root = root
61
- expect(base.destination_root).to eq(root)
62
- end
63
-
64
- it "uses the current directory if none is given" do
65
- base = MyCounter.new([1])
66
- expect(base.destination_root).to eq(File.expand_path(File.join(File.dirname(__FILE__), "..")))
67
- end
68
- end
69
-
70
- describe "#relative_to_original_destination_root" do
71
- it "returns the path relative to the absolute root" do
72
- expect(runner.relative_to_original_destination_root(file)).to eq("foo")
73
- end
74
-
75
- it "does not remove dot if required" do
76
- expect(runner.relative_to_original_destination_root(file, false)).to eq("./foo")
77
- end
78
-
79
- it "always use the absolute root" do
80
- runner.inside("foo") do
81
- expect(runner.relative_to_original_destination_root(file)).to eq("foo")
82
- end
83
- end
84
-
85
- it "creates proper relative paths for absolute file location" do
86
- expect(runner.relative_to_original_destination_root("/test/file")).to eq("/test/file")
87
- end
88
-
89
- it "does not fail with files containing regexp characters" do
90
- runner = MyCounter.new([1], {}, :destination_root => File.join(destination_root, "fo[o-b]ar"))
91
- expect(runner.relative_to_original_destination_root("bar")).to eq("bar")
92
- end
93
-
94
- describe "#source_paths_for_search" do
95
- it "add source_root to source_paths_for_search" do
96
- expect(MyCounter.source_paths_for_search).to include(File.expand_path("fixtures", File.dirname(__FILE__)))
97
- end
98
-
99
- it "keeps only current source root in source paths" do
100
- expect(ClearCounter.source_paths_for_search).to include(File.expand_path("fixtures/bundle", File.dirname(__FILE__)))
101
- expect(ClearCounter.source_paths_for_search).not_to include(File.expand_path("fixtures", File.dirname(__FILE__)))
102
- end
103
-
104
- it "customized source paths should be before source roots" do
105
- expect(ClearCounter.source_paths_for_search[0]).to eq(File.expand_path("fixtures/doc", File.dirname(__FILE__)))
106
- expect(ClearCounter.source_paths_for_search[1]).to eq(File.expand_path("fixtures/bundle", File.dirname(__FILE__)))
107
- end
108
-
109
- it "keeps inherited source paths at the end" do
110
- expect(ClearCounter.source_paths_for_search.last).to eq(File.expand_path("fixtures/broken", File.dirname(__FILE__)))
111
- end
112
- end
113
- end
114
-
115
- describe "#find_in_source_paths" do
116
- it "raises an error if source path is empty" do
117
- expect do
118
- A.new.find_in_source_paths("foo")
119
- end.to raise_error(Thor::Error, /Currently you have no source paths/)
120
- end
121
-
122
- it "finds a template inside the source path" do
123
- expect(runner.find_in_source_paths("doc")).to eq(File.expand_path("doc", source_root))
124
- expect { runner.find_in_source_paths("README") }.to raise_error
125
-
126
- new_path = File.join(source_root, "doc")
127
- runner.instance_variable_set(:@source_paths, nil)
128
- runner.source_paths.unshift(new_path)
129
- expect(runner.find_in_source_paths("README")).to eq(File.expand_path("README", new_path))
130
- end
131
- end
132
- end
133
-
134
- describe "#inside" do
135
- it "executes the block inside the given folder" do
136
- runner.inside("foo") do
137
- expect(Dir.pwd).to eq(file)
138
- end
139
- end
140
-
141
- it "changes the base root" do
142
- runner.inside("foo") do
143
- expect(runner.destination_root).to eq(file)
144
- end
145
- end
146
-
147
- it "creates the directory if it does not exist" do
148
- runner.inside("foo") do
149
- expect(File.exist?(file)).to be true
150
- end
151
- end
152
-
153
- describe "when pretending" do
154
- it "no directories should be created" do
155
- runner.inside("bar", :pretend => true) {}
156
- expect(File.exist?("bar")).to be false
157
- end
158
- end
159
-
160
- describe "when verbose" do
161
- it "logs status" do
162
- expect(capture(:stdout) do
163
- runner.inside("foo", :verbose => true) {}
164
- end).to match(/inside foo/)
165
- end
166
-
167
- it "uses padding in next status" do
168
- expect(capture(:stdout) do
169
- runner.inside("foo", :verbose => true) do
170
- runner.say_status :cool, :padding
171
- end
172
- end).to match(/cool padding/)
173
- end
174
-
175
- it "removes padding after block" do
176
- expect(capture(:stdout) do
177
- runner.inside("foo", :verbose => true) {}
178
- runner.say_status :no, :padding
179
- end).to match(/no padding/)
180
- end
181
- end
182
- end
183
-
184
- describe "#in_root" do
185
- it "executes the block in the root folder" do
186
- runner.inside("foo") do
187
- runner.in_root { expect(Dir.pwd).to eq(destination_root) }
188
- end
189
- end
190
-
191
- it "changes the base root" do
192
- runner.inside("foo") do
193
- runner.in_root { expect(runner.destination_root).to eq(destination_root) }
194
- end
195
- end
196
-
197
- it "returns to the previous state" do
198
- runner.inside("foo") do
199
- runner.in_root {}
200
- expect(runner.destination_root).to eq(file)
201
- end
202
- end
203
- end
204
-
205
- describe "#apply" do
206
- before do
207
- @template = <<-TEMPLATE
208
- @foo = "FOO"
209
- say_status :cool, :padding
210
- TEMPLATE
211
- allow(@template).to receive(:read).and_return(@template)
212
-
213
- @file = "/"
214
- allow(runner).to receive(:open).and_return(@template)
215
- end
216
-
217
- it "accepts a URL as the path" do
218
- @file = "http://gist.github.com/103208.txt"
219
- expect(runner).to receive(:open).with(@file, "Accept" => "application/x-thor-template").and_return(@template)
220
- action(:apply, @file)
221
- end
222
-
223
- it "accepts a secure URL as the path" do
224
- @file = "https://gist.github.com/103208.txt"
225
- expect(runner).to receive(:open).with(@file, "Accept" => "application/x-thor-template").and_return(@template)
226
- action(:apply, @file)
227
- end
228
-
229
- it "accepts a local file path with spaces" do
230
- @file = File.expand_path("fixtures/path with spaces", File.dirname(__FILE__))
231
- expect(runner).to receive(:open).with(@file).and_return(@template)
232
- action(:apply, @file)
233
- end
234
-
235
- it "opens a file and executes its content in the instance binding" do
236
- action :apply, @file
237
- expect(runner.instance_variable_get("@foo")).to eq("FOO")
238
- end
239
-
240
- it "applies padding to the content inside the file" do
241
- expect(action(:apply, @file)).to match(/cool padding/)
242
- end
243
-
244
- it "logs its status" do
245
- expect(action(:apply, @file)).to match(/ apply #{@file}\n/)
246
- end
247
-
248
- it "does not log status" do
249
- content = action(:apply, @file, :verbose => false)
250
- expect(content).to match(/cool padding/)
251
- expect(content).not_to match(/apply http/)
252
- end
253
- end
254
-
255
- describe "#run" do
256
- before do
257
- expect(runner).to receive(:system).with("ls")
258
- end
259
-
260
- it "executes the command given" do
261
- action :run, "ls"
262
- end
263
-
264
- it "logs status" do
265
- expect(action(:run, "ls")).to eq(" run ls from \".\"\n")
266
- end
267
-
268
- it "does not log status if required" do
269
- expect(action(:run, "ls", :verbose => false)).to be_empty
270
- end
271
-
272
- it "accepts a color as status" do
273
- expect(runner.shell).to receive(:say_status).with(:run, 'ls from "."', :yellow)
274
- action :run, "ls", :verbose => :yellow
275
- end
276
- end
277
-
278
- describe "#run_ruby_script" do
279
- before do
280
- allow(Thor::Util).to receive(:ruby_command).and_return("/opt/jruby")
281
- expect(runner).to receive(:system).with("/opt/jruby script.rb")
282
- end
283
-
284
- it "executes the ruby script" do
285
- action :run_ruby_script, "script.rb"
286
- end
287
-
288
- it "logs status" do
289
- expect(action(:run_ruby_script, "script.rb")).to eq(" run jruby script.rb from \".\"\n")
290
- end
291
-
292
- it "does not log status if required" do
293
- expect(action(:run_ruby_script, "script.rb", :verbose => false)).to be_empty
294
- end
295
- end
296
-
297
- describe "#thor" do
298
- it "executes the thor command" do
299
- expect(runner).to receive(:system).with("thor list")
300
- action :thor, :list, :verbose => true
301
- end
302
-
303
- it "converts extra arguments to command arguments" do
304
- expect(runner).to receive(:system).with("thor list foo bar")
305
- action :thor, :list, "foo", "bar"
306
- end
307
-
308
- it "converts options hash to switches" do
309
- expect(runner).to receive(:system).with("thor list foo bar --foo")
310
- action :thor, :list, "foo", "bar", :foo => true
311
-
312
- expect(runner).to receive(:system).with("thor list --foo 1 2 3")
313
- action :thor, :list, :foo => [1, 2, 3]
314
- end
315
-
316
- it "logs status" do
317
- expect(runner).to receive(:system).with("thor list")
318
- expect(action(:thor, :list)).to eq(" run thor list from \".\"\n")
319
- end
320
-
321
- it "does not log status if required" do
322
- expect(runner).to receive(:system).with("thor list --foo 1 2 3")
323
- expect(action(:thor, :list, :foo => [1, 2, 3], :verbose => false)).to be_empty
324
- end
325
-
326
- it "captures the output when :capture is given" do
327
- expect(runner).to receive(:`).with("thor foo bar")
328
- action(:thor, "foo", "bar", :capture => true)
329
- end
330
- end
331
- end