thor 0.18.1 → 0.19.0

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 (92) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +13 -7
  3. data/Thorfile +4 -5
  4. data/bin/thor +1 -1
  5. data/lib/thor.rb +78 -67
  6. data/lib/thor/actions.rb +57 -56
  7. data/lib/thor/actions/create_file.rb +33 -35
  8. data/lib/thor/actions/create_link.rb +2 -3
  9. data/lib/thor/actions/directory.rb +37 -38
  10. data/lib/thor/actions/empty_directory.rb +67 -69
  11. data/lib/thor/actions/file_manipulation.rb +17 -15
  12. data/lib/thor/actions/inject_into_file.rb +27 -29
  13. data/lib/thor/base.rb +193 -189
  14. data/lib/thor/command.rb +20 -23
  15. data/lib/thor/core_ext/hash_with_indifferent_access.rb +21 -24
  16. data/lib/thor/core_ext/io_binary_read.rb +2 -4
  17. data/lib/thor/core_ext/ordered_hash.rb +9 -11
  18. data/lib/thor/error.rb +5 -1
  19. data/lib/thor/group.rb +53 -54
  20. data/lib/thor/invocation.rb +44 -38
  21. data/lib/thor/line_editor.rb +17 -0
  22. data/lib/thor/line_editor/basic.rb +35 -0
  23. data/lib/thor/line_editor/readline.rb +88 -0
  24. data/lib/thor/parser.rb +4 -4
  25. data/lib/thor/parser/argument.rb +28 -29
  26. data/lib/thor/parser/arguments.rb +102 -98
  27. data/lib/thor/parser/option.rb +26 -22
  28. data/lib/thor/parser/options.rb +86 -86
  29. data/lib/thor/rake_compat.rb +9 -10
  30. data/lib/thor/runner.rb +141 -141
  31. data/lib/thor/shell.rb +27 -34
  32. data/lib/thor/shell/basic.rb +91 -63
  33. data/lib/thor/shell/color.rb +44 -43
  34. data/lib/thor/shell/html.rb +59 -60
  35. data/lib/thor/util.rb +24 -27
  36. data/lib/thor/version.rb +1 -1
  37. data/spec/actions/create_file_spec.rb +25 -27
  38. data/spec/actions/create_link_spec.rb +19 -18
  39. data/spec/actions/directory_spec.rb +31 -31
  40. data/spec/actions/empty_directory_spec.rb +18 -18
  41. data/spec/actions/file_manipulation_spec.rb +38 -28
  42. data/spec/actions/inject_into_file_spec.rb +13 -13
  43. data/spec/actions_spec.rb +43 -43
  44. data/spec/base_spec.rb +45 -38
  45. data/spec/command_spec.rb +13 -14
  46. data/spec/core_ext/hash_with_indifferent_access_spec.rb +19 -19
  47. data/spec/core_ext/ordered_hash_spec.rb +6 -6
  48. data/spec/exit_condition_spec.rb +4 -4
  49. data/spec/fixtures/invoke.thor +19 -0
  50. data/spec/fixtures/script.thor +1 -1
  51. data/spec/group_spec.rb +30 -24
  52. data/spec/helper.rb +28 -15
  53. data/spec/invocation_spec.rb +39 -19
  54. data/spec/line_editor/basic_spec.rb +28 -0
  55. data/spec/line_editor/readline_spec.rb +69 -0
  56. data/spec/line_editor_spec.rb +43 -0
  57. data/spec/parser/argument_spec.rb +12 -12
  58. data/spec/parser/arguments_spec.rb +11 -11
  59. data/spec/parser/option_spec.rb +33 -25
  60. data/spec/parser/options_spec.rb +66 -52
  61. data/spec/quality_spec.rb +75 -0
  62. data/spec/rake_compat_spec.rb +10 -10
  63. data/spec/register_spec.rb +60 -30
  64. data/spec/runner_spec.rb +67 -62
  65. data/spec/sandbox/application.rb +2 -0
  66. data/spec/sandbox/app{1}/README +3 -0
  67. data/spec/sandbox/bundle/execute.rb +6 -0
  68. data/spec/sandbox/bundle/main.thor +1 -0
  69. data/spec/sandbox/command.thor +10 -0
  70. data/spec/sandbox/doc/%file_name%.rb.tt +1 -0
  71. data/spec/sandbox/doc/COMMENTER +11 -0
  72. data/spec/sandbox/doc/README +3 -0
  73. data/spec/sandbox/doc/block_helper.rb +3 -0
  74. data/spec/sandbox/doc/config.rb +1 -0
  75. data/spec/sandbox/doc/config.yaml.tt +1 -0
  76. data/spec/sandbox/doc/excluding/%file_name%.rb.tt +1 -0
  77. data/spec/sandbox/enum.thor +10 -0
  78. data/spec/sandbox/group.thor +128 -0
  79. data/spec/sandbox/invoke.thor +131 -0
  80. data/spec/sandbox/path with spaces b/data/spec/sandbox/path with → spaces +0 -0
  81. data/spec/sandbox/preserve/script.sh +3 -0
  82. data/spec/sandbox/script.thor +220 -0
  83. data/spec/sandbox/subcommand.thor +17 -0
  84. data/spec/shell/basic_spec.rb +107 -86
  85. data/spec/shell/color_spec.rb +32 -8
  86. data/spec/shell/html_spec.rb +3 -4
  87. data/spec/shell_spec.rb +7 -7
  88. data/spec/subcommand_spec.rb +20 -2
  89. data/spec/thor_spec.rb +111 -97
  90. data/spec/util_spec.rb +30 -30
  91. data/thor.gemspec +14 -14
  92. metadata +69 -25
