[ruby/irb] Gracefully handle missing command argument

(https://github.com/ruby/irb/pull/473)

* Handle file loading commands' argument error gracefully

Currently, if users don't provide an argument to `source`,
`irb_load`, and `irb_require`, IRB raises `ArgumentError` with full
stacktrace. This is confusing because it looks similar to when IRB has
internal issues. The message also isn't helpful on helping users avoid
the error.

So in this commit, I add a new `CommandArgumentError` for commands to
raise explicitly when users' input doesn't satisfy a command's argument
requirement.

* Gracefully handle `fg` command's argument requirement
This commit is contained in:
Stan Lo 2022-12-08 21:05:33 +00:00 committed by git
parent 234c3a056e
commit 12b7c129bf
4 changed files with 44 additions and 16 deletions

View File

@ -17,24 +17,29 @@ module IRB
# :stopdoc: # :stopdoc:
module ExtendCommand module ExtendCommand
class Load < Nop class LoaderCommand < Nop
include IrbLoader include IrbLoader
category "IRB" def raise_cmd_argument_error
description "Load a Ruby file." raise CommandArgumentError.new("Please specify the file name.")
def execute(file_name, priv = nil)
return irb_load(file_name, priv)
end end
end end
class Require < Nop class Load < LoaderCommand
include IrbLoader category "IRB"
description "Load a Ruby file."
def execute(file_name = nil, priv = nil)
raise_cmd_argument_error unless file_name
irb_load(file_name, priv)
end
end
class Require < LoaderCommand
category "IRB" category "IRB"
description "Require a Ruby file." description "Require a Ruby file."
def execute(file_name = nil)
def execute(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)?")
return false if $".find{|f| f =~ rex} return false if $".find{|f| f =~ rex}
@ -62,17 +67,16 @@ module IRB
end end
end end
class Source < Nop class Source < LoaderCommand
include IrbLoader
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) def execute(file_name = nil)
raise_cmd_argument_error unless file_name
source_file(file_name) source_file(file_name)
end end
end end
end end
# :startdoc: # :startdoc:
end end

View File

@ -13,6 +13,8 @@ module IRB
# :stopdoc: # :stopdoc:
module ExtendCommand module ExtendCommand
class CommandArgumentError < StandardError; end
class Nop class Nop
class << self class << self
def category(category = nil) def category(category = nil)
@ -30,11 +32,15 @@ module IRB
def self.execute(conf, *opts, **kwargs, &block) def self.execute(conf, *opts, **kwargs, &block)
command = new(conf) command = new(conf)
command.execute(*opts, **kwargs, &block) command.execute(*opts, **kwargs, &block)
rescue CommandArgumentError => e
puts e.message
end end
else else
def self.execute(conf, *opts, &block) def self.execute(conf, *opts, &block)
command = new(conf) command = new(conf)
command.execute(*opts, &block) command.execute(*opts, &block)
rescue CommandArgumentError => e
puts e.message
end end
end end

View File

@ -51,7 +51,8 @@ module IRB
category "IRB" category "IRB"
description "Switches to the session of the given number." description "Switches to the session of the given number."
def execute(key) def execute(key = nil)
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)
end end
end end

View File

@ -368,6 +368,14 @@ module TestIRB
], out) ], out)
end end
def test_irb_source_without_argument
out, err = execute_lines(
"irb_source\n",
)
assert_empty err
assert_match(/Please specify the file name./, out)
end
def test_help def test_help
out, _ = execute_lines( out, _ = execute_lines(
"help 'String#gsub'\n", "help 'String#gsub'\n",
@ -416,6 +424,15 @@ module TestIRB
], out) ], out)
end end
def test_irb_load_without_argument
out, err = execute_lines(
"irb_load\n",
)
assert_empty err
assert_match(/Please specify the file name./, out)
end
def test_ls def test_ls
out, err = execute_lines( out, err = execute_lines(
"class P\n", "class P\n",