diff --git a/lib/reline.rb b/lib/reline.rb index d440b2d7ba..735a5afad8 100644 --- a/lib/reline.rb +++ b/lib/reline.rb @@ -24,7 +24,7 @@ module Reline end end CursorPos = Struct.new(:x, :y) - DialogRenderInfo = Struct.new(:pos, :contents, :pointer, :bg_color, :width, :height, keyword_init: true) + DialogRenderInfo = Struct.new(:pos, :contents, :pointer, :bg_color, :width, :height, :scrollbar, keyword_init: true) class Core ATTR_READER_NAMES = %i( @@ -228,7 +228,7 @@ module Reline context.clear context.push(cursor_pos_to_render, result, pointer, dialog) end - DialogRenderInfo.new(pos: cursor_pos_to_render, contents: result, pointer: pointer, height: 15) + DialogRenderInfo.new(pos: cursor_pos_to_render, contents: result, pointer: pointer, scrollbar: true, height: 15) } Reline::DEFAULT_DIALOG_CONTEXT = Array.new diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb index d3020087bf..e52c4e5fd3 100644 --- a/lib/reline/line_editor.rb +++ b/lib/reline/line_editor.rb @@ -661,6 +661,13 @@ class Reline::LineEditor reset_dialog(dialog, old_dialog) move_cursor_down(dialog.vertical_offset) Reline::IOGate.move_cursor_column(dialog.column) + if dialog_render_info.scrollbar and dialog_render_info.contents.size > height + bar_max_height = height * 2 + moving_distance = (dialog_render_info.contents.size - height) * 2 + position_ratio = dialog.scroll_top.zero? ? 0.0 : ((dialog.scroll_top * 2).to_f / moving_distance) + bar_height = (bar_max_height * ((dialog.contents.size * 2).to_f / (dialog_render_info.contents.size * 2))).floor.to_i + position = ((bar_max_height - bar_height) * position_ratio).floor.to_i + end dialog.contents.each_with_index do |item, i| if i == pointer bg_color = '45' @@ -672,10 +679,22 @@ class Reline::LineEditor end end str = padding_space_with_escape_sequences(Reline::Unicode.take_range(item, 0, dialog.width), dialog.width) + if dialog_render_info.scrollbar and dialog_render_info.contents.size > height + if position <= (i * 2) and (i * 2) <= (position + bar_height) + str += '█' + elsif position <= (i * 2) and (i * 2 - 1) <= (position + bar_height) + str += '▀' + elsif position <= (i * 2 + 1) and (i * 2) <= (position + bar_height) + str += '▄' + else + str += ' ' + end + end @output.write "\e[#{bg_color}m#{str}\e[49m" Reline::IOGate.move_cursor_column(dialog.column) move_cursor_down(1) if i < (dialog.contents.size - 1) end + dialog.width += 1 if dialog_render_info.scrollbar and dialog_render_info.contents.size > height Reline::IOGate.move_cursor_column(cursor_column) move_cursor_up(dialog.vertical_offset + dialog.contents.size - 1) Reline::IOGate.show_cursor