@@ -102,7 +102,7 @@ func (c *completionsCmp) Init() tea.Cmd {
102func (c *completionsCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
102func (c *completionsCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
103 switch msg := msg.(type) {
103 switch msg := msg.(type) {
104 case tea.WindowSizeMsg:
104 case tea.WindowSizeMsg:
105− c.width = min(msg.Width-c.x, maxCompletionsWidth)
105+ c.width = min(listWidth(c.list.Items()), maxCompletionsWidth)
106 c.height = min(msg.Height-c.y, 15)
106 c.height = min(msg.Height-c.y, 15)
107 return c, nil
107 return c, nil
108 case tea.KeyPressMsg:
108 case tea.KeyPressMsg:
@@ -168,10 +168,11 @@ func (c *completionsCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
168 item := NewCompletionItem(completion.Title, completion.Value, WithBackgroundColor(t.BgSubtle))
168 item := NewCompletionItem(completion.Title, completion.Value, WithBackgroundColor(t.BgSubtle))
169 items = append(items, item)
169 items = append(items, item)
171+ c.width = listWidth(msg.Completions)
171 c.height = max(min(c.height, len(items)), 1) // Ensure at least 1 item height
172 c.height = max(min(c.height, len(items)), 1) // Ensure at least 1 item height
172 return c, tea.Batch(
173 return c, tea.Batch(
173− c.list.SetSize(c.width, c.height),
174 c.list.SetItems(items),
174 c.list.SetItems(items),
175+ c.list.SetSize(c.width, c.height),
175 util.CmdHandler(CompletionsOpenedMsg{}),
176 util.CmdHandler(CompletionsOpenedMsg{}),
177 case FilterCompletionsMsg:
178 case FilterCompletionsMsg:
@@ -195,7 +196,9 @@ func (c *completionsCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
195 c.query = msg.Query
196 c.query = msg.Query
196 var cmds []tea.Cmd
197 var cmds []tea.Cmd
197 cmds = append(cmds, c.list.Filter(msg.Query))
198 cmds = append(cmds, c.list.Filter(msg.Query))
199+ items := c.list.Items()
198− itemsLen := len(c.list.Items())
200+ itemsLen := len(items)
201+ c.width = listWidth(items)
199 c.height = max(min(maxCompletionsHeight, itemsLen), 1)
202 c.height = max(min(maxCompletionsHeight, itemsLen), 1)
200 cmds = append(cmds, c.list.SetSize(c.width, c.height))
203 cmds = append(cmds, c.list.SetSize(c.width, c.height))
201 if itemsLen == 0 {
204 if itemsLen == 0 {
@@ -215,15 +218,34 @@ func (c *completionsCmp) View() string {
215 return ""
218 return ""
218− return c.style().Render(c.list.View())
221−func (c *completionsCmp) style() lipgloss.Style {
222 t := styles.CurrentTheme()
221 t := styles.CurrentTheme()
223− return t.S().Base.
222+ style := t.S().Base.
224 Width(c.width).
223 Width(c.width).
225 Height(c.height).
224 Height(c.height).
226 Background(t.BgSubtle)
225 Background(t.BgSubtle)
227+ return style.Render(c.list.View())
230+// listWidth returns the width of the last 10 items in the list, which is used
231+// to determine the width of the completions popup.
232+// Note this only works for [completionItemCmp] items.
233+func listWidth[T any](items []T) int {
235+ if len(items) == 0 {
239+ for i := len(items) - 1; i >= 0 && i >= len(items)-10; i-- {
240+ item, ok := any(items[i]).(*completionItemCmp)
244+ itemWidth := lipgloss.Width(item.text) + 2 // +2 for padding
245+ width = max(width, itemWidth)
229func (c *completionsCmp) Open() bool {
251func (c *completionsCmp) Open() bool {