mirror of
https://github.com/aljazceru/opencode.git
synced 2025-12-24 11:14:23 +01:00
wip: refactoring tui
This commit is contained in:
@@ -1,32 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"os/signal"
|
||||
|
||||
"github.com/sst/opencode/pkg/app"
|
||||
"github.com/sst/opencode/pkg/server"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
|
||||
cwd, _ := os.Getwd()
|
||||
app, err := app.New(ctx, cwd)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
server, err := server.New(app)
|
||||
|
||||
var wg errgroup.Group
|
||||
wg.Go(func() error {
|
||||
defer stop()
|
||||
return server.Start(ctx)
|
||||
})
|
||||
|
||||
<-ctx.Done()
|
||||
|
||||
wg.Wait()
|
||||
}
|
||||
26
cmd/root.go
26
cmd/root.go
@@ -13,35 +13,15 @@ import (
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
zone "github.com/lrstanley/bubblezone"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/sst/opencode/internal/app"
|
||||
"github.com/sst/opencode/internal/config"
|
||||
"github.com/sst/opencode/internal/logging"
|
||||
"github.com/sst/opencode/internal/lsp/discovery"
|
||||
"github.com/sst/opencode/internal/pubsub"
|
||||
"github.com/sst/opencode/internal/tui"
|
||||
"github.com/sst/opencode/internal/tui/app"
|
||||
"github.com/sst/opencode/internal/version"
|
||||
)
|
||||
|
||||
type SessionIDHandler struct {
|
||||
slog.Handler
|
||||
app *app.App
|
||||
}
|
||||
|
||||
func (h *SessionIDHandler) Handle(ctx context.Context, r slog.Record) error {
|
||||
if h.app != nil {
|
||||
sessionID := h.app.CurrentSession.ID
|
||||
if sessionID != "" {
|
||||
r.AddAttrs(slog.String("session_id", sessionID))
|
||||
}
|
||||
}
|
||||
return h.Handler.Handle(ctx, r)
|
||||
}
|
||||
|
||||
func (h *SessionIDHandler) WithApp(app *app.App) *SessionIDHandler {
|
||||
h.app = app
|
||||
return h
|
||||
}
|
||||
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "OpenCode",
|
||||
Short: "A terminal AI assistant for software development",
|
||||
@@ -244,10 +224,6 @@ func setupSubscriptions(app *app.App, parentCtx context.Context) (chan tea.Msg,
|
||||
wg := sync.WaitGroup{}
|
||||
ctx, cancel := context.WithCancel(parentCtx) // Inherit from parent context
|
||||
|
||||
// setupSubscriber(ctx, &wg, "logging", app.Logs.Subscribe, ch)
|
||||
// setupSubscriber(ctx, &wg, "sessions", app.Sessions.Subscribe, ch)
|
||||
// setupSubscriber(ctx, &wg, "messages", app.Messages.Subscribe, ch)
|
||||
// setupSubscriber(ctx, &wg, "permissions", app.Permissions.Subscribe, ch)
|
||||
setupSubscriber(ctx, &wg, "status", app.Status.Subscribe, ch)
|
||||
|
||||
cleanupFunc := func() {
|
||||
|
||||
143
cmd/root_test.go
143
cmd/root_test.go
@@ -1,143 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCheckStdinPipe(t *testing.T) {
|
||||
// Save original stdin
|
||||
origStdin := os.Stdin
|
||||
|
||||
// Restore original stdin when test completes
|
||||
defer func() {
|
||||
os.Stdin = origStdin
|
||||
}()
|
||||
|
||||
// Test case 1: Data is piped in
|
||||
t.Run("WithPipedData", func(t *testing.T) {
|
||||
// Create a pipe
|
||||
r, w, err := os.Pipe()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create pipe: %v", err)
|
||||
}
|
||||
|
||||
// Replace stdin with our pipe
|
||||
os.Stdin = r
|
||||
|
||||
// Write test data to the pipe
|
||||
testData := "test piped input"
|
||||
go func() {
|
||||
defer w.Close()
|
||||
w.Write([]byte(testData))
|
||||
}()
|
||||
|
||||
// Call the function
|
||||
data, hasPiped := checkStdinPipe()
|
||||
|
||||
// Check results
|
||||
if !hasPiped {
|
||||
t.Error("Expected hasPiped to be true, got false")
|
||||
}
|
||||
if data != testData {
|
||||
t.Errorf("Expected data to be %q, got %q", testData, data)
|
||||
}
|
||||
})
|
||||
|
||||
// Test case 2: No data is piped in (simulated terminal)
|
||||
t.Run("WithoutPipedData", func(t *testing.T) {
|
||||
// Create a temporary file to simulate a terminal
|
||||
tmpFile, err := os.CreateTemp("", "terminal-sim")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create temp file: %v", err)
|
||||
}
|
||||
defer os.Remove(tmpFile.Name())
|
||||
defer tmpFile.Close()
|
||||
|
||||
// Open the file for reading
|
||||
f, err := os.Open(tmpFile.Name())
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to open temp file: %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
// Replace stdin with our file
|
||||
os.Stdin = f
|
||||
|
||||
// Call the function
|
||||
data, hasPiped := checkStdinPipe()
|
||||
|
||||
// Check results
|
||||
if hasPiped {
|
||||
t.Error("Expected hasPiped to be false, got true")
|
||||
}
|
||||
if data != "" {
|
||||
t.Errorf("Expected data to be empty, got %q", data)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// This is a mock implementation for testing since we can't easily mock os.Stdin.Stat()
|
||||
// in a way that would return the correct Mode() for our test cases
|
||||
func mockCheckStdinPipe(reader io.Reader, isPipe bool) (string, bool) {
|
||||
if !isPipe {
|
||||
return "", false
|
||||
}
|
||||
|
||||
data, err := io.ReadAll(reader)
|
||||
if err != nil {
|
||||
return "", false
|
||||
}
|
||||
|
||||
if len(data) > 0 {
|
||||
return string(data), true
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
func TestMockCheckStdinPipe(t *testing.T) {
|
||||
// Test with data
|
||||
t.Run("WithData", func(t *testing.T) {
|
||||
testData := "test data"
|
||||
reader := bytes.NewBufferString(testData)
|
||||
|
||||
data, hasPiped := mockCheckStdinPipe(reader, true)
|
||||
|
||||
if !hasPiped {
|
||||
t.Error("Expected hasPiped to be true, got false")
|
||||
}
|
||||
if data != testData {
|
||||
t.Errorf("Expected data to be %q, got %q", testData, data)
|
||||
}
|
||||
})
|
||||
|
||||
// Test without data
|
||||
t.Run("WithoutData", func(t *testing.T) {
|
||||
reader := bytes.NewBufferString("")
|
||||
|
||||
data, hasPiped := mockCheckStdinPipe(reader, true)
|
||||
|
||||
if hasPiped {
|
||||
t.Error("Expected hasPiped to be false, got true")
|
||||
}
|
||||
if data != "" {
|
||||
t.Errorf("Expected data to be empty, got %q", data)
|
||||
}
|
||||
})
|
||||
|
||||
// Test not a pipe
|
||||
t.Run("NotAPipe", func(t *testing.T) {
|
||||
reader := bytes.NewBufferString("data that should be ignored")
|
||||
|
||||
data, hasPiped := mockCheckStdinPipe(reader, false)
|
||||
|
||||
if hasPiped {
|
||||
t.Error("Expected hasPiped to be false, got true")
|
||||
}
|
||||
if data != "" {
|
||||
t.Errorf("Expected data to be empty, got %q", data)
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user