irb 1.5.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 33ff0b70fb3730f087bc24a7a8b63253ba1a4ad0416a0ffcd1e5395f26e5d0b2
4
- data.tar.gz: 9cd418e90733c4cb4658368b2a899b50490ad9dbd7352a1c1df0070c10d9669d
3
+ metadata.gz: 2df1f78bfd3e28e4102262fc4b9011d6c84c7690cba11f870e6e9f54e8718ebe
4
+ data.tar.gz: 20d55eba407c974060b73fc4ba741d534da8f933f65ec1bb03e85ba36129dc01
5
5
  SHA512:
6
- metadata.gz: ec6102a41d55404aa8e5585243cbe74fcdbe1e1d5bcd88ddae4240adff4281d14200b99c621324515a4e226eff5964644a7e8456d707af2ca7dcf8e5211a0b4b
7
- data.tar.gz: 0ed81d78ce49803706b36f36e173acb1e27f3e217bd3c6e00e46d4875b6be3c7958a2cb3db146703c3cbf7198094561a562e0fd244f6a61501f9ae5196df343a
6
+ metadata.gz: a829406c154fb4cb7d877ebe95bfb8ab20dd894e6adaaa4fd05ee198740f2deff0a449c469ff1c388075424b04ecd28db6bb3298c345c46b9c821ffb8f1d4ad4
7
+ data.tar.gz: 0fde56ad653b34522edcc1f9d5f8d2524ced3551b1f1f3ff1b99226b8263433b27c416b10121ae6fdeb2ed82541341fe6dfd8e8e1ff712d01e3c32d69b6707b6
data/Gemfile CHANGED
@@ -11,4 +11,5 @@ group :development do
11
11
  gem "stackprof" if is_unix && !is_truffleruby
12
12
  gem "test-unit"
13
13
  gem "reline", github: "ruby/reline" if ENV["WITH_LATEST_RELINE"] == "true"
14
+ gem "debug", github: "ruby/debug"
14
15
  end
data/README.md CHANGED
@@ -42,54 +42,57 @@ The Readline extension module can be used with irb. Use of Readline is default i
42
42
 
43
43
  ## Commands
44
44
 
45
- The following commands are available on IRB.
46
-
47
- * `cwws`
48
- * Show the current workspace.
49
- * `cb`, `cws`, `chws`
50
- * Change the current workspace to an object.
51
- * `bindings`, `workspaces`
52
- * Show workspaces.
53
- * `edit`
54
- * Open a file with the editor command defined with `ENV["EDITOR"]`
55
- * `edit` - opens the file the current context belongs to (if applicable)
56
- * `edit foo.rb` - opens `foo.rb`
57
- * `edit Foo` - opens the location of `Foo`
58
- * `edit Foo.bar` - opens the location of `Foo.bar`
59
- * `edit Foo#bar` - opens the location of `Foo#bar`
60
- * `pushb`, `pushws`
61
- * Push an object to the workspace stack.
62
- * `popb`, `popws`
63
- * Pop a workspace from the workspace stack.
64
- * `load`
65
- * Load a Ruby file.
66
- * `require`
67
- * Require a Ruby file.
68
- * `source`
69
- * Loads a given file in the current session.
70
- * `irb`
71
- * Start a child IRB.
72
- * `jobs`
73
- * List of current sessions.
74
- * `fg`
75
- * Switches to the session of the given number.
76
- * `kill`
77
- * Kills the session with the given number.
78
- * `help`
79
- * Enter the mode to look up RI documents.
80
- * `irb_info`
81
- * Show information about IRB.
82
- * `ls`
83
- * Show methods, constants, and variables.
84
- `-g [query]` or `-G [query]` allows you to filter out the output.
85
- * `measure`
86
- * `measure` enables the mode to measure processing time. `measure :off` disables it.
87
- * `$`, `show_source`
88
- * Show the source code of a given method or constant.
89
- * `@`, `whereami`
90
- * Show the source code around binding.irb again.
91
- * `debug`
92
- * Start the debugger of debug.gem.
45
+ The following commands are available on IRB. You can get the same output from the `show_cmds` command.
46
+
47
+
48
+ ```
49
+ IRB
50
+ cwws Show the current workspace.
51
+ chws Change the current workspace to an object.
52
+ workspaces Show workspaces.
53
+ pushws Push an object to the workspace stack.
54
+ popws Pop a workspace from the workspace stack.
55
+ irb_load Load a Ruby file.
56
+ irb_require Require a Ruby file.
57
+ source Loads a given file in the current session.
58
+ irb Start a child IRB.
59
+ jobs List of current sessions.
60
+ fg Switches to the session of the given number.
61
+ kill Kills the session with the given number.
62
+ irb_info Show information about IRB.
63
+ show_cmds List all available commands and their description.
64
+
65
+ Debugging
66
+ debug Start the debugger of debug.gem.
67
+ break Start the debugger of debug.gem and run its `break` command.
68
+ catch Start the debugger of debug.gem and run its `catch` command.
69
+ next Start the debugger of debug.gem and run its `next` command.
70
+ delete Start the debugger of debug.gem and run its `delete` command.
71
+ step Start the debugger of debug.gem and run its `step` command.
72
+ continue Start the debugger of debug.gem and run its `continue` command.
73
+ finish Start the debugger of debug.gem and run its `finish` command.
74
+ backtrace Start the debugger of debug.gem and run its `backtrace` command.
75
+ info Start the debugger of debug.gem and run its `info` command.
76
+
77
+ Misc
78
+ edit Open a file with the editor command defined with `ENV["EDITOR"]`.
79
+ measure `measure` enables the mode to measure processing time. `measure :off` disables it.
80
+
81
+ Context
82
+ show_doc Enter the mode to look up RI documents.
83
+ ls Show methods, constants, and variables. `-g [query]` or `-G [query]` allows you to filter out the output.
84
+ show_source Show the source code of a given method or constant.
85
+ whereami Show the source code around binding.irb again.
86
+ ```
87
+
88
+ ## Configuration
89
+
90
+ ### Environment Variables
91
+
92
+ - `NO_COLOR`: Assigning a value to it disables IRB's colorization.
93
+ - `IRB_USE_AUTOCOMPLETE`: Setting it to `false` disables IRB's autocompletion.
94
+ - `EDITOR`: Its value would be used to open files by the `edit` command.
95
+ - `IRBRC`: The file specified would be evaluated as IRB's rc-file.
93
96
 
