mirror of https://github.com/docker/compose.git
better support NO_COLOR by disabling colors, not ANSI TUI (#10434)
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
parent
90eda35f3d
commit
d762f5f473
|
@ -305,11 +305,13 @@ func RootCommand(streams command.Cli, backend api.Service) *cobra.Command { //no
|
||||||
logrus.SetLevel(logrus.TraceLevel)
|
logrus.SetLevel(logrus.TraceLevel)
|
||||||
}
|
}
|
||||||
|
|
||||||
if noColor, ok := os.LookupEnv("NO_COLOR"); ok && noColor != "" && !cmd.Flags().Changed("ansi") {
|
formatter.SetANSIMode(streams, ansi)
|
||||||
ansi = "never"
|
|
||||||
|
if noColor, ok := os.LookupEnv("NO_COLOR"); ok && noColor != "" {
|
||||||
|
progress.NoColor()
|
||||||
|
formatter.SetANSIMode(streams, formatter.Never)
|
||||||
}
|
}
|
||||||
|
|
||||||
formatter.SetANSIMode(streams, ansi)
|
|
||||||
switch ansi {
|
switch ansi {
|
||||||
case "never":
|
case "never":
|
||||||
progress.Mode = progress.ModePlain
|
progress.Mode = progress.ModePlain
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 Docker Compose CLI authors
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package progress
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/morikuni/aec"
|
||||||
|
)
|
||||||
|
|
||||||
|
type colorFunc func(string) string
|
||||||
|
|
||||||
|
var (
|
||||||
|
nocolor colorFunc = func(s string) string {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
DoneColor colorFunc = aec.BlueF.Apply
|
||||||
|
TimerColor colorFunc = aec.BlueF.Apply
|
||||||
|
CountColor colorFunc = aec.YellowF.Apply
|
||||||
|
WarningColor colorFunc = aec.YellowF.With(aec.Bold).Apply
|
||||||
|
SuccessColor colorFunc = aec.GreenF.Apply
|
||||||
|
ErrorColor colorFunc = aec.RedF.With(aec.Bold).Apply
|
||||||
|
PrefixColor colorFunc = aec.CyanF.Apply
|
||||||
|
)
|
||||||
|
|
||||||
|
func NoColor() {
|
||||||
|
DoneColor = nocolor
|
||||||
|
TimerColor = nocolor
|
||||||
|
CountColor = nocolor
|
||||||
|
WarningColor = nocolor
|
||||||
|
SuccessColor = nocolor
|
||||||
|
ErrorColor = nocolor
|
||||||
|
PrefixColor = nocolor
|
||||||
|
}
|
|
@ -18,23 +18,21 @@ package progress
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/morikuni/aec"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// EventStatus indicates the status of an action
|
// EventStatus indicates the status of an action
|
||||||
type EventStatus int
|
type EventStatus int
|
||||||
|
|
||||||
func (s EventStatus) color() aec.ANSI {
|
func (s EventStatus) colorFn() colorFunc {
|
||||||
switch s {
|
switch s {
|
||||||
case Done:
|
case Done:
|
||||||
return aec.GreenF
|
return SuccessColor
|
||||||
case Warning:
|
case Warning:
|
||||||
return aec.YellowF.With(aec.Bold)
|
return WarningColor
|
||||||
case Error:
|
case Error:
|
||||||
return aec.RedF.With(aec.Bold)
|
return ErrorColor
|
||||||
default:
|
default:
|
||||||
return aec.DefaultF
|
return nocolor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,19 +168,19 @@ func (e *Event) stop() {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
spinnerDone = aec.Apply("✔", aec.GreenF)
|
spinnerDone = "✔"
|
||||||
spinnerWarning = aec.Apply("!", aec.YellowF)
|
spinnerWarning = "!"
|
||||||
spinnerError = aec.Apply("✘", aec.RedF)
|
spinnerError = "✘"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (e *Event) Spinner() any {
|
func (e *Event) Spinner() any {
|
||||||
switch e.Status {
|
switch e.Status {
|
||||||
case Done:
|
case Done:
|
||||||
return spinnerDone
|
return SuccessColor(spinnerDone)
|
||||||
case Warning:
|
case Warning:
|
||||||
return spinnerWarning
|
return WarningColor(spinnerWarning)
|
||||||
case Error:
|
case Error:
|
||||||
return spinnerError
|
return ErrorColor(spinnerError)
|
||||||
default:
|
default:
|
||||||
return e.spinner.String()
|
return e.spinner.String()
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,7 +151,7 @@ func (w *ttyWriter) print() { //nolint:gocyclo
|
||||||
|
|
||||||
firstLine := fmt.Sprintf("[+] Running %d/%d", numDone(w.events), w.numLines)
|
firstLine := fmt.Sprintf("[+] Running %d/%d", numDone(w.events), w.numLines)
|
||||||
if w.numLines != 0 && numDone(w.events) == w.numLines {
|
if w.numLines != 0 && numDone(w.events) == w.numLines {
|
||||||
firstLine = aec.Apply(firstLine, aec.BlueF)
|
firstLine = DoneColor(firstLine)
|
||||||
}
|
}
|
||||||
fmt.Fprintln(w.out, firstLine)
|
fmt.Fprintln(w.out, firstLine)
|
||||||
|
|
||||||
|
@ -210,7 +210,7 @@ func (w *ttyWriter) lineText(event Event, pad string, terminalWidth, statusPaddi
|
||||||
}
|
}
|
||||||
prefix := ""
|
prefix := ""
|
||||||
if dryRun {
|
if dryRun {
|
||||||
prefix = aec.Apply(api.DRYRUN_PREFIX, aec.CyanF)
|
prefix = PrefixColor(api.DRYRUN_PREFIX)
|
||||||
}
|
}
|
||||||
|
|
||||||
elapsed := endTime.Sub(event.startTime).Seconds()
|
elapsed := endTime.Sub(event.startTime).Seconds()
|
||||||
|
@ -234,8 +234,8 @@ func (w *ttyWriter) lineText(event Event, pad string, terminalWidth, statusPaddi
|
||||||
if len(completion) > 0 {
|
if len(completion) > 0 {
|
||||||
txt = fmt.Sprintf("%s %s [%s] %7s/%-7s %s",
|
txt = fmt.Sprintf("%s %s [%s] %7s/%-7s %s",
|
||||||
event.ID,
|
event.ID,
|
||||||
aec.Apply(fmt.Sprintf("%d layers", len(completion)), aec.YellowF),
|
CountColor(fmt.Sprintf("%d layers", len(completion))),
|
||||||
aec.Apply(strings.Join(completion, ""), aec.GreenF, aec.Bold),
|
SuccessColor(strings.Join(completion, "")),
|
||||||
units.HumanSize(float64(current)), units.HumanSize(float64(total)),
|
units.HumanSize(float64(current)), units.HumanSize(float64(total)),
|
||||||
event.Text)
|
event.Text)
|
||||||
} else {
|
} else {
|
||||||
|
@ -260,10 +260,10 @@ func (w *ttyWriter) lineText(event Event, pad string, terminalWidth, statusPaddi
|
||||||
prefix,
|
prefix,
|
||||||
txt,
|
txt,
|
||||||
strings.Repeat(" ", padding),
|
strings.Repeat(" ", padding),
|
||||||
aec.Apply(status, event.Status.color()),
|
event.Status.colorFn()(status),
|
||||||
)
|
)
|
||||||
timer := fmt.Sprintf("%.1fs ", elapsed)
|
timer := fmt.Sprintf("%.1fs ", elapsed)
|
||||||
o := align(text, aec.Apply(timer, aec.BlueF), terminalWidth)
|
o := align(text, TimerColor(timer), terminalWidth)
|
||||||
|
|
||||||
return o
|
return o
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ func TestLineText(t *testing.T) {
|
||||||
lineWidth := len(fmt.Sprintf("%s %s", ev.ID, ev.Text))
|
lineWidth := len(fmt.Sprintf("%s %s", ev.ID, ev.Text))
|
||||||
|
|
||||||
out := tty().lineText(ev, "", 50, lineWidth, false)
|
out := tty().lineText(ev, "", 50, lineWidth, false)
|
||||||
assert.Equal(t, out, " . id Text \x1b[39mStatus\x1b[0m \x1b[34m0.0s \x1b[0m\n")
|
assert.Equal(t, out, " . id Text Status \x1b[34m0.0s \x1b[0m\n")
|
||||||
|
|
||||||
ev.Status = Done
|
ev.Status = Done
|
||||||
out = tty().lineText(ev, "", 50, lineWidth, false)
|
out = tty().lineText(ev, "", 50, lineWidth, false)
|
||||||
|
@ -50,11 +50,11 @@ func TestLineText(t *testing.T) {
|
||||||
|
|
||||||
ev.Status = Error
|
ev.Status = Error
|
||||||
out = tty().lineText(ev, "", 50, lineWidth, false)
|
out = tty().lineText(ev, "", 50, lineWidth, false)
|
||||||
assert.Equal(t, out, " \x1b[31m✘\x1b[0m id Text \x1b[31m\x1b[1mStatus\x1b[0m \x1b[34m0.0s \x1b[0m\n")
|
assert.Equal(t, out, " \x1b[31m\x1b[1m✘\x1b[0m id Text \x1b[31m\x1b[1mStatus\x1b[0m \x1b[34m0.0s \x1b[0m\n")
|
||||||
|
|
||||||
ev.Status = Warning
|
ev.Status = Warning
|
||||||
out = tty().lineText(ev, "", 50, lineWidth, false)
|
out = tty().lineText(ev, "", 50, lineWidth, false)
|
||||||
assert.Equal(t, out, " \x1b[33m!\x1b[0m id Text \x1b[33m\x1b[1mStatus\x1b[0m \x1b[34m0.0s \x1b[0m\n")
|
assert.Equal(t, out, " \x1b[33m\x1b[1m!\x1b[0m id Text \x1b[33m\x1b[1mStatus\x1b[0m \x1b[34m0.0s \x1b[0m\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLineTextSingleEvent(t *testing.T) {
|
func TestLineTextSingleEvent(t *testing.T) {
|
||||||
|
|
Loading…
Reference in New Issue