irb 1.12.0 → 1.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -11
  3. data/Rakefile +10 -0
  4. data/irb.gemspec +1 -1
  5. data/lib/irb/cmd/nop.rb +1 -1
  6. data/lib/irb/color.rb +2 -2
  7. data/lib/irb/command/backtrace.rb +2 -6
  8. data/lib/irb/command/base.rb +7 -9
  9. data/lib/irb/command/break.rb +2 -6
  10. data/lib/irb/command/catch.rb +2 -6
  11. data/lib/irb/command/chws.rb +11 -5
  12. data/lib/irb/command/context.rb +16 -0
  13. data/lib/irb/command/continue.rb +2 -2
  14. data/lib/irb/command/debug.rb +8 -1
  15. data/lib/irb/command/delete.rb +2 -2
  16. data/lib/irb/command/disable_irb.rb +19 -0
  17. data/lib/irb/command/edit.rb +6 -13
  18. data/lib/irb/command/exit.rb +1 -3
  19. data/lib/irb/command/finish.rb +2 -2
  20. data/lib/irb/command/force_exit.rb +1 -3
  21. data/lib/irb/command/help.rb +8 -17
  22. data/lib/irb/command/history.rb +4 -6
  23. data/lib/irb/command/info.rb +2 -6
  24. data/lib/irb/command/internal_helpers.rb +27 -0
  25. data/lib/irb/command/irb_info.rb +2 -2
  26. data/lib/irb/command/load.rb +20 -3
  27. data/lib/irb/command/ls.rb +20 -10
  28. data/lib/irb/command/measure.rb +12 -6
  29. data/lib/irb/command/next.rb +2 -2
  30. data/lib/irb/command/pushws.rb +10 -5
  31. data/lib/irb/command/show_doc.rb +9 -18
  32. data/lib/irb/command/show_source.rb +5 -12
  33. data/lib/irb/command/step.rb +2 -2
  34. data/lib/irb/command/subirb.rb +28 -12
  35. data/lib/irb/command/whereami.rb +1 -1
  36. data/lib/irb/command.rb +8 -303
  37. data/lib/irb/completion.rb +16 -5
  38. data/lib/irb/context.rb +21 -19
  39. data/lib/irb/default_commands.rb +260 -0
  40. data/lib/irb/ext/change-ws.rb +3 -5
  41. data/lib/irb/ext/multi-irb.rb +4 -4
  42. data/lib/irb/ext/workspaces.rb +3 -4
  43. data/lib/irb/help.rb +1 -1
  44. data/lib/irb/helper_method/base.rb +16 -0
  45. data/lib/irb/helper_method/conf.rb +11 -0
  46. data/lib/irb/helper_method.rb +29 -0
  47. data/lib/irb/history.rb +6 -3
  48. data/lib/irb/init.rb +60 -44
  49. data/lib/irb/input-method.rb +18 -10
  50. data/lib/irb/lc/error.rb +0 -5
  51. data/lib/irb/lc/ja/error.rb +0 -5
  52. data/lib/irb/lc/ja/help-message +10 -0
  53. data/lib/irb/statement.rb +5 -27
  54. data/lib/irb/version.rb +2 -2
  55. data/lib/irb/workspace.rb +18 -2
  56. data/lib/irb.rb +675 -624
  57. metadata +12 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4ef257bd1b4917c3af8f4e1c372cb7c489cd16844df518e352c0bff74c77b4fc
4
- data.tar.gz: e9cd328330de9c415b93f680228ff79c3a798c481fe657bc48f7d7305470462c
3
+ metadata.gz: e4425b668e9f62b7535ef0db6b790b8e15a0ca62d4b81461d758c645c6043496
4
+ data.tar.gz: 36977d4a243c9acbc057729ff7bd6ea2432f8cfdb4013e7e4f2c05bebef26c70
5
5
  SHA512:
6
- metadata.gz: 78b5b33588812cda49274b45e7b905cec8cb9e6b0ed71be66a644680db5ac96a19e276952425ec54a05d2ce3e8cf99b69eb7964e310770e155ced4f51501b088
7
- data.tar.gz: 68ae7b61704a3356a14d526bdf058306c9ef158d8442030779b9256a59bee2929e1bab1fdf394f39bda09479b47430ca1de94c57c7b23017affec1400975e03a
6
+ metadata.gz: 804b6fa04f60f7ecc3bf98a9aa818fd8a0e177528c455ac46e853683463176b3eb651eb81e079b70870d2c4f55ab99d4292f10563f42b4c50d697e8e9684b810
7
+ data.tar.gz: 0f554e6950eda72508cf3af5eb4c446fc0584eec20c843cbf7ae653698b233add55251028dcf7a4991df5dfdfb90956589b728d727d4deb9e64cfe524349aab5
data/README.md CHANGED
@@ -351,21 +351,13 @@ irb(main):002> a.first. # Completes Integer methods
351
351
 
352
352
  ## Documentation
353
353
 
354
- https://docs.ruby-lang.org/en/master/IRB.html
354
+ https://ruby.github.io/irb/
355
355
 
356
356
  ## Extending IRB
357
357
 
358
- IRB is currently going through some refactoring to bring in some cool improvements and make things more flexible for developers.
359
- We know that in the past, due to a lack of public APIs and documentation, many of you have had to use IRB's private APIs
360
- and components to extend it. We also know that changes can be a bit annoying and might mess with your current setup.
358
+ IRB `v1.13.0` and later versions allows users/libraries to extend its functionality through official APIs.
361
359
 
362
- We're sorry if this causes a bit of a scramble. We're working hard to make IRB better and your input is super important to us.
363
- If you've been using private APIs or components in your projects, we'd love to hear about your use cases. Please feel free to file a new issue. Your feedback will be a massive help in guiding us on how to design and prioritize the development of official APIs in the future.
364
-
365
- Right now, we've got command extension APIs on the drawing board, as you can see in [#513](https://github.com/ruby/irb/issues/513).
366
- We've also got a prototype for helper method extension APIs in the works, as shown in [#588](https://github.com/ruby/irb/issues/588).
367
-
368
- We really appreciate your understanding and patience during this transition. We're pretty excited about the improvements these changes will bring to the IRB ecosystem and we hope you are too!
360
+ For more information, please visit [EXTEND_IRB.md](./EXTEND_IRB.md).
369
361
 
370
362
  ## Development
371
363
 
data/Rakefile CHANGED
@@ -1,5 +1,6 @@
1
1
  require "bundler/gem_tasks"
2
2
  require "rake/testtask"
3
+ require "rdoc/task"
3
4
 
4
5
  Rake::TestTask.new(:test) do |t|
5
6
  t.libs << "test" << "test/lib"
@@ -42,3 +43,12 @@ Rake::TestTask.new(:test_yamatanooroti) do |t|
42
43
  end
43
44
 
44
45
  task :default => :test
46
+
47
+ RDoc::Task.new do |rdoc|
48
+ rdoc.title = "IRB"
49
+ rdoc.rdoc_files.include("*.md", "lib/**/*.rb")
50
+ rdoc.rdoc_files.exclude("lib/irb/xmp.rb")
51
+ rdoc.rdoc_dir = "docs"
52
+ rdoc.main = "README.md"
53
+ rdoc.options.push("--copy-files", "LICENSE.txt")
54
+ end
data/irb.gemspec CHANGED
@@ -42,5 +42,5 @@ Gem::Specification.new do |spec|
42
42
  spec.required_ruby_version = Gem::Requirement.new(">= 2.7")
43
43
 
44
44
  spec.add_dependency "reline", ">= 0.4.2"
45
- spec.add_dependency "rdoc"
45
+ spec.add_dependency "rdoc", ">= 4.0.0"
46
46
  end
data/lib/irb/cmd/nop.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # This file is just a placeholder for backward-compatibility.
4
- # Please require 'irb' and inheirt your command from `IRB::Command::Base` instead.
4
+ # Please require 'irb' and inherit your command from `IRB::Command::Base` instead.
data/lib/irb/color.rb CHANGED
@@ -79,12 +79,12 @@ module IRB # :nodoc:
79
79
 