94
97
  ## Documentation
95
98
 
@@ -105,6 +108,13 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
105
108
 
106
109
  Bug reports and pull requests are welcome on GitHub at https://github.com/ruby/irb.
107
110
 
111
+ ## Releasing
112
+
113
+ ```
114
+ rake release
115
+ gh release create vX.Y.Z --generate-notes
116
+ ```
117
+
108
118
  ## License
109
119
 
110
120
  The gem is available as open source under the terms of the [2-Clause BSD License](https://opensource.org/licenses/BSD-2-Clause).
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "debug"
4
+
5
+ module IRB
6
+ # :stopdoc:
7
+
8
+ module ExtendCommand
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(" "))
16
+ end
17
+ end
18
+ end
19
+
20
+ # :startdoc:
21
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "debug"
4
+
5
+ module IRB
6
+ # :stopdoc:
7
+
8
+ module ExtendCommand
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}")
16
+ end
17
+ end
18
+ end
19
+
20
+ # :startdoc:
21
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "debug"
4
+
5
+ module IRB
6
+ # :stopdoc:
7
+
8
+ module ExtendCommand
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(" "))
16
+ end
17
+ end
18
+ end
19
+
20
+ # :startdoc:
21
+ end
data/lib/irb/cmd/chws.rb CHANGED
@@ -19,12 +19,18 @@ module IRB
19
19
  module ExtendCommand
20
20
 
21
21
  class CurrentWorkingWorkspace < Nop
22
+ category "IRB"
23
+ description "Show the current workspace."
24
+
22
25
  def execute(*obj)
23
26
  irb_context.main
24
27
  end
25
28
  end
26
29
 
27
30
  class ChangeWorkspace < Nop
31
+ category "IRB"
32
+ description "Change the current workspace to an object."
33
+
28
34
  def execute(*obj)
29
35
  irb_context.change_workspace(*obj)
30
36
  irb_context.main
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "debug"
4
+
5
+ module IRB
6
+ # :stopdoc:
7
+
8
+ module ExtendCommand
9
+ class Continue < DebugCommand
10
+ def execute(*args)
11
+ super(do_cmds: ["continue", *args].join(" "))
12
+ end
13
+ end
14
+ end
15
+
16
+ # :startdoc:
17
+ end
data/lib/irb/cmd/debug.rb CHANGED
@@ -5,13 +5,16 @@ module IRB
5
5
 
6
6
  module ExtendCommand
7
7
  class Debug < Nop
