Skip to content

Commit 3713667

Browse files
authored
libs/cmdio: centralize lipgloss renderer initialization (#5903)
Add `cmdio.NewRenderer(ctx, w)`, which builds a `lipgloss.Renderer` and forces the Ascii profile when the writer has no color, returning the renderer plus the resolved `colorOn` bool. Callers stop repeating the `NewRenderer` + `SetColorProfile(termenv.Ascii)` dance. This makes `cmdio` the sole importer of `muesli/termenv`, so it's promoted from indirect to a direct dependency (with `NOTICE` entry). This pull request and its description were written by Isaac.
1 parent c9a8fb0 commit 3713667

4 files changed

Lines changed: 34 additions & 1 deletion

File tree

NOTICE

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,10 @@ mattn/go-isatty - https://github.com/mattn/go-isatty
155155
Copyright (c) Yasuhiro MATSUMOTO <mattn.jp@gmail.com>
156156
License - https://github.com/mattn/go-isatty/blob/master/LICENSE
157157

158+
muesli/termenv - https://github.com/muesli/termenv
159+
Copyright (c) 2019 Christian Muehlhaeuser
160+
License - https://github.com/muesli/termenv/blob/master/LICENSE
161+
158162
sabhiram/go-gitignore - https://github.com/sabhiram/go-gitignore
159163
Copyright (c) 2015 Shaba Abhiram
160164
License - https://github.com/sabhiram/go-gitignore/blob/master/LICENSE

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ require (
2424
github.com/hexops/gotextdiff v1.0.3 // BSD-3-Clause
2525
github.com/jackc/pgx/v5 v5.10.0 // MIT
2626
github.com/mattn/go-isatty v0.0.22 // MIT
27+
github.com/muesli/termenv v0.16.0 // MIT
2728
github.com/palantir/pkg/yamlpatch v1.5.0 // BSD-3-Clause
2829
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // BSD-2-Clause
2930
github.com/quasilyte/go-ruleguard/dsl v0.3.22 // BSD-3-Clause
@@ -85,7 +86,6 @@ require (
8586
github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect
8687
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
8788
github.com/muesli/cancelreader v0.2.2 // indirect
88-
github.com/muesli/termenv v0.16.0 // indirect
8989
github.com/pkg/errors v0.9.1 // indirect
9090
github.com/pmezard/go-difflib v1.0.0 // indirect
9191
github.com/rivo/uniseg v0.4.7 // indirect

libs/cmdio/color.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ package cmdio
33
import (
44
"context"
55
"fmt"
6+
"io"
67
"strings"
78
"text/template"
89

910
"github.com/charmbracelet/lipgloss"
11+
"github.com/muesli/termenv"
1012
)
1113

1214
// SGR (Select Graphic Rendition) escapes; see
@@ -138,3 +140,17 @@ func PadLeft(s string, n int) string {
138140
}
139141
return s
140142
}
143+
144+
// NewRenderer returns a lipgloss renderer targeting w, along with whether w
145+
// supports color. When it does not (NO_COLOR, TERM=dumb, or w is piped or
146+
// redirected) the renderer is forced to the Ascii profile so every Style it
147+
// mints emits no SGR escapes. Callers still write rendered strings to w
148+
// themselves; the renderer only carries the color profile.
149+
func NewRenderer(ctx context.Context, w io.Writer) (*lipgloss.Renderer, bool) {
150+
color := SupportsColor(ctx, w)
151+
r := lipgloss.NewRenderer(w)
152+
if !color {
153+
r.SetColorProfile(termenv.Ascii)
154+
}
155+
return r, color
156+
}

libs/cmdio/color_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package cmdio_test
22

33
import (
4+
"bytes"
45
"context"
56
"testing"
67

78
"github.com/databricks/cli/libs/cmdio"
9+
"github.com/muesli/termenv"
810
"github.com/stretchr/testify/assert"
911
)
1012

@@ -126,6 +128,17 @@ func TestPadLeft(t *testing.T) {
126128
}
127129
}
128130

131+
func TestNewRendererForcesAsciiWhenNoColor(t *testing.T) {
132+
ctx := noColorContext(t)
133+
134+
// A bytes.Buffer is never a TTY, so the renderer must fall back to Ascii and
135+
// its styles must render without SGR escapes.
136+
r, color := cmdio.NewRenderer(ctx, &bytes.Buffer{})
137+
assert.False(t, color)
138+
assert.Equal(t, termenv.Ascii, r.ColorProfile())
139+
assert.Equal(t, "hi", r.NewStyle().Bold(true).Render("hi"))
140+
}
141+
129142
func TestRenderFuncMap(t *testing.T) {
130143
ctx := ttyContext(t)
131144
fm := cmdio.RenderFuncMap(ctx)

0 commit comments

Comments
 (0)