From 4fe5f7044773f595298b6af2094f9b2c4cfbda5e Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Sun, 1 Apr 2012 16:00:59 -0700 Subject: [PATCH] Rename Command#name -> Command#match MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The problem with using "name" for this is that several tools expect Class#name to return a String, and Commands are classes. This could cause some subtle breakage, but the tests seem ok™ --- lib/pry/command.rb | 43 ++++++++------ lib/pry/command_set.rb | 121 +++++++++++++++++++-------------------- test/test_command_set.rb | 6 +- 3 files changed, 88 insertions(+), 82 deletions(-) diff --git a/lib/pry/command.rb b/lib/pry/command.rb index 1fe36059..c31f980b 100644 --- a/lib/pry/command.rb +++ b/lib/pry/command.rb @@ -15,9 +15,14 @@ class Pry # {CommandSet#command} or {CommandSet#create_command}). class << self attr_accessor :block - attr_accessor :name attr_writer :description attr_writer :command_options + attr_writer :match + + def match(arg=nil) + @match = arg if arg + @match + end # Define or get the command's description def description(arg=nil) @@ -44,19 +49,23 @@ class Pry # Make those properties accessible to instances def name; self.class.name; end + def match; self.class.match; end def description; self.class.description; end def block; self.class.block; end def command_options; self.class.options; end def command_name; command_options[:listing]; end class << self + def name + super.to_s == "" ? "#" : super + end def inspect - "#" + name end # Create a new command with the given properties. # - # @param String name the name of the command + # @param String/Regex match the thing that triggers this command # @param String description the description to appear in {help} # @param Hash options behavioural options (@see {Pry::CommandSet#command}) # @param Module helpers a module of helper functions to be included. @@ -64,10 +73,10 @@ class Pry # # @return Class (a subclass of Pry::Command) # - def subclass(name, description, options, helpers, &block) + def subclass(match, description, options, helpers, &block) klass = Class.new(self) klass.send(:include, helpers) - klass.name = name + klass.match = match klass.description = description klass.command_options = options klass.block = block @@ -117,7 +126,7 @@ class Pry prefix = convert_to_regex(Pry.config.command_prefix) prefix = "(?:#{prefix})?" unless options[:use_prefix] - /^#{prefix}#{convert_to_regex(name)}(?!\S)/ + /^#{prefix}#{convert_to_regex(match)}(?!\S)/ end def convert_to_regex(obj) @@ -232,12 +241,12 @@ class Pry # the current scope. # @param [String] command_name_match The name of the colliding command. # @param [Binding] target The current binding context. - def check_for_command_name_collision(command_name_match, arg_string) - collision_type = target.eval("defined?(#{command_name_match})") + def check_for_command_collision(command_match, arg_string) + collision_type = target.eval("defined?(#{command_match})") collision_type ||= 'local-variable' if arg_string.match(%r{\A\s*[-+*/%&|^]*=}) if collision_type - output.puts "#{Pry::Helpers::Text.bold('WARNING:')} Calling Pry command '#{command_name_match}'," + + output.puts "#{Pry::Helpers::Text.bold('WARNING:')} Calling Pry command '#{command_match}'," + "which conflicts with a #{collision_type}.\n\n" end rescue Pry::RescuableException @@ -247,8 +256,8 @@ class Pry # # @param String the line of input # @return [ - # String the command name used, or portion of line that matched the command_regex - # String a string of all the arguments (i.e. everything but the name) + # String the portion of the line that matched with the Command match + # String a string of all the arguments (i.e. everything but the match) # Array the captures caught by the command_regex # Array args the arguments got by splitting the arg_string # ] @@ -284,9 +293,9 @@ class Pry # @param String the line to process # @return Object or Command::VOID_VALUE def process_line(line) - command_name, arg_string, captures, args = tokenize(line) + command_match, arg_string, captures, args = tokenize(line) - check_for_command_name_collision(command_name, arg_string) if Pry.config.collision_warning + check_for_command_collision(command_match, arg_string) if Pry.config.collision_warning self.arg_string = arg_string self.captures = captures @@ -334,14 +343,14 @@ class Pry unless dependencies_met? gems_needed = Array(command_options[:requires_gem]) gems_not_installed = gems_needed.select { |g| !gem_installed?(g) } - output.puts "\nThe command '#{name}' is #{Helpers::Text.bold("unavailable")} because it requires the following gems to be installed: #{(gems_not_installed.join(", "))}" + output.puts "\nThe command '#{command_name}' is #{Helpers::Text.bold("unavailable")} because it requires the following gems to be installed: #{(gems_not_installed.join(", "))}" output.puts "-" - output.puts "Type `install-command #{name}` to install the required gems and activate this command." + output.puts "Type `install-command #{command_name}` to install the required gems and activate this command." return void end if command_options[:argument_required] && args.empty? - raise CommandError, "The command '#{name}' requires an argument." + raise CommandError, "The command '#{command_name}' requires an argument." end ret = call_with_hooks(*args) @@ -506,6 +515,6 @@ class Pry # gist_method # end # end - def process; raise CommandError, "command '#{name}' not implemented" end + def process; raise CommandError, "command '#{command_name}' not implemented" end end end diff --git a/lib/pry/command_set.rb b/lib/pry/command_set.rb index 755a2f43..986acda9 100644 --- a/lib/pry/command_set.rb +++ b/lib/pry/command_set.rb @@ -1,7 +1,7 @@ class Pry class NoCommandError < StandardError - def initialize(name, owner) - super "Command '#{name}' not found in command set #{owner}" + def initialize(match, owner) + super "Command '#{match}' not found in command set #{owner}" end end @@ -27,8 +27,7 @@ class Pry end # Defines a new Pry command. - # @param [String, Regexp] name The name of the command. Can be - # Regexp as well as String. + # @param [String, Regexp] match The start of invocations of this command. # @param [String] description A description of the command. # @param [Hash] options The optional configuration parameters. # @option options [Boolean] :keep_retval Whether or not to use return value @@ -43,7 +42,7 @@ class Pry # executing the command. Defaults to true. # @option options [String] :listing The listing name of the # command. That is the name by which the command is looked up by - # help and by show-command. Necessary for regex based commands. + # help and by show-command. Necessary for commands with regex matches. # @option options [Boolean] :use_prefix Whether the command uses # `Pry.config.command_prefix` prefix (if one is defined). Defaults # to true. @@ -80,18 +79,17 @@ class Pry # # hello john, nice number: 10 # # pry(main)> help number # # number-N regex command - def block_command(name, description="No description.", options={}, &block) + def block_command(match, description="No description.", options={}, &block) description, options = ["No description.", description] if description.is_a?(Hash) - options = default_options(name).merge!(options) + options = default_options(match).merge!(options) - commands[name] = Pry::BlockCommand.subclass(name, description, options, helper_module, &block) + commands[match] = Pry::BlockCommand.subclass(match, description, options, helper_module, &block) end alias_method :command, :block_command # Defines a new Pry command class. # - # @param [String, Regexp] name The name of the command. Can be - # Regexp as well as String. + # @param [String, Regexp] match The start of invocations of this command. # @param [String] description A description of the command. # @param [Hash] options The optional configuration parameters, see {#command} # @param &Block The class body's definition. @@ -113,40 +111,40 @@ class Pry # end # end # - def create_command(name, description="No description.", options={}, &block) + def create_command(match, description="No description.", options={}, &block) description, options = ["No description.", description] if description.is_a?(Hash) - options = default_options(name).merge!(options) + options = default_options(match).merge!(options) - commands[name] = Pry::ClassCommand.subclass(name, description, options, helper_module, &block) - commands[name].class_eval(&block) - commands[name] + commands[match] = Pry::ClassCommand.subclass(match, description, options, helper_module, &block) + commands[match].class_eval(&block) + commands[match] end # Execute a block of code before a command is invoked. The block also # gets access to parameters that will be passed to the command and # is evaluated in the same context. - # @param [String, Regexp] name The name of the command. + # @param [String, Regexp] search The match or listing of the command. # @yield The block to be run before the command. # @example Display parameter before invoking command # Pry.commands.before_command("whereami") do |n| # output.puts "parameter passed was #{n}" # end - def before_command(name, &block) - cmd = find_command_by_name_or_listing(name) + def before_command(search, &block) + cmd = find_command_by_match_or_listing(search) cmd.hooks[:before].unshift block end # Execute a block of code after a command is invoked. The block also # gets access to parameters that will be passed to the command and # is evaluated in the same context. - # @param [String, Regexp] name The name of the command. + # @param [String, Regexp] search The match or listing of the command. # @yield The block to be run after the command. # @example Display text 'command complete' after invoking command # Pry.commands.after_command("whereami") do |n| # output.puts "command complete!" # end - def after_command(name, &block) - cmd = find_command_by_name_or_listing(name) + def after_command(search, &block) + cmd = find_command_by_match_or_listing(search) cmd.hooks[:after] << block end @@ -155,11 +153,11 @@ class Pry end # Removes some commands from the set - # @param [Array] names name of the commands to remove - def delete(*names) - names.each do |name| - cmd = find_command_by_name_or_listing(name) - commands.delete cmd.name + # @param [Array] searches the matches or listings of the commands to remove + def delete(*searches) + searches.each do |search| + cmd = find_command_by_match_or_listing(search) + commands.delete cmd.match end end @@ -175,34 +173,34 @@ class Pry # Imports some commands from a set # @param [CommandSet] set Set to import commands from - # @param [Array] names Commands to import - def import_from(set, *names) + # @param [Array] matches Commands to import + def import_from(set, *matches) helper_module.send :include, set.helper_module - names.each do |name| - cmd = set.find_command_by_name_or_listing(name) - commands[cmd.name] = cmd + matches.each do |match| + cmd = set.find_command_by_match_or_listing(match) + commands[cmd.match] = cmd end end - # @param [String, Regexp] name_or_listing The name or listing name + # @param [String, Regexp] match_or_listing The match or listing of a command. # of the command to retrieve. # @return [Command] The command object matched. - def find_command_by_name_or_listing(name_or_listing) - if commands[name_or_listing] - cmd = commands[name_or_listing] + def find_command_by_match_or_listing(match_or_listing) + if commands[match_or_listing] + cmd = commands[match_or_listing] else - _, cmd = commands.find { |name, command| command.options[:listing] == name_or_listing } + _, cmd = commands.find { |match, command| command.options[:listing] == match_or_listing } end - raise ArgumentError, "Cannot find a command with name: '#{name_or_listing}'!" if !cmd + raise ArgumentError, "Cannot find a command: '#{match_or_listing}'!" if !cmd cmd end - protected :find_command_by_name_or_listing + protected :find_command_by_match_or_listing # Aliases a command # Note that if `desc` parameter is `nil` then the default # description is used. - # @param [String, Regex] name The name of the alias (can be a regex). + # @param [String, Regex] match The match of the alias (can be a regex). # @param [String] action The action to be performed (typically # another command). # @param [Hash] options The optional configuration parameters, @@ -212,7 +210,7 @@ class Pry # Pry.config.commands.alias_command "lM", "ls -M" # @example Pass explicit description (overriding default). # Pry.config.commands.alias_command "lM", "ls -M", :desc => "cutiepie" - def alias_command(name, action, options={}) + def alias_command(match, action, options={}) options = { :desc => "Alias for `#{action}`", }.merge!(options) @@ -220,7 +218,7 @@ class Pry # ensure default description is used if desc is nil desc = options.delete(:desc).to_s - c = block_command name, desc, options do |*args| + c = block_command match, desc, options do |*args| run action, *args end @@ -229,35 +227,34 @@ class Pry c end - # Rename a command. Accepts either actual name or listing name for - # the `old_name`. - # `new_name` must be the actual name of the new command. - # @param [String, Regexp] new_name The new name for the command. - # @param [String, Regexp] old_name The command's current name. + # Rename a command. Accepts either match or listing for the search. + # + # @param [String, Regexp] new_name The new match for the command. + # @param [String, Regexp] search The command's current match or listing. # @param [Hash] options The optional configuration parameters, # accepts the same as the `command` method, but also allows the # command description to be passed this way too. # @example Renaming the `ls` command and changing its description. # Pry.config.commands.rename "dir", "ls", :description => "DOS friendly ls" - def rename_command(new_name, old_name, options={}) - cmd = find_command_by_name_or_listing(old_name) + def rename_command(new_match, search, options={}) + cmd = find_command_by_match_or_listing(search) options = { - :listing => new_name, + :listing => new_match, :description => cmd.description }.merge!(options) - commands[new_name] = cmd.dup - commands[new_name].name = new_name - commands[new_name].description = options.delete(:description) - commands[new_name].options.merge!(options) - commands.delete(cmd.name) + commands[new_match] = cmd.dup + commands[new_match].match = new_match + commands[new_match].description = options.delete(:description) + commands[new_match].options.merge!(options) + commands.delete(cmd.match) end # Sets or gets the description for a command (replacing the old # description). Returns current description if no description # parameter provided. - # @param [String, Regexp] name The command name. + # @param [String, Regexp] match The command match. # @param [String] description The command description. # @example Setting # MyCommands = Pry::CommandSet.new do @@ -265,8 +262,8 @@ class Pry # end # @example Getting # Pry.config.commands.desc "amend-line" - def desc(name, description=nil) - cmd = find_command_by_name_or_listing(name) + def desc(search, description=nil) + cmd = find_command_by_match_or_listing(search) return cmd.description if !description cmd.description = description @@ -308,7 +305,7 @@ class Pry # @return [Pry::Command, nil] def find_command_for_help(search) find_command(search) || (begin - find_command_by_name_or_listing(search) + find_command_by_match_or_listing(search) rescue ArgumentError nil end) @@ -339,21 +336,21 @@ class Pry end # @nodoc used for testing - def run_command(context, name, *args) - command = commands[name] or raise NoCommandError.new(name, self) + def run_command(context, match, *args) + command = commands[match] or raise NoCommandError.new(match, self) command.new(context).call_safely(*args) end private - def default_options(name) + def default_options(match) { :requires_gem => [], :keep_retval => false, :argument_required => false, :interpolate => true, :shellwords => true, - :listing => name, + :listing => (String === match ? match : match.inspect), :use_prefix => true, :takes_block => false } diff --git a/test/test_command_set.rb b/test/test_command_set.rb index 22979720..6ec14a35 100644 --- a/test/test_command_set.rb +++ b/test/test_command_set.rb @@ -127,7 +127,7 @@ describe Pry::CommandSet do @set.command('foo', 'stuff') { run = true } @set.alias_command 'bar', 'foo' - @set.commands['bar'].name.should == 'bar' + @set.commands['bar'].match.should == 'bar' @set.commands['bar'].description.should == 'Alias for `foo`' @set.run_command @ctx, 'bar' @@ -139,7 +139,7 @@ describe Pry::CommandSet do @set.command('foo', 'stuff') { run = true } @set.alias_command 'bar', 'foo', :desc => "tobina" - @set.commands['bar'].name.should == 'bar' + @set.commands['bar'].match.should == 'bar' @set.commands['bar'].description.should == "tobina" @set.run_command @ctx, 'bar' @@ -151,7 +151,7 @@ describe Pry::CommandSet do @set.command(/^foo1/, 'stuff', :listing => 'foo') { run = true } @set.alias_command 'bar', 'foo1' - @set.commands['bar'].name.should == 'bar' + @set.commands['bar'].match.should == 'bar' @set.commands['bar'].description.should == 'Alias for `foo1`' @set.run_command @ctx, 'bar'