Merge pull request #134 from charmbracelet/comp-padding

Kujtim Hoxha created

fix(tui): editor: position completions correctly and account for padding

Change summary

internal/tui/components/chat/editor/editor.go      |  5 ++-
internal/tui/components/completions/completions.go | 23 +++++++++++----
2 files changed, 19 insertions(+), 9 deletions(-)

Detailed changes

internal/tui/components/chat/editor/editor.go 🔗

@@ -361,8 +361,9 @@ func (m *editorCmp) startCompletions() tea.Msg {
 		})
 	}
 
-	x := m.textarea.Cursor().X + m.x + 1
-	y := m.textarea.Cursor().Y + m.y + 1
+	cur := m.textarea.Cursor()
+	x := cur.X + m.x // adjust for padding
+	y := cur.Y + m.y + 1
 	return completions.OpenCompletionsMsg{
 		Completions: completionItems,
 		X:           x,

internal/tui/components/completions/completions.go 🔗

@@ -9,6 +9,8 @@ import (
 	"github.com/charmbracelet/lipgloss/v2"
 )
 
+const maxCompletionsHeight = 10
+
 type Completion struct {
 	Title string // The title of the completion item
 	Value any    // The value of the completion item
@@ -43,7 +45,7 @@ type Completions interface {
 type completionsCmp struct {
 	width  int
 	height int  // Height of the completions component`
-	x      int  // X position for the completions popup\
+	x      int  // X position for the completions popup
 	y      int  // Y position for the completions popup
 	open   bool // Indicates if the completions are open
 	keyMap KeyMap
@@ -150,18 +152,25 @@ func (c *completionsCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 		if !c.open {
 			return c, nil // If completions are not open, do nothing
 		}
-		cmd := c.list.Filter(msg.Query)
-		c.height = max(min(10, len(c.list.Items())), 1)
-		return c, tea.Batch(
-			cmd,
-			c.list.SetSize(c.width, c.height),
-		)
+		var cmds []tea.Cmd
+		cmds = append(cmds, c.list.Filter(msg.Query))
+		itemsLen := len(c.list.Items())
+		c.height = max(min(maxCompletionsHeight, itemsLen), 1)
+		cmds = append(cmds, c.list.SetSize(c.width, c.height))
+		if itemsLen == 0 {
+			// Close completions if no items match the query
+			cmds = append(cmds, util.CmdHandler(CloseCompletionsMsg{}))
+		}
+		return c, tea.Batch(cmds...)
 	}
 	return c, nil
 }
 
 // View implements Completions.
 func (c *completionsCmp) View() string {
+	if !c.open {
+		return ""
+	}
 	if len(c.list.Items()) == 0 {
 		return c.style().Render("No completions found")
 	}