@@ -51,18 +51,22 @@ type Completions interface {
53type completionsCmp struct {
53type completionsCmp struct {
54− width int
54+ wWidth int // The window width
55− height int // Height of the completions component`
56+ height int // Height of the completions component`
56− x int // X position for the completions popup
57+ x, xorig int // X position for the completions popup
57− y int // Y position for the completions popup
58+ y int // Y position for the completions popup
58− open bool // Indicates if the completions are open
59+ open bool // Indicates if the completions are open
59− keyMap KeyMap
60+ keyMap KeyMap
61 list list.ListModel
62 list list.ListModel
62 query string // The current filter query
63 query string // The current filter query
65−const maxCompletionsWidth = 80 // Maximum width for the completions popup
67+ maxCompletionsWidth = 80 // Maximum width for the completions popup
68+ minCompletionsWidth = 20 // Minimum width for the completions popup
67func New() Completions {
71func New() Completions {
68 completionsKeyMap := DefaultKeyMap()
72 completionsKeyMap := DefaultKeyMap()
@@ -102,6 +106,7 @@ func (c *completionsCmp) Init() tea.Cmd {
102func (c *completionsCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
106func (c *completionsCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
103 switch msg := msg.(type) {
107 switch msg := msg.(type) {
104 case tea.WindowSizeMsg:
108 case tea.WindowSizeMsg:
109+ c.wWidth = msg.Width
105 c.width = min(listWidth(c.list.Items()), maxCompletionsWidth)
110 c.width = min(listWidth(c.list.Items()), maxCompletionsWidth)
106 c.height = min(msg.Height-c.y, 15)
111 c.height = min(msg.Height-c.y, 15)
107 return c, nil
112 return c, nil
@@ -160,7 +165,7 @@ func (c *completionsCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
160 case OpenCompletionsMsg:
165 case OpenCompletionsMsg:
161 c.open = true
166 c.open = true
162 c.query = ""
167 c.query = ""
163− c.x = msg.X
168+ c.x, c.xorig = msg.X, msg.X
164 c.y = msg.Y
169 c.y = msg.Y
165 items := []util.Model{}
170 items := []util.Model{}
166 t := styles.CurrentTheme()
171 t := styles.CurrentTheme()
@@ -168,7 +173,14 @@ func (c *completionsCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
168 item := NewCompletionItem(completion.Title, completion.Value, WithBackgroundColor(t.BgSubtle))
173 item := NewCompletionItem(completion.Title, completion.Value, WithBackgroundColor(t.BgSubtle))
169 items = append(items, item)
174 items = append(items, item)
171− c.width = listWidth(msg.Completions)
176+ width := listWidth(items)
177+ if len(items) == 0 {
178+ width = listWidth(c.list.Items())
180+ if c.x+width >= c.wWidth {
181+ c.x = c.wWidth - width - 1
183+ c.width = max(width, c.wWidth-minCompletionsWidth-1)
172 c.height = max(min(c.height, len(items)), 1) // Ensure at least 1 item height
184 c.height = max(min(c.height, len(items)), 1) // Ensure at least 1 item height
173 return c, tea.Batch(
185 return c, tea.Batch(
174 c.list.SetItems(items),
186 c.list.SetItems(items),
@@ -198,7 +210,13 @@ func (c *completionsCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
198 cmds = append(cmds, c.list.Filter(msg.Query))
210 cmds = append(cmds, c.list.Filter(msg.Query))
199 items := c.list.Items()
211 items := c.list.Items()
200 itemsLen := len(items)
212 itemsLen := len(items)
201− c.width = listWidth(items)
213+ width := listWidth(items)
216+ } else if c.x+width >= c.wWidth {
217+ c.x = c.wWidth - width - 1
202 c.height = max(min(maxCompletionsHeight, itemsLen), 1)
220 c.height = max(min(maxCompletionsHeight, itemsLen), 1)
203 cmds = append(cmds, c.list.SetSize(c.width, c.height))
221 cmds = append(cmds, c.list.SetSize(c.width, c.height))
204 if itemsLen == 0 {
222 if itemsLen == 0 {