thor 0.18.1 → 0.19.0
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.
Potentially problematic release.
This version of thor might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/README.md +13 -7
- data/Thorfile +4 -5
- data/bin/thor +1 -1
- data/lib/thor.rb +78 -67
- data/lib/thor/actions.rb +57 -56
- data/lib/thor/actions/create_file.rb +33 -35
- data/lib/thor/actions/create_link.rb +2 -3
- data/lib/thor/actions/directory.rb +37 -38
- data/lib/thor/actions/empty_directory.rb +67 -69
- data/lib/thor/actions/file_manipulation.rb +17 -15
- data/lib/thor/actions/inject_into_file.rb +27 -29
- data/lib/thor/base.rb +193 -189
- data/lib/thor/command.rb +20 -23
- data/lib/thor/core_ext/hash_with_indifferent_access.rb +21 -24
- data/lib/thor/core_ext/io_binary_read.rb +2 -4
- data/lib/thor/core_ext/ordered_hash.rb +9 -11
- data/lib/thor/error.rb +5 -1
- data/lib/thor/group.rb +53 -54
- data/lib/thor/invocation.rb +44 -38
- data/lib/thor/line_editor.rb +17 -0
- data/lib/thor/line_editor/basic.rb +35 -0
- data/lib/thor/line_editor/readline.rb +88 -0
- data/lib/thor/parser.rb +4 -4
- data/lib/thor/parser/argument.rb +28 -29
- data/lib/thor/parser/arguments.rb +102 -98
- data/lib/thor/parser/option.rb +26 -22
- data/lib/thor/parser/options.rb +86 -86
- data/lib/thor/rake_compat.rb +9 -10
- data/lib/thor/runner.rb +141 -141
- data/lib/thor/shell.rb +27 -34
- data/lib/thor/shell/basic.rb +91 -63
- data/lib/thor/shell/color.rb +44 -43
- data/lib/thor/shell/html.rb +59 -60
- data/lib/thor/util.rb +24 -27
- data/lib/thor/version.rb +1 -1
- data/spec/actions/create_file_spec.rb +25 -27
- data/spec/actions/create_link_spec.rb +19 -18
- data/spec/actions/directory_spec.rb +31 -31
- data/spec/actions/empty_directory_spec.rb +18 -18
- data/spec/actions/file_manipulation_spec.rb +38 -28
- data/spec/actions/inject_into_file_spec.rb +13 -13
- data/spec/actions_spec.rb +43 -43
- data/spec/base_spec.rb +45 -38
- data/spec/command_spec.rb +13 -14
- data/spec/core_ext/hash_with_indifferent_access_spec.rb +19 -19
- data/spec/core_ext/ordered_hash_spec.rb +6 -6
- data/spec/exit_condition_spec.rb +4 -4
- data/spec/fixtures/invoke.thor +19 -0
- data/spec/fixtures/script.thor +1 -1
- data/spec/group_spec.rb +30 -24
- data/spec/helper.rb +28 -15
- data/spec/invocation_spec.rb +39 -19
- data/spec/line_editor/basic_spec.rb +28 -0
- data/spec/line_editor/readline_spec.rb +69 -0
- data/spec/line_editor_spec.rb +43 -0
- data/spec/parser/argument_spec.rb +12 -12
- data/spec/parser/arguments_spec.rb +11 -11
- data/spec/parser/option_spec.rb +33 -25
- data/spec/parser/options_spec.rb +66 -52
- data/spec/quality_spec.rb +75 -0
- data/spec/rake_compat_spec.rb +10 -10
- data/spec/register_spec.rb +60 -30
- data/spec/runner_spec.rb +67 -62
- data/spec/sandbox/application.rb +2 -0
- data/spec/sandbox/app{1}/README +3 -0
- data/spec/sandbox/bundle/execute.rb +6 -0
- data/spec/sandbox/bundle/main.thor +1 -0
- data/spec/sandbox/command.thor +10 -0
- data/spec/sandbox/doc/%file_name%.rb.tt +1 -0
- data/spec/sandbox/doc/COMMENTER +11 -0
- data/spec/sandbox/doc/README +3 -0
- data/spec/sandbox/doc/block_helper.rb +3 -0
- data/spec/sandbox/doc/config.rb +1 -0
- data/spec/sandbox/doc/config.yaml.tt +1 -0
- data/spec/sandbox/doc/excluding/%file_name%.rb.tt +1 -0
- data/spec/sandbox/enum.thor +10 -0
- data/spec/sandbox/group.thor +128 -0
- data/spec/sandbox/invoke.thor +131 -0
- data/spec/sandbox/path with spaces b/data/spec/sandbox/path with → spaces +0 -0
- data/spec/sandbox/preserve/script.sh +3 -0
- data/spec/sandbox/script.thor +220 -0
- data/spec/sandbox/subcommand.thor +17 -0
- data/spec/shell/basic_spec.rb +107 -86
- data/spec/shell/color_spec.rb +32 -8
- data/spec/shell/html_spec.rb +3 -4
- data/spec/shell_spec.rb +7 -7
- data/spec/subcommand_spec.rb +20 -2
- data/spec/thor_spec.rb +111 -97
- data/spec/util_spec.rb +30 -30
- data/thor.gemspec +14 -14
- metadata +69 -25
    
        data/lib/thor/shell.rb
    CHANGED
    
    | @@ -1,33 +1,32 @@ | |
