engineyard-serverside 2.0.0 → 2.0.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 (36) hide show
  1. data/lib/engineyard-serverside/paths.rb +0 -1
  2. data/lib/engineyard-serverside/version.rb +1 -1
  3. data/lib/vendor/thor/{LICENSE → LICENSE.md} +2 -2
  4. data/lib/vendor/thor/README.md +28 -0
  5. data/lib/vendor/thor/lib/thor.rb +183 -48
  6. data/lib/vendor/thor/lib/thor/actions.rb +66 -23
  7. data/lib/vendor/thor/lib/thor/actions/create_file.rb +5 -3
  8. data/lib/vendor/thor/lib/thor/actions/create_link.rb +57 -0
  9. data/lib/vendor/thor/lib/thor/actions/directory.rb +14 -7
  10. data/lib/vendor/thor/lib/thor/actions/empty_directory.rb +24 -5
  11. data/lib/vendor/thor/lib/thor/actions/file_manipulation.rb +106 -21
  12. data/lib/vendor/thor/lib/thor/actions/inject_into_file.rb +15 -10
  13. data/lib/vendor/thor/lib/thor/base.rb +144 -43
  14. data/lib/vendor/thor/lib/thor/core_ext/dir_escape.rb +0 -0
  15. data/lib/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +1 -1
  16. data/lib/vendor/thor/lib/thor/error.rb +6 -1
  17. data/lib/vendor/thor/lib/thor/group.rb +41 -27
  18. data/lib/vendor/thor/lib/thor/invocation.rb +48 -58
  19. data/lib/vendor/thor/lib/thor/parser/argument.rb +29 -22
  20. data/lib/vendor/thor/lib/thor/parser/arguments.rb +26 -5
  21. data/lib/vendor/thor/lib/thor/parser/option.rb +42 -49
  22. data/lib/vendor/thor/lib/thor/parser/options.rb +39 -30
  23. data/lib/vendor/thor/lib/thor/rake_compat.rb +13 -8
  24. data/lib/vendor/thor/lib/thor/runner.rb +27 -20
  25. data/lib/vendor/thor/lib/thor/shell.rb +10 -5
  26. data/lib/vendor/thor/lib/thor/shell/basic.rb +228 -78
  27. data/lib/vendor/thor/lib/thor/shell/color.rb +40 -4
  28. data/lib/vendor/thor/lib/thor/shell/html.rb +123 -0
  29. data/lib/vendor/thor/lib/thor/task.rb +83 -53
  30. data/lib/vendor/thor/lib/thor/util.rb +57 -21
  31. data/lib/vendor/thor/lib/thor/version.rb +1 -1
  32. data/lib/vendor/thor/thor.gemspec +21 -115
  33. metadata +109 -217
  34. data/lib/vendor/thor/CHANGELOG.rdoc +0 -89
  35. data/lib/vendor/thor/README.rdoc +0 -297
  36. data/lib/vendor/thor/Thorfile +0 -69
@@ -1,4 +1,5 @@
1
1
  require 'rake'
2
+ require 'rake/dsl_definition'
2
3
 
3
4
  class Thor
4
5
  # Adds a compatibility layer to your Thor classes which allows you to use
@@ -16,6 +17,8 @@ class Thor
16
17
  # end
17
18
  #
18
19
  module RakeCompat
20
+ include Rake::DSL if defined?(Rake::DSL)
21
+
19
22
  def self.rake_classes
20
23
  @rake_classes ||= []
21
24
  end
@@ -29,12 +32,12 @@ class Thor
29
32
  end
30
33
  end
31
34
 
32
- class Object #:nodoc:
33
- alias :rake_task :task
34
- alias :rake_namespace :namespace
35
+ # override task on (main), for compatibility with Rake 0.9
36
+ self.instance_eval do
37
+ alias rake_namespace namespace
35
38
 
36
- def task(*args, &block)
37
- task = rake_task(*args, &block)
39
+ def task(*)
40
+ task = super
38
41
 
39
42
  if klass = Thor::RakeCompat.rake_classes.last
40
43
  non_namespaced_name = task.name.split(':').last
@@ -43,7 +46,8 @@ class Object #:nodoc:
43
46
  description << task.arg_names.map{ |n| n.to_s.upcase }.join(' ')
