[ruby/irb] Command implementation not by method
(https://github.com/ruby/irb/pull/824) * Command is not a method * Fix command test * Implement non-method command name completion * Add test for ExtendCommandBundle.def_extend_command * Add helper method install test * Remove spaces in command input parse * Remove command arg unquote in help command * Simplify Statement and handle execution in IRB::Irb * Tweak require, const name * Always install CommandBundle module to main object * Remove considering local variable in command or expression check * Remove unused method, tweak * Remove outdated comment for help command arg Co-authored-by: Stan Lo <stan001212@gmail.com> --------- https://github.com/ruby/irb/commit/8fb776e379 Co-authored-by: Stan Lo <stan001212@gmail.com>
This commit is contained in:
parent
9f6deaa688
commit
6a505d1b59
58
lib/irb.rb
58
lib/irb.rb
@ -929,7 +929,7 @@ module IRB
|
|||||||
# Creates a new irb session
|
# Creates a new irb session
|
||||||
def initialize(workspace = nil, input_method = nil)
|
def initialize(workspace = nil, input_method = nil)
|
||||||
@context = Context.new(self, workspace, input_method)
|
@context = Context.new(self, workspace, input_method)
|
||||||
@context.workspace.load_commands_to_main
|
@context.workspace.load_helper_methods_to_main
|
||||||
@signal_status = :IN_IRB
|
@signal_status = :IN_IRB
|
||||||
@scanner = RubyLex.new
|
@scanner = RubyLex.new
|
||||||
@line_no = 1
|
@line_no = 1
|
||||||
@ -950,7 +950,7 @@ module IRB
|
|||||||
def debug_readline(binding)
|
def debug_readline(binding)
|
||||||
workspace = IRB::WorkSpace.new(binding)
|
workspace = IRB::WorkSpace.new(binding)
|
||||||
context.replace_workspace(workspace)
|
context.replace_workspace(workspace)
|
||||||
context.workspace.load_commands_to_main
|
context.workspace.load_helper_methods_to_main
|
||||||
@line_no += 1
|
@line_no += 1
|
||||||
|
|
||||||
# When users run:
|
# When users run:
|
||||||
@ -1028,7 +1028,15 @@ module IRB
|
|||||||
return statement.code
|
return statement.code
|
||||||
end
|
end
|
||||||
|
|
||||||
@context.evaluate(statement.evaluable_code, line_no)
|
case statement
|
||||||
|
when Statement::EmptyInput
|
||||||
|
# Do nothing
|
||||||
|
when Statement::Expression
|
||||||
|
@context.evaluate(statement.code, line_no)
|
||||||
|
when Statement::Command
|
||||||
|
ret = statement.command_class.execute(@context, statement.arg)
|
||||||
|
@context.set_last_value(ret)
|
||||||
|
end
|
||||||
|
|
||||||
if @context.echo? && !statement.suppresses_echo?
|
if @context.echo? && !statement.suppresses_echo?
|
||||||
if statement.is_assignment?
|
if statement.is_assignment?
|
||||||
@ -1084,10 +1092,7 @@ module IRB
|
|||||||
end
|
end
|
||||||
|
|
||||||
code << line
|
code << line
|
||||||
|
return code if command?(code)
|
||||||
# Accept any single-line input for symbol aliases or commands that transform
|
|
||||||
# args
|
|
||||||
return code if single_line_command?(code)
|
|
||||||
|
|
||||||
tokens, opens, terminated = @scanner.check_code_state(code, local_variables: @context.local_variables)
|
tokens, opens, terminated = @scanner.check_code_state(code, local_variables: @context.local_variables)
|
||||||
return code if terminated
|
return code if terminated
|
||||||
@ -1114,23 +1119,36 @@ module IRB
|
|||||||
end
|
end
|
||||||
|
|
||||||
code.force_encoding(@context.io.encoding)
|
code.force_encoding(@context.io.encoding)
|
||||||
command_or_alias, arg = code.split(/\s/, 2)
|
if (command, arg = parse_command(code))
|
||||||
# Transform a non-identifier alias (@, $) or keywords (next, break)
|
command_class = ExtendCommandBundle.load_command(command)
|
||||||
command_name = @context.command_aliases[command_or_alias.to_sym]
|
Statement::Command.new(code, command_class, arg)
|
||||||
command = command_name || command_or_alias
|
|
||||||
command_class = ExtendCommandBundle.load_command(command)
|
|
||||||
|
|
||||||
if command_class
|
|
||||||
Statement::Command.new(code, command, arg, command_class)
|
|
||||||
else
|
else
|
||||||
is_assignment_expression = @scanner.assignment_expression?(code, local_variables: @context.local_variables)
|
is_assignment_expression = @scanner.assignment_expression?(code, local_variables: @context.local_variables)
|
||||||
Statement::Expression.new(code, is_assignment_expression)
|
Statement::Expression.new(code, is_assignment_expression)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def single_line_command?(code)
|
def parse_command(code)
|
||||||
command = code.split(/\s/, 2).first
|
command_name, arg = code.strip.split(/\s+/, 2)
|
||||||
@context.symbol_alias?(command) || @context.transform_args?(command)
|
return unless code.lines.size == 1 && command_name
|
||||||
|
|
||||||
|
arg ||= ''
|
||||||
|
command = command_name.to_sym
|
||||||
|
# Command aliases are always command. example: $, @
|
||||||
|
if (alias_name = @context.command_aliases[command])
|
||||||
|
return [alias_name, arg]
|
||||||
|
end
|
||||||
|
|
||||||
|
# Check visibility
|
||||||
|
public_method = !!Kernel.instance_method(:public_method).bind_call(@context.main, command) rescue false
|
||||||
|
private_method = !public_method && !!Kernel.instance_method(:method).bind_call(@context.main, command) rescue false
|
||||||
|
if ExtendCommandBundle.execute_as_command?(command, public_method: public_method, private_method: private_method)
|
||||||
|
[command, arg]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def command?(code)
|
||||||
|
!!parse_command(code)
|
||||||
end
|
end
|
||||||
|
|
||||||
def configure_io
|
def configure_io
|
||||||
@ -1148,9 +1166,7 @@ module IRB
|
|||||||
false
|
false
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
# Accept any single-line input for symbol aliases or commands that transform
|
next true if command?(code)
|
||||||
# args
|
|
||||||
next true if single_line_command?(code)
|
|
||||||
|
|
||||||
_tokens, _opens, terminated = @scanner.check_code_state(code, local_variables: @context.local_variables)
|
_tokens, _opens, terminated = @scanner.check_code_state(code, local_variables: @context.local_variables)
|
||||||
terminated
|
terminated
|
||||||
|
@ -12,29 +12,17 @@ module IRB # :nodoc:
|
|||||||
|
|
||||||
# Installs the default irb extensions command bundle.
|
# Installs the default irb extensions command bundle.
|
||||||
module ExtendCommandBundle
|
module ExtendCommandBundle
|
||||||
EXCB = ExtendCommandBundle # :nodoc:
|
# See ExtendCommandBundle.execute_as_command?.
|
||||||
|
|
||||||
# See #install_alias_method.
|
|
||||||
NO_OVERRIDE = 0
|
NO_OVERRIDE = 0
|
||||||
# See #install_alias_method.
|
|
||||||
OVERRIDE_PRIVATE_ONLY = 0x01
|
OVERRIDE_PRIVATE_ONLY = 0x01
|
||||||
# See #install_alias_method.
|
|
||||||
OVERRIDE_ALL = 0x02
|
OVERRIDE_ALL = 0x02
|
||||||
|
|
||||||
# Displays current configuration.
|
|
||||||
#
|
|
||||||
# Modifying the configuration is achieved by sending a message to IRB.conf.
|
|
||||||
def irb_context
|
|
||||||
IRB.CurrentContext
|
|
||||||
end
|
|
||||||
|
|
||||||
@ALIASES = [
|
|
||||||
[:context, :irb_context, NO_OVERRIDE],
|
|
||||||
[:conf, :irb_context, NO_OVERRIDE],
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
@EXTEND_COMMANDS = [
|
@EXTEND_COMMANDS = [
|
||||||
|
[
|
||||||
|
:irb_context, :Context, "command/context",
|
||||||
|
[:context, NO_OVERRIDE],
|
||||||
|
[:conf, NO_OVERRIDE],
|
||||||
|
],
|
||||||
[
|
[
|
||||||
:irb_exit, :Exit, "command/exit",
|
:irb_exit, :Exit, "command/exit",
|
||||||
[:exit, OVERRIDE_PRIVATE_ONLY],
|
[:exit, OVERRIDE_PRIVATE_ONLY],
|
||||||
@ -204,6 +192,26 @@ module IRB # :nodoc:
|
|||||||
],
|
],
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def self.command_override_policies
|
||||||
|
@@command_override_policies ||= @EXTEND_COMMANDS.flat_map do |cmd_name, cmd_class, load_file, *aliases|
|
||||||
|
[[cmd_name, OVERRIDE_ALL]] + aliases
|
||||||
|
end.to_h
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.execute_as_command?(name, public_method:, private_method:)
|
||||||
|
case command_override_policies[name]
|
||||||
|
when OVERRIDE_ALL
|
||||||
|
true
|
||||||
|
when OVERRIDE_PRIVATE_ONLY
|
||||||
|
!public_method
|
||||||
|
when NO_OVERRIDE
|
||||||
|
!public_method && !private_method
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.command_names
|
||||||
|
command_override_policies.keys.map(&:to_s)
|
||||||
|
end
|
||||||
|
|
||||||
@@commands = []
|
@@commands = []
|
||||||
|
|
||||||
@ -247,77 +255,13 @@ module IRB # :nodoc:
|
|||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
# Installs the default irb commands.
|
|
||||||
def self.install_extend_commands
|
|
||||||
for args in @EXTEND_COMMANDS
|
|
||||||
def_extend_command(*args)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Evaluate the given +cmd_name+ on the given +cmd_class+ Class.
|
|
||||||
#
|
|
||||||
# Will also define any given +aliases+ for the method.
|
|
||||||
#
|
|
||||||
# The optional +load_file+ parameter will be required within the method
|
|
||||||
# definition.
|
|
||||||
def self.def_extend_command(cmd_name, cmd_class, load_file, *aliases)
|
def self.def_extend_command(cmd_name, cmd_class, load_file, *aliases)
|
||||||
case cmd_class
|
@EXTEND_COMMANDS.delete_if { |name,| name == cmd_name }
|
||||||
when Symbol
|
@EXTEND_COMMANDS << [cmd_name, cmd_class, load_file, *aliases]
|
||||||
cmd_class = cmd_class.id2name
|
|
||||||
when String
|
|
||||||
when Class
|
|
||||||
cmd_class = cmd_class.name
|
|
||||||
end
|
|
||||||
|
|
||||||
line = __LINE__; eval %[
|
# Just clear memoized values
|
||||||
def #{cmd_name}(*opts, **kwargs, &b)
|
@@commands = []
|
||||||
Kernel.require_relative "#{load_file}"
|
@@command_override_policies = nil
|
||||||
::IRB::Command::#{cmd_class}.execute(irb_context, *opts, **kwargs, &b)
|
|
||||||
end
|
|
||||||
], nil, __FILE__, line
|
|
||||||
|
|
||||||
for ali, flag in aliases
|
|
||||||
@ALIASES.push [ali, cmd_name, flag]
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Installs alias methods for the default irb commands, see
|
|
||||||
# ::install_extend_commands.
|
|
||||||
def install_alias_method(to, from, override = NO_OVERRIDE)
|
|
||||||
to = to.id2name unless to.kind_of?(String)
|
|
||||||
from = from.id2name unless from.kind_of?(String)
|
|
||||||
|
|
||||||
if override == OVERRIDE_ALL or
|
|
||||||
(override == OVERRIDE_PRIVATE_ONLY) && !respond_to?(to) or
|
|
||||||
(override == NO_OVERRIDE) && !respond_to?(to, true)
|
|
||||||
target = self
|
|
||||||
(class << self; self; end).instance_eval{
|
|
||||||
if target.respond_to?(to, true) &&
|
|
||||||
!target.respond_to?(EXCB.irb_original_method_name(to), true)
|
|
||||||
alias_method(EXCB.irb_original_method_name(to), to)
|
|
||||||
end
|
|
||||||
alias_method to, from
|
|
||||||
}
|
|
||||||
else
|
|
||||||
Kernel.warn "irb: warn: can't alias #{to} from #{from}.\n"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.irb_original_method_name(method_name) # :nodoc:
|
|
||||||
"irb_" + method_name + "_org"
|
|
||||||
end
|
|
||||||
|
|
||||||
# Installs alias methods for the default irb commands on the given object
|
|
||||||
# using #install_alias_method.
|
|
||||||
def self.extend_object(obj)
|
|
||||||
unless (class << obj; ancestors; end).include?(EXCB)
|
|
||||||
super
|
|
||||||
for ali, com, flg in @ALIASES
|
|
||||||
obj.install_alias_method(ali, com, flg)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
install_extend_commands
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -7,12 +7,8 @@ module IRB
|
|||||||
|
|
||||||
module Command
|
module Command
|
||||||
class Backtrace < DebugCommand
|
class Backtrace < DebugCommand
|
||||||
def self.transform_args(args)
|
def execute(arg)
|
||||||
args&.dump
|
execute_debug_command(pre_cmds: "backtrace #{arg}".rstrip)
|
||||||
end
|
|
||||||
|
|
||||||
def execute(*args)
|
|
||||||
super(pre_cmds: ["backtrace", *args].join(" "))
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -10,6 +10,10 @@ module IRB
|
|||||||
module Command
|
module Command
|
||||||
class CommandArgumentError < StandardError; end
|
class CommandArgumentError < StandardError; end
|
||||||
|
|
||||||
|
def self.extract_ruby_args(*args, **kwargs)
|
||||||
|
throw :EXTRACT_RUBY_ARGS, [args, kwargs]
|
||||||
|
end
|
||||||
|
|
||||||
class Base
|
class Base
|
||||||
class << self
|
class << self
|
||||||
def category(category = nil)
|
def category(category = nil)
|
||||||
@ -29,19 +33,13 @@ module IRB
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def string_literal?(args)
|
|
||||||
sexp = Ripper.sexp(args)
|
|
||||||
sexp && sexp.size == 2 && sexp.last&.first&.first == :string_literal
|
|
||||||
end
|
|
||||||
|
|
||||||
def highlight(text)
|
def highlight(text)
|
||||||
Color.colorize(text, [:BOLD, :BLUE])
|
Color.colorize(text, [:BOLD, :BLUE])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.execute(irb_context, *opts, **kwargs, &block)
|
def self.execute(irb_context, arg)
|
||||||
command = new(irb_context)
|
new(irb_context).execute(arg)
|
||||||
command.execute(*opts, **kwargs, &block)
|
|
||||||
rescue CommandArgumentError => e
|
rescue CommandArgumentError => e
|
||||||
puts e.message
|
puts e.message
|
||||||
end
|
end
|
||||||
@ -52,7 +50,26 @@ module IRB
|
|||||||
|
|
||||||
attr_reader :irb_context
|
attr_reader :irb_context
|
||||||
|
|
||||||
def execute(*opts)
|
def unwrap_string_literal(str)
|
||||||
|
return if str.empty?
|
||||||
|
|
||||||
|
sexp = Ripper.sexp(str)
|
||||||
|
if sexp && sexp.size == 2 && sexp.last&.first&.first == :string_literal
|
||||||
|
@irb_context.workspace.binding.eval(str).to_s
|
||||||
|
else
|
||||||
|
str
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def ruby_args(arg)
|
||||||
|
# Use throw and catch to handle arg that includes `;`
|
||||||
|
# For example: "1, kw: (2; 3); 4" will be parsed to [[1], { kw: 3 }]
|
||||||
|
catch(:EXTRACT_RUBY_ARGS) do
|
||||||
|
@irb_context.workspace.binding.eval "IRB::Command.extract_ruby_args #{arg}"
|
||||||
|
end || [[], {}]
|
||||||
|
end
|
||||||
|
|
||||||
|
def execute(arg)
|
||||||
#nop
|
#nop
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -7,12 +7,8 @@ module IRB
|
|||||||
|
|
||||||
module Command
|
module Command
|
||||||
class Break < DebugCommand
|
class Break < DebugCommand
|
||||||
def self.transform_args(args)
|
def execute(arg)
|
||||||
args&.dump
|
execute_debug_command(pre_cmds: "break #{arg}".rstrip)
|
||||||
end
|
|
||||||
|
|
||||||
def execute(args = nil)
|
|
||||||
super(pre_cmds: "break #{args}")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -7,12 +7,8 @@ module IRB
|
|||||||
|
|
||||||
module Command
|
module Command
|
||||||
class Catch < DebugCommand
|
class Catch < DebugCommand
|
||||||
def self.transform_args(args)
|
def execute(arg)
|
||||||
args&.dump
|
execute_debug_command(pre_cmds: "catch #{arg}".rstrip)
|
||||||
end
|
|
||||||
|
|
||||||
def execute(*args)
|
|
||||||
super(pre_cmds: ["catch", *args].join(" "))
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -14,7 +14,7 @@ module IRB
|
|||||||
category "Workspace"
|
category "Workspace"
|
||||||
description "Show the current workspace."
|
description "Show the current workspace."
|
||||||
|
|
||||||
def execute(*obj)
|
def execute(_arg)
|
||||||
irb_context.main
|
irb_context.main
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -23,8 +23,13 @@ module IRB
|
|||||||
category "Workspace"
|
category "Workspace"
|
||||||
description "Change the current workspace to an object."
|
description "Change the current workspace to an object."
|
||||||
|
|
||||||
def execute(*obj)
|
def execute(arg)
|
||||||
irb_context.change_workspace(*obj)
|
if arg.empty?
|
||||||
|
irb_context.change_workspace
|
||||||
|
else
|
||||||
|
obj = eval(arg, irb_context.workspace.binding)
|
||||||
|
irb_context.change_workspace(obj)
|
||||||
|
end
|
||||||
irb_context.main
|
irb_context.main
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
16
lib/irb/command/context.rb
Normal file
16
lib/irb/command/context.rb
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module IRB
|
||||||
|
module Command
|
||||||
|
class Context < Base
|
||||||
|
category "IRB"
|
||||||
|
description "Displays current configuration."
|
||||||
|
|
||||||
|
def execute(_arg)
|
||||||
|
# This command just displays the configuration.
|
||||||
|
# Modifying the configuration is achieved by sending a message to IRB.conf.
|
||||||
|
Pager.page_content(IRB.CurrentContext.inspect)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -7,8 +7,8 @@ module IRB
|
|||||||
|
|
||||||
module Command
|
module Command
|
||||||
class Continue < DebugCommand
|
class Continue < DebugCommand
|
||||||
def execute(*args)
|
def execute(arg)
|
||||||
super(do_cmds: ["continue", *args].join(" "))
|
execute_debug_command(do_cmds: "continue #{arg}".rstrip)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -13,7 +13,11 @@ module IRB
|
|||||||
binding.method(:irb).source_location.first,
|
binding.method(:irb).source_location.first,
|
||||||
].map { |file| /\A#{Regexp.escape(file)}:\d+:in (`|'Binding#)irb'\z/ }
|
].map { |file| /\A#{Regexp.escape(file)}:\d+:in (`|'Binding#)irb'\z/ }
|
||||||
|
|
||||||
def execute(pre_cmds: nil, do_cmds: nil)
|
def execute(_arg)
|
||||||
|
execute_debug_command
|
||||||
|
end
|
||||||
|
|
||||||
|
def execute_debug_command(pre_cmds: nil, do_cmds: nil)
|
||||||
if irb_context.with_debugger
|
if irb_context.with_debugger
|
||||||
# If IRB is already running with a debug session, throw the command and IRB.debug_readline will pass it to the debugger.
|
# If IRB is already running with a debug session, throw the command and IRB.debug_readline will pass it to the debugger.
|
||||||
if cmd = pre_cmds || do_cmds
|
if cmd = pre_cmds || do_cmds
|
||||||
|
@ -7,8 +7,8 @@ module IRB
|
|||||||
|
|
||||||
module Command
|
module Command
|
||||||
class Delete < DebugCommand
|
class Delete < DebugCommand
|
||||||
def execute(*args)
|
def execute(arg)
|
||||||
super(pre_cmds: ["delete", *args].join(" "))
|
execute_debug_command(pre_cmds: "delete #{arg}".rstrip)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -26,19 +26,9 @@ module IRB
|
|||||||
edit Foo#bar
|
edit Foo#bar
|
||||||
HELP_MESSAGE
|
HELP_MESSAGE
|
||||||
|
|
||||||
class << self
|
def execute(arg)
|
||||||
def transform_args(args)
|
# Accept string literal for backward compatibility
|
||||||
# Return a string literal as is for backward compatibility
|
path = unwrap_string_literal(arg)
|
||||||
if args.nil? || args.empty? || string_literal?(args)
|
|
||||||
args
|
|
||||||
else # Otherwise, consider the input as a String for convenience
|
|
||||||
args.strip.dump
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def execute(*args)
|
|
||||||
path = args.first
|
|
||||||
|
|
||||||
if path.nil?
|
if path.nil?
|
||||||
path = @irb_context.irb_path
|
path = @irb_context.irb_path
|
||||||
|
@ -7,8 +7,8 @@ module IRB
|
|||||||
|
|
||||||
module Command
|
module Command
|
||||||
class Finish < DebugCommand
|
class Finish < DebugCommand
|
||||||
def execute(*args)
|
def execute(arg)
|
||||||
super(do_cmds: ["finish", *args].join(" "))
|
execute_debug_command(do_cmds: "finish #{arg}".rstrip)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -6,27 +6,16 @@ module IRB
|
|||||||
category "Help"
|
category "Help"
|
||||||
description "List all available commands. Use `help <command>` to get information about a specific command."
|
description "List all available commands. Use `help <command>` to get information about a specific command."
|
||||||
|
|
||||||
class << self
|
def execute(command_name)
|
||||||
def transform_args(args)
|
|
||||||
# Return a string literal as is for backward compatibility
|
|
||||||
if args.empty? || string_literal?(args)
|
|
||||||
args
|
|
||||||
else # Otherwise, consider the input as a String for convenience
|
|
||||||
args.strip.dump
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def execute(command_name = nil)
|
|
||||||
content =
|
content =
|
||||||
if command_name
|
if command_name.empty?
|
||||||
|
help_message
|
||||||
|
else
|
||||||
if command_class = ExtendCommandBundle.load_command(command_name)
|
if command_class = ExtendCommandBundle.load_command(command_name)
|
||||||
command_class.help_message || command_class.description
|
command_class.help_message || command_class.description
|
||||||
else
|
else
|
||||||
"Can't find command `#{command_name}`. Please check the command name and try again.\n\n"
|
"Can't find command `#{command_name}`. Please check the command name and try again.\n\n"
|
||||||
end
|
end
|
||||||
else
|
|
||||||
help_message
|
|
||||||
end
|
end
|
||||||
Pager.page_content(content)
|
Pager.page_content(content)
|
||||||
end
|
end
|
||||||
|
@ -12,14 +12,12 @@ module IRB
|
|||||||
category "IRB"
|
category "IRB"
|
||||||
description "Shows the input history. `-g [query]` or `-G [query]` allows you to filter the output."
|
description "Shows the input history. `-g [query]` or `-G [query]` allows you to filter the output."
|
||||||
|
|
||||||
def self.transform_args(args)
|
def execute(arg)
|
||||||
match = args&.match(/(-g|-G)\s+(?<grep>.+)\s*\n\z/)
|
|
||||||
return unless match
|
|
||||||
|
|
||||||
"grep: #{Regexp.new(match[:grep]).inspect}"
|
if (match = arg&.match(/(-g|-G)\s+(?<grep>.+)\s*\n\z/))
|
||||||
end
|
grep = Regexp.new(match[:grep])
|
||||||
|
end
|
||||||
|
|
||||||
def execute(grep: nil)
|
|
||||||
formatted_inputs = irb_context.io.class::HISTORY.each_with_index.reverse_each.filter_map do |input, index|
|
formatted_inputs = irb_context.io.class::HISTORY.each_with_index.reverse_each.filter_map do |input, index|
|
||||||
next if grep && !input.match?(grep)
|
next if grep && !input.match?(grep)
|
||||||
|
|
||||||
|
@ -7,12 +7,8 @@ module IRB
|
|||||||
|
|
||||||
module Command
|
module Command
|
||||||
class Info < DebugCommand
|
class Info < DebugCommand
|
||||||
def self.transform_args(args)
|
def execute(arg)
|
||||||
args&.dump
|
execute_debug_command(pre_cmds: "info #{arg}".rstrip)
|
||||||
end
|
|
||||||
|
|
||||||
def execute(*args)
|
|
||||||
super(pre_cmds: ["info", *args].join(" "))
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -8,7 +8,7 @@ module IRB
|
|||||||
category "IRB"
|
category "IRB"
|
||||||
description "Show information about IRB."
|
description "Show information about IRB."
|
||||||
|
|
||||||
def execute
|
def execute(_arg)
|
||||||
str = "Ruby version: #{RUBY_VERSION}\n"
|
str = "Ruby version: #{RUBY_VERSION}\n"
|
||||||
str += "IRB version: #{IRB.version}\n"
|
str += "IRB version: #{IRB.version}\n"
|
||||||
str += "InputMethod: #{IRB.CurrentContext.io.inspect}\n"
|
str += "InputMethod: #{IRB.CurrentContext.io.inspect}\n"
|
||||||
|
@ -21,7 +21,12 @@ module IRB
|
|||||||
category "IRB"
|
category "IRB"
|
||||||
description "Load a Ruby file."
|
description "Load a Ruby file."
|
||||||
|
|
||||||
def execute(file_name = nil, priv = nil)
|
def execute(arg)
|
||||||
|
args, kwargs = ruby_args(arg)
|
||||||
|
execute_internal(*args, **kwargs)
|
||||||
|
end
|
||||||
|
|
||||||
|
def execute_internal(file_name = nil, priv = nil)
|
||||||
raise_cmd_argument_error unless file_name
|
raise_cmd_argument_error unless file_name
|
||||||
irb_load(file_name, priv)
|
irb_load(file_name, priv)
|
||||||
end
|
end
|
||||||
@ -30,7 +35,13 @@ module IRB
|
|||||||
class Require < LoaderCommand
|
class Require < LoaderCommand
|
||||||
category "IRB"
|
category "IRB"
|
||||||
description "Require a Ruby file."
|
description "Require a Ruby file."
|
||||||
def execute(file_name = nil)
|
|
||||||
|
def execute(arg)
|
||||||
|
args, kwargs = ruby_args(arg)
|
||||||
|
execute_internal(*args, **kwargs)
|
||||||
|
end
|
||||||
|
|
||||||
|
def execute_internal(file_name = nil)
|
||||||
raise_cmd_argument_error unless file_name
|
raise_cmd_argument_error unless file_name
|
||||||
|
|
||||||
rex = Regexp.new("#{Regexp.quote(file_name)}(\.o|\.rb)?")
|
rex = Regexp.new("#{Regexp.quote(file_name)}(\.o|\.rb)?")
|
||||||
@ -63,7 +74,12 @@ module IRB
|
|||||||
category "IRB"
|
category "IRB"
|
||||||
description "Loads a given file in the current session."
|
description "Loads a given file in the current session."
|
||||||
|
|
||||||
def execute(file_name = nil)
|
def execute(arg)
|
||||||
|
args, kwargs = ruby_args(arg)
|
||||||
|
execute_internal(*args, **kwargs)
|
||||||
|
end
|
||||||
|
|
||||||
|
def execute_internal(file_name = nil)
|
||||||
raise_cmd_argument_error unless file_name
|
raise_cmd_argument_error unless file_name
|
||||||
|
|
||||||
source_file(file_name)
|
source_file(file_name)
|
||||||
|
@ -20,27 +20,35 @@ module IRB
|
|||||||
-g [query] Filter the output with a query.
|
-g [query] Filter the output with a query.
|
||||||
HELP_MESSAGE
|
HELP_MESSAGE
|
||||||
|
|
||||||
def self.transform_args(args)
|
def execute(arg)
|
||||||
if match = args&.match(/\A(?<args>.+\s|)(-g|-G)\s+(?<grep>[^\s]+)\s*\n\z/)
|
if match = arg.match(/\A(?<target>.+\s|)(-g|-G)\s+(?<grep>.+)$/)
|
||||||
args = match[:args]
|
if match[:target].empty?
|
||||||
"#{args}#{',' unless args.chomp.empty?} grep: /#{match[:grep]}/"
|
use_main = true
|
||||||
|
else
|
||||||
|
obj = @irb_context.workspace.binding.eval(match[:target])
|
||||||
|
end
|
||||||
|
grep = Regexp.new(match[:grep])
|
||||||
else
|
else
|
||||||
args
|
args, kwargs = ruby_args(arg)
|
||||||
|
use_main = args.empty?
|
||||||
|
obj = args.first
|
||||||
|
grep = kwargs[:grep]
|
||||||
|
end
|
||||||
|
|
||||||
|
if use_main
|
||||||
|
obj = irb_context.workspace.main
|
||||||
|
locals = irb_context.workspace.binding.local_variables
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
def execute(*arg, grep: nil)
|
|
||||||
o = Output.new(grep: grep)
|
o = Output.new(grep: grep)
|
||||||
|
|
||||||
obj = arg.empty? ? irb_context.workspace.main : arg.first
|
|
||||||
locals = arg.empty? ? irb_context.workspace.binding.local_variables : []
|
|
||||||
klass = (obj.class == Class || obj.class == Module ? obj : obj.class)
|
klass = (obj.class == Class || obj.class == Module ? obj : obj.class)
|
||||||
|
|
||||||
o.dump("constants", obj.constants) if obj.respond_to?(:constants)
|
o.dump("constants", obj.constants) if obj.respond_to?(:constants)
|
||||||
dump_methods(o, klass, obj)
|
dump_methods(o, klass, obj)
|
||||||
o.dump("instance variables", obj.instance_variables)
|
o.dump("instance variables", obj.instance_variables)
|
||||||
o.dump("class variables", klass.class_variables)
|
o.dump("class variables", klass.class_variables)
|
||||||
o.dump("locals", locals)
|
o.dump("locals", locals) if locals
|
||||||
o.print_result
|
o.print_result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -10,15 +10,19 @@ module IRB
|
|||||||
super(*args)
|
super(*args)
|
||||||
end
|
end
|
||||||
|
|
||||||
def execute(type = nil, arg = nil)
|
def execute(arg)
|
||||||
# Please check IRB.init_config in lib/irb/init.rb that sets
|
if arg&.match?(/^do$|^do[^\w]|^\{/)
|
||||||
# IRB.conf[:MEASURE_PROC] to register default "measure" methods,
|
|
||||||
# "measure :time" (abbreviated as "measure") and "measure :stackprof".
|
|
||||||
|
|
||||||
if block_given?
|
|
||||||
warn 'Configure IRB.conf[:MEASURE_PROC] to add custom measure methods.'
|
warn 'Configure IRB.conf[:MEASURE_PROC] to add custom measure methods.'
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
args, kwargs = ruby_args(arg)
|
||||||
|
execute_internal(*args, **kwargs)
|
||||||
|
end
|
||||||
|
|
||||||
|
def execute_internal(type = nil, arg = nil)
|
||||||
|
# Please check IRB.init_config in lib/irb/init.rb that sets
|
||||||
|
# IRB.conf[:MEASURE_PROC] to register default "measure" methods,
|
||||||
|
# "measure :time" (abbreviated as "measure") and "measure :stackprof".
|
||||||
|
|
||||||
case type
|
case type
|
||||||
when :off
|
when :off
|
||||||
|
@ -7,8 +7,8 @@ module IRB
|
|||||||
|
|
||||||
module Command
|
module Command
|
||||||
class Next < DebugCommand
|
class Next < DebugCommand
|
||||||
def execute(*args)
|
def execute(arg)
|
||||||
super(do_cmds: ["next", *args].join(" "))
|
execute_debug_command(do_cmds: "next #{arg}".rstrip)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -14,7 +14,7 @@ module IRB
|
|||||||
category "Workspace"
|
category "Workspace"
|
||||||
description "Show workspaces."
|
description "Show workspaces."
|
||||||
|
|
||||||
def execute(*obj)
|
def execute(_arg)
|
||||||
inspection_resuls = irb_context.instance_variable_get(:@workspace_stack).map do |ws|
|
inspection_resuls = irb_context.instance_variable_get(:@workspace_stack).map do |ws|
|
||||||
truncated_inspect(ws.main)
|
truncated_inspect(ws.main)
|
||||||
end
|
end
|
||||||
@ -39,8 +39,13 @@ module IRB
|
|||||||
category "Workspace"
|
category "Workspace"
|
||||||
description "Push an object to the workspace stack."
|
description "Push an object to the workspace stack."
|
||||||
|
|
||||||
def execute(*obj)
|
def execute(arg)
|
||||||
irb_context.push_workspace(*obj)
|
if arg.empty?
|
||||||
|
irb_context.push_workspace
|
||||||
|
else
|
||||||
|
obj = eval(arg, irb_context.workspace.binding)
|
||||||
|
irb_context.push_workspace(obj)
|
||||||
|
end
|
||||||
super
|
super
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -49,8 +54,8 @@ module IRB
|
|||||||
category "Workspace"
|
category "Workspace"
|
||||||
description "Pop a workspace from the workspace stack."
|
description "Pop a workspace from the workspace stack."
|
||||||
|
|
||||||
def execute(*obj)
|
def execute(_arg)
|
||||||
irb_context.pop_workspace(*obj)
|
irb_context.pop_workspace
|
||||||
super
|
super
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -3,17 +3,6 @@
|
|||||||
module IRB
|
module IRB
|
||||||
module Command
|
module Command
|
||||||
class ShowDoc < Base
|
class ShowDoc < Base
|
||||||
class << self
|
|
||||||
def transform_args(args)
|
|
||||||
# Return a string literal as is for backward compatibility
|
|
||||||
if args.empty? || string_literal?(args)
|
|
||||||
args
|
|
||||||
else # Otherwise, consider the input as a String for convenience
|
|
||||||
args.strip.dump
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
category "Context"
|
category "Context"
|
||||||
description "Look up documentation with RI."
|
description "Look up documentation with RI."
|
||||||
|
|
||||||
@ -31,7 +20,9 @@ module IRB
|
|||||||
|
|
||||||
HELP_MESSAGE
|
HELP_MESSAGE
|
||||||
|
|
||||||
def execute(*names)
|
def execute(arg)
|
||||||
|
# Accept string literal for backward compatibility
|
||||||
|
name = unwrap_string_literal(arg)
|
||||||
require 'rdoc/ri/driver'
|
require 'rdoc/ri/driver'
|
||||||
|
|
||||||
unless ShowDoc.const_defined?(:Ri)
|
unless ShowDoc.const_defined?(:Ri)
|
||||||
@ -39,15 +30,13 @@ module IRB
|
|||||||
ShowDoc.const_set(:Ri, RDoc::RI::Driver.new(opts))
|
ShowDoc.const_set(:Ri, RDoc::RI::Driver.new(opts))
|
||||||
end
|
end
|
||||||
|
|
||||||
if names.empty?
|
if name.nil?
|
||||||
Ri.interactive
|
Ri.interactive
|
||||||
else
|
else
|
||||||
names.each do |name|
|
begin
|
||||||
begin
|
Ri.display_name(name)
|
||||||
Ri.display_name(name.to_s)
|
rescue RDoc::RI::Error
|
||||||
rescue RDoc::RI::Error
|
puts $!.message
|
||||||
puts $!.message
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -24,18 +24,9 @@ module IRB
|
|||||||
show_source Foo::BAR
|
show_source Foo::BAR
|
||||||
HELP_MESSAGE
|
HELP_MESSAGE
|
||||||
|
|
||||||
class << self
|
def execute(arg)
|
||||||
def transform_args(args)
|
# Accept string literal for backward compatibility
|
||||||
# Return a string literal as is for backward compatibility
|
str = unwrap_string_literal(arg)
|
||||||
if args.empty? || string_literal?(args)
|
|
||||||
args
|
|
||||||
else # Otherwise, consider the input as a String for convenience
|
|
||||||
args.strip.dump
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def execute(str = nil)
|
|
||||||
unless str.is_a?(String)
|
unless str.is_a?(String)
|
||||||
puts "Error: Expected a string but got #{str.inspect}"
|
puts "Error: Expected a string but got #{str.inspect}"
|
||||||
return
|
return
|
||||||
|
@ -7,8 +7,8 @@ module IRB
|
|||||||
|
|
||||||
module Command
|
module Command
|
||||||
class Step < DebugCommand
|
class Step < DebugCommand
|
||||||
def execute(*args)
|
def execute(arg)
|
||||||
super(do_cmds: ["step", *args].join(" "))
|
execute_debug_command(do_cmds: "step #{arg}".rstrip)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -9,10 +9,6 @@ module IRB
|
|||||||
|
|
||||||
module Command
|
module Command
|
||||||
class MultiIRBCommand < Base
|
class MultiIRBCommand < Base
|
||||||
def execute(*args)
|
|
||||||
extend_irb_context
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def print_deprecated_warning
|
def print_deprecated_warning
|
||||||
@ -36,7 +32,12 @@ module IRB
|
|||||||
category "Multi-irb (DEPRECATED)"
|
category "Multi-irb (DEPRECATED)"
|
||||||
description "Start a child IRB."
|
description "Start a child IRB."
|
||||||
|
|
||||||
def execute(*obj)
|
def execute(arg)
|
||||||
|
args, kwargs = ruby_args(arg)
|
||||||
|
execute_internal(*args, **kwargs)
|
||||||
|
end
|
||||||
|
|
||||||
|
def execute_internal(*obj)
|
||||||
print_deprecated_warning
|
print_deprecated_warning
|
||||||
|
|
||||||
if irb_context.with_debugger
|
if irb_context.with_debugger
|
||||||
@ -44,7 +45,7 @@ module IRB
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
super
|
extend_irb_context
|
||||||
IRB.irb(nil, *obj)
|
IRB.irb(nil, *obj)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -53,7 +54,7 @@ module IRB
|
|||||||
category "Multi-irb (DEPRECATED)"
|
category "Multi-irb (DEPRECATED)"
|
||||||
description "List of current sessions."
|
description "List of current sessions."
|
||||||
|
|
||||||
def execute
|
def execute(_arg)
|
||||||
print_deprecated_warning
|
print_deprecated_warning
|
||||||
|
|
||||||
if irb_context.with_debugger
|
if irb_context.with_debugger
|
||||||
@ -61,7 +62,7 @@ module IRB
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
super
|
extend_irb_context
|
||||||
IRB.JobManager
|
IRB.JobManager
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -70,7 +71,12 @@ module IRB
|
|||||||
category "Multi-irb (DEPRECATED)"
|
category "Multi-irb (DEPRECATED)"
|
||||||
description "Switches to the session of the given number."
|
description "Switches to the session of the given number."
|
||||||
|
|
||||||
def execute(key = nil)
|
def execute(arg)
|
||||||
|
args, kwargs = ruby_args(arg)
|
||||||
|
execute_internal(*args, **kwargs)
|
||||||
|
end
|
||||||
|
|
||||||
|
def execute_internal(key = nil)
|
||||||
print_deprecated_warning
|
print_deprecated_warning
|
||||||
|
|
||||||
if irb_context.with_debugger
|
if irb_context.with_debugger
|
||||||
@ -78,7 +84,7 @@ module IRB
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
super
|
extend_irb_context
|
||||||
|
|
||||||
raise CommandArgumentError.new("Please specify the id of target IRB job (listed in the `jobs` command).") unless key
|
raise CommandArgumentError.new("Please specify the id of target IRB job (listed in the `jobs` command).") unless key
|
||||||
IRB.JobManager.switch(key)
|
IRB.JobManager.switch(key)
|
||||||
@ -89,7 +95,12 @@ module IRB
|
|||||||
category "Multi-irb (DEPRECATED)"
|
category "Multi-irb (DEPRECATED)"
|
||||||
description "Kills the session with the given number."
|
description "Kills the session with the given number."
|
||||||
|
|
||||||
def execute(*keys)
|
def execute(arg)
|
||||||
|
args, kwargs = ruby_args(arg)
|
||||||
|
execute_internal(*args, **kwargs)
|
||||||
|
end
|
||||||
|
|
||||||
|
def execute_internal(*keys)
|
||||||
print_deprecated_warning
|
print_deprecated_warning
|
||||||
|
|
||||||
if irb_context.with_debugger
|
if irb_context.with_debugger
|
||||||
@ -97,7 +108,7 @@ module IRB
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
super
|
extend_irb_context
|
||||||
IRB.JobManager.kill(*keys)
|
IRB.JobManager.kill(*keys)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -8,7 +8,7 @@ module IRB
|
|||||||
category "Context"
|
category "Context"
|
||||||
description "Show the source code around binding.irb again."
|
description "Show the source code around binding.irb again."
|
||||||
|
|
||||||
def execute(*)
|
def execute(_arg)
|
||||||
code = irb_context.workspace.code_around_binding
|
code = irb_context.workspace.code_around_binding
|
||||||
if code
|
if code
|
||||||
puts code
|
puts code
|
||||||
|
@ -86,6 +86,14 @@ module IRB
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def command_completions(preposing, target)
|
||||||
|
if preposing.empty? && !target.empty?
|
||||||
|
IRB::ExtendCommandBundle.command_names.select { _1.start_with?(target) }
|
||||||
|
else
|
||||||
|
[]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def retrieve_files_to_require_relative_from_current_dir
|
def retrieve_files_to_require_relative_from_current_dir
|
||||||
@files_from_current_dir ||= Dir.glob("**/*.{rb,#{RbConfig::CONFIG['DLEXT']}}", base: '.').map { |path|
|
@files_from_current_dir ||= Dir.glob("**/*.{rb,#{RbConfig::CONFIG['DLEXT']}}", base: '.').map { |path|
|
||||||
path.sub(/\.(rb|#{RbConfig::CONFIG['DLEXT']})\z/, '')
|
path.sub(/\.(rb|#{RbConfig::CONFIG['DLEXT']})\z/, '')
|
||||||
@ -103,9 +111,11 @@ module IRB
|
|||||||
end
|
end
|
||||||
|
|
||||||
def completion_candidates(preposing, target, _postposing, bind:)
|
def completion_candidates(preposing, target, _postposing, bind:)
|
||||||
|
commands = command_completions(preposing, target)
|
||||||
result = ReplTypeCompletor.analyze(preposing + target, binding: bind, filename: @context.irb_path)
|
result = ReplTypeCompletor.analyze(preposing + target, binding: bind, filename: @context.irb_path)
|
||||||
return [] unless result
|
return commands unless result
|
||||||
result.completion_candidates.map { target + _1 }
|
|
||||||
|
commands | result.completion_candidates.map { target + _1 }
|
||||||
end
|
end
|
||||||
|
|
||||||
def doc_namespace(preposing, matched, _postposing, bind:)
|
def doc_namespace(preposing, matched, _postposing, bind:)
|
||||||
@ -181,7 +191,8 @@ module IRB
|
|||||||
result = complete_require_path(target, preposing, postposing)
|
result = complete_require_path(target, preposing, postposing)
|
||||||
return result if result
|
return result if result
|
||||||
end
|
end
|
||||||
retrieve_completion_data(target, bind: bind, doc_namespace: false).compact.map{ |i| i.encode(Encoding.default_external) }
|
commands = command_completions(preposing || '', target)
|
||||||
|
commands | retrieve_completion_data(target, bind: bind, doc_namespace: false).compact.map{ |i| i.encode(Encoding.default_external) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def doc_namespace(_preposing, matched, _postposing, bind:)
|
def doc_namespace(_preposing, matched, _postposing, bind:)
|
||||||
|
@ -646,17 +646,5 @@ module IRB
|
|||||||
def local_variables # :nodoc:
|
def local_variables # :nodoc:
|
||||||
workspace.binding.local_variables
|
workspace.binding.local_variables
|
||||||
end
|
end
|
||||||
|
|
||||||
# Return true if it's aliased from the argument and it's not an identifier.
|
|
||||||
def symbol_alias?(command)
|
|
||||||
return nil if command.match?(/\A\w+\z/)
|
|
||||||
command_aliases.key?(command.to_sym)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Return true if the command supports transforming args
|
|
||||||
def transform_args?(command)
|
|
||||||
command = command_aliases.fetch(command.to_sym, command)
|
|
||||||
ExtendCommandBundle.load_command(command)&.respond_to?(:transform_args)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -29,11 +29,9 @@ module IRB # :nodoc:
|
|||||||
return main
|
return main
|
||||||
end
|
end
|
||||||
|
|
||||||
replace_workspace(WorkSpace.new(_main[0]))
|
workspace = WorkSpace.new(_main[0])
|
||||||
|
replace_workspace(workspace)
|
||||||
if !(class<<main;ancestors;end).include?(ExtendCommandBundle)
|
workspace.load_helper_methods_to_main
|
||||||
main.extend ExtendCommandBundle
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -19,10 +19,9 @@ module IRB # :nodoc:
|
|||||||
@workspace_stack.push current_workspace, previous_workspace
|
@workspace_stack.push current_workspace, previous_workspace
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@workspace_stack.push WorkSpace.new(workspace.binding, _main[0])
|
new_workspace = WorkSpace.new(workspace.binding, _main[0])
|
||||||
if !(class<<main;ancestors;end).include?(ExtendCommandBundle)
|
@workspace_stack.push new_workspace
|
||||||
main.extend ExtendCommandBundle
|
new_workspace.load_helper_methods_to_main
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -16,10 +16,6 @@ module IRB
|
|||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
end
|
end
|
||||||
|
|
||||||
def evaluable_code
|
|
||||||
raise NotImplementedError
|
|
||||||
end
|
|
||||||
|
|
||||||
class EmptyInput < Statement
|
class EmptyInput < Statement
|
||||||
def is_assignment?
|
def is_assignment?
|
||||||
false
|
false
|
||||||
@ -37,10 +33,6 @@ module IRB
|
|||||||
def code
|
def code
|
||||||
""
|
""
|
||||||
end
|
end
|
||||||
|
|
||||||
def evaluable_code
|
|
||||||
code
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class Expression < Statement
|
class Expression < Statement
|
||||||
@ -60,18 +52,15 @@ module IRB
|
|||||||
def is_assignment?
|
def is_assignment?
|
||||||
@is_assignment
|
@is_assignment
|
||||||
end
|
end
|
||||||
|
|
||||||
def evaluable_code
|
|
||||||
@code
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class Command < Statement
|
class Command < Statement
|
||||||
def initialize(code, command, arg, command_class)
|
attr_reader :command_class, :arg
|
||||||
@code = code
|
|
||||||
@command = command
|
def initialize(original_code, command_class, arg)
|
||||||
@arg = arg
|
@code = original_code
|
||||||
@command_class = command_class
|
@command_class = command_class
|
||||||
|
@arg = arg
|
||||||
end
|
end
|
||||||
|
|
||||||
def is_assignment?
|
def is_assignment?
|
||||||
@ -86,17 +75,6 @@ module IRB
|
|||||||
require_relative 'command/debug'
|
require_relative 'command/debug'
|
||||||
IRB::Command::DebugCommand > @command_class
|
IRB::Command::DebugCommand > @command_class
|
||||||
end
|
end
|
||||||
|
|
||||||
def evaluable_code
|
|
||||||
# Hook command-specific transformation to return valid Ruby code
|
|
||||||
if @command_class.respond_to?(:transform_args)
|
|
||||||
arg = @command_class.transform_args(@arg)
|
|
||||||
else
|
|
||||||
arg = @arg
|
|
||||||
end
|
|
||||||
|
|
||||||
[@command, arg].compact.join(' ')
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -108,8 +108,10 @@ EOF
|
|||||||
# <code>IRB.conf[:__MAIN__]</code>
|
# <code>IRB.conf[:__MAIN__]</code>
|
||||||
attr_reader :main
|
attr_reader :main
|
||||||
|
|
||||||
def load_commands_to_main
|
def load_helper_methods_to_main
|
||||||
main.extend ExtendCommandBundle
|
if !(class<<main;ancestors;end).include?(ExtendCommandBundle)
|
||||||
|
main.extend ExtendCommandBundle
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Evaluate the given +statements+ within the context of this workspace.
|
# Evaluate the given +statements+ within the context of this workspace.
|
||||||
|
@ -210,6 +210,98 @@ module TestIRB
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class CustomCommandTestCase < CommandTestCase
|
||||||
|
def setup
|
||||||
|
super
|
||||||
|
execute_lines("help\n") # To ensure command initialization is done
|
||||||
|
@EXTEND_COMMANDS_backup = IRB::ExtendCommandBundle.instance_variable_get(:@EXTEND_COMMANDS).dup
|
||||||
|
@cvars_backup = IRB::ExtendCommandBundle.class_variables.to_h do |cvar|
|
||||||
|
[cvar, IRB::ExtendCommandBundle.class_variable_get(cvar)]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def teardown
|
||||||
|
super
|
||||||
|
IRB::ExtendCommandBundle.instance_variable_set(:@EXTEND_COMMANDS, @EXTEND_COMMANDS_backup)
|
||||||
|
@cvars_backup.each do |cvar, value|
|
||||||
|
IRB::ExtendCommandBundle.class_variable_set(cvar, value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class CommandArgTest < CustomCommandTestCase
|
||||||
|
class PrintArgCommand < IRB::Command::Base
|
||||||
|
category 'CommandTest'
|
||||||
|
description 'print_command_arg'
|
||||||
|
def execute(arg)
|
||||||
|
puts "arg=#{arg.inspect}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_arg
|
||||||
|
IRB::Command.const_set :PrintArgCommand, PrintArgCommand
|
||||||
|
IRB::ExtendCommandBundle.def_extend_command(:print_arg, :PrintArgCommand, nil, [:pa, IRB::ExtendCommandBundle::OVERRIDE_ALL])
|
||||||
|
out, err = execute_lines("print_arg\n")
|
||||||
|
assert_empty err
|
||||||
|
assert_include(out, 'arg=""')
|
||||||
|
|
||||||
|
out, err = execute_lines("print_arg \n")
|
||||||
|
assert_empty err
|
||||||
|
assert_include(out, 'arg=""')
|
||||||
|
|
||||||
|
out, err = execute_lines("print_arg a r g\n")
|
||||||
|
assert_empty err
|
||||||
|
assert_include(out, 'arg="a r g"')
|
||||||
|
|
||||||
|
out, err = execute_lines("print_arg a r g \n")
|
||||||
|
assert_empty err
|
||||||
|
assert_include(out, 'arg="a r g"')
|
||||||
|
|
||||||
|
out, err = execute_lines("pa a r g \n")
|
||||||
|
assert_empty err
|
||||||
|
assert_include(out, 'arg="a r g"')
|
||||||
|
ensure
|
||||||
|
IRB::Command.send(:remove_const, :PrintArgCommand)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class ExtendCommandBundleCompatibilityTest < CustomCommandTestCase
|
||||||
|
class FooBarCommand < IRB::Command::Base
|
||||||
|
category 'FooBarCategory'
|
||||||
|
description 'foobar_description'
|
||||||
|
def execute(_arg)
|
||||||
|
puts "FooBar executed"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def setup
|
||||||
|
super
|
||||||
|
IRB::Command.const_set :FooBarCommand, FooBarCommand
|
||||||
|
end
|
||||||
|
|
||||||
|
def teardown
|
||||||
|
super
|
||||||
|
IRB::Command.send(:remove_const, :FooBarCommand)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_def_extend_command
|
||||||
|
command = [:foobar, :FooBarCommand, nil, [:fbalias, IRB::ExtendCommandBundle::OVERRIDE_ALL]]
|
||||||
|
IRB::ExtendCommandBundle.instance_variable_get(:@EXTEND_COMMANDS).push(command)
|
||||||
|
IRB::ExtendCommandBundle.def_extend_command(*command)
|
||||||
|
out, err = execute_lines("foobar\n")
|
||||||
|
assert_empty err
|
||||||
|
assert_include(out, "FooBar executed")
|
||||||
|
|
||||||
|
out, err = execute_lines("fbalias\n")
|
||||||
|
assert_empty err
|
||||||
|
assert_include(out, "FooBar executed")
|
||||||
|
|
||||||
|
out, err = execute_lines("show_cmds\n")
|
||||||
|
assert_include(out, "FooBarCategory")
|
||||||
|
assert_include(out, "foobar_description")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
class MeasureTest < CommandTestCase
|
class MeasureTest < CommandTestCase
|
||||||
def test_measure
|
def test_measure
|
||||||
conf = {
|
conf = {
|
||||||
@ -373,17 +465,19 @@ module TestIRB
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
out, err = execute_lines(
|
out, err = execute_lines(
|
||||||
"measure :foo",
|
"measure :foo\n",
|
||||||
"measure :on, :bar",
|
"1\n",
|
||||||
"3\n",
|
"measure :on, :bar\n",
|
||||||
|
"2\n",
|
||||||
"measure :off, :foo\n",
|
"measure :off, :foo\n",
|
||||||
"measure :off, :bar\n",
|
|
||||||
"3\n",
|
"3\n",
|
||||||
|
"measure :off, :bar\n",
|
||||||
|
"4\n",
|
||||||
conf: conf
|
conf: conf
|
||||||
)
|
)
|
||||||
|
|
||||||
assert_empty err
|
assert_empty err
|
||||||
assert_match(/\AFOO is added\.\n=> nil\nfoo\nBAR is added\.\n=> nil\nbar\nfoo\n=> 3\nbar\nfoo\n=> nil\nbar\n=> nil\n=> 3\n/, out)
|
assert_match(/\AFOO is added\.\n=> nil\nfoo\n=> 1\nBAR is added\.\n=> nil\nbar\nfoo\n=> 2\n=> nil\nbar\n=> 3\n=> nil\n=> 4\n/, out)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_measure_with_proc_warning
|
def test_measure_with_proc_warning
|
||||||
@ -402,7 +496,6 @@ module TestIRB
|
|||||||
out, err = execute_lines(
|
out, err = execute_lines(
|
||||||
"3\n",
|
"3\n",
|
||||||
"measure do\n",
|
"measure do\n",
|
||||||
"end\n",
|
|
||||||
"3\n",
|
"3\n",
|
||||||
conf: conf,
|
conf: conf,
|
||||||
main: c
|
main: c
|
||||||
@ -554,7 +647,8 @@ module TestIRB
|
|||||||
out, err = execute_lines(
|
out, err = execute_lines(
|
||||||
"pushws Foo.new\n",
|
"pushws Foo.new\n",
|
||||||
"popws\n",
|
"popws\n",
|
||||||
"cwws.class",
|
"cwws\n",
|
||||||
|
"_.class",
|
||||||
)
|
)
|
||||||
assert_empty err
|
assert_empty err
|
||||||
assert_include(out, "=> #{self.class}")
|
assert_include(out, "=> #{self.class}")
|
||||||
@ -573,7 +667,8 @@ module TestIRB
|
|||||||
def test_chws_replaces_the_current_workspace
|
def test_chws_replaces_the_current_workspace
|
||||||
out, err = execute_lines(
|
out, err = execute_lines(
|
||||||
"chws #{self.class}::Foo.new\n",
|
"chws #{self.class}::Foo.new\n",
|
||||||
"cwws.class",
|
"cwws\n",
|
||||||
|
"_.class",
|
||||||
)
|
)
|
||||||
assert_empty err
|
assert_empty err
|
||||||
assert_include(out, "=> #{self.class}::Foo")
|
assert_include(out, "=> #{self.class}::Foo")
|
||||||
@ -582,7 +677,8 @@ module TestIRB
|
|||||||
def test_chws_does_nothing_when_receiving_no_argument
|
def test_chws_does_nothing_when_receiving_no_argument
|
||||||
out, err = execute_lines(
|
out, err = execute_lines(
|
||||||
"chws\n",
|
"chws\n",
|
||||||
"cwws.class",
|
"cwws\n",
|
||||||
|
"_.class",
|
||||||
)
|
)
|
||||||
assert_empty err
|
assert_empty err
|
||||||
assert_include(out, "=> #{self.class}")
|
assert_include(out, "=> #{self.class}")
|
||||||
@ -730,18 +826,18 @@ module TestIRB
|
|||||||
def test_ls_grep_empty
|
def test_ls_grep_empty
|
||||||
out, err = execute_lines("ls\n")
|
out, err = execute_lines("ls\n")
|
||||||
assert_empty err
|
assert_empty err
|
||||||
assert_match(/whereami/, out)
|
assert_match(/assert/, out)
|
||||||
assert_match(/show_source/, out)
|
assert_match(/refute/, out)
|
||||||
|
|
||||||
[
|
[
|
||||||
"ls grep: /whereami/\n",
|
"ls grep: /assert/\n",
|
||||||
"ls -g whereami\n",
|
"ls -g assert\n",
|
||||||
"ls -G whereami\n",
|
"ls -G assert\n",
|
||||||
].each do |line|
|
].each do |line|
|
||||||
out, err = execute_lines(line)
|
out, err = execute_lines(line)
|
||||||
assert_empty err
|
assert_empty err
|
||||||
assert_match(/whereami/, out)
|
assert_match(/assert/, out)
|
||||||
assert_not_match(/show_source/, out)
|
assert_not_match(/refute/, out)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -951,4 +1047,19 @@ module TestIRB
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class HelperMethodInsallTest < CommandTestCase
|
||||||
|
def test_helper_method_install
|
||||||
|
IRB::ExtendCommandBundle.module_eval do
|
||||||
|
def foobar
|
||||||
|
"test_helper_method_foobar"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
out, err = execute_lines("foobar.upcase")
|
||||||
|
assert_empty err
|
||||||
|
assert_include(out, '=> "TEST_HELPER_METHOD_FOOBAR"')
|
||||||
|
ensure
|
||||||
|
IRB::ExtendCommandBundle.remove_method :foobar
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -14,6 +14,13 @@ module TestIRB
|
|||||||
IRB::RegexpCompletor.new.doc_namespace('', target, '', bind: bind)
|
IRB::RegexpCompletor.new.doc_namespace('', target, '', bind: bind)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class CommandCompletionTest < CompletionTest
|
||||||
|
def test_command_completion
|
||||||
|
assert_include(IRB::RegexpCompletor.new.completion_candidates('', 'show_s', '', bind: binding), 'show_source')
|
||||||
|
assert_not_include(IRB::RegexpCompletor.new.completion_candidates(';', 'show_s', '', bind: binding), 'show_source')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
class MethodCompletionTest < CompletionTest
|
class MethodCompletionTest < CompletionTest
|
||||||
def test_complete_string
|
def test_complete_string
|
||||||
assert_include(completion_candidates("'foo'.up", binding), "'foo'.upcase")
|
assert_include(completion_candidates("'foo'.up", binding), "'foo'.upcase")
|
||||||
|
@ -9,7 +9,7 @@ rescue LoadError
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
require 'irb/completion'
|
require 'irb'
|
||||||
require 'tempfile'
|
require 'tempfile'
|
||||||
require_relative './helper'
|
require_relative './helper'
|
||||||
|
|
||||||
@ -54,6 +54,11 @@ module TestIRB
|
|||||||
assert_equal [], candidates
|
assert_equal [], candidates
|
||||||
assert_doc_namespace('(', ')', nil)
|
assert_doc_namespace('(', ')', nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_command_completion
|
||||||
|
assert_include(@completor.completion_candidates('', 'show_s', '', bind: binding), 'show_source')
|
||||||
|
assert_not_include(@completor.completion_candidates(';', 'show_s', '', bind: binding), 'show_source')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class TypeCompletorIntegrationTest < IntegrationTestCase
|
class TypeCompletorIntegrationTest < IntegrationTestCase
|
||||||
|
Loading…
x
Reference in New Issue
Block a user