mirror of
https://github.com/ruby/ruby.git
synced 2025-08-26 06:25:31 +02:00
[ruby/reline] Separate prompt and input line in rendering
(https://github.com/ruby/reline/pull/652)
* Separate prompt and input line in rendering
Often, only one of prompt and input changes.
Split prompt+input_line to a separate rendering item will improve differential rendering performance.
* Rename method wrapped_prompt_lines to more descriptive name
16d82f1f23
This commit is contained in:
parent
f7d1699f67
commit
53a67efc9a
2 changed files with 19 additions and 12 deletions
|
@ -295,8 +295,8 @@ class Reline::LineEditor
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private def split_by_width(str, max_width)
|
private def split_by_width(str, max_width, offset: 0)
|
||||||
Reline::Unicode.split_by_width(str, max_width, @encoding)
|
Reline::Unicode.split_by_width(str, max_width, @encoding, offset: offset)
|
||||||
end
|
end
|
||||||
|
|
||||||
def current_byte_pointer_cursor
|
def current_byte_pointer_cursor
|
||||||
|
@ -370,7 +370,7 @@ class Reline::LineEditor
|
||||||
@scroll_partial_screen
|
@scroll_partial_screen
|
||||||
end
|
end
|
||||||
|
|
||||||
def wrapped_lines
|
def wrapped_prompt_and_input_lines
|
||||||
with_cache(__method__, @buffer_of_lines.size, modified_lines, prompt_list, screen_width) do |n, lines, prompts, width, prev_cache_key, cached_value|
|
with_cache(__method__, @buffer_of_lines.size, modified_lines, prompt_list, screen_width) do |n, lines, prompts, width, prev_cache_key, cached_value|
|
||||||
prev_n, prev_lines, prev_prompts, prev_width = prev_cache_key
|
prev_n, prev_lines, prev_prompts, prev_width = prev_cache_key
|
||||||
cached_wraps = {}
|
cached_wraps = {}
|
||||||
|
@ -381,9 +381,14 @@ class Reline::LineEditor
|
||||||
end
|
end
|
||||||
|
|
||||||
n.times.map do |i|
|
n.times.map do |i|
|
||||||
prompt = prompts[i]
|
prompt = prompts[i] || ''
|
||||||
line = lines[i]
|
line = lines[i] || ''
|
||||||
cached_wraps[[prompt, line]] || split_by_width("#{prompt}#{line}", width).first.compact
|
if (cached = cached_wraps[[prompt, line]])
|
||||||
|
next cached
|
||||||
|
end
|
||||||
|
*wrapped_prompts, code_line_prompt = split_by_width(prompt, width).first.compact
|
||||||
|
wrapped_lines = split_by_width(line, width, offset: calculate_width(code_line_prompt)).first.compact
|
||||||
|
wrapped_prompts.map { |p| [p, ''] } + [[code_line_prompt, wrapped_lines.first]] + wrapped_lines.drop(1).map { |c| ['', c] }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -426,7 +431,7 @@ class Reline::LineEditor
|
||||||
prompt_width = calculate_width(prompt_list[@line_index], true)
|
prompt_width = calculate_width(prompt_list[@line_index], true)
|
||||||
line_before_cursor = whole_lines[@line_index].byteslice(0, @byte_pointer)
|
line_before_cursor = whole_lines[@line_index].byteslice(0, @byte_pointer)
|
||||||
wrapped_line_before_cursor = split_by_width(' ' * prompt_width + line_before_cursor, screen_width).first.compact
|
wrapped_line_before_cursor = split_by_width(' ' * prompt_width + line_before_cursor, screen_width).first.compact
|
||||||
wrapped_cursor_y = wrapped_lines[0...@line_index].sum(&:size) + wrapped_line_before_cursor.size - 1
|
wrapped_cursor_y = wrapped_prompt_and_input_lines[0...@line_index].sum(&:size) + wrapped_line_before_cursor.size - 1
|
||||||
wrapped_cursor_x = calculate_width(wrapped_line_before_cursor.last)
|
wrapped_cursor_x = calculate_width(wrapped_line_before_cursor.last)
|
||||||
[wrapped_cursor_x, wrapped_cursor_y]
|
[wrapped_cursor_x, wrapped_cursor_y]
|
||||||
end
|
end
|
||||||
|
@ -490,8 +495,9 @@ class Reline::LineEditor
|
||||||
wrapped_cursor_x, wrapped_cursor_y = wrapped_cursor_position
|
wrapped_cursor_x, wrapped_cursor_y = wrapped_cursor_position
|
||||||
|
|
||||||
rendered_lines = @rendered_screen.lines
|
rendered_lines = @rendered_screen.lines
|
||||||
new_lines = wrapped_lines.flatten[screen_scroll_top, screen_height].map do |l|
|
new_lines = wrapped_prompt_and_input_lines.flatten(1)[screen_scroll_top, screen_height].map do |prompt, line|
|
||||||
[[0, Reline::Unicode.calculate_width(l, true), l]]
|
prompt_width = Reline::Unicode.calculate_width(prompt, true)
|
||||||
|
[[0, prompt_width, prompt], [prompt_width, Reline::Unicode.calculate_width(line, true), line]]
|
||||||
end
|
end
|
||||||
if @menu_info
|
if @menu_info
|
||||||
@menu_info.lines(screen_width).each do |item|
|
@menu_info.lines(screen_width).each do |item|
|
||||||
|
@ -507,7 +513,8 @@ class Reline::LineEditor
|
||||||
y_range.each do |row|
|
y_range.each do |row|
|
||||||
next if row < 0 || row >= screen_height
|
next if row < 0 || row >= screen_height
|
||||||
dialog_rows = new_lines[row] ||= []
|
dialog_rows = new_lines[row] ||= []
|
||||||
dialog_rows[index + 1] = [x_range.begin, dialog.width, dialog.contents[row - y_range.begin]]
|
# index 0 is for prompt, index 1 is for line, index 2.. is for dialog
|
||||||
|
dialog_rows[index + 2] = [x_range.begin, dialog.width, dialog.contents[row - y_range.begin]]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -128,10 +128,10 @@ class Reline::Unicode
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.split_by_width(str, max_width, encoding = str.encoding)
|
def self.split_by_width(str, max_width, encoding = str.encoding, offset: 0)
|
||||||
lines = [String.new(encoding: encoding)]
|
lines = [String.new(encoding: encoding)]
|
||||||
height = 1
|
height = 1
|
||||||
width = 0
|
width = offset
|
||||||
rest = str.encode(Encoding::UTF_8)
|
rest = str.encode(Encoding::UTF_8)
|
||||||
in_zero_width = false
|
in_zero_width = false
|
||||||
seq = String.new(encoding: encoding)
|
seq = String.new(encoding: encoding)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue