irb 1.3.7 → 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 +2 -1
- data/lib/irb/cmd/show_source.rb +2 -5
- 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 +119 -75
- data/lib/irb/version.rb +2 -2
- data/lib/irb/workspace.rb +3 -0
- data/lib/irb.rb +20 -5
- data/man/irb.1 +23 -1
- metadata +4 -4
data/lib/irb/ruby-lex.rb
CHANGED
@@ -87,8 +87,8 @@ class RubyLex
|
|
87
87
|
tokens.each do |t|
|
88
88
|
partial_tokens << t
|
89
89
|
unprocessed_tokens << t
|
90
|
-
if t
|
91
|
-
t_str = t
|
90
|
+
if t.tok.include?("\n")
|
91
|
+
t_str = t.tok
|
92
92
|
t_str.each_line("\n") do |s|
|
93
93
|
code << s << "\n"
|
94
94
|
ltype, indent, continue, code_block_open = check_state(code, partial_tokens, context: context)
|
@@ -97,9 +97,10 @@ class RubyLex
|
|
97
97
|
end
|
98
98
|
unprocessed_tokens = []
|
99
99
|
else
|
100
|
-
code << t
|
100
|
+
code << t.tok
|
101
101
|
end
|
102
102
|
end
|
103
|
+
|
103
104
|
unless unprocessed_tokens.empty?
|
104
105
|
ltype, indent, continue, code_block_open = check_state(code, unprocessed_tokens, context: context)
|
105
106
|
result << @prompt.call(ltype, indent, continue || code_block_open, @line_no + line_num_offset)
|
@@ -107,6 +108,7 @@ class RubyLex
|
|
107
108
|
result
|
108
109
|
end
|
109
110
|
end
|
111
|
+
|
110
112
|
if p.respond_to?(:call)
|
111
113
|
@input = p
|
112
114
|
elsif block_given?
|
@@ -153,19 +155,19 @@ class RubyLex
|
|
153
155
|
pos_to_index = {}
|
154
156
|
lexer.scan.each do |t|
|
155
157
|
next if t.pos.first == 0
|
156
|
-
if pos_to_index.has_key?(t
|
157
|
-
index = pos_to_index[t
|
158
|
+
if pos_to_index.has_key?(t.pos)
|
159
|
+
index = pos_to_index[t.pos]
|
158
160
|
found_tk = tokens[index]
|
159
|
-
if ERROR_TOKENS.include?(found_tk
|
161
|
+
if ERROR_TOKENS.include?(found_tk.event) && !ERROR_TOKENS.include?(t.event)
|
160
162
|
tokens[index] = t
|
161
163
|
end
|
162
164
|
else
|
163
|
-
pos_to_index[t
|
165
|
+
pos_to_index[t.pos] = tokens.size
|
164
166
|
tokens << t
|
165
167
|
end
|
166
168
|
end
|
167
169
|
else
|
168
|
-
tokens = lexer.parse
|
170
|
+
tokens = lexer.parse.reject { |it| it.pos.first == 0 }
|
169
171
|
end
|
170
172
|
end
|
171
173
|
tokens
|
@@ -175,17 +177,17 @@ class RubyLex
|
|
175
177
|
|
176
178
|
def find_prev_spaces(line_index)
|
177
179
|
return 0 if @tokens.size == 0
|
178
|
-
md = @tokens[0]
|
180
|
+
md = @tokens[0].tok.match(/(\A +)/)
|
179
181
|
prev_spaces = md.nil? ? 0 : md[1].count(' ')
|
180
182
|
line_count = 0
|
181
183
|
@tokens.each_with_index do |t, i|
|
182
|
-
if t
|
183
|
-
line_count += t
|
184
|
+
if t.tok.include?("\n")
|
185
|
+
line_count += t.tok.count("\n")
|
184
186
|
if line_count >= line_index
|
185
187
|
return prev_spaces
|
186
188
|
end
|
187
189
|
if (@tokens.size - 1) > i
|
188
|
-
md = @tokens[i + 1]
|
190
|
+
md = @tokens[i + 1].tok.match(/(\A +)/)
|
189
191
|
prev_spaces = md.nil? ? 0 : md[1].count(' ')
|
190
192
|
end
|
191
193
|
end
|
@@ -207,7 +209,7 @@ class RubyLex
|
|
207
209
|
last_line = lines[line_index]&.byteslice(0, byte_pointer)
|
208
210
|
code += last_line if last_line
|
209
211
|
@tokens = self.class.ripper_lex_without_warning(code, context: context)
|
210
|
-
corresponding_token_depth = check_corresponding_token_depth
|
212
|
+
corresponding_token_depth = check_corresponding_token_depth(lines, line_index)
|
211
213
|
if corresponding_token_depth
|
212
214
|
corresponding_token_depth
|
213
215
|
else
|
@@ -295,18 +297,18 @@ class RubyLex
|
|
295
297
|
|
296
298
|
def process_continue(tokens = @tokens)
|
297
299
|
# last token is always newline
|
298
|
-
if tokens.size >= 2 and tokens[-2]
|
300
|
+
if tokens.size >= 2 and tokens[-2].event == :on_regexp_end
|
299
301
|
# end of regexp literal
|
300
302
|
return false
|
301
|
-
elsif tokens.size >= 2 and tokens[-2]
|
303
|
+
elsif tokens.size >= 2 and tokens[-2].event == :on_semicolon
|
302
304
|
return false
|
303
|
-
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)
|
304
306
|
return false
|
305
|
-
elsif !tokens.empty? and tokens.last
|
307
|
+
elsif !tokens.empty? and tokens.last.tok == "\\\n"
|
306
308
|
return true
|
307
|
-
elsif tokens.size >= 1 and tokens[-1]
|
309
|
+
elsif tokens.size >= 1 and tokens[-1].event == :on_heredoc_end # "EOH\n"
|
308
310
|
return false
|
309
|
-
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/
|
310
312
|
# end of literal except for regexp
|
311
313
|
# endless range at end of line is not a continue
|
312
314
|
return true
|
@@ -316,7 +318,7 @@ class RubyLex
|
|
316
318
|
|
317
319
|
def check_code_block(code, tokens = @tokens)
|
318
320
|
return true if tokens.empty?
|
319
|
-
if tokens.last
|
321
|
+
if tokens.last.event == :on_heredoc_beg
|
320
322
|
return true
|
321
323
|
end
|
322
324
|
|
@@ -388,7 +390,7 @@ class RubyLex
|
|
388
390
|
end
|
389
391
|
|
390
392
|
if defined?(Ripper::EXPR_BEG)
|
391
|
-
last_lex_state = tokens.last
|
393
|
+
last_lex_state = tokens.last.state
|
392
394
|
if last_lex_state.allbits?(Ripper::EXPR_BEG)
|
393
395
|
return false
|
394
396
|
elsif last_lex_state.allbits?(Ripper::EXPR_DOT)
|
@@ -413,14 +415,14 @@ class RubyLex
|
|
413
415
|
tokens.each_with_index { |t, index|
|
414
416
|
# detecting one-liner method definition
|
415
417
|
if in_oneliner_def.nil?
|
416
|
-
if t
|
418
|
+
if t.state.allbits?(Ripper::EXPR_ENDFN)
|
417
419
|
in_oneliner_def = :ENDFN
|
418
420
|
end
|
419
421
|
else
|
420
|
-
if t
|
422
|
+
if t.state.allbits?(Ripper::EXPR_ENDFN)
|
421
423
|
# continuing
|
422
|
-
elsif t
|
423
|
-
if t
|
424
|
+
elsif t.state.allbits?(Ripper::EXPR_BEG)
|
425
|
+
if t.tok == '='
|
424
426
|
in_oneliner_def = :BODY
|
425
427
|
end
|
426
428
|
else
|
@@ -432,14 +434,14 @@ class RubyLex
|
|
432
434
|
end
|
433
435
|
end
|
434
436
|
|
435
|
-
case t
|
437
|
+
case t.event
|
436
438
|
when :on_lbracket, :on_lbrace, :on_lparen, :on_tlambeg
|
437
439
|
indent += 1
|
438
440
|
when :on_rbracket, :on_rbrace, :on_rparen
|
439
441
|
indent -= 1
|
440
442
|
when :on_kw
|
441
|
-
next if index > 0 and tokens[index - 1]
|
442
|
-
case t
|
443
|
+
next if index > 0 and tokens[index - 1].state.allbits?(Ripper::EXPR_FNAME)
|
444
|
+
case t.tok
|
443
445
|
when 'do'
|
444
446
|
syntax_of_do = take_corresponding_syntax_to_kw_do(tokens, index)
|
445
447
|
indent += 1 if syntax_of_do == :method_calling
|
@@ -447,7 +449,7 @@ class RubyLex
|
|
447
449
|
indent += 1
|
448
450
|
when 'if', 'unless', 'while', 'until'
|
449
451
|
# postfix if/unless/while/until must be Ripper::EXPR_LABEL
|
450
|
-
indent += 1 unless t
|
452
|
+
indent += 1 unless t.state.allbits?(Ripper::EXPR_LABEL)
|
451
453
|
when 'end'
|
452
454
|
indent -= 1
|
453
455
|
end
|
@@ -459,14 +461,14 @@ class RubyLex
|
|
459
461
|
|
460
462
|
def is_method_calling?(tokens, index)
|
461
463
|
tk = tokens[index]
|
462
|
-
if tk
|
464
|
+
if tk.state.anybits?(Ripper::EXPR_CMDARG) and tk.event == :on_ident
|
463
465
|
# The target method call to pass the block with "do".
|
464
466
|
return true
|
465
|
-
elsif tk
|
466
|
-
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 }
|
467
469
|
if non_sp_index
|
468
470
|
prev_tk = tokens[non_sp_index]
|
469
|
-
if prev_tk
|
471
|
+
if prev_tk.state.anybits?(Ripper::EXPR_DOT) and prev_tk.event == :on_period
|
470
472
|
# The target method call with receiver to pass the block with "do".
|
471
473
|
return true
|
472
474
|
end
|
@@ -477,21 +479,21 @@ class RubyLex
|
|
477
479
|
|
478
480
|
def take_corresponding_syntax_to_kw_do(tokens, index)
|
479
481
|
syntax_of_do = nil
|
480
|
-
# Finding a syntax
|
482
|
+
# Finding a syntax corresponding to "do".
|
481
483
|
index.downto(0) do |i|
|
482
484
|
tk = tokens[i]
|
483
485
|
# In "continue", the token isn't the corresponding syntax to "do".
|
484
|
-
non_sp_index = tokens[0..(i - 1)].rindex{ |t| t
|
486
|
+
non_sp_index = tokens[0..(i - 1)].rindex{ |t| t.event != :on_sp }
|
485
487
|
first_in_fomula = false
|
486
488
|
if non_sp_index.nil?
|
487
489
|
first_in_fomula = true
|
488
|
-
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)
|
489
491
|
first_in_fomula = true
|
490
492
|
end
|
491
493
|
if is_method_calling?(tokens, i)
|
492
494
|
syntax_of_do = :method_calling
|
493
495
|
break if first_in_fomula
|
494
|
-
elsif tk
|
496
|
+
elsif tk.event == :on_kw && %w{while until for}.include?(tk.tok)
|
495
497
|
# A loop syntax in front of "do" found.
|
496
498
|
#
|
497
499
|
# while cond do # also "until" or "for"
|
@@ -508,18 +510,18 @@ class RubyLex
|
|
508
510
|
|
509
511
|
def is_the_in_correspond_to_a_for(tokens, index)
|
510
512
|
syntax_of_in = nil
|
511
|
-
# Finding a syntax
|
513
|
+
# Finding a syntax corresponding to "do".
|
512
514
|
index.downto(0) do |i|
|
513
515
|
tk = tokens[i]
|
514
516
|
# In "continue", the token isn't the corresponding syntax to "do".
|
515
|
-
non_sp_index = tokens[0..(i - 1)].rindex{ |t| t
|
517
|
+
non_sp_index = tokens[0..(i - 1)].rindex{ |t| t.event != :on_sp }
|
516
518
|
first_in_fomula = false
|
517
519
|
if non_sp_index.nil?
|
518
520
|
first_in_fomula = true
|
519
|
-
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)
|
520
522
|
first_in_fomula = true
|
521
523
|
end
|
522
|
-
if tk
|
524
|
+
if tk.event == :on_kw && tk.tok == 'for'
|
523
525
|
# A loop syntax in front of "do" found.
|
524
526
|
#
|
525
527
|
# while cond do # also "until" or "for"
|
@@ -541,14 +543,14 @@ class RubyLex
|
|
541
543
|
@tokens.each_with_index do |t, index|
|
542
544
|
# detecting one-liner method definition
|
543
545
|
if in_oneliner_def.nil?
|
544
|
-
if t
|
546
|
+
if t.state.allbits?(Ripper::EXPR_ENDFN)
|
545
547
|
in_oneliner_def = :ENDFN
|
546
548
|
end
|
547
549
|
else
|
548
|
-
if t
|
550
|
+
if t.state.allbits?(Ripper::EXPR_ENDFN)
|
549
551
|
# continuing
|
550
|
-
elsif t
|
551
|
-
if t
|
552
|
+
elsif t.state.allbits?(Ripper::EXPR_BEG)
|
553
|
+
if t.tok == '='
|
552
554
|
in_oneliner_def = :BODY
|
553
555
|
end
|
554
556
|
else
|
@@ -560,7 +562,7 @@ class RubyLex
|
|
560
562
|
end
|
561
563
|
end
|
562
564
|
|
563
|
-
case t
|
565
|
+
case t.event
|
564
566
|
when :on_ignored_nl, :on_nl, :on_comment
|
565
567
|
if index != (@tokens.size - 1) and in_oneliner_def != :BODY
|
566
568
|
depth_difference = 0
|
@@ -570,15 +572,16 @@ class RubyLex
|
|
570
572
|
when :on_sp
|
571
573
|
next
|
572
574
|
end
|
573
|
-
|
575
|
+
|
576
|
+
case t.event
|
574
577
|
when :on_lbracket, :on_lbrace, :on_lparen, :on_tlambeg
|
575
578
|
depth_difference += 1
|
576
579
|
open_brace_on_line += 1
|
577
580
|
when :on_rbracket, :on_rbrace, :on_rparen
|
578
581
|
depth_difference -= 1 if open_brace_on_line > 0
|
579
582
|
when :on_kw
|
580
|
-
next if index > 0 and @tokens[index - 1]
|
581
|
-
case t
|
583
|
+
next if index > 0 and @tokens[index - 1].state.allbits?(Ripper::EXPR_FNAME)
|
584
|
+
case t.tok
|
582
585
|
when 'do'
|
583
586
|
syntax_of_do = take_corresponding_syntax_to_kw_do(@tokens, index)
|
584
587
|
depth_difference += 1 if syntax_of_do == :method_calling
|
@@ -586,7 +589,7 @@ class RubyLex
|
|
586
589
|
depth_difference += 1
|
587
590
|
when 'if', 'unless', 'while', 'until', 'rescue'
|
588
591
|
# postfix if/unless/while/until/rescue must be Ripper::EXPR_LABEL
|
589
|
-
unless t
|
592
|
+
unless t.state.allbits?(Ripper::EXPR_LABEL)
|
590
593
|
depth_difference += 1
|
591
594
|
end
|
592
595
|
when 'else', 'elsif', 'ensure', 'when'
|
@@ -603,7 +606,7 @@ class RubyLex
|
|
603
606
|
depth_difference
|
604
607
|
end
|
605
608
|
|
606
|
-
def check_corresponding_token_depth
|
609
|
+
def check_corresponding_token_depth(lines, line_index)
|
607
610
|
corresponding_token_depth = nil
|
608
611
|
is_first_spaces_of_line = true
|
609
612
|
is_first_printable_of_line = true
|
@@ -611,17 +614,22 @@ class RubyLex
|
|
611
614
|
spaces_at_line_head = 0
|
612
615
|
open_brace_on_line = 0
|
613
616
|
in_oneliner_def = nil
|
617
|
+
|
618
|
+
if heredoc_scope?
|
619
|
+
return lines[line_index][/^ */].length
|
620
|
+
end
|
621
|
+
|
614
622
|
@tokens.each_with_index do |t, index|
|
615
623
|
# detecting one-liner method definition
|
616
624
|
if in_oneliner_def.nil?
|
617
|
-
if t
|
625
|
+
if t.state.allbits?(Ripper::EXPR_ENDFN)
|
618
626
|
in_oneliner_def = :ENDFN
|
619
627
|
end
|
620
628
|
else
|
621
|
-
if t
|
629
|
+
if t.state.allbits?(Ripper::EXPR_ENDFN)
|
622
630
|
# continuing
|
623
|
-
elsif t
|
624
|
-
if t
|
631
|
+
elsif t.state.allbits?(Ripper::EXPR_BEG)
|
632
|
+
if t.tok == '='
|
625
633
|
in_oneliner_def = :BODY
|
626
634
|
end
|
627
635
|
else
|
@@ -638,7 +646,7 @@ class RubyLex
|
|
638
646
|
end
|
639
647
|
end
|
640
648
|
|
641
|
-
case t
|
649
|
+
case t.event
|
642
650
|
when :on_ignored_nl, :on_nl, :on_comment
|
643
651
|
if in_oneliner_def != :BODY
|
644
652
|
corresponding_token_depth = nil
|
@@ -649,11 +657,12 @@ class RubyLex
|
|
649
657
|
end
|
650
658
|
next
|
651
659
|
when :on_sp
|
652
|
-
spaces_at_line_head = t
|
660
|
+
spaces_at_line_head = t.tok.count(' ') if is_first_spaces_of_line
|
653
661
|
is_first_spaces_of_line = false
|
654
662
|
next
|
655
663
|
end
|
656
|
-
|
664
|
+
|
665
|
+
case t.event
|
657
666
|
when :on_lbracket, :on_lbrace, :on_lparen, :on_tlambeg
|
658
667
|
spaces_of_nest.push(spaces_at_line_head + open_brace_on_line * 2)
|
659
668
|
open_brace_on_line += 1
|
@@ -666,8 +675,8 @@ class RubyLex
|
|
666
675
|
end
|
667
676
|
open_brace_on_line -= 1
|
668
677
|
when :on_kw
|
669
|
-
next if index > 0 and @tokens[index - 1]
|
670
|
-
case t
|
678
|
+
next if index > 0 and @tokens[index - 1].state.allbits?(Ripper::EXPR_FNAME)
|
679
|
+
case t.tok
|
671
680
|
when 'do'
|
672
681
|
syntax_of_do = take_corresponding_syntax_to_kw_do(@tokens, index)
|
673
682
|
if syntax_of_do == :method_calling
|
@@ -676,16 +685,20 @@ class RubyLex
|
|
676
685
|
when 'def', 'case', 'for', 'begin', 'class', 'module'
|
677
686
|
spaces_of_nest.push(spaces_at_line_head)
|
678
687
|
when 'rescue'
|
679
|
-
unless t
|
688
|
+
unless t.state.allbits?(Ripper::EXPR_LABEL)
|
680
689
|
corresponding_token_depth = spaces_of_nest.last
|
681
690
|
end
|
682
691
|
when 'if', 'unless', 'while', 'until'
|
683
692
|
# postfix if/unless/while/until must be Ripper::EXPR_LABEL
|
684
|
-
unless t
|
693
|
+
unless t.state.allbits?(Ripper::EXPR_LABEL)
|
685
694
|
spaces_of_nest.push(spaces_at_line_head)
|
686
695
|
end
|
687
|
-
when 'else', 'elsif', 'ensure', 'when'
|
696
|
+
when 'else', 'elsif', 'ensure', 'when'
|
688
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
|
689
702
|
when 'end'
|
690
703
|
if is_first_printable_of_line
|
691
704
|
corresponding_token_depth = spaces_of_nest.pop
|
@@ -707,7 +720,10 @@ class RubyLex
|
|
707
720
|
end_type = []
|
708
721
|
while i < tokens.size
|
709
722
|
t = tokens[i]
|
710
|
-
case t
|
723
|
+
case t.event
|
724
|
+
when *end_type.last
|
725
|
+
start_token.pop
|
726
|
+
end_type.pop
|
711
727
|
when :on_tstring_beg
|
712
728
|
start_token << t
|
713
729
|
end_type << [:on_tstring_end, :on_label_end]
|
@@ -715,10 +731,14 @@ class RubyLex
|
|
715
731
|
start_token << t
|
716
732
|
end_type << :on_regexp_end
|
717
733
|
when :on_symbeg
|
718
|
-
acceptable_single_tokens = %i{on_ident on_const on_op on_cvar on_ivar on_gvar on_kw on_int}
|
719
|
-
if (i + 1) < tokens.size
|
720
|
-
|
721
|
-
|
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
|
722
742
|
end
|
723
743
|
when :on_backtick
|
724
744
|
start_token << t
|
@@ -729,20 +749,19 @@ class RubyLex
|
|
729
749
|
when :on_heredoc_beg
|
730
750
|
start_token << t
|
731
751
|
end_type << :on_heredoc_end
|
732
|
-
when *end_type.last
|
733
|
-
start_token.pop
|
734
|
-
end_type.pop
|
735
752
|
end
|
736
753
|
i += 1
|
737
754
|
end
|
738
|
-
start_token.last.nil? ?
|
755
|
+
start_token.last.nil? ? nil : start_token.last
|
739
756
|
end
|
740
757
|
|
741
758
|
def process_literal_type(tokens = @tokens)
|
742
759
|
start_token = check_string_literal(tokens)
|
743
|
-
|
760
|
+
return nil if start_token == ""
|
761
|
+
|
762
|
+
case start_token&.event
|
744
763
|
when :on_tstring_beg
|
745
|
-
case start_token
|
764
|
+
case start_token&.tok
|
746
765
|
when ?" then ?"
|
747
766
|
when /^%.$/ then ?"
|
748
767
|
when /^%Q.$/ then ?"
|
@@ -757,7 +776,7 @@ class RubyLex
|
|
757
776
|
when :on_qsymbols_beg then ?]
|
758
777
|
when :on_symbols_beg then ?]
|
759
778
|
when :on_heredoc_beg
|
760
|
-
start_token
|
779
|
+
start_token&.tok =~ /<<[-~]?(['"`])[_a-zA-Z0-9]+\1/
|
761
780
|
case $1
|
762
781
|
when ?" then ?"
|
763
782
|
when ?' then ?'
|
@@ -785,6 +804,7 @@ class RubyLex
|
|
785
804
|
false
|
786
805
|
end
|
787
806
|
end
|
807
|
+
|
788
808
|
if index
|
789
809
|
first_token = nil
|
790
810
|
last_line_tokens = tokens[(index + 1)..(tokens.size - 1)]
|
@@ -794,6 +814,7 @@ class RubyLex
|
|
794
814
|
break
|
795
815
|
end
|
796
816
|
end
|
817
|
+
|
797
818
|
if first_token.nil?
|
798
819
|
return false
|
799
820
|
elsif first_token && first_token.state == Ripper::EXPR_DOT
|
@@ -813,5 +834,28 @@ class RubyLex
|
|
813
834
|
end
|
814
835
|
false
|
815
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
|
816
860
|
end
|
817
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
|
data/lib/irb.rb
CHANGED
@@ -62,8 +62,15 @@ require_relative "irb/easter-egg"
|
|
62
62
|
# -W[level=2] Same as `ruby -W`
|
63
63
|
# --context-mode n Set n[0-4] to method to create Binding Object,
|
64
64
|
# when new workspace was created
|
65
|
-
# --
|
65
|
+
# --extra-doc-dir Add an extra doc dir for the doc dialog
|
66
|
+
# --echo Show result (default)
|
66
67
|
# --noecho Don't show result
|
68
|
+
# --echo-on-assignment
|
69
|
+
# Show result on assignment
|
70
|
+
# --noecho-on-assignment
|
71
|
+
# Don't show result on assignment
|
72
|
+
# --truncate-echo-on-assignment
|
73
|
+
# Show truncated result on assignment (default)
|
67
74
|
# --inspect Use `inspect' for output
|
68
75
|
# --noinspect Don't use inspect for output
|
69
76
|
# --multiline Use multiline editor module
|
@@ -72,6 +79,8 @@ require_relative "irb/easter-egg"
|
|
72
79
|
# --nosingleline Don't use singleline editor module
|
73
80
|
# --colorize Use colorization
|
74
81
|
# --nocolorize Don't use colorization
|
82
|
+
# --autocomplete Use autocompletion
|
83
|
+
# --noautocomplete Don't use autocompletion
|
75
84
|
# --prompt prompt-mode/--prompt-mode prompt-mode
|
76
85
|
# Switch prompt mode. Pre-defined prompt modes are
|
77
86
|
# `default', `simple', `xmp' and `inf-ruby'
|
@@ -114,6 +123,7 @@ require_relative "irb/easter-egg"
|
|
114
123
|
# IRB.conf[:USE_SINGLELINE] = nil
|
115
124
|
# IRB.conf[:USE_COLORIZE] = true
|
116
125
|
# IRB.conf[:USE_TRACER] = false
|
126
|
+
# IRB.conf[:USE_AUTOCOMPLETE] = true
|
117
127
|
# IRB.conf[:IGNORE_SIGINT] = true
|
118
128
|
# IRB.conf[:IGNORE_EOF] = false
|
119
129
|
# IRB.conf[:PROMPT_MODE] = :DEFAULT
|
@@ -604,7 +614,7 @@ module IRB
|
|
604
614
|
ret = conv.primitive_convert(str, dst)
|
605
615
|
case ret
|
606
616
|
when :invalid_byte_sequence
|
607
|
-
conv.insert_output(
|
617
|
+
conv.insert_output(conv.primitive_errinfo[3].dump[1..-2])
|
608
618
|
redo
|
609
619
|
when :undefined_conversion
|
610
620
|
c = conv.primitive_errinfo[3].dup.force_encoding(conv.primitive_errinfo[1])
|
@@ -666,6 +676,8 @@ module IRB
|
|
666
676
|
lines = lines.reverse if order == :bottom
|
667
677
|
lines.map{ |l| l + "\n" }.join
|
668
678
|
}
|
679
|
+
# The "<top (required)>" in "(irb)" may be the top level of IRB so imitate the main object.
|
680
|
+
message = message.gsub(/\(irb\):(?<num>\d+):in `<(?<frame>top \(required\))>'/) { "(irb):#{$~[:num]}:in `<main>'" }
|
669
681
|
puts message
|
670
682
|
end
|
671
683
|
print "Maybe IRB bug!\n" if irb_bug
|
@@ -812,17 +824,20 @@ module IRB
|
|
812
824
|
diff_size = output_width - Reline::Unicode.calculate_width(first_line, true)
|
813
825
|
if diff_size.positive? and output_width > winwidth
|
814
826
|
lines, _ = Reline::Unicode.split_by_width(first_line, winwidth - diff_size - 3)
|
815
|
-
str = "%s
|
827
|
+
str = "%s..." % lines.first
|
828
|
+
str += "\e[0m" if @context.use_colorize
|
816
829
|
multiline_p = false
|
817
830
|
else
|
818
831
|
str = str.gsub(/(\A.*?\n).*/m, "\\1...")
|
832
|
+
str += "\e[0m" if @context.use_colorize
|
819
833
|
end
|
820
834
|
else
|
821
835
|
output_width = Reline::Unicode.calculate_width(@context.return_format % str, true)
|
822
836
|
diff_size = output_width - Reline::Unicode.calculate_width(str, true)
|
823
837
|
if diff_size.positive? and output_width > winwidth
|
824
838
|
lines, _ = Reline::Unicode.split_by_width(str, winwidth - diff_size - 3)
|
825
|
-
str = "%s
|
839
|
+
str = "%s..." % lines.first
|
840
|
+
str += "\e[0m" if @context.use_colorize
|
826
841
|
end
|
827
842
|
end
|
828
843
|
end
|
@@ -856,7 +871,7 @@ module IRB
|
|
856
871
|
|
857
872
|
# If the expression is invalid, Ripper.sexp should return nil which will
|
858
873
|
# result in false being returned. Any valid expression should return an
|
859
|
-
# s-expression where the second
|
874
|
+
# s-expression where the second element of the top level array is an
|
860
875
|
# array of parsed expressions. The first element of each expression is the
|
861
876
|
# expression's type.
|
862
877
|
verbose, $VERBOSE = $VERBOSE, nil
|
data/man/irb.1
CHANGED
@@ -18,6 +18,7 @@
|
|
18
18
|
.Op Fl - Ns Oo no Oc Ns singleline
|
19
19
|
.Op Fl - Ns Oo no Oc Ns echo
|
20
20
|
.Op Fl - Ns Oo no Oc Ns colorize
|
21
|
+
.Op Fl - Ns Oo no Oc Ns autocomplete
|
21
22
|
.Op Fl - Ns Oo no Oc Ns verbose
|
22
23
|
.Op Fl -prompt Ar mode
|
23
24
|
.Op Fl -prompt-mode Ar mode
|
@@ -104,13 +105,27 @@ Uses singleline editor module.
|
|
104
105
|
Doesn't use singleline editor module.
|
105
106
|
.Pp
|
106
107
|
.Pp
|
108
|
+
.It Fl -extra-doc-dir
|
109
|
+
Add an extra doc dir for the doc dialog.
|
110
|
+
.Pp
|
111
|
+
.Pp
|
107
112
|
.It Fl -echo
|
108
|
-
Show result(default).
|
113
|
+
Show result (default).
|
109
114
|
.Pp
|
110
115
|
.It Fl -noecho
|
111
116
|
Don't show result.
|
112
117
|
.Pp
|
113
118
|
.Pp
|
119
|
+
.It Fl -echo-on-assignment
|
120
|
+
Show result on assignment.
|
121
|
+
.Pp
|
122
|
+
.It Fl -noecho-on-assignment
|
123
|
+
Don't show result on assignment.
|
124
|
+
.Pp
|
125
|
+
.It Fl -truncate-echo-on-assignment
|
126
|
+
Show truncated result on assignment (default).
|
127
|
+
.Pp
|
128
|
+
.Pp
|
114
129
|
.It Fl -colorize
|
115
130
|
Use colorization.
|
116
131
|
.Pp
|
@@ -118,6 +133,13 @@ Use colorization.
|
|
118
133
|
Don't use colorization.
|
119
134
|
.Pp
|
120
135
|
.Pp
|
136
|
+
.It Fl -autocomplete
|
137
|
+
Use autocompletion.
|
138
|
+
.Pp
|
139
|
+
.It Fl -noautocomplete
|
140
|
+
Don't use autocompletion.
|
141
|
+
.Pp
|
142
|
+
.Pp
|
121
143
|
.It Fl -verbose
|
122
144
|
Show details.
|
123
145
|
.Pp
|