Skip to content

Commit

Permalink
Consider fullwidth take_range in differential rendering
Browse files Browse the repository at this point in the history
  • Loading branch information
tompng committed Nov 14, 2023
1 parent 5adc98d commit 16d68a5
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 11 deletions.
17 changes: 6 additions & 11 deletions lib/reline/line_editor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -373,9 +373,11 @@ def render_line_differential(old_items, new_items)
Reline::IOGate.move_cursor_column base_x
@output.write "\e[0m#{' ' * width}"
else
x, w, content = new_items[level]
content = Reline::Unicode.take_range(content, base_x - x, width) unless x == base_x && w == width
Reline::IOGate.move_cursor_column base_x
x, _w, content = new_items[level]
cover_begin = base_x != 0 && new_levels[base_x - 1] == level
cover_end = new_levels[base_x + width] == level
content, pos = Reline::Unicode.take_mbchar_range(content, base_x - x, width, cover_begin: cover_begin, cover_end: cover_end, padding: true)
Reline::IOGate.move_cursor_column x + pos
@output.write "\e[0m#{content}\e[0m"
end
base_x += width
Expand Down Expand Up @@ -654,13 +656,6 @@ def add_dialog_proc(name, p, context = nil)

DIALOG_DEFAULT_HEIGHT = 20

private def padding_space_with_escape_sequences(str, width)
padding_width = width - calculate_width(str, true)
# padding_width should be only positive value. But macOS and Alacritty returns negative value.
padding_width = 0 if padding_width < 0
str + (' ' * padding_width)
end

private def dialog_range(dialog, dialog_y)
x_range = dialog.column...dialog.column + dialog.width
y_range = dialog_y + dialog.vertical_offset...dialog_y + dialog.vertical_offset + dialog.contents.size
Expand Down Expand Up @@ -734,7 +729,7 @@ def add_dialog_proc(name, p, context = nil)
dialog.contents = contents.map.with_index do |item, i|
line_sgr = i == pointer ? enhanced_sgr : default_sgr
str_width = dialog.width - (scrollbar_pos.nil? ? 0 : @block_elem_width)
str = padding_space_with_escape_sequences(Reline::Unicode.take_range(item, 0, str_width), str_width)
str, = Reline::Unicode.take_mbchar_range(item, 0, str_width, padding: true)
colored_content = "#{line_sgr}#{str}"
if scrollbar_pos
if scrollbar_pos <= (i * 2) and (i * 2 + 1) < (scrollbar_pos + bar_height)
Expand Down
30 changes: 30 additions & 0 deletions test/reline/test_line_editor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,36 @@ def test_dialog_move
end
end

def test_multibyte
base = [0, 12, '一二三一二三']
left = [0, 3, 'LLL']
right = [9, 3, 'RRR']
front = [3, 6, 'FFFFFF']
# 一 FFFFF 三
# 一二三一二三
assert_output '[COL_2]二三一二' do
@line_editor.render_line_differential([base, front], [base, nil])
end

# LLLFFFFF 三
# LLL 三一二三
assert_output '[COL_3] 三一二' do
@line_editor.render_line_differential([base, left, front], [base, left, nil])
end

# 一 FFFFFRRR
# 一二三一 RRR
assert_output '[COL_2]二三一 ' do
@line_editor.render_line_differential([base, right, front], [base, right, nil])
end

# LLLFFFFFRRR
# LLL 三一 RRR
assert_output '[COL_3] 三一 ' do
@line_editor.render_line_differential([base, left, right, front], [base, left, right, nil])
end
end

def test_complex
state_a = [nil, [19, 7, 'bbbbbbb'], [15, 8, 'cccccccc'], [10, 5, 'ddddd'], [18, 4, 'eeee'], [1, 3, 'fff'], [17, 2, 'gg'], [7, 1, 'h']]
state_b = [[5, 9, 'aaaaaaaaa'], nil, [15, 8, 'cccccccc'], nil, [18, 4, 'EEEE'], [25, 4, 'ffff'], [17, 2, 'gg'], [2, 2, 'hh']]
Expand Down

0 comments on commit 16d68a5

Please sign in to comment.