irb 1.7.1 → 1.13.2

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.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/.document +1 -1
  3. data/Gemfile +10 -1
  4. data/README.md +265 -20
  5. data/Rakefile +13 -10
  6. data/doc/irb/irb.rd.ja +1 -3
  7. data/irb.gemspec +2 -1
  8. data/lib/irb/cmd/nop.rb +3 -52
  9. data/lib/irb/color.rb +4 -2
  10. data/lib/irb/command/backtrace.rb +17 -0
  11. data/lib/irb/command/base.rb +62 -0
  12. data/lib/irb/command/break.rb +17 -0
  13. data/lib/irb/command/catch.rb +17 -0
  14. data/lib/irb/command/chws.rb +40 -0
  15. data/lib/irb/command/context.rb +16 -0
  16. data/lib/irb/{cmd → command}/continue.rb +3 -3
  17. data/lib/irb/command/debug.rb +71 -0
  18. data/lib/irb/{cmd → command}/delete.rb +3 -3
  19. data/lib/irb/command/disable_irb.rb +19 -0
  20. data/lib/irb/command/edit.rb +63 -0
  21. data/lib/irb/command/exit.rb +18 -0
  22. data/lib/irb/{cmd → command}/finish.rb +3 -3
  23. data/lib/irb/command/force_exit.rb +18 -0
  24. data/lib/irb/command/help.rb +83 -0
  25. data/lib/irb/command/history.rb +45 -0
  26. data/lib/irb/command/info.rb +17 -0
  27. data/lib/irb/command/internal_helpers.rb +27 -0
  28. data/lib/irb/{cmd → command}/irb_info.rb +7 -7
  29. data/lib/irb/{cmd → command}/load.rb +23 -8
  30. data/lib/irb/{cmd → command}/ls.rb +42 -19
  31. data/lib/irb/{cmd → command}/measure.rb +18 -17
  32. data/lib/irb/{cmd → command}/next.rb +3 -3
  33. data/lib/irb/command/pushws.rb +65 -0
  34. data/lib/irb/command/show_doc.rb +51 -0
  35. data/lib/irb/command/show_source.rb +74 -0
  36. data/lib/irb/{cmd → command}/step.rb +3 -3
  37. data/lib/irb/command/subirb.rb +123 -0
  38. data/lib/irb/{cmd → command}/whereami.rb +3 -5
  39. data/lib/irb/command.rb +23 -0
  40. data/lib/irb/completion.rb +133 -102
  41. data/lib/irb/context.rb +182 -66
  42. data/lib/irb/debug/ui.rb +103 -0
  43. data/lib/irb/{cmd/debug.rb → debug.rb} +53 -59
  44. data/lib/irb/default_commands.rb +265 -0
  45. data/lib/irb/easter-egg.rb +16 -6
  46. data/lib/irb/ext/change-ws.rb +6 -8
  47. data/lib/irb/ext/{history.rb → eval_history.rb} +7 -7
  48. data/lib/irb/ext/loader.rb +4 -4
  49. data/lib/irb/ext/multi-irb.rb +5 -5
  50. data/lib/irb/ext/tracer.rb +12 -51
  51. data/lib/irb/ext/use-loader.rb +6 -8
  52. data/lib/irb/ext/workspaces.rb +10 -34
  53. data/lib/irb/frame.rb +1 -1
  54. data/lib/irb/help.rb +3 -3
  55. data/lib/irb/helper_method/base.rb +16 -0
  56. data/lib/irb/helper_method/conf.rb +11 -0
  57. data/lib/irb/helper_method.rb +29 -0
  58. data/lib/irb/{ext/save-history.rb → history.rb} +20 -58
  59. data/lib/irb/init.rb +154 -58
  60. data/lib/irb/input-method.rb +238 -203
  61. data/lib/irb/inspector.rb +3 -3
  62. data/lib/irb/lc/error.rb +1 -11
  63. data/lib/irb/lc/help-message +4 -0
  64. data/lib/irb/lc/ja/error.rb +1 -11
  65. data/lib/irb/lc/ja/help-message +13 -0
  66. data/lib/irb/locale.rb +2 -2
  67. data/lib/irb/nesting_parser.rb +13 -3
  68. data/lib/irb/notifier.rb +1 -1
  69. data/lib/irb/output-method.rb +2 -8
  70. data/lib/irb/pager.rb +91 -0
  71. data/lib/irb/ruby-lex.rb +391 -471
  72. data/lib/irb/ruby_logo.aa +43 -0
  73. data/lib/irb/source_finder.rb +139 -0
  74. data/lib/irb/statement.rb +80 -0
  75. data/lib/irb/version.rb +3 -3
  76. data/lib/irb/workspace.rb +24 -4
  77. data/lib/irb/ws-for-case-2.rb +1 -1
  78. data/lib/irb/xmp.rb +3 -3
  79. data/lib/irb.rb +1232 -604
  80. data/man/irb.1 +7 -0
  81. metadata +60 -32
  82. data/lib/irb/cmd/backtrace.rb +0 -21
  83. data/lib/irb/cmd/break.rb +0 -21
  84. data/lib/irb/cmd/catch.rb +0 -21
  85. data/lib/irb/cmd/chws.rb +0 -36
  86. data/lib/irb/cmd/edit.rb +0 -61
  87. data/lib/irb/cmd/help.rb +0 -23
  88. data/lib/irb/cmd/info.rb +0 -21
  89. data/lib/irb/cmd/pushws.rb +0 -45
  90. data/lib/irb/cmd/show_cmds.rb +0 -39
  91. data/lib/irb/cmd/show_doc.rb +0 -48
  92. data/lib/irb/cmd/show_source.rb +0 -113
  93. data/lib/irb/cmd/subirb.rb +0 -66
  94. data/lib/irb/extend-command.rb +0 -356
  95. data/lib/irb/src_encoding.rb +0 -7
