Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 8 additions & 14 deletions lib/reline/line_editor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1131,23 +1131,17 @@ def just_move_cursor
if Reline::Unicode::CSI_REGEXP.match?(prompt + line_to_render)
@output.write "\e[0m" # clear character decorations
end
visual_lines.each_with_index do |line, index|
visual_lines.each do |line|
Reline::IOGate.move_cursor_column(0)
if line.nil?
if calculate_width(visual_lines[index - 1], true) == Reline::IOGate.get_screen_size.last
Copy link
Member Author

@tompng tompng Sep 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

visual_lines is calculated by Reline::Unicode.split_by_width

screen_width = 4
Reline::Unicode.split_by_width('helloworld', screen_width).first 
# => ["hell", nil, "owor", nil, "ld"]
irb(main):021> Reline::Unicode.split_by_width('Hello World!', screen_width).first 
# => ["Hell", nil, "o Wo", nil, "rld!", nil, ""]
Reline::Unicode.split_by_width('helloあwいoうrlえおd', screen_width).first 
#=> ["hell", nil, "oあw", nil, "いo", nil, "うrl", nil, "えお", nil, "d"]

Odd index value is always nil.
Normally, Even index value except last value satisfies Reline::Unicode.calculate_width(_1) == screen_width.
If there is a fullwidth character, text width might not equal to screen_width.

This condition is always true for halfwidth chars.
I think this condition is trying to check if visual_lines[index - 1] is the last element or not.
It's always non last element because visual_lines[index] is nil and visual_lines[index + 1] is the last element of visual_lines.
So this condition must be true for fullwidth chars too.

# reaches the end of line
if Reline::IOGate.win? and Reline::IOGate.win_legacy_console?
# A newline is automatically inserted if a character is rendered at
# eol on command prompt.
else
# When the cursor is at the end of the line and erases characters
# after the cursor, some terminals delete the character at the
# cursor position.
move_cursor_down(1)
Reline::IOGate.move_cursor_column(0)
end
# reaches the end of line
if Reline::IOGate.win? and Reline::IOGate.win_legacy_console?
# A newline is automatically inserted if a character is rendered at
# eol on command prompt.
else
Reline::IOGate.erase_after_cursor
# When the cursor is at the end of the line and erases characters
# after the cursor, some terminals delete the character at the
# cursor position.
move_cursor_down(1)
Reline::IOGate.move_cursor_column(0)
end
Expand Down
15 changes: 15 additions & 0 deletions test/reline/yamatanooroti/test_rendering.rb
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,21 @@ def test_two_fullwidth
EOC
end

def test_fullwidth_autowrap
start_terminal(10, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
fullwidth_numbers = '0123456789'
write("'#{fullwidth_numbers * 2}-#{fullwidth_numbers * 2}")
close
assert_screen(<<~EOC)
Multiline REPL.
prompt> '01234
5678901234
56789-0123
4567890123
456789
EOC
end

def test_finish_autowrapped_line
start_terminal(10, 40, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
write("[{'user'=>{'email'=>'a@a', 'id'=>'ABC'}, 'version'=>4, 'status'=>'succeeded'}]\n")
Expand Down