44
47
  description.strip!
45
48
 
46
- klass.desc description, task.comment || non_namespaced_name
49
+ klass.desc description, Rake.application.last_description || non_namespaced_name
50
+ Rake.application.last_description = nil
47
51
  klass.send :define_method, non_namespaced_name do |*args|
48
52
  Rake::Task[task.name.to_sym].invoke(*args)
49
53
  end
@@ -52,7 +56,7 @@ class Object #:nodoc:
52
56
  task
53
57
  end
54
58
 
55
- def namespace(name, &block)
59
+ def namespace(name)
56
60
  if klass = Thor::RakeCompat.rake_classes.last
57
61
  const_name = Thor::Util.camel_case(name.to_s).to_sym
58
62
  klass.const_set(const_name, Class.new(Thor))
@@ -60,7 +64,8 @@ class Object #:nodoc:
60
64
  Thor::RakeCompat.rake_classes << new_klass
61
65
  end
62
66
 
63
- rake_namespace(name, &block)
67
+ super
64
68
  Thor::RakeCompat.rake_classes.pop
65
69
  end
66
70
  end
71
+
@@ -13,10 +13,11 @@ class Thor::Runner < Thor #:nodoc:
13
13
 
14
14
  # Override Thor#help so it can give information about any class and any method.
15
15
  #
16
- def help(meth=nil)
16
+ def help(meth = nil)
17
17
  if meth && !self.respond_to?(meth)
18
18
  initialize_thorfiles(meth)
19
- klass, task = Thor::Util.find_class_and_task_by_namespace!(meth)
19
+ klass, task = Thor::Util.find_class_and_task_by_namespace(meth)
20
+ self.class.handle_no_task_error(task, false) if klass.nil?
20
21
  klass.start(["-h", task].compact, :shell => self.shell)
21
22
  else
22
23
  super
@@ -29,7 +30,8 @@ class Thor::Runner < Thor #:nodoc:
29
30
  def method_missing(meth, *args)
30
31
  meth = meth.to_s
31
32
  initialize_thorfiles(meth)
32
- klass, task = Thor::Util.find_class_and_task_by_namespace!(meth)
33
+ klass, task = Thor::Util.find_class_and_task_by_namespace(meth)
34
+ self.class.handle_no_task_error(task, false) if klass.nil?
33
35
  args.unshift(task) if task
34
36
  klass.start(args, :shell => self.shell)
35
37
  end
@@ -39,15 +41,15 @@ class Thor::Runner < Thor #:nodoc:
39
41
  def install(name)
40
42
  initialize_thorfiles
41
43
 
42
- # If a directory name is provided as the argument, look for a 'main.thor'
44
+ # If a directory name is provided as the argument, look for a 'main.thor'
43
45
  # task in said directory.
44
46
  begin
45
47
  if File.directory?(File.expand_path(name))
46
48
  base, package = File.join(name, "main.thor"), :directory
47
- contents = open(base).read
49
+ contents = open(base) {|input| input.read }
48
50
  else
49
51
  base, package = name, :file
50
- contents = open(name).read
52
+ contents = open(name) {|input| input.read }
51
53
  end
52
54
  rescue OpenURI::HTTPError
53
55
  raise Error, "Error opening URI '#{name}'"
@@ -73,7 +75,7 @@ class Thor::Runner < Thor #:nodoc:
73
75
  as = basename if as.empty?
74
76
  end
75
77
 
76
- location = if options[:relative] || name =~ /^http:\/\//
78
+ location = if options[:relative] || name =~ /^https?:\/\//
77
79
  name
78
80
  else
79
81
  File.expand_path(name)
@@ -124,7 +126,17 @@ class Thor::Runner < Thor #:nodoc:
124
126
 
125
127
  old_filename = thor_yaml[name][:filename]
126
128
  self.options = self.options.merge("as" => name)
127
- filename = install(thor_yaml[name][:location])
129
+
130
+ if File.directory? File.expand_path(name)
131
+ FileUtils.rm_rf(File.join(thor_root, old_filename))
132
+
133
+ thor_yaml.delete(old_filename)
134
+ save_yaml(thor_yaml)
135
+
136
+ filename = install(name)
137
+ else
138
+ filename = install(thor_yaml[name][:location])
139
+ end
128
140
 
