irb 1.9.1 → 1.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +4 -4
- data/README.md +10 -9
- data/Rakefile +2 -2
- data/lib/irb/cmd/history.rb +47 -0
- data/lib/irb/cmd/show_cmds.rb +6 -0
- data/lib/irb/cmd/show_source.rb +9 -2
- data/lib/irb/completion.rb +21 -0
- data/lib/irb/context.rb +22 -14
- data/lib/irb/debug.rb +18 -0
- data/lib/irb/extend-command.rb +6 -0
- data/lib/irb/history.rb +1 -1
- data/lib/irb/init.rb +3 -4
- data/lib/irb/lc/help-message +1 -0
- data/lib/irb/pager.rb +12 -11
- data/lib/irb/source_finder.rb +26 -6
- data/lib/irb/version.rb +2 -2
- data/lib/irb.rb +48 -40
- metadata +3 -7
- data/lib/irb/type_completion/completor.rb +0 -235
- data/lib/irb/type_completion/methods.rb +0 -13
- data/lib/irb/type_completion/scope.rb +0 -412
- data/lib/irb/type_completion/type_analyzer.rb +0 -1169
- data/lib/irb/type_completion/types.rb +0 -426
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c0e7153fbd64c519a7af411d95779821c279a63b786c16df0e5cff4b577a258f
|
4
|
+
data.tar.gz: 86c81569fa9788676c575f64b1010191690b4b3c056330e5f21fb798d724924f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e78e35a1a46ac5b4e62e93f7cac0e1b3657b16cd108851624b3cfd2b6c81662ca6dfa7aff9737d743a625eaa96a47179c95e9af28833dcb9d761ee150923497d
|
7
|
+
data.tar.gz: 562c5e88c5c09adbe4f882d30a34b496599af4f7a45f41d60609ef91148d7271cd97bbfd629ca75da4f3845d7815e51bca3b1969e9bff1c723c18b3c0840517d
|
data/Gemfile
CHANGED
@@ -16,9 +16,9 @@ gem "reline", github: "ruby/reline" if ENV["WITH_LATEST_RELINE"] == "true"
|
|
16
16
|
gem "rake"
|
17
17
|
gem "test-unit"
|
18
18
|
gem "test-unit-ruby-core"
|
19
|
-
gem "debug", github: "ruby/debug"
|
20
19
|
|
21
|
-
|
22
|
-
|
23
|
-
|
20
|
+
gem "debug", github: "ruby/debug", platforms: [:mri, :mswin]
|
21
|
+
|
22
|
+
if RUBY_VERSION >= "3.0.0" && !is_truffleruby
|
23
|
+
gem "repl_type_completor"
|
24
24
|
end
|
data/README.md
CHANGED
@@ -119,6 +119,7 @@ IRB
|
|
119
119
|
source Loads a given file in the current session.
|
120
120
|
irb_info Show information about IRB.
|
121
121
|
show_cmds List all available commands and their description.
|
122
|
+
history Shows the input history. `-g [query]` or `-G [query]` allows you to filter the output.
|
122
123
|
|
123
124
|
Multi-irb (DEPRECATED)
|
124
125
|
irb Start a child IRB.
|
@@ -237,11 +238,11 @@ However, there are also some limitations to be aware of:
|
|
237
238
|
|
238
239
|
## Type Based Completion
|
239
240
|
|
240
|
-
IRB's default completion `IRB::RegexpCompletor` uses Regexp. IRB has another experimental completion `IRB::
|
241
|
+
IRB's default completion `IRB::RegexpCompletor` uses Regexp. IRB has another experimental completion `IRB::TypeCompletor` that uses type analysis.
|
241
242
|
|
242
|
-
### How to Enable IRB::
|
243
|
+
### How to Enable IRB::TypeCompletor
|
243
244
|
|
244
|
-
To enable IRB::
|
245
|
+
To enable IRB::TypeCompletor, run IRB with `--type-completor` option
|
245
246
|
```
|
246
247
|
$ irb --type-completor
|
247
248
|
```
|
@@ -249,14 +250,14 @@ Or write the code below to IRB's rc-file.
|
|
249
250
|
```ruby
|
250
251
|
IRB.conf[:COMPLETOR] = :type # default is :regexp
|
251
252
|
```
|
252
|
-
You also need `gem
|
253
|
+
You also need `gem repl_type_completor` to use this feature.
|
253
254
|
|
254
255
|
To check if it's enabled, type `irb_info` into IRB and see the `Completion` section.
|
255
256
|
```
|
256
257
|
irb(main):001> irb_info
|
257
258
|
...
|
258
259
|
# Enabled
|
259
|
-
Completion: Autocomplete,
|
260
|
+
Completion: Autocomplete, ReplTypeCompletor: 0.1.0, Prism: 0.18.0, RBS: 3.3.0
|
260
261
|
# Not enabled
|
261
262
|
Completion: Autocomplete, RegexpCompletor
|
262
263
|
...
|
@@ -265,7 +266,7 @@ If you have `sig/` directory or `rbs_collection.lock.yaml` in current directory,
|
|
265
266
|
|
266
267
|
### Advantage over Default IRB::RegexpCompletor
|
267
268
|
|
268
|
-
IRB::
|
269
|
+
IRB::TypeCompletor can autocomplete chained methods, block parameters and more if type information is available.
|
269
270
|
These are some examples IRB::RegexpCompletor cannot complete.
|
270
271
|
|
271
272
|
```ruby
|
@@ -287,11 +288,11 @@ As a trade-off, completion calculation takes more time than IRB::RegexpCompletor
|
|
287
288
|
|
288
289
|
### Difference between Steep's Completion
|
289
290
|
|
290
|
-
Compared with Steep, IRB::
|
291
|
+
Compared with Steep, IRB::TypeCompletor has some difference and limitations.
|
291
292
|
```ruby
|
292
293
|
[0, 'a'].sample.
|
293
294
|
# Steep completes intersection of Integer methods and String methods
|
294
|
-
# IRB::
|
295
|
+
# IRB::TypeCompletor completes both Integer and String methods
|
295
296
|
```
|
296
297
|
|
297
298
|
Some features like type narrowing is not implemented.
|
@@ -301,7 +302,7 @@ def f(arg = [0, 'a'].sample)
|
|
301
302
|
arg. # Completes both Integer and String methods
|
302
303
|
```
|
303
304
|
|
304
|
-
Unlike other static type checker, IRB::
|
305
|
+
Unlike other static type checker, IRB::TypeCompletor uses runtime information to provide better completion.
|
305
306
|
```ruby
|
306
307
|
irb(main):001> a = [1]
|
307
308
|
=> [1]
|
data/Rakefile
CHANGED
@@ -5,7 +5,7 @@ Rake::TestTask.new(:test) do |t|
|
|
5
5
|
t.libs << "test" << "test/lib"
|
6
6
|
t.libs << "lib"
|
7
7
|
t.ruby_opts << "-rhelper"
|
8
|
-
t.test_files = FileList["test/irb
|
8
|
+
t.test_files = FileList["test/irb/**/test_*.rb"]
|
9
9
|
end
|
10
10
|
|
11
11
|
# To make sure they have been correctly setup for Ruby CI.
|
@@ -13,7 +13,7 @@ desc "Run each irb test file in isolation."
|
|
13
13
|
task :test_in_isolation do
|
14
14
|
failed = false
|
15
15
|
|
16
|
-
FileList["test/irb
|
16
|
+
FileList["test/irb/**/test_*.rb"].each do |test_file|
|
17
17
|
ENV["TEST"] = test_file
|
18
18
|
begin
|
19
19
|
Rake::Task["test"].execute
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "stringio"
|
4
|
+
require_relative "nop"
|
5
|
+
require_relative "../pager"
|
6
|
+
|
7
|
+
module IRB
|
8
|
+
# :stopdoc:
|
9
|
+
|
10
|
+
module ExtendCommand
|
11
|
+
class History < Nop
|
12
|
+
category "IRB"
|
13
|
+
description "Shows the input history. `-g [query]` or `-G [query]` allows you to filter the output."
|
14
|
+
|
15
|
+
def self.transform_args(args)
|
16
|
+
match = args&.match(/(-g|-G)\s+(?<grep>.+)\s*\n\z/)
|
17
|
+
return unless match
|
18
|
+
|
19
|
+
"grep: #{Regexp.new(match[:grep]).inspect}"
|
20
|
+
end
|
21
|
+
|
22
|
+
def execute(grep: nil)
|
23
|
+
formatted_inputs = irb_context.io.class::HISTORY.each_with_index.reverse_each.filter_map do |input, index|
|
24
|
+
next if grep && !input.match?(grep)
|
25
|
+
|
26
|
+
header = "#{index}: "
|
27
|
+
|
28
|
+
first_line, *other_lines = input.split("\n")
|
29
|
+
first_line = "#{header}#{first_line}"
|
30
|
+
|
31
|
+
truncated_lines = other_lines.slice!(1..) # Show 1 additional line (2 total)
|
32
|
+
other_lines << "..." if truncated_lines&.any?
|
33
|
+
|
34
|
+
other_lines.map! do |line|
|
35
|
+
" " * header.length + line
|
36
|
+
end
|
37
|
+
|
38
|
+
[first_line, *other_lines].join("\n") + "\n"
|
39
|
+
end
|
40
|
+
|
41
|
+
Pager.page_content(formatted_inputs.join)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# :startdoc:
|
47
|
+
end
|
data/lib/irb/cmd/show_cmds.rb
CHANGED
@@ -16,6 +16,12 @@ module IRB
|
|
16
16
|
commands_info = IRB::ExtendCommandBundle.all_commands_info
|
17
17
|
commands_grouped_by_categories = commands_info.group_by { |cmd| cmd[:category] }
|
18
18
|
|
19
|
+
user_aliases = irb_context.instance_variable_get(:@user_aliases)
|
20
|
+
|
21
|
+
commands_grouped_by_categories["Aliases"] = user_aliases.map do |alias_name, target|
|
22
|
+
{ display_name: alias_name, description: "Alias for `#{target}`" }
|
23
|
+
end
|
24
|
+
|
19
25
|
if irb_context.with_debugger
|
20
26
|
# Remove the original "Debugging" category
|
21
27
|
commands_grouped_by_categories.delete("Debugging")
|
data/lib/irb/cmd/show_source.rb
CHANGED
@@ -27,11 +27,18 @@ module IRB
|
|
27
27
|
puts "Error: Expected a string but got #{str.inspect}"
|
28
28
|
return
|
29
29
|
end
|
30
|
-
|
31
|
-
|
30
|
+
if str.include? " -s"
|
31
|
+
str, esses = str.split(" -")
|
32
|
+
s_count = esses.count("^s").zero? ? esses.size : 1
|
33
|
+
source = SourceFinder.new(@irb_context).find_source(str, s_count)
|
34
|
+
else
|
35
|
+
source = SourceFinder.new(@irb_context).find_source(str)
|
36
|
+
end
|
32
37
|
|
33
38
|
if source
|
34
39
|
show_source(source)
|
40
|
+
elsif s_count
|
41
|
+
puts "Error: Couldn't locate a super definition for #{str}"
|
35
42
|
else
|
36
43
|
puts "Error: Couldn't locate a definition for #{str}"
|
37
44
|
end
|
data/lib/irb/completion.rb
CHANGED
@@ -93,6 +93,27 @@ module IRB
|
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
96
|
+
class TypeCompletor < BaseCompletor # :nodoc:
|
97
|
+
def initialize(context)
|
98
|
+
@context = context
|
99
|
+
end
|
100
|
+
|
101
|
+
def inspect
|
102
|
+
ReplTypeCompletor.info
|
103
|
+
end
|
104
|
+
|
105
|
+
def completion_candidates(preposing, target, _postposing, bind:)
|
106
|
+
result = ReplTypeCompletor.analyze(preposing + target, binding: bind, filename: @context.irb_path)
|
107
|
+
return [] unless result
|
108
|
+
result.completion_candidates.map { target + _1 }
|
109
|
+
end
|
110
|
+
|
111
|
+
def doc_namespace(preposing, matched, _postposing, bind:)
|
112
|
+
result = ReplTypeCompletor.analyze(preposing + matched, binding: bind, filename: @context.irb_path)
|
113
|
+
result&.doc_namespace('')
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
96
117
|
class RegexpCompletor < BaseCompletor # :nodoc:
|
97
118
|
using Module.new {
|
98
119
|
refine ::Binding do
|
data/lib/irb/context.rb
CHANGED
@@ -146,9 +146,21 @@ module IRB
|
|
146
146
|
@newline_before_multiline_output = true
|
147
147
|
end
|
148
148
|
|
149
|
-
@
|
149
|
+
@user_aliases = IRB.conf[:COMMAND_ALIASES].dup
|
150
|
+
@command_aliases = @user_aliases.merge(KEYWORD_ALIASES)
|
150
151
|
end
|
151
152
|
|
153
|
+
# because all input will eventually be evaluated as Ruby code,
|
154
|
+
# command names that conflict with Ruby keywords need special workaround
|
155
|
+
# we can remove them once we implemented a better command system for IRB
|
156
|
+
KEYWORD_ALIASES = {
|
157
|
+
:break => :irb_break,
|
158
|
+
:catch => :irb_catch,
|
159
|
+
:next => :irb_next,
|
160
|
+
}.freeze
|
161
|
+
|
162
|
+
private_constant :KEYWORD_ALIASES
|
163
|
+
|
152
164
|
private def build_completor
|
153
165
|
completor_type = IRB.conf[:COMPLETOR]
|
154
166
|
case completor_type
|
@@ -164,26 +176,22 @@ module IRB
|
|
164
176
|
RegexpCompletor.new
|
165
177
|
end
|
166
178
|
|
167
|
-
TYPE_COMPLETION_REQUIRED_PRISM_VERSION = '0.17.1'
|
168
|
-
|
169
179
|
private def build_type_completor
|
170
|
-
|
171
|
-
|
180
|
+
if RUBY_ENGINE == 'truffleruby'
|
181
|
+
# Avoid SynatxError. truffleruby does not support endless method definition yet.
|
182
|
+
warn 'TypeCompletor is not supported on TruffleRuby yet'
|
172
183
|
return
|
173
184
|
end
|
185
|
+
|
174
186
|
begin
|
175
|
-
require '
|
187
|
+
require 'repl_type_completor'
|
176
188
|
rescue LoadError => e
|
177
|
-
warn "
|
189
|
+
warn "TypeCompletor requires `gem repl_type_completor`: #{e.message}"
|
178
190
|
return
|
179
191
|
end
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
end
|
184
|
-
require 'irb/type_completion/completor'
|
185
|
-
TypeCompletion::Types.preload_in_thread
|
186
|
-
TypeCompletion::Completor.new
|
192
|
+
|
193
|
+
ReplTypeCompletor.preload_rbs
|
194
|
+
TypeCompletor.new(self)
|
187
195
|
end
|
188
196
|
|
189
197
|
def save_history=(val)
|
data/lib/irb/debug.rb
CHANGED
@@ -57,6 +57,24 @@ module IRB
|
|
57
57
|
DEBUGGER__::ThreadClient.prepend(SkipPathHelperForIRB)
|
58
58
|
end
|
59
59
|
|
60
|
+
if !@output_modifier_defined && !DEBUGGER__::CONFIG[:no_hint]
|
61
|
+
irb_output_modifier_proc = Reline.output_modifier_proc
|
62
|
+
|
63
|
+
Reline.output_modifier_proc = proc do |output, complete:|
|
64
|
+
unless output.strip.empty?
|
65
|
+
cmd = output.split(/\s/, 2).first
|
66
|
+
|
67
|
+
if !complete && DEBUGGER__.commands.key?(cmd)
|
68
|
+
output = output.sub(/\n$/, " # debug command\n")
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
irb_output_modifier_proc.call(output, complete: complete)
|
73
|
+
end
|
74
|
+
|
75
|
+
@output_modifier_defined = true
|
76
|
+
end
|
77
|
+
|
60
78
|
true
|
61
79
|
end
|
62
80
|
|
data/lib/irb/extend-command.rb
CHANGED
data/lib/irb/history.rb
CHANGED
@@ -60,7 +60,7 @@ module IRB
|
|
60
60
|
end
|
61
61
|
|
62
62
|
File.open(history_file, (append_history ? 'a' : 'w'), 0o600, encoding: IRB.conf[:LC_MESSAGES]&.encoding) do |f|
|
63
|
-
hist = history.map{ |l| l.split("\n").join("\\\n") }
|
63
|
+
hist = history.map{ |l| l.scrub.split("\n").join("\\\n") }
|
64
64
|
unless append_history
|
65
65
|
begin
|
66
66
|
hist = hist.last(num) if hist.size > num and num > 0
|
data/lib/irb/init.rb
CHANGED
@@ -82,6 +82,7 @@ module IRB # :nodoc:
|
|
82
82
|
@CONF[:USE_LOADER] = false
|
83
83
|
@CONF[:IGNORE_SIGINT] = true
|
84
84
|
@CONF[:IGNORE_EOF] = false
|
85
|
+
@CONF[:USE_PAGER] = true
|
85
86
|
@CONF[:EXTRA_DOC_DIRS] = []
|
86
87
|
@CONF[:ECHO] = nil
|
87
88
|
@CONF[:ECHO_ON_ASSIGNMENT] = nil
|
@@ -188,10 +189,6 @@ module IRB # :nodoc:
|
|
188
189
|
# Symbol aliases
|
189
190
|
:'$' => :show_source,
|
190
191
|
:'@' => :whereami,
|
191
|
-
# Keyword aliases
|
192
|
-
:break => :irb_break,
|
193
|
-
:catch => :irb_catch,
|
194
|
-
:next => :irb_next,
|
195
192
|
}
|
196
193
|
end
|
197
194
|
|
@@ -285,6 +282,8 @@ module IRB # :nodoc:
|
|
285
282
|
end
|
286
283
|
when "--noinspect"
|
287
284
|
@CONF[:INSPECT_MODE] = false
|
285
|
+
when "--no-pager"
|
286
|
+
@CONF[:USE_PAGER] = false
|
288
287
|
when "--singleline", "--readline", "--legacy"
|
289
288
|
@CONF[:USE_SINGLELINE] = true
|
290
289
|
when "--nosingleline", "--noreadline"
|
data/lib/irb/lc/help-message
CHANGED
@@ -22,6 +22,7 @@ Usage: irb.rb [options] [programfile] [arguments]
|
|
22
22
|
Show truncated result on assignment (default).
|
23
23
|
--inspect Use 'inspect' for output.
|
24
24
|
--noinspect Don't use 'inspect' for output.
|
25
|
+
--no-pager Don't use pager.
|
25
26
|
--multiline Use multiline editor module (default).
|
26
27
|
--nomultiline Don't use multiline editor module.
|
27
28
|
--singleline Use single line editor module.
|
data/lib/irb/pager.rb
CHANGED
@@ -7,9 +7,9 @@ module IRB
|
|
7
7
|
PAGE_COMMANDS = [ENV['RI_PAGER'], ENV['PAGER'], 'less', 'more'].compact.uniq
|
8
8
|
|
9
9
|
class << self
|
10
|
-
def page_content(content)
|
10
|
+
def page_content(content, **options)
|
11
11
|
if content_exceeds_screen_height?(content)
|
12
|
-
page do |io|
|
12
|
+
page(**options) do |io|
|
13
13
|
io.puts content
|
14
14
|
end
|
15
15
|
else
|
@@ -17,8 +17,8 @@ module IRB
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
def page
|
21
|
-
if STDIN.tty? && pager = setup_pager
|
20
|
+
def page(retain_content: false)
|
21
|
+
if IRB.conf[:USE_PAGER] && STDIN.tty? && pager = setup_pager(retain_content: retain_content)
|
22
22
|
begin
|
23
23
|
pid = pager.pid
|
24
24
|
yield pager
|
@@ -55,19 +55,20 @@ module IRB
|
|
55
55
|
pageable_height * screen_width < Reline::Unicode.calculate_width(content, true)
|
56
56
|
end
|
57
57
|
|
58
|
-
def setup_pager
|
58
|
+
def setup_pager(retain_content:)
|
59
59
|
require 'shellwords'
|
60
60
|
|
61
|
-
PAGE_COMMANDS.each do |
|
62
|
-
|
63
|
-
next if
|
61
|
+
PAGE_COMMANDS.each do |pager_cmd|
|
62
|
+
cmd = Shellwords.split(pager_cmd)
|
63
|
+
next if cmd.empty?
|
64
64
|
|
65
|
-
if
|
66
|
-
|
65
|
+
if cmd.first == 'less'
|
66
|
+
cmd << '-R' unless cmd.include?('-R')
|
67
|
+
cmd << '-X' if retain_content && !cmd.include?('-X')
|
67
68
|
end
|
68
69
|
|
69
70
|
begin
|
70
|
-
io = IO.popen(
|
71
|
+
io = IO.popen(cmd, 'w')
|
71
72
|
rescue
|
72
73
|
next
|
73
74
|
end
|
data/lib/irb/source_finder.rb
CHANGED
@@ -16,7 +16,7 @@ module IRB
|
|
16
16
|
@irb_context = irb_context
|
17
17
|
end
|
18
18
|
|
19
|
-
def find_source(signature)
|
19
|
+
def find_source(signature, s_count = nil)
|
20
20
|
context_binding = @irb_context.workspace.binding
|
21
21
|
case signature
|
22
22
|
when /\A[A-Z]\w*(::[A-Z]\w*)*\z/ # Const::Name
|
@@ -26,14 +26,13 @@ module IRB
|
|
26
26
|
when /\A(?<owner>[A-Z]\w*(::[A-Z]\w*)*)#(?<method>[^ :.]+)\z/ # Class#method
|
27
27
|
owner = eval(Regexp.last_match[:owner], context_binding)
|
28
28
|
method = Regexp.last_match[:method]
|
29
|
-
|
30
|
-
|
31
|
-
file, line = owner.instance_method(method).source_location if methods.include?(method.to_sym)
|
32
|
-
end
|
29
|
+
return unless owner.respond_to?(:instance_method)
|
30
|
+
file, line = method_target(owner, s_count, method, "owner")
|
33
31
|
when /\A((?<receiver>.+)(\.|::))?(?<method>[^ :.]+)\z/ # method, receiver.method, receiver::method
|
34
32
|
receiver = eval(Regexp.last_match[:receiver] || 'self', context_binding)
|
35
33
|
method = Regexp.last_match[:method]
|
36
|
-
|
34
|
+
return unless receiver.respond_to?(method, true)
|
35
|
+
file, line = method_target(receiver, s_count, method, "receiver")
|
37
36
|
end
|
38
37
|
if file && line && File.exist?(file)
|
39
38
|
Source.new(file: file, first_line: line, last_line: find_end(file, line))
|
@@ -60,5 +59,26 @@ module IRB
|
|
60
59
|
end
|
61
60
|
first_line
|
62
61
|
end
|
62
|
+
|
63
|
+
def method_target(owner_receiver, s_count, method, type)
|
64
|
+
case type
|
65
|
+
when "owner"
|
66
|
+
target_method = owner_receiver.instance_method(method)
|
67
|
+
return target_method.source_location unless s_count
|
68
|
+
when "receiver"
|
69
|
+
if s_count
|
70
|
+
target_method = owner_receiver.class.instance_method(method)
|
71
|
+
else
|
72
|
+
target_method = method
|
73
|
+
return owner_receiver.method(method).source_location
|
74
|
+
end
|
75
|
+
end
|
76
|
+
s_count.times do |s|
|
77
|
+
target_method = target_method.super_method if target_method
|
78
|
+
end
|
79
|
+
target_method.nil? ? nil : target_method.source_location
|
80
|
+
rescue NameError
|
81
|
+
nil
|
82
|
+
end
|
63
83
|
end
|
64
84
|
end
|
data/lib/irb/version.rb
CHANGED
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
|
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
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
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
|
-
|
723
|
-
message =
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
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
|
-
|
740
|
-
|
741
|
-
}
|
742
|
-
|
743
|
-
|
744
|
-
|
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
|
-
|
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
|
-
|
935
|
+
main_str = @context.main.to_s rescue "!#{$!.class}"
|
936
|
+
truncate_prompt_main(main_str)
|
930
937
|
when "M"
|
931
|
-
|
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.
|
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-
|
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
|