irb 1.9.0 → 1.10.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.
data/lib/irb.rb CHANGED
@@ -20,6 +20,7 @@ require_relative "irb/color"
20
20
  require_relative "irb/version"
21
21
  require_relative "irb/easter-egg"
22
22
  require_relative "irb/debug"
23
+ require_relative "irb/pager"
23
24
 
24
25
  # IRB stands for "interactive Ruby" and is a tool to interactively execute Ruby
25
26
  # expressions read from the standard input.
@@ -697,7 +698,7 @@ module IRB
697
698
  end
698
699
 
699
700
  def handle_exception(exc)
700
- if exc.backtrace && exc.backtrace[0] =~ /\/irb(2)?(\/.*|-.*|\.rb)?:/ && exc.class.to_s !~ /^IRB/ &&
701
+ if exc.backtrace[0] =~ /\/irb(2)?(\/.*|-.*|\.rb)?:/ && exc.class.to_s !~ /^IRB/ &&
701
702
  !(SyntaxError === exc) && !(EncodingError === exc)
702
703
  # The backtrace of invalid encoding hash (ex. {"\xAE": 1}) raises EncodingError without lineno.
703
704
  irb_bug = true
@@ -705,45 +706,49 @@ module IRB
705
706
  irb_bug = false
706
707
  end
707
708
 
708
- if exc.backtrace
709
- order = nil
710
- if RUBY_VERSION < '3.0.0'
711
- if STDOUT.tty?
712
- message = exc.full_message(order: :bottom)
713
- order = :bottom
714
- else
715
- message = exc.full_message(order: :top)
716
- order = :top
717
- end
718
- else # '3.0.0' <= RUBY_VERSION
709
+ if RUBY_VERSION < '3.0.0'
710
+ if STDOUT.tty?
711
+ message = exc.full_message(order: :bottom)
712
+ order = :bottom
713
+ else
719
714
  message = exc.full_message(order: :top)
720
715
  order = :top
721
716
  end
