thor 0.20.3 → 1.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.
Potentially problematic release.
This version of thor might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +17 -1
- data/lib/thor.rb +12 -4
- data/lib/thor/actions.rb +17 -12
- data/lib/thor/actions/create_file.rb +1 -1
- data/lib/thor/actions/create_link.rb +3 -2
- data/lib/thor/actions/directory.rb +7 -17
- data/lib/thor/actions/file_manipulation.rb +5 -5
- data/lib/thor/actions/inject_into_file.rb +19 -8
- data/lib/thor/base.rb +59 -38
- data/lib/thor/command.rb +21 -14
- data/lib/thor/error.rb +14 -18
- data/lib/thor/group.rb +1 -1
- data/lib/thor/invocation.rb +1 -0
- data/lib/thor/line_editor.rb +2 -2
- data/lib/thor/line_editor/basic.rb +1 -1
- data/lib/thor/line_editor/readline.rb +6 -6
- data/lib/thor/nested_context.rb +29 -0
- data/lib/thor/parser.rb +4 -4
- data/lib/thor/parser/arguments.rb +2 -2
- data/lib/thor/parser/option.rb +20 -7
- data/lib/thor/parser/options.rb +13 -3
- data/lib/thor/rake_compat.rb +1 -0
- data/lib/thor/runner.rb +5 -4
- data/lib/thor/shell.rb +3 -3
- data/lib/thor/shell/basic.rb +10 -1
- data/lib/thor/shell/color.rb +6 -2
- data/lib/thor/shell/html.rb +3 -3
- data/lib/thor/util.rb +16 -0
- data/lib/thor/version.rb +1 -1
- data/thor.gemspec +9 -2
- metadata +19 -10
- data/lib/thor/core_ext/io_binary_read.rb +0 -12
- data/lib/thor/core_ext/ordered_hash.rb +0 -129
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 2c23d1fdac6ea485b4cbfe91abad33a46e03c00baf2e7e0068c9f8d4ce41e607
         | 
| 4 | 
            +
              data.tar.gz: 368fe9c87e8a426eaf38278acaba2b7a3171c96c99298ca5e2eddf3b1b466ff6
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 6f2e3b52a657bc5318fed8a5e3f15368d734f62e7b8039a296add626ff6bdc415e6c8a85cea31bdd591a629960854f0d34e47ef81161c63acf4ef140457a7bdb
         | 
| 7 | 
            +
              data.tar.gz: 8086cd52e16a12fb63dad7df484f0c079feed33d7aa6078d8683f895ddcd92da21be58d26a3b33f89e44d822ae9b01e73ef36672aa77a7befcfa3198523df253
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -1,3 +1,19 @@ | |
| 1 | 
            +
            # 1.0.1
         | 
| 2 | 
            +
            * Fix thor when `thor/base` and `thor/group` are required without `thor.rb`.
         | 
| 3 | 
            +
            * Handle relative source path in `create_link`.
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            # 1.0.0
         | 
| 6 | 
            +
            * Drop support to Ruby 1.8 and 1.9.
         | 
| 7 | 
            +
            * Deprecate relying on default `exit_on_failure?`.
         | 
| 8 | 
            +
              In preparation to make Thor commands exit when there is a failure we are deprecating
         | 
| 9 | 
            +
              defining a command without defining what behavior is expected when there is a failure.
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              To fix the deprecation you need to define a class method called `exit_on_failure?` returning
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              `false` if you want the current behavior or `true` if you want the new behavior.
         | 
| 14 | 
            +
            * Deprecate defining an option with the default value using a different type as defined in the option.
         | 
| 15 | 
            +
            * Allow options to be repeatable. See #674.
         | 
| 16 | 
            +
             | 
| 1 17 | 
             
            # 0.20.3
         | 
| 2 18 | 
             
            * Support old versions of `did_you_mean`.
         | 
| 3 19 |  | 
| @@ -5,7 +21,7 @@ | |
| 5 21 | 
             
            * Fix `did_you_mean` support.
         | 
| 6 22 |  | 
| 7 23 | 
             
            # 0.20.1
         | 
| 8 | 
            -
            * Support new versions  | 
| 24 | 
            +
            * Support new versions of ERB.
         | 
| 9 25 | 
             
            * Fix `check_unknown_options!` to not check the content that was not parsed, i.e. after a `--` or after the first unknown with `stop_on_unknown_option!`
         | 
| 10 26 | 
             
            * Add `did_you_mean` support.
         | 
| 11 27 |  | 
    
        data/lib/thor.rb
    CHANGED
    
    | @@ -1,5 +1,5 @@ | |
| 1 1 | 
             
            require "set"
         | 
| 2 | 
            -
             | 
| 2 | 
            +
            require_relative "thor/base"
         | 
| 3 3 |  | 
| 4 4 | 
             
            class Thor
         | 
| 5 5 | 
             
              class << self
         | 
| @@ -90,9 +90,14 @@ class Thor | |
| 90 90 | 
             
                # ==== Parameters
         | 
| 91 91 | 
             
                # Hash[String|Array => Symbol]:: Maps the string or the strings in the array to the given command.
         | 
| 92 92 | 
             
                #
         | 
| 93 | 
            -
                def map(mappings = nil)
         | 
| 93 | 
            +
                def map(mappings = nil, **kw)
         | 
| 94 94 | 
             
                  @map ||= from_superclass(:map, {})
         | 
| 95 95 |  | 
| 96 | 
            +
                  if mappings && !kw.empty?
         | 
| 97 | 
            +
                    mappings = kw.merge!(mappings)
         | 
| 98 | 
            +
                  else
         | 
| 99 | 
            +
                    mappings ||= kw
         | 
| 100 | 
            +
                  end
         | 
| 96 101 | 
             
                  if mappings
         | 
| 97 102 | 
             
                    mappings.each do |key, value|
         | 
| 98 103 | 
             
                      if key.respond_to?(:each)
         | 
| @@ -170,7 +175,7 @@ class Thor | |
| 170 175 | 
             
                  handle_no_command_error(meth) unless command
         | 
| 171 176 |  | 
| 172 177 | 
             
                  shell.say "Usage:"
         | 
| 173 | 
            -
                  shell.say "  #{banner(command)}"
         | 
| 178 | 
            +
                  shell.say "  #{banner(command).split("\n").join("\n  ")}"
         | 
| 174 179 | 
             
                  shell.say
         | 
| 175 180 | 
             
                  class_options_help(shell, nil => command.options.values)
         | 
| 176 181 | 
             
                  if command.long_description
         | 
| @@ -393,7 +398,10 @@ class Thor | |
| 393 398 | 
             
                # the namespace should be displayed as arguments.
         | 
| 394 399 | 
             
                #
         | 
| 395 400 | 
             
                def banner(command, namespace = nil, subcommand = false)
         | 
| 396 | 
            -
                   | 
| 401 | 
            +
                  $thor_runner ||= false
         | 
| 402 | 
            +
                  command.formatted_usage(self, $thor_runner, subcommand).split("\n").map do |formatted_usage|
         | 
| 403 | 
            +
                    "#{basename} #{formatted_usage}"
         | 
| 404 | 
            +
                  end.join("\n")
         | 
| 397 405 | 
             
                end
         | 
| 398 406 |  | 
| 399 407 | 
             
                def baseclass #:nodoc:
         | 
    
        data/lib/thor/actions.rb
    CHANGED
    
    | @@ -1,17 +1,16 @@ | |
| 1 | 
            -
             | 
| 2 | 
            -
             | 
| 3 | 
            -
             | 
| 4 | 
            -
             | 
| 5 | 
            -
             | 
| 6 | 
            -
             | 
| 7 | 
            -
            require "thor/actions/file_manipulation"
         | 
| 8 | 
            -
            require "thor/actions/inject_into_file"
         | 
| 1 | 
            +
            require_relative "actions/create_file"
         | 
| 2 | 
            +
            require_relative "actions/create_link"
         | 
| 3 | 
            +
            require_relative "actions/directory"
         | 
| 4 | 
            +
            require_relative "actions/empty_directory"
         | 
| 5 | 
            +
            require_relative "actions/file_manipulation"
         | 
| 6 | 
            +
            require_relative "actions/inject_into_file"
         | 
| 9 7 |  | 
| 10 8 | 
             
            class Thor
         | 
| 11 9 | 
             
              module Actions
         | 
| 12 10 | 
             
                attr_accessor :behavior
         | 
| 13 11 |  | 
| 14 12 | 
             
                def self.included(base) #:nodoc:
         | 
| 13 | 
            +
                  super(base)
         | 
| 15 14 | 
             
                  base.extend ClassMethods
         | 
| 16 15 | 
             
                end
         | 
| 17 16 |  | 
| @@ -257,13 +256,19 @@ class Thor | |
| 257 256 |  | 
| 258 257 | 
             
                  return if options[:pretend]
         | 
| 259 258 |  | 
| 260 | 
            -
                   | 
| 259 | 
            +
                  env_splat = [config[:env]] if config[:env]
         | 
