Skip to content

Commit a622704

Browse files
authored
Align completion menu items (#613)
1 parent 1d65696 commit a622704

File tree

2 files changed

+51
-4
lines changed

2 files changed

+51
-4
lines changed

lib/reline/line_editor.rb

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,29 @@ module CompletionState
4949
RenderedScreen = Struct.new(:base_y, :lines, :cursor_y, keyword_init: true)
5050

5151
CompletionJourneyData = Struct.new(:preposing, :postposing, :list, :pointer)
52-
MenuInfo = Struct.new(:target, :list)
52+
53+
class MenuInfo
54+
attr_reader :list
55+
56+
def initialize(list)
57+
@list = list
58+
end
59+
60+
def lines(screen_width)
61+
return [] if @list.empty?
62+
63+
list = @list.sort
64+
sizes = list.map { |item| Reline::Unicode.calculate_width(item) }
65+
item_width = sizes.max + 2
66+
num_cols = [screen_width / item_width, 1].max
67+
num_rows = list.size.fdiv(num_cols).ceil
68+
list_with_padding = list.zip(sizes).map { |item, size| item + ' ' * (item_width - size) }
69+
aligned = (list_with_padding + [nil] * (num_rows * num_cols - list_with_padding.size)).each_slice(num_rows).to_a.transpose
70+
aligned.map do |row|
71+
row.join.rstrip
72+
end
73+
end
74+
end
5375

5476
MINIMUM_SCROLLBAR_HEIGHT = 1
5577

@@ -458,7 +480,7 @@ def render_differential
458480
[[0, Reline::Unicode.calculate_width(l, true), l]]
459481
end
460482
if @menu_info
461-
@menu_info.list.sort!.each do |item|
483+
@menu_info.lines(screen_width).each do |item|
462484
new_lines << [[0, Reline::Unicode.calculate_width(item), item]]
463485
end
464486
@menu_info = nil # TODO: do not change state here
@@ -779,8 +801,8 @@ def editing_mode
779801
@config.editing_mode
780802
end
781803

782-
private def menu(target, list)
783-
@menu_info = MenuInfo.new(target, list)
804+
private def menu(_target, list)
805+
@menu_info = MenuInfo.new(list)
784806
end
785807

786808
private def complete_internal_proc(list, is_menu)

test/reline/test_line_editor.rb

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,4 +127,29 @@ def test_complicated
127127
end
128128
end
129129
end
130+
131+
def test_menu_info_format
132+
list = %w[aa b c d e f g hhh i j k]
133+
col3 = [
134+
'aa e i',
135+
'b f j',
136+
'c g k',
137+
'd hhh'
138+
]
139+
col2 = [
140+
'aa g',
141+
'b hhh',
142+
'c i',
143+
'd j',
144+
'e k',
145+
'f'
146+
]
147+
assert_equal(col3, Reline::LineEditor::MenuInfo.new(list).lines(19))
148+
assert_equal(col3, Reline::LineEditor::MenuInfo.new(list).lines(15))
149+
assert_equal(col2, Reline::LineEditor::MenuInfo.new(list).lines(14))
150+
assert_equal(col2, Reline::LineEditor::MenuInfo.new(list).lines(10))
151+
assert_equal(list, Reline::LineEditor::MenuInfo.new(list).lines(9))
152+
assert_equal(list, Reline::LineEditor::MenuInfo.new(list).lines(0))
153+
assert_equal([], Reline::LineEditor::MenuInfo.new([]).lines(10))
154+
end
130155
end

0 commit comments

Comments
 (0)