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/lib/thor/actions.rb CHANGED
@@ -1,18 +1,16 @@
1
- require 'fileutils'
2
- require 'uri'
3
- require 'thor/core_ext/file_binary_read'
4
- require 'thor/actions/create_file'
5
- require 'thor/actions/create_link'
6
- require 'thor/actions/directory'
7
- require 'thor/actions/empty_directory'
8
- require 'thor/actions/file_manipulation'
9
- require 'thor/actions/inject_into_file'
1
+ require_relative "actions/create_file"
2
+ require_relative "actions/create_link"
3
+ require_relative "actions/directory"
4
+ require_relative "actions/empty_directory"
5
+ require_relative "actions/file_manipulation"
6
+ require_relative "actions/inject_into_file"
10
7
 
11
8
  class Thor
12
9
  module Actions
13
10
  attr_accessor :behavior
14
11
 
15
12
  def self.included(base) #:nodoc:
13
+ super(base)
16
14
  base.extend ClassMethods
17
15
  end
18
16
 
@@ -26,9 +24,9 @@ class Thor
26
24
  end
27
25
 
28
26
  # Stores and return the source root for this class
29
- def source_root(path=nil)
27
+ def source_root(path = nil)
30
28
  @_source_root = path if path
31
- @_source_root
29
+ @_source_root ||= nil
32
30
  end
33
31
 
34
32
  # Returns the source paths in the following order:
@@ -39,8 +37,8 @@ class Thor
39
37
  #
40
38
  def source_paths_for_search
41
39
  paths = []
42
- paths += self.source_paths
43
- paths << self.source_root if self.source_root
40
+ paths += source_paths
41
+ paths << source_root if source_root
44
42
  paths += from_superclass(:source_paths, [])
45
43
  paths
46
44
  end
@@ -71,15 +69,15 @@ class Thor
71
69
  #
72
70
  # destination_root<String>:: The root directory needed for some actions.
73
71
  #
74
- def initialize(args=[], options={}, config={})
72
+ def initialize(args = [], options = {}, config = {})
75
73
  self.behavior = case config[:behavior].to_s
76
- when "force", "skip"
77
- _cleanup_options_and_set(options, config[:behavior])
78
- :invoke
79
- when "revoke"
80
- :revoke
81
- else
82
- :invoke
74
+ when "force", "skip"
75
+ _cleanup_options_and_set(options, config[:behavior])
76
+ :invoke
77
+ when "revoke"
78
+ :revoke
79
+ else
80
+ :invoke
83
81
  end
84
82
 
85
83
  super
@@ -107,16 +105,18 @@ class Thor
107
105
  #
108
106
  def destination_root=(root)
109
107
  @destination_stack ||= []
110
- @destination_stack[0] = File.expand_path(root || '')
108
+ @destination_stack[0] = File.expand_path(root || "")
111
109
  end
112
110
 
113
111
  # Returns the given path relative to the absolute root (ie, root where
114
112
  # the script started).
115
113
  #
116
- def relative_to_original_destination_root(path, remove_dot=true)
117
- path = path.dup
118
- if path.gsub!(@destination_stack[0], '.')
119
- remove_dot ? (path[2..-1] || '') : path
114
+ def relative_to_original_destination_root(path, remove_dot = true)
115
+ root = @destination_stack[0]
116
+ if path.start_with?(root) && [File::SEPARATOR, File::ALT_SEPARATOR, nil, ''].include?(path[root.size..root.size])
117
+ path = path.dup
118
+ path[0...root.size] = '.'
119
+ remove_dot ? (path[2..-1] || "") : path
120
120
  else
121
121
  path
122
122
  end
@@ -131,24 +131,27 @@ class Thor
131
131
  # Receives a file or directory and search for it in the source paths.
132
132
  #
133
133
  def find_in_source_paths(file)
134
+ possible_files = [file, file + TEMPLATE_EXTNAME]
134
135
  relative_root = relative_to_original_destination_root(destination_root, false)
135
136
 
136
137
  source_paths.each do |source|
