Просмотр исходного кода

fix(tui): file completion quirks

adamdottv 8 месяцев назад
Родитель
Сommit
87d1d3fb62

+ 3 - 0
packages/tui/internal/app/app.go

@@ -42,6 +42,9 @@ type SendMsg struct {
 	Text        string
 	Attachments []Attachment
 }
+type CompletionDialogTriggerdMsg struct {
+	InitialValue string
+}
 
 func New(
 	ctx context.Context,

+ 3 - 3
packages/tui/internal/components/chat/editor.go

@@ -80,7 +80,7 @@ func (m *editorComponent) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 		} else {
 			existingValue := m.textarea.Value()
 			modifiedValue := strings.Replace(existingValue, msg.SearchString, msg.CompletionValue, 1)
-			m.textarea.SetValue(modifiedValue)
+			m.textarea.SetValue(modifiedValue + " ")
 			return m, nil
 		}
 	}
@@ -152,11 +152,11 @@ func (m *editorComponent) SetSize(width, height int) tea.Cmd {
 }
 
 func (m *editorComponent) Value() string {
-	return strings.TrimSpace(m.textarea.Value())
+	return m.textarea.Value()
 }
 
 func (m *editorComponent) Submit() (tea.Model, tea.Cmd) {
-	value := m.Value()
+	value := strings.TrimSpace(m.Value())
 	m.textarea.Reset()
 	if value == "" {
 		return m, nil

+ 33 - 31
packages/tui/internal/components/dialog/complete.go

@@ -7,6 +7,7 @@ import (
 	"github.com/charmbracelet/bubbles/v2/textarea"
 	tea "github.com/charmbracelet/bubbletea/v2"
 	"github.com/charmbracelet/lipgloss/v2"
+	"github.com/sst/opencode/internal/app"
 	"github.com/sst/opencode/internal/components/list"
 	"github.com/sst/opencode/internal/styles"
 	"github.com/sst/opencode/internal/theme"
@@ -111,39 +112,13 @@ func (c *completionDialogComponent) Init() tea.Cmd {
 	return nil
 }
 
-func (c *completionDialogComponent) complete(item CompletionItemI) tea.Cmd {
-	value := c.pseudoSearchTextArea.Value()
-
-	if value == "" {
-		return nil
-	}
-
-	// Check if this is a command completion
-	isCommand := c.completionProvider.GetId() == "commands"
-
-	return tea.Batch(
-		util.CmdHandler(CompletionSelectedMsg{
-			SearchString:    value,
-			CompletionValue: item.GetValue(),
-			IsCommand:       isCommand,
-		}),
-		c.close(),
-	)
-}
-
-func (c *completionDialogComponent) close() tea.Cmd {
-	c.list.SetItems([]CompletionItemI{})
-	c.pseudoSearchTextArea.Reset()
-	c.pseudoSearchTextArea.Blur()
-
-	return util.CmdHandler(CompletionDialogCloseMsg{})
-}
-
 func (c *completionDialogComponent) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 	var cmds []tea.Cmd
 	switch msg := msg.(type) {
 	case []CompletionItemI:
 		c.list.SetItems(msg)
+	case app.CompletionDialogTriggerdMsg:
+		c.pseudoSearchTextArea.SetValue(msg.InitialValue)
 	case tea.KeyMsg:
 		if c.pseudoSearchTextArea.Focused() {
 			if !key.Matches(msg, completionDialogKeys.Complete) {
@@ -194,13 +169,12 @@ func (c *completionDialogComponent) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 				items, err := c.completionProvider.GetChildEntries("")
 				if err != nil {
 					slog.Error("Failed to get completion items", "error", err)
-					// status.Error(err.Error())
 				}
 				return items
 			}
 			cmds = append(cmds, cmd)
 			cmds = append(cmds, c.pseudoSearchTextArea.Focus())
-			c.pseudoSearchTextArea.SetValue(msg.String())
+			// c.pseudoSearchTextArea.SetValue(msg.String())
 			return c, tea.Batch(cmds...)
 		}
 	case tea.WindowSizeMsg:
@@ -255,6 +229,34 @@ func (c *completionDialogComponent) SetProvider(provider CompletionProvider) {
 	}
 }
 
+func (c *completionDialogComponent) complete(item CompletionItemI) tea.Cmd {
+	value := c.pseudoSearchTextArea.Value()
+
+	if value == "" {
+		return nil
+	}
+
+	// Check if this is a command completion
+	isCommand := c.completionProvider.GetId() == "commands"
+
+	return tea.Batch(
+		util.CmdHandler(CompletionSelectedMsg{
+			SearchString:    value,
+			CompletionValue: item.GetValue(),
+			IsCommand:       isCommand,
+		}),
+		c.close(),
+	)
+}
+
+func (c *completionDialogComponent) close() tea.Cmd {
+	c.list.SetItems([]CompletionItemI{})
+	c.pseudoSearchTextArea.Reset()
+	c.pseudoSearchTextArea.Blur()
+
+	return util.CmdHandler(CompletionDialogCloseMsg{})
+}
+
 func NewCompletionDialogComponent(completionProvider CompletionProvider) CompletionDialog {
 	ti := textarea.New()
 
@@ -268,7 +270,7 @@ func NewCompletionDialogComponent(completionProvider CompletionProvider) Complet
 	go func() {
 		items, err := completionProvider.GetChildEntries("")
 		if err != nil {
-			// status.Error(err.Error())
+			slog.Error("Failed to get completion items", "error", err)
 		}
 		li.SetItems(items)
 	}()

+ 41 - 6
packages/tui/internal/tui/tui.go

@@ -5,6 +5,7 @@ import (
 	"log/slog"
 	"os"
 	"os/exec"
+	"strings"
 
 	"github.com/charmbracelet/bubbles/v2/key"
 	tea "github.com/charmbracelet/bubbletea/v2"
@@ -90,10 +91,49 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 		// 3. Handle completions trigger
 		switch msg.String() {
 		case "/":
-			a.showCompletionDialog = true
+			if !a.showCompletionDialog {
+				a.showCompletionDialog = true
+
+				initialValue := "/"
+				currentInput := a.editor.Value()
+				// if the input doesn't end with a space,
+				// then we want to include the last word
+				if !strings.HasSuffix(currentInput, " ") {
+					words := strings.Split(a.editor.Value(), " ")
+					if len(words) > 0 {
+						lastWord := words[len(words)-1]
+						lastWord = strings.TrimSpace(lastWord)
+						initialValue = lastWord + "/"
+					}
+				}
+				updated, cmd := a.completions.Update(
+					app.CompletionDialogTriggerdMsg{
+						InitialValue: initialValue,
+					},
+				)
+				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)
+				return a, tea.Sequence(cmds...)
+			}
 		}
 
 		if a.showCompletionDialog {
+			switch msg.String() {
+			case "tab", "enter", "esc":
+				context, contextCmd := a.completions.Update(msg)
+				a.completions = context.(dialog.CompletionDialog)
+				cmds = append(cmds, contextCmd)
+				return a, tea.Batch(cmds...)
+			}
+
 			updated, cmd := a.editor.Update(msg)
 			a.editor = updated.(chat.EditorComponent)
 			cmds = append(cmds, cmd)
@@ -106,11 +146,6 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 			a.completions = context.(dialog.CompletionDialog)
 			cmds = append(cmds, contextCmd)
 			return a, tea.Batch(cmds...)
-
-			// Doesn't forward event if enter key is pressed
-			// if msg.String() == "enter" {
-			// 	return a, tea.Batch(cmds...)
-			// }
 		}
 
 		// 4. Maximize editor responsiveness for printable characters