fix: use ANSI colors codes instead of RGB (#14665)

* chore: add command for showing colors

* fix: use ANSI color codes instead of RGB

* feat: add '--no-color' flag

* fix: revert colors

* chore: change colors

* fix: update golden files

* fix: replace blue with brightBlue

* fix: drop '> ' for unfocused prompts

* fix: run 'make fmt'

* chore: allow disabling color with env flags

* fix: apply fixes from feedback

* fix: run 'make gen'

* fix: refactor janky code

* fix: re-add public function

* fix: re-add init for non-color tests

* fix: move styles to 'init' that can be

* fix: stop overwriting entire DefaultStyles

* fix: make code and field obey --no-color

* fix: rip out '--no-color' due to race condition

We still support `NO_COLOR` env variable through termenv's
`EnvColorProfile`. The reason for the race condition is that
`DefaultStyles` is a global that we shouldn't mutate after `init`
is called, but we have to mutate it after `init` has ran to have
serpent collect the cli flags and env vars for us.

* fix: apply nit

* fix: simplify code && hide command

* fix: newline shouldn't be themed

* fix: appease the linter
This commit is contained in:
Danielle Maywood
2024-09-17 14:21:24 +01:00
committed by GitHub
parent 6ff9a05832
commit 14d3e300d3
3 changed files with 73 additions and 27 deletions

View File

@ -37,17 +37,21 @@ var (
) )
var ( var (
Green = Color("#04B575") // ANSI color codes
Red = Color("#ED567A") red = Color("1")
Fuchsia = Color("#EE6FF8") green = Color("2")
Yellow = Color("#ECFD65") yellow = Color("3")
Blue = Color("#5000ff") magenta = Color("5")
white = Color("7")
brightBlue = Color("12")
brightMagenta = Color("13")
) )
// Color returns a color for the given string. // Color returns a color for the given string.
func Color(s string) termenv.Color { func Color(s string) termenv.Color {
colorOnce.Do(func() { colorOnce.Do(func() {
color = termenv.NewOutput(os.Stdout).ColorProfile() color = termenv.NewOutput(os.Stdout).EnvColorProfile()
if flag.Lookup("test.v") != nil { if flag.Lookup("test.v") != nil {
// Use a consistent colorless profile in tests so that results // Use a consistent colorless profile in tests so that results
// are deterministic. // are deterministic.
@ -123,42 +127,45 @@ func init() {
DefaultStyles = Styles{ DefaultStyles = Styles{
Code: pretty.Style{ Code: pretty.Style{
ifTerm(pretty.XPad(1, 1)), ifTerm(pretty.XPad(1, 1)),
pretty.FgColor(Red), pretty.FgColor(Color("#ED567A")),
pretty.BgColor(color.Color("#2c2c2c")), pretty.BgColor(Color("#2C2C2C")),
}, },
DateTimeStamp: pretty.Style{ DateTimeStamp: pretty.Style{
pretty.FgColor(color.Color("#7571F9")), pretty.FgColor(brightBlue),
}, },
Error: pretty.Style{ Error: pretty.Style{
pretty.FgColor(Red), pretty.FgColor(red),
}, },
Field: pretty.Style{ Field: pretty.Style{
pretty.XPad(1, 1), pretty.XPad(1, 1),
pretty.FgColor(color.Color("#FFFFFF")), pretty.FgColor(Color("#FFFFFF")),
pretty.BgColor(color.Color("#2b2a2a")), pretty.BgColor(Color("#2B2A2A")),
},
Fuchsia: pretty.Style{
pretty.FgColor(brightMagenta),
},
FocusedPrompt: pretty.Style{
pretty.FgColor(white),
pretty.Wrap("> ", ""),
pretty.FgColor(brightBlue),
}, },
Keyword: pretty.Style{ Keyword: pretty.Style{
pretty.FgColor(Green), pretty.FgColor(green),
}, },
Placeholder: pretty.Style{ Placeholder: pretty.Style{
pretty.FgColor(color.Color("#4d46b3")), pretty.FgColor(magenta),
}, },
Prompt: pretty.Style{ Prompt: pretty.Style{
pretty.FgColor(color.Color("#5C5C5C")), pretty.FgColor(white),
pretty.Wrap("> ", ""), pretty.Wrap(" ", ""),
}, },
Warn: pretty.Style{ Warn: pretty.Style{
pretty.FgColor(Yellow), pretty.FgColor(yellow),
}, },
Wrap: pretty.Style{ Wrap: pretty.Style{
pretty.LineWrap(80), pretty.LineWrap(80),
}, },
} }
DefaultStyles.FocusedPrompt = append(
DefaultStyles.Prompt,
pretty.FgColor(Blue),
)
} }
// ValidateNotEmpty is a helper function to disallow empty inputs! // ValidateNotEmpty is a helper function to disallow empty inputs!

View File

@ -256,7 +256,7 @@ func (m selectModel) View() string {
if m.cursor == start+i { if m.cursor == start+i {
style = pretty.Style{ style = pretty.Style{
pretty.Wrap("> ", ""), pretty.Wrap("> ", ""),
pretty.FgColor(Green), DefaultStyles.Keyword,
} }
} }
@ -481,13 +481,13 @@ func (m multiSelectModel) View() string {
o := option.option o := option.option
if m.cursor == i { if m.cursor == i {
cursor = pretty.Sprint(pretty.FgColor(Green), "> ") cursor = pretty.Sprint(DefaultStyles.Keyword, "> ")
chosen = pretty.Sprint(pretty.FgColor(Green), "[ ]") chosen = pretty.Sprint(DefaultStyles.Keyword, "[ ]")
o = pretty.Sprint(pretty.FgColor(Green), o) o = pretty.Sprint(DefaultStyles.Keyword, o)
} }
if option.chosen { if option.chosen {
chosen = pretty.Sprint(pretty.FgColor(Green), "[x]") chosen = pretty.Sprint(DefaultStyles.Keyword, "[x]")
} }
_, _ = s.WriteString(fmt.Sprintf( _, _ = s.WriteString(fmt.Sprintf(

View File

@ -18,6 +18,7 @@ import (
"github.com/coder/coder/v2/cli/cliui" "github.com/coder/coder/v2/cli/cliui"
"github.com/coder/coder/v2/coderd/database/dbtime" "github.com/coder/coder/v2/coderd/database/dbtime"
"github.com/coder/coder/v2/codersdk" "github.com/coder/coder/v2/codersdk"
"github.com/coder/pretty"
"github.com/coder/serpent" "github.com/coder/serpent"
) )
@ -37,6 +38,44 @@ func main() {
}, },
} }
root.Children = append(root.Children, &serpent.Command{
Use: "colors",
Hidden: true,
Handler: func(inv *serpent.Invocation) error {
pretty.Fprintf(inv.Stdout, cliui.DefaultStyles.Code, "This is a code message")
_, _ = fmt.Fprintln(inv.Stdout)
pretty.Fprintf(inv.Stdout, cliui.DefaultStyles.DateTimeStamp, "This is a datetimestamp message")
_, _ = fmt.Fprintln(inv.Stdout)
pretty.Fprintf(inv.Stdout, cliui.DefaultStyles.Error, "This is an error message")
_, _ = fmt.Fprintln(inv.Stdout)
pretty.Fprintf(inv.Stdout, cliui.DefaultStyles.Field, "This is a field message")
_, _ = fmt.Fprintln(inv.Stdout)
pretty.Fprintf(inv.Stdout, cliui.DefaultStyles.Keyword, "This is a keyword message")
_, _ = fmt.Fprintln(inv.Stdout)
pretty.Fprintf(inv.Stdout, cliui.DefaultStyles.Placeholder, "This is a placeholder message")
_, _ = fmt.Fprintln(inv.Stdout)
pretty.Fprintf(inv.Stdout, cliui.DefaultStyles.Prompt, "This is a prompt message")
_, _ = fmt.Fprintln(inv.Stdout)
pretty.Fprintf(inv.Stdout, cliui.DefaultStyles.FocusedPrompt, "This is a focused prompt message")
_, _ = fmt.Fprintln(inv.Stdout)
pretty.Fprintf(inv.Stdout, cliui.DefaultStyles.Fuchsia, "This is a fuchsia message")
_, _ = fmt.Fprintln(inv.Stdout)
pretty.Fprintf(inv.Stdout, cliui.DefaultStyles.Warn, "This is a warning message")
_, _ = fmt.Fprintln(inv.Stdout)
return nil
},
})
root.Children = append(root.Children, &serpent.Command{ root.Children = append(root.Children, &serpent.Command{
Use: "prompt", Use: "prompt",
Handler: func(inv *serpent.Invocation) error { Handler: func(inv *serpent.Invocation) error {