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.
- data/lib/engineyard-serverside/paths.rb +0 -1
- data/lib/engineyard-serverside/version.rb +1 -1
- data/lib/vendor/thor/{LICENSE → LICENSE.md} +2 -2
- data/lib/vendor/thor/README.md +28 -0
- data/lib/vendor/thor/lib/thor.rb +183 -48
- data/lib/vendor/thor/lib/thor/actions.rb +66 -23
- data/lib/vendor/thor/lib/thor/actions/create_file.rb +5 -3
- data/lib/vendor/thor/lib/thor/actions/create_link.rb +57 -0
- data/lib/vendor/thor/lib/thor/actions/directory.rb +14 -7
- data/lib/vendor/thor/lib/thor/actions/empty_directory.rb +24 -5
- data/lib/vendor/thor/lib/thor/actions/file_manipulation.rb +106 -21
- data/lib/vendor/thor/lib/thor/actions/inject_into_file.rb +15 -10
- data/lib/vendor/thor/lib/thor/base.rb +144 -43
- data/lib/vendor/thor/lib/thor/core_ext/dir_escape.rb +0 -0
- data/lib/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +1 -1
- data/lib/vendor/thor/lib/thor/error.rb +6 -1
- data/lib/vendor/thor/lib/thor/group.rb +41 -27
- data/lib/vendor/thor/lib/thor/invocation.rb +48 -58
- data/lib/vendor/thor/lib/thor/parser/argument.rb +29 -22
- data/lib/vendor/thor/lib/thor/parser/arguments.rb +26 -5
- data/lib/vendor/thor/lib/thor/parser/option.rb +42 -49
- data/lib/vendor/thor/lib/thor/parser/options.rb +39 -30
- data/lib/vendor/thor/lib/thor/rake_compat.rb +13 -8
- data/lib/vendor/thor/lib/thor/runner.rb +27 -20
- data/lib/vendor/thor/lib/thor/shell.rb +10 -5
- data/lib/vendor/thor/lib/thor/shell/basic.rb +228 -78
- data/lib/vendor/thor/lib/thor/shell/color.rb +40 -4
- data/lib/vendor/thor/lib/thor/shell/html.rb +123 -0
- data/lib/vendor/thor/lib/thor/task.rb +83 -53
- data/lib/vendor/thor/lib/thor/util.rb +57 -21
- data/lib/vendor/thor/lib/thor/version.rb +1 -1
- data/lib/vendor/thor/thor.gemspec +21 -115
- metadata +109 -217
- data/lib/vendor/thor/CHANGELOG.rdoc +0 -89
- data/lib/vendor/thor/README.rdoc +0 -297
- 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
|
-
|
33
|
-
|
34
|
-
alias
|
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(*
|
37
|
-
task =
|
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,
|
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
|
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
|
-
|
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
|
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
|
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 =~ /^
|
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
|
-
|
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,
|
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
|
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
|
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
|
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
|
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
|
-
#
|
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
|
-
|
26
|
-
|
27
|
-
|
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
|
39
|
-
|
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
|
-
|
69
|
+
stdout.puts(spaces + message)
|
43
70
|
else
|
44
|
-
|
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
|
-
|
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
|
-
#
|
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(
|
87
|
-
return if
|
134
|
+
def print_table(array, options={})
|
135
|
+
return if array.empty?
|
88
136
|
|
89
|
-
formats,
|
137
|
+
formats, indent, colwidth = [], options[:indent].to_i, options[:colwidth]
|
90
138
|
options[:truncate] = terminal_width if options[:truncate] == true
|
91
139
|
|
92
|
-
|
93
|
-
|
94
|
-
|
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, " " *
|
158
|
+
formats[0] = formats[0].insert(0, " " * indent)
|
98
159
|
formats << "%s"
|
99
160
|
|
100
|
-
|
161
|
+
array.each do |row|
|
101
162
|
sentence = ""
|
102
163
|
|
103
|
-
row.each_with_index do |column,
|
104
|
-
|
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
|
-
|
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
|
-
#
|
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
|
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
|
-
|
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,
|
272
|
+
def set_color(string, *args) #:nodoc:
|
159
273
|
string
|
160
274
|
end
|
161
275
|
|
162
|
-
|
276
|
+
protected
|
163
277
|
|
164
|
-
|
165
|
-
|
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
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
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
|
-
|
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
|
-
|
314
|
+
end
|
184
315
|
|
185
|
-
|
186
|
-
|
316
|
+
def show_diff(destination, content) #:nodoc:
|
317
|
+
diff_cmd = ENV['THOR_DIFF'] || ENV['RAILS_DIFF'] || 'diff -u'
|
187
318
|
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
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
|
-
|
196
|
-
|
197
|
-
|
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
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
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
|
-
|
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
|
-
|
218
|
-
|
358
|
+
if "".respond_to?(:encode)
|
359
|
+
def as_unicode
|
360
|
+
yield
|
219
361
|
end
|
220
|
-
|
221
|
-
def
|
222
|
-
|
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
|
-
|
226
|
-
|
227
|
-
|
371
|
+
def ask_simply(statement, color=nil)
|
372
|
+
say("#{statement} ", color)
|
373
|
+
stdin.gets.strip
|
374
|
+
end
|
228
375
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
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
|