From 53c5b9e8b009cff5e4234502155ab50333cbc755 Mon Sep 17 00:00:00 2001 From: tompng Date: Wed, 29 Nov 2023 22:37:49 +0900 Subject: [PATCH] Align completion menu items --- lib/reline/line_editor.rb | 30 ++++++++++++++++++++++++++---- test/reline/test_line_editor.rb | 25 +++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb index d71b903701..02a3ee8484 100644 --- a/lib/reline/line_editor.rb +++ b/lib/reline/line_editor.rb @@ -49,7 +49,29 @@ module CompletionState end CompletionJourneyData = Struct.new(:preposing, :postposing, :list, :pointer) - MenuInfo = Struct.new(:target, :list) + + class MenuInfo + attr_reader :list + + def initialize(list) + @list = list + end + + def lines(screen_width) + return [] if @list.empty? + + list = @list.sort + sizes = list.map { |item| Reline::Unicode.calculate_width(item) } + item_width = sizes.max + 2 + num_cols = [screen_width / item_width, 1].max + num_rows = list.size.fdiv(num_cols).ceil + list_with_padding = list.zip(sizes).map { |item, size| item + ' ' * (item_width - size) } + aligned = (list_with_padding + [nil] * (num_rows * num_cols - list_with_padding.size)).each_slice(num_rows).to_a.transpose + aligned.map do |row| + row.join.rstrip + end + end + end PROMPT_LIST_CACHE_TIMEOUT = 0.5 MINIMUM_SCROLLBAR_HEIGHT = 1 @@ -1192,7 +1214,7 @@ def just_move_cursor private def show_menu scroll_down(@highest_in_all - @first_line_started_from) @rerender_all = true - @menu_info.list.sort!.each do |item| + @menu_info.lines(@screen_size.last).each do |item| Reline::IOGate.move_cursor_column(0) @output.write item @output.flush @@ -1227,8 +1249,8 @@ def editing_mode @config.editing_mode end - private def menu(target, list) - @menu_info = MenuInfo.new(target, list) + private def menu(_target, list) + @menu_info = MenuInfo.new(list) end private def complete_internal_proc(list, is_menu) diff --git a/test/reline/test_line_editor.rb b/test/reline/test_line_editor.rb index 8399e76e92..5ae416d907 100644 --- a/test/reline/test_line_editor.rb +++ b/test/reline/test_line_editor.rb @@ -10,4 +10,29 @@ def test_range_subtract expected_result = [3...5, 7...8, 9...10, 13...17, 19...20] assert_equal expected_result, editor.send(:range_subtract, base_ranges, subtract_ranges) end + + def test_menu_info_format + list = %w[aa b c d e f g hhh i j k] + col3 = [ + 'aa e i', + 'b f j', + 'c g k', + 'd hhh' + ] + col2 = [ + 'aa g', + 'b hhh', + 'c i', + 'd j', + 'e k', + 'f' + ] + assert_equal(col3, Reline::LineEditor::MenuInfo.new(list).lines(19)) + assert_equal(col3, Reline::LineEditor::MenuInfo.new(list).lines(15)) + assert_equal(col2, Reline::LineEditor::MenuInfo.new(list).lines(14)) + assert_equal(col2, Reline::LineEditor::MenuInfo.new(list).lines(10)) + assert_equal(list, Reline::LineEditor::MenuInfo.new(list).lines(9)) + assert_equal(list, Reline::LineEditor::MenuInfo.new(list).lines(0)) + assert_equal([], Reline::LineEditor::MenuInfo.new([]).lines(10)) + end end