on main help sign in
fix: completions width (#1956)
fb3eeb0Kujtim Hoxha
internal/ui/completions/completions.go+25−13
@@ -83,7 +83,7 @@ func (c *Completions) Query() string {
83
83
84// Size returns the visible size of the popup.
84// Size returns the visible size of the popup.
85func (c *Completions) Size() (width, height int) {
85func (c *Completions) Size() (width, height int) {
86− visible := len(c.list.VisibleItems())
86+ visible := len(c.list.FilteredItems())
87 return c.width, min(visible, c.height)
87 return c.width, min(visible, c.height)
88}
88}
89
89
@@ -104,7 +104,6 @@ func (c *Completions) OpenWithFiles(depth, limit int) tea.Cmd {
104// SetFiles sets the file items on the completions popup.
104// SetFiles sets the file items on the completions popup.
105func (c *Completions) SetFiles(files []string) {
105func (c *Completions) SetFiles(files []string) {
106 items := make([]list.FilterableItem, 0, len(files))
106 items := make([]list.FilterableItem, 0, len(files))
107− width := 0
108 for _, file := range files {
107 for _, file := range files {
109 file = strings.TrimPrefix(file, "./")
108 file = strings.TrimPrefix(file, "./")
110 item := NewCompletionItem(
109 item := NewCompletionItem(
@@ -114,8 +113,6 @@ func (c *Completions) SetFiles(files []string) {
114 c.focusedStyle,
113 c.focusedStyle,
115 c.matchStyle,
114 c.matchStyle,
116 )
115 )
117−
118− width = max(width, ansi.StringWidth(file))
119 items = append(items, item)
116 items = append(items, item)
120 }
117 }
121
118
@@ -125,11 +122,22 @@ func (c *Completions) SetFiles(files []string) {
125 c.list.SetFilter("") // Clear any previous filter.
122 c.list.SetFilter("") // Clear any previous filter.
126 c.list.Focus()
123 c.list.Focus()
127
124
128− c.width = ordered.Clamp(width+2, int(minWidth), int(maxWidth))
125+ c.width = maxWidth
129 c.height = ordered.Clamp(len(items), int(minHeight), int(maxHeight))
126 c.height = ordered.Clamp(len(items), int(minHeight), int(maxHeight))
130 c.list.SetSize(c.width, c.height)
127 c.list.SetSize(c.width, c.height)
131 c.list.SelectFirst()
128 c.list.SelectFirst()
132 c.list.ScrollToSelected()
129 c.list.ScrollToSelected()
130+
131+ // recalculate width by using just the visible items
132+ start, end := c.list.VisibleItemIndices()
133+ width := 0
134+ if end != 0 {
135+ for _, file := range files[start : end+1] {
136+ width = max(width, ansi.StringWidth(file))
137+ }
138+ }
139+ c.width = ordered.Clamp(width+2, int(minWidth), int(maxWidth))
140+ c.list.SetSize(c.width, c.height)
133}
141}
134
142
135// Close closes the completions popup.
143// Close closes the completions popup.
@@ -150,10 +158,14 @@ func (c *Completions) Filter(query string) {
150 c.query = query
158 c.query = query
151 c.list.SetFilter(query)
159 c.list.SetFilter(query)
152
160
161+ // recalculate width by using just the visible items
153− items := c.list.VisibleItems()
162+ items := c.list.FilteredItems()
163+ start, end := c.list.VisibleItemIndices()
154 width := 0
164 width := 0
165+ if end != 0 {
155− for _, item := range items {
166+ for _, item := range items[start : end+1] {
156− width = max(width, ansi.StringWidth(item.(interface{ Text() string }).Text()))
167+ width = max(width, ansi.StringWidth(item.(interface{ Text() string }).Text()))
168+ }
157 }
169 }
158 c.width = ordered.Clamp(width+2, int(minWidth), int(maxWidth))
170 c.width = ordered.Clamp(width+2, int(minWidth), int(maxWidth))
159 c.height = ordered.Clamp(len(items), int(minHeight), int(maxHeight))
171 c.height = ordered.Clamp(len(items), int(minHeight), int(maxHeight))
@@ -164,7 +176,7 @@ func (c *Completions) Filter(query string) {
164
176
165// HasItems returns whether there are visible items.
177// HasItems returns whether there are visible items.
166func (c *Completions) HasItems() bool {
178func (c *Completions) HasItems() bool {
167− return len(c.list.VisibleItems()) > 0
179+ return len(c.list.FilteredItems()) > 0
168}
180}
169
181
170// Update handles key events for the completions.
182// Update handles key events for the completions.
@@ -203,7 +215,7 @@ func (c *Completions) Update(msg tea.KeyPressMsg) (tea.Msg, bool) {
203
215
204// selectPrev selects the previous item with circular navigation.
216// selectPrev selects the previous item with circular navigation.
205func (c *Completions) selectPrev() {
217func (c *Completions) selectPrev() {
206− items := c.list.VisibleItems()
218+ items := c.list.FilteredItems()
207 if len(items) == 0 {
219 if len(items) == 0 {
208 return
220 return
209 }
221 }
@@ -215,7 +227,7 @@ func (c *Completions) selectPrev() {
215
227
216// selectNext selects the next item with circular navigation.
228// selectNext selects the next item with circular navigation.
217func (c *Completions) selectNext() {
229func (c *Completions) selectNext() {
218− items := c.list.VisibleItems()
230+ items := c.list.FilteredItems()
219 if len(items) == 0 {
231 if len(items) == 0 {
220 return
232 return
221 }
233 }
@@ -227,7 +239,7 @@ func (c *Completions) selectNext() {
227
239
228// selectCurrent returns a command with the currently selected item.
240// selectCurrent returns a command with the currently selected item.
229func (c *Completions) selectCurrent(insert bool) tea.Msg {
241func (c *Completions) selectCurrent(insert bool) tea.Msg {
230− items := c.list.VisibleItems()
242+ items := c.list.FilteredItems()
231 if len(items) == 0 {
243 if len(items) == 0 {
232 return nil
244 return nil
233 }
245 }
@@ -258,7 +270,7 @@ func (c *Completions) Render() string {
258 return ""
270 return ""
259 }
271 }
260
272
261− items := c.list.VisibleItems()
273+ items := c.list.FilteredItems()
262 if len(items) == 0 {
274 if len(items) == 0 {
263 return ""
275 return ""
264 }
276 }
internal/ui/dialog/commands.go+1−1
@@ -188,7 +188,7 @@ func (c *Commands) HandleMsg(msg tea.Msg) Action {
188 }
188 }
189 default:
189 default:
190 var cmd tea.Cmd
190 var cmd tea.Cmd
191− for _, item := range c.list.VisibleItems() {
191+ for _, item := range c.list.FilteredItems() {
192 if item, ok := item.(*CommandItem); ok && item != nil {
192 if item, ok := item.(*CommandItem); ok && item != nil {
193 if msg.String() == item.Shortcut() {
193 if msg.String() == item.Shortcut() {
194 return item.Action()
194 return item.Action()
internal/ui/dialog/reasoning.go+1−1
@@ -176,7 +176,7 @@ func (r *Reasoning) Draw(scr uv.Screen, area uv.Rectangle) *tea.Cursor {
176 inputView := t.Dialog.InputPrompt.Render(r.input.View())
176 inputView := t.Dialog.InputPrompt.Render(r.input.View())
177 rc.AddPart(inputView)
177 rc.AddPart(inputView)
178
178
179− visibleCount := len(r.list.VisibleItems())
179+ visibleCount := len(r.list.FilteredItems())
180 if r.list.Height() >= visibleCount {
180 if r.list.Height() >= visibleCount {
181 r.list.ScrollToTop()
181 r.list.ScrollToTop()
182 } else {
182 } else {
internal/ui/list/filterable.go+4−4
@@ -69,7 +69,7 @@ func (f *FilterableList) PrependItems(items ...FilterableItem) {
69// SetFilter sets the filter query and updates the list items.
69// SetFilter sets the filter query and updates the list items.
70func (f *FilterableList) SetFilter(q string) {
70func (f *FilterableList) SetFilter(q string) {
71 f.query = q
71 f.query = q
72− f.List.SetItems(f.VisibleItems()...)
72+ f.List.SetItems(f.FilteredItems()...)
73 f.ScrollToTop()
73 f.ScrollToTop()
74}
74}
75
75
@@ -87,8 +87,8 @@ func (f FilterableItemsSource) String(i int) string {
87 return f[i].Filter()
87 return f[i].Filter()
88}
88}
89
89
90−// VisibleItems returns the visible items after filtering.
90+// FilteredItems returns the visible items after filtering.
91−func (f *FilterableList) VisibleItems() []Item {
91+func (f *FilterableList) FilteredItems() []Item {
92 if f.query == "" {
92 if f.query == "" {
93 items := make([]Item, len(f.items))
93 items := make([]Item, len(f.items))
94 for i, item := range f.items {
94 for i, item := range f.items {
@@ -120,6 +120,6 @@ func (f *FilterableList) VisibleItems() []Item {
120
120
121// Render renders the filterable list.
121// Render renders the filterable list.
122func (f *FilterableList) Render() string {
122func (f *FilterableList) Render() string {
123− f.List.SetItems(f.VisibleItems()...)
123+ f.List.SetItems(f.FilteredItems()...)
124 return f.List.Render()
124 return f.List.Render()
125}
125}