@@ -4,7 +4,7 @@ class Thor
4
4
 
5
5
  VALID_TYPES = [:boolean, :numeric, :hash, :array, :string]
6
6
 
7
- def initialize(name, options={})
7
+ def initialize(name, options = {})
8
8
  options[:required] = false unless options.key?(:required)
9
9
  super
10
10
  @lazy_default = options[:lazy_default]
@@ -40,7 +40,7 @@ class Thor
40
40
  #
41
41
  # By default all options are optional, unless :required is given.
42
42
  #
43
- def self.parse(key, value)
43
+ def self.parse(key, value) # rubocop:disable MethodLength
44
44
  if key.is_a?(Array)
45
45
  name, *aliases = key
46
46
  else
@@ -51,21 +51,21 @@ class Thor
51
51
  default = value
52
52
 
53
53
  type = case value
54
- when Symbol
55
- default = nil
56
- if VALID_TYPES.include?(value)
57
- value
58
- elsif required = (value == :required)
59
- :string
60
- end
61
- when TrueClass, FalseClass
62
- :boolean
63
- when Numeric
64
- :numeric
65
- when Hash, Array, String
66
- value.class.name.downcase.to_sym
67
- end
68
- self.new(name.to_s, :required => required, :type => type, :default => default, :aliases => aliases)
54
+ when Symbol
55
+ default = nil
56
+ if VALID_TYPES.include?(value)
57
+ value
58
+ elsif required = (value == :required) # rubocop:disable AssignmentInCondition
59
+ :string
60
+ end
61
+ when TrueClass, FalseClass
62
+ :boolean
63
+ when Numeric
64
+ :numeric
65
+ when Hash, Array, String
66
+ value.class.name.downcase.to_sym
67
+ end
68
+ new(name.to_s, :required => required, :type => type, :default => default, :aliases => aliases)
69
69
  end
70
70
 
71
71
  def switch_name
@@ -76,7 +76,7 @@ class Thor
76
76
  @human_name ||= dasherized? ? undasherize(name) : name
77
77
  end
78
78
 
79
- def usage(padding=0)
79
+ def usage(padding = 0)
80
80
  sample = if banner && !banner.to_s.empty?
81
81
  "#{switch_name}=#{banner}"
82
82
  else
@@ -85,6 +85,10 @@ class Thor
85
85
 
86
86
  sample = "[#{sample}]" unless required?
87
87
 
88
+ if boolean?
89
+ sample << ", [#{dasherize("no-" + human_name)}]" unless name == "force"
90
+ end
91
+
88
92
  if aliases.empty?
89
93
  (" " * padding) << sample
90
94
  else
@@ -103,19 +107,19 @@ class Thor
103
107
  protected
104
108
 
105
109
  def validate!
106
- raise ArgumentError, "An option cannot be boolean and required." if boolean? && required?
110
+ fail ArgumentError, "An option cannot be boolean and required." if boolean? && required?
107
111
  end
108
112
 
109
113
  def dasherized?
110
- name.index('-') == 0
114
+ name.index("-") == 0
111
115
  end
112
116
 
113
117
  def undasherize(str)
114
- str.sub(/^-{1,2}/, '')
118
+ str.sub(/^-{1,2}/, "")
115
119
  end
116
120
 
117
121
  def dasherize(str)
118
- (str.length > 1 ? "--" : "-") + str.gsub('_', '-')
122
+ (str.length > 1 ? "--" : "-") + str.gsub("_", "-")
119
123
  end
120
124
  end
121
125
  end
@@ -1,11 +1,11 @@
1
1
  class Thor
2
- class Options < Arguments #:nodoc:
2
+ class Options < Arguments #:nodoc: # rubocop:disable ClassLength
3
3
  LONG_RE = /^(--\w+(?:-\w+)*)$/
4
4
  SHORT_RE = /^(-[a-z])$/i
5
5
  EQ_RE = /^(--\w+(?:-\w+)*|-[a-z])=(.*)$/i
6
6
  SHORT_SQ_RE = /^-([a-z]{2,})$/i # Allow either -x -v or -xv style for single char args
7
7
  SHORT_NUM = /^(-[a-z])#{NUMERIC}$/i