data/lib/irb/ruby_logo.aa CHANGED
@@ -1,3 +1,4 @@
1
+ TYPE: LARGE
1
2
 
2
3
  -+smJYYN?mm-
3
4
  HB"BBYT TQg NggT
@@ -35,3 +36,45 @@
35
36
  m7 NW H N HSVO1z=?11-
36
37
  NgTH bB kH WBHWWHBHWmQgg&gggggNNN
37
38
  NNggggggNN
39
+ TYPE: ASCII
40
+ ,,,;;;;''''';;;'';,
41
+ ,,;'' ';;,;;; ',
42
+ ,,'' ;;'';'''';;;;;;
43
+ ,;' ;; ',, ;
44
+ ,;' ,;' ';, ;
45
+ ;' ,;; ',,,;
46
+ ,' ,;;,,,,,,,,,,,;;;;
47
+ ;' ;;';;;; ,;;
48
+ ;' ,;' ;; '',, ,;;;
49
+ ;; ,;' ; '';, ,; ;'
50
+ ;; ,;;' ;; ;; ;;
51
+ ;;, ,,;;' ; ;'; ;;
52
+ ;';;,,,,;;;;;;;,,, ;; ,' ; ;;
53
+ ; ;;''' ,;'; ''';,,, ; ,;' ;;;;
54
+ ;;;;, ; '; ''';;;' ';;;
55
+ ;'; ;, ;' '; ,;' ', ;;;
56
+ ;;; ; ,; '; ,,' ',, ;;
57
+ ;;; '; ;' ';,,'' ';,;;
58
+ '; ';,; ,,;''''''''';;;;;;,,;;;
59
+ ';,,;;,,;;;;;;;;;;''''''''''''''
60
+ TYPE: UNICODE
61
+ ⣀⣤⣴⣾⣿⣿⣿⡛⠛⠛⠛⠛⣻⣿⠿⠛⠛⠶⣤⡀
62
+ ⣀⣴⠾⠛⠉⠁ ⠙⣿⣶⣤⣶⣟⣉ ⠈⠻⣦
63
+ ⣀⣴⠟⠋ ⢸⣿⠟⠻⣯⡙⠛⠛⠛⠶⠶⠶⢶⣽⣇
64
+ ⣠⡾⠋⠁ ⣾⡿ ⠈⠛⢦⣄ ⣿
65
+ ⣠⡾⠋ ⣰⣿⠃ ⠙⠷⣤⡀ ⣿
66
+ ⢀⡾⠋ ⣰⣿⡏ ⠈⠻⣦⣄⢠⣿
67
+ ⣰⠟⠁ ⣴⣿⣿⣁⣀⣠⣤⣤⣤⣤⣤⣤⣤⣴⠶⠿⣿⡏
68
+ ⣼⠏ ⢀⣾⣿⠟⣿⠿⣯⣍⠁ ⣰⣿⡇
69
+ ⢀⣼⠋ ⢀⣴⣿⠟⠁ ⢸⡇ ⠙⠻⢦⣄⡀ ⢠⡿⣿⡇
70
+ ⢀⣾⡏ ⢀⣴⣿⠟⠁ ⣿ ⠉⠻⢶⣄⡀⣰⡟ ⣿⠃
71
+ ⣾⣿⠁ ⣠⣶⡿⠋⠁ ⢹⡇ ⠈⣿⡏ ⢸⣿
72
+ ⣿⣿⡆ ⢀⣠⣴⣿⡿⠋ ⠈⣿ ⢀⡾⠋⣿ ⢸⣿
73
+ ⣿⠸⣿⣶⣤⣤⣤⣤⣶⣾⠿⠿⣿⣿⠶⣤⣤⣀⡀ ⢹⡇ ⣴⠟⠁ ⣿⡀⢸⣿
74
+ ⣿⢀⣿⣟⠛⠋⠉⠁ ⢰⡟⠹⣧ ⠈⠉⠛⠻⠶⢦⣤⣀⡀ ⠈⣿ ⣠⡾⠃ ⢸⡇⢸⡇
75
+ ⣿⣾⣿⢿⡄ ⣿⠁ ⠘⣧ ⠉⠙⠛⠷⣿⣿⡋ ⠸⣇⣸⡇
76
+ ⣿⠃⣿⠈⢿⡄ ⣸⠇ ⠘⣧ ⢀⣤⠾⠋⠈⠻⣦⡀ ⣿⣿⡇
77
+ ⣿⢸⡏ ⠈⣷⡀ ⢠⡿ ⠘⣧⡀ ⣠⡴⠟⠁ ⠈⠻⣦⣀ ⢿⣿⠁
78
+ ⢻⣾⡇ ⠘⣷ ⣼⠃ ⠘⣷⣠⣴⠟⠋ ⠙⢷⣄⢸⣿
79
+ ⠻⣧⡀ ⠘⣧⣰⡏ ⢀⣠⣤⠶⠛⠉⠛⠛⠛⠛⠛⠛⠻⢶⣶⣶⣶⣶⣶⣤⣤⣽⣿⣿
80
+ ⠈⠛⠷⢦⣤⣽⣿⣥⣤⣶⣶⡿⠿⠿⠶⠶⠶⠶⠾⠛⠛⠛⠛⠛⠛⠛⠋⠉⠉⠉⠉⠉⠉⠁
@@ -0,0 +1,139 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "ruby-lex"
4
+
5
+ module IRB
6
+ class SourceFinder
7
+ class EvaluationError < StandardError; end
8
+
9
+ class Source
10
+ attr_reader :file, :line
11
+ def initialize(file, line, ast_source = nil)
12
+ @file = file
13
+ @line = line
14
+ @ast_source = ast_source
15
+ end
16
+
17
+ def file_exist?
18
+ File.exist?(@file)
19
+ end
20
+
21
+ def binary_file?
22
+ # If the line is zero, it means that the target's source is probably in a binary file.
23
+ @line.zero?
24
+ end
25
+
26
+ def file_content
27
+ @file_content ||= File.read(@file)
28
+ end
29
+
30
+ def colorized_content
31
+ if !binary_file? && file_exist?
32
+ end_line = find_end
33
+ # To correctly colorize, we need to colorize full content and extract the relevant lines.
34
+ colored = IRB::Color.colorize_code(file_content)
35
+ colored.lines[@line - 1...end_line].join
36
+ elsif @ast_source
37
+ IRB::Color.colorize_code(@ast_source)
38
+ end
39
+ end
40
+
41
+ private
42
+
43
+ def find_end
44
+ lex = RubyLex.new
45
+ code = file_content
46
+ lines = code.lines[(@line - 1)..-1]
47
+ tokens = RubyLex.ripper_lex_without_warning(lines.join)
48
+ prev_tokens = []
49
+
50
+ # chunk with line number
51
+ tokens.chunk { |tok| tok.pos[0] }.each do |lnum, chunk|
52
+ code = lines[0..lnum].join
53
+ prev_tokens.concat chunk
54
+ continue = lex.should_continue?(prev_tokens)
55
+ syntax = lex.check_code_syntax(code, local_variables: [])
56
+ if !continue && syntax == :valid
57
+ return @line + lnum
58
+ end
59
+ end
60
+ @line
61
+ end
62
+ end
63
+
64
+ private_constant :Source
65
+
66
+ def initialize(irb_context)
67
+ @irb_context = irb_context
68
+ end
69
+
70
+ def find_source(signature, super_level = 0)
71
+ case signature
72
+ when /\A(::)?[A-Z]\w*(::[A-Z]\w*)*\z/ # ConstName, ::ConstName, ConstPath::ConstName
73
+ eval_receiver_or_owner(signature) # trigger autoload
74
+ *parts, name = signature.split('::', -1)
75
+ base =
76
+ if parts.empty? # ConstName
77
+ find_const_owner(name)
78
+ elsif parts == [''] # ::ConstName
79
+ Object
80
+ else # ConstPath::ConstName
81
+ eval_receiver_or_owner(parts.join('::'))
82
+ end
83
+ file, line = base.const_source_location(name)
84
+ when /\A(?<owner>[A-Z]\w*(::[A-Z]\w*)*)#(?<method>[^ :.]+)\z/ # Class#method
85
+ owner = eval_receiver_or_owner(Regexp.last_match[:owner])
86
+ method = Regexp.last_match[:method]
87
+ return unless owner.respond_to?(:instance_method)
88
+ method = method_target(owner, super_level, method, "owner")
89
+ file, line = method&.source_location
90
+ when /\A((?<receiver>.+)(\.|::))?(?<method>[^ :.]+)\z/ # method, receiver.method, receiver::method
91
+ receiver = eval_receiver_or_owner(Regexp.last_match[:receiver] || 'self')
92
+ method = Regexp.last_match[:method]
93
+ return unless receiver.respond_to?(method, true)
94
+ method = method_target(receiver, super_level, method, "receiver")
95
+ file, line = method&.source_location
96
+ end
97
+ return unless file && line
98
+
99
+ if File.exist?(file)
100
+ Source.new(file, line)
101
+ elsif method
102
+ # Method defined with eval, probably in IRB session
103
+ source = RubyVM::AbstractSyntaxTree.of(method)&.source rescue nil
104
+ Source.new(file, line, source)
105
+ end
106
+ rescue EvaluationError
107
+ nil
108
+ end
109
+
110
+ private
111
+
112
+ def method_target(owner_receiver, super_level, method, type)
113
+ case type
114
+ when "owner"
115
+ target_method = owner_receiver.instance_method(method)
116
+ when "receiver"
117
+ target_method = owner_receiver.method(method)
118
+ end
119
+ super_level.times do |s|
120
+ target_method = target_method.super_method if target_method
121
+ end
122
+ target_method
123
+ rescue NameError
124
+ nil
125
+ end
126
+
127
+ def eval_receiver_or_owner(code)
128
+ context_binding = @irb_context.workspace.binding
129
+ eval(code, context_binding)
130
+ rescue NameError
131
+ raise EvaluationError
132
+ end
133
+
134
+ def find_const_owner(name)
135
+ module_nesting = @irb_context.workspace.binding.eval('::Module.nesting')
136
+ module_nesting.find { |mod| mod.const_defined?(name, false) } || module_nesting.find { |mod| mod.const_defined?(name) } || Object
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ module IRB
4
+ class Statement
5
+ attr_reader :code
6
+
7
+ def is_assignment?
8
+ raise NotImplementedError
9
+ end
10
+
11
+ def suppresses_echo?
12
+ raise NotImplementedError
13
+ end
14
+
15
+ def should_be_handled_by_debugger?
16
+ raise NotImplementedError
17
+ end
18
+
19
+ class EmptyInput < Statement
20
+ def is_assignment?
21
+ false
22
+ end
23
+
24
+ def suppresses_echo?
25
+ true
26
+ end
27
+
28
+ # Debugger takes empty input to repeat the last command
29
+ def should_be_handled_by_debugger?
30
+ true
31
+ end
32
+
33
+ def code
34
+ ""
35
+ end
36
+ end
37
+
38
+ class Expression < Statement
39
+ def initialize(code, is_assignment)
40
+ @code = code
41
+ @is_assignment = is_assignment
42
+ end
43
+
44
+ def suppresses_echo?
45
+ @code.match?(/;\s*\z/)
46
+ end
47
+
48
+ def should_be_handled_by_debugger?
49
+ true
50
+ end
51
+
52
+ def is_assignment?
53
+ @is_assignment
54
+ end
55
+ end
56
+
57
+ class Command < Statement
58
+ attr_reader :command_class, :arg
59
+
60
+ def initialize(original_code, command_class, arg)
61
+ @code = original_code
62
+ @command_class = command_class
63
+ @arg = arg
64
+ end
65
+
66
+ def is_assignment?
67
+ false
68
+ end
69
+
70
+ def suppresses_echo?
71
+ false
72
+ end
73
+
74
+ def should_be_handled_by_debugger?
75
+ require_relative 'command/debug'
76
+ IRB::Command::DebugCommand > @command_class
77
+ end
78
+ end
79
+ end
80
+ end
data/lib/irb/version.rb CHANGED
@@ -1,11 +1,11 @@
1
- # frozen_string_literal: false
1
+ # frozen_string_literal: true
2
2
  #
3
3
  # irb/version.rb - irb version definition file
4
4
  # by Keiju ISHITSUKA(keiju@ishitsuka.com)
5
5
  #
6
6
 
7
7
  module IRB # :nodoc:
8
- VERSION = "1.7.1"
8
+ VERSION = "1.13.2"
9
9
  @RELEASE_VERSION = VERSION
10
- @LAST_UPDATE_DATE = "2023-07-01"
10
+ @LAST_UPDATE_DATE = "2024-06-15"
11
11
  end
data/lib/irb/workspace.rb CHANGED
@@ -1,4 +1,4 @@
1
- # frozen_string_literal: false
1
+ # frozen_string_literal: true
2
2
  #
3
3
  # irb/workspace-binding.rb -
4
4
  # by Keiju ISHITSUKA(keiju@ruby-lang.org)
@@ -6,6 +6,8 @@
6
6
 
7
7
  require "delegate"
8
8
 
9
+ require_relative "helper_method"
10
+
9
11
  IRB::TOPLEVEL_BINDING = binding
10
12
  module IRB # :nodoc:
11
13
  class WorkSpace
@@ -90,11 +92,11 @@ EOF
90
92
  IRB.conf[:__MAIN__] = @main
91
93
  @main.singleton_class.class_eval do
92
94
  private
93
- define_method(:exit) do |*a, &b|
94
- # Do nothing, will be overridden
95
- end
96
95
  define_method(:binding, Kernel.instance_method(:binding))
97
96
  define_method(:local_variables, Kernel.instance_method(:local_variables))
97
+ # Define empty method to avoid delegator warning, will be overridden.
98
+ define_method(:exit) {|*a, &b| }
99
+ define_method(:exit!) {|*a, &b| }
98
100
  end
99
101
  @binding = eval("IRB.conf[:__MAIN__].instance_eval('binding', __FILE__, __LINE__)", @binding, *@binding.source_location)
100
102
  end
@@ -108,6 +110,12 @@ EOF
108
110
  # <code>IRB.conf[:__MAIN__]</code>
109
111
  attr_reader :main
110
112
 
113
+ def load_helper_methods_to_main
114
+ ancestors = class<<main;ancestors;end
115
+ main.extend ExtendCommandBundle if !ancestors.include?(ExtendCommandBundle)
116
+ main.extend HelpersContainer if !ancestors.include?(HelpersContainer)
117
+ end
118
+
111
119
  # Evaluate the given +statements+ within the context of this workspace.
112
120
  def evaluate(statements, file = __FILE__, line = __LINE__)
113
121
  eval(statements, @binding, file, line)
@@ -166,4 +174,16 @@ EOF
166
174
  "\nFrom: #{file} @ line #{pos + 1} :\n\n#{body}#{Color.clear}\n"
167
175
  end
168
176
  end
177
+
178
+ module HelpersContainer
179
+ def self.install_helper_methods
180
+ HelperMethod.helper_methods.each do |name, helper_method_class|
181
+ define_method name do |*args, **opts, &block|
182
+ helper_method_class.instance.execute(*args, **opts, &block)
183
+ end unless method_defined?(name)
184
+ end
185
+ end
186
+
187
+ install_helper_methods
188
+ end
169
189
  end
@@ -1,4 +1,4 @@
1
- # frozen_string_literal: false
1
+ # frozen_string_literal: true
2
2
  #
3
3
  # irb/ws-for-case-2.rb -
4
4
  # by Keiju ISHITSUKA(keiju@ruby-lang.org)
data/lib/irb/xmp.rb CHANGED
@@ -1,4 +1,4 @@
1
- # frozen_string_literal: false
1
+ # frozen_string_literal: true
2
2
  #
3
3
  # xmp.rb - irb version of gotoken xmp
4
4
  # by Keiju ISHITSUKA(Nippon Rational Inc.)
@@ -44,8 +44,8 @@ class XMP
44
44
  # The top-level binding or, optional +bind+ parameter will be used when
45
45
  # creating the workspace. See WorkSpace.new for more information.
46
46
  #
47
- # This uses the +:XMP+ prompt mode, see IRB@Customizing+the+IRB+Prompt for
48
- # full detail.
47
+ # This uses the +:XMP+ prompt mode.
48
+ # See {Custom Prompts}[rdoc-ref:IRB@Custom+Prompts] for more information.
49
49
  def initialize(bind = nil)
50
50
  IRB.init_config(nil)
51
51