Browse Source

fix(tui): typeahead open/close perf

adamdottv 8 months ago
parent
commit
311b9c74dd

+ 9 - 6
packages/tui/internal/completions/commands.go

@@ -35,8 +35,7 @@ func (c *CommandCompletionProvider) GetEmptyMessage() string {
 	return "no matching commands"
 }
 
-func getCommandCompletionItem(cmd commands.Command, space int) dialog.CompletionItemI {
-	t := theme.CurrentTheme()
+func getCommandCompletionItem(cmd commands.Command, space int, t theme.Theme) dialog.CompletionItemI {
 	spacer := strings.Repeat(" ", space)
 	title := "  /" + cmd.Trigger + lipgloss.NewStyle().Foreground(t.TextMuted()).Render(spacer+cmd.Description)
 	value := string(cmd.Name)
@@ -47,6 +46,9 @@ func getCommandCompletionItem(cmd commands.Command, space int) dialog.Completion
 }
 
 func (c *CommandCompletionProvider) GetChildEntries(query string) ([]dialog.CompletionItemI, error) {
+	t := theme.CurrentTheme()
+	commands := c.app.Commands
+
 	space := 1
 	for _, cmd := range c.app.Commands {
 		if lipgloss.Width(cmd.Trigger) > space {
@@ -55,15 +57,16 @@ func (c *CommandCompletionProvider) GetChildEntries(query string) ([]dialog.Comp
 	}
 	space += 2
 
+	sorted := commands.Sorted()
 	if query == "" {
 		// If no query, return all commands
 		items := []dialog.CompletionItemI{}
-		for _, cmd := range c.app.Commands {
+		for _, cmd := range sorted {
 			if cmd.Trigger == "" {
 				continue
 			}
 			space := space - lipgloss.Width(cmd.Trigger)
-			items = append(items, getCommandCompletionItem(cmd, space))
+			items = append(items, getCommandCompletionItem(cmd, space, t))
 		}
 		return items, nil
 	}
@@ -72,13 +75,13 @@ func (c *CommandCompletionProvider) GetChildEntries(query string) ([]dialog.Comp
 	var commandNames []string
 	commandMap := make(map[string]dialog.CompletionItemI)
 
-	for _, cmd := range c.app.Commands {
+	for _, cmd := range sorted {
 		if cmd.Trigger == "" {
 			continue
 		}
 		space := space - lipgloss.Width(cmd.Trigger)
 		commandNames = append(commandNames, cmd.Trigger)
-		commandMap[cmd.Trigger] = getCommandCompletionItem(cmd, space)
+		commandMap[cmd.Trigger] = getCommandCompletionItem(cmd, space, t)
 	}
 
 	// Find fuzzy matches

+ 1 - 4
packages/tui/internal/components/dialog/complete.go

@@ -173,7 +173,6 @@ func (c *completionDialogComponent) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 			}
 			cmds = append(cmds, cmd)
 			cmds = append(cmds, c.pseudoSearchTextArea.Focus())
-			// c.pseudoSearchTextArea.SetValue(msg.String())
 			return c, tea.Batch(cmds...)
 		}
 	case tea.WindowSizeMsg:
@@ -218,12 +217,12 @@ func (c *completionDialogComponent) SetProvider(provider CompletionProvider) {
 	if c.completionProvider.GetId() != provider.GetId() {
 		c.completionProvider = provider
 		c.list.SetEmptyMessage(" " + provider.GetEmptyMessage())
+		c.list.SetItems([]CompletionItemI{})
 	}
 }
 
 func (c *completionDialogComponent) complete(item CompletionItemI) tea.Cmd {
 	value := c.pseudoSearchTextArea.Value()
-
 	if value == "" {
 		return nil
 	}
@@ -242,10 +241,8 @@ func (c *completionDialogComponent) complete(item CompletionItemI) tea.Cmd {
 }
 
 func (c *completionDialogComponent) close() tea.Cmd {
-	c.list.SetItems([]CompletionItemI{})
 	c.pseudoSearchTextArea.Reset()
 	c.pseudoSearchTextArea.Blur()
-
 	return util.CmdHandler(CompletionDialogCloseMsg{})
 }
 

+ 22 - 30
packages/tui/internal/tui/tui.go

@@ -123,22 +123,23 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 			a.completions = updated.(dialog.CompletionDialog)
 			cmds = append(cmds, cmd)
 
-			updated, cmd = a.completions.Update(msg)
-			a.completions = updated.(dialog.CompletionDialog)
-			cmds = append(cmds, cmd)
-
 			updated, cmd = a.editor.Update(msg)
 			a.editor = updated.(chat.EditorComponent)
 			cmds = append(cmds, cmd)
+
+			updated, cmd = a.updateCompletions(msg)
+			a.completions = updated.(dialog.CompletionDialog)
+			cmds = append(cmds, cmd)
+
 			return a, tea.Sequence(cmds...)
 		}
 
 		if a.showCompletionDialog {
 			switch keyString {
 			case "tab", "enter", "esc", "ctrl+c":
-				context, contextCmd := a.completions.Update(msg)
-				a.completions = context.(dialog.CompletionDialog)
-				cmds = append(cmds, contextCmd)
+				updated, cmd := a.updateCompletions(msg)
+				a.completions = updated.(dialog.CompletionDialog)
+				cmds = append(cmds, cmd)
 				return a, tea.Batch(cmds...)
 			}
 
@@ -146,13 +147,10 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 			a.editor = updated.(chat.EditorComponent)
 			cmds = append(cmds, cmd)
 
-			currentInput := a.editor.Value()
-			provider := a.completionManager.GetProvider(currentInput)
-			a.completions.SetProvider(provider)
+			updated, cmd = a.updateCompletions(msg)
+			a.completions = updated.(dialog.CompletionDialog)
+			cmds = append(cmds, cmd)
 
-			context, contextCmd := a.completions.Update(msg)
-			a.completions = context.(dialog.CompletionDialog)
-			cmds = append(cmds, contextCmd)
 			return a, tea.Batch(cmds...)
 		}
 
@@ -178,10 +176,8 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 			return a, util.CmdHandler(commands.ExecuteCommandsMsg(matches))
 		}
 
-		// 7. Fallback to editor. This shouldn't happen?
-		// All printable characters were already sent, and
-		// any other keypress that didn't match a command
-		// is likely a noop.
+		// 7. Fallback to editor. This is for other characters
+		// likek backspace, tab, etc.
 		updatedEditor, cmd := a.editor.Update(msg)
 		a.editor = updatedEditor.(chat.EditorComponent)
 		return a, cmd
@@ -216,7 +212,6 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 		cmds = append(cmds, cmd)
 	case dialog.CompletionDialogCloseMsg:
 		a.showCompletionDialog = false
-		a.completions.SetProvider(a.completionManager.DefaultProvider())
 	case client.EventInstallationUpdated:
 		return a, toast.NewSuccessToast(
 			"opencode updated to "+msg.Properties.Version+", restart to apply.",
@@ -512,30 +507,18 @@ func (a appModel) executeCommand(command commands.Command) (tea.Model, tea.Cmd)
 		a.messages = updated.(chat.MessagesComponent)
 		cmds = append(cmds, cmd)
 	case commands.MessagesPageUpCommand:
-		if a.showCompletionDialog {
-			return a, nil
-		}
 		updated, cmd := a.messages.PageUp()
 		a.messages = updated.(chat.MessagesComponent)
 		cmds = append(cmds, cmd)
 	case commands.MessagesPageDownCommand:
-		if a.showCompletionDialog {
-			return a, nil
-		}
 		updated, cmd := a.messages.PageDown()
 		a.messages = updated.(chat.MessagesComponent)
 		cmds = append(cmds, cmd)
 	case commands.MessagesHalfPageUpCommand:
-		if a.showCompletionDialog {
-			return a, nil
-		}
 		updated, cmd := a.messages.HalfPageUp()
 		a.messages = updated.(chat.MessagesComponent)
 		cmds = append(cmds, cmd)
 	case commands.MessagesHalfPageDownCommand:
-		if a.showCompletionDialog {
-			return a, nil
-		}
 		updated, cmd := a.messages.HalfPageDown()
 		a.messages = updated.(chat.MessagesComponent)
 		cmds = append(cmds, cmd)
@@ -545,6 +528,15 @@ func (a appModel) executeCommand(command commands.Command) (tea.Model, tea.Cmd)
 	return a, tea.Batch(cmds...)
 }
 
+func (a appModel) updateCompletions(msg tea.Msg) (tea.Model, tea.Cmd) {
+	currentInput := a.editor.Value()
+	if currentInput != "" {
+		provider := a.completionManager.GetProvider(currentInput)
+		a.completions.SetProvider(provider)
+	}
+	return a.completions.Update(msg)
+}
+
 func NewModel(app *app.App) tea.Model {
 	completionManager := completions.NewCompletionManager(app)
 	initialProvider := completionManager.DefaultProvider()