Skip to content

Commit 9704808

Browse files
committed
Heredoc may contain multiple newlines in a single token
Use the start token as the indentation criteria so that it works properly in heredoc. ref. ruby/reline#242
1 parent 88b6542 commit 9704808

File tree

2 files changed

+38
-2
lines changed

2 files changed

+38
-2
lines changed

lib/irb/ruby-lex.rb

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,13 +116,32 @@ def ripper_lex_without_warning(code)
116116
tokens
117117
end
118118

119+
def find_prev_spaces(line_index)
120+
return 0 if @tokens.size == 0
121+
md = @tokens[0][2].match(/(\A +)/)
122+
prev_spaces = md.nil? ? 0 : md[1].count(' ')
123+
line_count = 0
124+
@tokens.each_with_index do |t, i|
125+
if t[2].include?("\n")
126+
line_count += t[2].count("\n")
127+
if line_count >= line_index
128+
return prev_spaces
129+
end
130+
if (@tokens.size - 1) > i
131+
md = @tokens[i + 1][2].match(/(\A +)/)
132+
prev_spaces = md.nil? ? 0 : md[1].count(' ')
133+
end
134+
end
135+
end
136+
prev_spaces
137+
end
138+
119139
def set_auto_indent(context)
120140
if @io.respond_to?(:auto_indent) and context.auto_indent_mode
121141
@io.auto_indent do |lines, line_index, byte_pointer, is_newline|
122142
if is_newline
123-
md = lines[line_index - 1].match(/(\A +)/)
124-
prev_spaces = md.nil? ? 0 : md[1].count(' ')
125143
@tokens = ripper_lex_without_warning(lines[0..line_index].join("\n"))
144+
prev_spaces = find_prev_spaces(line_index)
126145
depth_difference = check_newline_depth_difference
127146
depth_difference = 0 if depth_difference < 0
128147
prev_spaces + depth_difference * 2

test/irb/test_ruby_lex.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,23 @@ def test_corresponding_syntax_to_keyword_do
333333
end
334334
end
335335

336+
def test_heredoc_with_indent
337+
input_with_correct_indents = [
338+
Row.new(%q(<<~Q), nil, 0, 0),
339+
Row.new(%q({), nil, 0, 0),
340+
Row.new(%q( #), nil, 0, 0),
341+
Row.new(%q(}), nil, 0, 0),
342+
]
343+
344+
lines = []
345+
input_with_correct_indents.each do |row|
346+
lines << row.content
347+
assert_indenting(lines, row.current_line_spaces, false)
348+
assert_indenting(lines, row.new_line_spaces, true)
349+
assert_nesting_level(lines, row.nesting_level)
350+
end
351+
end
352+
336353
def test_oneliner_def_in_multiple_lines
337354
input_with_correct_indents = [
338355
Row.new(%q(def a()=[), nil, 4, 2),

0 commit comments

Comments
 (0)