80
80
  class << self
81
81
  def colorable?
82
- supported = $stdout.tty? && (/mswin|mingw/ =~ RUBY_PLATFORM || (ENV.key?('TERM') && ENV['TERM'] != 'dumb'))
82
+ supported = $stdout.tty? && (/mswin|mingw/.match?(RUBY_PLATFORM) || (ENV.key?('TERM') && ENV['TERM'] != 'dumb'))
83
83
 
84
84
  # because ruby/debug also uses irb's color module selectively,
85
85
  # irb won't be activated in that case.
86
86
  if IRB.respond_to?(:conf)
87
- supported && IRB.conf.fetch(:USE_COLORIZE, true)
87
+ supported && !!IRB.conf.fetch(:USE_COLORIZE, true)
88
88
  else
89
89
  supported
90
90
  end
@@ -7,12 +7,8 @@ module IRB
7
7
 
8
8
  module Command
9
9
  class Backtrace < DebugCommand
10
- def self.transform_args(args)
11
- args&.dump
12
- end
13
-
14
- def execute(*args)
15
- super(pre_cmds: ["backtrace", *args].join(" "))
10
+ def execute(arg)
11
+ execute_debug_command(pre_cmds: "backtrace #{arg}")
16
12
  end
17
13
  end
18
14
  end
@@ -10,6 +10,10 @@ module IRB
10
10
  module Command
11
11
  class CommandArgumentError < StandardError; end
12
12
 
13
+ def self.extract_ruby_args(*args, **kwargs)
14
+ throw :EXTRACT_RUBY_ARGS, [args, kwargs]
15
+ end
16
+
13
17
  class Base
14
18
  class << self
15
19
  def category(category = nil)
@@ -29,19 +33,13 @@ module IRB
29
33
 
30
34
  private
31
35
 
32
- def string_literal?(args)
33
- sexp = Ripper.sexp(args)
34
- sexp && sexp.size == 2 && sexp.last&.first&.first == :string_literal
35
- end
36
-
37
36
  def highlight(text)
38
37
  Color.colorize(text, [:BOLD, :BLUE])
39
38
  end
40
39
  end
41
40
 
42
- def self.execute(irb_context, *opts, **kwargs, &block)
43
- command = new(irb_context)
44
- command.execute(*opts, **kwargs, &block)
41
+ def self.execute(irb_context, arg)
42
+ new(irb_context).execute(arg)
45
43
  rescue CommandArgumentError => e
46
44
  puts e.message
47
45
  end
@@ -52,7 +50,7 @@ module IRB
52
50
 
53
51
  attr_reader :irb_context
54
52
 
55
- def execute(*opts)
53
+ def execute(arg)
56
54
  #nop
57
55
  end
58
56
  end
@@ -7,12 +7,8 @@ module IRB
7
7
 
8
8
  module Command
9
9
  class Break < DebugCommand
10
- def self.transform_args(args)
11
- args&.dump
12
- end
13
-
14
- def execute(args = nil)
15
- super(pre_cmds: "break #{args}")
10
+ def execute(arg)
11
+ execute_debug_command(pre_cmds: "break #{arg}")
16
12
  end
17
13
  end
18
14
  end
@@ -7,12 +7,8 @@ module IRB
7
7
 
8
8
  module Command
9
9
  class Catch < DebugCommand
10
- def self.transform_args(args)
11
- args&.dump
12
- end
13
-
14
- def execute(*args)
15
- super(pre_cmds: ["catch", *args].join(" "))
10
+ def execute(arg)
11
+ execute_debug_command(pre_cmds: "catch #{arg}")
16
12
  end
17
13
  end
18
14
  end
@@ -14,8 +14,8 @@ module IRB
14
14
  category "Workspace"
15
15
  description "Show the current workspace."
16
16
 
17
- def execute(*obj)
18
- irb_context.main
17
+ def execute(_arg)
18
+ puts "Current workspace: #{irb_context.main}"
19
19
  end
20
20
  end
21
21
 
@@ -23,9 +23,15 @@ module IRB
23
23
  category "Workspace"
