irb 1.3.6 → 1.4.1
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/Gemfile +3 -5
- data/Rakefile +10 -1
- data/doc/irb/irb.rd.ja +30 -14
- data/irb.gemspec +1 -1
- data/lib/irb/cmd/help.rb +2 -1
- data/lib/irb/cmd/info.rb +7 -0
- data/lib/irb/cmd/ls.rb +9 -15
- data/lib/irb/cmd/measure.rb +3 -0
- data/lib/irb/cmd/show_source.rb +11 -4
- data/lib/irb/completion.rb +57 -17
- data/lib/irb/context.rb +37 -9
- data/lib/irb/init.rb +9 -0
- data/lib/irb/input-method.rb +100 -1
- data/lib/irb/lc/help-message +10 -1
- data/lib/irb/lc/ja/help-message +2 -0
- data/lib/irb/ruby-lex.rb +151 -92
- data/lib/irb/version.rb +2 -2
- data/lib/irb/workspace.rb +3 -0
- data/lib/irb.rb +21 -6
- data/man/irb.1 +23 -1
- metadata +9 -9
data/lib/irb/ruby-lex.rb
CHANGED
@@ -30,26 +30,31 @@ class RubyLex
|
|
30
30
|
@prompt = nil
|
31
31
|
end
|
32
32
|
|
33
|
-
def self.compile_with_errors_suppressed(code)
|
34
|
-
line_no = 1
|
33
|
+
def self.compile_with_errors_suppressed(code, line_no: 1)
|
35
34
|
begin
|
36
35
|
result = yield code, line_no
|
37
36
|
rescue ArgumentError
|
37
|
+
# Ruby can issue an error for the code if there is an
|
38
|
+
# incomplete magic comment for encoding in it. Force an
|
39
|
+
# expression with a new line before the code in this
|
40
|
+
# case to prevent magic comment handling. To make sure
|
41
|
+
# line numbers in the lexed code remain the same,
|
42
|
+
# decrease the line number by one.
|
38
43
|
code = ";\n#{code}"
|
39
|
-
line_no
|
44
|
+
line_no -= 1
|
40
45
|
result = yield code, line_no
|
41
46
|
end
|
42
47
|
result
|
43
48
|
end
|
44
49
|
|
45
50
|
# io functions
|
46
|
-
def set_input(io, p = nil, &block)
|
51
|
+
def set_input(io, p = nil, context: nil, &block)
|
47
52
|
@io = io
|
48
53
|
if @io.respond_to?(:check_termination)
|
49
54
|
@io.check_termination do |code|
|
50
55
|
if Reline::IOGate.in_pasting?
|
51
56
|
lex = RubyLex.new
|
52
|
-
rest = lex.check_termination_in_prev_line(code)
|
57
|
+
rest = lex.check_termination_in_prev_line(code, context: context)
|
53
58
|
if rest
|
54
59
|
Reline.delete_text
|
55
60
|
rest.bytes.reverse_each do |c|
|
@@ -61,7 +66,7 @@ class RubyLex
|
|
61
66
|
end
|
62
67
|
else
|
63
68
|
code.gsub!(/\s*\z/, '').concat("\n")
|
64
|
-
ltype, indent, continue, code_block_open = check_state(code)
|
69
|
+
ltype, indent, continue, code_block_open = check_state(code, context: context)
|
65
70
|
if ltype or indent > 0 or continue or code_block_open
|
66
71
|
false
|
67
72
|
else
|
@@ -74,7 +79,7 @@ class RubyLex
|
|
74
79
|
@io.dynamic_prompt do |lines|
|
75
80
|
lines << '' if lines.empty?
|
76
81
|
result = []
|
77
|
-
tokens = self.class.ripper_lex_without_warning(lines.map{ |l| l + "\n" }.join)
|
82
|
+
tokens = self.class.ripper_lex_without_warning(lines.map{ |l| l + "\n" }.join, context: context)
|
78
83
|
code = String.new
|
79
84
|
partial_tokens = []
|
80
85
|
unprocessed_tokens = []
|
@@ -82,26 +87,28 @@ class RubyLex
|
|
82
87
|
tokens.each do |t|
|
83
88
|
partial_tokens << t
|
84
89
|
unprocessed_tokens << t
|
85
|
-
if t
|
86
|
-
t_str = t
|
90
|
+
if t.tok.include?("\n")
|
91
|
+
t_str = t.tok
|
87
92
|
t_str.each_line("\n") do |s|
|
88
93
|
code << s << "\n"
|
89
|
-
ltype, indent, continue, code_block_open = check_state(code, partial_tokens)
|
94
|
+
ltype, indent, continue, code_block_open = check_state(code, partial_tokens, context: context)
|
90
95
|
result << @prompt.call(ltype, indent, continue || code_block_open, @line_no + line_num_offset)
|
91
96
|
line_num_offset += 1
|
92
97
|
end
|
93
98
|
unprocessed_tokens = []
|
94
99
|
else
|
95
|
-
code << t
|
100
|
+
code << t.tok
|
96
101
|
end
|
97
102
|
end
|
103
|
+
|
98
104
|
unless unprocessed_tokens.empty?
|
99
|
-
ltype, indent, continue, code_block_open = check_state(code, unprocessed_tokens)
|
105
|
+
ltype, indent, continue, code_block_open = check_state(code, unprocessed_tokens, context: context)
|
100
106
|
result << @prompt.call(ltype, indent, continue || code_block_open, @line_no + line_num_offset)
|
101
107
|
end
|
102
108
|
result
|
103
109
|
end
|
104
110
|
end
|
111
|
+
|
105
112
|
if p.respond_to?(:call)
|
106
113
|
@input = p
|
107
114
|
elsif block_given?
|
@@ -129,28 +136,38 @@ class RubyLex
|
|
129
136
|
:on_param_error
|
130
137
|
]
|
131
138
|
|
132
|
-
def self.ripper_lex_without_warning(code)
|
139
|
+
def self.ripper_lex_without_warning(code, context: nil)
|
133
140
|
verbose, $VERBOSE = $VERBOSE, nil
|
141
|
+
if context
|
142
|
+
lvars = context&.workspace&.binding&.local_variables
|
143
|
+
if lvars && !lvars.empty?
|
144
|
+
code = "#{lvars.join('=')}=nil\n#{code}"
|
145
|
+
line_no = 0
|
146
|
+
else
|
147
|
+
line_no = 1
|
148
|
+
end
|
149
|
+
end
|
134
150
|
tokens = nil
|
135
|
-
compile_with_errors_suppressed(code) do |inner_code, line_no|
|
151
|
+
compile_with_errors_suppressed(code, line_no: line_no) do |inner_code, line_no|
|
136
152
|
lexer = Ripper::Lexer.new(inner_code, '-', line_no)
|
137
153
|
if lexer.respond_to?(:scan) # Ruby 2.7+
|
138
154
|
tokens = []
|
139
155
|
pos_to_index = {}
|
140
156
|
lexer.scan.each do |t|
|
141
|
-
if
|
142
|
-
|
157
|
+
next if t.pos.first == 0
|
158
|
+
if pos_to_index.has_key?(t.pos)
|
159
|
+
index = pos_to_index[t.pos]
|
143
160
|
found_tk = tokens[index]
|
144
|
-
if ERROR_TOKENS.include?(found_tk
|
161
|
+
if ERROR_TOKENS.include?(found_tk.event) && !ERROR_TOKENS.include?(t.event)
|
145
162
|
tokens[index] = t
|
146
163
|
end
|
147
164
|
else
|
148
|
-
pos_to_index[t
|
165
|
+
pos_to_index[t.pos] = tokens.size
|
149
166
|
tokens << t
|
150
167
|
end
|
151
168
|
end
|
152
169
|
else
|
153
|
-
tokens = lexer.parse
|
170
|
+
tokens = lexer.parse.reject { |it| it.pos.first == 0 }
|
154
171
|
end
|
155
172
|
end
|
156
173
|
tokens
|
@@ -160,17 +177,17 @@ class RubyLex
|
|
160
177
|
|
161
178
|
def find_prev_spaces(line_index)
|
162
179
|
return 0 if @tokens.size == 0
|
163
|
-
md = @tokens[0]
|
180
|
+
md = @tokens[0].tok.match(/(\A +)/)
|
164
181
|
prev_spaces = md.nil? ? 0 : md[1].count(' ')
|
165
182
|
line_count = 0
|
166
183
|
@tokens.each_with_index do |t, i|
|
167
|
-
if t
|
168
|
-
line_count += t
|
184
|
+
if t.tok.include?("\n")
|
185
|
+
line_count += t.tok.count("\n")
|
169
186
|
if line_count >= line_index
|
170
187
|
return prev_spaces
|
171
188
|
end
|
172
189
|
if (@tokens.size - 1) > i
|
173
|
-
md = @tokens[i + 1]
|
190
|
+
md = @tokens[i + 1].tok.match(/(\A +)/)
|
174
191
|
prev_spaces = md.nil? ? 0 : md[1].count(' ')
|
175
192
|
end
|
176
193
|
end
|
@@ -182,7 +199,7 @@ class RubyLex
|
|
182
199
|
if @io.respond_to?(:auto_indent) and context.auto_indent_mode
|
183
200
|
@io.auto_indent do |lines, line_index, byte_pointer, is_newline|
|
184
201
|
if is_newline
|
185
|
-
@tokens = self.class.ripper_lex_without_warning(lines[0..line_index].join("\n"))
|
202
|
+
@tokens = self.class.ripper_lex_without_warning(lines[0..line_index].join("\n"), context: context)
|
186
203
|
prev_spaces = find_prev_spaces(line_index)
|
187
204
|
depth_difference = check_newline_depth_difference
|
188
205
|
depth_difference = 0 if depth_difference < 0
|
@@ -191,8 +208,8 @@ class RubyLex
|
|
191
208
|
code = line_index.zero? ? '' : lines[0..(line_index - 1)].map{ |l| l + "\n" }.join
|
192
209
|
last_line = lines[line_index]&.byteslice(0, byte_pointer)
|
193
210
|
code += last_line if last_line
|
194
|
-
@tokens = self.class.ripper_lex_without_warning(code)
|
195
|
-
corresponding_token_depth = check_corresponding_token_depth
|
211
|
+
@tokens = self.class.ripper_lex_without_warning(code, context: context)
|
212
|
+
corresponding_token_depth = check_corresponding_token_depth(lines, line_index)
|
196
213
|
if corresponding_token_depth
|
197
214
|
corresponding_token_depth
|
198
215
|
else
|
@@ -203,8 +220,8 @@ class RubyLex
|
|
203
220
|
end
|
204
221
|
end
|
205
222
|
|
206
|
-
def check_state(code, tokens = nil)
|
207
|
-
tokens = self.class.ripper_lex_without_warning(code) unless tokens
|
223
|
+
def check_state(code, tokens = nil, context: nil)
|
224
|
+
tokens = self.class.ripper_lex_without_warning(code, context: context) unless tokens
|
208
225
|
ltype = process_literal_type(tokens)
|
209
226
|
indent = process_nesting_level(tokens)
|
210
227
|
continue = process_continue(tokens)
|
@@ -280,18 +297,18 @@ class RubyLex
|
|
280
297
|
|
281
298
|
def process_continue(tokens = @tokens)
|
282
299
|
# last token is always newline
|
283
|
-
if tokens.size >= 2 and tokens[-2]
|
300
|
+
if tokens.size >= 2 and tokens[-2].event == :on_regexp_end
|
284
301
|
# end of regexp literal
|
285
302
|
return false
|
286
|
-
elsif tokens.size >= 2 and tokens[-2]
|
303
|
+
elsif tokens.size >= 2 and tokens[-2].event == :on_semicolon
|
287
304
|
return false
|
288
|
-
elsif tokens.size >= 2 and tokens[-2]
|
305
|
+
elsif tokens.size >= 2 and tokens[-2].event == :on_kw and ['begin', 'else', 'ensure'].include?(tokens[-2].tok)
|
289
306
|
return false
|
290
|
-
elsif !tokens.empty? and tokens.last
|
307
|
+
elsif !tokens.empty? and tokens.last.tok == "\\\n"
|
291
308
|
return true
|
292
|
-
elsif tokens.size >= 1 and tokens[-1]
|
309
|
+
elsif tokens.size >= 1 and tokens[-1].event == :on_heredoc_end # "EOH\n"
|
293
310
|
return false
|
294
|
-
elsif tokens.size >= 2 and defined?(Ripper::EXPR_BEG) and tokens[-2]
|
311
|
+
elsif tokens.size >= 2 and defined?(Ripper::EXPR_BEG) and tokens[-2].state.anybits?(Ripper::EXPR_BEG | Ripper::EXPR_FNAME) and tokens[-2].tok !~ /\A\.\.\.?\z/
|
295
312
|
# end of literal except for regexp
|
296
313
|
# endless range at end of line is not a continue
|
297
314
|
return true
|
@@ -301,7 +318,7 @@ class RubyLex
|
|
301
318
|
|
302
319
|
def check_code_block(code, tokens = @tokens)
|
303
320
|
return true if tokens.empty?
|
304
|
-
if tokens.last
|
321
|
+
if tokens.last.event == :on_heredoc_beg
|
305
322
|
return true
|
306
323
|
end
|
307
324
|
|
@@ -373,7 +390,7 @@ class RubyLex
|
|
373
390
|
end
|
374
391
|
|
375
392
|
if defined?(Ripper::EXPR_BEG)
|
376
|
-
last_lex_state = tokens.last
|
393
|
+
last_lex_state = tokens.last.state
|
377
394
|
if last_lex_state.allbits?(Ripper::EXPR_BEG)
|
378
395
|
return false
|
379
396
|
elsif last_lex_state.allbits?(Ripper::EXPR_DOT)
|
@@ -398,14 +415,14 @@ class RubyLex
|
|
398
415
|
tokens.each_with_index { |t, index|
|
399
416
|
# detecting one-liner method definition
|
400
417
|
if in_oneliner_def.nil?
|
401
|
-
if t
|
418
|
+
if t.state.allbits?(Ripper::EXPR_ENDFN)
|
402
419
|
in_oneliner_def = :ENDFN
|
403
420
|
end
|
404
421
|
else
|
405
|
-
if t
|
422
|
+
if t.state.allbits?(Ripper::EXPR_ENDFN)
|
406
423
|
# continuing
|
407
|
-
elsif t
|
408
|
-
if t
|
424
|
+
elsif t.state.allbits?(Ripper::EXPR_BEG)
|
425
|
+
if t.tok == '='
|
409
426
|
in_oneliner_def = :BODY
|
410
427
|
end
|
411
428
|
else
|
@@ -417,14 +434,14 @@ class RubyLex
|
|
417
434
|
end
|
418
435
|
end
|
419
436
|
|
420
|
-
case t
|
437
|
+
case t.event
|
421
438
|
when :on_lbracket, :on_lbrace, :on_lparen, :on_tlambeg
|
422
439
|
indent += 1
|
423
440
|
when :on_rbracket, :on_rbrace, :on_rparen
|
424
441
|
indent -= 1
|
425
442
|
when :on_kw
|
426
|
-
next if index > 0 and tokens[index - 1]
|
427
|
-
case t
|
443
|
+
next if index > 0 and tokens[index - 1].state.allbits?(Ripper::EXPR_FNAME)
|
444
|
+
case t.tok
|
428
445
|
when 'do'
|
429
446
|
syntax_of_do = take_corresponding_syntax_to_kw_do(tokens, index)
|
430
447
|
indent += 1 if syntax_of_do == :method_calling
|
@@ -432,7 +449,7 @@ class RubyLex
|
|
432
449
|
indent += 1
|
433
450
|
when 'if', 'unless', 'while', 'until'
|
434
451
|
# postfix if/unless/while/until must be Ripper::EXPR_LABEL
|
435
|
-
indent += 1 unless t
|
452
|
+
indent += 1 unless t.state.allbits?(Ripper::EXPR_LABEL)
|
436
453
|
when 'end'
|
437
454
|
indent -= 1
|
438
455
|
end
|
@@ -444,14 +461,14 @@ class RubyLex
|
|
444
461
|
|
445
462
|
def is_method_calling?(tokens, index)
|
446
463
|
tk = tokens[index]
|
447
|
-
if tk
|
464
|
+
if tk.state.anybits?(Ripper::EXPR_CMDARG) and tk.event == :on_ident
|
448
465
|
# The target method call to pass the block with "do".
|
449
466
|
return true
|
450
|
-
elsif tk
|
451
|
-
non_sp_index = tokens[0..(index - 1)].rindex{ |t| t
|
467
|
+
elsif tk.state.anybits?(Ripper::EXPR_ARG) and tk.event == :on_ident
|
468
|
+
non_sp_index = tokens[0..(index - 1)].rindex{ |t| t.event != :on_sp }
|
452
469
|
if non_sp_index
|
453
470
|
prev_tk = tokens[non_sp_index]
|
454
|
-
if prev_tk
|
471
|
+
if prev_tk.state.anybits?(Ripper::EXPR_DOT) and prev_tk.event == :on_period
|
455
472
|
# The target method call with receiver to pass the block with "do".
|
456
473
|
return true
|
457
474
|
end
|
@@ -462,21 +479,21 @@ class RubyLex
|
|
462
479
|
|
463
480
|
def take_corresponding_syntax_to_kw_do(tokens, index)
|
464
481
|
syntax_of_do = nil
|
465
|
-
# Finding a syntax
|
482
|
+
# Finding a syntax corresponding to "do".
|
466
483
|
index.downto(0) do |i|
|
467
484
|
tk = tokens[i]
|
468
485
|
# In "continue", the token isn't the corresponding syntax to "do".
|
469
|
-
non_sp_index = tokens[0..(i - 1)].rindex{ |t| t
|
486
|
+
non_sp_index = tokens[0..(i - 1)].rindex{ |t| t.event != :on_sp }
|
470
487
|
first_in_fomula = false
|
471
488
|
if non_sp_index.nil?
|
472
489
|
first_in_fomula = true
|
473
|
-
elsif [:on_ignored_nl, :on_nl, :on_comment].include?(tokens[non_sp_index]
|
490
|
+
elsif [:on_ignored_nl, :on_nl, :on_comment].include?(tokens[non_sp_index].event)
|
474
491
|
first_in_fomula = true
|
475
492
|
end
|
476
493
|
if is_method_calling?(tokens, i)
|
477
494
|
syntax_of_do = :method_calling
|
478
495
|
break if first_in_fomula
|
479
|
-
elsif tk
|
496
|
+
elsif tk.event == :on_kw && %w{while until for}.include?(tk.tok)
|
480
497
|
# A loop syntax in front of "do" found.
|
481
498
|
#
|
482
499
|
# while cond do # also "until" or "for"
|
@@ -493,18 +510,18 @@ class RubyLex
|
|
493
510
|
|
494
511
|
def is_the_in_correspond_to_a_for(tokens, index)
|
495
512
|
syntax_of_in = nil
|
496
|
-
# Finding a syntax
|
513
|
+
# Finding a syntax corresponding to "do".
|
497
514
|
index.downto(0) do |i|
|
498
515
|
tk = tokens[i]
|
499
516
|
# In "continue", the token isn't the corresponding syntax to "do".
|
500
|
-
non_sp_index = tokens[0..(i - 1)].rindex{ |t| t
|
517
|
+
non_sp_index = tokens[0..(i - 1)].rindex{ |t| t.event != :on_sp }
|
501
518
|
first_in_fomula = false
|
502
519
|
if non_sp_index.nil?
|
503
520
|
first_in_fomula = true
|
504
|
-
elsif [:on_ignored_nl, :on_nl, :on_comment].include?(tokens[non_sp_index]
|
521
|
+
elsif [:on_ignored_nl, :on_nl, :on_comment].include?(tokens[non_sp_index].event)
|
505
522
|
first_in_fomula = true
|
506
523
|
end
|
507
|
-
if tk
|
524
|
+
if tk.event == :on_kw && tk.tok == 'for'
|
508
525
|
# A loop syntax in front of "do" found.
|
509
526
|
#
|
510
527
|
# while cond do # also "until" or "for"
|
@@ -526,14 +543,14 @@ class RubyLex
|
|
526
543
|
@tokens.each_with_index do |t, index|
|
527
544
|
# detecting one-liner method definition
|
528
545
|
if in_oneliner_def.nil?
|
529
|
-
if t
|
546
|
+
if t.state.allbits?(Ripper::EXPR_ENDFN)
|
530
547
|
in_oneliner_def = :ENDFN
|
531
548
|
end
|
532
549
|
else
|
533
|
-
if t
|
550
|
+
if t.state.allbits?(Ripper::EXPR_ENDFN)
|
534
551
|
# continuing
|
535
|
-
elsif t
|
536
|
-
if t
|
552
|
+
elsif t.state.allbits?(Ripper::EXPR_BEG)
|
553
|
+
if t.tok == '='
|
537
554
|
in_oneliner_def = :BODY
|
538
555
|
end
|
539
556
|
else
|
@@ -545,7 +562,7 @@ class RubyLex
|
|
545
562
|
end
|
546
563
|
end
|
547
564
|
|
548
|
-
case t
|
565
|
+
case t.event
|
549
566
|
when :on_ignored_nl, :on_nl, :on_comment
|
550
567
|
if index != (@tokens.size - 1) and in_oneliner_def != :BODY
|
551
568
|
depth_difference = 0
|
@@ -555,15 +572,16 @@ class RubyLex
|
|
555
572
|
when :on_sp
|
556
573
|
next
|
557
574
|
end
|
558
|
-
|
575
|
+
|
576
|
+
case t.event
|
559
577
|
when :on_lbracket, :on_lbrace, :on_lparen, :on_tlambeg
|
560
578
|
depth_difference += 1
|
561
579
|
open_brace_on_line += 1
|
562
580
|
when :on_rbracket, :on_rbrace, :on_rparen
|
563
581
|
depth_difference -= 1 if open_brace_on_line > 0
|
564
582
|
when :on_kw
|
565
|
-
next if index > 0 and @tokens[index - 1]
|
566
|
-
case t
|
583
|
+
next if index > 0 and @tokens[index - 1].state.allbits?(Ripper::EXPR_FNAME)
|
584
|
+
case t.tok
|
567
585
|
when 'do'
|
568
586
|
syntax_of_do = take_corresponding_syntax_to_kw_do(@tokens, index)
|
569
587
|
depth_difference += 1 if syntax_of_do == :method_calling
|
@@ -571,7 +589,7 @@ class RubyLex
|
|
571
589
|
depth_difference += 1
|
572
590
|
when 'if', 'unless', 'while', 'until', 'rescue'
|
573
591
|
# postfix if/unless/while/until/rescue must be Ripper::EXPR_LABEL
|
574
|
-
unless t
|
592
|
+
unless t.state.allbits?(Ripper::EXPR_LABEL)
|
575
593
|
depth_difference += 1
|
576
594
|
end
|
577
595
|
when 'else', 'elsif', 'ensure', 'when'
|
@@ -588,7 +606,7 @@ class RubyLex
|
|
588
606
|
depth_difference
|
589
607
|
end
|
590
608
|
|
591
|
-
def check_corresponding_token_depth
|
609
|
+
def check_corresponding_token_depth(lines, line_index)
|
592
610
|
corresponding_token_depth = nil
|
593
611
|
is_first_spaces_of_line = true
|
594
612
|
is_first_printable_of_line = true
|
@@ -596,17 +614,22 @@ class RubyLex
|
|
596
614
|
spaces_at_line_head = 0
|
597
615
|
open_brace_on_line = 0
|
598
616
|
in_oneliner_def = nil
|
617
|
+
|
618
|
+
if heredoc_scope?
|
619
|
+
return lines[line_index][/^ */].length
|
620
|
+
end
|
621
|
+
|
599
622
|
@tokens.each_with_index do |t, index|
|
600
623
|
# detecting one-liner method definition
|
601
624
|
if in_oneliner_def.nil?
|
602
|
-
if t
|
625
|
+
if t.state.allbits?(Ripper::EXPR_ENDFN)
|
603
626
|
in_oneliner_def = :ENDFN
|
604
627
|
end
|
605
628
|
else
|
606
|
-
if t
|
629
|
+
if t.state.allbits?(Ripper::EXPR_ENDFN)
|
607
630
|
# continuing
|
608
|
-
elsif t
|
609
|
-
if t
|
631
|
+
elsif t.state.allbits?(Ripper::EXPR_BEG)
|
632
|
+
if t.tok == '='
|
610
633
|
in_oneliner_def = :BODY
|
611
634
|
end
|
612
635
|
else
|
@@ -623,7 +646,7 @@ class RubyLex
|
|
623
646
|
end
|
624
647
|
end
|
625
648
|
|
626
|
-
case t
|
649
|
+
case t.event
|
627
650
|
when :on_ignored_nl, :on_nl, :on_comment
|
628
651
|
if in_oneliner_def != :BODY
|
629
652
|
corresponding_token_depth = nil
|
@@ -634,11 +657,12 @@ class RubyLex
|
|
634
657
|
end
|
635
658
|
next
|
636
659
|
when :on_sp
|
637
|
-
spaces_at_line_head = t
|
660
|
+
spaces_at_line_head = t.tok.count(' ') if is_first_spaces_of_line
|
638
661
|
is_first_spaces_of_line = false
|
639
662
|
next
|
640
663
|
end
|
641
|
-
|
664
|
+
|
665
|
+
case t.event
|
642
666
|
when :on_lbracket, :on_lbrace, :on_lparen, :on_tlambeg
|
643
667
|
spaces_of_nest.push(spaces_at_line_head + open_brace_on_line * 2)
|
644
668
|
open_brace_on_line += 1
|
@@ -651,8 +675,8 @@ class RubyLex
|
|
651
675
|
end
|
652
676
|
open_brace_on_line -= 1
|
653
677
|
when :on_kw
|
654
|
-
next if index > 0 and @tokens[index - 1]
|
655
|
-
case t
|
678
|
+
next if index > 0 and @tokens[index - 1].state.allbits?(Ripper::EXPR_FNAME)
|
679
|
+
case t.tok
|
656
680
|
when 'do'
|
657
681
|
syntax_of_do = take_corresponding_syntax_to_kw_do(@tokens, index)
|
658
682
|
if syntax_of_do == :method_calling
|
@@ -661,16 +685,20 @@ class RubyLex
|
|
661
685
|
when 'def', 'case', 'for', 'begin', 'class', 'module'
|
662
686
|
spaces_of_nest.push(spaces_at_line_head)
|
663
687
|
when 'rescue'
|
664
|
-
unless t
|
688
|
+
unless t.state.allbits?(Ripper::EXPR_LABEL)
|
665
689
|
corresponding_token_depth = spaces_of_nest.last
|
666
690
|
end
|
667
691
|
when 'if', 'unless', 'while', 'until'
|
668
692
|
# postfix if/unless/while/until must be Ripper::EXPR_LABEL
|
669
|
-
unless t
|
693
|
+
unless t.state.allbits?(Ripper::EXPR_LABEL)
|
670
694
|
spaces_of_nest.push(spaces_at_line_head)
|
671
695
|
end
|
672
|
-
when 'else', 'elsif', 'ensure', 'when'
|
696
|
+
when 'else', 'elsif', 'ensure', 'when'
|
673
697
|
corresponding_token_depth = spaces_of_nest.last
|
698
|
+
when 'in'
|
699
|
+
if in_keyword_case_scope?
|
700
|
+
corresponding_token_depth = spaces_of_nest.last
|
701
|
+
end
|
674
702
|
when 'end'
|
675
703
|
if is_first_printable_of_line
|
676
704
|
corresponding_token_depth = spaces_of_nest.pop
|
@@ -692,7 +720,10 @@ class RubyLex
|
|
692
720
|
end_type = []
|
693
721
|
while i < tokens.size
|
694
722
|
t = tokens[i]
|
695
|
-
case t
|
723
|
+
case t.event
|
724
|
+
when *end_type.last
|
725
|
+
start_token.pop
|
726
|
+
end_type.pop
|
696
727
|
when :on_tstring_beg
|
697
728
|
start_token << t
|
698
729
|
end_type << [:on_tstring_end, :on_label_end]
|
@@ -700,10 +731,14 @@ class RubyLex
|
|
700
731
|
start_token << t
|
701
732
|
end_type << :on_regexp_end
|
702
733
|
when :on_symbeg
|
703
|
-
acceptable_single_tokens = %i{on_ident on_const on_op on_cvar on_ivar on_gvar on_kw}
|
704
|
-
if (i + 1) < tokens.size
|
705
|
-
|
706
|
-
|
734
|
+
acceptable_single_tokens = %i{on_ident on_const on_op on_cvar on_ivar on_gvar on_kw on_int on_backtick}
|
735
|
+
if (i + 1) < tokens.size
|
736
|
+
if acceptable_single_tokens.all?{ |st| tokens[i + 1].event != st }
|
737
|
+
start_token << t
|
738
|
+
end_type << :on_tstring_end
|
739
|
+
else
|
740
|
+
i += 1
|
741
|
+
end
|
707
742
|
end
|
708
743
|
when :on_backtick
|
709
744
|
start_token << t
|
@@ -714,20 +749,19 @@ class RubyLex
|
|
714
749
|
when :on_heredoc_beg
|
715
750
|
start_token << t
|
716
751
|
end_type << :on_heredoc_end
|
717
|
-
when *end_type.last
|
718
|
-
start_token.pop
|
719
|
-
end_type.pop
|
720
752
|
end
|
721
753
|
i += 1
|
722
754
|
end
|
723
|
-
start_token.last.nil? ?
|
755
|
+
start_token.last.nil? ? nil : start_token.last
|
724
756
|
end
|
725
757
|
|
726
758
|
def process_literal_type(tokens = @tokens)
|
727
759
|
start_token = check_string_literal(tokens)
|
728
|
-
|
760
|
+
return nil if start_token == ""
|
761
|
+
|
762
|
+
case start_token&.event
|
729
763
|
when :on_tstring_beg
|
730
|
-
case start_token
|
764
|
+
case start_token&.tok
|
731
765
|
when ?" then ?"
|
732
766
|
when /^%.$/ then ?"
|
733
767
|
when /^%Q.$/ then ?"
|
@@ -742,7 +776,7 @@ class RubyLex
|
|
742
776
|
when :on_qsymbols_beg then ?]
|
743
777
|
when :on_symbols_beg then ?]
|
744
778
|
when :on_heredoc_beg
|
745
|
-
start_token
|
779
|
+
start_token&.tok =~ /<<[-~]?(['"`])[_a-zA-Z0-9]+\1/
|
746
780
|
case $1
|
747
781
|
when ?" then ?"
|
748
782
|
when ?' then ?'
|
@@ -754,8 +788,8 @@ class RubyLex
|
|
754
788
|
end
|
755
789
|
end
|
756
790
|
|
757
|
-
def check_termination_in_prev_line(code)
|
758
|
-
tokens = self.class.ripper_lex_without_warning(code)
|
791
|
+
def check_termination_in_prev_line(code, context: nil)
|
792
|
+
tokens = self.class.ripper_lex_without_warning(code, context: context)
|
759
793
|
past_first_newline = false
|
760
794
|
index = tokens.rindex do |t|
|
761
795
|
# traverse first token before last line
|
@@ -770,6 +804,7 @@ class RubyLex
|
|
770
804
|
false
|
771
805
|
end
|
772
806
|
end
|
807
|
+
|
773
808
|
if index
|
774
809
|
first_token = nil
|
775
810
|
last_line_tokens = tokens[(index + 1)..(tokens.size - 1)]
|
@@ -779,6 +814,7 @@ class RubyLex
|
|
779
814
|
break
|
780
815
|
end
|
781
816
|
end
|
817
|
+
|
782
818
|
if first_token.nil?
|
783
819
|
return false
|
784
820
|
elsif first_token && first_token.state == Ripper::EXPR_DOT
|
@@ -798,5 +834,28 @@ class RubyLex
|
|
798
834
|
end
|
799
835
|
false
|
800
836
|
end
|
837
|
+
|
838
|
+
private
|
839
|
+
|
840
|
+
def heredoc_scope?
|
841
|
+
heredoc_tokens = @tokens.select { |t| [:on_heredoc_beg, :on_heredoc_end].include?(t.event) }
|
842
|
+
heredoc_tokens[-1]&.event == :on_heredoc_beg
|
843
|
+
end
|
844
|
+
|
845
|
+
def in_keyword_case_scope?
|
846
|
+
kw_tokens = @tokens.select { |t| t.event == :on_kw && ['case', 'for', 'end'].include?(t.tok) }
|
847
|
+
counter = 0
|
848
|
+
kw_tokens.reverse.each do |t|
|
849
|
+
if t.tok == 'case'
|
850
|
+
return true if counter.zero?
|
851
|
+
counter += 1
|
852
|
+
elsif t.tok == 'for'
|
853
|
+
counter += 1
|
854
|
+
elsif t.tok == 'end'
|
855
|
+
counter -= 1
|
856
|
+
end
|
857
|
+
end
|
858
|
+
false
|
859
|
+
end
|
801
860
|
end
|
802
861
|
# :startdoc:
|
data/lib/irb/version.rb
CHANGED
data/lib/irb/workspace.rb
CHANGED
@@ -12,6 +12,7 @@
|
|
12
12
|
|
13
13
|
require "delegate"
|
14
14
|
|
15
|
+
IRB::TOPLEVEL_BINDING = binding
|
15
16
|
module IRB # :nodoc:
|
16
17
|
class WorkSpace
|
17
18
|
# Creates a new workspace.
|
@@ -57,6 +58,8 @@ EOF
|
|
57
58
|
__FILE__,
|
58
59
|
__LINE__ - 3)
|
59
60
|
when 4 # binding is a copy of TOPLEVEL_BINDING (default)
|
61
|
+
# Note that this will typically be IRB::TOPLEVEL_BINDING
|
62
|
+
# This is to avoid RubyGems' local variables (see issue #17623)
|
60
63
|
@binding = TOPLEVEL_BINDING.dup
|
61
64
|
end
|
62
65
|
end
|