irb 1.15.2 → 1.17.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 +4 -4
- data/.rdoc_options +5 -0
- data/CONTRIBUTING.md +52 -0
- data/EXTEND_IRB.md +3 -0
- data/Gemfile +9 -1
- data/doc/COMMAND_LINE_OPTIONS.md +69 -0
- data/doc/COMPARED_WITH_PRY.md +22 -0
- data/doc/Configurations.md +274 -0
- data/doc/EXTEND_IRB.md +122 -0
- data/doc/Index.md +705 -0
- data/doc/irb/irb.rd.ja +1 -1
- data/lib/irb/color.rb +198 -167
- data/lib/irb/command/copy.rb +11 -1
- data/lib/irb/completion.rb +31 -36
- data/lib/irb/context.rb +9 -8
- data/lib/irb/debug.rb +3 -3
- data/lib/irb/easter-egg.rb +3 -1
- data/lib/irb/ext/multi-irb.rb +2 -0
- data/lib/irb/input-method.rb +2 -2
- data/lib/irb/inspector.rb +1 -1
- data/lib/irb/lc/help-message +2 -2
- data/lib/irb/lc/ja/help-message +1 -1
- data/lib/irb/nesting_parser.rb +361 -213
- data/lib/irb/ruby-lex.rb +67 -41
- data/lib/irb/source_finder.rb +7 -4
- data/lib/irb/version.rb +2 -2
- data/lib/irb/workspace.rb +9 -0
- data/lib/irb.rb +61 -28
- metadata +25 -7
- data/Rakefile +0 -52
- data/bin/console +0 -6
- data/bin/setup +0 -6
- data/irb.gemspec +0 -48
data/lib/irb/ruby-lex.rb
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
|
|
5
5
|
#
|
|
6
6
|
|
|
7
|
+
require "prism"
|
|
7
8
|
require "ripper"
|
|
8
9
|
require "jruby" if RUBY_ENGINE == "jruby"
|
|
9
10
|
require_relative "nesting_parser"
|
|
@@ -52,6 +53,27 @@ module IRB
|
|
|
52
53
|
on_words_beg on_qwords_beg
|
|
53
54
|
]
|
|
54
55
|
|
|
56
|
+
RESERVED_WORDS = %i[
|
|
57
|
+
__ENCODING__ __LINE__ __FILE__
|
|
58
|
+
BEGIN END
|
|
59
|
+
alias and
|
|
60
|
+
begin break
|
|
61
|
+
case class
|
|
62
|
+
def defined? do
|
|
63
|
+
else elsif end ensure
|
|
64
|
+
false for
|
|
65
|
+
if in
|
|
66
|
+
module
|
|
67
|
+
next nil not
|
|
68
|
+
or
|
|
69
|
+
redo rescue retry return
|
|
70
|
+
self super
|
|
71
|
+
then true
|
|
72
|
+
undef unless until
|
|
73
|
+
when while
|
|
74
|
+
yield
|
|
75
|
+
]
|
|
76
|
+
|
|
55
77
|
class TerminateLineInput < StandardError
|
|
56
78
|
def initialize
|
|
57
79
|
super("Terminate Line Input")
|
|
@@ -77,6 +99,10 @@ module IRB
|
|
|
77
99
|
end
|
|
78
100
|
|
|
79
101
|
def generate_local_variables_assign_code(local_variables)
|
|
102
|
+
# Some reserved words could be a local variable
|
|
103
|
+
# Example: def f(if: 1); binding.irb; end
|
|
104
|
+
# These reserved words should be removed from assignment code
|
|
105
|
+
local_variables -= RESERVED_WORDS
|
|
80
106
|
"#{local_variables.join('=')}=nil;" unless local_variables.empty?
|
|
81
107
|
end
|
|
82
108
|
|
|
@@ -145,7 +171,7 @@ module IRB
|
|
|
145
171
|
|
|
146
172
|
def check_code_state(code, local_variables:)
|
|
147
173
|
tokens = self.class.ripper_lex_without_warning(code, local_variables: local_variables)
|
|
148
|
-
opens = NestingParser.
|
|
174
|
+
opens = NestingParser.open_nestings(Prism.parse_lex(code, scopes: [local_variables]))
|
|
149
175
|
[tokens, opens, code_terminated?(code, tokens, opens, local_variables: local_variables)]
|
|
150
176
|
end
|
|
151
177
|
|
|
@@ -282,11 +308,11 @@ module IRB
|
|
|
282
308
|
|
|
283
309
|
def calc_indent_level(opens)
|
|
284
310
|
indent_level = 0
|
|
285
|
-
opens.each_with_index do |
|
|
286
|
-
case
|
|
311
|
+
opens.each_with_index do |elem, index|
|
|
312
|
+
case elem.event
|
|
287
313
|
when :on_heredoc_beg
|
|
288
314
|
if opens[index + 1]&.event != :on_heredoc_beg
|
|
289
|
-
if
|
|
315
|
+
if elem.tok.match?(/^<<[~-]/)
|
|
290
316
|
indent_level += 1
|
|
291
317
|
else
|
|
292
318
|
indent_level = 0
|
|
@@ -295,50 +321,50 @@ module IRB
|
|
|
295
321
|
when :on_tstring_beg, :on_regexp_beg, :on_symbeg, :on_backtick
|
|
296
322
|
# No indent: "", //, :"", ``
|
|
297
323
|
# Indent: %(), %r(), %i(), %x()
|
|
298
|
-
indent_level += 1 if
|
|
324
|
+
indent_level += 1 if elem.tok.start_with? '%'
|
|
299
325
|
when :on_embdoc_beg
|
|
300
326
|
indent_level = 0
|
|
301
327
|
else
|
|
302
|
-
indent_level += 1 unless
|
|
328
|
+
indent_level += 1 unless elem.tok == 'alias' || elem.tok == 'undef'
|
|
303
329
|
end
|
|
304
330
|
end
|
|
305
331
|
indent_level
|
|
306
332
|
end
|
|
307
333
|
|
|
308
|
-
|
|
334
|
+
FREE_INDENT_NESTINGS = %i[on_tstring_beg on_backtick on_regexp_beg on_symbeg]
|
|
309
335
|
|
|
310
|
-
def
|
|
311
|
-
|
|
336
|
+
def free_indent_nesting_element?(elem)
|
|
337
|
+
FREE_INDENT_NESTINGS.include?(elem&.event)
|
|
312
338
|
end
|
|
313
339
|
|
|
314
340
|
# Calculates the difference of pasted code's indent and indent calculated from tokens
|
|
315
341
|
def indent_difference(lines, line_results, line_index)
|
|
316
342
|
loop do
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
if !
|
|
343
|
+
prev_opens, _next_opens, min_depth = line_results[line_index]
|
|
344
|
+
open_elem = prev_opens.last
|
|
345
|
+
if !open_elem || (open_elem.event != :on_heredoc_beg && !free_indent_nesting_element?(open_elem))
|
|
320
346
|
# If the leading whitespace is an indent, return the difference
|
|
321
347
|
indent_level = calc_indent_level(prev_opens.take(min_depth))
|
|
322
348
|
calculated_indent = 2 * indent_level
|
|
323
349
|
actual_indent = lines[line_index][/^ */].size
|
|
324
350
|
return actual_indent - calculated_indent
|
|
325
|
-
elsif
|
|
351
|
+
elsif open_elem.event == :on_heredoc_beg && open_elem.tok.match?(/^<<[^-~]/)
|
|
326
352
|
return 0
|
|
327
353
|
end
|
|
328
354
|
# If the leading whitespace is not an indent but part of a multiline token
|
|
329
355
|
# Calculate base_indent of the multiline token's beginning line
|
|
330
|
-
line_index =
|
|
356
|
+
line_index = open_elem.pos[0] - 1
|
|
331
357
|
end
|
|
332
358
|
end
|
|
333
359
|
|
|
334
|
-
def process_indent_level(
|
|
335
|
-
line_results = NestingParser.parse_by_line(
|
|
360
|
+
def process_indent_level(parse_lex_result, lines, line_index, is_newline)
|
|
361
|
+
line_results = NestingParser.parse_by_line(parse_lex_result)
|
|
336
362
|
result = line_results[line_index]
|
|
337
363
|
if result
|
|
338
|
-
|
|
364
|
+
prev_opens, next_opens, min_depth = result
|
|
339
365
|
else
|
|
340
366
|
# When last line is empty
|
|
341
|
-
prev_opens = next_opens = line_results.last[
|
|
367
|
+
prev_opens = next_opens = line_results.last[1]
|
|
342
368
|
min_depth = next_opens.size
|
|
343
369
|
end
|
|
344
370
|
|
|
@@ -348,39 +374,39 @@ module IRB
|
|
|
348
374
|
|
|
349
375
|
preserve_indent = lines[line_index - (is_newline ? 1 : 0)][/^ */].size
|
|
350
376
|
|
|
351
|
-
|
|
352
|
-
|
|
377
|
+
prev_open_elem = prev_opens.last
|
|
378
|
+
next_open_elem = next_opens.last
|
|
353
379
|
|
|
354
|
-
# Calculates base indent for pasted code on the line where
|
|
355
|
-
# irb(main):001:1* if a # base_indent is 2, indent calculated from
|
|
356
|
-
# irb(main):002:1* if b # base_indent is 6, indent calculated from
|
|
357
|
-
# irb(main):003:0> c # base_indent is 6, indent calculated from
|
|
358
|
-
if
|
|
359
|
-
base_indent = [0, indent_difference(lines, line_results,
|
|
380
|
+
# Calculates base indent for pasted code on the line where prev_open_elem is located
|
|
381
|
+
# irb(main):001:1* if a # base_indent is 2, indent calculated from nestings is 0
|
|
382
|
+
# irb(main):002:1* if b # base_indent is 6, indent calculated from nestings is 2
|
|
383
|
+
# irb(main):003:0> c # base_indent is 6, indent calculated from nestings is 4
|
|
384
|
+
if prev_open_elem
|
|
385
|
+
base_indent = [0, indent_difference(lines, line_results, prev_open_elem.pos[0] - 1)].max
|
|
360
386
|
else
|
|
361
387
|
base_indent = 0
|
|
362
388
|
end
|
|
363
389
|
|
|
364
|
-
if
|
|
365
|
-
if is_newline &&
|
|
390
|
+
if free_indent_nesting_element?(prev_open_elem)
|
|
391
|
+
if is_newline && prev_open_elem.pos[0] == line_index
|
|
366
392
|
# First newline inside free-indent token
|
|
367
393
|
base_indent + indent
|
|
368
394
|
else
|
|
369
395
|
# Accept any number of indent inside free-indent token
|
|
370
396
|
preserve_indent
|
|
371
397
|
end
|
|
372
|
-
elsif
|
|
373
|
-
if
|
|
398
|
+
elsif prev_open_elem&.event == :on_embdoc_beg || next_open_elem&.event == :on_embdoc_beg
|
|
399
|
+
if prev_open_elem&.event == next_open_elem&.event
|
|
374
400
|
# Accept any number of indent inside embdoc content
|
|
375
401
|
preserve_indent
|
|
376
402
|
else
|
|
377
403
|
# =begin or =end
|
|
378
404
|
0
|
|
379
405
|
end
|
|
380
|
-
elsif
|
|
381
|
-
tok =
|
|
406
|
+
elsif prev_open_elem&.event == :on_heredoc_beg
|
|
407
|
+
tok = prev_open_elem.tok
|
|
382
408
|
if prev_opens.size <= next_opens.size
|
|
383
|
-
if is_newline && lines[line_index].empty? && line_results[line_index - 1][
|
|
409
|
+
if is_newline && lines[line_index].empty? && line_results[line_index - 1][0].last != next_open_elem
|
|
384
410
|
# First line in heredoc
|
|
385
411
|
tok.match?(/^<<[-~]/) ? base_indent + indent : indent
|
|
386
412
|
elsif tok.match?(/^<<~/)
|
|
@@ -400,15 +426,15 @@ module IRB
|
|
|
400
426
|
end
|
|
401
427
|
end
|
|
402
428
|
|
|
403
|
-
def
|
|
404
|
-
|
|
405
|
-
LTYPE_TOKENS.include?(
|
|
429
|
+
def ltype_from_open_nestings(opens)
|
|
430
|
+
start_nesting = opens.reverse_each.find do |elem|
|
|
431
|
+
LTYPE_TOKENS.include?(elem.event)
|
|
406
432
|
end
|
|
407
|
-
return nil unless
|
|
433
|
+
return nil unless start_nesting
|
|
408
434
|
|
|
409
|
-
case
|
|
435
|
+
case start_nesting&.event
|
|
410
436
|
when :on_tstring_beg
|
|
411
|
-
case
|
|
437
|
+
case start_nesting&.tok
|
|
412
438
|
when ?" then ?"
|
|
413
439
|
when /^%.$/ then ?"
|
|
414
440
|
when /^%Q.$/ then ?"
|
|
@@ -423,7 +449,7 @@ module IRB
|
|
|
423
449
|
when :on_qsymbols_beg then ?]
|
|
424
450
|
when :on_symbols_beg then ?]
|
|
425
451
|
when :on_heredoc_beg
|
|
426
|
-
|
|
452
|
+
start_nesting&.tok =~ /<<[-~]?(['"`])\w+\1/
|
|
427
453
|
$1 || ?"
|
|
428
454
|
else
|
|
429
455
|
nil
|
|
@@ -460,7 +486,7 @@ module IRB
|
|
|
460
486
|
if first_token && first_token.state != Ripper::EXPR_DOT
|
|
461
487
|
tokens_without_last_line = tokens[0..index]
|
|
462
488
|
code_without_last_line = tokens_without_last_line.map(&:tok).join
|
|
463
|
-
opens_without_last_line = NestingParser.
|
|
489
|
+
opens_without_last_line = NestingParser.open_nestings(Prism.parse_lex(code_without_last_line, scopes: [local_variables]))
|
|
464
490
|
if code_terminated?(code_without_last_line, tokens_without_last_line, opens_without_last_line, local_variables: local_variables)
|
|
465
491
|
return last_line_tokens.map(&:tok).join
|
|
466
492
|
end
|
data/lib/irb/source_finder.rb
CHANGED
|
@@ -29,10 +29,13 @@ module IRB
|
|
|
29
29
|
|
|
30
30
|
def colorized_content
|
|
31
31
|
if !binary_file? && file_exist?
|
|
32
|
-
end_line = find_end
|
|
33
32
|
# To correctly colorize, we need to colorize full content and extract the relevant lines.
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
colored_lines = IRB::Color.colorize_code(file_content).lines
|
|
34
|
+
|
|
35
|
+
# Handle wrong line number case: line_no passed to eval is wrong, file is edited after load, etc
|
|
36
|
+
return if colored_lines.size < @line
|
|
37
|
+
|
|
38
|
+
colored_lines[@line - 1...find_end].join
|
|
36
39
|
elsif @ast_source
|
|
37
40
|
IRB::Color.colorize_code(@ast_source)
|
|
38
41
|
end
|
|
@@ -114,7 +117,7 @@ module IRB
|
|
|
114
117
|
when "owner"
|
|
115
118
|
target_method = owner_receiver.instance_method(method)
|
|
116
119
|
when "receiver"
|
|
117
|
-
target_method =
|
|
120
|
+
target_method = Kernel.instance_method(:method).bind_call(owner_receiver, method)
|
|
118
121
|
end
|
|
119
122
|
super_level.times do |s|
|
|
120
123
|
target_method = target_method.super_method if target_method
|
data/lib/irb/version.rb
CHANGED
data/lib/irb/workspace.rb
CHANGED
|
@@ -55,6 +55,15 @@ EOF
|
|
|
55
55
|
# Note that this will typically be IRB::TOPLEVEL_BINDING
|
|
56
56
|
# This is to avoid RubyGems' local variables (see issue #17623)
|
|
57
57
|
@binding = TOPLEVEL_BINDING.dup
|
|
58
|
+
|
|
59
|
+
when 5 # binding in Ruby::Box
|
|
60
|
+
unless defined?(Ruby::Box)
|
|
61
|
+
puts 'Context-mode 5 (binding in Ruby::Box) requires Ruby 4.0 or later.'
|
|
62
|
+
raise NameError, 'Ruby::Box not defined'
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
puts 'Context-mode 5 (binding in Ruby::Box) is experimental. It may be removed or changed without notice.'
|
|
66
|
+
@binding = Ruby::Box.new.eval('Kernel.binding')
|
|
58
67
|
end
|
|
59
68
|
end
|
|
60
69
|
|
data/lib/irb.rb
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
|
|
6
6
|
#
|
|
7
7
|
|
|
8
|
+
require "prism"
|
|
8
9
|
require "ripper"
|
|
9
10
|
require "reline"
|
|
10
11
|
|
|
@@ -77,6 +78,15 @@ module IRB
|
|
|
77
78
|
PROMPT_MAIN_TRUNCATE_OMISSION = '...'
|
|
78
79
|
CONTROL_CHARACTERS_PATTERN = "\x00-\x1F"
|
|
79
80
|
|
|
81
|
+
# Track the nesting depth of run loops. This is used for history management
|
|
82
|
+
# only the outermost run loop should load/save history.
|
|
83
|
+
@run_nesting_depth = 0
|
|
84
|
+
|
|
85
|
+
class << self
|
|
86
|
+
# TODO: When refactoring to v2.0, find a better way to manage and track nesting sessions.
|
|
87
|
+
attr_accessor :run_nesting_depth
|
|
88
|
+
end
|
|
89
|
+
|
|
80
90
|
# Returns the current context of this irb session
|
|
81
91
|
attr_reader :context
|
|
82
92
|
# The lexer used by this irb session
|
|
@@ -87,6 +97,7 @@ module IRB
|
|
|
87
97
|
# Creates a new irb session
|
|
88
98
|
def initialize(workspace = nil, input_method = nil, from_binding: false)
|
|
89
99
|
@from_binding = from_binding
|
|
100
|
+
@prompt_part_cache = nil
|
|
90
101
|
@context = Context.new(self, workspace, input_method)
|
|
91
102
|
@context.workspace.load_helper_methods_to_main
|
|
92
103
|
@signal_status = :IN_IRB
|
|
@@ -147,7 +158,10 @@ module IRB
|
|
|
147
158
|
end
|
|
148
159
|
|
|
149
160
|
def run(conf = IRB.conf)
|
|
150
|
-
|
|
161
|
+
# Use run_nesting_depth to determine if we're in a nested session.
|
|
162
|
+
in_nested_session = Irb.run_nesting_depth > 0
|
|
163
|
+
Irb.run_nesting_depth += 1
|
|
164
|
+
|
|
151
165
|
conf[:IRB_RC].call(context) if conf[:IRB_RC]
|
|
152
166
|
prev_context = conf[:MAIN_CONTEXT]
|
|
153
167
|
conf[:MAIN_CONTEXT] = context
|
|
@@ -173,6 +187,8 @@ module IRB
|
|
|
173
187
|
eval_input
|
|
174
188
|
end
|
|
175
189
|
ensure
|
|
190
|
+
Irb.run_nesting_depth -= 1
|
|
191
|
+
|
|
176
192
|
# Do not restore to nil. It will cause IRB crash when used with threads.
|
|
177
193
|
IRB.conf[:MAIN_CONTEXT] = prev_context if prev_context
|
|
178
194
|
|
|
@@ -238,13 +254,7 @@ module IRB
|
|
|
238
254
|
end
|
|
239
255
|
end
|
|
240
256
|
|
|
241
|
-
def
|
|
242
|
-
prompt = generate_prompt([], false, 0)
|
|
243
|
-
|
|
244
|
-
# multiline
|
|
245
|
-
return read_input(prompt) if @context.io.respond_to?(:check_termination)
|
|
246
|
-
|
|
247
|
-
# nomultiline
|
|
257
|
+
def read_input_nomultiline(prompt)
|
|
248
258
|
code = +''
|
|
249
259
|
line_offset = 0
|
|
250
260
|
loop do
|
|
@@ -265,6 +275,20 @@ module IRB
|
|
|
265
275
|
end
|
|
266
276
|
end
|
|
267
277
|
|
|
278
|
+
def readmultiline
|
|
279
|
+
with_prompt_part_cached do
|
|
280
|
+
prompt = generate_prompt([], false, 0)
|
|
281
|
+
|
|
282
|
+
if @context.io.respond_to?(:check_termination)
|
|
283
|
+
# multiline
|
|
284
|
+
read_input(prompt)
|
|
285
|
+
else
|
|
286
|
+
# nomultiline
|
|
287
|
+
read_input_nomultiline(prompt)
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
|
|
268
292
|
def each_top_level_statement
|
|
269
293
|
loop do
|
|
270
294
|
code = readmultiline
|
|
@@ -314,15 +338,13 @@ module IRB
|
|
|
314
338
|
end
|
|
315
339
|
if @context.io.respond_to?(:dynamic_prompt)
|
|
316
340
|
@context.io.dynamic_prompt do |lines|
|
|
317
|
-
|
|
318
|
-
|
|
341
|
+
code = lines.map{ |l| l + "\n" }.join
|
|
342
|
+
tokens = RubyLex.ripper_lex_without_warning(code, local_variables: @context.local_variables)
|
|
343
|
+
parse_lex_result = Prism.parse_lex(code, scopes: [@context.local_variables])
|
|
344
|
+
line_results = IRB::NestingParser.parse_by_line(parse_lex_result)
|
|
319
345
|
tokens_until_line = []
|
|
320
|
-
line_results.map.with_index do |(
|
|
321
|
-
|
|
322
|
-
# Avoid appending duplicated token. Tokens that include "n" like multiline
|
|
323
|
-
# tstring_content can exist in multiple lines.
|
|
324
|
-
tokens_until_line << token if token != tokens_until_line.last
|
|
325
|
-
end
|
|
346
|
+
line_results.map.with_index do |(_prev_opens, next_opens, _min_depth), line_num_offset|
|
|
347
|
+
tokens_until_line << tokens.shift while !tokens.empty? && tokens.first.pos[0] <= line_num_offset + 1
|
|
326
348
|
continue = @scanner.should_continue?(tokens_until_line)
|
|
327
349
|
generate_prompt(next_opens, continue, line_num_offset)
|
|
328
350
|
end
|
|
@@ -335,8 +357,8 @@ module IRB
|
|
|
335
357
|
next nil if !is_newline && lines[line_index]&.byteslice(0, byte_pointer)&.match?(/\A\s*\z/)
|
|
336
358
|
|
|
337
359
|
code = lines[0..line_index].map { |l| "#{l}\n" }.join
|
|
338
|
-
|
|
339
|
-
@scanner.process_indent_level(
|
|
360
|
+
parse_lex_result = Prism.parse_lex(code, scopes: [@context.local_variables])
|
|
361
|
+
@scanner.process_indent_level(parse_lex_result, lines, line_index, is_newline)
|
|
340
362
|
end
|
|
341
363
|
end
|
|
342
364
|
end
|
|
@@ -567,8 +589,15 @@ module IRB
|
|
|
567
589
|
|
|
568
590
|
private
|
|
569
591
|
|
|
592
|
+
def with_prompt_part_cached
|
|
593
|
+
@prompt_part_cache = {}
|
|
594
|
+
yield
|
|
595
|
+
ensure
|
|
596
|
+
@prompt_part_cache = nil
|
|
597
|
+
end
|
|
598
|
+
|
|
570
599
|
def generate_prompt(opens, continue, line_offset)
|
|
571
|
-
ltype = @scanner.
|
|
600
|
+
ltype = @scanner.ltype_from_open_nestings(opens)
|
|
572
601
|
indent = @scanner.calc_indent_level(opens)
|
|
573
602
|
continue = opens.any? || continue
|
|
574
603
|
line_no = @line_no + line_offset
|
|
@@ -598,25 +627,29 @@ module IRB
|
|
|
598
627
|
end
|
|
599
628
|
|
|
600
629
|
def truncate_prompt_main(str) # :nodoc:
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
str
|
|
604
|
-
else
|
|
605
|
-
str[0, PROMPT_MAIN_TRUNCATE_LENGTH - PROMPT_MAIN_TRUNCATE_OMISSION.size] + PROMPT_MAIN_TRUNCATE_OMISSION
|
|
630
|
+
if str.size > PROMPT_MAIN_TRUNCATE_LENGTH
|
|
631
|
+
str = str[0, PROMPT_MAIN_TRUNCATE_LENGTH - PROMPT_MAIN_TRUNCATE_OMISSION.size] + PROMPT_MAIN_TRUNCATE_OMISSION
|
|
606
632
|
end
|
|
633
|
+
str.tr(CONTROL_CHARACTERS_PATTERN, ' ')
|
|
607
634
|
end
|
|
608
635
|
|
|
609
636
|
def format_prompt(format, ltype, indent, line_no) # :nodoc:
|
|
637
|
+
# @prompt_part_cache could be nil in unit tests
|
|
638
|
+
part_cache = @prompt_part_cache || {}
|
|
610
639
|
format.gsub(/%([0-9]+)?([a-zA-Z%])/) do
|
|
611
640
|
case $2
|
|
612
641
|
when "N"
|
|
613
642
|
@context.irb_name
|
|
614
643
|
when "m"
|
|
615
|
-
|
|
616
|
-
|
|
644
|
+
part_cache[:m] ||= (
|
|
645
|
+
main_str = "#{@context.safe_method_call_on_main(:to_s)}" rescue "!#{$!.class}"
|
|
646
|
+
truncate_prompt_main(main_str)
|
|
647
|
+
)
|
|
617
648
|
when "M"
|
|
618
|
-
|
|
619
|
-
|
|
649
|
+
part_cache[:M] ||= (
|
|
650
|
+
main_str = "#{@context.safe_method_call_on_main(:inspect)}" rescue "!#{$!.class}"
|
|
651
|
+
truncate_prompt_main(main_str)
|
|
652
|
+
)
|
|
620
653
|
when "l"
|
|
621
654
|
ltype
|
|
622
655
|
when "i"
|
metadata
CHANGED
|
@@ -1,15 +1,29 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: irb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.17.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- aycabta
|
|
8
8
|
- Keiju ISHITSUKA
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: prism
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: 1.3.0
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: 1.3.0
|
|
13
27
|
- !ruby/object:Gem::Dependency
|
|
14
28
|
name: reline
|
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -61,16 +75,20 @@ executables:
|
|
|
61
75
|
extensions: []
|
|
62
76
|
extra_rdoc_files: []
|
|
63
77
|
files:
|
|
78
|
+
- ".rdoc_options"
|
|
79
|
+
- CONTRIBUTING.md
|
|
80
|
+
- EXTEND_IRB.md
|
|
64
81
|
- Gemfile
|
|
65
82
|
- LICENSE.txt
|
|
66
83
|
- README.md
|
|
67
|
-
-
|
|
68
|
-
-
|
|
69
|
-
-
|
|
84
|
+
- doc/COMMAND_LINE_OPTIONS.md
|
|
85
|
+
- doc/COMPARED_WITH_PRY.md
|
|
86
|
+
- doc/Configurations.md
|
|
87
|
+
- doc/EXTEND_IRB.md
|
|
88
|
+
- doc/Index.md
|
|
70
89
|
- doc/irb/irb-tools.rd.ja
|
|
71
90
|
- doc/irb/irb.rd.ja
|
|
72
91
|
- exe/irb
|
|
73
|
-
- irb.gemspec
|
|
74
92
|
- lib/irb.rb
|
|
75
93
|
- lib/irb/cmd/nop.rb
|
|
76
94
|
- lib/irb/color.rb
|
|
@@ -170,7 +188,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
170
188
|
- !ruby/object:Gem::Version
|
|
171
189
|
version: '0'
|
|
172
190
|
requirements: []
|
|
173
|
-
rubygems_version: 3.6.
|
|
191
|
+
rubygems_version: 3.6.7
|
|
174
192
|
specification_version: 4
|
|
175
193
|
summary: Interactive Ruby command-line tool for REPL (Read Eval Print Loop).
|
|
176
194
|
test_files: []
|
data/Rakefile
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
require "bundler/gem_tasks"
|
|
2
|
-
require "rake/testtask"
|
|
3
|
-
require "rdoc/task"
|
|
4
|
-
|
|
5
|
-
Rake::TestTask.new(:test) do |t|
|
|
6
|
-
t.libs << "test" << "test/lib"
|
|
7
|
-
t.libs << "lib"
|
|
8
|
-
t.ruby_opts << "-rhelper"
|
|
9
|
-
t.test_files = FileList["test/irb/**/test_*.rb"]
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
# To make sure they have been correctly setup for Ruby CI.
|
|
13
|
-
desc "Run each irb test file in isolation."
|
|
14
|
-
task :test_in_isolation do
|
|
15
|
-
failed = false
|
|
16
|
-
|
|
17
|
-
FileList["test/irb/**/test_*.rb"].each do |test_file|
|
|
18
|
-
ENV["TEST"] = test_file
|
|
19
|
-
begin
|
|
20
|
-
Rake::Task["test"].execute
|
|
21
|
-
rescue
|
|
22
|
-
failed = true
|
|
23
|
-
msg = "Test '#{test_file}' failed when being executed in isolation. Please make sure 'rake test TEST=#{test_file}' passes."
|
|
24
|
-
separation_line = '=' * msg.length
|
|
25
|
-
|
|
26
|
-
puts <<~MSG
|
|
27
|
-
#{separation_line}
|
|
28
|
-
#{msg}
|
|
29
|
-
#{separation_line}
|
|
30
|
-
MSG
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
fail "Some tests failed when being executed in isolation" if failed
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
Rake::TestTask.new(:test_yamatanooroti) do |t|
|
|
38
|
-
t.libs << 'test' << "test/lib"
|
|
39
|
-
t.libs << 'lib'
|
|
40
|
-
#t.loader = :direct
|
|
41
|
-
t.ruby_opts << "-rhelper"
|
|
42
|
-
t.pattern = 'test/irb/yamatanooroti/test_*.rb'
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
task :default => :test
|
|
46
|
-
|
|
47
|
-
RDoc::Task.new do |rdoc|
|
|
48
|
-
rdoc.title = "IRB Documentation"
|
|
49
|
-
rdoc.main = "Index.md"
|
|
50
|
-
rdoc.rdoc_dir = "_site"
|
|
51
|
-
rdoc.options.push("lib")
|
|
52
|
-
end
|
data/bin/console
DELETED
data/bin/setup
DELETED
data/irb.gemspec
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
begin
|
|
2
|
-
require_relative "lib/irb/version"
|
|
3
|
-
rescue LoadError
|
|
4
|
-
# for Ruby core repository
|
|
5
|
-
require_relative "version"
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
Gem::Specification.new do |spec|
|
|
9
|
-
spec.name = "irb"
|
|
10
|
-
spec.version = IRB::VERSION
|
|
11
|
-
spec.authors = ["aycabta", "Keiju ISHITSUKA"]
|
|
12
|
-
spec.email = ["aycabta@gmail.com", "keiju@ruby-lang.org"]
|
|
13
|
-
|
|
14
|
-
spec.summary = %q{Interactive Ruby command-line tool for REPL (Read Eval Print Loop).}
|
|
15
|
-
spec.description = %q{Interactive Ruby command-line tool for REPL (Read Eval Print Loop).}
|
|
16
|
-
spec.homepage = "https://github.com/ruby/irb"
|
|
17
|
-
spec.licenses = ["Ruby", "BSD-2-Clause"]
|
|
18
|
-
|
|
19
|
-
spec.metadata["homepage_uri"] = spec.homepage
|
|
20
|
-
spec.metadata["source_code_uri"] = spec.homepage
|
|
21
|
-
spec.metadata["documentation_uri"] = "https://ruby.github.io/irb/"
|
|
22
|
-
spec.metadata["changelog_uri"] = "#{spec.homepage}/releases"
|
|
23
|
-
|
|
24
|
-
spec.files = [
|
|
25
|
-
"Gemfile",
|
|
26
|
-
"LICENSE.txt",
|
|
27
|
-
"README.md",
|
|
28
|
-
"Rakefile",
|
|
29
|
-
"bin/console",
|
|
30
|
-
"bin/setup",
|
|
31
|
-
"doc/irb/irb-tools.rd.ja",
|
|
32
|
-
"doc/irb/irb.rd.ja",
|
|
33
|
-
"exe/irb",
|
|
34
|
-
"irb.gemspec",
|
|
35
|
-
"man/irb.1",
|
|
36
|
-
] + Dir.chdir(File.expand_path('..', __FILE__)) do
|
|
37
|
-
Dir.glob("lib/**/*").map {|f| f unless File.directory?(f) }.compact
|
|
38
|
-
end
|
|
39
|
-
spec.bindir = "exe"
|
|
40
|
-
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
41
|
-
spec.require_paths = ["lib"]
|
|
42
|
-
|
|
43
|
-
spec.required_ruby_version = Gem::Requirement.new(">= 2.7")
|
|
44
|
-
|
|
45
|
-
spec.add_dependency "reline", ">= 0.4.2"
|
|
46
|
-
spec.add_dependency "rdoc", ">= 4.0.0"
|
|
47
|
-
spec.add_dependency "pp", ">= 0.6.0"
|
|
48
|
-
end
|