8
+ category "Debugging"
9
+ description "Start the debugger of debug.gem."
10
+
8
11
  BINDING_IRB_FRAME_REGEXPS = [
9
12
  '<internal:prelude>',
10
13
  binding.method(:irb).source_location.first,
11
14
  ].map { |file| /\A#{Regexp.escape(file)}:\d+:in `irb'\z/ }
12
15
  IRB_DIR = File.expand_path('..', __dir__)
13
16
 
14
- def execute(*args)
17
+ def execute(pre_cmds: nil, do_cmds: nil)
15
18
  unless binding_irb?
16
19
  puts "`debug` command is only available when IRB is started with binding.irb"
17
20
  return
@@ -25,11 +28,19 @@ module IRB
25
28
  return
26
29
  end
27
30
 
31
+ options = { oneshot: true, hook_call: false }
32
+ if pre_cmds || do_cmds
33
+ options[:command] = ['irb', pre_cmds, do_cmds]
34
+ end
35
+ if DEBUGGER__::LineBreakpoint.instance_method(:initialize).parameters.include?([:key, :skip_src])
36
+ options[:skip_src] = true
37
+ end
38
+
28
39
  # To make debugger commands like `next` or `continue` work without asking
29
40
  # the user to quit IRB after that, we need to exit IRB first and then hit
30
41
  # a TracePoint on #debug_break.
31
42
  file, lineno = IRB::Irb.instance_method(:debug_break).source_location
32
- DEBUGGER__::SESSION.add_line_breakpoint(file, lineno + 1, oneshot: true, hook_call: false)
43
+ DEBUGGER__::SESSION.add_line_breakpoint(file, lineno + 1, **options)
33
44
  # exit current Irb#run call
34
45
  throw :IRB_EXIT
35
46
  end
@@ -74,14 +85,22 @@ module IRB
74
85
  # it's a bundled gem. This method tries to activate and load that.
75
86
  def load_bundled_debug_gem
76
87
  # Discover latest debug.gem under GEM_PATH
77
- debug_gem = Gem.paths.path.map { |path| Dir.glob("#{path}/gems/debug-*") }.flatten.select do |path|
78
- File.basename(path).match?(/\Adebug-\d+\.\d+\.\d+\z/)
88
+ debug_gem = Gem.paths.path.flat_map { |path| Dir.glob("#{path}/gems/debug-*") }.select do |path|
89
+ File.basename(path).match?(/\Adebug-\d+\.\d+\.\d+(\w+)?\z/)
79
90
  end.sort_by do |path|
80
91
  Gem::Version.new(File.basename(path).delete_prefix('debug-'))
81
92
  end.last
82
93
  return false unless debug_gem
83
94
 
95
+ # Discover debug/debug.so under extensions for Ruby 3.2+
96
+ debug_so = Gem.paths.path.flat_map do |path|
97
+ Dir.glob("#{path}/extensions/**/#{File.basename(debug_gem)}/debug/debug.so")
98
+ end.first
99
+
84
100
  # Attempt to forcibly load the bundled gem
101
+ if debug_so
102
+ $LOAD_PATH << debug_so.delete_suffix('/debug/debug.so')
103
+ end
85
104
  $LOAD_PATH << "#{debug_gem}/lib"
86
105
  begin
87
106
  require "debug/session"
@@ -92,5 +111,16 @@ module IRB
92
111
  end
93
112
  end
94
113
  end
114
+
115
+ class DebugCommand < Debug
116
+ def self.category
117
+ "Debugging"
118
+ end
119
+
120
+ def self.description
121
+ command_name = self.name.split("::").last.downcase
122
+ "Start the debugger of debug.gem and run its `#{command_name}` command."
123
+ end
124
+ end
95
125
  end
96
126
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "debug"
4
+
5
+ module IRB
6
+ # :stopdoc:
7
+
8
+ module ExtendCommand
9
+ class Delete < DebugCommand
10
+ def execute(*args)
11
+ super(pre_cmds: ["delete", *args].join(" "))
12
+ end
13
+ end
14
+ end
15
+
16
+ # :startdoc:
17
+ end
data/lib/irb/cmd/edit.rb CHANGED
@@ -6,6 +6,9 @@ module IRB
6
6
 
7
7
  module ExtendCommand
8
8
  class Edit < Nop
9
+ category "Misc"
10
+ description 'Open a file with the editor command defined with `ENV["EDITOR"]`.'
11
+
9
12
  class << self
10
13
  def transform_args(args)
11
14
  # Return a string literal as is for backward compatibility
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "debug"
4
+
5
+ module IRB
6
+ # :stopdoc:
7
+
8
+ module ExtendCommand
9
+ class Finish < DebugCommand
10
+ def execute(*args)
11
+ super(do_cmds: ["finish", *args].join(" "))
12
+ end
13
+ end
14
+ end
15
+
16
+ # :startdoc:
17
+ end
data/lib/irb/cmd/help.rb CHANGED
@@ -16,6 +16,9 @@ module IRB
16
16
 
17
17
  module ExtendCommand
18
18
  class Help < Nop
19
+ category "Context"
20
+ description "Enter the mode to look up RI documents."
21
+
19
22
  def execute(*names)
20
23
  require 'rdoc/ri/driver'
21
24
  opts = RDoc::RI::Driver.process_args([])
data/lib/irb/cmd/info.rb CHANGED
@@ -1,31 +1,18 @@
1
- # frozen_string_literal: false
1
+ # frozen_string_literal: true
2
2
 
3
- require_relative "nop"
3
+ require_relative "debug"
4
4
 
5
5
  module IRB
6
6
  # :stopdoc:
7
7
 
8
8
  module ExtendCommand
9
- class Info < Nop
10
- def execute
11
- Class.new {
12
- def inspect
13
- str = "Ruby version: #{RUBY_VERSION}\n"
14
- str += "IRB version: #{IRB.version}\n"
15
- str += "InputMethod: #{IRB.CurrentContext.io.inspect}\n"
16
- str += ".irbrc path: #{IRB.rc_file}\n" if File.exist?(IRB.rc_file)
17
- str += "RUBY_PLATFORM: #{RUBY_PLATFORM}\n"
18
- str += "LANG env: #{ENV["LANG"]}\n" if ENV["LANG"] && !ENV["LANG"].empty?
19
- str += "LC_ALL env: #{ENV["LC_ALL"]}\n" if ENV["LC_ALL"] && !ENV["LC_ALL"].empty?
20
- str += "East Asian Ambiguous Width: #{Reline.ambiguous_width.inspect}\n"
21
- if RbConfig::CONFIG['host_os'] =~ /mswin|msys|mingw|cygwin|bccwin|wince|emc/
22
- codepage = `chcp`.b.sub(/.*: (\d+)\n/, '\1')
23
- str += "Code page: #{codepage}\n"
24
- end
25
- str
26
- end
27
- alias_method :to_s, :inspect
28
- }.new
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(" "))
29
16
  end