| 1 | 
            -
            require  | 
| 1 | 
            +
            require "rbconfig"
         | 
| 2 2 |  | 
| 3 3 | 
             
            class Thor
         | 
| 4 4 | 
             
              module Base
         | 
| 5 | 
            -
                 | 
| 6 | 
            -
             | 
| 7 | 
            -
                #
         | 
| 8 | 
            -
                def self.shell
         | 
| 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']))
         | 
| 12 | 
            -
                    Thor::Shell::Basic
         | 
| 13 | 
            -
                  else
         | 
| 14 | 
            -
                    Thor::Shell::Color
         | 
| 15 | 
            -
                  end
         | 
| 16 | 
            -
                end
         | 
| 5 | 
            +
                class << self
         | 
| 6 | 
            +
                  attr_writer :shell
         | 
| 17 7 |  | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 21 | 
            -
                   | 
| 8 | 
            +
                  # Returns the shell used in all Thor classes. If you are in a Unix platform
         | 
| 9 | 
            +
                  # it will use a colored log, otherwise it will use a basic one without color.
         | 
| 10 | 
            +
                  #
         | 
| 11 | 
            +
                  def shell
         | 
| 12 | 
            +
                    @shell ||= if ENV["THOR_SHELL"] && ENV["THOR_SHELL"].size > 0
         | 
| 13 | 
            +
                      Thor::Shell.const_get(ENV["THOR_SHELL"])
         | 
| 14 | 
            +
                    elsif RbConfig::CONFIG["host_os"] =~ /mswin|mingw/ && !ENV["ANSICON"]
         | 
| 15 | 
            +
                      Thor::Shell::Basic
         | 
| 16 | 
            +
                    else
         | 
| 17 | 
            +
                      Thor::Shell::Color
         | 
| 18 | 
            +
                    end
         | 
| 19 | 
            +
                  end
         | 
| 22 20 | 
             
                end
         | 
| 23 21 | 
             
              end
         | 
| 24 22 |  | 
| 25 23 | 
             
              module Shell
         | 
| 26 24 | 
             
                SHELL_DELEGATED_METHODS = [:ask, :error, :set_color, :yes?, :no?, :say, :say_status, :print_in_columns, :print_table, :print_wrapped, :file_collision, :terminal_width]
         | 
| 25 | 
            +
                attr_writer :shell
         | 
| 27 26 |  | 
| 28 | 
            -
                autoload :Basic,  | 
| 29 | 
            -
                autoload :Color,  | 
| 30 | 
            -
                autoload :HTML,   | 
| 27 | 
            +
                autoload :Basic, "thor/shell/basic"
         | 
| 28 | 
            +
                autoload :Color, "thor/shell/color"
         | 
| 29 | 
            +
                autoload :HTML,  "thor/shell/html"
         | 
| 31 30 |  | 
| 32 31 | 
             
                # Add shell to initialize config values.
         | 
| 33 32 | 
             
                #
         | 
| @@ -42,10 +41,10 @@ class Thor | |
| 42 41 | 
             
                #
         | 
| 43 42 | 
             
                #   MyScript.new [1.0], { :foo => :bar }, :shell => Thor::Shell::Basic.new
         | 
| 44 43 | 
             
                #
         | 
| 45 | 
            -
                def initialize(args=[], options={}, config={})
         | 
| 44 | 
            +
                def initialize(args = [], options = {}, config = {})
         | 
| 46 45 | 
             
                  super
         | 
| 47 46 | 
             
                  self.shell = config[:shell]
         | 
| 48 | 
            -
                   | 
| 47 | 
            +
                  shell.base ||= self if shell.respond_to?(:base)
         | 
| 49 48 | 
             
                end
         | 
| 50 49 |  | 
| 51 50 | 
             
                # Holds the shell for the given Thor instance. If no shell is given,
         | 
| @@ -54,11 +53,6 @@ class Thor | |
| 54 53 | 
             
                  @shell ||= Thor::Base.shell.new
         | 
| 55 54 | 
             
                end
         | 
| 56 55 |  | 
| 57 | 
            -
                # Sets the shell for this thor class.
         | 
| 58 | 
            -
                def shell=(shell)
         | 
| 59 | 
            -
                  @shell = shell
         | 
| 60 | 
            -
                end
         | 
| 61 | 
            -
             | 
| 62 56 | 
             
                # Common methods that are delegated to the shell.
         | 
| 63 57 | 
             
                SHELL_DELEGATED_METHODS.each do |method|
         | 
