chore: add completions help and small improvements

Kujtim Hoxha created

Change summary

internal/tui/components/chat/editor/editor.go      |  5 ++++
internal/tui/components/completions/completions.go | 10 +++++--
internal/tui/components/completions/item.go        |  1 
internal/tui/components/completions/keys.go        |  2 
internal/tui/page/chat/chat.go                     | 20 ++++++++++++++++
internal/tui/tui.go                                |  5 +++
6 files changed, 38 insertions(+), 5 deletions(-)

Detailed changes

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

@@ -35,6 +35,7 @@ type Editor interface {
 	layout.Positional
 
 	SetSession(session session.Session) tea.Cmd
+	IsCompletionsOpen() bool
 	Cursor() *tea.Cursor
 }
 
@@ -391,6 +392,10 @@ func (c *editorCmp) SetSession(session session.Session) tea.Cmd {
 	return nil
 }
 
+func (c *editorCmp) IsCompletionsOpen() bool {
+	return c.isCompletionsOpen
+}
+
 func New(app *app.App) Editor {
 	t := styles.CurrentTheme()
 	ta := textarea.New()

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

@@ -70,8 +70,8 @@ func New() Completions {
 		list.WithHideFilterInput(true),
 	)
 	return &completionsCmp{
-		width:  30,
-		height: 10,
+		width:  0,
+		height: 0,
 		list:   l,
 		query:  "",
 		keyMap: completionsKeyMap,
@@ -89,6 +89,10 @@ func (c *completionsCmp) Init() tea.Cmd {
 // Update implements Completions.
 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, 80)
+		c.height = min(msg.Height-c.y, 15)
+		return c, nil
 	case tea.KeyPressMsg:
 		switch {
 		case key.Matches(msg, c.keyMap.Up):
@@ -135,7 +139,7 @@ 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.height = max(min(10, len(items)), 1) // Ensure at least 1 item height
+		c.height = max(min(c.height, len(items)), 1) // Ensure at least 1 item height
 		cmds := []tea.Cmd{
 			c.list.SetSize(c.width, c.height),
 			c.list.SetItems(items),

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

@@ -90,6 +90,7 @@ func (c *completionItemCmp) View() string {
 	if c.bgColor != nil {
 		titleStyle = titleStyle.Background(c.bgColor)
 		titleMatchStyle = titleMatchStyle.Background(c.bgColor)
+		itemStyle = itemStyle.Background(c.bgColor)
 	}
 
 	if c.focus {

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

@@ -22,7 +22,7 @@ func DefaultKeyMap() KeyMap {
 			key.WithHelp("up", "move up"),
 		),
 		Select: key.NewBinding(
-			key.WithKeys("enter"),
+			key.WithKeys("enter", "tab", "ctrl+y"),
 			key.WithHelp("enter", "select"),
 		),
 		Cancel: key.NewBinding(

internal/tui/page/chat/chat.go 🔗

@@ -657,6 +657,26 @@ func (a *chatPage) Help() help.KeyMap {
 			fullList = append(fullList, []key.Binding{v})
 		}
 	default:
+		if a.editor.IsCompletionsOpen() {
+			shortList = append(shortList,
+				key.NewBinding(
+					key.WithKeys("tab", "enter"),
+					key.WithHelp("tab/enter", "complete"),
+				),
+				key.NewBinding(
+					key.WithKeys("esc"),
+					key.WithHelp("esc", "cancel"),
+				),
+				key.NewBinding(
+					key.WithKeys("up", "down"),
+					key.WithHelp("↑/↓", "choose"),
+				),
+			)
+			for _, v := range shortList {
+				fullList = append(fullList, []key.Binding{v})
+			}
+			return core.NewSimpleHelp(shortList, fullList)
+		}
 		if a.app.CoderAgent != nil && a.app.CoderAgent.IsBusy() {
 			cancelBinding := key.NewBinding(
 				key.WithKeys("esc"),

internal/tui/tui.go 🔗

@@ -109,6 +109,7 @@ func (a *appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 		}
 		return a, tea.Batch(cmds...)
 	case tea.WindowSizeMsg:
+		a.completions.Update(msg)
 		return a, a.handleWindowResize(msg.Width, msg.Height)
 
 	// Completions messages
@@ -119,9 +120,11 @@ func (a *appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 
 	// Dialog messages
 	case dialogs.OpenDialogMsg, dialogs.CloseDialogMsg:
+		u, completionCmd := a.completions.Update(completions.CloseCompletionsMsg{})
+		a.completions = u.(completions.Completions)
 		u, dialogCmd := a.dialog.Update(msg)
 		a.dialog = u.(dialogs.DialogCmp)
-		return a, dialogCmd
+		return a, tea.Batch(completionCmd, dialogCmd)
 	case commands.ShowArgumentsDialogMsg:
 		return a, util.CmdHandler(
 			dialogs.OpenDialogMsg{