30
17
  end
31
18
  end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: false
2
+
3
+ require_relative "nop"
4
+
5
+ module IRB
6
+ # :stopdoc:
7
+
8
+ module ExtendCommand
9
+ class IrbInfo < Nop
10
+ category "IRB"
11
+ description "Show information about IRB."
12
+
13
+ def execute
14
+ Class.new {
15
+ def inspect
16
+ str = "Ruby version: #{RUBY_VERSION}\n"
17
+ str += "IRB version: #{IRB.version}\n"
18
+ str += "InputMethod: #{IRB.CurrentContext.io.inspect}\n"
19
+ str += ".irbrc path: #{IRB.rc_file}\n" if File.exist?(IRB.rc_file)
20
+ str += "RUBY_PLATFORM: #{RUBY_PLATFORM}\n"
21
+ str += "LANG env: #{ENV["LANG"]}\n" if ENV["LANG"] && !ENV["LANG"].empty?
22
+ str += "LC_ALL env: #{ENV["LC_ALL"]}\n" if ENV["LC_ALL"] && !ENV["LC_ALL"].empty?
23
+ str += "East Asian Ambiguous Width: #{Reline.ambiguous_width.inspect}\n"
24
+ if RbConfig::CONFIG['host_os'] =~ /mswin|msys|mingw|cygwin|bccwin|wince|emc/
25
+ codepage = `chcp`.b.sub(/.*: (\d+)\n/, '\1')
26
+ str += "Code page: #{codepage}\n"
27
+ end
28
+ str
29
+ end
30
+ alias_method :to_s, :inspect
31
+ }.new
32
+ end
33
+ end
34
+ end
35
+
36
+ # :startdoc:
37
+ end
data/lib/irb/cmd/load.rb CHANGED
@@ -17,18 +17,29 @@ module IRB
17
17
  # :stopdoc:
18
18
 
19
19
  module ExtendCommand
20
- class Load < Nop
20
+ class LoaderCommand < Nop
21
21
  include IrbLoader
22
22
 
23
- def execute(file_name, priv = nil)
24
- return irb_load(file_name, priv)
23
+ def raise_cmd_argument_error
24
+ raise CommandArgumentError.new("Please specify the file name.")
25
25
  end
26
26
  end
27
27
 
28
- class Require < Nop
29
- include IrbLoader
28
+ class Load < LoaderCommand
29
+ category "IRB"
30
+ description "Load a Ruby file."
31
+
32
+ def execute(file_name = nil, priv = nil)
33
+ raise_cmd_argument_error unless file_name
34
+ irb_load(file_name, priv)
35
+ end
36
+ end
30
37
 
31
- def execute(file_name)
38
+ class Require < LoaderCommand
39
+ category "IRB"
40
+ description "Require a Ruby file."
41
+ def execute(file_name = nil)
42
+ raise_cmd_argument_error unless file_name
32
43
 
33
44
  rex = Regexp.new("#{Regexp.quote(file_name)}(\.o|\.rb)?")
34
45
  return false if $".find{|f| f =~ rex}
@@ -56,13 +67,16 @@ module IRB
56
67
  end
57
68
  end
58
69
 
59
- class Source < Nop
60
- include IrbLoader
61
- def execute(file_name)
70
+ class Source < LoaderCommand
71
+ category "IRB"
72
+ description "Loads a given file in the current session."
73
+
74
+ def execute(file_name = nil)
75
+ raise_cmd_argument_error unless file_name
76
+
62
77
  source_file(file_name)
63
78
  end
64
79
  end
65
80
  end
66
-
67
81
  # :startdoc:
68
82
  end
data/lib/irb/cmd/ls.rb CHANGED
@@ -9,6 +9,9 @@ module IRB
9
9
 
10
10
  module ExtendCommand
11
11
  class Ls < Nop
12
+ category "Context"
13
+ description "Show methods, constants, and variables. `-g [query]` or `-G [query]` allows you to filter out the output."
14
+
12
15
  def self.transform_args(args)
13
16
  if match = args&.match(/\A(?<args>.+\s|)(-g|-G)\s+(?<grep>[^\s]+)\s*\n\z/)
14
17
  args = match[:args]
@@ -30,6 +33,7 @@ module IRB
30
33
  o.dump("instance variables", obj.instance_variables)
31
34
  o.dump("class variables", klass.class_variables)
32
35
  o.dump("locals", locals)
36
+ nil
33
37
  end
34
38
 
35
39
  def dump_methods(o, klass, obj)
@@ -5,6 +5,9 @@ module IRB
5
5
 
6
6
  module ExtendCommand
7
7
  class Measure < Nop