129
141
  unless filename == old_filename
130
142
  File.delete(File.join(thor_root, old_filename))
@@ -139,7 +151,7 @@ class Thor::Runner < Thor #:nodoc:
139
151
  end
140
152
 
141
153
  desc "list [SEARCH]", "List the available thor tasks (--substring means .*SEARCH)"
142
- method_options :substring => :boolean, :group => :string, :all => :boolean
154
+ method_options :substring => :boolean, :group => :string, :all => :boolean, :debug => :boolean
143
155
  def list(search="")
144
156
  initialize_thorfiles
145
157
 
@@ -156,8 +168,8 @@ class Thor::Runner < Thor #:nodoc:
156
168
 
157
169
  private
158
170
 
159
- def self.banner(task)
160
- "thor " + task.formatted_usage(self, false)
171
+ def self.banner(task, all = false, subcommand = false)
172
+ "thor " + task.formatted_usage(self, all, subcommand)
161
173
  end
162
174
 
163
175
  def thor_root
@@ -190,7 +202,7 @@ class Thor::Runner < Thor #:nodoc:
190
202
  true
191
203
  end
192
204
 
193
- # Load the thorfiles. If relevant_to is supplied, looks for specific files
205
+ # Load the Thorfiles. If relevant_to is supplied, looks for specific files
194
206
  # in the thor_root instead of loading them all.
195
207
  #
196
208
  # By default, it also traverses the current path until find Thor files, as
@@ -199,7 +211,7 @@ class Thor::Runner < Thor #:nodoc:
199
211
  #
200
212
  def initialize_thorfiles(relevant_to=nil, skip_lookup=false)
201
213
  thorfiles(relevant_to, skip_lookup).each do |f|
202
- Thor::Util.load_thorfile(f) unless Thor::Base.subclass_files.keys.include?(File.expand_path(f))
214
+ Thor::Util.load_thorfile(f, nil, options[:debug]) unless Thor::Base.subclass_files.keys.include?(File.expand_path(f))
203
215
  end
204
216
  end
205
217
 
@@ -244,7 +256,7 @@ class Thor::Runner < Thor #:nodoc:
244
256
  end
245
257
  end
246
258
 
247
- # Load thorfiles relevant to the given method. If you provide "foo:bar" it
259
+ # Load Thorfiles relevant to the given method. If you provide "foo:bar" it
248
260
  # will load all thor files in the thor.yaml that has "foo" e "foo:bar"
249
261
  # namespaces registered.
250
262
  #
@@ -267,16 +279,11 @@ class Thor::Runner < Thor #:nodoc:
267
279
  raise Error, "No Thor tasks available" if klasses.empty?
268
280
  show_modules if with_modules && !thor_yaml.empty?
269
281
 
270
- # Remove subclasses
271
- klasses.dup.each do |klass|
272
- klasses -= Thor::Util.thor_classes_in(klass)
273
- end
274
-
275
282
  list = Hash.new { |h,k| h[k] = [] }
276
283
  groups = klasses.select { |k| k.ancestors.include?(Thor::Group) }
277
284
 
278
285
  # Get classes which inherit from Thor
279
- (klasses - groups).each { |k| list[k.namespace] += k.printable_tasks(false) }
286
+ (klasses - groups).each { |k| list[k.namespace.split(":").first] += k.printable_tasks(false) }
280
287
 
281
288
  # Get classes which inherit from Thor::Base
282
289
  groups.map! { |k| k.printable_tasks(false).first }
@@ -1,5 +1,4 @@
1
1
  require 'rbconfig'
2
- require 'thor/shell/color'
3
2
 
4
3
  class Thor
5
4
  module Base
@@ -7,7 +6,9 @@ class Thor
7
6
  # it will use a colored log, otherwise it will use a basic one without color.
8
7
  #
9
8
  def self.shell
10
- @shell ||= if Config::CONFIG['host_os'] =~ /mswin|mingw/
9
+ @shell ||= if ENV['THOR_SHELL'] && ENV['THOR_SHELL'].size > 0
10
+ Thor::Shell.const_get(ENV['THOR_SHELL'])
11
+ elsif ((RbConfig::CONFIG['host_os'] =~ /mswin|mingw/) && !(ENV['ANSICON']))
11
12
  Thor::Shell::Basic
