88 "unicode/utf8"
99
1010 "github.com/kovidgoyal/kitty/tools/icons"
11- "github.com/kovidgoyal/kitty/tools/tui/loop"
1211 "github.com/kovidgoyal/kitty/tools/utils"
1312 "github.com/kovidgoyal/kitty/tools/utils/style"
1413 "github.com/kovidgoyal/kitty/tools/wcswidth"
@@ -55,26 +54,16 @@ func (h *Handler) draw_no_matches_message(in_progress bool) {
5554}
5655
5756const matching_position_style = "fg=green"
57+ const current_style = "fg=intense-white bold"
5858
59- func (h * Handler ) draw_matching_result (r * ResultItem ) {
60- icon := icon_for (r .abspath , r .dir_entry )
61- h .lp .MoveCursorHorizontally (1 )
62- p , s , _ := strings .Cut (h .lp .SprintStyled (matching_position_style , " " ), " " )
63- h .lp .QueueWriteString (p )
64- h .lp .DrawSizedText (icon , loop.SizedText {Scale : 2 })
65- h .lp .QueueWriteString (s )
66- text := r .text
67- available_width := (h .screen_size .width - 6 ) / 2
68- add_ellipsis := false
69- if wcswidth .Stringwidth (text ) > available_width {
70- text = wcswidth .TruncateToVisualLength (text , available_width - 2 )
71- add_ellipsis = true
72- }
73- h .render_match_with_positions (text , add_ellipsis , r .positions , 2 )
74- }
75-
76- func (h * Handler ) render_match_with_positions (text string , add_ellipsis bool , positions []int , scale int ) {
59+ func (h * Handler ) render_match_with_positions (text string , add_ellipsis bool , positions []int , is_current bool ) {
7760 prefix , suffix , _ := strings .Cut (h .lp .SprintStyled (matching_position_style , " " ), " " )
61+ if is_current {
62+ p , s , _ := strings .Cut (h .lp .SprintStyled (current_style , " " ), " " )
63+ h .lp .QueueWriteString (p )
64+ defer h .lp .QueueWriteString (s )
65+ suffix += p
66+ }
7867 write_chunk := func (text string , emphasize bool ) {
7968 if text == "" {
8069 return
@@ -85,11 +74,7 @@ func (h *Handler) render_match_with_positions(text string, add_ellipsis bool, po
8574 h .lp .QueueWriteString (suffix )
8675 }()
8776 }
88- if scale > 1 {
89- h .lp .DrawSizedText (text , loop.SizedText {Scale : scale })
90- } else {
91- h .lp .QueueWriteString (text )
92- }
77+ h .lp .QueueWriteString (text )
9378 }
9479 at := 0
9580 limit := len (text )
@@ -129,29 +114,40 @@ func icon_for(path string, x os.DirEntry) string {
129114 return ans
130115}
131116
132- func (h * Handler ) draw_column_of_matches (matches []* ResultItem , x , available_width , num_extra_matches int ) {
117+ func (h * Handler ) draw_column_of_matches (matches []* ResultItem , current_idx int , x , available_width , num_before , num_after int ) {
118+ if num_before > 0 {
119+ h .lp .QueueWriteString ("\r " )
120+ h .lp .MoveCursorHorizontally (x )
121+ h .lp .QueueWriteString ("… " )
122+ text := h .lp .SprintStyled ("italic" , fmt .Sprintf ("%d prev matches" , num_before ))
123+ h .render_match_with_positions (text , false , nil , false )
124+ }
133125 for i , m := range matches {
134126 h .lp .QueueWriteString ("\r " )
135127 h .lp .MoveCursorHorizontally (x )
136128 icon := icon_for (m .abspath , m .dir_entry )
137- text := ""
129+ text := m . text
138130 add_ellipsis := false
139- positions := m .positions
140- if num_extra_matches > 0 && i == len (matches )- 1 {
141- icon = "… "
142- text = h .lp .SprintStyled ("italic" , fmt .Sprintf ("%d more matches" , num_extra_matches ))
143- positions = nil
131+ if wcswidth .Stringwidth (text ) > available_width - 3 {
132+ text = wcswidth .TruncateToVisualLength (text , available_width - 4 )
133+ add_ellipsis = true
134+ }
135+ is_current := i == current_idx
136+ if is_current {
137+ h .lp .QueueWriteString (h .lp .SprintStyled (matching_position_style , icon + " " ))
144138 } else {
145- text = m .text
146- if wcswidth .Stringwidth (text ) > available_width - 3 {
147- text = wcswidth .TruncateToVisualLength (text , available_width - 4 )
148- add_ellipsis = true
149- }
139+ h .lp .QueueWriteString (icon + " " )
150140 }
151- h .lp .QueueWriteString (icon + " " )
152- h .render_match_with_positions (text , add_ellipsis , positions , 1 )
141+ h .render_match_with_positions (text , add_ellipsis , m .positions , is_current )
153142 h .lp .MoveCursorVertically (1 )
154143 }
144+ if num_after > 0 {
145+ h .lp .QueueWriteString ("\r " )
146+ h .lp .MoveCursorHorizontally (x )
147+ h .lp .QueueWriteString ("… " )
148+ text := h .lp .SprintStyled ("italic" , fmt .Sprintf ("%d more matches" , num_after ))
149+ h .render_match_with_positions (text , false , nil , false )
150+ }
155151}
156152
157153func (h * Handler ) draw_list_of_results (matches []* ResultItem , y , height int ) {
@@ -169,14 +165,39 @@ func (h *Handler) draw_list_of_results(matches []*ResultItem, y, height int) {
169165 }
170166 col_width = available_width / num_cols
171167 }
168+ num_that_can_be_displayed := num_cols * height
169+ num_after , num_before := 0 , 0
170+ idx := min (h .state .CurrentIndex (), len (matches )- 1 )
171+ if idx == 0 {
172+ num_after = max (0 , len (matches )- num_that_can_be_displayed )
173+ } else {
174+ num_after = max (0 , len (matches )- num_that_can_be_displayed )
175+ last_idx := len (matches ) - 1 - num_after
176+ if last_idx < idx {
177+ num_before = last_idx - idx
178+ num_after = max (0 , num_after - num_before )
179+ }
180+ }
181+ pos := num_before
172182 x := 1
173183 for i := range num_cols {
174- is_last := i == num_cols - 1
175- chunk := matches [:min (len (matches ), height )]
176- matches = matches [len (chunk ):]
184+ is_last , is_first := i == num_cols - 1 , i == 0
185+ num := height
186+ if is_first && num_before > 0 {
187+ num --
188+ }
189+ if is_last && num_after > 0 {
190+ num --
191+ }
177192 h .lp .MoveCursorTo (x , y )
178- h .draw_column_of_matches (chunk , x , col_width - 1 , utils .IfElse (is_last , len (matches ), 0 ))
193+ limit := min (len (matches ), pos + num )
194+ h .draw_column_of_matches (matches [pos :limit ], idx - pos , x , col_width - 1 , num_before , utils .IfElse (is_last , len (matches )- limit , 0 ))
179195 x += col_width
196+ pos += num
197+ num_before = 0
198+ if pos >= len (matches ) {
199+ break
200+ }
180201 }
181202}
182203
@@ -192,14 +213,7 @@ func (h *Handler) draw_results(y, bottom_margin int, matches []*ResultItem, in_p
192213 case 0 :
193214 h .draw_no_matches_message (in_progress )
194215 default :
195- switch h .state .SearchText () {
196- case "" :
197- h .draw_list_of_results (matches , y , height - 2 )
198- default :
199- h .draw_matching_result (matches [0 ])
200- y += 2
201- h .draw_list_of_results (matches [1 :], y , height - 4 )
202- }
216+ h .draw_list_of_results (matches , y , height - 2 )
203217 }
204218 return
205219}
0 commit comments