8
- OPTS_END = '--'.freeze
8
+ OPTS_END = "--".freeze
9
9
 
10
10
  # Receives a hash and makes it switches.
11
11
  def self.to_switches(options)
@@ -14,9 +14,9 @@ class Thor
14
14
  when true
15
15
  "--#{key}"
16
16
  when Array
17
- "--#{key} #{value.map{ |v| v.inspect }.join(' ')}"
17
+ "--#{key} #{value.map { |v| v.inspect }.join(' ')}"
18
18
  when Hash
19
- "--#{key} #{value.map{ |k,v| "#{k}:#{v}" }.join(' ')}"
19
+ "--#{key} #{value.map { |k, v| "#{k}:#{v}" }.join(' ')}"
20
20
  when nil, false
21
21
  ""
22
22
  else
@@ -29,7 +29,7 @@ class Thor
29
29
  #
30
30
  # If +stop_on_unknown+ is true, #parse will stop as soon as it encounters
31
31
  # an unknown option or a regular argument.
32
- def initialize(hash_options={}, defaults={}, stop_on_unknown=false)
32
+ def initialize(hash_options = {}, defaults = {}, stop_on_unknown = false)
33
33
  @stop_on_unknown = stop_on_unknown
34
34
  options = hash_options.values
35
35
  super(options)
@@ -46,13 +46,13 @@ class Thor
46
46
  @switches[option.switch_name] = option
47
47
 
48
48
  option.aliases.each do |short|
49
- name = short.to_s.sub(/^(?!\-)/, '-')
49
+ name = short.to_s.sub(/^(?!\-)/, "-")
50
50
  @shorts[name] ||= option.switch_name
51
51
  end
52
52
  end
53
53
  end
54
54
 
55
- def remaining
55
+ def remaining # rubocop:disable TrivialAccessors
56
56
  @extra
57
57
  end
58
58
 
@@ -69,7 +69,7 @@ class Thor
69
69
  end
70
70
  end
71
71
 
72
- def parse(args)
72
+ def parse(args) # rubocop:disable MethodLength
73
73
  @pile = args.dup
74
74
  @parsing_options = true
75
75
 
@@ -81,7 +81,7 @@ class Thor
81
81
  if is_switch
82
82
  case shifted
83
83
  when SHORT_SQ_RE
84
- unshift($1.split('').map { |f| "-#{f}" })
84
+ unshift($1.split("").map { |f| "-#{f}" })
85
85
  next
86
86
  when EQ_RE, SHORT_NUM
87
87
  unshift($2)
@@ -119,100 +119,100 @@ class Thor
119
119
  def check_unknown!
120
120
  # an unknown option starts with - or -- and has no more --'s afterward.
121
121
  unknown = @extra.select { |str| str =~ /^--?(?:(?!--).)*$/ }
122
- raise UnknownArgumentError, "Unknown switches '#{unknown.join(', ')}'" unless unknown.empty?
122
+ fail UnknownArgumentError, "Unknown switches '#{unknown.join(', ')}'" unless unknown.empty?
123
123
  end
124
124
 
125
- protected
126
-
127
- # Check if the current value in peek is a registered switch.
128
- #
129
- # Two booleans are returned. The first is true if the current value
130
- # starts with a hyphen; the second is true if it is a registered switch.
131
- def current_is_switch?
132
- case peek
133
- when LONG_RE, SHORT_RE, EQ_RE, SHORT_NUM
134
- [true, switch?($1)]
135
- when SHORT_SQ_RE
136
- [true, $1.split('').any? { |f| switch?("-#{f}") }]
137
- else
138
- [false, false]
139
- end
140
- end
125
+ protected
141
126
 
142
- def current_is_switch_formatted?
143
- case peek
144
- when LONG_RE, SHORT_RE, EQ_RE, SHORT_NUM, SHORT_SQ_RE
145
- true
146
- else
147
- false
148
- end
127
+ # Check if the current value in peek is a registered switch.
128
+ #
129
+ # Two booleans are returned. The first is true if the current value
130
+ # starts with a hyphen; the second is true if it is a registered switch.
131
+ def current_is_switch?
132
+ case peek
133
+ when LONG_RE, SHORT_RE, EQ_RE, SHORT_NUM
134
+ [true, switch?($1)]
135
+ when SHORT_SQ_RE
136
+ [true, $1.split("").any? { |f| switch?("-#{f}") }]
137
+ else
138
+ [false, false]
149
139
  end
140
+ end
150
141
 
151
- def current_is_value?
152
- peek && (!parsing_options? || super)
142
+ def current_is_switch_formatted?
143
+ case peek
144
+ when LONG_RE, SHORT_RE, EQ_RE, SHORT_NUM, SHORT_SQ_RE
145
+ true
146
+ else
147
+ false
153
148
  end
149
+ end
154
150
 