12
13
  else
13
14
  Thor::Shell::Color
@@ -22,7 +23,11 @@ class Thor
22
23
  end
23
24
 
24
25
  module Shell
25
- SHELL_DELEGATED_METHODS = [:ask, :yes?, :no?, :say, :say_status, :print_table]
26
+ SHELL_DELEGATED_METHODS = [:ask, :error, :set_color, :yes?, :no?, :say, :say_status, :print_in_columns, :print_table, :print_wrapped, :file_collision, :terminal_width]
27
+
28
+ autoload :Basic, 'thor/shell/basic'
29
+ autoload :Color, 'thor/shell/color'
30
+ autoload :HTML, 'thor/shell/html'
26
31
 
27
32
  # Add shell to initialize config values.
28
33
  #
@@ -57,8 +62,8 @@ class Thor
57
62
  # Common methods that are delegated to the shell.
58
63
  SHELL_DELEGATED_METHODS.each do |method|
59
64
  module_eval <<-METHOD, __FILE__, __LINE__
60
- def #{method}(*args)
61
- shell.#{method}(*args)
65
+ def #{method}(*args,&block)
66
+ shell.#{method}(*args,&block)
62
67
  end
63
68
  METHOD
64
69
  end
@@ -3,12 +3,28 @@ require 'tempfile'
3
3
  class Thor
4
4
  module Shell
5
5
  class Basic
6
- attr_accessor :base, :padding
6
+ attr_accessor :base
7
+ attr_reader :padding
7
8
 
8
- # Initialize base and padding to nil.
9
+ # Initialize base, mute and padding to nil.
9
10
  #
10
11
  def initialize #:nodoc:
11
- @base, @padding = nil, 0
12
+ @base, @mute, @padding = nil, false, 0
13
+ end
14
+
15
+ # Mute everything that's inside given block
16
+ #
17
+ def mute
18
+ @mute = true
19
+ yield
20
+ ensure
21
+ @mute = false
22
+ end
23
+
24
+ # Check if base is muted
25
+ #
26
+ def mute?
27
+ @mute
12
28
  end
13
29
 
14
30
  # Sets the output padding, not allowing less than zero values.
@@ -17,14 +33,22 @@ class Thor
17
33
  @padding = [0, value].max
18
34
  end
19
35
 
20
- # Ask something to the user and receives a response.
36
+ # Asks something to the user and receives a response.
37
+ #
38
+ # If asked to limit the correct responses, you can pass in an
39
+ # array of acceptable answers. If one of those is not supplied,
40
+ # they will be shown a message stating that one of those answers
41
+ # must be given and re-asked the question.
21
42
  #
22
43
  # ==== Example
23
44
  # ask("What is your name?")
24
45
  #
25
- def ask(statement, color=nil)
26
- say("#{statement} ", color)
27
- $stdin.gets.strip
46
+ # ask("What is your favorite Neopolitan flavor?", :limited_to => ["strawberry", "chocolate", "vanilla"])
47
+ #
48
+ def ask(statement, *args)
49
+ options = args.last.is_a?(Hash) ? args.pop : {}
50
+
51
+ options[:limited_to] ? ask_filtered(statement, options[:limited_to], *args) : ask_simply(statement, *args)
28
52
  end
29
53
 
30
54
  # Say (print) something to the user. If the sentence ends with a whitespace
@@ -35,15 +59,18 @@ class Thor
35
59
  # say("I know you knew that.")
36
60
  #
37
61
  def say(message="", color=nil, force_new_line=(message.to_s !~ /( |\t)$/))
38
- message = message.to_s
39
- message = set_color(message, color) if color
62
+ message = message.to_s
63
+
64
+ message = set_color(message, *color) if color
65
+
66
+ spaces = " " * padding
40
67
 
41
68
  if force_new_line
42
- $stdout.puts(message)
69
+ stdout.puts(spaces + message)
43
70
  else
44
- $stdout.print(message)
45
- $stdout.flush
71
+ stdout.print(spaces + message)
46
72
  end