| 64 58 | 
             
                  module_eval <<-METHOD, __FILE__, __LINE__
         | 
| @@ -76,13 +70,12 @@ class Thor | |
| 76 70 | 
             
                  shell.padding -= 1
         | 
| 77 71 | 
             
                end
         | 
| 78 72 |  | 
| 79 | 
            -
             | 
| 80 | 
            -
             | 
| 81 | 
            -
                  # Allow shell to be shared between invocations.
         | 
| 82 | 
            -
                  #
         | 
| 83 | 
            -
                  def _shared_configuration #:nodoc:
         | 
| 84 | 
            -
                    super.merge!(:shell => self.shell)
         | 
| 85 | 
            -
                  end
         | 
| 73 | 
            +
              protected
         | 
| 86 74 |  | 
| 75 | 
            +
                # Allow shell to be shared between invocations.
         | 
| 76 | 
            +
                #
         | 
| 77 | 
            +
                def _shared_configuration #:nodoc:
         | 
| 78 | 
            +
                  super.merge!(:shell => shell)
         | 
| 79 | 
            +
                end
         | 
| 87 80 | 
             
              end
         | 
| 88 81 | 
             
            end
         | 
    
        data/lib/thor/shell/basic.rb
    CHANGED
    
    | @@ -1,15 +1,16 @@ | |
| 1 | 
            -
            require  | 
| 1 | 
            +
            require "tempfile"
         | 
| 2 | 
            +
            require "io/console" if RUBY_VERSION > "1.9.2"
         | 
| 2 3 |  | 
| 3 4 | 
             
            class Thor
         | 
| 4 5 | 
             
              module Shell
         | 
| 5 | 
            -
                class Basic
         | 
| 6 | 
            +
                class Basic # rubocop:disable ClassLength
         | 
| 6 7 | 
             
                  attr_accessor :base
         | 
| 7 8 | 
             
                  attr_reader   :padding
         | 
| 8 9 |  | 
| 9 10 | 
             
                  # Initialize base, mute and padding to nil.
         | 
| 10 11 | 
             
                  #
         | 
| 11 12 | 
             
                  def initialize #:nodoc:
         | 
| 12 | 
            -
                    @base, @mute, @padding = nil, false, 0
         | 
| 13 | 
            +
                    @base, @mute, @padding, @always_force = nil, false, 0, false
         | 
| 13 14 | 
             
                  end
         | 
| 14 15 |  | 
| 15 16 | 
             
                  # Mute everything that's inside given block
         | 
| @@ -23,7 +24,7 @@ class Thor | |
| 23 24 |  | 
| 24 25 | 
             
                  # Check if base is muted
         | 
| 25 26 | 
             
                  #
         | 
| 26 | 
            -
                  def mute?
         | 
| 27 | 
            +
                  def mute? # rubocop:disable TrivialAccessors
         | 
| 27 28 | 
             
                    @mute
         | 
| 28 29 | 
             
                  end
         | 
| 29 30 |  | 
| @@ -40,15 +41,32 @@ class Thor | |
| 40 41 | 
             
                  # they will be shown a message stating that one of those answers
         | 
| 41 42 | 
             
                  # must be given and re-asked the question.
         | 
| 42 43 | 
             
                  #
         | 
| 44 | 
            +
                  # If asking for sensitive information, the :echo option can be set
         | 
| 45 | 
            +
                  # to false to mask user input from $stdin.
         | 
| 46 | 
            +
                  #
         | 
| 47 | 
            +
                  # If the required input is a path, then set the path option to
         | 
| 48 | 
            +
                  # true. This will enable tab completion for file paths relative
         | 
| 49 | 
            +
                  # to the current working directory on systems that support
         | 
| 50 | 
            +
                  # Readline.
         | 
| 51 | 
            +
                  #
         | 
| 43 52 | 
             
                  # ==== Example
         | 
| 44 53 | 
             
                  # ask("What is your name?")
         | 
| 45 54 | 
             
                  #
         | 
| 46 55 | 
             
                  # ask("What is your favorite Neopolitan flavor?", :limited_to => ["strawberry", "chocolate", "vanilla"])
         | 
| 47 56 | 
             
                  #
         | 
| 57 | 
            +
                  # ask("What is your password?", :echo => false)
         | 
| 58 | 
            +
                  #
         | 
| 59 | 
            +
                  # ask("Where should the file be saved?", :path => true)
         | 
| 60 | 
            +
                  #
         | 
| 48 61 | 
             
                  def ask(statement, *args)
         | 
| 49 62 | 
             
                    options = args.last.is_a?(Hash) ? args.pop : {}
         | 
| 63 | 
            +
                    color = args.first
         | 
| 50 64 |  | 
| 51 | 
            -
                     | 
| 65 | 
            +
                    if options[:limited_to]
         | 
| 66 | 
            +
                      ask_filtered(statement, color, options)
         | 
| 67 | 
            +
                    else
         | 
| 68 | 
            +
                      ask_simply(statement, color, options)
         | 