8
+ category "Misc"
9
+ description "`measure` enables the mode to measure processing time. `measure :off` disables it."
10
+
8
11
  def initialize(*args)
9
12
  super(*args)
10
13
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "debug"
4
+
5
+ module IRB
6
+ # :stopdoc:
7
+
8
+ module ExtendCommand
9
+ class Next < DebugCommand
10
+ def execute(*args)
11
+ super(do_cmds: ["next", *args].join(" "))
12
+ end
13
+ end
14
+ end
15
+
16
+ # :startdoc:
17
+ end
data/lib/irb/cmd/nop.rb CHANGED
@@ -13,17 +13,34 @@ module IRB
13
13
  # :stopdoc:
14
14
 
15
15
  module ExtendCommand
16
+ class CommandArgumentError < StandardError; end
17
+
16
18
  class Nop
19
+ class << self
20
+ def category(category = nil)
21
+ @category = category if category
22
+ @category
23
+ end
24
+
25
+ def description(description = nil)
26
+ @description = description if description
27
+ @description
28
+ end
29
+ end
17
30
 
18
31
  if RUBY_ENGINE == "ruby" && RUBY_VERSION >= "2.7.0"
19
32
  def self.execute(conf, *opts, **kwargs, &block)
20
33
  command = new(conf)
21
34
  command.execute(*opts, **kwargs, &block)
35
+ rescue CommandArgumentError => e
36
+ puts e.message
22
37
  end
23
38
  else
24
39
  def self.execute(conf, *opts, &block)
25
40
  command = new(conf)
26
41
  command.execute(*opts, &block)
42
+ rescue CommandArgumentError => e
43
+ puts e.message
27
44
  end
28
45
  end
29
46
 
@@ -18,12 +18,18 @@ module IRB
18
18
 
19
19
  module ExtendCommand
20
20
  class Workspaces < Nop
21
+ category "IRB"
22
+ description "Show workspaces."
23
+
21
24
  def execute(*obj)
22
25
  irb_context.workspaces.collect{|ws| ws.main}
23
26
  end
24
27
  end
25
28
 
26
29
  class PushWorkspace < Workspaces
30
+ category "IRB"
31
+ description "Push an object to the workspace stack."
32
+
27
33
  def execute(*obj)
28
34
  irb_context.push_workspace(*obj)
29
35
  super
@@ -31,6 +37,9 @@ module IRB
31
37
  end
32
38
 
33
39
  class PopWorkspace < Workspaces
40
+ category "IRB"
41
+ description "Pop a workspace from the workspace stack."
42
+
34
43
  def execute(*obj)
35
44
  irb_context.pop_workspace(*obj)
36
45
  super
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "stringio"
4
+ require_relative "nop"
5
+
6
+ module IRB
7
+ # :stopdoc:
8
+
9
+ module ExtendCommand
10
+ class ShowCmds < Nop
11
+ category "IRB"
12
+ description "List all available commands and their description."
13
+
14
+ def execute(*args)
15
+ commands_info = IRB::ExtendCommandBundle.all_commands_info
16
+ commands_grouped_by_categories = commands_info.group_by { |cmd| cmd[:category] }
17
+ longest_cmd_name_length = commands_info.map { |c| c[:display_name] }.max { |a, b| a.length <=> b.length }.length
18
+
19
+ output = StringIO.new
20
+
21
+ commands_grouped_by_categories.each do |category, cmds|
22
+ output.puts Color.colorize(category, [:BOLD])
23
+
24
+ cmds.each do |cmd|
25
+ output.puts " #{cmd[:display_name].to_s.ljust(longest_cmd_name_length)} #{cmd[:description]}"
26
+ end
27
+
28
+ output.puts
29
+ end
30
+
31
+ puts output.string
32
+
33
+ nil
34
+ end
35
+ end
36
+ end
37
+
38
+ # :startdoc:
39
+ end
@@ -9,6 +9,9 @@ module IRB
9
9
 
10
10
  module ExtendCommand
11
11
  class ShowSource < Nop
12
+ category "Context"
13
+ description "Show the source code of a given method or constant."
14
+
12
15
  class << self
13
16
  def transform_args(args)
14
17
  # Return a string literal as is for backward compatibility
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "debug"
4
+
5
+ module IRB
6
+ # :stopdoc:
7
+
8
+ module ExtendCommand
9
+ class Step < DebugCommand
10
+ def execute(*args)
11
+ # Run `next` first to move out of binding.irb
12
+ super(pre_cmds: "next", do_cmds: ["step", *args].join(" "))
13
+ end
14
+ end
15
+ end
16
+
17
+ # :startdoc:
18
+ end
@@ -10,31 +10,57 @@
10
10
  #
11
11
 
12
12
  require_relative "nop"
13
- require_relative "../ext/multi-irb"
14
13
 
15
14
  module IRB
16
15
  # :stopdoc:
17
16
 
18
17
  module ExtendCommand