155
- def switch?(arg)
156
- switch_option(normalize_switch(arg))
157
- end
151
+ def current_is_value?
152
+ peek && (!parsing_options? || super)
153
+ end
158
154
 
159
- def switch_option(arg)
160
- if match = no_or_skip?(arg)
161
- @switches[arg] || @switches["--#{match}"]
162
- else
163
- @switches[arg]
164
- end
165
- end
155
+ def switch?(arg)
156
+ switch_option(normalize_switch(arg))
157
+ end
166
158
 
167
- # Check if the given argument is actually a shortcut.
168
- #
169
- def normalize_switch(arg)
170
- (@shorts[arg] || arg).tr('_', '-')
159
+ def switch_option(arg)
160
+ if match = no_or_skip?(arg) # rubocop:disable AssignmentInCondition
161
+ @switches[arg] || @switches["--#{match}"]
162
+ else
163
+ @switches[arg]
171
164
  end
165
+ end
172
166
 
173
- def parsing_options?
174
- peek
175
- @parsing_options
176
- end
167
+ # Check if the given argument is actually a shortcut.
168
+ #
169
+ def normalize_switch(arg)
170
+ (@shorts[arg] || arg).tr("_", "-")
171
+ end
177
172
 
178
- # Parse boolean values which can be given as --foo=true, --foo or --no-foo.
179
- #
180
- def parse_boolean(switch)
181
- if current_is_value?
182
- if ["true", "TRUE", "t", "T", true].include?(peek)
183
- shift
184
- true
185
- elsif ["false", "FALSE", "f", "F", false].include?(peek)
186
- shift
187
- false
188
- else
189
- true
190
- end
173
+ def parsing_options?
174
+ peek
175
+ @parsing_options
176
+ end
177
+
178
+ # Parse boolean values which can be given as --foo=true, --foo or --no-foo.
179
+ #
180
+ def parse_boolean(switch)
181
+ if current_is_value?
182
+ if ["true", "TRUE", "t", "T", true].include?(peek)
183
+ shift
184
+ true
185
+ elsif ["false", "FALSE", "f", "F", false].include?(peek)
186
+ shift
187
+ false
191
188
  else
192
- @switches.key?(switch) || !no_or_skip?(switch)
189
+ true
193
190
  end
191
+ else
192
+ @switches.key?(switch) || !no_or_skip?(switch)
194
193
  end
194
+ end
195
195
 
196
- # Parse the value at the peek analyzing if it requires an input or not.
197
- #
198
- def parse_peek(switch, option)
199
- if parsing_options? && (current_is_switch_formatted? || last?)
200
- if option.boolean?
201
- # No problem for boolean types
202
- elsif no_or_skip?(switch)
203
- return nil # User set value to nil
204
- elsif option.string? && !option.required?
205
- # Return the default if there is one, else the human name
206
- return option.lazy_default || option.default || option.human_name
207
- elsif option.lazy_default
208
- return option.lazy_default
209
- else
210
- raise MalformattedArgumentError, "No value provided for option '#{switch}'"
211
- end
196
+ # Parse the value at the peek analyzing if it requires an input or not.
197
+ #
198
+ def parse_peek(switch, option)
199
+ if parsing_options? && (current_is_switch_formatted? || last?)
200
+ if option.boolean?
201
+ # No problem for boolean types
202
+ elsif no_or_skip?(switch)
203
+ return nil # User set value to nil
204
+ elsif option.string? && !option.required?
205
+ # Return the default if there is one, else the human name
206
+ return option.lazy_default || option.default || option.human_name
207
+ elsif option.lazy_default
208
+ return option.lazy_default
209
+ else
210
+ fail MalformattedArgumentError, "No value provided for option '#{switch}'"
212
211
  end
213
-
214
- @non_assigned_required.delete(option)
215
- send(:"parse_#{option.type}", switch)
216
212
  end
213
+
214
+ @non_assigned_required.delete(option)
215
+ send(:"parse_#{option.type}", switch)
216
+ end
217
217
  end
218
218
  end
@@ -1,5 +1,5 @@
1
- require 'rake'
2
- require 'rake/dsl_definition'
1
+ require "rake"
2
+ require "rake/dsl_definition"
3
3
 
4
4
  class Thor
5
5
  # Adds a compatibility layer to your Thor classes which allows you to use
@@ -12,7 +12,7 @@ class Thor
12
12
  # include Thor::RakeCompat
13
13
  #
14
14
  # RSpec::Core::RakeTask.new(:spec) do |t|
15
- # t.spec_opts = ['--options', "./.rspec"]
15
+ # t.spec_opts = ['--options', './.rspec']
16
16
  # t.spec_files = FileList['spec/**/*_spec.rb']
17
17
  # end
18
18
  # end
@@ -28,23 +28,23 @@ class Thor
28
28
  # Hack. Make rakefile point to invoker, so rdoc task is generated properly.
29
29
  rakefile = File.basename(caller[0].match(/(.*):\d+/)[1])
