irb 1.7.1 → 1.13.2

Sign up to get free protection for your applications and to get access to all the features.
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