| 69 | 
            +
                    end
         | 
| 52 70 | 
             
                  end
         | 
| 53 71 |  | 
| 54 72 | 
             
                  # Say (print) something to the user. If the sentence ends with a whitespace
         | 
| @@ -58,18 +76,11 @@ class Thor | |
| 58 76 | 
             
                  # ==== Example
         | 
| 59 77 | 
             
                  # say("I know you knew that.")
         | 
| 60 78 | 
             
                  #
         | 
| 61 | 
            -
                  def say(message="", color=nil, force_new_line=(message.to_s !~ /( |\t)\Z/))
         | 
| 62 | 
            -
                     | 
| 79 | 
            +
                  def say(message = "", color = nil, force_new_line = (message.to_s !~ /( |\t)\Z/))
         | 
| 80 | 
            +
                    buffer = prepare_message(message, *color)
         | 
| 81 | 
            +
                    buffer << "\n" if force_new_line && !message.end_with?("\n")
         | 
| 63 82 |  | 
| 64 | 
            -
                     | 
| 65 | 
            -
             | 
| 66 | 
            -
                    spaces = "  " * padding
         | 
| 67 | 
            -
             | 
| 68 | 
            -
                    if force_new_line
         | 
| 69 | 
            -
                      stdout.puts(spaces + message)
         | 
| 70 | 
            -
                    else
         | 
| 71 | 
            -
                      stdout.print(spaces + message)
         | 
| 72 | 
            -
                    end
         | 
| 83 | 
            +
                    stdout.print(buffer)
         | 
| 73 84 | 
             
                    stdout.flush
         | 
| 74 85 | 
             
                  end
         | 
| 75 86 |  | 
| @@ -78,7 +89,7 @@ class Thor | |
| 78 89 | 
             
                  # in log_status, avoiding the message from being shown. If a Symbol is
         | 
| 79 90 | 
             
                  # given in log_status, it's used as the color.
         | 
| 80 91 | 
             
                  #
         | 
| 81 | 
            -
                  def say_status(status, message, log_status=true)
         | 
| 92 | 
            +
                  def say_status(status, message, log_status = true)
         | 
| 82 93 | 
             
                    return if quiet? || log_status == false
         | 
| 83 94 | 
             
                    spaces = "  " * (padding + 1)
         | 
| 84 95 | 
             
                    color  = log_status.is_a?(Symbol) ? log_status : :green
         | 
| @@ -86,22 +97,25 @@ class Thor | |
| 86 97 | 
             
                    status = status.to_s.rjust(12)
         | 
| 87 98 | 
             
                    status = set_color status, color, true if color
         | 
| 88 99 |  | 
| 89 | 
            -
                     | 
| 100 | 
            +
                    buffer = "#{status}#{spaces}#{message}"
         | 
| 101 | 
            +
                    buffer << "\n" unless buffer.end_with?("\n")
         | 
| 102 | 
            +
             | 
| 103 | 
            +
                    stdout.print(buffer)
         | 
| 90 104 | 
             
                    stdout.flush
         | 
| 91 105 | 
             
                  end
         | 
| 92 106 |  | 
| 93 107 | 
             
                  # Make a question the to user and returns true if the user replies "y" or
         | 
| 94 108 | 
             
                  # "yes".
         | 
| 95 109 | 
             
                  #
         | 
| 96 | 
            -
                  def yes?(statement, color=nil)
         | 
| 97 | 
            -
                    !!(ask(statement, color) =~ is?(:yes))
         | 
| 110 | 
            +
                  def yes?(statement, color = nil)
         | 
| 111 | 
            +
                    !!(ask(statement, color, :add_to_history => false) =~ is?(:yes))
         | 
| 98 112 | 
             
                  end
         | 
| 99 113 |  | 
| 100 114 | 
             
                  # Make a question the to user and returns true if the user replies "n" or
         | 
| 101 115 | 
             
                  # "no".
         | 
| 102 116 | 
             
                  #
         | 
| 103 | 
            -
                  def no?(statement, color=nil)
         | 
| 104 | 
            -
                     | 
| 117 | 
            +
                  def no?(statement, color = nil)
         | 
| 118 | 
            +
                    !!(ask(statement, color, :add_to_history => false) =~ is?(:no))
         | 
| 105 119 | 
             
                  end
         | 
| 106 120 |  | 
| 107 121 | 
             
                  # Prints values in columns
         | 
| @@ -111,7 +125,7 @@ class Thor | |
| 111 125 | 
             
                  #
         | 
| 112 126 | 
             
                  def print_in_columns(array)
         | 
| 113 127 | 
             
                    return if array.empty?
         | 
| 114 | 
            -
                    colwidth = (array.map{|el| el.to_s.size}.max || 0) + 2
         | 
| 128 | 
            +
                    colwidth = (array.map { |el| el.to_s.size }.max || 0) + 2
         | 
| 115 129 | 
             
                    array.each_with_index do |value, index|
         | 