30
30
  Rake.application.instance_variable_set(:@rakefile, rakefile)
31
- self.rake_classes << base
31
+ rake_classes << base
32
32
  end
33
33
  end
34
34
  end
35
35
 
36
36
  # override task on (main), for compatibility with Rake 0.9
37
- self.instance_eval do
37
+ instance_eval do
38
38
  alias rake_namespace namespace
39
39
 
40
40
  def task(*)
41
41
  task = super
42
42
 
43
- if klass = Thor::RakeCompat.rake_classes.last
44
- non_namespaced_name = task.name.split(':').last
43
+ if klass = Thor::RakeCompat.rake_classes.last # rubocop:disable AssignmentInCondition
44
+ non_namespaced_name = task.name.split(":").last
45
45
 
46
46
  description = non_namespaced_name
47
- description << task.arg_names.map{ |n| n.to_s.upcase }.join(' ')
47
+ description << task.arg_names.map { |n| n.to_s.upcase }.join(" ")
48
48
  description.strip!
49
49
 
50
50
  klass.desc description, Rake.application.last_description || non_namespaced_name
@@ -58,7 +58,7 @@ self.instance_eval do
58
58
  end
59
59
 
60
60
  def namespace(name)
61
- if klass = Thor::RakeCompat.rake_classes.last
61
+ if klass = Thor::RakeCompat.rake_classes.last # rubocop:disable AssignmentInCondition
62
62
  const_name = Thor::Util.camel_case(name.to_s).to_sym
63
63
  klass.const_set(const_name, Class.new(Thor))
64
64
  new_klass = klass.const_get(const_name)
@@ -69,4 +69,3 @@ self.instance_eval do
69
69
  Thor::RakeCompat.rake_classes.pop
70
70
  end
71
71
  end
72
-
@@ -1,14 +1,14 @@
1
- require 'thor'
2
- require 'thor/group'
3
- require 'thor/core_ext/io_binary_read'
1
+ require "thor"
2
+ require "thor/group"
3
+ require "thor/core_ext/io_binary_read"
4
4
 
5
- require 'fileutils'
6
- require 'open-uri'
7
- require 'yaml'
8
- require 'digest/md5'
9
- require 'pathname'
5
+ require "fileutils"
6
+ require "open-uri"
7
+ require "yaml"
8
+ require "digest/md5"
9
+ require "pathname"
10
10
 
11
- class Thor::Runner < Thor #:nodoc:
11
+ class Thor::Runner < Thor #:nodoc: # rubocop:disable ClassLength
12
12
  map "-T" => :list, "-i" => :install, "-u" => :update, "-v" => :version
13
13
 
14
14
  # Override Thor#help so it can give information about any class and any method.
@@ -18,7 +18,7 @@ class Thor::Runner < Thor #:nodoc:
18
18
  initialize_thorfiles(meth)
19
19
  klass, command = Thor::Util.find_class_and_command_by_namespace(meth)
20
20
  self.class.handle_no_command_error(command, false) if klass.nil?
21
- klass.start(["-h", command].compact, :shell => self.shell)
21
+ klass.start(["-h", command].compact, :shell => shell)
22
22
  else
23
23
  super
24
24
  end
@@ -33,12 +33,12 @@ class Thor::Runner < Thor #:nodoc:
33
33
  klass, command = Thor::Util.find_class_and_command_by_namespace(meth)
34
34
  self.class.handle_no_command_error(command, false) if klass.nil?
35
35
  args.unshift(command) if command
36
- klass.start(args, :shell => self.shell)
36
+ klass.start(args, :shell => shell)
37
37
  end
38
38
 
39
39
  desc "install NAME", "Install an optionally named Thor file into your system commands"
40
40
  method_options :as => :string, :relative => :boolean, :force => :boolean
41
- def install(name)
41
+ def install(name) # rubocop:disable MethodLength
42
42
  initialize_thorfiles
43
43
 
44
44
  # If a directory name is provided as the argument, look for a 'main.thor'
@@ -46,15 +46,15 @@ class Thor::Runner < Thor #:nodoc:
46
46
  begin
47
47
  if File.directory?(File.expand_path(name))
48
48
  base, package = File.join(name, "main.thor"), :directory
49
- contents = open(base) {|input| input.read }
49
+ contents = open(base) { |input| input.read }
50
50
  else
51
51
  base, package = name, :file
52
- contents = open(name) {|input| input.read }
52
+ contents = open(name) { |input| input.read }
53
53
  end
54
54
  rescue OpenURI::HTTPError
55
55
  raise Error, "Error opening URI '#{name}'"
56
56
  rescue Errno::ENOENT
57
- raise Error, "Error opening file '#{name}'"
57
+ fail Error, "Error opening file '#{name}'"
58
58
  end
59
59
 
60
60
  say "Your Thorfile contains:"
@@ -75,7 +75,7 @@ class Thor::Runner < Thor #:nodoc:
75
75
  as = basename if as.empty?