137
- source_file = File.expand_path(file, File.join(source, relative_root))
138
- return source_file if File.exists?(source_file)
138
+ possible_files.each do |f|
139
+ source_file = File.expand_path(f, File.join(source, relative_root))
140
+ return source_file if File.exist?(source_file)
141
+ end
139
142
  end
140
143
 
141
- message = "Could not find #{file.inspect} in any of your source paths. "
144
+ message = "Could not find #{file.inspect} in any of your source paths. ".dup
142
145
 
143
146
  unless self.class.source_root
144
147
  message << "Please invoke #{self.class.name}.source_root(PATH) with the PATH containing your templates. "
145
148
  end
146
149
 
147
- if source_paths.empty?
148
- message << "Currently you have no source paths."
149
- else
150
- message << "Your current source paths are: \n#{source_paths.join("\n")}"
151
- end
150
+ message << if source_paths.empty?
151
+ "Currently you have no source paths."
152
+ else
153
+ "Your current source paths are: \n#{source_paths.join("\n")}"
154
+ end
152
155
 
153
156
  raise Error, message
154
157
  end
@@ -158,11 +161,13 @@ class Thor
158
161
  # to the block you provide. The path is set back to the previous path when
159
162
  # the method exits.
160
163
  #
164
+ # Returns the value yielded by the block.
165
+ #
161
166
  # ==== Parameters
162
167
  # dir<String>:: the directory to move to.
163
168
  # config<Hash>:: give :verbose => true to log and use padding.
164
169
  #
165
- def inside(dir='', config={}, &block)
170
+ def inside(dir = "", config = {}, &block)
166
171
  verbose = config.fetch(:verbose, false)
167
172
  pretend = options[:pretend]
168
173
 
@@ -172,18 +177,22 @@ class Thor
172
177
 
173
178
  # If the directory doesnt exist and we're not pretending
174
179
  if !File.exist?(destination_root) && !pretend
180
+ require "fileutils"
175
181
  FileUtils.mkdir_p(destination_root)
176
182
  end
177
183
 
184
+ result = nil
178
185
  if pretend
179
186
  # In pretend mode, just yield down to the block
180
- block.arity == 1 ? yield(destination_root) : yield
187
+ result = block.arity == 1 ? yield(destination_root) : yield
181
188
  else
182
- FileUtils.cd(destination_root) { block.arity == 1 ? yield(destination_root) : yield }
189
+ require "fileutils"
190
+ FileUtils.cd(destination_root) { result = block.arity == 1 ? yield(destination_root) : yield }
183
191
  end
184
192
 
185
193
  @destination_stack.pop
186
194
  shell.padding -= 1 if verbose
195
+ result
187
196
  end
188
197
 
189
198
  # Goes to the root and execute the given block.
@@ -204,18 +213,19 @@ class Thor
204
213
  #
205
214
  # apply "recipes/jquery.rb"
206
215
  #
207
- def apply(path, config={})
216
+ def apply(path, config = {})
208
217
  verbose = config.fetch(:verbose, true)
