Skip to content

Commit 8895e4f

Browse files
committed
Re-implement prev_spaces feature for pasted code
1 parent 540b64c commit 8895e4f

File tree

2 files changed

+51
-5
lines changed

2 files changed

+51
-5
lines changed

lib/irb/ruby-lex.rb

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,23 @@ def free_indent_token?(token)
356356
%i[on_tstring_beg on_backtick on_regexp_beg on_symbeg].include?(token.event)
357357
end
358358

359+
def indent_difference(lines, line_results, open_token)
360+
return 0 unless open_token
361+
loop do
362+
line_index = open_token.pos[0] - 1
363+
_tokens, prev_opens, _next_opens, min_depth = line_results[line_index]
364+
indent_level, _nesting_level = calc_nesting_depth(prev_opens.take(min_depth))
365+
calculated_indent = 2 * indent_level
366+
open_token = prev_opens.last
367+
if !open_token || (open_token.event != :on_heredoc_beg && !free_indent_token?(open_token))
368+
actual_indent = lines[line_index][/^ */].size
369+
return actual_indent - calculated_indent
370+
elsif open_token.event == :on_heredoc_beg && open_token.tok.match?(/^<<[^-~]/)
371+
return 0
372+
end
373+
end
374+
end
375+
359376
def process_indent_level(tokens, lines, line_index, is_newline)
360377
line_results = IRB::NestingParser.parse_by_line(tokens)
361378
result = line_results[line_index]
@@ -374,10 +391,16 @@ def process_indent_level(tokens, lines, line_index, is_newline)
374391

375392
preserve_indent = lines[line_index - (is_newline ? 1 : 0)][/^ */].size
376393

394+
# Calculates base indent for pasted code
395+
# irb(main):001:1* if 1 # Base indent is 4
396+
# irb(main):002:1* 2
397+
# irb(main):003:0> end
398+
base_indent = [0, indent_difference(lines, line_results, prev_opens.last)].max
399+
377400
if free_indent_token?(prev_opens.last)
378401
if is_newline && prev_opens.last.pos[0] == line_index
379402
# First newline inside free-indent token
380-
indent
403+
base_indent + indent
381404
else
382405
# Accept any number of indent inside free-indent token
383406
preserve_indent
@@ -395,21 +418,21 @@ def process_indent_level(tokens, lines, line_index, is_newline)
395418
if prev_opens.size < next_opens.size || prev_opens.last == next_opens.last
396419
if is_newline && lines[line_index].empty? && line_results[line_index - 1][1].last != prev_opens.last
397420
# First line in heredoc
398-
indent
421+
tok.match?(/^<<[-~]/) ? base_indent + indent : indent
399422
elsif tok.match?(/^<<~/)
400423
# Accept extra indent spaces inside `<<~` heredoc
401-
[indent, preserve_indent].max
424+
[base_indent + indent, preserve_indent].max
402425
else
403426
# Accept any number of indent inside other heredoc
404427
preserve_indent
405428
end
406429
else
407430
# Heredoc close
408431
prev_line_indent_level, _prev_line_nesting_level = calc_nesting_depth(prev_opens)
409-
tok.match?(/^<<[~-]/) ? 2 * (prev_line_indent_level - 1) : 0
432+
tok.match?(/^<<[~-]/) ? base_indent + 2 * (prev_line_indent_level - 1) : 0
410433
end
411434
else
412-
indent
435+
base_indent + indent
413436
end
414437
end
415438

test/irb/test_ruby_lex.rb

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,29 @@ def dynamic_prompt(&block)
654654
end
655655
end
656656

657+
def test_pasted_code_keep_base_indent_spaces
658+
input_with_correct_indents = [
659+
Row.new(%q( def foo), 0, 6, 1),
660+
Row.new(%q( if bar), 6, 10, 2),
661+
Row.new(%q( [1), 10, 12, 3),
662+
Row.new(%q( ]+[["a), 10, 14, 4),
663+
Row.new(%q(b" + `c), 0, 16, 5),
664+
Row.new(%q(d`.tap do), 0, 16, 5),
665+
Row.new(%q( 1), 16, 16, 5),
666+
Row.new(%q( end), 14, 14, 4),
667+
Row.new(%q( ]), 12, 12, 3),
668+
Row.new(%q( ]), 10, 10, 2),
669+
Row.new(%q( end), 8, 6, 1),
670+
Row.new(%q( end), 4, 0, 0),
671+
]
672+
lines = []
673+
input_with_correct_indents.each do |row|
674+
lines << row.content
675+
assert_row_indenting(lines, row)
676+
assert_nesting_level(lines, row.nesting_level)
677+
end
678+
end
679+
657680
def assert_dynamic_prompt(lines, expected_prompt_list)
658681
pend if RUBY_ENGINE == 'truffleruby'
659682
context = build_context

0 commit comments

Comments
 (0)