Skip to content

Commit

Permalink
Test and document NO_COLOR support.
Browse files Browse the repository at this point in the history
  • Loading branch information
xiaq committed Aug 21, 2023
1 parent c61a5c7 commit e5e26f1
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 7 deletions.
4 changes: 4 additions & 0 deletions 0.20.0-release-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ Draft release notes for Elvish 0.20.0.
- The language server now supports showing the documentation of builtin
functions and variables on hover ([#1684](https://b.elv.sh/1684)).

- Elvish now respects the [`NO_COLOR`](https://no-color.org) environment
variable. Builtin UI elements as well as styled texts will no have colors if
it is set and non-empty.

# Notable bugfixes

- `has-value $li $v` now works correctly when `$li` is a list and `$v` is a
Expand Down
1 change: 1 addition & 0 deletions pkg/env/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package env
const (
HOME = "HOME"
LS_COLORS = "LS_COLORS"
NO_COLOR = "NO_COLOR"
PATH = "PATH"
PWD = "PWD"
SHLVL = "SHLVL"
Expand Down
5 changes: 5 additions & 0 deletions pkg/eval/builtin_fn_styled.d.elv
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ fn styled-segment {|object &fg-color=default &bg-color=default &bold=$false &dim
# [ANSI SGR code](https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_.28Select_Graphic_Rendition.29_parameters)
# is built to render the style.
#
# If the [`NO_COLOR`](https://no-color.org) environment variable is set and
# non-empty when Elvish starts, color output is suppressed. Modifications to
# `NO_COLOR` within Elvish (including from `rc.elv`) do not affect the current
# process, but will affect child Elvish processes.
#
# Examples:
#
# ```elvish
Expand Down
3 changes: 2 additions & 1 deletion pkg/shell/shell.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ func (p *Program) Run(fds [3]*os.File, args []string) error {
cleanup2 := initSignal(fds)
defer cleanup2()

ui.NoColor = os.Getenv("NO_COLOR") != ""
// https://no-color.org
ui.NoColor = os.Getenv(env.NO_COLOR) != ""
interactive := len(args) == 0
ev := p.makeEvaler(fds[2], interactive)
defer ev.PreExit()
Expand Down
37 changes: 31 additions & 6 deletions pkg/shell/shell_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,28 @@ func TestShell_LibPath_Legacy(t *testing.T) {
// Most high-level tests against Program are specific to either script mode or
// interactive mode, and are found in script_test.go and interact_test.go.

var noColorTests = []struct {
name string
value string
unset bool
wantRedFoo string
}{
{name: "unset", unset: true, wantRedFoo: "\033[;31mfoo\033[m"},
{name: "empty", value: "", wantRedFoo: "\033[;31mfoo\033[m"},
{name: "non-empty", value: "yes", wantRedFoo: "\033[mfoo"},
}

func TestShell_NO_COLOR(t *testing.T) {
for _, test := range noColorTests {
t.Run(test.name, func(t *testing.T) {
setOrUnsetenv(t, env.NO_COLOR, test.unset, test.value)
Test(t, &Program{},
ThatElvish("-c", "print (styled foo red)").
WritesStdout(test.wantRedFoo))
})
}
}

var incSHLVLTests = []struct {
name string
old string
Expand All @@ -104,12 +126,7 @@ var incSHLVLTests = []struct {
func TestShell_SHLVL(t *testing.T) {
for _, test := range incSHLVLTests {
t.Run(test.name, func(t *testing.T) {
if test.unset {
testutil.Unsetenv(t, env.SHLVL)
} else {
testutil.Setenv(t, env.SHLVL, test.old)
}

setOrUnsetenv(t, env.SHLVL, test.unset, test.old)
Test(t, &Program{},
ThatElvish("-c", "print $E:SHLVL").WritesStdout(test.wantNew))

Expand All @@ -128,6 +145,14 @@ func TestShell_SHLVL(t *testing.T) {
}
}

func setOrUnsetenv(t *testing.T, name string, unset bool, set string) {
if unset {
testutil.Unsetenv(t, name)
} else {
testutil.Setenv(t, name, set)
}
}

// Common test utilities.

func setupCleanHomePaths(t testutil.Cleanuper) string {
Expand Down
2 changes: 2 additions & 0 deletions pkg/ui/style.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"strings"
)

// NoColor can be set to true to suppress foreground and background colors when
// writing text to the terminal.
var NoColor bool = false

// Style specifies how something (mostly a string) shall be displayed.
Expand Down
11 changes: 11 additions & 0 deletions pkg/ui/style_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package ui

import (
"testing"

"src.elv.sh/pkg/testutil"
)

func TestStyleSGR(t *testing.T) {
Expand All @@ -20,6 +22,15 @@ func TestStyleSGR(t *testing.T) {
})
}

func TestStyleSGR_NoColor(t *testing.T) {
testutil.Set(t, &NoColor, true)
testTextVTString(t, []textVTStringTest{
{T("foo", FgRed), "\033[mfoo"},
{T("foo", BgRed), "\033[mfoo"},
{T("foo", FgRed, BgBlue), "\033[mfoo"},
})
}

type mergeFromOptionsTest struct {
style Style
options map[string]any
Expand Down

0 comments on commit e5e26f1

Please sign in to comment.