24
24
  description "Change the current workspace to an object."
25
25
 
26
- def execute(*obj)
27
- irb_context.change_workspace(*obj)
28
- irb_context.main
26
+ def execute(arg)
27
+ if arg.empty?
28
+ irb_context.change_workspace
29
+ else
30
+ obj = eval(arg, irb_context.workspace.binding)
31
+ irb_context.change_workspace(obj)
32
+ end
33
+
34
+ puts "Current workspace: #{irb_context.main}"
29
35
  end
30
36
  end
31
37
  end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module IRB
4
+ module Command
5
+ class Context < Base
6
+ category "IRB"
7
+ description "Displays current configuration."
8
+
9
+ def execute(_arg)
10
+ # This command just displays the configuration.
11
+ # Modifying the configuration is achieved by sending a message to IRB.conf.
12
+ Pager.page_content(IRB.CurrentContext.inspect)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -7,8 +7,8 @@ module IRB
7
7
 
8
8
  module Command
9
9
  class Continue < DebugCommand
10
- def execute(*args)
11
- super(do_cmds: ["continue", *args].join(" "))
10
+ def execute(arg)
11
+ execute_debug_command(do_cmds: "continue #{arg}")
12
12
  end
13
13
  end
14
14
  end
@@ -13,7 +13,14 @@ module IRB
13
13
  binding.method(:irb).source_location.first,
