From 527e9d1c197919e7ed7aabf7a76090ef0523a444 Mon Sep 17 00:00:00 2001 From: John Mair Date: Mon, 26 Mar 2012 00:26:48 +1300 Subject: [PATCH] supercharged Pry.commands.alias_command method * Now accepts arbitrary command code for alias, e.g alias_command "lM", "ls -M" * Adds all aliases to the "Aliases" group in `help` --- lib/pry/command.rb | 7 +- lib/pry/command_set.rb | 30 ++++++-- test/test_command_integration.rb | 120 ++++++++++++++++++++++++++++--- test/test_command_set.rb | 64 ++++++++++++----- 4 files changed, 187 insertions(+), 34 deletions(-) diff --git a/lib/pry/command.rb b/lib/pry/command.rb index bce46a1d..7903c346 100644 --- a/lib/pry/command.rb +++ b/lib/pry/command.rb @@ -42,7 +42,6 @@ class Pry end end - # Make those properties accessible to instances def name; self.class.name; end def description; self.class.description; end @@ -145,7 +144,11 @@ class Pry when /pryrc/ "~/.pryrc" else - "(other)" + if options[:alias] + "Aliases" + else + "(other)" + end end ) end diff --git a/lib/pry/command_set.rb b/lib/pry/command_set.rb index 0ada9d93..412eb866 100644 --- a/lib/pry/command_set.rb +++ b/lib/pry/command_set.rb @@ -200,14 +200,30 @@ class Pry protected :find_command_by_name_or_listing # Aliases a command - # @param [String] new_name New name of the command. - # @param [String] old_name Old name of the 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] action The action to be performed (typically + # another command). # @param [String, nil] desc New description of the command. - def alias_command(new_name, old_name, desc="") - orig_command = find_command_by_name_or_listing(old_name) - commands[new_name] = orig_command.dup - commands[new_name].name = new_name - commands[new_name].description = desc + # @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 Creating an alias for `ls -M` + # Pry.config.commands.alias_command "lM", "ls -M" + def alias_command(name, action, desc="Alias for `#{action}`", options={}) + options = { + :alias => true + }.merge!(options) + + # ensure default description is used if desc is nil + desc = "Alias for `#{action}`" if !desc + + create_command name, desc, options do + define_method(:process) do + run action, *args + end + end end # Rename a command. Accepts either actual name or listing name for diff --git a/test/test_command_integration.rb b/test/test_command_integration.rb index 8417ba8b..8febd88e 100644 --- a/test/test_command_integration.rb +++ b/test/test_command_integration.rb @@ -1,5 +1,117 @@ require 'helper' describe "commands" do + + describe "alias_command" do + it 'should make an aliasd command behave like its original' do + set = Pry::CommandSet.new do + command "test-command" do + output.puts "testing 1, 2, 3" + end + alias_command "test-alias", "test-command" + end + redirect_pry_io(InputTester.new("test-alias"), out1 = StringIO.new) do + Pry.start self, :commands => set + end + + redirect_pry_io(InputTester.new("test-command"), out2 = StringIO.new) do + Pry.start self, :commands => set + end + + out1.string.should == out2.string + end + + it 'should pass on arguments to original' do + set = Pry::CommandSet.new do + command "test-command" do |*args| + output.puts "testing #{args.join(' ')}" + end + alias_command "test-alias", "test-command" + end + + redirect_pry_io(InputTester.new("test-command hello baby duck"), out1 = StringIO.new) do + Pry.start self, :commands => set + end + + out1.string.should =~ /hello baby duck/ + + redirect_pry_io(InputTester.new("test-alias hello baby duck"), out2 = StringIO.new) do + Pry.start self, :commands => set + end + + out2.string.should == out1.string + end + + it 'should pass option arguments to original' do + set = Pry::CommandSet.new do + import Pry::Commands + alias_command "test-alias", "ls" + end + + obj = Class.new { @x = 10 } + redirect_pry_io(InputTester.new("ls -i"), out1 = StringIO.new) do + Pry.start obj, :commands => set + end + + out1.string.should =~ /@x/ + + redirect_pry_io(InputTester.new("test-alias -i"), out2 = StringIO.new) do + Pry.start obj, :commands => set + end + + out2.string.should == out1.string + end + + it 'should pass option arguments to original with additional parameters' do + set = Pry::CommandSet.new do + import Pry::Commands + alias_command "test-alias", "ls -M" + end + + obj = Class.new { @x = Class.new { define_method(:plymouth) {} } } + redirect_pry_io(InputTester.new("ls -M @x"), out1 = StringIO.new) do + Pry.start obj, :commands => set + end + + out1.string.should =~ /plymouth/ + + redirect_pry_io(InputTester.new("test-alias @x"), out2 = StringIO.new) do + Pry.start obj, :commands => set + end + + out2.string.should == out1.string + end + + it 'should be able to alias a regex command' do + set = Pry::CommandSet.new do + command /du.k/ do + output.puts "ducky" + end + alias_command "test-alias", "duck" + end + + redirect_pry_io(InputTester.new("test-alias"), out1 = StringIO.new) do + Pry.start self, :commands => set + end + + out1.string.should =~ /ducky/ + end + + it 'should be able to make the alias a regex' do + set = Pry::CommandSet.new do + command /du.k/ do + output.puts "ducky" + end + alias_command /test-ali.s/, "duck" + end + + redirect_pry_io(InputTester.new("test-alias"), out1 = StringIO.new) do + Pry.start self, :commands => set + end + + out1.string.should =~ /ducky/ + end + end + it 'should interpolate ruby code into commands' do klass = Pry::CommandSet.new do command "hello", "", :keep_retval => true do |arg| @@ -299,14 +411,6 @@ str_output.string !~ /=>/ klass.commands.include?("v").should == true end - it 'should alias a command with another command' do - klass = Pry::CommandSet.new do - import Pry::DefaultCommands::Help - alias_command "help2", "help" - end - klass.commands["help2"].block.should == klass.commands["help"].block - end - it 'should change description of a command using desc' do klass = Pry::CommandSet.new do; import Pry::DefaultCommands::Help; end orig = klass.commands["help"].description diff --git a/test/test_command_set.rb b/test/test_command_set.rb index fec2f795..9909b2d1 100644 --- a/test/test_command_set.rb +++ b/test/test_command_set.rb @@ -121,28 +121,58 @@ describe Pry::CommandSet do @set.commands['foo'].description.should == 'some stuff' end - it 'should be able to alias method' do - run = false - @set.command('foo', 'stuff') { run = true } + describe "aliases" do + it 'should be able to alias command' do + run = false + @set.command('foo', 'stuff') { run = true } - @set.alias_command 'bar', 'foo' - @set.commands['bar'].name.should == 'bar' - @set.commands['bar'].description.should == '' + @set.alias_command 'bar', 'foo' + @set.commands['bar'].name.should == 'bar' + @set.commands['bar'].description.should == 'Alias for `foo`' - @set.run_command @ctx, 'bar' - run.should == true - end + @set.run_command @ctx, 'bar' + run.should == true + end - it "should be able to alias a method by the command's listing name" do - run = false - @set.command(/^foo1/, 'stuff', :listing => 'foo') { run = true } + it 'should be able to specify alias\'s description when aliasing' do + run = false + @set.command('foo', 'stuff') { run = true } - @set.alias_command 'bar', 'foo' - @set.commands['bar'].name.should == 'bar' - @set.commands['bar'].description.should == '' + @set.alias_command 'bar', 'foo', "tobina" + @set.commands['bar'].name.should == 'bar' + @set.commands['bar'].description.should == "tobina" - @set.run_command @ctx, 'bar' - run.should == true + @set.run_command @ctx, 'bar' + run.should == true + end + + it "should be able to alias a command by its invocation line" do + run = false + @set.command(/^foo1/, 'stuff', :listing => 'foo') { run = true } + + @set.alias_command 'bar', 'foo1' + @set.commands['bar'].name.should == 'bar' + @set.commands['bar'].description.should == 'Alias for `foo1`' + + @set.run_command @ctx, 'bar' + run.should == true + end + + it "should be able to specify options when creating alias" do + run = false + @set.command(/^foo1/, 'stuff', :listing => 'foo') { run = true } + + @set.alias_command /^b.r/, 'foo1', nil, :listing => "bar" + @set.commands[/^b.r/].options[:listing].should == "bar" + end + + it "should set description to default if description parameter is nil" do + run = false + @set.command(/^foo1/, 'stuff', :listing => 'foo') { run = true } + + @set.alias_command "bar", 'foo1', nil + @set.commands["bar"].description.should == "Alias for `foo1`" + end end it 'should be able to change the descriptions of commands' do