diff --git a/internal/tui/components/completions/completions.go b/internal/tui/components/completions/completions.go index 6c63afd22e982e5ba40f5d175fc71449bcd0879e..ed1e90557bc98e87cf799abfb3c29fb28c94007c 100644 --- a/internal/tui/components/completions/completions.go +++ b/internal/tui/components/completions/completions.go @@ -102,7 +102,7 @@ func (c *completionsCmp) Init() tea.Cmd { func (c *completionsCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { case tea.WindowSizeMsg: - c.width = min(msg.Width-c.x, maxCompletionsWidth) + c.width = min(listWidth(c.list.Items()), maxCompletionsWidth) c.height = min(msg.Height-c.y, 15) return c, nil case tea.KeyPressMsg: @@ -168,10 +168,11 @@ func (c *completionsCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) { item := NewCompletionItem(completion.Title, completion.Value, WithBackgroundColor(t.BgSubtle)) items = append(items, item) } + c.width = listWidth(msg.Completions) c.height = max(min(c.height, len(items)), 1) // Ensure at least 1 item height return c, tea.Batch( - c.list.SetSize(c.width, c.height), c.list.SetItems(items), + c.list.SetSize(c.width, c.height), util.CmdHandler(CompletionsOpenedMsg{}), ) case FilterCompletionsMsg: @@ -195,7 +196,9 @@ func (c *completionsCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) { c.query = msg.Query var cmds []tea.Cmd cmds = append(cmds, c.list.Filter(msg.Query)) - itemsLen := len(c.list.Items()) + items := c.list.Items() + itemsLen := len(items) + c.width = listWidth(items) c.height = max(min(maxCompletionsHeight, itemsLen), 1) cmds = append(cmds, c.list.SetSize(c.width, c.height)) if itemsLen == 0 { @@ -215,15 +218,34 @@ func (c *completionsCmp) View() string { return "" } - return c.style().Render(c.list.View()) -} - -func (c *completionsCmp) style() lipgloss.Style { t := styles.CurrentTheme() - return t.S().Base. + style := t.S().Base. Width(c.width). Height(c.height). Background(t.BgSubtle) + + return style.Render(c.list.View()) +} + +// listWidth returns the width of the last 10 items in the list, which is used +// to determine the width of the completions popup. +// Note this only works for [completionItemCmp] items. +func listWidth[T any](items []T) int { + var width int + if len(items) == 0 { + return width + } + + for i := len(items) - 1; i >= 0 && i >= len(items)-10; i-- { + item, ok := any(items[i]).(*completionItemCmp) + if !ok { + continue + } + itemWidth := lipgloss.Width(item.text) + 2 // +2 for padding + width = max(width, itemWidth) + } + + return width } func (c *completionsCmp) Open() bool {