diff options
Diffstat (limited to 'lib/bundler/vendor/thor/shell/basic.rb')
-rw-r--r-- | lib/bundler/vendor/thor/shell/basic.rb | 251 |
1 files changed, 169 insertions, 82 deletions
diff --git a/lib/bundler/vendor/thor/shell/basic.rb b/lib/bundler/vendor/thor/shell/basic.rb index c8411d3d..3c5904b2 100644 --- a/lib/bundler/vendor/thor/shell/basic.rb +++ b/lib/bundler/vendor/thor/shell/basic.rb @@ -3,12 +3,13 @@ require 'tempfile' class Thor module Shell class Basic - attr_accessor :base, :padding + attr_accessor :base + attr_reader :padding - # Initialize base and padding to nil. + # Initialize base, mute and padding to nil. # def initialize #:nodoc: - @base, @padding = nil, 0 + @base, @mute, @padding = nil, false, 0 end # Mute everything that's inside given block @@ -32,14 +33,22 @@ class Thor @padding = [0, value].max end - # Ask something to the user and receives a response. + # 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. # # ==== Example # ask("What is your name?") # - def ask(statement, color=nil) - say("#{statement} ", color) - stdin.gets.strip + # ask("What is your favorite Neopolitan flavor?", :limited_to => ["strawberry", "chocolate", "vanilla"]) + # + def ask(statement, *args) + options = args.last.is_a?(Hash) ? args.pop : {} + + options[:limited_to] ? ask_filtered(statement, options[:limited_to], *args) : ask_simply(statement, *args) end # Say (print) something to the user. If the sentence ends with a whitespace @@ -51,7 +60,8 @@ class Thor # def say(message="", color=nil, force_new_line=(message.to_s !~ /( |\t)$/)) message = message.to_s - message = set_color(message, color) if color + + message = set_color(message, *color) if color spaces = " " * padding @@ -94,37 +104,77 @@ class Thor !yes?(statement, color) end + # Prints values in columns + # + # ==== Parameters + # Array[String, String, ...] + # + 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 + # Prints a table. # # ==== Parameters # Array[Array[String, String, ...]] # # ==== Options - # ident<Integer>:: Indent the first column by ident value. + # indent<Integer>:: Indent the first column by indent value. # colwidth<Integer>:: Force the first column to colwidth spaces wide. # - def print_table(table, options={}) - return if table.empty? + def print_table(array, options={}) + return if array.empty? - formats, ident, colwidth = [], options[:ident].to_i, options[:colwidth] + formats, indent, colwidth = [], options[:indent].to_i, options[:colwidth] options[:truncate] = terminal_width if options[:truncate] == true formats << "%-#{colwidth + 2}s" if colwidth start = colwidth ? 1 : 0 - start.upto(table.first.length - 2) do |i| - maxima ||= table.max{|a,b| a[i].size <=> b[i].size }[i].size - formats << "%-#{maxima + 2}s" + 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 + if index == colcount - 1 + # Don't output 2 trailing spaces when printing the last column + formats << "%-s" + else + formats << "%-#{maxima + 2}s" + end end - formats[0] = formats[0].insert(0, " " * ident) + formats[0] = formats[0].insert(0, " " * indent) formats << "%s" - table.each do |row| + array.each do |row| sentence = "" - row.each_with_index do |column, i| - sentence << formats[i] % column.to_s + row.each_with_index do |column, index| + maxima = maximas[index] + + if column.is_a?(Numeric) + if index == row.size - 1 + # Don't output 2 trailing spaces when printing the last column + f = "%#{maxima}s" + else + f = "%#{maxima}s " + end + else + f = formats[index] + end + sentence << f % column.to_s end sentence = truncate(sentence, options[:truncate]) if options[:truncate] @@ -139,11 +189,11 @@ class Thor # String # # ==== Options - # ident<Integer>:: Indent each line of the printed paragraph by ident value. + # indent<Integer>:: Indent each line of the printed paragraph by indent value. # def print_wrapped(message, options={}) - ident = options[:ident] || 0 - width = terminal_width - ident + indent = options[:indent] || 0 + width = terminal_width - indent paras = message.split("\n\n") paras.map! do |unwrapped| @@ -154,14 +204,14 @@ class Thor paras.each do |para| para.split("\n").each do |line| - stdout.puts line.insert(0, " " * ident) + stdout.puts line.insert(0, " " * indent) end stdout.puts unless para == paras.last end end # Deals with file collision and returns true if the file should be - # overwriten and false otherwise. If a block is given, it uses the block + # overwritten and false otherwise. If a block is given, it uses the block # response as the content for the diff. # # ==== Parameters @@ -194,6 +244,19 @@ class Thor end end + # This code was copied from Rake, available under MIT-LICENSE + # Copyright (c) 2003, 2004 Jim Weirich + def terminal_width + if ENV['THOR_COLUMNS'] + result = ENV['THOR_COLUMNS'].to_i + else + result = unix? ? dynamic_width : 80 + end + (result < 10) ? 80 : result + rescue + 80 + end + # 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 @@ -206,35 +269,40 @@ class Thor # Apply color to the given string with optional bold. Disabled in the # Thor::Shell::Basic class. # - def set_color(string, color, bold=false) #:nodoc: + def set_color(string, *args) #:nodoc: string end - protected + protected - def stdout - $stdout - end + def lookup_color(color) + return color unless color.is_a?(Symbol) + self.class.const_get(color.to_s.upcase) + end - def stdin - $stdin - end + def stdout + $stdout + end - def stderr - $stderr - end + def stdin + $stdin + end + + def stderr + $stderr + end - def is?(value) #:nodoc: - value = value.to_s + 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 + if value.size == 1 + /\A#{value}\z/i + else + /\A(#{value}|#{value[0,1]})\z/i end + end - def file_collision_help #:nodoc: + def file_collision_help #:nodoc: <<HELP Y - yes, overwrite n - no, do not overwrite @@ -243,59 +311,78 @@ q - quit, abort d - diff, show the differences between the old and the new h - help, show this help HELP - end + end - def show_diff(destination, content) #:nodoc: - diff_cmd = ENV['THOR_DIFF'] || ENV['RAILS_DIFF'] || 'diff -u' + def show_diff(destination, content) #:nodoc: + diff_cmd = ENV['THOR_DIFF'] || ENV['RAILS_DIFF'] || 'diff -u' - Tempfile.open(File.basename(destination), File.dirname(destination)) do |temp| - temp.write content - temp.rewind - system %(#{diff_cmd} "#{destination}" "#{temp.path}") - end + Tempfile.open(File.basename(destination), File.dirname(destination)) do |temp| + temp.write content + temp.rewind + system %(#{diff_cmd} "#{destination}" "#{temp.path}") end + end - def quiet? #:nodoc: - mute? || (base && base.options[:quiet]) - end + def quiet? #:nodoc: + mute? || (base && base.options[:quiet]) + end + + # Calculate the dynamic width of the terminal + def dynamic_width + @dynamic_width ||= (dynamic_width_stty.nonzero? || dynamic_width_tput) + end + + def dynamic_width_stty + %x{stty size 2>/dev/null}.split[1].to_i + end - # This code was copied from Rake, available under MIT-LICENSE - # Copyright (c) 2003, 2004 Jim Weirich - def terminal_width - if ENV['THOR_COLUMNS'] - result = ENV['THOR_COLUMNS'].to_i + def dynamic_width_tput + %x{tput cols 2>/dev/null}.to_i + end + + def unix? + RUBY_PLATFORM =~ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris|irix|hpux)/i + end + + def truncate(string, width) + as_unicode do + chars = string.chars.to_a + if chars.length <= width + chars.join else - result = unix? ? dynamic_width : 80 + ( chars[0, width-3].join ) + "..." end - (result < 10) ? 80 : result - rescue - 80 - end - - # Calculate the dynamic width of the terminal - def dynamic_width - @dynamic_width ||= (dynamic_width_stty.nonzero? || dynamic_width_tput) end + end - def dynamic_width_stty - %x{stty size 2>/dev/null}.split[1].to_i + if "".respond_to?(:encode) + def as_unicode + yield end - - def dynamic_width_tput - %x{tput cols 2>/dev/null}.to_i + else + def as_unicode + old, $KCODE = $KCODE, "U" + yield + ensure + $KCODE = old end + end - def unix? - RUBY_PLATFORM =~ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris|irix|hpux)/i - end + def ask_simply(statement, color=nil) + say("#{statement} ", color) + stdin.gets.strip + end - def truncate(string, width) - if string.length <= width - string - else - ( string[0, width-3] || "" ) + "..." - end + def ask_filtered(statement, answer_set, *args) + correct_answer = nil + until correct_answer + answer = ask_simply("#{statement} #{answer_set.inspect}", *args) + correct_answer = answer_set.include?(answer) ? answer : nil + answers = answer_set.map(&:inspect).join(", ") + say("Your response must be one of: [#{answers}]. Please try again.") unless correct_answer end + correct_answer + end end end |