Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 23 additions & 10 deletions internal/colour/colour.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,36 @@ const (
//
// If $NO_COLOR is set, text will be returned unmodified.
func Title(text string) string {
if noColour() {
return text
}
return CodeTitle + text + CodeReset
return sprint(CodeTitle, text)
}

// Bold returns the given text in bold white.
//
// If $NO_COLOR is set, text will be returned unmodified.
func Bold(text string) string {
if noColour() {
return sprint(CodeBold, text)
}

// sprint returns a string with a given colour and the reset code.
//
// It handles checking for NO_COLOR and FORCE_COLOR.
func sprint(code, text string) string {
// TODO(@FollowTheProcess): I don't like checking *every* time but doing it
// via e.g. sync.Once means that tests are annoying unless we ensure env vars are
// set at the process level
noColor := os.Getenv("NO_COLOR") != ""
forceColor := os.Getenv("FORCE_COLOR") != ""

// $FORCE_COLOR overrides $NO_COLOR
if forceColor {
return code + text + CodeReset
}

// $NO_COLOR is next
if noColor {
return text
}
return CodeBold + text + CodeReset
}

// noColour returns whether the $NO_COLOR env var was set.
func noColour() bool {
return os.Getenv("NO_COLOR") != ""
// Normal
return code + text + CodeReset
}
44 changes: 39 additions & 5 deletions internal/colour/colour_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ import (

func TestColour(t *testing.T) {
tests := []struct {
name string // Name of the test case
text string // Text to colour
fn func(text string) string // Printer function to return the coloured version of text
want string // Expected result containing ANSI escape codes
noColor bool // Whether to set the $NO_COLOR env var
name string // Name of the test case
text string // Text to colour
fn func(text string) string // Printer function to return the coloured version of text
want string // Expected result containing ANSI escape codes
noColor bool // Whether to set the $NO_COLOR env var
forceColor bool // Whether to set the $FORCE_COLOR env var
}{
{
name: "bold",
Expand All @@ -28,6 +29,21 @@ func TestColour(t *testing.T) {
noColor: true,
want: "hello bold",
},
{
name: "bold force color",
text: "hello bold",
fn: colour.Bold,
want: colour.CodeBold + "hello bold" + colour.CodeReset,
forceColor: true,
},
{
name: "bold force color and no color",
text: "hello bold",
fn: colour.Bold,
want: colour.CodeBold + "hello bold" + colour.CodeReset,
forceColor: true, // force should override no
noColor: true,
},
{
name: "title",
text: "Section",
Expand All @@ -41,13 +57,31 @@ func TestColour(t *testing.T) {
noColor: true,
want: "Section",
},
{
name: "title force color",
text: "Section",
fn: colour.Title,
want: colour.CodeTitle + "Section" + colour.CodeReset,
forceColor: true,
},
{
name: "title force color and no color",
text: "Section",
fn: colour.Title,
want: colour.CodeTitle + "Section" + colour.CodeReset,
forceColor: true, // force should override no
noColor: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.noColor {
t.Setenv("NO_COLOR", "true")
}
if tt.forceColor {
t.Setenv("FORCE_COLOR", "true")
}
got := tt.fn(tt.text)
test.Equal(t, got, tt.want)
})
Expand Down