19
- class IrbCommand < Nop
18
+ class MultiIRBCommand < Nop
19
+ def initialize(conf)
20
+ super
21
+ extend_irb_context
22
+ end
23
+
24
+ private
25
+
26
+ def extend_irb_context
27
+ # this extension patches IRB context like IRB.CurrentContext
28
+ require_relative "../ext/multi-irb"
29
+ end
30
+ end
31
+
32
+ class IrbCommand < MultiIRBCommand
33
+ category "IRB"
34
+ description "Start a child IRB."
35
+
20
36
  def execute(*obj)
21
37
  IRB.irb(nil, *obj)
22
38
  end
23
39
  end
24
40
 
25
- class Jobs < Nop
41
+ class Jobs < MultiIRBCommand
42
+ category "IRB"
43
+ description "List of current sessions."
44
+
26
45
  def execute
27
46
  IRB.JobManager
28
47
  end
29
48
  end
30
49
 
31
- class Foreground < Nop
32
- def execute(key)
50
+ class Foreground < MultiIRBCommand
51
+ category "IRB"
52
+ description "Switches to the session of the given number."
53
+
54
+ def execute(key = nil)
55
+ raise CommandArgumentError.new("Please specify the id of target IRB job (listed in the `jobs` command).") unless key
33
56
  IRB.JobManager.switch(key)
34
57
  end
35
58
  end
36
59
 
37
- class Kill < Nop
60
+ class Kill < MultiIRBCommand
61
+ category "IRB"
62
+ description "Kills the session with the given number."
63
+
38
64
  def execute(*keys)
39
65
  IRB.JobManager.kill(*keys)
40
66
  end
@@ -7,6 +7,9 @@ module IRB
7
7
 
8
8
  module ExtendCommand
9
9
  class Whereami < Nop
10
+ category "Context"
11
+ description "Show the source code around binding.irb again."
12
+
10
13
  def execute(*)
11
14
  code = irb_context.workspace.code_around_binding
12
15
  if code
data/lib/irb/context.rb CHANGED
@@ -486,9 +486,9 @@ module IRB
486
486
  @workspace.local_variable_set(:_, exception)
487
487
  end
488
488
 
489
- # Transform a non-identifier alias (ex: @, $)
489
+ # Transform a non-identifier alias (@, $) or keywords (next, break)
490
490
  command, args = line.split(/\s/, 2)