76
76
  end
77
77
 
78
- location = if options[:relative] || name =~ /^https?:\/\//
78
+ location = if options[:relative] || name =~ %r{^https?://}
79
79
  name
80
80
  else
81
81
  File.expand_path(name)
@@ -102,13 +102,13 @@ class Thor::Runner < Thor #:nodoc:
102
102
 
103
103
  desc "version", "Show Thor version"
104
104
  def version
105
- require 'thor/version'
105
+ require "thor/version"
106
106
  say "Thor #{Thor::VERSION}"
107
107
  end
108
108
 
109
109
  desc "uninstall NAME", "Uninstall a named Thor module"
110
110
  def uninstall(name)
111
- raise Error, "Can't find module '#{name}'" unless thor_yaml[name]
111
+ fail Error, "Can't find module '#{name}'" unless thor_yaml[name]
112
112
  say "Uninstalling #{name}."
113
113
  FileUtils.rm_rf(File.join(thor_root, "#{thor_yaml[name][:filename]}"))
114
114
 
@@ -120,12 +120,12 @@ class Thor::Runner < Thor #:nodoc:
120
120
 
121
121
  desc "update NAME", "Update a Thor file from its original location"
122
122
  def update(name)
123
- raise Error, "Can't find module '#{name}'" if !thor_yaml[name] || !thor_yaml[name][:location]
123
+ fail Error, "Can't find module '#{name}'" if !thor_yaml[name] || !thor_yaml[name][:location]
124
124
 
125
125
  say "Updating '#{name}' from #{thor_yaml[name][:location]}"
126
126
 
127
127
  old_filename = thor_yaml[name][:filename]
128
- self.options = self.options.merge("as" => name)
128
+ self.options = options.merge("as" => name)
129
129
 
130
130
  if File.directory? File.expand_path(name)
131
131
  FileUtils.rm_rf(File.join(thor_root, old_filename))
@@ -152,7 +152,7 @@ class Thor::Runner < Thor #:nodoc:
152
152
 
153
153
  desc "list [SEARCH]", "List the available thor commands (--substring means .*SEARCH)"
154
154
  method_options :substring => :boolean, :group => :string, :all => :boolean, :debug => :boolean
155
- def list(search="")
155
+ def list(search = "")
156
156
  initialize_thorfiles
157
157
 
158
158
  search = ".*#{search}" if options["substring"]
@@ -166,157 +166,157 @@ class Thor::Runner < Thor #:nodoc:
166
166
  display_klasses(false, false, klasses)
167
167
  end
168
168
 
169
- private
169
+ private
170
170
 
171
- def self.banner(command, all = false, subcommand = false)
172
- "thor " + command.formatted_usage(self, all, subcommand)
173
- end
171
+ def self.banner(command, all = false, subcommand = false)
172
+ "thor " + command.formatted_usage(self, all, subcommand)
173
+ end
174
174
 
175
- def thor_root
176
- Thor::Util.thor_root
177
- end
175
+ def thor_root
176
+ Thor::Util.thor_root
177
+ end
178
178
 
179
- def thor_yaml
180
- @thor_yaml ||= begin
181
- yaml_file = File.join(thor_root, "thor.yml")
182
- yaml = YAML.load_file(yaml_file) if File.exists?(yaml_file)
183
- yaml || {}
184
- end
179
+ def thor_yaml
180
+ @thor_yaml ||= begin
181
+ yaml_file = File.join(thor_root, "thor.yml")
182
+ yaml = YAML.load_file(yaml_file) if File.exist?(yaml_file)
183
+ yaml || {}
185
184
  end
185
+ end
186
+
187
+ # Save the yaml file. If none exists in thor root, creates one.
188
+ #
189
+ def save_yaml(yaml)
190
+ yaml_file = File.join(thor_root, "thor.yml")
186
191
 
187
- # Save the yaml file. If none exists in thor root, creates one.
188
- #
189
- def save_yaml(yaml)
192
+ unless File.exist?(yaml_file)
193
+ FileUtils.mkdir_p(thor_root)
190
194
  yaml_file = File.join(thor_root, "thor.yml")
195
+ FileUtils.touch(yaml_file)
196
+ end
191
197
 
192
- unless File.exists?(yaml_file)
193
- FileUtils.mkdir_p(thor_root)
194
- yaml_file = File.join(thor_root, "thor.yml")
195
- FileUtils.touch(yaml_file)
196
- end
198
+ File.open(yaml_file, "w") { |f| f.puts yaml.to_yaml }
199
+ end
197
200
 
198
- File.open(yaml_file, "w") { |f| f.puts yaml.to_yaml }
199
- end
201
+ def self.exit_on_failure?
202
+ true
203
+ end
200
204
 
201
- def self.exit_on_failure?
202
- true
205
+ # Load the Thorfiles. If relevant_to is supplied, looks for specific files
206
+ # in the thor_root instead of loading them all.
207
+ #
208
+ # By default, it also traverses the current path until find Thor files, as
209
+ # described in thorfiles. This look up can be skipped by supplying
210
+ # skip_lookup true.
211
+ #
212
+ def initialize_thorfiles(relevant_to = nil, skip_lookup = false)
213
+ thorfiles(relevant_to, skip_lookup).each do |f|
214
+ Thor::Util.load_thorfile(f, nil, options[:debug]) unless Thor::Base.subclass_files.keys.include?(File.expand_path(f))
203
215
  end
216
+ end
204
217
 
205
- # Load the Thorfiles. If relevant_to is supplied, looks for specific files
206
- # in the thor_root instead of loading them all.
207
- #
208
- # By default, it also traverses the current path until find Thor files, as
209
- # described in thorfiles. This look up can be skipped by suppliying
210
- # skip_lookup true.
211
- #
212
- def initialize_thorfiles(relevant_to=nil, skip_lookup=false)
213
- thorfiles(relevant_to, skip_lookup).each do |f|
214
- Thor::Util.load_thorfile(f, nil, options[:debug]) unless Thor::Base.subclass_files.keys.include?(File.expand_path(f))
215
- end
216
- end
218
+ # Finds Thorfiles by traversing from your current directory down to the root
219
+ # directory of your system. If at any time we find a Thor file, we stop.
220
+ #
221
+ # We also ensure that system-wide Thorfiles are loaded first, so local
222
+ # Thorfiles can override them.
223
+ #
224
+ # ==== Example
225
+ #
226
+ # If we start at /Users/wycats/dev/thor ...
227
+ #
228
+ # 1. /Users/wycats/dev/thor
229
+ # 2. /Users/wycats/dev
230
+ # 3. /Users/wycats <-- we find a Thorfile here, so we stop
231
+ #
232
+ # Suppose we start at c:\Documents and Settings\james\dev\thor ...
233
+ #
234
+ # 1. c:\Documents and Settings\james\dev\thor
235
+ # 2. c:\Documents and Settings\james\dev
236
+ # 3. c:\Documents and Settings\james
237
+ # 4. c:\Documents and Settings
238
+ # 5. c:\ <-- no Thorfiles found!
239
+ #
240
+ def thorfiles(relevant_to = nil, skip_lookup = false)
241
+ thorfiles = []
217
242
 
218
- # Finds Thorfiles by traversing from your current directory down to the root
219
- # directory of your system. If at any time we find a Thor file, we stop.
220
- #
221
- # We also ensure that system-wide Thorfiles are loaded first, so local
222
- # Thorfiles can override them.
223
- #
224
- # ==== Example
225
- #
226
- # If we start at /Users/wycats/dev/thor ...
227
- #
228
- # 1. /Users/wycats/dev/thor
229
- # 2. /Users/wycats/dev
230
- # 3. /Users/wycats <-- we find a Thorfile here, so we stop
231
- #
232
- # Suppose we start at c:\Documents and Settings\james\dev\thor ...
233
- #
234
- # 1. c:\Documents and Settings\james\dev\thor
235
- # 2. c:\Documents and Settings\james\dev
236
- # 3. c:\Documents and Settings\james
237
- # 4. c:\Documents and Settings
238
- # 5. c:\ <-- no Thorfiles found!
239
- #
240
- def thorfiles(relevant_to=nil, skip_lookup=false)
241
- thorfiles = []
242
-
243
- unless skip_lookup
244
- Pathname.pwd.ascend do |path|
245
- thorfiles = Thor::Util.globs_for(path).map { |g| Dir[g] }.flatten
246
- break unless thorfiles.empty?
247
- end
243
+ unless skip_lookup
244
+ Pathname.pwd.ascend do |path|
245
+ thorfiles = Thor::Util.globs_for(path).map { |g| Dir[g] }.flatten
246
+ break unless thorfiles.empty?
248
247
  end
248
+ end
249
249
 
250
- files = (relevant_to ? thorfiles_relevant_to(relevant_to) : Thor::Util.thor_root_glob)
251
- files += thorfiles
252
- files -= ["#{thor_root}/thor.yml"]
250
+ files = (relevant_to ? thorfiles_relevant_to(relevant_to) : Thor::Util.thor_root_glob)
251
+ files += thorfiles
252
+ files -= ["#{thor_root}/thor.yml"]
253
253
 
254
- files.map! do |file|
255
- File.directory?(file) ? File.join(file, "main.thor") : file
256
- end
254
+ files.map! do |file|
255
+ File.directory?(file) ? File.join(file, "main.thor") : file
257
256
  end
257
+ end
258
258
 
259
- # Load Thorfiles relevant to the given method. If you provide "foo:bar" it
260
- # will load all thor files in the thor.yaml that has "foo" e "foo:bar"
261
- # namespaces registered.
262
- #
263
- def thorfiles_relevant_to(meth)
264
- lookup = [ meth, meth.split(":")[0...-1].join(":") ]
265
-
266
- files = thor_yaml.select do |k, v|
267
- v[:namespaces] && !(v[:namespaces] & lookup).empty?
268
- end
259
+ # Load Thorfiles relevant to the given method. If you provide "foo:bar" it
260
+ # will load all thor files in the thor.yaml that has "foo" e "foo:bar"
261
+ # namespaces registered.
262
+ #
263
+ def thorfiles_relevant_to(meth)
264
+ lookup = [meth, meth.split(":")[0...-1].join(":")]
269
265
 
270
- files.map { |k, v| File.join(thor_root, "#{v[:filename]}") }
266
+ files = thor_yaml.select do |k, v|
267
+ v[:namespaces] && !(v[:namespaces] & lookup).empty?
271
268
  end
272
269
 
273
- # Display information about the given klasses. If with_module is given,
274
- # it shows a table with information extracted from the yaml file.
275
- #
276
- def display_klasses(with_modules=false, show_internal=false, klasses=Thor::Base.subclasses)
277
- klasses -= [Thor, Thor::Runner, Thor::Group] unless show_internal
270
+ files.map { |k, v| File.join(thor_root, "#{v[:filename]}") }
271
+ end
278
272
 
279
- raise Error, "No Thor commands available" if klasses.empty?
280
- show_modules if with_modules && !thor_yaml.empty?
273
+ # Display information about the given klasses. If with_module is given,
274
+ # it shows a table with information extracted from the yaml file.
275
+ #
276
+ def display_klasses(with_modules = false, show_internal = false, klasses = Thor::Base.subclasses)
277
+ klasses -= [Thor, Thor::Runner, Thor::Group] unless show_internal
281
278
 
282
- list = Hash.new { |h,k| h[k] = [] }
283
- groups = klasses.select { |k| k.ancestors.include?(Thor::Group) }
279
+ fail Error, "No Thor commands available" if klasses.empty?
280
+ show_modules if with_modules && !thor_yaml.empty?
284
281
 
285
- # Get classes which inherit from Thor
286
- (klasses - groups).each { |k| list[k.namespace.split(":").first] += k.printable_commands(false) }
282
+ list = Hash.new { |h, k| h[k] = [] }
283
+ groups = klasses.select { |k| k.ancestors.include?(Thor::Group) }
287
284
 
288
- # Get classes which inherit from Thor::Base
289
- groups.map! { |k| k.printable_commands(false).first }
290
- list["root"] = groups
285
+ # Get classes which inherit from Thor
286
+ (klasses - groups).each { |k| list[k.namespace.split(":").first] += k.printable_commands(false) }
291
287
 
292
- # Order namespaces with default coming first
293
- list = list.sort{ |a,b| a[0].sub(/^default/, '') <=> b[0].sub(/^default/, '') }
294
- list.each { |n, commands| display_commands(n, commands) unless commands.empty? }
295
- end
288
+ # Get classes which inherit from Thor::Base
289
+ groups.map! { |k| k.printable_commands(false).first }
290
+ list["root"] = groups
296
291
 
297
- def display_commands(namespace, list) #:nodoc:
298
- list.sort!{ |a,b| a[0] <=> b[0] }
292
+ # Order namespaces with default coming first
293
+ list = list.sort { |a, b| a[0].sub(/^default/, "") <=> b[0].sub(/^default/, "") }
294
+ list.each { |n, commands| display_commands(n, commands) unless commands.empty? }
295
+ end
299
296
 
300
- say shell.set_color(namespace, :blue, true)
301
- say "-" * namespace.size
297
+ def display_commands(namespace, list) #:nodoc:
298
+ list.sort! { |a, b| a[0] <=> b[0] }
302
299
 
303
- print_table(list, :truncate => true)
304
- say
305
- end
306
- alias display_tasks display_commands
300
+ say shell.set_color(namespace, :blue, true)
301
+ say "-" * namespace.size
307
302
 
308
- def show_modules #:nodoc:
309
- info = []
310
- labels = ["Modules", "Namespaces"]
303
+ print_table(list, :truncate => true)
304
+ say
305
+ end
306
+ alias_method :display_tasks, :display_commands
311
307
 
312
- info << labels
313
- info << [ "-" * labels[0].size, "-" * labels[1].size ]
308
+ def show_modules #:nodoc:
309
+ info = []
310
+ labels = %w[Modules Namespaces]
314
311
 
315
- thor_yaml.each do |name, hash|
316
- info << [ name, hash[:namespaces].join(", ") ]
317
- end
312
+ info << labels
313
+ info << ["-" * labels[0].size, "-" * labels[1].size]
318
314
 
319
- print_table info
320
- say ""
315
+ thor_yaml.each do |name, hash|
316
+ info << [name, hash[:namespaces].join(", ")]
321
317
  end
318
+
319
+ print_table info
320
+ say ""
321
+ end
322
322
  end