on main help sign in
fix(noninteractive): spinner text on light backgrounds
3398577Christian Rocha
internal/agent/agent.go+1−1
@@ -286,7 +286,7 @@ func (a *sessionAgent) Run(ctx context.Context, call SessionAgentCall) (*fantasy
286 // Strip leading newline from initial text content. This is is
286 // Strip leading newline from initial text content. This is is
287 // particularly important in non-interactive mode where leading
287 // particularly important in non-interactive mode where leading
288 // newlines are very visible.
288 // newlines are very visible.
289− if len(currentAssistant.Parts) == 0 && strings.HasPrefix(text, "\n") {
289+ if len(currentAssistant.Parts) == 0 {
290 text = strings.TrimPrefix(text, "\n")
290 text = strings.TrimPrefix(text, "\n")
291 }
291 }
292
292
internal/app/app.go+24−1
@@ -9,6 +9,7 @@ import (
9 "fmt"
9 "fmt"
10 "io"
10 "io"
11 "log/slog"
11 "log/slog"
12+ "os"
12 "sync"
13 "sync"
13 "time"
14 "time"
14
15
@@ -27,7 +28,11 @@ import (
27 "github.com/charmbracelet/crush/internal/permission"
28 "github.com/charmbracelet/crush/internal/permission"
28 "github.com/charmbracelet/crush/internal/pubsub"
29 "github.com/charmbracelet/crush/internal/pubsub"
29 "github.com/charmbracelet/crush/internal/session"
30 "github.com/charmbracelet/crush/internal/session"
31+ "github.com/charmbracelet/crush/internal/tui/components/anim"
32+ "github.com/charmbracelet/crush/internal/tui/styles"
33+ "github.com/charmbracelet/lipgloss/v2"
30 "github.com/charmbracelet/x/ansi"
34 "github.com/charmbracelet/x/ansi"
35+ "github.com/charmbracelet/x/exp/charmtone"
31)
36)
32
37
33type App struct {
38type App struct {
@@ -114,7 +119,25 @@ func (app *App) RunNonInteractive(ctx context.Context, output io.Writer, prompt
114
119
115 var spinner *format.Spinner
120 var spinner *format.Spinner
116 if !quiet {
121 if !quiet {
122+ t := styles.CurrentTheme()
123+
124+ // Detect background color to set the appropriate color for the
125+ // spinner's 'Generating...' text. Without this, that text would be
126+ // unreadable in light terminals.
127+ hasDarkBG := true
128+ if f, ok := output.(*os.File); ok {
129+ hasDarkBG = lipgloss.HasDarkBackground(os.Stdin, f)
130+ }
131+ defaultFG := lipgloss.LightDark(hasDarkBG)(charmtone.Pepper, t.FgBase)
132+
117− spinner = format.NewSpinner(ctx, cancel, "Generating")
133+ spinner = format.NewSpinner(ctx, cancel, anim.Settings{
134+ Size: 10,
135+ Label: "Generating",
136+ LabelColor: defaultFG,
137+ GradColorA: t.Primary,
138+ GradColorB: t.Secondary,
139+ CycleColors: true,
140+ })
118 spinner.Start()
141 spinner.Start()
119 }
142 }
120
143
internal/format/spinner.go+5−18
@@ -8,7 +8,6 @@ import (
8
8
9 tea "github.com/charmbracelet/bubbletea/v2"
9 tea "github.com/charmbracelet/bubbletea/v2"
10 "github.com/charmbracelet/crush/internal/tui/components/anim"
10 "github.com/charmbracelet/crush/internal/tui/components/anim"
11− "github.com/charmbracelet/crush/internal/tui/styles"
12 "github.com/charmbracelet/x/ansi"
11 "github.com/charmbracelet/x/ansi"
13)
12)
14
13
@@ -42,28 +41,16 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
42}
41}
43
42
44// NewSpinner creates a new spinner with the given message
43// NewSpinner creates a new spinner with the given message
45−func NewSpinner(ctx context.Context, cancel context.CancelFunc, message string) *Spinner {
44+func NewSpinner(ctx context.Context, cancel context.CancelFunc, animSettings anim.Settings) *Spinner {
46− t := styles.CurrentTheme()
47− model := model{
45+ m := model{
48− anim: anim.New(anim.Settings{
46+ anim: anim.New(animSettings),
49− Size: 10,
50− Label: message,
51− LabelColor: t.FgBase,
52− GradColorA: t.Primary,
53− GradColorB: t.Secondary,
54− CycleColors: true,
55− }),
56 cancel: cancel,
47 cancel: cancel,
57 }
48 }
58
49
59− prog := tea.NewProgram(
60− model,
61− tea.WithOutput(os.Stderr),
50+ p := tea.NewProgram(m, tea.WithOutput(os.Stderr), tea.WithContext(ctx))
62− tea.WithContext(ctx),
63− )
64
51
65 return &Spinner{
52 return &Spinner{
66− prog: prog,
53+ prog: p,
67 done: make(chan struct{}, 1),
54 done: make(chan struct{}, 1),
68 }
55 }
69}
56}