491
- if original = symbol_alias(command)
491
+ if original = command_aliases[command.to_sym]
492
492
  line = line.gsub(/\A#{Regexp.escape(command)}/, original.to_s)
493
493
  command = original
494
494
  end
@@ -545,10 +545,16 @@ module IRB
545
545
  workspace.binding.local_variables
546
546
  end
547
547
 
548
- # Return a command name if it's aliased from the argument and it's not an identifier.
549
- def symbol_alias(command)
548
+ # Return true if it's aliased from the argument and it's not an identifier.
549
+ def symbol_alias?(command)
550
550
  return nil if command.match?(/\A\w+\z/)
551
- command_aliases[command.to_sym]
551
+ command_aliases.key?(command.to_sym)
552
+ end
553
+
554
+ # Return true if the command supports transforming args
555
+ def transform_args?(command)
556
+ command = command_aliases.fetch(command.to_sym, command)
557
+ ExtendCommandBundle.load_command(command)&.respond_to?(:transform_args)
552
558
  end
553
559
  end
554
560
  end
@@ -70,7 +70,7 @@ module IRB
70
70
  end
71
71
  history_file = IRB.rc_file("_history") unless history_file
72
72
  if File.exist?(history_file)
73
- open(history_file, "r:#{IRB.conf[:LC_MESSAGES].encoding}") do |f|
73
+ File.open(history_file, "r:#{IRB.conf[:LC_MESSAGES].encoding}") do |f|
74
74
  f.each { |l|
75
75
  l = l.chomp
76
76
  if self.class == RelineInputMethod and history.last&.end_with?("\\")
@@ -45,14 +45,15 @@ module IRB # :nodoc:
45
45
  [:quit, :irb_exit, OVERRIDE_PRIVATE_ONLY],
46
46
  ]
47
47
 
48
+
48
49
  @EXTEND_COMMANDS = [
49
50
  [
50
51
  :irb_current_working_workspace, :CurrentWorkingWorkspace, "cmd/chws",
52
+ [:cwws, NO_OVERRIDE],
53
+ [:pwws, NO_OVERRIDE],
51
54
  [:irb_print_working_workspace, OVERRIDE_ALL],
52
55
  [:irb_cwws, OVERRIDE_ALL],
53
56
  [:irb_pwws, OVERRIDE_ALL],
54
- [:cwws, NO_OVERRIDE],
55
- [:pwws, NO_OVERRIDE],
56
57
  [:irb_current_working_binding, OVERRIDE_ALL],
57
58
  [:irb_print_working_binding, OVERRIDE_ALL],
58
59
  [:irb_cwb, OVERRIDE_ALL],
@@ -60,10 +61,10 @@ module IRB # :nodoc:
60
61
  ],
61
62
  [
62
63
  :irb_change_workspace, :ChangeWorkspace, "cmd/chws",
63
- [:irb_chws, OVERRIDE_ALL],
64
- [:irb_cws, OVERRIDE_ALL],
65
64
  [:chws, NO_OVERRIDE],
66
65
  [:cws, NO_OVERRIDE],
66
+ [:irb_chws, OVERRIDE_ALL],
67
+ [:irb_cws, OVERRIDE_ALL],
67
68
  [:irb_change_binding, OVERRIDE_ALL],
68
69
  [:irb_cb, OVERRIDE_ALL],
69
70
  [:cb, NO_OVERRIDE],
@@ -77,16 +78,16 @@ module IRB # :nodoc:
77
78
  ],
78
79
  [
79
80
  :irb_push_workspace, :PushWorkspace, "cmd/pushws",
80
- [:irb_pushws, OVERRIDE_ALL],
81
81
  [:pushws, NO_OVERRIDE],
82
+ [:irb_pushws, OVERRIDE_ALL],
82
83
  [:irb_push_binding, OVERRIDE_ALL],
83
84
  [:irb_pushb, OVERRIDE_ALL],
84
85
  [:pushb, NO_OVERRIDE],
85
86
  ],
86
87
  [
87
88
  :irb_pop_workspace, :PopWorkspace, "cmd/pushws",
88
- [:irb_popws, OVERRIDE_ALL],
89
89
  [:popws, NO_OVERRIDE],
90
+ [:irb_popws, OVERRIDE_ALL],
90
91
  [:irb_pop_binding, OVERRIDE_ALL],
91
92
  [:irb_popb, OVERRIDE_ALL],
92
93
  [:popb, NO_OVERRIDE],
@@ -124,13 +125,49 @@ module IRB # :nodoc:
124
125
  :irb_edit, :Edit, "cmd/edit",
125
126
  [:edit, NO_OVERRIDE],
126
127
  ],
128
+ [
129
+ :irb_break, :Break, "cmd/break",
130
+ ],
131
+ [
132
+ :irb_catch, :Catch, "cmd/catch",
133
+ ],
134
+ [
135
+ :irb_next, :Next, "cmd/next"
136
+ ],
137
+ [
138
+ :irb_delete, :Delete, "cmd/delete",
139
+ [:delete, NO_OVERRIDE],
140
+ ],
141
+ [
142
+ :irb_step, :Step, "cmd/step",
143
+ [:step, NO_OVERRIDE],
144
+ ],
145
+ [
146
+ :irb_continue, :Continue, "cmd/continue",
147
+ [:continue, NO_OVERRIDE],
148
+ ],
149
+ [
150
+ :irb_finish, :Finish, "cmd/finish",
151
+ [:finish, NO_OVERRIDE],
152
+ ],
153
+ [
154
+ :irb_backtrace, :Backtrace, "cmd/backtrace",
155
+ [:backtrace, NO_OVERRIDE],
156
+ [:bt, NO_OVERRIDE],
157
+ ],
158
+ [
159
+ :irb_debug_info, :Info, "cmd/info",
160
+ [:info, NO_OVERRIDE],
161
+ ],
162
+
127
163
  [
128
164
  :irb_help, :Help, "cmd/help",
165
+ [:show_doc, NO_OVERRIDE],
129
166
  [:help, NO_OVERRIDE],
130
167
  ],
131
168
 
132
169
  [
133
- :irb_info, :Info, "cmd/info"
170
+ :irb_info, :IrbInfo, "cmd/irb_info"
134
171
  ],
135
172
 
136
173
  [
@@ -152,9 +189,41 @@ module IRB # :nodoc:
152
189
  :irb_whereami, :Whereami, "cmd/whereami",
153
190
  [:whereami, NO_OVERRIDE],
154
191
  ],
155
-
192
+ [
193
+ :irb_show_cmds, :ShowCmds, "cmd/show_cmds",
194
+ [:show_cmds, NO_OVERRIDE],
195
+ ]
156
196
  ]
157
197
 
198
+
199
+ @@commands = []
200
+
201
+ def self.all_commands_info
202
+ return @@commands unless @@commands.empty?
203
+ user_aliases = IRB.CurrentContext.command_aliases.each_with_object({}) do |(alias_name, target), result|
204
+ result[target] ||= []
205
+ result[target] << alias_name
206
+ end
207
+
208
+ @EXTEND_COMMANDS.each do |cmd_name, cmd_class, load_file, *aliases|
209
+ if !defined?(ExtendCommand) || !ExtendCommand.const_defined?(cmd_class, false)
210
+ require_relative load_file
211
+ end
212
+
213
+ klass = ExtendCommand.const_get(cmd_class, false)
214
+ aliases = aliases.map { |a| a.first }
215
+
216
+ if additional_aliases = user_aliases[cmd_name]
217
+ aliases += additional_aliases
218
+ end
219
+
220
+ display_name = aliases.shift || cmd_name
221
+ @@commands << { display_name: display_name, description: klass.description, category: klass.category }
222
+ end
223
+
224
+ @@commands
225
+ end
226
+
158
227
  # Convert a command name to its implementation class if such command exists
159
228
  def self.load_command(command)
160
229
  command = command.to_sym
data/lib/irb/init.rb CHANGED
@@ -45,7 +45,7 @@ module IRB # :nodoc:
45
45
 
46
46
  @CONF[:USE_SINGLELINE] = false unless defined?(ReadlineInputMethod)
47
47
  @CONF[:USE_COLORIZE] = (nc = ENV['NO_COLOR']).nil? || nc.empty?
48
- @CONF[:USE_AUTOCOMPLETE] = true
48
+ @CONF[:USE_AUTOCOMPLETE] = ENV.fetch("IRB_USE_AUTOCOMPLETE", "true") != "false"
49
49
  @CONF[:INSPECT_MODE] = true
50
50
  @CONF[:USE_TRACER] = false
51
51
  @CONF[:USE_LOADER] = false
@@ -160,8 +160,13 @@ module IRB # :nodoc:
160
160
  @CONF[:AT_EXIT] = []
161
161
 
162
162
  @CONF[:COMMAND_ALIASES] = {
163
+ # Symbol aliases
163
164
  :'$' => :show_source,
164
165
  :'@' => :whereami,
166
+ # Keyword aliases
167
+ :break => :irb_break,
168
+ :catch => :irb_catch,
169
+ :next => :irb_next,
165
170
  }
166
171
  end
167
172
 
data/lib/irb/ruby-lex.rb CHANGED
@@ -65,9 +65,9 @@ class RubyLex
65
65
  false
66
66
  end
67
67
  else
68
- # Accept any single-line input starting with a non-identifier alias (ex: @, $)
68
+ # Accept any single-line input for symbol aliases or commands that transform args
69
69
  command = code.split(/\s/, 2).first
70
- if context.symbol_alias(command)
70
+ if context.symbol_alias?(command) || context.transform_args?(command)
71
71
  next true
72
72
  end
73
73
 
data/lib/irb/version.rb CHANGED
@@ -11,7 +11,7 @@
11
11
  #
12
12
 
13
13
  module IRB # :nodoc:
14
- VERSION = "1.5.0"
14
+ VERSION = "1.6.0"
15
15
  @RELEASE_VERSION = VERSION
16
- @LAST_UPDATE_DATE = "2022-11-20"
16
+ @LAST_UPDATE_DATE = "2022-11-28"
17
17
  end
data/lib/irb.rb CHANGED
@@ -96,6 +96,8 @@ require_relative "irb/easter-egg"
96
96
  # * Show the source code around binding.irb again.
97
97
  # * debug
98
98
  # * Start the debugger of debug.gem.
99
+ # * break, delete, next, step, continue, finish, backtrace, info, catch
100
+ # * Start the debugger of debug.gem and run the command on it.
99
101
  #
100
102
  # == Configuration
101
103
  #
@@ -470,10 +472,6 @@ module IRB
470
472
  def initialize(workspace = nil, input_method = nil)
471
473
  @context = Context.new(self, workspace, input_method)
472
474
  @context.main.extend ExtendCommandBundle
473
- @context.command_aliases.each do |alias_name, cmd_name|
474
- next if @context.symbol_alias(alias_name)
475
- @context.main.install_alias_method(alias_name, cmd_name)
476
- end
477
475
  @signal_status = :IN_IRB
478
476
  @scanner = RubyLex.new
479
477
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: irb
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.0
4
+ version: 1.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - aycabta
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2022-11-21 00:00:00.000000000 Z
12
+ date: 2022-12-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: reline
@@ -46,18 +46,28 @@ files:
46
46
  - exe/irb
47
47
  - irb.gemspec
48
48
  - lib/irb.rb
49
+ - lib/irb/cmd/backtrace.rb
50
+ - lib/irb/cmd/break.rb
51
+ - lib/irb/cmd/catch.rb
49
52
  - lib/irb/cmd/chws.rb
53
+ - lib/irb/cmd/continue.rb
50
54
  - lib/irb/cmd/debug.rb
55
+ - lib/irb/cmd/delete.rb
51
56
  - lib/irb/cmd/edit.rb
57
+ - lib/irb/cmd/finish.rb
52
58
  - lib/irb/cmd/fork.rb
53
59
  - lib/irb/cmd/help.rb
54
60
  - lib/irb/cmd/info.rb
61
+ - lib/irb/cmd/irb_info.rb
55
62
  - lib/irb/cmd/load.rb
56
63
  - lib/irb/cmd/ls.rb
57
64
  - lib/irb/cmd/measure.rb
65
+ - lib/irb/cmd/next.rb
58
66
  - lib/irb/cmd/nop.rb
59
67
  - lib/irb/cmd/pushws.rb
68
+ - lib/irb/cmd/show_cmds.rb
60
69
  - lib/irb/cmd/show_source.rb
70
+ - lib/irb/cmd/step.rb
61
71
  - lib/irb/cmd/subirb.rb
62
72
  - lib/irb/cmd/whereami.rb
63
73
  - lib/irb/color.rb
@@ -116,7 +126,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
116
126
  - !ruby/object:Gem::Version
117
127
  version: '0'
118
128
  requirements: []
119
- rubygems_version: 3.3.7
129
+ rubygems_version: 3.3.26
120
130
  signing_key:
121
131
  specification_version: 4
122
132
  summary: Interactive Ruby command-line tool for REPL (Read Eval Print Loop).