From 12b7c129bf8ed3a113e2cc73f817868507504268 Mon Sep 17 00:00:00 2001 From: Stan Lo Date: Thu, 8 Dec 2022 21:05:33 +0000 Subject: [PATCH] [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 --- lib/irb/cmd/load.rb | 34 +++++++++++++++++++--------------- lib/irb/cmd/nop.rb | 6 ++++++ lib/irb/cmd/subirb.rb | 3 ++- test/irb/test_cmd.rb | 17 +++++++++++++++++ 4 files changed, 44 insertions(+), 16 deletions(-) diff --git a/lib/irb/cmd/load.rb b/lib/irb/cmd/load.rb index 76368f856c..2897bbd975 100644 --- a/lib/irb/cmd/load.rb +++ b/lib/irb/cmd/load.rb @@ -17,24 +17,29 @@ module IRB # :stopdoc: module ExtendCommand - class Load < Nop + class LoaderCommand < Nop include IrbLoader - category "IRB" - description "Load a Ruby file." - - def execute(file_name, priv = nil) - return irb_load(file_name, priv) + def raise_cmd_argument_error + raise CommandArgumentError.new("Please specify the file name.") end end - class Require < Nop - include IrbLoader + class Load < LoaderCommand + 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" description "Require a Ruby file." - - def execute(file_name) + def execute(file_name = nil) + raise_cmd_argument_error unless file_name rex = Regexp.new("#{Regexp.quote(file_name)}(\.o|\.rb)?") return false if $".find{|f| f =~ rex} @@ -62,17 +67,16 @@ module IRB end end - class Source < Nop - include IrbLoader - + class Source < LoaderCommand category "IRB" 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) end end end - # :startdoc: end diff --git a/lib/irb/cmd/nop.rb b/lib/irb/cmd/nop.rb index 280bfe4677..32074f2d9f 100644 --- a/lib/irb/cmd/nop.rb +++ b/lib/irb/cmd/nop.rb @@ -13,6 +13,8 @@ module IRB # :stopdoc: module ExtendCommand + class CommandArgumentError < StandardError; end + class Nop class << self def category(category = nil) @@ -30,11 +32,15 @@ module IRB def self.execute(conf, *opts, **kwargs, &block) command = new(conf) command.execute(*opts, **kwargs, &block) + rescue CommandArgumentError => e + puts e.message end else def self.execute(conf, *opts, &block) command = new(conf) command.execute(*opts, &block) + rescue CommandArgumentError => e + puts e.message end end diff --git a/lib/irb/cmd/subirb.rb b/lib/irb/cmd/subirb.rb index 43364f1393..699b35fcb4 100644 --- a/lib/irb/cmd/subirb.rb +++ b/lib/irb/cmd/subirb.rb @@ -51,7 +51,8 @@ module IRB category "IRB" 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) end end diff --git a/test/irb/test_cmd.rb b/test/irb/test_cmd.rb index ac0c115339..31cd786ffe 100644 --- a/test/irb/test_cmd.rb +++ b/test/irb/test_cmd.rb @@ -368,6 +368,14 @@ module TestIRB ], out) 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 out, _ = execute_lines( "help 'String#gsub'\n", @@ -416,6 +424,15 @@ module TestIRB ], out) 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 out, err = execute_lines( "class P\n",