| 261 260 |  | 
| 262 | 
            -
                  if config[: | 
| 263 | 
            -
                     | 
| 264 | 
            -
                     | 
| 261 | 
            +
                  if config[:capture]
         | 
| 262 | 
            +
                    require "open3"
         | 
| 263 | 
            +
                    result, status = Open3.capture2e(*env_splat, command.to_s)
         | 
| 264 | 
            +
                    success = status.success?
         | 
| 265 | 
            +
                  else
         | 
| 266 | 
            +
                    result = system(*env_splat, command.to_s)
         | 
| 267 | 
            +
                    success = result
         | 
| 265 268 | 
             
                  end
         | 
| 266 269 |  | 
| 270 | 
            +
                  abort if !success && config.fetch(:abort_on_failure, self.class.exit_on_failure?)
         | 
| 271 | 
            +
             | 
| 267 272 | 
             
                  result
         | 
| 268 273 | 
             
                end
         | 
| 269 274 |  | 
| @@ -1,4 +1,4 @@ | |
| 1 | 
            -
             | 
| 1 | 
            +
            require_relative "create_file"
         | 
| 2 2 |  | 
| 3 3 | 
             
            class Thor
         | 
| 4 4 | 
             
              module Actions
         | 
| @@ -33,7 +33,8 @@ class Thor | |
| 33 33 | 
             
                  # Boolean:: true if it is identical, false otherwise.
         | 
| 34 34 | 
             
                  #
         | 
| 35 35 | 
             
                  def identical?
         | 
| 36 | 
            -
                     | 
| 36 | 
            +
                    source = File.expand_path(render, File.dirname(destination))
         | 
| 37 | 
            +
                    exists? && File.identical?(source, destination)
         | 
| 37 38 | 
             
                  end
         | 
| 38 39 |  | 
| 39 40 | 
             
                  def invoke!
         | 
| @@ -1,4 +1,4 @@ | |
| 1 | 
            -
             | 
| 1 | 
            +
            require_relative "empty_directory"
         | 
| 2 2 |  | 
| 3 3 | 
             
            class Thor
         | 
| 4 4 | 
             
              module Actions
         | 
| @@ -56,7 +56,7 @@ class Thor | |
| 56 56 | 
             
                  attr_reader :source
         | 
| 57 57 |  | 
| 58 58 | 
             
                  def initialize(base, source, destination = nil, config = {}, &block)
         | 
| 59 | 
            -
                    @source = File.expand_path(base.find_in_source_paths(source.to_s))
         | 
| 59 | 
            +
                    @source = File.expand_path(Dir[Util.escape_globs(base.find_in_source_paths(source.to_s))].first)
         | 
| 60 60 | 
             
                    @block  = block
         | 
| 61 61 | 
             
                    super(base, destination, {:recursive => true}.merge(config))
         | 
| 62 62 | 
             
                  end
         | 
| @@ -96,22 +96,12 @@ class Thor | |
| 96 96 | 
             
                    end
         | 
| 97 97 | 
             
                  end
         | 
| 98 98 |  | 
| 99 | 
            -
                   | 
| 100 | 
            -
                     | 
| 101 | 
            -
             | 
| 102 | 
            -
                    end
         | 
| 103 | 
            -
             | 
| 104 | 
            -
                    def files(lookup)
         | 
| 105 | 
            -
                      Dir[lookup]
         | 
| 106 | 
            -
                    end
         | 
| 107 | 
            -
                  else
         | 
| 108 | 
            -
                    def file_level_lookup(previous_lookup)
         | 
| 109 | 
            -
                      File.join(previous_lookup, "*")
         | 
| 110 | 
            -
                    end
         | 
| 99 | 
            +
                  def file_level_lookup(previous_lookup)
         | 
| 100 | 
            +
                    File.join(previous_lookup, "*")
         | 
| 101 | 
            +
                  end
         | 
| 111 102 |  | 
| 112 | 
            -
             | 
| 113 | 
            -
             | 
| 114 | 
            -
                    end
         | 
| 103 | 
            +
                  def files(lookup)
         | 
| 104 | 
            +
                    Dir.glob(lookup, File::FNM_DOTMATCH)
         | 
| 115 105 | 
             
                  end
         | 
| 116 106 | 
             
                end
         | 
| 117 107 | 
             
              end
         | 
| @@ -23,14 +23,14 @@ class Thor | |
| 23 23 | 
             
                  destination = args.first || source
         | 
| 24 24 | 
             
                  source = File.expand_path(find_in_source_paths(source.to_s))
         | 
| 25 25 |  | 
| 26 | 
            -
                  create_file destination, nil, config do
         | 
| 26 | 
            +
                  resulting_destination = create_file destination, nil, config do
         | 
| 27 27 | 
             
                    content = File.binread(source)
         | 
| 28 28 | 
             
                    content = yield(content) if block
         | 
| 29 29 | 
             
                    content
         | 
| 30 30 | 
             
                  end
         | 
| 31 31 | 
             
                  if config[:mode] == :preserve
         | 
| 32 32 | 
             
                    mode = File.stat(source).mode
         | 
| 33 | 
            -
                    chmod( | 
| 33 | 
            +
                    chmod(resulting_destination, mode, config)
         | 
| 34 34 | 
             
                  end
         | 
| 35 35 | 
             
                end
         | 
| 36 36 |  | 
| @@ -80,14 +80,14 @@ class Thor | |
| 80 80 | 
             
                  config = args.last.is_a?(Hash) ? args.pop : {}
         | 
| 81 81 | 
             
                  destination = args.first
         | 
| 82 82 |  | 
| 83 | 
            -
                  if source =~ %r{^https?\://}
         | 
| 83 | 
            +
                  render = if source =~ %r{^https?\://}
         | 
| 84 84 | 
             
                    require "open-uri"
         | 
| 85 | 
            +
                    URI.send(:open, source) { |input| input.binmode.read }
         | 
| 85 86 | 
             
                  else
         | 
| 86 87 | 
             
                    source = File.expand_path(find_in_source_paths(source.to_s))
         | 
| 88 | 
            +
                    open(source) { |input| input.binmode.read }
         | 
| 87 89 | 
             
                  end
         | 
| 88 90 |  | 
| 89 | 
            -
                  render = open(source) { |input| input.binmode.read }
         | 
| 90 | 
            -
             | 
| 91 91 | 
             
                  destination ||= if block_given?
         | 
| 92 92 | 
             
                    block.arity == 1 ? yield(render) : yield
         | 
| 93 93 | 
             
                  else
         | 
| @@ -1,4 +1,4 @@ | |
| 1 | 
            -
             | 
| 1 | 
            +
            require_relative "empty_directory"
         | 
| 2 2 |  | 
| 3 3 | 
             
            class Thor
         | 
| 4 4 | 
             
              module Actions
         | 
| @@ -21,9 +21,14 @@ class Thor | |
| 21 21 | 
             
                #     gems.split(" ").map{ |gem| "  config.gem :#{gem}" }.join("\n")
         | 
| 22 22 | 
             
                #   end
         | 
| 23 23 | 
             
                #
         | 
| 24 | 
            +
                WARNINGS = { unchanged_no_flag: 'File unchanged! The supplied flag value not found!' }
         | 
| 25 | 
            +
             | 
| 24 26 | 
             
                def insert_into_file(destination, *args, &block)
         | 
| 25 27 | 
             
                  data = block_given? ? block : args.shift
         | 
| 26 | 
            -
             | 
| 28 | 
            +
             | 
| 29 | 
            +
                  config = args.shift || {}
         | 
| 30 | 
            +
                  config[:after] = /\z/ unless config.key?(:before) || config.key?(:after)
         | 
| 31 | 
            +
             | 
| 27 32 | 
             
                  action InjectIntoFile.new(self, destination, data, config)
         | 
| 28 33 | 
             
                end
         | 
| 29 34 | 
             
                alias_method :inject_into_file, :insert_into_file
         | 
| @@ -45,8 +50,6 @@ class Thor | |
| 45 50 | 
             
                  end
         | 
| 46 51 |  | 
| 47 52 | 
             
                  def invoke!
         | 
| 48 | 
            -
                    say_status :invoke
         | 
| 49 | 
            -
             | 
| 50 53 | 
             
                    content = if @behavior == :after
         | 
| 51 54 | 
             
                      '\0' + replacement
         | 
| 52 55 | 
             
                    else
         | 
| @@ -54,7 +57,11 @@ class Thor | |
| 54 57 | 
             
                    end
         | 
| 55 58 |  | 
| 56 59 | 
             
                    if exists?
         | 
| 57 | 
            -
                      replace!(/#{flag}/, content, config[:force])
         | 
| 60 | 
            +
                      if replace!(/#{flag}/, content, config[:force])
         | 
| 61 | 
            +
                        say_status(:invoke)
         | 
| 62 | 
            +
                      else
         | 
| 63 | 
            +
                        say_status(:unchanged, warning: WARNINGS[:unchanged_no_flag], color: :red)
         | 
| 64 | 
            +
                      end
         | 
| 58 65 | 
             
                    else
         | 
| 59 66 | 
             
                      unless pretend?
         | 
| 60 67 | 
             
                        raise Thor::Error, "The file #{ destination } does not appear to exist"
         | 
| @@ -78,7 +85,7 @@ class Thor | |
| 78 85 |  | 
| 79 86 | 
             
                protected
         | 
| 80 87 |  | 
| 81 | 
            -
                  def say_status(behavior)
         | 
| 88 | 
            +
                  def say_status(behavior, warning: nil, color: nil)
         | 
| 82 89 | 
             
                    status = if behavior == :invoke
         | 
| 83 90 | 
             
                      if flag == /\A/
         | 
| 84 91 | 
             
                        :prepend
         | 
| @@ -87,11 +94,13 @@ class Thor | |
| 87 94 | 
             
                      else
         | 
| 88 95 | 
             
                        :insert
         | 
| 89 96 | 
             
                      end
         | 
| 97 | 
            +
                    elsif warning
         | 
| 98 | 
            +
                      warning
         | 
| 90 99 | 
             
                    else
         | 
| 91 100 | 
             
                      :subtract
         | 
| 92 101 | 
             
                    end
         | 
| 93 102 |  | 
| 94 | 
            -
                    super(status, config[:verbose])
         | 
| 103 | 
            +
                    super(status, (color || config[:verbose]))
         | 
| 95 104 | 
             
                  end
         | 
| 96 105 |  | 
| 97 106 | 
             
                  # Adds the content to the file.
         | 
| @@ -100,8 +109,10 @@ class Thor | |
| 100 109 | 
             
                    return if pretend?
         | 
| 101 110 | 
             
                    content = File.read(destination)
         | 
| 102 111 | 
             
                    if force || !content.include?(replacement)
         | 
| 103 | 
            -
                      content.gsub!(regexp, string)
         | 
| 112 | 
            +
                      success = content.gsub!(regexp, string)
         | 
| 113 | 
            +
             | 
| 104 114 | 
             
                      File.open(destination, "wb") { |file| file.write(content) }
         | 
| 115 | 
            +
                      success
         | 
| 105 116 | 
             
                    end
         | 
| 106 117 | 
             
                  end
         | 
| 107 118 | 
             
                end
         | 
    
        data/lib/thor/base.rb
    CHANGED
    
    | @@ -1,17 +1,17 @@ | |
| 1 | 
            -
             | 
| 2 | 
            -
             | 
| 3 | 
            -
             | 
| 4 | 
            -
             | 
| 5 | 
            -
             | 
| 6 | 
            -
             | 
| 7 | 
            -
             | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 1 | 
            +
            require_relative "command"
         | 
| 2 | 
            +
            require_relative "core_ext/hash_with_indifferent_access"
         | 
| 3 | 
            +
            require_relative "error"
         | 
| 4 | 
            +
            require_relative "invocation"
         | 
| 5 | 
            +
            require_relative "nested_context"
         | 
| 6 | 
            +
            require_relative "parser"
         | 
| 7 | 
            +
            require_relative "shell"
         | 
| 8 | 
            +
            require_relative "line_editor"
         | 
| 9 | 
            +
            require_relative "util"
         | 
| 10 10 |  | 
| 11 11 | 
             
            class Thor
         | 
| 12 | 
            -
              autoload :Actions,    " | 
| 13 | 
            -
              autoload :RakeCompat, " | 
| 14 | 
            -
              autoload :Group,      " | 
| 12 | 
            +
              autoload :Actions,    File.expand_path("actions", __dir__)
         | 
| 13 | 
            +
              autoload :RakeCompat, File.expand_path("rake_compat", __dir__)
         | 
| 14 | 
            +
              autoload :Group,      File.expand_path("group", __dir__)
         | 
| 15 15 |  | 
| 16 16 | 
             
              # Shortcuts for help.
         | 
| 17 17 | 
             
              HELP_MAPPINGS       = %w(-h -? --help -D)
         | 
| @@ -22,6 +22,15 @@ class Thor | |
| 22 22 |  | 
| 23 23 | 
             
              TEMPLATE_EXTNAME = ".tt"
         | 
| 24 24 |  | 
| 25 | 
            +
              class << self
         | 
| 26 | 
            +
                def deprecation_warning(message) #:nodoc:
         | 
| 27 | 
            +
                  unless ENV['THOR_SILENCE_DEPRECATION']
         | 
| 28 | 
            +
                    warn "Deprecation warning: #{message}\n" +
         | 
| 29 | 
            +
                      'You can silence deprecations warning by setting the environment variable THOR_SILENCE_DEPRECATION.'
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
             | 
| 25 34 | 
             
              module Base
         | 
| 26 35 | 
             
                attr_accessor :options, :parent_options, :args
         | 
| 27 36 |  | 
| @@ -89,6 +98,7 @@ class Thor | |
| 89 98 |  | 
| 90 99 | 
             
                class << self
         | 
| 91 100 | 
             
                  def included(base) #:nodoc:
         | 
| 101 | 
            +
                    super(base)
         | 
| 92 102 | 
             
                    base.extend ClassMethods
         | 
| 93 103 | 
             
                    base.send :include, Invocation
         | 
| 94 104 | 
             
                    base.send :include, Shell
         | 
| @@ -153,17 +163,20 @@ class Thor | |
| 153 163 |  | 
| 154 164 | 
             
                  # If you want to raise an error when the default value of an option does not match
         | 
| 155 165 | 
             
                  # the type call check_default_type!
         | 
| 156 | 
            -
                  # This  | 
| 166 | 
            +
                  # This will be the default; for compatibility a deprecation warning is issued if necessary.
         | 
| 157 167 | 
             
                  def check_default_type!
         | 
| 158 168 | 
             
                    @check_default_type = true
         | 
| 159 169 | 
             
                  end
         | 
| 160 170 |  | 
| 161 | 
            -
                   | 
| 162 | 
            -
             | 
| 171 | 
            +
                  # If you want to use defaults that don't match the type of an option,
         | 
| 172 | 
            +
                  # either specify `check_default_type: false` or call `allow_incompatible_default_type!`
         | 
| 173 | 
            +
                  def allow_incompatible_default_type!
         | 
| 174 | 
            +
                    @check_default_type = false
         | 
| 163 175 | 
             
                  end
         | 
| 164 176 |  | 
| 165 | 
            -
                  def check_default_type | 
| 166 | 
            -
                     | 
| 177 | 
            +
                  def check_default_type #:nodoc:
         | 
| 178 | 
            +
                    @check_default_type = from_superclass(:check_default_type, nil) unless defined?(@check_default_type)
         | 
| 179 | 
            +
                    @check_default_type
         | 
| 167 180 | 
             
                  end
         | 
| 168 181 |  | 
| 169 182 | 
             
                  # If true, option parsing is suspended as soon as an unknown option or a
         | 
| @@ -353,22 +366,22 @@ class Thor | |
| 353 366 | 
             
                  # Returns the commands for this Thor class.
         | 
| 354 367 | 
             
                  #
         | 
| 355 368 | 
             
                  # ==== Returns
         | 
| 356 | 
            -
                  #  | 
| 357 | 
            -
                  # | 
| 369 | 
            +
                  # Hash:: An ordered hash with commands names as keys and Thor::Command
         | 
| 370 | 
            +
                  #        objects as values.
         | 
| 358 371 | 
             
                  #
         | 
| 359 372 | 
             
                  def commands
         | 
| 360 | 
            -
                    @commands ||=  | 
| 373 | 
            +
                    @commands ||= Hash.new
         | 
| 361 374 | 
             
                  end
         | 
| 362 375 | 
             
                  alias_method :tasks, :commands
         | 
| 363 376 |  | 
| 364 377 | 
             
                  # Returns the commands for this Thor class and all subclasses.
         | 
| 365 378 | 
             
                  #
         | 
| 366 379 | 
             
                  # ==== Returns
         | 
| 367 | 
            -
                  #  | 
| 368 | 
            -
                  # | 
| 380 | 
            +
                  # Hash:: An ordered hash with commands names as keys and Thor::Command
         | 
| 381 | 
            +
                  #        objects as values.
         | 
| 369 382 | 
             
                  #
         | 
| 370 383 | 
             
                  def all_commands
         | 
| 371 | 
            -
                    @all_commands ||= from_superclass(:all_commands,  | 
| 384 | 
            +
                    @all_commands ||= from_superclass(:all_commands, Hash.new)
         | 
| 372 385 | 
             
                    @all_commands.merge!(commands)
         | 
| 373 386 | 
             
                  end
         | 
| 374 387 | 
             
                  alias_method :all_tasks, :all_commands
         | 
| @@ -415,14 +428,20 @@ class Thor | |
| 415 428 | 
             
                  #     remove_command :this_is_not_a_command
         | 
| 416 429 | 
             
                  #   end
         | 
| 417 430 | 
             
                  #
         | 
| 418 | 
            -
                  def no_commands
         | 
| 419 | 
            -
                     | 
| 420 | 
            -
                    yield
         | 
| 421 | 
            -
                  ensure
         | 
| 422 | 
            -
                    @no_commands = false
         | 
| 431 | 
            +
                  def no_commands(&block)
         | 
| 432 | 
            +
                    no_commands_context.enter(&block)
         | 
| 423 433 | 
             
                  end
         | 
| 434 | 
            +
             | 
| 424 435 | 
             
                  alias_method :no_tasks, :no_commands
         | 
| 425 436 |  | 
| 437 | 
            +
                  def no_commands_context
         | 
| 438 | 
            +
                    @no_commands_context ||= NestedContext.new
         | 
| 439 | 
            +
                  end
         | 
| 440 | 
            +
             | 
| 441 | 
            +
                  def no_commands?
         | 
| 442 | 
            +
                    no_commands_context.entered?
         | 
| 443 | 
            +
                  end
         | 
| 444 | 
            +
             | 
| 426 445 | 
             
                  # Sets the namespace for the Thor or Thor::Group class. By default the
         | 
| 427 446 | 
             
                  # namespace is retrieved from the class name. If your Thor class is named
         | 
| 428 447 | 
             
                  # Scripts::MyScript, the help method, for example, will be called as:
         | 
| @@ -502,10 +521,16 @@ class Thor | |
| 502 521 | 
             
                    msg = "ERROR: \"#{basename} #{name}\" was called with ".dup
         | 
| 503 522 | 
             
                    msg << "no arguments"               if     args.empty?
         | 
| 504 523 | 
             
                    msg << "arguments " << args.inspect unless args.empty?
         | 
| 505 | 
            -
                    msg << "\nUsage: #{banner(command). | 
| 524 | 
            +
                    msg << "\nUsage: \"#{banner(command).split("\n").join("\"\n       \"")}\""
         | 
| 506 525 | 
             
                    raise InvocationError, msg
         | 
| 507 526 | 
             
                  end
         | 
| 508 527 |  | 
| 528 | 
            +
                  # A flag that makes the process exit with status 1 if any error happens.
         | 
| 529 | 
            +
                  def exit_on_failure?
         | 
| 530 | 
            +
                    Thor.deprecation_warning "Thor exit with status 0 on errors. To keep this behavior, you must define `exit_on_failure?` in `#{self.name}`"
         | 
| 531 | 
            +
                    false
         | 
| 532 | 
            +
                  end
         | 
| 533 | 
            +
             | 
| 509 534 | 
             
                protected
         | 
| 510 535 |  | 
| 511 536 | 
             
                  # Prints the class options per group. If an option does not belong to
         | 
| @@ -563,7 +588,7 @@ class Thor | |
| 563 588 | 
             
                  # options<Hash>:: Described in both class_option and method_option.
         | 
| 564 589 | 
             
                  # scope<Hash>:: Options hash that is being built up
         | 
| 565 590 | 
             
                  def build_option(name, options, scope) #:nodoc:
         | 
| 566 | 
            -
                    scope[name] = Thor::Option.new(name,  | 
| 591 | 
            +
                    scope[name] = Thor::Option.new(name, {:check_default_type => check_default_type}.merge!(options))
         | 
| 567 592 | 
             
                  end
         | 
| 568 593 |  | 
| 569 594 | 
             
                  # Receives a hash of options, parse them and add to the scope. This is a
         | 
| @@ -596,13 +621,15 @@ class Thor | |
| 596 621 | 
             
                  # Everytime someone inherits from a Thor class, register the klass
         | 
| 597 622 | 
             
                  # and file into baseclass.
         | 
| 598 623 | 
             
                  def inherited(klass)
         | 
| 624 | 
            +
                    super(klass)
         | 
| 599 625 | 
             
                    Thor::Base.register_klass_file(klass)
         | 
| 600 | 
            -
                    klass.instance_variable_set(:@no_commands,  | 
| 626 | 
            +
                    klass.instance_variable_set(:@no_commands, 0)
         | 
| 601 627 | 
             
                  end
         | 
| 602 628 |  | 
| 603 629 | 
             
                  # Fire this callback whenever a method is added. Added methods are
         | 
| 604 630 | 
             
                  # tracked as commands by invoking the create_command method.
         | 
| 605 631 | 
             
                  def method_added(meth)
         | 
| 632 | 
            +
                    super(meth)
         | 
| 606 633 | 
             
                    meth = meth.to_s
         | 
| 607 634 |  | 
| 608 635 | 
             
                    if meth == "initialize"
         | 
| @@ -613,8 +640,7 @@ class Thor | |
| 613 640 | 
             
                    # Return if it's not a public instance method
         | 
| 614 641 | 
             
                    return unless public_method_defined?(meth.to_sym)
         | 
| 615 642 |  | 
| 616 | 
            -
                     | 
| 617 | 
            -
                    return if @no_commands || !create_command(meth)
         | 
| 643 | 
            +
                    return if no_commands? || !create_command(meth)
         | 
| 618 644 |  | 
| 619 645 | 
             
                    is_thor_reserved_word?(meth, :command)
         | 
| 620 646 | 
             
                    Thor::Base.register_klass_file(self)
         | 
| @@ -641,11 +667,6 @@ class Thor | |
| 641 667 | 
             
                    end
         | 
| 642 668 | 
             
                  end
         | 
| 643 669 |  | 
| 644 | 
            -
                  # A flag that makes the process exit with status 1 if any error happens.
         | 
| 645 | 
            -
                  def exit_on_failure?
         | 
| 646 | 
            -
                    false
         | 
| 647 | 
            -
                  end
         | 
| 648 | 
            -
             | 
| 649 670 | 
             
                  #
         | 
| 650 671 | 
             
                  # The basename of the program invoking the thor class.
         | 
| 651 672 | 
             
                  #
         | 
    
        data/lib/thor/command.rb
    CHANGED
    
    | @@ -49,24 +49,32 @@ class Thor | |
| 49 49 |  | 
| 50 50 | 
             
                  formatted ||= "".dup
         | 
| 51 51 |  | 
| 52 | 
            -
                   | 
| 53 | 
            -
             | 
| 54 | 
            -
                                 usage.to_s.gsub(/^#{name}/) do |match|
         | 
| 55 | 
            -
                                   match << " " << klass.arguments.map(&:usage).compact.join(" ")
         | 
| 56 | 
            -
                                 end
         | 
| 57 | 
            -
                               else
         | 
| 58 | 
            -
                                 usage.to_s
         | 
| 59 | 
            -
                               end
         | 
| 52 | 
            +
                  Array(usage).map do |specific_usage|
         | 
| 53 | 
            +
                    formatted_specific_usage = formatted
         | 
| 60 54 |  | 
| 61 | 
            -
             | 
| 62 | 
            -
                  formatted << " #{required_options}"
         | 
| 55 | 
            +
                    formatted_specific_usage += required_arguments_for(klass, specific_usage)
         | 
| 63 56 |  | 
| 64 | 
            -
             | 
| 65 | 
            -
             | 
| 57 | 
            +
                    # Add required options
         | 
| 58 | 
            +
                    formatted_specific_usage += " #{required_options}"
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                    # Strip and go!
         | 
| 61 | 
            +
                    formatted_specific_usage.strip
         | 
| 62 | 
            +
                  end.join("\n")
         | 
| 66 63 | 
             
                end
         | 
| 67 64 |  | 
| 68 65 | 
             
              protected
         | 
| 69 66 |  | 
| 67 | 
            +
                # Add usage with required arguments
         | 
| 68 | 
            +
                def required_arguments_for(klass, usage)
         | 
| 69 | 
            +
                  if klass && !klass.arguments.empty?
         | 
| 70 | 
            +
                    usage.to_s.gsub(/^#{name}/) do |match|
         | 
| 71 | 
            +
                      match << " " << klass.arguments.map(&:usage).compact.join(" ")
         | 
| 72 | 
            +
                    end
         | 
| 73 | 
            +
                  else
         | 
| 74 | 
            +
                    usage.to_s
         | 
| 75 | 
            +
                  end
         | 
| 76 | 
            +
                end
         | 
| 77 | 
            +
             | 
| 70 78 | 
             
                def not_debugging?(instance)
         | 
| 71 79 | 
             
                  !(instance.class.respond_to?(:debugging) && instance.class.debugging)
         | 
| 72 80 | 
             
                end
         | 
| @@ -97,8 +105,7 @@ class Thor | |
| 97 105 | 
             
                def handle_argument_error?(instance, error, caller)
         | 
| 98 106 | 
             
                  not_debugging?(instance) && (error.message =~ /wrong number of arguments/ || error.message =~ /given \d*, expected \d*/) && begin
         | 
| 99 107 | 
             
                    saned = sans_backtrace(error.backtrace, caller)
         | 
| 100 | 
            -
                     | 
| 101 | 
            -
                    saned.empty? || (saned.size == 1 && RUBY_VERSION >= "1.9")
         | 
| 108 | 
            +
                    saned.empty? || saned.size == 1
         | 
| 102 109 | 
             
                  end
         | 
| 103 110 | 
             
                end
         | 
| 104 111 |  | 
    
        data/lib/thor/error.rb
    CHANGED
    
    | @@ -1,22 +1,18 @@ | |
| 1 1 | 
             
            class Thor
         | 
| 2 | 
            -
              Correctable =
         | 
| 3 | 
            -
             | 
| 4 | 
            -
             | 
| 5 | 
            -
             | 
| 6 | 
            -
             | 
| 7 | 
            -
             | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
             | 
| 17 | 
            -
                  DidYouMean::Correctable
         | 
| 18 | 
            -
                rescue LoadError, NameError
         | 
| 19 | 
            -
                end
         | 
| 2 | 
            +
              Correctable = if defined?(DidYouMean::SpellChecker) && defined?(DidYouMean::Correctable)
         | 
| 3 | 
            +
                              # In order to support versions of Ruby that don't have keyword
         | 
| 4 | 
            +
                              # arguments, we need our own spell checker class that doesn't take key
         | 
| 5 | 
            +
                              # words. Even though this code wouldn't be hit because of the check
         | 
| 6 | 
            +
                              # above, it's still necessary because the interpreter would otherwise be
         | 
| 7 | 
            +
                              # unable to parse the file.
         | 
| 8 | 
            +
                              class NoKwargSpellChecker < DidYouMean::SpellChecker # :nodoc:
         | 
| 9 | 
            +
                                def initialize(dictionary)
         | 
| 10 | 
            +
                                  @dictionary = dictionary
         | 
| 11 | 
            +
                                end
         | 
| 12 | 
            +
                              end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                              DidYouMean::Correctable
         | 
| 15 | 
            +
                            end
         | 
| 20 16 |  | 
| 21 17 | 
             
              # Thor::Error is raised when it's caused by wrong usage of thor classes. Those
         | 
| 22 18 | 
             
              # errors have their backtrace suppressed and are nicely shown to the user.
         | 
    
        data/lib/thor/group.rb
    CHANGED
    
    
    
        data/lib/thor/invocation.rb
    CHANGED
    
    
    
        data/lib/thor/line_editor.rb
    CHANGED
    
    
| @@ -1,19 +1,19 @@ | |
| 1 | 
            -
            begin
         | 
| 2 | 
            -
              require "readline"
         | 
| 3 | 
            -
            rescue LoadError
         | 
| 4 | 
            -
            end
         | 
| 5 | 
            -
             | 
| 6 1 | 
             
            class Thor
         | 
| 7 2 | 
             
              module LineEditor
         | 
| 8 3 | 
             
                class Readline < Basic
         | 
| 9 4 | 
             
                  def self.available?
         | 
| 5 | 
            +
                    begin
         | 
| 6 | 
            +
                      require "readline"
         | 
| 7 | 
            +
                    rescue LoadError
         | 
| 8 | 
            +
                    end
         | 
| 9 | 
            +
             | 
| 10 10 | 
             
                    Object.const_defined?(:Readline)
         | 
| 11 11 | 
             
                  end
         | 
| 12 12 |  | 
| 13 13 | 
             
                  def readline
         | 
| 14 14 | 
             
                    if echo?
         | 
| 15 15 | 
             
                      ::Readline.completion_append_character = nil
         | 
| 16 | 
            -
                      #  | 
| 16 | 
            +
                      # rb-readline does not allow Readline.completion_proc= to receive nil.
         | 
| 17 17 | 
             
                      if complete = completion_proc
         | 
| 18 18 | 
             
                        ::Readline.completion_proc = complete
         | 
| 19 19 | 
             
                      end
         | 
| @@ -0,0 +1,29 @@ | |
| 1 | 
            +
            class Thor
         | 
| 2 | 
            +
              class NestedContext
         | 
| 3 | 
            +
                def initialize
         | 
| 4 | 
            +
                  @depth = 0
         | 
| 5 | 
            +
                end
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                def enter
         | 
| 8 | 
            +
                  push
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  yield
         | 
| 11 | 
            +
                ensure
         | 
| 12 | 
            +
                  pop
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                def entered?
         | 
| 16 | 
            +
                  @depth > 0
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                private
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                def push
         | 
| 22 | 
            +
                  @depth += 1
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                def pop
         | 
| 26 | 
            +
                  @depth -= 1
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
            end
         | 
    
        data/lib/thor/parser.rb
    CHANGED
    
    | @@ -1,4 +1,4 @@ | |
| 1 | 
            -
             | 
| 2 | 
            -
             | 
| 3 | 
            -
             | 
| 4 | 
            -
             | 
| 1 | 
            +
            require_relative "parser/argument"
         | 
| 2 | 
            +
            require_relative "parser/arguments"
         | 
| 3 | 
            +
            require_relative "parser/option"
         | 
| 4 | 
            +
            require_relative "parser/options"
         | 
| @@ -9,7 +9,7 @@ class Thor | |
| 9 9 | 
             
                  arguments = []
         | 
| 10 10 |  | 
| 11 11 | 
             
                  args.each do |item|
         | 
| 12 | 
            -
                    break if item =~ /^-/
         | 
| 12 | 
            +
                    break if item.is_a?(String) && item =~ /^-/
         | 
| 13 13 | 
             
                    arguments << item
         | 
| 14 14 | 
             
                  end
         | 
| 15 15 |  | 
| @@ -82,7 +82,7 @@ class Thor | |
| 82 82 | 
             
                end
         | 
| 83 83 |  | 
| 84 84 | 
             
                def current_is_value?
         | 
| 85 | 
            -
                  peek && peek.to_s !~  | 
| 85 | 
            +
                  peek && peek.to_s !~ /^-{1,2}\S+/
         | 
| 86 86 | 
             
                end
         | 
| 87 87 |  | 
| 88 88 | 
             
                # Runs through the argument array getting strings that contains ":" and
         | 
    
        data/lib/thor/parser/option.rb
    CHANGED
    
    | @@ -1,17 +1,18 @@ | |
| 1 1 | 
             
            class Thor
         | 
| 2 2 | 
             
              class Option < Argument #:nodoc:
         | 
| 3 | 
            -
                attr_reader :aliases, :group, :lazy_default, :hide
         | 
| 3 | 
            +
                attr_reader :aliases, :group, :lazy_default, :hide, :repeatable
         | 
| 4 4 |  | 
| 5 5 | 
             
                VALID_TYPES = [:boolean, :numeric, :hash, :array, :string]
         | 
| 6 6 |  | 
| 7 7 | 
             
                def initialize(name, options = {})
         | 
| 8 8 | 
             
                  @check_default_type = options[:check_default_type]
         | 
| 9 9 | 
             
                  options[:required] = false unless options.key?(:required)
         | 
| 10 | 
            +
                  @repeatable     = options.fetch(:repeatable, false)
         | 
| 10 11 | 
             
                  super
         | 
| 11 | 
            -
                  @lazy_default | 
| 12 | 
            -
                  @group | 
| 13 | 
            -
                  @aliases | 
| 14 | 
            -
                  @hide | 
| 12 | 
            +
                  @lazy_default   = options[:lazy_default]
         | 
| 13 | 
            +
                  @group          = options[:group].to_s.capitalize if options[:group]
         | 
| 14 | 
            +
                  @aliases        = Array(options[:aliases])
         | 
| 15 | 
            +
                  @hide           = options[:hide]
         | 
| 15 16 | 
             
                end
         | 
| 16 17 |  | 
| 17 18 | 
             
                # This parse quick options given as method_options. It makes several
         | 
| @@ -111,7 +112,7 @@ class Thor | |
| 111 112 |  | 
| 112 113 | 
             
                def validate!
         | 
| 113 114 | 
             
                  raise ArgumentError, "An option cannot be boolean and required." if boolean? && required?
         | 
| 114 | 
            -
                  validate_default_type! | 
| 115 | 
            +
                  validate_default_type!
         | 
| 115 116 | 
             
                end
         | 
| 116 117 |  | 
| 117 118 | 
             
                def validate_default_type!
         | 
| @@ -128,7 +129,19 @@ class Thor | |
| 128 129 | 
             
                    @default.class.name.downcase.to_sym
         | 
| 129 130 | 
             
                  end
         | 
| 130 131 |  | 
| 131 | 
            -
                   | 
| 132 | 
            +
                  expected_type = (@repeatable && @type != :hash) ? :array : @type
         | 
| 133 | 
            +
             | 
| 134 | 
            +
                  if default_type != expected_type
         | 
| 135 | 
            +
                    err = "Expected #{expected_type} default value for '#{switch_name}'; got #{@default.inspect} (#{default_type})"
         | 
| 136 | 
            +
             | 
| 137 | 
            +
                    if @check_default_type
         | 
| 138 | 
            +
                      raise ArgumentError, err
         | 
| 139 | 
            +
                    elsif @check_default_type == nil
         | 
| 140 | 
            +
                      Thor.deprecation_warning "#{err}.\n" +
         | 
| 141 | 
            +
                        'This will be rejected in the future unless you explicitly pass the options `check_default_type: false`' +
         | 
| 142 | 
            +
                        ' or call `allow_incompatible_default_type!` in your code'
         | 
| 143 | 
            +
                    end
         | 
| 144 | 
            +
                  end
         | 
| 132 145 | 
             
                end
         | 
| 133 146 |  | 
| 134 147 | 
             
                def dasherized?
         | 
    
        data/lib/thor/parser/options.rb
    CHANGED
    
    | @@ -97,7 +97,8 @@ class Thor | |
| 97 97 |  | 
| 98 98 | 
             
                        switch = normalize_switch(switch)
         | 
| 99 99 | 
             
                        option = switch_option(switch)
         | 
| 100 | 
            -
                         | 
| 100 | 
            +
                        result = parse_peek(switch, option)
         | 
| 101 | 
            +
                        assign_result!(option, result)
         | 
| 101 102 | 
             
                      elsif @stop_on_unknown
         | 
| 102 103 | 
             
                        @parsing_options = false
         | 
| 103 104 | 
             
                        @extra << shifted
         | 
| @@ -132,6 +133,15 @@ class Thor | |
| 132 133 |  | 
| 133 134 | 
             
              protected
         | 
| 134 135 |  | 
| 136 | 
            +
              def assign_result!(option, result)
         | 
| 137 | 
            +
                if option.repeatable && option.type == :hash
         | 
| 138 | 
            +
                  (@assigns[option.human_name] ||= {}).merge!(result)
         | 
| 139 | 
            +
                elsif option.repeatable
         | 
| 140 | 
            +
                  (@assigns[option.human_name] ||= []) << result
         | 
| 141 | 
            +
                else
         | 
| 142 | 
            +
                  @assigns[option.human_name] = result
         | 
| 143 | 
            +
                end
         | 
| 144 | 
            +
              end
         | 
| 135 145 | 
             
                # Check if the current value in peek is a registered switch.
         | 
| 136 146 | 
             
                #
         | 
| 137 147 | 
             
                # Two booleans are returned.  The first is true if the current value
         | 
| @@ -161,7 +171,7 @@ class Thor | |
| 161 171 | 
             
                end
         | 
| 162 172 |  | 
| 163 173 | 
             
                def switch?(arg)
         | 
| 164 | 
            -
                  switch_option(normalize_switch(arg))
         | 
| 174 | 
            +
                  !switch_option(normalize_switch(arg)).nil?
         | 
| 165 175 | 
             
                end
         | 
| 166 176 |  | 
| 167 177 | 
             
                def switch_option(arg)
         | 
| @@ -194,7 +204,7 @@ class Thor | |
| 194 204 | 
             
                      shift
         | 
| 195 205 | 
             
                      false
         | 
| 196 206 | 
             
                    else
         | 
| 197 | 
            -
                      !no_or_skip?(switch)
         | 
| 207 | 
            +
                      @switches.key?(switch) || !no_or_skip?(switch)
         | 
| 198 208 | 
             
                    end
         | 
| 199 209 | 
             
                  else
         | 
| 200 210 | 
             
                    @switches.key?(switch) || !no_or_skip?(switch)
         | 
    
        data/lib/thor/rake_compat.rb
    CHANGED
    
    | @@ -25,6 +25,7 @@ class Thor | |
| 25 25 | 
             
                end
         | 
| 26 26 |  | 
| 27 27 | 
             
                def self.included(base)
         | 
| 28 | 
            +
                  super(base)
         | 
| 28 29 | 
             
                  # Hack. Make rakefile point to invoker, so rdoc task is generated properly.
         | 
| 29 30 | 
             
                  rakefile = File.basename(caller[0].match(/(.*):\d+/)[1])
         | 
| 30 31 | 
             
                  Rake.application.instance_variable_set(:@rakefile, rakefile)
         | 
    
        data/lib/thor/runner.rb
    CHANGED
    
    | @@ -1,12 +1,13 @@ | |
| 1 | 
            -
             | 
| 2 | 
            -
             | 
| 3 | 
            -
            require "thor/core_ext/io_binary_read"
         | 
| 1 | 
            +
            require_relative "../thor"
         | 
| 2 | 
            +
            require_relative "group"
         | 
| 4 3 |  | 
| 5 4 | 
             
            require "yaml"
         | 
| 6 5 | 
             
            require "digest/md5"
         | 
| 7 6 | 
             
            require "pathname"
         | 
| 8 7 |  | 
| 9 8 | 
             
            class Thor::Runner < Thor #:nodoc: # rubocop:disable ClassLength
         | 
| 9 | 
            +
              autoload :OpenURI, "open-uri"
         | 
| 10 | 
            +
             | 
| 10 11 | 
             
              map "-T" => :list, "-i" => :install, "-u" => :update, "-v" => :version
         | 
| 11 12 |  | 
| 12 13 | 
             
              def self.banner(command, all = false, subcommand = false)
         | 
| @@ -111,7 +112,7 @@ class Thor::Runner < Thor #:nodoc: # rubocop:disable ClassLength | |
| 111 112 |  | 
| 112 113 | 
             
              desc "version", "Show Thor version"
         | 
| 113 114 | 
             
              def version
         | 
| 114 | 
            -
                 | 
| 115 | 
            +
                require_relative "version"
         | 
| 115 116 | 
             
                say "Thor #{Thor::VERSION}"
         | 
| 116 117 | 
             
              end
         | 
| 117 118 |  | 
    
        data/lib/thor/shell.rb
    CHANGED
    
    | @@ -24,9 +24,9 @@ class Thor | |
| 24 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 25 | 
             
                attr_writer :shell
         | 
| 26 26 |  | 
| 27 | 
            -
                autoload :Basic, " | 
| 28 | 
            -
                autoload :Color, " | 
| 29 | 
            -
                autoload :HTML,  " | 
| 27 | 
            +
                autoload :Basic, File.expand_path("shell/basic", __dir__)
         | 
| 28 | 
            +
                autoload :Color, File.expand_path("shell/color", __dir__)
         | 
| 29 | 
            +
                autoload :HTML,  File.expand_path("shell/html", __dir__)
         | 
| 30 30 |  | 
| 31 31 | 
             
                # Add shell to initialize config values.
         | 
| 32 32 | 
             
                #
         | 
    
        data/lib/thor/shell/basic.rb
    CHANGED
    
    | @@ -451,16 +451,25 @@ class Thor | |
| 451 451 |  | 
| 452 452 | 
             
                  def ask_filtered(statement, color, options)
         | 
| 453 453 | 
             
                    answer_set = options[:limited_to]
         | 
| 454 | 
            +
                    case_insensitive = options.fetch(:case_insensitive, false)
         | 
| 454 455 | 
             
                    correct_answer = nil
         | 
| 455 456 | 
             
                    until correct_answer
         | 
| 456 457 | 
             
                      answers = answer_set.join(", ")
         | 
| 457 458 | 
             
                      answer = ask_simply("#{statement} [#{answers}]", color, options)
         | 
| 458 | 
            -
                      correct_answer = answer_set | 
| 459 | 
            +
                      correct_answer = answer_match(answer_set, answer, case_insensitive)
         | 
| 459 460 | 
             
                      say("Your response must be one of: [#{answers}]. Please try again.") unless correct_answer
         | 
| 460 461 | 
             
                    end
         | 
| 461 462 | 
             
                    correct_answer
         | 
| 462 463 | 
             
                  end
         | 
| 463 464 |  | 
| 465 | 
            +
                  def answer_match(possibilities, answer, case_insensitive)
         | 
| 466 | 
            +
                    if case_insensitive
         | 
| 467 | 
            +
                      possibilities.detect{ |possibility| possibility.downcase == answer.downcase }
         | 
| 468 | 
            +
                    else
         | 
| 469 | 
            +
                      possibilities.detect{ |possibility| possibility == answer }
         | 
| 470 | 
            +
                    end
         | 
| 471 | 
            +
                  end
         | 
| 472 | 
            +
             | 
| 464 473 | 
             
                  def merge(destination, content) #:nodoc:
         | 
| 465 474 | 
             
                    require "tempfile"
         | 
| 466 475 | 
             
                    Tempfile.open([File.basename(destination), File.extname(destination)], File.dirname(destination)) do |temp|
         | 
    
        data/lib/thor/shell/color.rb
    CHANGED
    
    | @@ -1,4 +1,4 @@ | |
| 1 | 
            -
             | 
| 1 | 
            +
            require_relative "basic"
         | 
| 2 2 |  | 
| 3 3 | 
             
            class Thor
         | 
| 4 4 | 
             
              module Shell
         | 
| @@ -97,7 +97,11 @@ class Thor | |
| 97 97 | 
             
                protected
         | 
| 98 98 |  | 
| 99 99 | 
             
                  def can_display_colors?
         | 
| 100 | 
            -
                    stdout.tty?
         | 
| 100 | 
            +
                    stdout.tty? && !are_colors_disabled?
         | 
| 101 | 
            +
                  end
         | 
| 102 | 
            +
             | 
| 103 | 
            +
                  def are_colors_disabled?
         | 
| 104 | 
            +
                    !ENV['NO_COLOR'].nil?
         | 
| 101 105 | 
             
                  end
         | 
| 102 106 |  | 
| 103 107 | 
             
                  # Overwrite show_diff to show diff with colors if Diff::LCS is
         | 
    
        data/lib/thor/shell/html.rb
    CHANGED
    
    | @@ -1,4 +1,4 @@ | |
| 1 | 
            -
             | 
| 1 | 
            +
            require_relative "basic"
         | 
| 2 2 |  | 
| 3 3 | 
             
            class Thor
         | 
| 4 4 | 
             
              module Shell
         | 
| @@ -51,13 +51,13 @@ class Thor | |
| 51 51 | 
             
                  def set_color(string, *colors)
         | 
| 52 52 | 
             
                    if colors.all? { |color| color.is_a?(Symbol) || color.is_a?(String) }
         | 
| 53 53 | 
             
                      html_colors = colors.map { |color| lookup_color(color) }
         | 
| 54 | 
            -
                      "<span style=\"#{html_colors.join('; ')};\">#{string}</span>"
         | 
| 54 | 
            +
                      "<span style=\"#{html_colors.join('; ')};\">#{Thor::Util.escape_html(string)}</span>"
         | 
| 55 55 | 
             
                    else
         | 
| 56 56 | 
             
                      color, bold = colors
         | 
| 57 57 | 
             
                      html_color = self.class.const_get(color.to_s.upcase) if color.is_a?(Symbol)
         | 
| 58 58 | 
             
                      styles = [html_color]
         | 
| 59 59 | 
             
                      styles << BOLD if bold
         | 
| 60 | 
            -
                      "<span style=\"#{styles.join('; ')};\">#{string}</span>"
         | 
| 60 | 
            +
                      "<span style=\"#{styles.join('; ')};\">#{Thor::Util.escape_html(string)}</span>"
         | 
| 61 61 | 
             
                    end
         | 
| 62 62 | 
             
                  end
         | 
| 63 63 |  | 
    
        data/lib/thor/util.rb
    CHANGED
    
    | @@ -263,6 +263,22 @@ class Thor | |
| 263 263 | 
             
                  def escape_globs(path)
         | 
| 264 264 | 
             
                    path.to_s.gsub(/[*?{}\[\]]/, '\\\\\\&')
         | 
| 265 265 | 
             
                  end
         | 
| 266 | 
            +
             | 
| 267 | 
            +
                  # Returns a string that has had any HTML characters escaped.
         | 
| 268 | 
            +
                  #
         | 
| 269 | 
            +
                  # ==== Examples
         | 
| 270 | 
            +
                  #
         | 
| 271 | 
            +
                  #   Thor::Util.escape_html('<div>')   # => "<div>"
         | 
| 272 | 
            +
                  #
         | 
| 273 | 
            +
                  # ==== Parameters
         | 
| 274 | 
            +
                  # String
         | 
| 275 | 
            +
                  #
         | 
| 276 | 
            +
                  # ==== Returns
         | 
| 277 | 
            +
                  # String
         | 
| 278 | 
            +
                  #
         | 
| 279 | 
            +
                  def escape_html(string)
         | 
| 280 | 
            +
                    CGI.escapeHTML(string)
         | 
| 281 | 
            +
                  end
         | 
| 266 282 | 
             
                end
         | 
| 267 283 | 
             
              end
         | 
| 268 284 | 
             
            end
         | 
    
        data/lib/thor/version.rb
    CHANGED
    
    
    
        data/thor.gemspec
    CHANGED
    
    | @@ -4,7 +4,7 @@ $LOAD_PATH.unshift lib unless $LOAD_PATH.include?(lib) | |
| 4 4 | 
             
            require "thor/version"
         | 
| 5 5 |  | 
| 6 6 | 
             
            Gem::Specification.new do |spec|
         | 
| 7 | 
            -
              spec.add_development_dependency "bundler", " | 
| 7 | 
            +
              spec.add_development_dependency "bundler", ">= 1.0", "< 3"
         | 
| 8 8 | 
             
              spec.authors = ["Yehuda Katz", "José Valim"]
         | 
| 9 9 | 
             
              spec.description = "Thor is a toolkit for building powerful command-line interfaces."
         | 
| 10 10 | 
             
              spec.email = "ruby-thor@googlegroups.com"
         | 
| @@ -13,8 +13,15 @@ Gem::Specification.new do |spec| | |
| 13 13 | 
             
              spec.homepage = "http://whatisthor.com/"
         | 
| 14 14 | 
             
              spec.licenses = %w(MIT)
         | 
| 15 15 | 
             
              spec.name = "thor"
         | 
| 16 | 
            +
              spec.metadata = {
         | 
| 17 | 
            +
                "bug_tracker_uri" => "https://github.com/erikhuda/thor/issues",
         | 
| 18 | 
            +
                "changelog_uri" => "https://github.com/erikhuda/thor/blob/master/CHANGELOG.md",
         | 
| 19 | 
            +
                "documentation_uri" => "http://whatisthor.com/",
         | 
| 20 | 
            +
                "source_code_uri" => "https://github.com/erikhuda/thor/tree/v#{Thor::VERSION}",
         | 
| 21 | 
            +
                "wiki_uri" => "https://github.com/erikhuda/thor/wiki"
         | 
| 22 | 
            +
              }
         | 
| 16 23 | 
             
              spec.require_paths = %w(lib)
         | 
| 17 | 
            -
              spec.required_ruby_version = ">=  | 
| 24 | 
            +
              spec.required_ruby_version = ">= 2.0.0"
         | 
| 18 25 | 
             
              spec.required_rubygems_version = ">= 1.3.5"
         | 
| 19 26 | 
             
              spec.summary = spec.description
         | 
| 20 27 | 
             
              spec.version = Thor::VERSION
         | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: thor
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 1.0.1
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Yehuda Katz
         | 
| @@ -9,22 +9,28 @@ authors: | |
| 9 9 | 
             
            autorequire: 
         | 
| 10 10 | 
             
            bindir: bin
         | 
| 11 11 | 
             
            cert_chain: []
         | 
| 12 | 
            -
            date:  | 
| 12 | 
            +
            date: 2019-12-17 00:00:00.000000000 Z
         | 
| 13 13 | 
             
            dependencies:
         | 
| 14 14 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 15 15 | 
             
              name: bundler
         | 
| 16 16 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 17 17 | 
             
                requirements:
         | 
| 18 | 
            -
                - - " | 
| 18 | 
            +
                - - ">="
         | 
| 19 19 | 
             
                  - !ruby/object:Gem::Version
         | 
| 20 20 | 
             
                    version: '1.0'
         | 
| 21 | 
            +
                - - "<"
         | 
| 22 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 23 | 
            +
                    version: '3'
         | 
| 21 24 | 
             
              type: :development
         | 
| 22 25 | 
             
              prerelease: false
         | 
| 23 26 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 24 27 | 
             
                requirements:
         | 
| 25 | 
            -
                - - " | 
| 28 | 
            +
                - - ">="
         | 
| 26 29 | 
             
                  - !ruby/object:Gem::Version
         | 
| 27 30 | 
             
                    version: '1.0'
         | 
| 31 | 
            +
                - - "<"
         | 
| 32 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 33 | 
            +
                    version: '3'
         | 
| 28 34 | 
             
            description: Thor is a toolkit for building powerful command-line interfaces.
         | 
| 29 35 | 
             
            email: ruby-thor@googlegroups.com
         | 
| 30 36 | 
             
            executables:
         | 
| @@ -49,14 +55,13 @@ files: | |
| 49 55 | 
             
            - lib/thor/base.rb
         | 
| 50 56 | 
             
            - lib/thor/command.rb
         | 
| 51 57 | 
             
            - lib/thor/core_ext/hash_with_indifferent_access.rb
         | 
| 52 | 
            -
            - lib/thor/core_ext/io_binary_read.rb
         | 
| 53 | 
            -
            - lib/thor/core_ext/ordered_hash.rb
         | 
| 54 58 | 
             
            - lib/thor/error.rb
         | 
| 55 59 | 
             
            - lib/thor/group.rb
         | 
| 56 60 | 
             
            - lib/thor/invocation.rb
         | 
| 57 61 | 
             
            - lib/thor/line_editor.rb
         | 
| 58 62 | 
             
            - lib/thor/line_editor/basic.rb
         | 
| 59 63 | 
             
            - lib/thor/line_editor/readline.rb
         | 
| 64 | 
            +
            - lib/thor/nested_context.rb
         | 
| 60 65 | 
             
            - lib/thor/parser.rb
         | 
| 61 66 | 
             
            - lib/thor/parser/argument.rb
         | 
| 62 67 | 
             
            - lib/thor/parser/arguments.rb
         | 
| @@ -74,7 +79,12 @@ files: | |
| 74 79 | 
             
            homepage: http://whatisthor.com/
         | 
| 75 80 | 
             
            licenses:
         | 
| 76 81 | 
             
            - MIT
         | 
| 77 | 
            -
            metadata: | 
| 82 | 
            +
            metadata:
         | 
| 83 | 
            +
              bug_tracker_uri: https://github.com/erikhuda/thor/issues
         | 
| 84 | 
            +
              changelog_uri: https://github.com/erikhuda/thor/blob/master/CHANGELOG.md
         | 
| 85 | 
            +
              documentation_uri: http://whatisthor.com/
         | 
| 86 | 
            +
              source_code_uri: https://github.com/erikhuda/thor/tree/v1.0.1
         | 
| 87 | 
            +
              wiki_uri: https://github.com/erikhuda/thor/wiki
         | 
| 78 88 | 
             
            post_install_message: 
         | 
| 79 89 | 
             
            rdoc_options: []
         | 
| 80 90 | 
             
            require_paths:
         | 
| @@ -83,15 +93,14 @@ required_ruby_version: !ruby/object:Gem::Requirement | |
| 83 93 | 
             
              requirements:
         | 
| 84 94 | 
             
              - - ">="
         | 
| 85 95 | 
             
                - !ruby/object:Gem::Version
         | 
| 86 | 
            -
                  version:  | 
| 96 | 
            +
                  version: 2.0.0
         | 
| 87 97 | 
             
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 88 98 | 
             
              requirements:
         | 
| 89 99 | 
             
              - - ">="
         | 
| 90 100 | 
             
                - !ruby/object:Gem::Version
         | 
| 91 101 | 
             
                  version: 1.3.5
         | 
| 92 102 | 
             
            requirements: []
         | 
| 93 | 
            -
             | 
| 94 | 
            -
            rubygems_version: 2.7.6
         | 
| 103 | 
            +
            rubygems_version: 3.0.3
         | 
| 95 104 | 
             
            signing_key: 
         | 
| 96 105 | 
             
            specification_version: 4
         | 
| 97 106 | 
             
            summary: Thor is a toolkit for building powerful command-line interfaces.
         | 
| @@ -1,12 +0,0 @@ | |
| 1 | 
            -
            class IO #:nodoc:
         | 
| 2 | 
            -
              class << self
         | 
| 3 | 
            -
                unless method_defined? :binread
         | 
| 4 | 
            -
                  def binread(file, *args)
         | 
| 5 | 
            -
                    raise ArgumentError, "wrong number of arguments (#{1 + args.size} for 1..3)" unless args.size < 3
         | 
| 6 | 
            -
                    File.open(file, "rb") do |f|
         | 
| 7 | 
            -
                      f.read(*args)
         | 
| 8 | 
            -
                    end
         | 
| 9 | 
            -
                  end
         | 
| 10 | 
            -
                end
         | 
| 11 | 
            -
              end
         | 
| 12 | 
            -
            end
         | 
| @@ -1,129 +0,0 @@ | |
| 1 | 
            -
            class Thor
         | 
| 2 | 
            -
              module CoreExt
         | 
| 3 | 
            -
                class OrderedHash < ::Hash
         | 
| 4 | 
            -
                  if RUBY_VERSION < "1.9"
         | 
| 5 | 
            -
                    def initialize(*args, &block)
         | 
| 6 | 
            -
                      super
         | 
| 7 | 
            -
                      @keys = []
         | 
| 8 | 
            -
                    end
         | 
| 9 | 
            -
             | 
| 10 | 
            -
                    def initialize_copy(other)
         | 
| 11 | 
            -
                      super
         | 
| 12 | 
            -
                      # make a deep copy of keys
         | 
| 13 | 
            -
                      @keys = other.keys
         | 
| 14 | 
            -
                    end
         | 
| 15 | 
            -
             | 
| 16 | 
            -
                    def []=(key, value)
         | 
| 17 | 
            -
                      @keys << key unless key?(key)
         | 
| 18 | 
            -
                      super
         | 
| 19 | 
            -
                    end
         | 
| 20 | 
            -
             | 
| 21 | 
            -
                    def delete(key)
         | 
| 22 | 
            -
                      if key? key
         | 
| 23 | 
            -
                        index = @keys.index(key)
         | 
| 24 | 
            -
                        @keys.delete_at index
         | 
| 25 | 
            -
                      end
         | 
| 26 | 
            -
                      super
         | 
| 27 | 
            -
                    end
         | 
| 28 | 
            -
             | 
| 29 | 
            -
                    def delete_if
         | 
| 30 | 
            -
                      super
         | 
| 31 | 
            -
                      sync_keys!
         | 
| 32 | 
            -
                      self
         | 
| 33 | 
            -
                    end
         | 
| 34 | 
            -
             | 
| 35 | 
            -
                    alias_method :reject!, :delete_if
         | 
| 36 | 
            -
             | 
| 37 | 
            -
                    def reject(&block)
         | 
| 38 | 
            -
                      dup.reject!(&block)
         | 
| 39 | 
            -
                    end
         | 
| 40 | 
            -
             | 
| 41 | 
            -
                    def keys
         | 
| 42 | 
            -
                      @keys.dup
         | 
| 43 | 
            -
                    end
         | 
| 44 | 
            -
             | 
| 45 | 
            -
                    def values
         | 
| 46 | 
            -
                      @keys.map { |key| self[key] }
         | 
| 47 | 
            -
                    end
         | 
| 48 | 
            -
             | 
| 49 | 
            -
                    def to_hash
         | 
| 50 | 
            -
                      self
         | 
| 51 | 
            -
                    end
         | 
| 52 | 
            -
             | 
| 53 | 
            -
                    def to_a
         | 
| 54 | 
            -
                      @keys.map { |key| [key, self[key]] }
         | 
| 55 | 
            -
                    end
         | 
| 56 | 
            -
             | 
| 57 | 
            -
                    def each_key
         | 
| 58 | 
            -
                      return to_enum(:each_key) unless block_given?
         | 
| 59 | 
            -
                      @keys.each { |key| yield(key) }
         | 
| 60 | 
            -
                      self
         | 
| 61 | 
            -
                    end
         | 
| 62 | 
            -
             | 
| 63 | 
            -
                    def each_value
         | 
| 64 | 
            -
                      return to_enum(:each_value) unless block_given?
         | 
| 65 | 
            -
                      @keys.each { |key| yield(self[key]) }
         | 
| 66 | 
            -
                      self
         | 
| 67 | 
            -
                    end
         | 
| 68 | 
            -
             | 
| 69 | 
            -
                    def each
         | 
| 70 | 
            -
                      return to_enum(:each) unless block_given?
         | 
| 71 | 
            -
                      @keys.each { |key| yield([key, self[key]]) }
         | 
| 72 | 
            -
                      self
         | 
| 73 | 
            -
                    end
         | 
| 74 | 
            -
             | 
| 75 | 
            -
                    def each_pair
         | 
| 76 | 
            -
                      return to_enum(:each_pair) unless block_given?
         | 
| 77 | 
            -
                      @keys.each { |key| yield(key, self[key]) }
         | 
| 78 | 
            -
                      self
         | 
| 79 | 
            -
                    end
         | 
| 80 | 
            -
             | 
| 81 | 
            -
                    alias_method :select, :find_all
         | 
| 82 | 
            -
             | 
| 83 | 
            -
                    def clear
         | 
| 84 | 
            -
                      super
         | 
| 85 | 
            -
                      @keys.clear
         | 
| 86 | 
            -
                      self
         | 
| 87 | 
            -
                    end
         | 
| 88 | 
            -
             | 
| 89 | 
            -
                    def shift
         | 
| 90 | 
            -
                      k = @keys.first
         | 
| 91 | 
            -
                      v = delete(k)
         | 
| 92 | 
            -
                      [k, v]
         | 
| 93 | 
            -
                    end
         | 
| 94 | 
            -
             | 
| 95 | 
            -
                    def merge!(other_hash)
         | 
| 96 | 
            -
                      if block_given?
         | 
| 97 | 
            -
                        other_hash.each { |k, v| self[k] = key?(k) ? yield(k, self[k], v) : v }
         | 
| 98 | 
            -
                      else
         | 
| 99 | 
            -
                        other_hash.each { |k, v| self[k] = v }
         | 
| 100 | 
            -
                      end
         | 
| 101 | 
            -
                      self
         | 
| 102 | 
            -
                    end
         | 
| 103 | 
            -
             | 
| 104 | 
            -
                    alias_method :update, :merge!
         | 
| 105 | 
            -
             | 
| 106 | 
            -
                    def merge(other_hash, &block)
         | 
| 107 | 
            -
                      dup.merge!(other_hash, &block)
         | 
| 108 | 
            -
                    end
         | 
| 109 | 
            -
             | 
| 110 | 
            -
                    # When replacing with another hash, the initial order of our keys must come from the other hash -ordered or not.
         | 
| 111 | 
            -
                    def replace(other)
         | 
| 112 | 
            -
                      super
         | 
| 113 | 
            -
                      @keys = other.keys
         | 
| 114 | 
            -
                      self
         | 
| 115 | 
            -
                    end
         | 
| 116 | 
            -
             | 
| 117 | 
            -
                    def inspect
         | 
| 118 | 
            -
                      "#<#{self.class} #{super}>"
         | 
| 119 | 
            -
                    end
         | 
| 120 | 
            -
             | 
| 121 | 
            -
                    private
         | 
| 122 | 
            -
             | 
| 123 | 
            -
                    def sync_keys!
         | 
| 124 | 
            -
                      @keys.delete_if { |k| !key?(k) }
         | 
| 125 | 
            -
                    end
         | 
| 126 | 
            -
                  end
         | 
| 127 | 
            -
                end
         | 
| 128 | 
            -
              end
         | 
| 129 | 
            -
            end
         |