722
- message = convert_invalid_byte_sequence(message, exc.message.encoding)
723
- message = encode_with_invalid_byte_sequence(message, IRB.conf[:LC_MESSAGES].encoding) unless message.encoding.to_s.casecmp?(IRB.conf[:LC_MESSAGES].encoding.to_s)
724
- message = message.gsub(/((?:^\t.+$\n)+)/) { |m|
725
- case order
726
- when :top
727
- lines = m.split("\n")
728
- when :bottom
729
- lines = m.split("\n").reverse
730
- end
731
- unless irb_bug
732
- lines = lines.map { |l| @context.workspace.filter_backtrace(l) }.compact
733
- if lines.size > @context.back_trace_limit
734
- omit = lines.size - @context.back_trace_limit
735
- lines = lines[0..(@context.back_trace_limit - 1)]
736
- lines << "\t... %d levels..." % omit
737
- end
717
+ else # '3.0.0' <= RUBY_VERSION
718
+ message = exc.full_message(order: :top)
719
+ order = :top
720
+ end
721
+ message = convert_invalid_byte_sequence(message, exc.message.encoding)
722
+ message = encode_with_invalid_byte_sequence(message, IRB.conf[:LC_MESSAGES].encoding) unless message.encoding.to_s.casecmp?(IRB.conf[:LC_MESSAGES].encoding.to_s)
723
+ message = message.gsub(/((?:^\t.+$\n)+)/) { |m|
724
+ case order
725
+ when :top
726
+ lines = m.split("\n")
727
+ when :bottom
728
+ lines = m.split("\n").reverse
729
+ end
730
+ unless irb_bug
731
+ lines = lines.map { |l| @context.workspace.filter_backtrace(l) }.compact
732
+ if lines.size > @context.back_trace_limit
733
+ omit = lines.size - @context.back_trace_limit
734
+ lines = lines[0..(@context.back_trace_limit - 1)]
735
+ lines << "\t... %d levels..." % omit
738
736
  end
739
- lines = lines.reverse if order == :bottom
740
- lines.map{ |l| l + "\n" }.join
741
- }
742
- # The "<top (required)>" in "(irb)" may be the top level of IRB so imitate the main object.
743
- message = message.gsub(/\(irb\):(?<num>\d+):in `<(?<frame>top \(required\))>'/) { "(irb):#{$~[:num]}:in `<main>'" }
744
- puts message
737
+ end
738
+ lines = lines.reverse if order == :bottom
739
+ lines.map{ |l| l + "\n" }.join
740
+ }
741
+ # The "<top (required)>" in "(irb)" may be the top level of IRB so imitate the main object.
742
+ message = message.gsub(/\(irb\):(?<num>\d+):in `<(?<frame>top \(required\))>'/) { "(irb):#{$~[:num]}:in `<main>'" }
743
+ puts message
744
+ puts 'Maybe IRB bug!' if irb_bug
745
+ rescue Exception => handler_exc
746
+ begin
747
+ puts exc.inspect
748
+ puts "backtraces are hidden because #{handler_exc} was raised when processing them"
749
+ rescue Exception
750
+ puts 'Uninspectable exception occurred'
745
751
  end
746
- print "Maybe IRB bug!\n" if irb_bug
747
752
  end
748
753
 
749
754
  # Evaluates the given block using the given +path+ as the Context#irb_path
@@ -855,11 +860,12 @@ module IRB
855
860
  end
856
861
  end
857
862
  end
863
+
858
864
  if multiline_p && @context.newline_before_multiline_output?
859
- printf @context.return_format, "\n#{str}"
860
- else
861
- printf @context.return_format, str
865
+ str = "\n" + str
862
866
  end
867
+
868
+ Pager.page_content(format(@context.return_format, str), retain_content: true)
863
869
  end
864
870
 
865
871
  # Outputs the local variables to this current session, including
@@ -926,9 +932,11 @@ module IRB
926
932
  when "N"
927
933
  @context.irb_name
928
934
  when "m"
929
- truncate_prompt_main(@context.main.to_s)
935
+ main_str = @context.main.to_s rescue "!#{$!.class}"
936
+ truncate_prompt_main(main_str)
930
937
  when "M"
931
- truncate_prompt_main(@context.main.inspect)
938
+ main_str = @context.main.inspect rescue "!#{$!.class}"
939
+ truncate_prompt_main(main_str)
932
940
  when "l"
933
941
  ltype
934
942
  when "i"
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.9.0
4
+ version: 1.10.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: 2023-11-10 00:00:00.000000000 Z
12
+ date: 2023-12-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: reline
@@ -70,6 +70,7 @@ files:
70
70
  - lib/irb/cmd/edit.rb
71
71
  - lib/irb/cmd/finish.rb
72
72
  - lib/irb/cmd/help.rb
73
+ - lib/irb/cmd/history.rb
73
74
  - lib/irb/cmd/info.rb
74
75
  - lib/irb/cmd/irb_info.rb
75
76
  - lib/irb/cmd/load.rb
@@ -118,11 +119,6 @@ files:
118
119
  - lib/irb/ruby_logo.aa
119
120
  - lib/irb/source_finder.rb
120
121
  - lib/irb/statement.rb
121
- - lib/irb/type_completion/completor.rb
122
- - lib/irb/type_completion/methods.rb
123
- - lib/irb/type_completion/scope.rb
124
- - lib/irb/type_completion/type_analyzer.rb
125
- - lib/irb/type_completion/types.rb
126
122
  - lib/irb/version.rb
127
123
  - lib/irb/workspace.rb
128
124
  - lib/irb/ws-for-case-2.rb
@@ -152,7 +148,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
152
148
  - !ruby/object:Gem::Version
153
149
  version: '0'
154
150
  requirements: []
155
- rubygems_version: 3.5.0.dev
151
+ rubygems_version: 3.4.10
156
152
  signing_key:
157
153
  specification_version: 4
158
154
  summary: Interactive Ruby command-line tool for REPL (Read Eval Print Loop).
@@ -1,235 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'prism'
4
- require 'irb/completion'
5
- require_relative 'type_analyzer'
6
-
7
- module IRB
8
- module TypeCompletion
9
- class Completor < BaseCompletor # :nodoc:
10
- HIDDEN_METHODS = %w[Namespace TypeName] # defined by rbs, should be hidden
11
-
12
- class << self
13
- attr_accessor :last_completion_error
14
- end
15
-
16
- def inspect
17
- name = 'TypeCompletion::Completor'
18
- prism_info = "Prism: #{Prism::VERSION}"
19
- if Types.rbs_builder
20
- "#{name}(#{prism_info}, RBS: #{RBS::VERSION})"
21
- elsif Types.rbs_load_error
22
- "#{name}(#{prism_info}, RBS: #{Types.rbs_load_error.inspect})"
23
- else
24
- "#{name}(#{prism_info}, RBS: loading)"
25
- end
26
- end
27
-
28
- def completion_candidates(preposing, target, _postposing, bind:)
29
- @preposing = preposing
30
- verbose, $VERBOSE = $VERBOSE, nil
31
- code = "#{preposing}#{target}"
32
- @result = analyze code, bind
33
- name, candidates = candidates_from_result(@result)
34
-
35
- all_symbols_pattern = /\A[ -\/:-@\[-`\{-~]*\z/
36
- candidates.map(&:to_s).select { !_1.match?(all_symbols_pattern) && _1.start_with?(name) }.uniq.sort.map do
37
- target + _1[name.size..]
38
- end
39
- rescue SyntaxError, StandardError => e
40
- Completor.last_completion_error = e
41
- handle_error(e)
42
- []
43
- ensure
44
- $VERBOSE = verbose
45
- end
46
-
47
- def doc_namespace(preposing, matched, postposing, bind:)
48
- name = matched[/[a-zA-Z_0-9]*[!?=]?\z/]
49
- method_doc = -> type do
50
- type = type.types.find { _1.all_methods.include? name.to_sym }
51
- case type
52
- when Types::SingletonType
53
- "#{Types.class_name_of(type.module_or_class)}.#{name}"
54
- when Types::InstanceType
55
- "#{Types.class_name_of(type.klass)}##{name}"
56
- end
57
- end
58
- call_or_const_doc = -> type do
59
- if name =~ /\A[A-Z]/
60
- type = type.types.grep(Types::SingletonType).find { _1.module_or_class.const_defined?(name) }
61
- type.module_or_class == Object ? name : "#{Types.class_name_of(type.module_or_class)}::#{name}" if type
62
- else
63
- method_doc.call(type)
64
- end
65
- end
66
-
67
- value_doc = -> type do
68
- return unless type
69
- type.types.each do |t|
70
- case t
71
- when Types::SingletonType
72
- return Types.class_name_of(t.module_or_class)
73
- when Types::InstanceType
74
- return Types.class_name_of(t.klass)
75
- end
76
- end
77
- nil
78
- end
79
-
80
- case @result
81
- in [:call_or_const, type, _name, _self_call]
82
- call_or_const_doc.call type
83
- in [:const, type, _name, scope]
84
- if type
85
- call_or_const_doc.call type
86
- else
87
- value_doc.call scope[name]
88
- end
89
- in [:gvar, _name, scope]
90
- value_doc.call scope["$#{name}"]
91
- in [:ivar, _name, scope]
92
- value_doc.call scope["@#{name}"]
93
- in [:cvar, _name, scope]
94
- value_doc.call scope["@@#{name}"]
95
- in [:call, type, _name, _self_call]
96
- method_doc.call type
97
- in [:lvar_or_method, _name, scope]
98
- if scope.local_variables.include?(name)
99
- value_doc.call scope[name]
100
- else
101
- method_doc.call scope.self_type
102
- end
103
- else
104
- end
105
- end
106
-
107
- def candidates_from_result(result)
108
- candidates = case result
109
- in [:require, name]
110
- retrieve_files_to_require_from_load_path
111
- in [:require_relative, name]
112
- retrieve_files_to_require_relative_from_current_dir
113
- in [:call_or_const, type, name, self_call]
114
- ((self_call ? type.all_methods : type.methods).map(&:to_s) - HIDDEN_METHODS) | type.constants
115
- in [:const, type, name, scope]
116
- if type
117
- scope_constants = type.types.flat_map do |t|
118
- scope.table_module_constants(t.module_or_class) if t.is_a?(Types::SingletonType)
119
- end
120
- (scope_constants.compact | type.constants.map(&:to_s)).sort
121
- else
122
- scope.constants.sort | ReservedWords
123
- end
124
- in [:ivar, name, scope]
125
- ivars = scope.instance_variables.sort
126
- name == '@' ? ivars + scope.class_variables.sort : ivars
127
- in [:cvar, name, scope]
128
- scope.class_variables
129
- in [:gvar, name, scope]
130
- scope.global_variables
131
- in [:symbol, name]
132
- Symbol.all_symbols.map { _1.inspect[1..] }
133
- in [:call, type, name, self_call]
134
- (self_call ? type.all_methods : type.methods).map(&:to_s) - HIDDEN_METHODS
135
- in [:lvar_or_method, name, scope]
136
- scope.self_type.all_methods.map(&:to_s) | scope.local_variables | ReservedWords
137
- else
138
- []
139
- end
140
- [name || '', candidates]
141
- end
142
-
143
- def analyze(code, binding = Object::TOPLEVEL_BINDING)
144
- # Workaround for https://github.com/ruby/prism/issues/1592
145
- return if code.match?(/%[qQ]\z/)
146
-
147
- ast = Prism.parse(code, scopes: [binding.local_variables]).value
148
- name = code[/(@@|@|\$)?\w*[!?=]?\z/]
149
- *parents, target_node = find_target ast, code.bytesize - name.bytesize
150
- return unless target_node
151
-
152
- calculate_scope = -> { TypeAnalyzer.calculate_target_type_scope(binding, parents, target_node).last }
153
- calculate_type_scope = ->(node) { TypeAnalyzer.calculate_target_type_scope binding, [*parents, target_node], node }
154
-
155
- case target_node
156
- when Prism::StringNode, Prism::InterpolatedStringNode
157
- call_node, args_node = parents.last(2)
158
- return unless call_node.is_a?(Prism::CallNode) && call_node.receiver.nil?
159
- return unless args_node.is_a?(Prism::ArgumentsNode) && args_node.arguments.size == 1
160
-
161
- case call_node.name
162
- when :require
163
- [:require, name.rstrip]
164
- when :require_relative
165
- [:require_relative, name.rstrip]
166
- end
167
- when Prism::SymbolNode
168
- if parents.last.is_a? Prism::BlockArgumentNode # method(&:target)
169
- receiver_type, _scope = calculate_type_scope.call target_node
170
- [:call, receiver_type, name, false]
171
- else
172
- [:symbol, name] unless name.empty?
173
- end
174
- when Prism::CallNode
175
- return [:lvar_or_method, name, calculate_scope.call] if target_node.receiver.nil?
176
-
177
- self_call = target_node.receiver.is_a? Prism::SelfNode
178
- op = target_node.call_operator
179
- receiver_type, _scope = calculate_type_scope.call target_node.receiver
180
- receiver_type = receiver_type.nonnillable if op == '&.'
181
- [op == '::' ? :call_or_const : :call, receiver_type, name, self_call]
182
- when Prism::LocalVariableReadNode, Prism::LocalVariableTargetNode
183
- [:lvar_or_method, name, calculate_scope.call]
184
- when Prism::ConstantReadNode, Prism::ConstantTargetNode
185
- if parents.last.is_a? Prism::ConstantPathNode
186
- path_node = parents.last
187
- if path_node.parent # A::B
188
- receiver, scope = calculate_type_scope.call(path_node.parent)
189
- [:const, receiver, name, scope]
190
- else # ::A
191
- scope = calculate_scope.call
192
- [:const, Types::SingletonType.new(Object), name, scope]
193
- end
194
- else
195
- [:const, nil, name, calculate_scope.call]
196
- end
197
- when Prism::GlobalVariableReadNode, Prism::GlobalVariableTargetNode
198
- [:gvar, name, calculate_scope.call]
199
- when Prism::InstanceVariableReadNode, Prism::InstanceVariableTargetNode
200
- [:ivar, name, calculate_scope.call]
201
- when Prism::ClassVariableReadNode, Prism::ClassVariableTargetNode
202
- [:cvar, name, calculate_scope.call]
203
- end
204
- end
205
-
206
- def find_target(node, position)
207
- location = (
208
- case node
209
- when Prism::CallNode
210
- node.message_loc
211
- when Prism::SymbolNode
212
- node.value_loc
213
- when Prism::StringNode
214
- node.content_loc
215
- when Prism::InterpolatedStringNode
216
- node.closing_loc if node.parts.empty?
217
- end
218
- )
219
- return [node] if location&.start_offset == position
220
-
221
- node.compact_child_nodes.each do |n|
222
- match = find_target(n, position)
223
- next unless match
224
- match.unshift node
225
- return match
226
- end
227
-
228
- [node] if node.location.start_offset == position
229
- end
230
-
231
- def handle_error(e)
232
- end
233
- end
234
- end
235
- end
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module IRB
4
- module TypeCompletion
5
- module Methods
6
- OBJECT_SINGLETON_CLASS_METHOD = Object.instance_method(:singleton_class)
7
- OBJECT_INSTANCE_VARIABLES_METHOD = Object.instance_method(:instance_variables)
8
- OBJECT_INSTANCE_VARIABLE_GET_METHOD = Object.instance_method(:instance_variable_get)
9
- OBJECT_CLASS_METHOD = Object.instance_method(:class)
10
- MODULE_NAME_METHOD = Module.instance_method(:name)
11
- end
12
- end
13
- end