| 116 130 | 
             
                      # Don't output trailing spaces when printing the last column
         | 
| 117 131 | 
             
                      if ((((index + 1) % (terminal_width / colwidth))).zero? && !index.zero?) || index + 1 == array.length
         | 
| @@ -131,7 +145,7 @@ class Thor | |
| 131 145 | 
             
                  # indent<Integer>:: Indent the first column by indent value.
         | 
| 132 146 | 
             
                  # colwidth<Integer>:: Force the first column to colwidth spaces wide.
         | 
| 133 147 | 
             
                  #
         | 
| 134 | 
            -
                  def print_table(array, options={})
         | 
| 148 | 
            +
                  def print_table(array, options = {}) # rubocop:disable MethodLength
         | 
| 135 149 | 
             
                    return if array.empty?
         | 
| 136 150 |  | 
| 137 151 | 
             
                    formats, indent, colwidth = [], options[:indent].to_i, options[:colwidth]
         | 
| @@ -140,12 +154,12 @@ class Thor | |
| 140 154 | 
             
                    formats << "%-#{colwidth + 2}s" if colwidth
         | 
| 141 155 | 
             
                    start = colwidth ? 1 : 0
         | 
| 142 156 |  | 
| 143 | 
            -
                    colcount = array.max{|a,b| a.size <=> b.size }.size
         | 
| 157 | 
            +
                    colcount = array.max { |a, b| a.size <=> b.size }.size
         | 
| 144 158 |  | 
| 145 159 | 
             
                    maximas = []
         | 
| 146 160 |  | 
| 147 161 | 
             
                    start.upto(colcount - 1) do |index|
         | 
| 148 | 
            -
                      maxima = array.map {|row| row[index] ? row[index].to_s.size : 0 }.max
         | 
| 162 | 
            +
                      maxima = array.map { |row| row[index] ? row[index].to_s.size : 0 }.max
         | 
| 149 163 | 
             
                      maximas << maxima
         | 
| 150 164 | 
             
                      if index == colcount - 1
         | 
| 151 165 | 
             
                        # Don't output 2 trailing spaces when printing the last column
         | 
| @@ -191,15 +205,13 @@ class Thor | |
| 191 205 | 
             
                  # ==== Options
         | 
| 192 206 | 
             
                  # indent<Integer>:: Indent each line of the printed paragraph by indent value.
         | 
| 193 207 | 
             
                  #
         | 
| 194 | 
            -
                  def print_wrapped(message, options={})
         | 
| 208 | 
            +
                  def print_wrapped(message, options = {})
         | 
| 195 209 | 
             
                    indent = options[:indent] || 0
         | 
| 196 210 | 
             
                    width = terminal_width - indent
         | 
| 197 211 | 
             
                    paras = message.split("\n\n")
         | 
| 198 212 |  | 
| 199 213 | 
             
                    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")}
         | 
