diff options
Diffstat (limited to 'packages/tui/internal')
| -rw-r--r-- | packages/tui/internal/commands/command.go | 22 | ||||
| -rw-r--r-- | packages/tui/internal/components/ide/ide.go | 112 | ||||
| -rw-r--r-- | packages/tui/internal/tui/tui.go | 32 |
3 files changed, 164 insertions, 2 deletions
diff --git a/packages/tui/internal/commands/command.go b/packages/tui/internal/commands/command.go index dde49e824..6015ab85b 100644 --- a/packages/tui/internal/commands/command.go +++ b/packages/tui/internal/commands/command.go @@ -63,17 +63,37 @@ func (r CommandRegistry) Sorted() []Command { commands = append(commands, command) } slices.SortFunc(commands, func(a, b Command) int { + // Priority order: session_new, session_share, model_list, app_help first, app_exit last + priorityOrder := map[CommandName]int{ + SessionNewCommand: 0, + AppHelpCommand: 1, + SessionShareCommand: 2, + ModelListCommand: 3, + } + + aPriority, aHasPriority := priorityOrder[a.Name] + bPriority, bHasPriority := priorityOrder[b.Name] + + if aHasPriority && bHasPriority { + return aPriority - bPriority + } + if aHasPriority { + return -1 + } + if bHasPriority { + return 1 + } if a.Name == AppExitCommand { return 1 } if b.Name == AppExitCommand { return -1 } + return strings.Compare(string(a.Name), string(b.Name)) }) return commands } - func (r CommandRegistry) Matches(msg tea.KeyPressMsg, leader bool) []Command { var matched []Command for _, command := range r.Sorted() { diff --git a/packages/tui/internal/components/ide/ide.go b/packages/tui/internal/components/ide/ide.go new file mode 100644 index 000000000..cb10f0fc9 --- /dev/null +++ b/packages/tui/internal/components/ide/ide.go @@ -0,0 +1,112 @@ +package ide + +import ( + "fmt" + "strings" + + tea "github.com/charmbracelet/bubbletea/v2" + "github.com/charmbracelet/lipgloss/v2" + "github.com/charmbracelet/lipgloss/v2/compat" + "github.com/sst/opencode/internal/styles" + "github.com/sst/opencode/internal/theme" +) + +type IdeComponent interface { + tea.ViewModel + SetSize(width, height int) tea.Cmd + SetBackgroundColor(color compat.AdaptiveColor) +} + +type ideComponent struct { + width, height int + background *compat.AdaptiveColor +} + +func (c *ideComponent) SetSize(width, height int) tea.Cmd { + c.width = width + c.height = height + return nil +} + +func (c *ideComponent) SetBackgroundColor(color compat.AdaptiveColor) { + c.background = &color +} + +func (c *ideComponent) View() string { + t := theme.CurrentTheme() + + triggerStyle := styles.NewStyle().Foreground(t.Primary()).Bold(true) + descriptionStyle := styles.NewStyle().Foreground(t.Text()) + + if c.background != nil { + triggerStyle = triggerStyle.Background(*c.background) + descriptionStyle = descriptionStyle.Background(*c.background) + } + + // VSCode shortcuts data + shortcuts := []struct { + shortcut string + description string + }{ + {"Cmd+Esc", "open opencode in VS Code"}, + {"Cmd+Opt+K", "insert file from VS Code"}, + } + + // Calculate column widths + maxShortcutWidth := 0 + maxDescriptionWidth := 0 + + for _, shortcut := range shortcuts { + if len(shortcut.shortcut) > maxShortcutWidth { + maxShortcutWidth = len(shortcut.shortcut) + } + if len(shortcut.description) > maxDescriptionWidth { + maxDescriptionWidth = len(shortcut.description) + } + } + + // Add padding between columns + columnPadding := 3 + + // Build the output + var output strings.Builder + + maxWidth := 0 + for _, shortcut := range shortcuts { + // Pad each column to align properly + shortcutText := fmt.Sprintf("%-*s", maxShortcutWidth, shortcut.shortcut) + description := fmt.Sprintf("%-*s", maxDescriptionWidth, shortcut.description) + + // Apply styles and combine + line := triggerStyle.Render(shortcutText) + + triggerStyle.Render(strings.Repeat(" ", columnPadding)) + + descriptionStyle.Render(description) + + output.WriteString(line + "\n") + maxWidth = max(maxWidth, lipgloss.Width(line)) + } + + // Remove trailing newline + result := strings.TrimSuffix(output.String(), "\n") + if c.background != nil { + result = styles.NewStyle().Background(*c.background).Width(maxWidth).Render(result) + } + + return result +} + +type Option func(*ideComponent) + +func WithBackground(background compat.AdaptiveColor) Option { + return func(c *ideComponent) { + c.background = &background + } +} + +func New(opts ...Option) IdeComponent { + c := &ideComponent{} + for _, opt := range opts { + opt(c) + } + return c +} diff --git a/packages/tui/internal/tui/tui.go b/packages/tui/internal/tui/tui.go index 6ff8f9282..bd0eaeada 100644 --- a/packages/tui/internal/tui/tui.go +++ b/packages/tui/internal/tui/tui.go @@ -22,6 +22,7 @@ import ( cmdcomp "github.com/sst/opencode/internal/components/commands" "github.com/sst/opencode/internal/components/dialog" "github.com/sst/opencode/internal/components/fileviewer" + "github.com/sst/opencode/internal/components/ide" "github.com/sst/opencode/internal/components/modal" "github.com/sst/opencode/internal/components/status" "github.com/sst/opencode/internal/components/toast" @@ -347,6 +348,11 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { "opencode updated to "+msg.Properties.Version+", restart to apply.", toast.WithTitle("New version installed"), ) + case opencode.EventListResponseEventIdeInstalled: + return a, toast.NewSuccessToast( + "Installed the opencode extension in "+msg.Properties.Ide, + toast.WithTitle(msg.Properties.Ide+" extension installed"), + ) case opencode.EventListResponseEventSessionDeleted: if a.app.Session != nil && msg.Properties.Info.ID == a.app.Session.ID { a.app.Session = &opencode.Session{} @@ -623,10 +629,17 @@ func (a appModel) home() string { logoAndVersion, styles.WhitespaceStyle(t.Background()), ) + + // Use limit of 4 for vscode, 6 for others + limit := 6 + if os.Getenv("OPENCODE_CALLER") == "vscode" { + limit = 4 + } + commandsView := cmdcomp.New( a.app, cmdcomp.WithBackground(t.Background()), - cmdcomp.WithLimit(6), + cmdcomp.WithLimit(limit), ) cmds := lipgloss.PlaceHorizontal( effectiveWidth, @@ -635,6 +648,19 @@ func (a appModel) home() string { styles.WhitespaceStyle(t.Background()), ) + // Add VSCode shortcuts if in VSCode environment + var ideShortcuts string + if os.Getenv("OPENCODE_CALLER") == "vscode" { + ideView := ide.New() + ideView.SetBackgroundColor(t.Background()) + ideShortcuts = lipgloss.PlaceHorizontal( + effectiveWidth, + lipgloss.Center, + ideView.View(), + styles.WhitespaceStyle(t.Background()), + ) + } + lines := []string{} lines = append(lines, "") lines = append(lines, "") @@ -642,6 +668,10 @@ func (a appModel) home() string { lines = append(lines, "") lines = append(lines, "") lines = append(lines, cmds) + if os.Getenv("OPENCODE_CALLER") == "vscode" { + lines = append(lines, "") + lines = append(lines, ideShortcuts) + } lines = append(lines, "") lines = append(lines, "") |
