diff options
| author | adamdottv <[email protected]> | 2025-06-13 15:56:30 -0500 |
|---|---|---|
| committer | adamdottv <[email protected]> | 2025-06-13 15:56:33 -0500 |
| commit | 67023bb00710b6a40836800da2eb5cdacc1ee9c1 (patch) | |
| tree | 4c6fce2842956f214b8e39a7465d4444b37d39b0 /packages/tui/internal/components/chat | |
| parent | a316aed4fe973682667a19e6ba550270cf1a9df4 (diff) | |
| download | opencode-67023bb00710b6a40836800da2eb5cdacc1ee9c1.tar.gz opencode-67023bb00710b6a40836800da2eb5cdacc1ee9c1.zip | |
wip: refactoring tui
Diffstat (limited to 'packages/tui/internal/components/chat')
| -rw-r--r-- | packages/tui/internal/components/chat/editor.go | 38 | ||||
| -rw-r--r-- | packages/tui/internal/components/chat/message.go | 114 | ||||
| -rw-r--r-- | packages/tui/internal/components/chat/messages.go | 3 |
3 files changed, 86 insertions, 69 deletions
diff --git a/packages/tui/internal/components/chat/editor.go b/packages/tui/internal/components/chat/editor.go index 2e89a7db4..95ca3e14b 100644 --- a/packages/tui/internal/components/chat/editor.go +++ b/packages/tui/internal/components/chat/editor.go @@ -44,11 +44,6 @@ type EditorKeyMaps struct { HistoryDown key.Binding } -type bluredEditorKeyMaps struct { - Send key.Binding - Focus key.Binding - OpenEditor key.Binding -} type DeleteAttachmentKeyMaps struct { AttachmentDeleteMode key.Binding Escape key.Binding @@ -108,10 +103,18 @@ func (m *editorComponent) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case dialog.ThemeChangedMsg: m.textarea = createTextArea(&m.textarea) case dialog.CompletionSelectedMsg: - existingValue := m.textarea.Value() - modifiedValue := strings.Replace(existingValue, msg.SearchString, msg.CompletionValue, 1) - m.textarea.SetValue(modifiedValue) - return m, nil + if msg.IsCommand { + // Execute the command directly + commandName := strings.TrimPrefix(msg.CompletionValue, "/") + m.textarea.Reset() + return m, util.CmdHandler(commands.ExecuteCommandMsg{Name: commandName}) + } else { + // For files, replace the text in the editor + existingValue := m.textarea.Value() + modifiedValue := strings.Replace(existingValue, msg.SearchString, msg.CompletionValue, 1) + m.textarea.SetValue(modifiedValue) + return m, nil + } case tea.KeyMsg: switch msg.String() { case "ctrl+c": @@ -378,12 +381,13 @@ func (m *editorComponent) send() tea.Cmd { } // Check for slash command - if strings.HasPrefix(value, "/") { - commandName := strings.TrimPrefix(value, "/") - if _, ok := m.app.Commands[commandName]; ok { - return util.CmdHandler(commands.ExecuteCommandMsg{Name: commandName}) - } - } + // if strings.HasPrefix(value, "/") { + // commandName := strings.TrimPrefix(value, "/") + // if _, ok := m.app.Commands[commandName]; ok { + // return util.CmdHandler(commands.ExecuteCommandMsg{Name: commandName}) + // } + // } + slog.Info("Send message", "value", value) return tea.Batch( util.CmdHandler(SendMsg{ @@ -452,6 +456,10 @@ func createTextArea(existing *textarea.Model) textarea.Model { return ta } +func (m *editorComponent) GetValue() string { + return m.textarea.Value() +} + func NewEditorComponent(app *app.App) layout.ModelWithView { s := spinner.New(spinner.WithSpinner(spinner.Ellipsis), spinner.WithStyle(styles.Muted().Width(3))) ta := createTextArea(nil) diff --git a/packages/tui/internal/components/chat/message.go b/packages/tui/internal/components/chat/message.go index 44aceea93..3315d4ba3 100644 --- a/packages/tui/internal/components/chat/message.go +++ b/packages/tui/internal/components/chat/message.go @@ -216,7 +216,7 @@ func renderText(message client.MessageInfo, text string, author string) string { align = lipgloss.Left } - textWidth := lipgloss.Width(text) + textWidth := max(lipgloss.Width(text), lipgloss.Width(info)) markdownWidth := min(textWidth, width-padding-4) // -4 for the border and padding content := toMarkdown(text, markdownWidth, t.BackgroundSubtle()) content = lipgloss.JoinVertical(align, content, info) @@ -299,13 +299,9 @@ func renderToolInvocation( body := "" error := "" finished := result != nil && *result != "" - if finished { - body = *result - } if e, ok := metadata.Get("error"); ok && e.(bool) == true { if m, ok := metadata.Get("message"); ok { - body = "" // don't show the body if there's an error style = style.BorderLeftForeground(t.Error()) error = styles.BaseStyle(). Background(t.BackgroundSubtle()). @@ -336,58 +332,61 @@ func renderToolInvocation( case "opencode_read": toolArgs = renderArgs(&toolArgsMap, "filePath") title = fmt.Sprintf("Read: %s %s", toolArgs, elapsed) - body = "" if preview, ok := metadata.Get("preview"); ok && toolArgsMap["filePath"] != nil { filename := toolArgsMap["filePath"].(string) body = preview.(string) body = renderFile(filename, body, WithTruncate(6)) } case "opencode_edit": - filename := toolArgsMap["filePath"].(string) - title = fmt.Sprintf("Edit: %s %s", relative(filename), elapsed) - if d, ok := metadata.Get("diff"); ok { - patch := d.(string) - var formattedDiff string - if layout.Current.Viewport.Width < 80 { - formattedDiff, _ = diff.FormatUnifiedDiff( - filename, - patch, - diff.WithWidth(layout.Current.Container.Width-2), + if filename, ok := toolArgsMap["filePath"].(string); ok { + title = fmt.Sprintf("Edit: %s %s", relative(filename), elapsed) + if d, ok := metadata.Get("diff"); ok { + patch := d.(string) + var formattedDiff string + if layout.Current.Viewport.Width < 80 { + formattedDiff, _ = diff.FormatUnifiedDiff( + filename, + patch, + diff.WithWidth(layout.Current.Container.Width-2), + ) + } else { + diffWidth := min(layout.Current.Viewport.Width-2, 120) + formattedDiff, _ = diff.FormatDiff(filename, patch, diff.WithTotalWidth(diffWidth)) + } + formattedDiff = strings.TrimSpace(formattedDiff) + formattedDiff = lipgloss.NewStyle(). + BorderStyle(lipgloss.ThickBorder()). + BorderForeground(t.BackgroundSubtle()). + BorderLeft(true). + BorderRight(true). + Render(formattedDiff) + + if showResult { + style = style.Width(lipgloss.Width(formattedDiff)) + title += "\n" + } + + body = strings.TrimSpace(formattedDiff) + body = lipgloss.Place( + layout.Current.Viewport.Width, + lipgloss.Height(body)+1, + lipgloss.Center, + lipgloss.Top, + body, ) - } else { - diffWidth := min(layout.Current.Viewport.Width-2, 120) - formattedDiff, _ = diff.FormatDiff(filename, patch, diff.WithTotalWidth(diffWidth)) - } - formattedDiff = strings.TrimSpace(formattedDiff) - formattedDiff = lipgloss.NewStyle(). - BorderStyle(lipgloss.ThickBorder()). - BorderForeground(t.BackgroundSubtle()). - BorderLeft(true). - BorderRight(true). - Render(formattedDiff) - - if showResult { - style = style.Width(lipgloss.Width(formattedDiff)) - title += "\n" } - - body = strings.TrimSpace(formattedDiff) - body = lipgloss.Place( - layout.Current.Viewport.Width, - lipgloss.Height(body)+1, - lipgloss.Center, - lipgloss.Top, - body, - ) } case "opencode_write": - filename := toolArgsMap["filePath"].(string) - title = fmt.Sprintf("Write: %s %s", relative(filename), elapsed) - content := toolArgsMap["content"].(string) - body = renderFile(filename, content) + if filename, ok := toolArgsMap["filePath"].(string); ok { + title = fmt.Sprintf("Write: %s %s", relative(filename), elapsed) + if content, ok := toolArgsMap["content"].(string); ok { + body = renderFile(filename, content) + } + } case "opencode_bash": - description := toolArgsMap["description"].(string) - title = fmt.Sprintf("Shell: %s %s", description, elapsed) + if description, ok := toolArgsMap["description"].(string); ok { + title = fmt.Sprintf("Shell: %s %s", description, elapsed) + } if stdout, ok := metadata.Get("stdout"); ok { command := toolArgsMap["command"].(string) stdout := stdout.(string) @@ -396,18 +395,20 @@ func renderToolInvocation( body = renderContentBlock(body, WithFullWidth(), WithMarginBottom(1)) } case "opencode_webfetch": + toolArgs = renderArgs(&toolArgsMap, "url") title = fmt.Sprintf("Fetching: %s %s", toolArgs, elapsed) - format := toolArgsMap["format"].(string) - body = truncateHeight(body, 10) - if format == "html" || format == "markdown" { - body = toMarkdown(body, innerWidth, t.BackgroundSubtle()) + if format, ok := toolArgsMap["format"].(string); ok { + body = *result + body = truncateHeight(body, 10) + if format == "html" || format == "markdown" { + body = toMarkdown(body, innerWidth, t.BackgroundSubtle()) + } + body = renderContentBlock(body, WithFullWidth(), WithMarginBottom(1)) } - body = renderContentBlock(body, WithFullWidth(), WithMarginBottom(1)) case "opencode_todowrite": title = fmt.Sprintf("Planning %s", elapsed) if to, ok := metadata.Get("todos"); ok && finished { - body = "" todos := to.([]any) for _, todo := range todos { t := todo.(map[string]any) @@ -416,7 +417,7 @@ func renderToolInvocation( case "completed": body += fmt.Sprintf("- [x] %s\n", content) // case "in-progress": - // body += fmt.Sprintf("- [ ] _%s_\n", content) + // body += fmt.Sprintf("- [ ] %s\n", content) default: body += fmt.Sprintf("- [ ] %s\n", content) } @@ -427,6 +428,13 @@ func renderToolInvocation( default: toolName := renderToolName(toolCall.ToolName) title = fmt.Sprintf("%s: %s %s", toolName, toolArgs, elapsed) + body = *result + body = truncateHeight(body, 10) + body = renderContentBlock(body, WithFullWidth(), WithMarginBottom(1)) + } + + if body == "" && error == "" { + body = *result body = truncateHeight(body, 10) body = renderContentBlock(body, WithFullWidth(), WithMarginBottom(1)) } diff --git a/packages/tui/internal/components/chat/messages.go b/packages/tui/internal/components/chat/messages.go index 8ab11a54a..83c3898a7 100644 --- a/packages/tui/internal/components/chat/messages.go +++ b/packages/tui/internal/components/chat/messages.go @@ -245,7 +245,7 @@ func (m *messagesComponent) header() string { base := styles.BaseStyle().Render muted := styles.Muted().Render headerLines := []string{} - headerLines = append(headerLines, toMarkdown("# "+m.app.Session.Title, width-4, t.Background())) + headerLines = append(headerLines, toMarkdown("# "+m.app.Session.Title, width-6, t.Background())) if m.app.Session.Share != nil && m.app.Session.Share.Url != "" { headerLines = append(headerLines, muted(m.app.Session.Share.Url)) } else { @@ -256,6 +256,7 @@ func (m *messagesComponent) header() string { header = styles.BaseStyle(). Width(width). PaddingLeft(2). + PaddingRight(2). // Background(t.BackgroundElement()). BorderLeft(true). BorderRight(true). |
