diff --git a/lib/irb.rb b/lib/irb.rb index 70d5a5cb7..e99c190dc 100644 --- a/lib/irb.rb +++ b/lib/irb.rb @@ -616,7 +616,6 @@ def build_statement(code) if command_match command_or_alias = command_match[:cmd_name] - arg = [command_match[:cmd_arg], command_match[:cmd_flag]].compact.join(' ') # Transform a non-identifier alias (@, $) or keywords (next, break) command_name = @context.command_aliases[command_or_alias.to_sym] command = command_name || command_or_alias @@ -624,7 +623,9 @@ def build_statement(code) end if command_class - Statement::Command.new(code, command, arg, command_class) + arg = command_match[:cmd_arg] + flags = command_match[:cmd_flag] + Statement::Command.new(code, command, arg, flags, command_class) else is_assignment_expression = @scanner.assignment_expression?(code, local_variables: @context.local_variables) Statement::Expression.new(code, is_assignment_expression) diff --git a/lib/irb/cmd/history.rb b/lib/irb/cmd/history.rb index 5b712fa44..52aa9f3f8 100644 --- a/lib/irb/cmd/history.rb +++ b/lib/irb/cmd/history.rb @@ -12,11 +12,10 @@ class History < Nop category "IRB" description "Shows the input history. `-g [query]` or `-G [query]` allows you to filter the output." - def self.transform_args(args) - match = args&.match(/(-g|-G)\s+(?.+)\s*\n\z/) - return unless match - - "grep: #{Regexp.new(match[:grep]).inspect}" + def self.set_options(options, parser) + parser.on("-g [query]", "-G [query]", "Filter out the output with a query") do |v| + options[:grep] = "\/#{v}\/" + end end def execute(grep: nil) diff --git a/lib/irb/cmd/ls.rb b/lib/irb/cmd/ls.rb index 648afddf1..cb7c5738d 100644 --- a/lib/irb/cmd/ls.rb +++ b/lib/irb/cmd/ls.rb @@ -14,12 +14,11 @@ class Ls < Nop category "Context" description "Show methods, constants, and variables. `-g [query]` or `-G [query]` allows you to filter out the output." - def self.transform_args(args) - if match = args&.match(/\A(?.+\s|)(-g|-G)\s+(?[^\s]+)\s*\z/) - args = match[:args] - "#{args}#{',' unless args.chomp.empty?} grep: /#{match[:grep]}/" - else - args + class << self + def set_options(options, parser) + parser.on("-g [query]", "-G [query]", "Filter out the output with a query") do |v| + options[:grep] = "\/#{v}\/" + end end end diff --git a/lib/irb/cmd/nop.rb b/lib/irb/cmd/nop.rb index 7fb197c51..dc022ac84 100644 --- a/lib/irb/cmd/nop.rb +++ b/lib/irb/cmd/nop.rb @@ -3,6 +3,7 @@ # nop.rb - # by Keiju ISHITSUKA(keiju@ruby-lang.org) # +require "optparse" module IRB # :stopdoc: @@ -22,12 +23,29 @@ def description(description = nil) @description end + def parse_flags(flags) + options = {} + + OptionParser.new do |parser| + set_options(options, parser) + end.parse(flags) + + options + rescue OptionParser::InvalidOption => e + warn e + options + end + private def string_literal?(args) sexp = Ripper.sexp(args) sexp && sexp.size == 2 && sexp.last&.first&.first == :string_literal end + + def set_options(opts, _parser) + opts + end end def self.execute(irb_context, *opts, **kwargs, &block) diff --git a/lib/irb/cmd/show_source.rb b/lib/irb/cmd/show_source.rb index 09d653bc7..170058bc4 100644 --- a/lib/irb/cmd/show_source.rb +++ b/lib/irb/cmd/show_source.rb @@ -12,6 +12,13 @@ class ShowSource < Nop description "Show the source code of a given method or constant." class << self + def set_options(options, parser) + parser.on("-s", "show super method") do |v| + options[:super_level] ||= 0 + options[:super_level] += 1 + end + end + def transform_args(args) # Return a string literal as is for backward compatibility if args.empty? || string_literal?(args) @@ -22,15 +29,13 @@ def transform_args(args) end end - def execute(str = nil) + def execute(str = nil, super_level: nil) unless str.is_a?(String) puts "Error: Expected a string but got #{str.inspect}" return end - str, esses = str.split(" -") - super_level = esses ? esses.count("s") : 0 - source = SourceFinder.new(@irb_context).find_source(str, super_level) + source = SourceFinder.new(@irb_context).find_source(str, super_level || 0) if source show_source(source) diff --git a/lib/irb/statement.rb b/lib/irb/statement.rb index b12110600..f6472a63f 100644 --- a/lib/irb/statement.rb +++ b/lib/irb/statement.rb @@ -44,10 +44,11 @@ def evaluable_code end class Command < Statement - def initialize(code, command, arg, command_class) + def initialize(code, command, arg, flags, command_class) @code = code @command = command @arg = arg + @flags = command_class.parse_flags(flags&.split || []) @command_class = command_class end @@ -73,7 +74,18 @@ def evaluable_code arg = @arg end - [@command, arg].compact.join(' ') + result = [@command, arg].compact.join(' ') + + if @flags.any? + converted_flags = @flags.map do |k, v| + "#{k}: #{v}" + end + + result += "," if arg + result += " #{converted_flags.join(' ')}" + end + + result end end end