@@ -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 )
0 commit comments