209
- is_uri = path =~ /^https?\:\/\//
218
+ is_uri = path =~ %r{^https?\://}
210
219
  path = find_in_source_paths(path) unless is_uri
211
220
 
212
221
  say_status :apply, path, verbose
213
222
  shell.padding += 1 if verbose
214
223
 
215
- if is_uri
216
- contents = open(path, "Accept" => "application/x-thor-template") {|io| io.read }
224
+ contents = if is_uri
225
+ require "open-uri"
226
+ URI.open(path, "Accept" => "application/x-thor-template", &:read)
217
227
  else
218
- contents = open(path) {|io| io.read }
228
+ open(path, &:read)
219
229
  end
220
230
 
221
231
  instance_eval(contents, path)
@@ -227,7 +237,7 @@ class Thor
227
237
  # ==== Parameters
228
238
  # command<String>:: the command to be executed.
229
239
  # config<Hash>:: give :verbose => false to not log the status, :capture => true to hide to output. Specify :with
230
- # to append an executable to command executation.
240
+ # to append an executable to command execution.
231
241
  #
232
242
  # ==== Example
233
243
  #
@@ -235,7 +245,7 @@ class Thor
235
245
  # run('ln -s ~/edge rails')
236
246
  # end
237
247
  #
238
- def run(command, config={})
248
+ def run(command, config = {})
239
249
  return unless behavior == :invoke
240
250
 
241
251
  destination = relative_to_original_destination_root(destination_root, false)
@@ -248,9 +258,22 @@ class Thor
248
258
 
249
259
  say_status :run, desc, config.fetch(:verbose, true)
250
260
 
251
- unless options[:pretend]
252
- config[:capture] ? `#{command}` : system("#{command}")
261
+ return if options[:pretend]
262
+
263
+ env_splat = [config[:env]] if config[:env]
264
+
265
+ if config[:capture]
266
+ require "open3"
267
+ result, status = Open3.capture2e(*env_splat, command.to_s)
268
+ success = status.success?
269
+ else
270
+ result = system(*env_splat, command.to_s)
271
+ success = result
253
272
  end
273
+
274
+ abort if !success && config.fetch(:abort_on_failure, self.class.exit_on_failure?)
275
+
276
+ result
254
277
  end
255
278
 
256
279
  # Executes a ruby script (taking into account WIN32 platform quirks).
@@ -259,7 +282,7 @@ class Thor
259
282
  # command<String>:: the command to be executed.
260
283
  # config<Hash>:: give :verbose => false to not log the status.
261
284
  #
262
- def run_ruby_script(command, config={})
285
+ def run_ruby_script(command, config = {})
263
286
  return unless behavior == :invoke
264
287
  run command, config.merge(:with => Thor::Util.ruby_command)
265
288
  end
@@ -268,8 +291,8 @@ class Thor
268
291
  # switches.
269
292
  #
270
293
  # ==== Parameters
271
- # task<String>:: the task to be invoked
272
- # args<Array>:: arguments to the task
294
+ # command<String>:: the command to be invoked
295
+ # args<Array>:: arguments to the command
273
296
  # config<Hash>:: give :verbose => false to not log the status, :capture => true to hide to output.
274
297
  # Other options are given as parameter to Thor.
275
298
  #
@@ -282,37 +305,36 @@ class Thor
282
305
  # thor :list, :all => true, :substring => 'rails'
283
306
  # #=> thor list --all --substring=rails
284
307
  #
285
- def thor(task, *args)
308
+ def thor(command, *args)
286
309
  config = args.last.is_a?(Hash) ? args.pop : {}
287
310
  verbose = config.key?(:verbose) ? config.delete(:verbose) : true
288
311
  pretend = config.key?(:pretend) ? config.delete(:pretend) : false
289
312
  capture = config.key?(:capture) ? config.delete(:capture) : false
290
313
 
291
- args.unshift task
314
+ args.unshift(command)
292
315
  args.push Thor::Options.to_switches(config)
293
- command = args.join(' ').strip
316
+ command = args.join(" ").strip
294
317
 
295
318
  run command, :with => :thor, :verbose => verbose, :pretend => pretend, :capture => capture
296
319
  end
297
320
 
298
- protected
321
+ protected
299
322
 
300
- # Allow current root to be shared between invocations.
301
- #
302
- def _shared_configuration #:nodoc:
303
- super.merge!(:destination_root => self.destination_root)
304
- end
323
+ # Allow current root to be shared between invocations.
324
+ #
325
+ def _shared_configuration #:nodoc:
326
+ super.merge!(:destination_root => destination_root)
327
+ end
305
328
 
306
- def _cleanup_options_and_set(options, key) #:nodoc:
307
- case options
308
- when Array
309
- %w(--force -f --skip -s).each { |i| options.delete(i) }
310
- options << "--#{key}"
311
- when Hash
312
- [:force, :skip, "force", "skip"].each { |i| options.delete(i) }
313
- options.merge!(key => true)
314
- end
329
+ def _cleanup_options_and_set(options, key) #:nodoc:
330
+ case options
331
+ when Array
332
+ %w(--force -f --skip -s).each { |i| options.delete(i) }
333
+ options << "--#{key}"
334
+ when Hash
335
+ [:force, :skip, "force", "skip"].each { |i| options.delete(i) }
336
+ options.merge!(key => true)
315
337
  end
316
-
338
+ end
317
339
  end
318
340
  end