14
14
  ].map { |file| /\A#{Regexp.escape(file)}:\d+:in (`|'Binding#)irb'\z/ }
15
15
 
16
- def execute(pre_cmds: nil, do_cmds: nil)
16
+ def execute(_arg)
17
+ execute_debug_command
18
+ end
19
+
20
+ def execute_debug_command(pre_cmds: nil, do_cmds: nil)
21
+ pre_cmds = pre_cmds&.rstrip
22
+ do_cmds = do_cmds&.rstrip
23
+
17
24
  if irb_context.with_debugger
18
25
  # If IRB is already running with a debug session, throw the command and IRB.debug_readline will pass it to the debugger.
19
26
  if cmd = pre_cmds || do_cmds
@@ -7,8 +7,8 @@ module IRB
7
7
 
8
8
  module Command
9
9
  class Delete < DebugCommand
10
- def execute(*args)
11
- super(pre_cmds: ["delete", *args].join(" "))
10
+ def execute(arg)
11
+ execute_debug_command(pre_cmds: "delete #{arg}")
12
12
  end
13
13
  end
14
14
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module IRB
4
+ # :stopdoc:
5
+
6
+ module Command
7
+ class DisableIrb < Base
8
+ category "IRB"
9
+ description "Disable binding.irb."
10
+
11
+ def execute(*)
12
+ ::Binding.define_method(:irb) {}
13
+ IRB.irb_exit
14
+ end
15
+ end
16
+ end
17
+
18
+ # :startdoc:
19
+ end
@@ -1,5 +1,6 @@
1
1
  require 'shellwords'
2
2
 
3
+ require_relative "../color"
3
4
  require_relative "../source_finder"
4
5
 
5
6
  module IRB
@@ -7,6 +8,8 @@ module IRB
7
8
 
8
9
  module Command
9
10
  class Edit < Base
11
+ include RubyArgsExtractor
12
+
10
13
  category "Misc"
11
14
  description 'Open a file or source location.'
12
15
  help_message <<~HELP_MESSAGE
@@ -26,19 +29,9 @@ module IRB
26
29
  edit Foo#bar
27
30
  HELP_MESSAGE
28
31
 
29
- class << self
30
- def transform_args(args)
31
- # Return a string literal as is for backward compatibility
32
- if args.nil? || args.empty? || string_literal?(args)
33
- args
34
- else # Otherwise, consider the input as a String for convenience
35
- args.strip.dump
36
- end
37
- end
38
- end
39
-
40
- def execute(*args)
41
- path = args.first
32
+ def execute(arg)
33
+ # Accept string literal for backward compatibility
34
+ path = unwrap_string_literal(arg)
42
35
 
43
36
  if path.nil?
44
37
  path = @irb_context.irb_path
@@ -8,10 +8,8 @@ module IRB
8
8
  category "IRB"
9
9
  description "Exit the current irb session."
10
10
 
11
- def execute(*)
11
+ def execute(_arg)
12
12
  IRB.irb_exit
13
- rescue UncaughtThrowError
14
- Kernel.exit
15
13
  end
16
14
  end
17
15
  end
@@ -7,8 +7,8 @@ module IRB
7
7
 
8
8
  module Command
9
9
  class Finish < DebugCommand
10
- def execute(*args)
11
- super(do_cmds: ["finish", *args].join(" "))
10
+ def execute(arg)
11
+ execute_debug_command(do_cmds: "finish #{arg}")
12
12
  end
13
13
  end
14
14
  end
@@ -8,10 +8,8 @@ module IRB
8
8
  category "IRB"
9
9
  description "Exit the current process."
10
10
 
11
- def execute(*)
11
+ def execute(_arg)
12
12
  throw :IRB_EXIT, true
13
- rescue UncaughtThrowError
14
- Kernel.exit!
15
13
  end
16
14
  end
17
15
  end
@@ -6,27 +6,16 @@ module IRB
6
6
  category "Help"
7
7
  description "List all available commands. Use `help <command>` to get information about a specific command."
8
8
 
9
- class << self
10
- def transform_args(args)
11
- # Return a string literal as is for backward compatibility
12
- if args.empty? || string_literal?(args)
13
- args
14
- else # Otherwise, consider the input as a String for convenience
15
- args.strip.dump
16
- end
17
- end
18
- end
19
-
20
- def execute(command_name = nil)
9
+ def execute(command_name)
21
10
  content =
22
- if command_name
23
- if command_class = ExtendCommandBundle.load_command(command_name)
11
+ if command_name.empty?
12
+ help_message
13
+ else
14
+ if command_class = Command.load_command(command_name)
24
15
  command_class.help_message || command_class.description
25
16
  else
26
17
  "Can't find command `#{command_name}`. Please check the command name and try again.\n\n"
27
18
  end
28
- else
29
- help_message
30
19
  end
31
20
  Pager.page_content(content)
32
21
  end
@@ -34,8 +23,10 @@ module IRB
34
23
  private
35
24
 
36
25
  def help_message
37
- commands_info = IRB::ExtendCommandBundle.all_commands_info
26
+ commands_info = IRB::Command.all_commands_info
27
+ helper_methods_info = IRB::HelperMethod.all_helper_methods_info
38
28
  commands_grouped_by_categories = commands_info.group_by { |cmd| cmd[:category] }
29
+ commands_grouped_by_categories["Helper methods"] = helper_methods_info
39
30
 
40
31
  user_aliases = irb_context.instance_variable_get(:@user_aliases)
41
32
 
@@ -12,14 +12,12 @@ module IRB
12
12
  category "IRB"
13
13
  description "Shows the input history. `-g [query]` or `-G [query]` allows you to filter the output."
14
14
 
15
- def self.transform_args(args)
16
- match = args&.match(/(-g|-G)\s+(?<grep>.+)\s*\n\z/)
17
- return unless match
15
+ def execute(arg)
18
16
 
19
- "grep: #{Regexp.new(match[:grep]).inspect}"
20
- end
17
+ if (match = arg&.match(/(-g|-G)\s+(?<grep>.+)\s*\n\z/))
18
+ grep = Regexp.new(match[:grep])
19
+ end
21
20
 
22
- def execute(grep: nil)
23
21
  formatted_inputs = irb_context.io.class::HISTORY.each_with_index.reverse_each.filter_map do |input, index|
24
22
  next if grep && !input.match?(grep)
25
23
 
@@ -7,12 +7,8 @@ module IRB
7
7
 
8
8
  module Command
9
9
  class Info < DebugCommand
10
- def self.transform_args(args)
11
- args&.dump
12
- end
13
-
14
- def execute(*args)
15
- super(pre_cmds: ["info", *args].join(" "))
10
+ def execute(arg)
11
+ execute_debug_command(pre_cmds: "info #{arg}")
16
12
  end
17
13
  end
18
14
  end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module IRB
4
+ module Command
5
+ # Internal use only, for default command's backward compatibility.
6
+ module RubyArgsExtractor # :nodoc:
7
+ def unwrap_string_literal(str)
8
+ return if str.empty?
9
+
10
+ sexp = Ripper.sexp(str)
11
+ if sexp && sexp.size == 2 && sexp.last&.first&.first == :string_literal
12
+ @irb_context.workspace.binding.eval(str).to_s
13
+ else
14
+ str
15
+ end
16
+ end
17
+
18
+ def ruby_args(arg)
19
+ # Use throw and catch to handle arg that includes `;`
20
+ # For example: "1, kw: (2; 3); 4" will be parsed to [[1], { kw: 3 }]
21
+ catch(:EXTRACT_RUBY_ARGS) do
22
+ @irb_context.workspace.binding.eval "IRB::Command.extract_ruby_args #{arg}"
23
+ end || [[], {}]
24
+ end
25
+ end
26
+ end
27
+ end
@@ -8,12 +8,12 @@ module IRB
8
8
  category "IRB"
9
9
  description "Show information about IRB."
10
10
 
11
- def execute
11
+ def execute(_arg)
12
12
  str = "Ruby version: #{RUBY_VERSION}\n"
13
13
  str += "IRB version: #{IRB.version}\n"
14
14
  str += "InputMethod: #{IRB.CurrentContext.io.inspect}\n"
15
15
  str += "Completion: #{IRB.CurrentContext.io.respond_to?(:completion_info) ? IRB.CurrentContext.io.completion_info : 'off'}\n"
16
- rc_files = IRB.rc_files.select { |rc| File.exist?(rc) }
16
+ rc_files = IRB.irbrc_files
17
17
  str += ".irbrc paths: #{rc_files.join(", ")}\n" if rc_files.any?
18
18
  str += "RUBY_PLATFORM: #{RUBY_PLATFORM}\n"
19
19
  str += "LANG env: #{ENV["LANG"]}\n" if ENV["LANG"] && !ENV["LANG"].empty?
@@ -10,6 +10,7 @@ module IRB
10
10
 
11
11
  module Command
12
12
  class LoaderCommand < Base
13
+ include RubyArgsExtractor
13
14
  include IrbLoader
14
15
 
15
16
  def raise_cmd_argument_error
@@ -21,7 +22,12 @@ module IRB
21
22
  category "IRB"
22
23
  description "Load a Ruby file."
23
24
 
24
- def execute(file_name = nil, priv = nil)
25
+ def execute(arg)
26
+ args, kwargs = ruby_args(arg)
27
+ execute_internal(*args, **kwargs)
28
+ end
29
+
30
+ def execute_internal(file_name = nil, priv = nil)
25
31
  raise_cmd_argument_error unless file_name
26
32
  irb_load(file_name, priv)
27
33
  end
@@ -30,7 +36,13 @@ module IRB
30
36
  class Require < LoaderCommand
31
37
  category "IRB"
32
38
  description "Require a Ruby file."
33
- def execute(file_name = nil)
39
+
40
+ def execute(arg)
41
+ args, kwargs = ruby_args(arg)
42
+ execute_internal(*args, **kwargs)
43
+ end
44
+
45
+ def execute_internal(file_name = nil)
34
46
  raise_cmd_argument_error unless file_name
35
47
 
36
48
  rex = Regexp.new("#{Regexp.quote(file_name)}(\.o|\.rb)?")
@@ -63,7 +75,12 @@ module IRB
63
75
  category "IRB"
64
76
  description "Loads a given file in the current session."
65
77
 
66
- def execute(file_name = nil)
78
+ def execute(arg)
79
+ args, kwargs = ruby_args(arg)
80
+ execute_internal(*args, **kwargs)
81
+ end
82
+
83
+ def execute_internal(file_name = nil)
67
84
  raise_cmd_argument_error unless file_name
68
85
 
69
86
  source_file(file_name)
@@ -11,6 +11,8 @@ module IRB
11
11
 
12
12
  module Command
13
13
  class Ls < Base
14
+ include RubyArgsExtractor
15
+
14
16
  category "Context"
15
17
  description "Show methods, constants, and variables."
16
18
 
@@ -20,27 +22,35 @@ module IRB
20
22
  -g [query] Filter the output with a query.
21
23
  HELP_MESSAGE
22
24
 
23
- def self.transform_args(args)
24
- if match = args&.match(/\A(?<args>.+\s|)(-g|-G)\s+(?<grep>[^\s]+)\s*\n\z/)
25
- args = match[:args]
26
- "#{args}#{',' unless args.chomp.empty?} grep: /#{match[:grep]}/"
25
+ def execute(arg)
26
+ if match = arg.match(/\A(?<target>.+\s|)(-g|-G)\s+(?<grep>.+)$/)
27
+ if match[:target].empty?
28
+ use_main = true
29
+ else
30
+ obj = @irb_context.workspace.binding.eval(match[:target])
31
+ end
32
+ grep = Regexp.new(match[:grep])
27
33
  else
28
- args
34
+ args, kwargs = ruby_args(arg)
35
+ use_main = args.empty?
36
+ obj = args.first
37
+ grep = kwargs[:grep]
38
+ end
39
+
40
+ if use_main
41
+ obj = irb_context.workspace.main
42
+ locals = irb_context.workspace.binding.local_variables
29
43
  end
30
- end
31
44
 
32
- def execute(*arg, grep: nil)
33
45
  o = Output.new(grep: grep)
34
46
 
35
- obj = arg.empty? ? irb_context.workspace.main : arg.first
36
- locals = arg.empty? ? irb_context.workspace.binding.local_variables : []
37
47
  klass = (obj.class == Class || obj.class == Module ? obj : obj.class)
38
48
 
39
49
  o.dump("constants", obj.constants) if obj.respond_to?(:constants)
40
50
  dump_methods(o, klass, obj)
41
51
  o.dump("instance variables", obj.instance_variables)
42
52
  o.dump("class variables", klass.class_variables)
43
- o.dump("locals", locals)
53
+ o.dump("locals", locals) if locals
44
54
  o.print_result
45
55
  end
46
56
 
@@ -3,6 +3,8 @@ module IRB
3
3
 
4
4
  module Command
5
5
  class Measure < Base
6
+ include RubyArgsExtractor
7
+
6
8
  category "Misc"
7
9
  description "`measure` enables the mode to measure processing time. `measure :off` disables it."
8
10
 
@@ -10,15 +12,19 @@ module IRB
10
12
  super(*args)
11
13
  end
12
14
 
13
- def execute(type = nil, arg = nil)
14
- # Please check IRB.init_config in lib/irb/init.rb that sets
15
- # IRB.conf[:MEASURE_PROC] to register default "measure" methods,
16
- # "measure :time" (abbreviated as "measure") and "measure :stackprof".
17
-
18
- if block_given?
15
+ def execute(arg)
16
+ if arg&.match?(/^do$|^do[^\w]|^\{/)
19
17
  warn 'Configure IRB.conf[:MEASURE_PROC] to add custom measure methods.'
20
18
  return
21
19
  end
20
+ args, kwargs = ruby_args(arg)
21
+ execute_internal(*args, **kwargs)
22
+ end
23
+
24
+ def execute_internal(type = nil, arg = nil)
25
+ # Please check IRB.init_config in lib/irb/init.rb that sets
26
+ # IRB.conf[:MEASURE_PROC] to register default "measure" methods,
27
+ # "measure :time" (abbreviated as "measure") and "measure :stackprof".
22
28
 
23
29
  case type
24
30
  when :off
@@ -7,8 +7,8 @@ module IRB
7
7
 
8
8
  module Command
9
9
  class Next < DebugCommand
10
- def execute(*args)
11
- super(do_cmds: ["next", *args].join(" "))
10
+ def execute(arg)
11
+ execute_debug_command(do_cmds: "next #{arg}")
12
12
  end
13
13
  end
14
14
  end