| 214 | 
            +
                      unwrapped.strip.gsub(/\n/, " ").squeeze(" ").gsub(/.{1,#{width}}(?:\s|\Z)/) { ($& + 5.chr).gsub(/\n\005/, "\n").gsub(/\005/, "\n") }
         | 
| 203 215 | 
             
                    end
         | 
| 204 216 |  | 
| 205 217 | 
             
                    paras.each do |para|
         | 
| @@ -218,12 +230,15 @@ class Thor | |
| 218 230 | 
             
                  # destination<String>:: the destination file to solve conflicts
         | 
| 219 231 | 
             
                  # block<Proc>:: an optional block that returns the value to be used in diff
         | 
| 220 232 | 
             
                  #
         | 
| 221 | 
            -
                  def file_collision(destination)
         | 
| 233 | 
            +
                  def file_collision(destination) # rubocop:disable MethodLength
         | 
| 222 234 | 
             
                    return true if @always_force
         | 
| 223 235 | 
             
                    options = block_given? ? "[Ynaqdh]" : "[Ynaqh]"
         | 
| 224 236 |  | 
| 225 | 
            -
                     | 
| 226 | 
            -
                      answer = ask | 
| 237 | 
            +
                    loop do
         | 
| 238 | 
            +
                      answer = ask(
         | 
| 239 | 
            +
                        %[Overwrite #{destination}? (enter "h" for help) #{options}],
         | 
| 240 | 
            +
                        :add_to_history => false
         | 
| 241 | 
            +
                      )
         | 
| 227 242 |  | 
| 228 243 | 
             
                      case answer
         | 
| 229 244 | 
             
                      when is?(:yes), is?(:force), ""
         | 
| @@ -233,11 +248,11 @@ class Thor | |
| 233 248 | 
             
                      when is?(:always)
         | 
| 234 249 | 
             
                        return @always_force = true
         | 
| 235 250 | 
             
                      when is?(:quit)
         | 
| 236 | 
            -
                        say  | 
| 237 | 
            -
                         | 
| 251 | 
            +
                        say "Aborting..."
         | 
| 252 | 
            +
                        fail SystemExit
         | 
| 238 253 | 
             
                      when is?(:diff)
         | 
| 239 254 | 
             
                        show_diff(destination, yield) if block_given?
         | 
| 240 | 
            -
                        say  | 
| 255 | 
            +
                        say "Retrying..."
         | 
| 241 256 | 
             
                      else
         | 
| 242 257 | 
             
                        say file_collision_help
         | 
| 243 258 | 
             
                      end
         | 
| @@ -247,12 +262,12 @@ class Thor | |
| 247 262 | 
             
                  # This code was copied from Rake, available under MIT-LICENSE
         | 
| 248 263 | 
             
                  # Copyright (c) 2003, 2004 Jim Weirich
         | 
| 249 264 | 
             
                  def terminal_width
         | 
| 250 | 
            -
                    if ENV[ | 
| 251 | 
            -
                      result = ENV[ | 
| 265 | 
            +
                    if ENV["THOR_COLUMNS"]
         | 
| 266 | 
            +
                      result = ENV["THOR_COLUMNS"].to_i
         | 
| 252 267 | 
             
                    else
         | 
| 253 268 | 
             
                      result = unix? ? dynamic_width : 80
         | 
| 254 269 | 
             
                    end
         | 
| 255 | 
            -
                     | 
| 270 | 
            +
                    result < 10 ? 80 : result
         | 
| 256 271 | 
             
                  rescue
         | 
| 257 272 | 
             
                    80
         | 
| 258 273 | 
             
                  end
         | 
| @@ -275,6 +290,11 @@ class Thor | |
| 275 290 |  | 
| 276 291 | 
             
                protected
         | 
| 277 292 |  | 
| 293 | 
            +
                  def prepare_message(message, *color)
         | 
| 294 | 
            +
                    spaces = "  " * padding
         | 
| 295 | 
            +
                    spaces + set_color(message.to_s, *color)
         | 
| 296 | 
            +
                  end
         | 
| 297 | 
            +
             | 
| 278 298 | 
             
                  def can_display_colors?
         | 
| 279 299 | 
             
                    false
         | 
| 280 300 | 
             
                  end
         | 
| @@ -288,10 +308,6 @@ class Thor | |
| 288 308 | 
             
                    $stdout
         | 
| 289 309 | 
             
                  end
         | 
| 290 310 |  | 
| 291 | 
            -
                  def stdin
         | 
| 292 | 
            -
                    $stdin
         | 
| 293 | 
            -
                  end
         | 
| 294 | 
            -
             | 
| 295 311 | 
             
                  def stderr
         | 
| 296 312 | 
             
                    $stderr
         | 
| 297 313 | 
             
                  end
         | 
| @@ -302,23 +318,23 @@ class Thor | |
| 302 318 | 
             
                    if value.size == 1
         | 
| 303 319 | 
             
                      /\A#{value}\z/i
         | 
| 304 320 | 
             
                    else
         | 
| 305 | 
            -
                      /\A(#{value}|#{value[0,1]})\z/i
         | 
| 321 | 
            +
                      /\A(#{value}|#{value[0, 1]})\z/i
         | 
| 306 322 | 
             
                    end
         | 
| 307 323 | 
             
                  end
         | 
| 308 324 |  | 
| 309 325 | 
             
                  def file_collision_help #:nodoc:
         | 
| 310 | 
            -
             | 
| 311 | 
            -
            Y - yes, overwrite
         | 
| 312 | 
            -
            n - no, do not overwrite
         | 
| 313 | 
            -
            a - all, overwrite this and all others
         | 
| 314 | 
            -
            q - quit, abort
         | 
| 315 | 
            -
            d - diff, show the differences between the old and the new
         | 
| 316 | 
            -
            h - help, show this help
         | 
| 317 | 
            -
            HELP
         | 
| 326 | 
            +
                    <<-HELP
         | 
| 327 | 
            +
                    Y - yes, overwrite
         | 
| 328 | 
            +
                    n - no, do not overwrite
         | 
| 329 | 
            +
                    a - all, overwrite this and all others
         | 
| 330 | 
            +
                    q - quit, abort
         | 
| 331 | 
            +
                    d - diff, show the differences between the old and the new
         | 
| 332 | 
            +
                    h - help, show this help
         | 
| 333 | 
            +
                    HELP
         | 
| 318 334 | 
             
                  end
         | 
| 319 335 |  | 
| 320 336 | 
             
                  def show_diff(destination, content) #:nodoc:
         | 
| 321 | 
            -
                    diff_cmd = ENV[ | 
| 337 | 
            +
                    diff_cmd = ENV["THOR_DIFF"] || ENV["RAILS_DIFF"] || "diff -u"
         | 
| 322 338 |  | 
| 323 339 | 
             
                    Tempfile.open(File.basename(destination), File.dirname(destination)) do |temp|
         | 
| 324 340 | 
             
                      temp.write content
         | 
| @@ -337,11 +353,11 @@ HELP | |
| 337 353 | 
             
                  end
         | 
| 338 354 |  | 
| 339 355 | 
             
                  def dynamic_width_stty
         | 
| 340 | 
            -
                    %x | 
| 356 | 
            +
                    %x(stty size 2>/dev/null).split[1].to_i
         | 
| 341 357 | 
             
                  end
         | 
| 342 358 |  | 
| 343 359 | 
             
                  def dynamic_width_tput
         | 
| 344 | 
            -
                    %x | 
| 360 | 
            +
                    %x(tput cols 2>/dev/null).to_i
         | 
| 345 361 | 
             
                  end
         | 
| 346 362 |  | 
| 347 363 | 
             
                  def unix?
         | 
| @@ -354,7 +370,7 @@ HELP | |
| 354 370 | 
             
                      if chars.length <= width
         | 
| 355 371 | 
             
                        chars.join
         | 
| 356 372 | 
             
                      else
         | 
| 357 | 
            -
                        ( chars[0, width-3].join | 
| 373 | 
            +
                        ( chars[0, width - 3].join) + "..."
         | 
| 358 374 | 
             
                      end
         | 
| 359 375 | 
             
                    end
         | 
| 360 376 | 
             
                  end
         | 
| @@ -372,22 +388,34 @@ HELP | |
| 372 388 | 
             
                    end
         | 
| 373 389 | 
             
                  end
         | 
| 374 390 |  | 
| 375 | 
            -
                  def ask_simply(statement, color | 
| 376 | 
            -
                     | 
| 377 | 
            -
                     | 
| 391 | 
            +
                  def ask_simply(statement, color, options)
         | 
| 392 | 
            +
                    default = options[:default]
         | 
| 393 | 
            +
                    message = [statement, ("(#{default})" if default), nil].uniq.join(" ")
         | 
| 394 | 
            +
                    message = prepare_message(message, color)
         | 
| 395 | 
            +
                    result = Thor::LineEditor.readline(message, options)
         | 
| 396 | 
            +
             | 
| 397 | 
            +
                    return unless result
         | 
| 398 | 
            +
             | 
| 399 | 
            +
                    result.strip!
         | 
| 400 | 
            +
             | 
| 401 | 
            +
                    if default && result == ""
         | 
| 402 | 
            +
                      default
         | 
| 403 | 
            +
                    else
         | 
| 404 | 
            +
                      result
         | 
| 405 | 
            +
                    end
         | 
| 378 406 | 
             
                  end
         | 
| 379 407 |  | 
| 380 | 
            -
                  def ask_filtered(statement,  | 
| 408 | 
            +
                  def ask_filtered(statement, color, options)
         | 
| 409 | 
            +
                    answer_set = options[:limited_to]
         | 
| 381 410 | 
             
                    correct_answer = nil
         | 
| 382 411 | 
             
                    until correct_answer
         | 
| 383 | 
            -
                       | 
| 412 | 
            +
                      answers = answer_set.join(", ")
         | 
| 413 | 
            +
                      answer = ask_simply("#{statement} [#{answers}]", color, options)
         | 
| 384 414 | 
             
                      correct_answer = answer_set.include?(answer) ? answer : nil
         | 
| 385 | 
            -
                      answers = answer_set.map(&:inspect).join(", ")
         | 
| 386 415 | 
             
                      say("Your response must be one of: [#{answers}]. Please try again.") unless correct_answer
         | 
| 387 416 | 
             
                    end
         | 
| 388 417 | 
             
                    correct_answer
         | 
| 389 418 | 
             
                  end
         | 
| 390 | 
            -
             | 
| 391 419 | 
             
                end
         | 
| 392 420 | 
             
              end
         | 
| 393 421 | 
             
            end
         | 
    
        data/lib/thor/shell/color.rb
    CHANGED
    
    | @@ -1,4 +1,4 @@ | |
| 1 | 
            -
            require  | 
| 1 | 
            +
            require "thor/shell/basic"
         | 
| 2 2 |  | 
| 3 3 | 
             
            class Thor
         | 
| 4 4 | 
             
              module Shell
         | 
| @@ -77,7 +77,9 @@ class Thor | |
| 77 77 | 
             
                  #   :on_cyan
         | 
| 78 78 | 
             
                  #   :on_white
         | 
| 79 79 | 
             
                  def set_color(string, *colors)
         | 
| 80 | 
            -
                    if colors. | 
| 80 | 
            +
                    if colors.compact.empty? || !can_display_colors?
         | 
| 81 | 
            +
                      string
         | 
| 82 | 
            +
                    elsif colors.all? { |color| color.is_a?(Symbol) || color.is_a?(String) }
         | 
| 81 83 | 
             
                      ansi_colors = colors.map { |color| lookup_color(color) }
         | 
| 82 84 | 
             
                      "#{ansi_colors.join}#{string}#{CLEAR}"
         | 
| 83 85 | 
             
                    else
         | 
| @@ -92,57 +94,56 @@ class Thor | |
| 92 94 | 
             
                    end
         | 
| 93 95 | 
             
                  end
         | 
| 94 96 |  | 
| 95 | 
            -
             | 
| 97 | 
            +
                protected
         | 
| 96 98 |  | 
| 97 | 
            -
             | 
| 98 | 
            -
             | 
| 99 | 
            -
             | 
| 99 | 
            +
                  def can_display_colors?
         | 
| 100 | 
            +
                    stdout.tty?
         | 
| 101 | 
            +
                  end
         | 
| 100 102 |  | 
| 101 | 
            -
             | 
| 102 | 
            -
             | 
| 103 | 
            -
             | 
| 104 | 
            -
             | 
| 105 | 
            -
             | 
| 106 | 
            -
             | 
| 107 | 
            -
             | 
| 103 | 
            +
                  # Overwrite show_diff to show diff with colors if Diff::LCS is
         | 
| 104 | 
            +
                  # available.
         | 
| 105 | 
            +
                  #
         | 
| 106 | 
            +
                  def show_diff(destination, content) #:nodoc:
         | 
| 107 | 
            +
                    if diff_lcs_loaded? && ENV["THOR_DIFF"].nil? && ENV["RAILS_DIFF"].nil?
         | 
| 108 | 
            +
                      actual  = File.binread(destination).to_s.split("\n")
         | 
| 109 | 
            +
                      content = content.to_s.split("\n")
         | 
| 108 110 |  | 
| 109 | 
            -
             | 
| 110 | 
            -
             | 
| 111 | 
            -
                        end
         | 
| 112 | 
            -
                      else
         | 
| 113 | 
            -
                        super
         | 
| 111 | 
            +
                      Diff::LCS.sdiff(actual, content).each do |diff|
         | 
| 112 | 
            +
                        output_diff_line(diff)
         | 
| 114 113 | 
             
                      end
         | 
| 114 | 
            +
                    else
         | 
| 115 | 
            +
                      super
         | 
| 115 116 | 
             
                    end
         | 
| 117 | 
            +
                  end
         | 
| 116 118 |  | 
| 117 | 
            -
             | 
| 118 | 
            -
             | 
| 119 | 
            -
             | 
| 120 | 
            -
             | 
| 121 | 
            -
             | 
| 122 | 
            -
             | 
| 123 | 
            -
             | 
| 124 | 
            -
             | 
| 125 | 
            -
             | 
| 126 | 
            -
             | 
| 127 | 
            -
             | 
| 128 | 
            -
                      end
         | 
| 119 | 
            +
                  def output_diff_line(diff) #:nodoc:
         | 
| 120 | 
            +
                    case diff.action
         | 
| 121 | 
            +
                    when "-"
         | 
| 122 | 
            +
                      say "- #{diff.old_element.chomp}", :red, true
         | 
| 123 | 
            +
                    when "+"
         | 
| 124 | 
            +
                      say "+ #{diff.new_element.chomp}", :green, true
         | 
| 125 | 
            +
                    when "!"
         | 
| 126 | 
            +
                      say "- #{diff.old_element.chomp}", :red, true
         | 
| 127 | 
            +
                      say "+ #{diff.new_element.chomp}", :green, true
         | 
| 128 | 
            +
                    else
         | 
| 129 | 
            +
                      say "  #{diff.old_element.chomp}", nil, true
         | 
| 129 130 | 
             
                    end
         | 
| 131 | 
            +
                  end
         | 
| 130 132 |  | 
| 131 | 
            -
             | 
| 132 | 
            -
             | 
| 133 | 
            -
             | 
| 134 | 
            -
             | 
| 135 | 
            -
             | 
| 136 | 
            -
             | 
| 133 | 
            +
                  # Check if Diff::LCS is loaded. If it is, use it to create pretty output
         | 
| 134 | 
            +
                  # for diff.
         | 
| 135 | 
            +
                  #
         | 
| 136 | 
            +
                  def diff_lcs_loaded? #:nodoc:
         | 
| 137 | 
            +
                    return true  if defined?(Diff::LCS)
         | 
| 138 | 
            +
                    return @diff_lcs_loaded unless @diff_lcs_loaded.nil?
         | 
| 137 139 |  | 
| 138 | 
            -
             | 
| 139 | 
            -
             | 
| 140 | 
            -
             | 
| 141 | 
            -
             | 
| 142 | 
            -
             | 
| 143 | 
            -
                      end
         | 
| 140 | 
            +
                    @diff_lcs_loaded = begin
         | 
| 141 | 
            +
                      require "diff/lcs"
         | 
| 142 | 
            +
                      true
         | 
| 143 | 
            +
                    rescue LoadError
         | 
| 144 | 
            +
                      false
         | 
| 144 145 | 
             
                    end
         | 
| 145 | 
            -
             | 
| 146 | 
            +
                  end
         | 
| 146 147 | 
             
                end
         | 
| 147 148 | 
             
              end
         | 
| 148 149 | 
             
            end
         |