73
+ stdout.flush
47
74
  end
48
75
 
49
76
  # Say a status with the given color and appends the message. Since this
@@ -58,14 +85,16 @@ class Thor
58
85
 
59
86
  status = status.to_s.rjust(12)
60
87
  status = set_color status, color, true if color
61
- say "#{status}#{spaces}#{message}", nil, true
88
+
89
+ stdout.puts "#{status}#{spaces}#{message}"
90
+ stdout.flush
62
91
  end
63
92
 
64
93
  # Make a question the to user and returns true if the user replies "y" or
65
94
  # "yes".
66
95
  #
67
96
  def yes?(statement, color=nil)
68
- ask(statement, color) =~ is?(:yes)
97
+ !!(ask(statement, color) =~ is?(:yes))
69
98
  end
70
99
 
71
100
  # Make a question the to user and returns true if the user replies "n" or
@@ -75,42 +104,114 @@ class Thor
75
104
  !yes?(statement, color)
76
105
  end
77
106
 
107
+ # Prints values in columns
108
+ #
109
+ # ==== Parameters
110
+ # Array[String, String, ...]
111
+ #
112
+ def print_in_columns(array)
113
+ return if array.empty?
114
+ colwidth = (array.map{|el| el.to_s.size}.max || 0) + 2
115
+ array.each_with_index do |value, index|
116
+ # Don't output trailing spaces when printing the last column
117
+ if ((((index + 1) % (terminal_width / colwidth))).zero? && !index.zero?) || index + 1 == array.length
118
+ stdout.puts value
119
+ else
120
+ stdout.printf("%-#{colwidth}s", value)
121
+ end
122
+ end
123
+ end
124
+
78
125
  # Prints a table.
79
126
  #
80
127
  # ==== Parameters
81
128
  # Array[Array[String, String, ...]]
82
129
  #
83
130
  # ==== Options
84
- # ident<Integer>:: Ident the first column by ident value.
131
+ # indent<Integer>:: Indent the first column by indent value.
132
+ # colwidth<Integer>:: Force the first column to colwidth spaces wide.
85
133
  #
86
- def print_table(table, options={})
87
- return if table.empty?
134
+ def print_table(array, options={})
135
+ return if array.empty?
88
136
 
89
- formats, ident = [], options[:ident].to_i
137
+ formats, indent, colwidth = [], options[:indent].to_i, options[:colwidth]
90
138
  options[:truncate] = terminal_width if options[:truncate] == true
91
139
 
92
- 0.upto(table.first.length - 2) do |i|
93
- maxima = table.max{ |a,b| a[i].size <=> b[i].size }[i].size
94
- formats << "%-#{maxima + 2}s"
140
+ formats << "%-#{colwidth + 2}s" if colwidth
141
+ start = colwidth ? 1 : 0
142
+
143
+ colcount = array.max{|a,b| a.size <=> b.size }.size
144
+
145
+ maximas = []
146
+
147
+ start.upto(colcount - 1) do |index|
148
+ maxima = array.map {|row| row[index] ? row[index].to_s.size : 0 }.max
149
+ maximas << maxima
150
+ if index == colcount - 1
151
+ # Don't output 2 trailing spaces when printing the last column
152
+ formats << "%-s"
153
+ else
154
+ formats << "%-#{maxima + 2}s"
155
+ end
95
156
  end
96
157
 
97
- formats[0] = formats[0].insert(0, " " * ident)
158
+ formats[0] = formats[0].insert(0, " " * indent)
98
159
  formats << "%s"
99
160
 
100
- table.each do |row|
161
+ array.each do |row|
101
162
  sentence = ""
102
163
 
103
- row.each_with_index do |column, i|
104
- sentence << formats[i] % column.to_s
164
+ row.each_with_index do |column, index|
165
+ maxima = maximas[index]
166
+
167
+ if column.is_a?(Numeric)
168
+ if index == row.size - 1
169
+ # Don't output 2 trailing spaces when printing the last column
170
+ f = "%#{maxima}s"
171
+ else
172
+ f = "%#{maxima}s "
173
+ end
174
+ else
175
+ f = formats[index]
176
+ end
177
+ sentence << f % column.to_s
105
178
  end
