Class: Thor::Shell::Basic
- Inherits:
-
Object
- Object
- Thor::Shell::Basic
- Defined in:
- lib/thor/shell/basic.rb
Constant Summary collapse
- DEFAULT_TERMINAL_WIDTH =
80
Instance Attribute Summary collapse
-
#base ⇒ Object
Returns the value of attribute base.
-
#padding ⇒ Object
Returns the value of attribute padding.
Instance Method Summary collapse
- #as_unicode ⇒ Object protected
-
#ask(statement, *args) ⇒ Object
Asks something to the user and receives a response.
- #ask_filtered(statement, color, options) ⇒ Object protected
- #ask_simply(statement, color, options) ⇒ Object protected
- #can_display_colors? ⇒ Boolean protected
-
#dynamic_width ⇒ Object
protected
Calculate the dynamic width of the terminal.
- #dynamic_width_stty ⇒ Object protected
- #dynamic_width_tput ⇒ Object protected
-
#error(statement) ⇒ Object
Called if something goes wrong during the execution.
-
#file_collision(destination) ⇒ Object
Deals with file collision and returns true if the file should be overwritten and false otherwise.
-
#file_collision_help ⇒ Object
protected
:nodoc:.
-
#indent(count = 1) ⇒ Object
Sets the output padding while executing a block and resets it.
-
#initialize ⇒ Basic
constructor
Initialize base, mute and padding to nil.
-
#is?(value) ⇒ Boolean
protected
:nodoc:.
- #lookup_color(color) ⇒ Object protected
-
#mute ⇒ Object
Mute everything that’s inside given block.
-
#mute? ⇒ Boolean
Check if base is muted.
-
#no?(statement, color = nil) ⇒ Boolean
Make a question the to user and returns true if the user replies “n” or “no”.
- #prepare_message(message, *color) ⇒ Object protected
-
#print_in_columns(array) ⇒ Object
Prints values in columns.
-
#print_table(array, options = {}) ⇒ Object
Prints a table.
-
#print_wrapped(message, options = {}) ⇒ Object
Prints a long string, word-wrapping the text to the current width of the terminal display.
-
#quiet? ⇒ Boolean
protected
:nodoc:.
-
#say(message = "", color = nil, force_new_line = (message.to_s !~ /( |\t)\Z/)) ⇒ Object
Say (print) something to the user.
-
#say_status(status, message, log_status = true) ⇒ Object
Say a status with the given color and appends the message.
-
#set_color(string) ⇒ Object
Apply color to the given string with optional bold.
-
#show_diff(destination, content) ⇒ Object
protected
:nodoc:.
- #stderr ⇒ Object protected
- #stdout ⇒ Object protected
-
#terminal_width ⇒ Object
This code was copied from Rake, available under MIT-LICENSE Copyright © 2003, 2004 Jim Weirich.
- #truncate(string, width) ⇒ Object protected
- #unix? ⇒ Boolean protected
-
#yes?(statement, color = nil) ⇒ Boolean
Make a question the to user and returns true if the user replies “y” or “yes”.
Constructor Details
#initialize ⇒ Basic
Initialize base, mute and padding to nil.
11 12 13 14 15 16 |
# File 'lib/thor/shell/basic.rb', line 11 def initialize #:nodoc: @base = nil @mute = false @padding = 0 @always_force = false end |
Instance Attribute Details
#base ⇒ Object
Returns the value of attribute base.
6 7 8 |
# File 'lib/thor/shell/basic.rb', line 6 def base @base end |
#padding ⇒ Object
Returns the value of attribute padding.
7 8 9 |
# File 'lib/thor/shell/basic.rb', line 7 def padding @padding end |
Instance Method Details
#as_unicode ⇒ Object (protected)
396 397 398 |
# File 'lib/thor/shell/basic.rb', line 396 def as_unicode yield end |
#ask(statement, *args) ⇒ Object
Asks something to the user and receives a response.
If asked to limit the correct responses, you can pass in an array of acceptable answers. If one of those is not supplied, they will be shown a message stating that one of those answers must be given and re-asked the question.
If asking for sensitive information, the :echo option can be set to false to mask user input from $stdin.
If the required input is a path, then set the path option to true. This will enable tab completion for file paths relative to the current working directory on systems that support Readline.
Example
ask(“What is your name?”)
ask(“What is your favorite Neopolitan flavor?”, :limited_to => [“strawberry”, “chocolate”, “vanilla”])
ask(“What is your password?”, :echo => false)
ask(“Where should the file be saved?”, :path => true)
72 73 74 75 76 77 78 79 80 81 |
# File 'lib/thor/shell/basic.rb', line 72 def ask(statement, *args) = args.last.is_a?(Hash) ? args.pop : {} color = args.first if [:limited_to] ask_filtered(statement, color, ) else ask_simply(statement, color, ) end end |
#ask_filtered(statement, color, options) ⇒ Object (protected)
426 427 428 429 430 431 432 433 434 435 436 |
# File 'lib/thor/shell/basic.rb', line 426 def ask_filtered(statement, color, ) answer_set = [:limited_to] correct_answer = nil until correct_answer answers = answer_set.join(", ") answer = ask_simply("#{statement} [#{answers}]", color, ) correct_answer = answer_set.include?(answer) ? answer : nil say("Your response must be one of: [#{answers}]. Please try again.") unless correct_answer end correct_answer end |
#ask_simply(statement, color, options) ⇒ Object (protected)
409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 |
# File 'lib/thor/shell/basic.rb', line 409 def ask_simply(statement, color, ) default = [:default] = [statement, ("(#{default})" if default), nil].uniq.join(" ") = (, *color) result = Thor::LineEditor.readline(, ) return unless result result = result.strip if default && result == "" default else result end end |
#can_display_colors? ⇒ Boolean (protected)
314 315 316 |
# File 'lib/thor/shell/basic.rb', line 314 def can_display_colors? false end |
#dynamic_width ⇒ Object (protected)
Calculate the dynamic width of the terminal
368 369 370 |
# File 'lib/thor/shell/basic.rb', line 368 def dynamic_width @dynamic_width ||= (dynamic_width_stty.nonzero? || dynamic_width_tput) end |
#dynamic_width_stty ⇒ Object (protected)
372 373 374 |
# File 'lib/thor/shell/basic.rb', line 372 def dynamic_width_stty `stty size 2>/dev/null`.split[1].to_i end |
#dynamic_width_tput ⇒ Object (protected)
376 377 378 |
# File 'lib/thor/shell/basic.rb', line 376 def dynamic_width_tput `tput cols 2>/dev/null`.to_i end |
#error(statement) ⇒ Object
Called if something goes wrong during the execution. This is used by Thor internally and should not be used inside your scripts. If something went wrong, you can always raise an exception. If you raise a Thor::Error, it will be rescued and wrapped in the method below.
296 297 298 |
# File 'lib/thor/shell/basic.rb', line 296 def error(statement) stderr.puts statement end |
#file_collision(destination) ⇒ Object
Deals with file collision and returns true if the file should be overwritten and false otherwise. If a block is given, it uses the block response as the content for the diff.
Parameters
- destination<String>
-
the destination file to solve conflicts
- block<Proc>
-
an optional block that returns the value to be used in diff
246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 |
# File 'lib/thor/shell/basic.rb', line 246 def file_collision(destination) return true if @always_force = block_given? ? "[Ynaqdh]" : "[Ynaqh]" loop do answer = ask( %[Overwrite #{destination}? (enter "h" for help) #{}], :add_to_history => false ) case answer when nil say "" return true when is?(:yes), is?(:force), "" return true when is?(:no), is?(:skip) return false when is?(:always) return @always_force = true when is?(:quit) say "Aborting..." raise SystemExit when is?(:diff) show_diff(destination, yield) if block_given? say "Retrying..." else say file_collision_help end end end |
#file_collision_help ⇒ Object (protected)
:nodoc:
341 342 343 344 345 346 347 348 349 350 |
# File 'lib/thor/shell/basic.rb', line 341 def file_collision_help #:nodoc: <<-HELP Y - yes, overwrite n - no, do not overwrite a - all, overwrite this and all others q - quit, abort d - diff, show the differences between the old and the new h - help, show this help HELP end |
#indent(count = 1) ⇒ Object
Sets the output padding while executing a block and resets it.
41 42 43 44 45 46 |
# File 'lib/thor/shell/basic.rb', line 41 def indent(count = 1) orig_padding = padding self.padding = padding + count yield self.padding = orig_padding end |
#is?(value) ⇒ Boolean (protected)
:nodoc:
331 332 333 334 335 336 337 338 339 |
# File 'lib/thor/shell/basic.rb', line 331 def is?(value) #:nodoc: value = value.to_s if value.size == 1 /\A#{value}\z/i else /\A(#{value}|#{value[0, 1]})\z/i end end |
#lookup_color(color) ⇒ Object (protected)
318 319 320 321 |
# File 'lib/thor/shell/basic.rb', line 318 def lookup_color(color) return color unless color.is_a?(Symbol) self.class.const_get(color.to_s.upcase) end |
#mute ⇒ Object
Mute everything that’s inside given block
20 21 22 23 24 25 |
# File 'lib/thor/shell/basic.rb', line 20 def mute @mute = true yield ensure @mute = false end |
#mute? ⇒ Boolean
Check if base is muted
29 30 31 |
# File 'lib/thor/shell/basic.rb', line 29 def mute? @mute end |
#no?(statement, color = nil) ⇒ Boolean
Make a question the to user and returns true if the user replies “n” or “no”.
128 129 130 |
# File 'lib/thor/shell/basic.rb', line 128 def no?(statement, color = nil) !!(ask(statement, color, :add_to_history => false) =~ is?(:no)) end |
#prepare_message(message, *color) ⇒ Object (protected)
309 310 311 312 |
# File 'lib/thor/shell/basic.rb', line 309 def (, *color) spaces = " " * padding spaces + set_color(.to_s, *color) end |
#print_in_columns(array) ⇒ Object
Prints values in columns
Parameters
Array[String, String, …]
137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/thor/shell/basic.rb', line 137 def print_in_columns(array) return if array.empty? colwidth = (array.map { |el| el.to_s.size }.max || 0) + 2 array.each_with_index do |value, index| # Don't output trailing spaces when printing the last column if ((((index + 1) % (terminal_width / colwidth))).zero? && !index.zero?) || index + 1 == array.length stdout.puts value else stdout.printf("%-#{colwidth}s", value) end end end |
#print_table(array, options = {}) ⇒ Object
Prints a table.
Parameters
Array[Array[String, String, …]]
Options
- indent<Integer>
-
Indent the first column by indent value.
- colwidth<Integer>
-
Force the first column to colwidth spaces wide.
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
# File 'lib/thor/shell/basic.rb', line 159 def print_table(array, = {}) # rubocop:disable MethodLength return if array.empty? formats = [] indent = [:indent].to_i colwidth = [:colwidth] [:truncate] = terminal_width if [:truncate] == true formats << "%-#{colwidth + 2}s".dup if colwidth start = colwidth ? 1 : 0 colcount = array.max { |a, b| a.size <=> b.size }.size maximas = [] start.upto(colcount - 1) do |index| maxima = array.map { |row| row[index] ? row[index].to_s.size : 0 }.max maximas << maxima formats << if index == colcount - 1 # Don't output 2 trailing spaces when printing the last column "%-s".dup else "%-#{maxima + 2}s".dup end end formats[0] = formats[0].insert(0, " " * indent) formats << "%s" array.each do |row| sentence = "".dup row.each_with_index do |column, index| maxima = maximas[index] f = if column.is_a?(Numeric) if index == row.size - 1 # Don't output 2 trailing spaces when printing the last column "%#{maxima}s" else "%#{maxima}s " end else formats[index] end sentence << f % column.to_s end sentence = truncate(sentence, [:truncate]) if [:truncate] stdout.puts sentence end end |
#print_wrapped(message, options = {}) ⇒ Object
Prints a long string, word-wrapping the text to the current width of the terminal display. Ideal for printing heredocs.
Parameters
String
Options
- indent<Integer>
-
Indent each line of the printed paragraph by indent value.
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 |
# File 'lib/thor/shell/basic.rb', line 221 def print_wrapped(, = {}) indent = [:indent] || 0 width = terminal_width - indent paras = .split("\n\n") paras.map! do |unwrapped| unwrapped.strip.tr("\n", " ").squeeze(" ").gsub(/.{1,#{width}}(?:\s|\Z)/) { ($& + 5.chr).gsub(/\n\005/, "\n").gsub(/\005/, "\n") } end paras.each do |para| para.split("\n").each do |line| stdout.puts line.insert(0, " " * indent) end stdout.puts unless para == paras.last end end |
#quiet? ⇒ Boolean (protected)
:nodoc:
363 364 365 |
# File 'lib/thor/shell/basic.rb', line 363 def quiet? #:nodoc: mute? || (base && base.[:quiet]) end |
#say(message = "", color = nil, force_new_line = (message.to_s !~ /( |\t)\Z/)) ⇒ Object
Say (print) something to the user. If the sentence ends with a whitespace or tab character, a new line is not appended (print + flush). Otherwise are passed straight to puts (behavior got from Highline).
Example
say(“I know you knew that.”)
90 91 92 93 94 95 96 |
# File 'lib/thor/shell/basic.rb', line 90 def say( = "", color = nil, force_new_line = (.to_s !~ /( |\t)\Z/)) buffer = (, *color) buffer << "\n" if force_new_line && !.to_s.end_with?("\n") stdout.print(buffer) stdout.flush end |
#say_status(status, message, log_status = true) ⇒ Object
Say a status with the given color and appends the message. Since this method is used frequently by actions, it allows nil or false to be given in log_status, avoiding the message from being shown. If a Symbol is given in log_status, it’s used as the color.
103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/thor/shell/basic.rb', line 103 def say_status(status, , log_status = true) return if quiet? || log_status == false spaces = " " * (padding + 1) color = log_status.is_a?(Symbol) ? log_status : :green status = status.to_s.rjust(12) status = set_color status, color, true if color buffer = "#{status}#{spaces}#{}" buffer = "#{buffer}\n" unless buffer.end_with?("\n") stdout.print(buffer) stdout.flush end |
#set_color(string) ⇒ Object
Apply color to the given string with optional bold. Disabled in the Thor::Shell::Basic class.
303 304 305 |
# File 'lib/thor/shell/basic.rb', line 303 def set_color(string, *) #:nodoc: string end |
#show_diff(destination, content) ⇒ Object (protected)
:nodoc:
352 353 354 355 356 357 358 359 360 361 |
# File 'lib/thor/shell/basic.rb', line 352 def show_diff(destination, content) #:nodoc: diff_cmd = ENV["THOR_DIFF"] || ENV["RAILS_DIFF"] || "diff -u" require "tempfile" Tempfile.open(File.basename(destination), File.dirname(destination)) do |temp| temp.write content temp.rewind system %(#{diff_cmd} "#{destination}" "#{temp.path}") end end |
#stderr ⇒ Object (protected)
327 328 329 |
# File 'lib/thor/shell/basic.rb', line 327 def stderr $stderr end |
#stdout ⇒ Object (protected)
323 324 325 |
# File 'lib/thor/shell/basic.rb', line 323 def stdout $stdout end |
#terminal_width ⇒ Object
This code was copied from Rake, available under MIT-LICENSE Copyright © 2003, 2004 Jim Weirich
280 281 282 283 284 285 286 287 288 289 |
# File 'lib/thor/shell/basic.rb', line 280 def terminal_width result = if ENV["THOR_COLUMNS"] ENV["THOR_COLUMNS"].to_i else unix? ? dynamic_width : DEFAULT_TERMINAL_WIDTH end result < 10 ? DEFAULT_TERMINAL_WIDTH : result rescue DEFAULT_TERMINAL_WIDTH end |
#truncate(string, width) ⇒ Object (protected)
384 385 386 387 388 389 390 391 392 393 |
# File 'lib/thor/shell/basic.rb', line 384 def truncate(string, width) as_unicode do chars = string.chars.to_a if chars.length <= width chars.join else chars[0, width - 3].join + "..." end end end |
#unix? ⇒ Boolean (protected)
380 381 382 |
# File 'lib/thor/shell/basic.rb', line 380 def unix? RUBY_PLATFORM =~ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris|irix|hpux)/i end |
#yes?(statement, color = nil) ⇒ Boolean
Make a question the to user and returns true if the user replies “y” or “yes”.
121 122 123 |
# File 'lib/thor/shell/basic.rb', line 121 def yes?(statement, color = nil) !!(ask(statement, color, :add_to_history => false) =~ is?(:yes)) end |