thor 0.18.1 → 0.19.0

Sign up to get free protection for your applications and to get access to all the features.
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