106
179
 
107
180
  sentence = truncate(sentence, options[:truncate]) if options[:truncate]
108
- $stdout.puts sentence
181
+ stdout.puts sentence
182
+ end
183
+ end
184
+
185
+ # Prints a long string, word-wrapping the text to the current width of the
186
+ # terminal display. Ideal for printing heredocs.
187
+ #
188
+ # ==== Parameters
189
+ # String
190
+ #
191
+ # ==== Options
192
+ # indent<Integer>:: Indent each line of the printed paragraph by indent value.
193
+ #
194
+ def print_wrapped(message, options={})
195
+ indent = options[:indent] || 0
196
+ width = terminal_width - indent
197
+ paras = message.split("\n\n")
198
+
199
+ paras.map! do |unwrapped|
200
+ unwrapped.strip.gsub(/\n/, " ").squeeze(" ").
201
+ gsub(/.{1,#{width}}(?:\s|\Z)/){($& + 5.chr).
202
+ gsub(/\n\005/,"\n").gsub(/\005/,"\n")}
203
+ end
204
+
205
+ paras.each do |para|
206
+ para.split("\n").each do |line|
207
+ stdout.puts line.insert(0, " " * indent)
208
+ end
209
+ stdout.puts unless para == paras.last
109
210
  end
110
211
  end
111
212
 
112
213
  # Deals with file collision and returns true if the file should be
113
- # overwriten and false otherwise. If a block is given, it uses the block
214
+ # overwritten and false otherwise. If a block is given, it uses the block
114
215
  # response as the content for the diff.
115
216
  #
116
217
  # ==== Parameters
@@ -143,35 +244,65 @@ class Thor
143
244
  end
144
245
  end
145
246
 
247
+ # This code was copied from Rake, available under MIT-LICENSE
248
+ # Copyright (c) 2003, 2004 Jim Weirich
249
+ def terminal_width
250
+ if ENV['THOR_COLUMNS']
251
+ result = ENV['THOR_COLUMNS'].to_i
252
+ else
253
+ result = unix? ? dynamic_width : 80
254
+ end
255
+ (result < 10) ? 80 : result
256
+ rescue
257
+ 80
258
+ end
259
+
146
260
  # Called if something goes wrong during the execution. This is used by Thor
147
- # internally and should not be used inside your scripts. If someone went
261
+ # internally and should not be used inside your scripts. If something went
148
262
  # wrong, you can always raise an exception. If you raise a Thor::Error, it
149
263
  # will be rescued and wrapped in the method below.
150
264
  #
151
265
  def error(statement)
152
- $stderr.puts statement
266
+ stderr.puts statement
153
267
  end
154
268
 
155
269
  # Apply color to the given string with optional bold. Disabled in the
156
270
  # Thor::Shell::Basic class.
157
271
  #
158
- def set_color(string, color, bold=false) #:nodoc:
272
+ def set_color(string, *args) #:nodoc:
159
273
  string
160
274
  end
161
275
 
162
- protected
276
+ protected
163
277
 
164
- def is?(value) #:nodoc:
165
- value = value.to_s
278
+ def lookup_color(color)
279
+ return color unless color.is_a?(Symbol)
280
+ self.class.const_get(color.to_s.upcase)
281
+ end
166
282
 
167
- if value.size == 1
168
- /\A#{value}\z/i
169
- else
170
- /\A(#{value}|#{value[0,1]})\z/i
171
- end
283
+ def stdout
284
+ $stdout
285
+ end
286
+
287
+ def stdin
288
+ $stdin
289
+ end
290
+
291
+ def stderr
292
+ $stderr
293
+ end
294
+
295
+ def is?(value) #:nodoc:
296
+ value = value.to_s
297
+
298
+ if value.size == 1
299
+ /\A#{value}\z/i
300
+ else
301
+ /\A(#{value}|#{value[0,1]})\z/i
172
302
  end
303
+ end
173
304
 
174
- def file_collision_help #:nodoc:
305
+ def file_collision_help #:nodoc:
175
306
  <<HELP
176
307
  Y - yes, overwrite
177
308
  n - no, do not overwrite
@@ -180,59 +311,78 @@ q - quit, abort
180
311
  d - diff, show the differences between the old and the new
181
312
  h - help, show this help
182
313
  HELP
183
- end
314
+ end
184
315
 
185
- def show_diff(destination, content) #:nodoc:
186
- diff_cmd = ENV['THOR_DIFF'] || ENV['RAILS_DIFF'] || 'diff -u'
316
+ def show_diff(destination, content) #:nodoc:
317
+ diff_cmd = ENV['THOR_DIFF'] || ENV['RAILS_DIFF'] || 'diff -u'
187
318
 
188
- Tempfile.open(File.basename(destination), File.dirname(destination)) do |temp|
189
- temp.write content
190
- temp.rewind
191
- system %(#{diff_cmd} "#{destination}" "#{temp.path}")
192
- end
319
+ Tempfile.open(File.basename(destination), File.dirname(destination)) do |temp|
320
+ temp.write content
321
+ temp.rewind
322
+ system %(#{diff_cmd} "#{destination}" "#{temp.path}")
193
323
  end
324
+ end
194
325
 
195
- def quiet? #:nodoc:
196
- base && base.options[:quiet]
197
- end
326
+ def quiet? #:nodoc:
327
+ mute? || (base && base.options[:quiet])
328
+ end
329
+
330
+ # Calculate the dynamic width of the terminal
331
+ def dynamic_width
332
+ @dynamic_width ||= (dynamic_width_stty.nonzero? || dynamic_width_tput)
333
+ end
334
+
335
+ def dynamic_width_stty
336
+ %x{stty size 2>/dev/null}.split[1].to_i
337
+ end
198
338
 
199
- # This code was copied from Rake, available under MIT-LICENSE
200
- # Copyright (c) 2003, 2004 Jim Weirich
201
- def terminal_width
202
- if ENV['THOR_COLUMNS']
203
- result = ENV['THOR_COLUMNS'].to_i
339
+ def dynamic_width_tput
340
+ %x{tput cols 2>/dev/null}.to_i
341
+ end
342
+
343
+ def unix?
344
+ RUBY_PLATFORM =~ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris|irix|hpux)/i
345
+ end
346
+
347
+ def truncate(string, width)
348
+ as_unicode do
349
+ chars = string.chars.to_a
350
+ if chars.length <= width
351
+ chars.join
204
352
  else
205
- result = unix? ? dynamic_width : 80
353
+ ( chars[0, width-3].join ) + "..."
206
354
  end
207
- (result < 10) ? 80 : result
208
- rescue
209
- 80
210
- end
211
-
212
- # Calculate the dynamic width of the terminal
213
- def dynamic_width
214
- @dynamic_width ||= (dynamic_width_stty.nonzero? || dynamic_width_tput)
215
355
  end
356
+ end
216
357
 
217
- def dynamic_width_stty
218
- %x{stty size 2>/dev/null}.split[1].to_i
358
+ if "".respond_to?(:encode)
359
+ def as_unicode
360
+ yield
219
361
  end
220
-
221
- def dynamic_width_tput
222
- %x{tput cols 2>/dev/null}.to_i
362
+ else
363
+ def as_unicode
364
+ old, $KCODE = $KCODE, "U"
365
+ yield
366
+ ensure
367
+ $KCODE = old
223
368
  end
369
+ end
224
370
 
225
- def unix?
226
- RUBY_PLATFORM =~ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris|irix|hpux)/i
227
- end
371
+ def ask_simply(statement, color=nil)
372
+ say("#{statement} ", color)
373
+ stdin.gets.strip
374
+ end
228
375
 
229
- def truncate(string, width)
230
- if string.length <= width
231
- string
232
- else
233
- ( string[0, width-3] || "" ) + "..."
234
- end
376
+ def ask_filtered(statement, answer_set, *args)
377
+ correct_answer = nil
378
+ until correct_answer
379
+ answer = ask_simply("#{statement} #{answer_set.inspect}", *args)
380
+ correct_answer = answer_set.include?(answer) ? answer : nil
381
+ answers = answer_set.map(&:inspect).join(", ")
382
+ say("Your response must be one of: [#{answers}]. Please try again.") unless correct_answer
235
383
  end
384
+ correct_answer
385
+ end
236
386
 
237
387
  end
238
388
  end