1
0
mirror of https://github.com/go-task/task.git synced 2025-02-03 13:22:11 +02:00

Use colors for some output messages

This commit is contained in:
Andrey Nering 2019-05-26 18:36:39 -03:00
parent 6ff9ba9df9
commit 8efc38ad82
11 changed files with 75 additions and 42 deletions

View File

@ -9,6 +9,7 @@ import (
"github.com/go-task/task/v2"
"github.com/go-task/task/v2/internal/args"
"github.com/go-task/task/v2/internal/logger"
"github.com/spf13/pflag"
)
@ -117,7 +118,7 @@ func main() {
arguments := pflag.Args()
if len(arguments) == 0 {
log.Println("task: No argument given, trying default task")
e.Logger.Errf(logger.Yellow, "task: No argument given, trying default task")
arguments = []string{"default"}
}
@ -139,7 +140,8 @@ func main() {
}
if err := e.Run(ctx, calls...); err != nil {
log.Fatal(err)
e.Logger.Errf(logger.Red, "%v", err)
os.Exit(1)
}
}

3
go.mod
View File

@ -5,10 +5,12 @@ require (
github.com/Masterminds/sprig v2.16.0+incompatible
github.com/aokoli/goutils v1.0.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fatih/color v1.7.0
github.com/google/uuid v1.0.0 // indirect
github.com/huandu/xstrings v1.1.0 // indirect
github.com/imdario/mergo v0.3.6 // indirect
github.com/kr/pretty v0.1.0 // indirect
github.com/mattn/go-colorable v0.1.2 // indirect
github.com/mattn/go-zglob v0.0.1
github.com/mitchellh/go-homedir v1.0.0
github.com/radovskyb/watcher v1.0.5
@ -17,7 +19,6 @@ require (
golang.org/x/crypto v0.0.0-20180830192347-182538f80094 // indirect
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d // indirect
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f
golang.org/x/sys v0.0.0-20180831094639-fa5fdf94c789 // indirect
gopkg.in/yaml.v2 v2.2.1
mvdan.cc/sh v2.6.4+incompatible
)

8
go.sum
View File

@ -7,6 +7,8 @@ github.com/aokoli/goutils v1.0.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/huandu/xstrings v1.1.0 h1:9oZY6Z/H3A1gytJxzuicbmV5QoR8M1TAPcn9WTg7vqg=
@ -18,6 +20,10 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-zglob v0.0.1 h1:xsEx/XUoVlI6yXjqBK062zYhRTZltCNmYPx6v+8DNaY=
github.com/mattn/go-zglob v0.0.1/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo=
github.com/mitchellh/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnGC8aR0=
@ -39,6 +45,8 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6Zh
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180831094639-fa5fdf94c789 h1:T8D7l6WB3tLu+VpKvw06ieD/OhBi1XpJmG1U/FtttZg=
golang.org/x/sys v0.0.0-20180831094639-fa5fdf94c789/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=

View File

@ -5,6 +5,7 @@ import (
"sort"
"text/tabwriter"
"github.com/go-task/task/v2/internal/logger"
"github.com/go-task/task/v2/internal/taskfile"
)
@ -12,10 +13,10 @@ import (
func (e *Executor) PrintTasksHelp() {
tasks := e.tasksWithDesc()
if len(tasks) == 0 {
e.Logger.Outf("task: No tasks with description available")
e.Logger.Outf(logger.Yellow, "task: No tasks with description available")
return
}
e.Logger.Outf("task: Available tasks for this project:")
e.Logger.Outf(logger.Default, "task: Available tasks for this project:")
// Format in tab-separated columns with a tab stop of 8.
w := tabwriter.NewWriter(e.Stdout, 0, 8, 0, '\t', 0)

View File

@ -131,7 +131,7 @@ func (c *CompilerV1) HandleDynamicVar(v taskfile.Var) (string, error) {
result := strings.TrimSuffix(stdout.String(), "\n")
c.dynamicCache[v.Sh] = result
c.Logger.VerboseErrf(`task: dynamic variable: '%s' result: '%s'`, v.Sh, result)
c.Logger.VerboseErrf(logger.Magenta, `task: dynamic variable: '%s' result: '%s'`, v.Sh, result)
return result, nil
}

View File

@ -103,7 +103,7 @@ func (c *CompilerV2) HandleDynamicVar(v taskfile.Var) (string, error) {
result := strings.TrimSuffix(stdout.String(), "\n")
c.dynamicCache[v.Sh] = result
c.Logger.VerboseErrf(`task: dynamic variable: '%s' result: '%s'`, v.Sh, result)
c.Logger.VerboseErrf(logger.Magenta, `task: dynamic variable: '%s' result: '%s'`, v.Sh, result)
return result, nil
}

View File

@ -1,38 +1,58 @@
package logger
import (
"fmt"
"io"
"github.com/fatih/color"
)
type PrintFunc func(io.Writer, string, ...interface{})
var (
Default PrintFunc = color.New(color.Reset).FprintfFunc()
Bold PrintFunc = color.New(color.Bold).FprintfFunc()
Blue PrintFunc = color.New(color.FgBlue, color.Bold).FprintfFunc()
Green PrintFunc = color.New(color.FgGreen, color.Bold).FprintfFunc()
Cyan PrintFunc = color.New(color.FgCyan, color.Bold).FprintfFunc()
Yellow PrintFunc = color.New(color.FgYellow, color.Bold).FprintfFunc()
Magenta PrintFunc = color.New(color.FgMagenta, color.Bold).FprintfFunc()
Red PrintFunc = color.New(color.FgRed, color.Bold).FprintfFunc()
)
// Logger is just a wrapper that prints stuff to STDOUT or STDERR,
// with optional color.
type Logger struct {
Stdout io.Writer
Stderr io.Writer
Verbose bool
}
func (l *Logger) Outf(s string, args ...interface{}) {
// Outf prints stuff to STDOUT.
func (l *Logger) Outf(print PrintFunc, s string, args ...interface{}) {
if len(args) == 0 {
s, args = "%s", []interface{}{s}
}
fmt.Fprintf(l.Stdout, s+"\n", args...)
print(l.Stdout, s+"\n", args...)
}
func (l *Logger) VerboseOutf(s string, args ...interface{}) {
// VerboseOutf prints stuff to STDOUT if verbose mode is enabled.
func (l *Logger) VerboseOutf(print PrintFunc, s string, args ...interface{}) {
if l.Verbose {
l.Outf(s, args...)
l.Outf(print, s, args...)
}
}
func (l *Logger) Errf(s string, args ...interface{}) {
// Errf prints stuff to STDERR.
func (l *Logger) Errf(print PrintFunc, s string, args ...interface{}) {
if len(args) == 0 {
s, args = "%s", []interface{}{s}
}
fmt.Fprintf(l.Stderr, s+"\n", args...)
print(l.Stderr, s+"\n", args...)
}
func (l *Logger) VerboseErrf(s string, args ...interface{}) {
// VerboseErrf prints stuff to STDERR if verbose mode is enabled.
func (l *Logger) VerboseErrf(print PrintFunc, s string, args ...interface{}) {
if l.Verbose {
l.Errf(s, args...)
l.Errf(print, s, args...)
}
}

View File

@ -20,8 +20,8 @@ func printSpaceBetweenSummaries(l *logger.Logger, i int) {
return
}
l.Outf("")
l.Outf("")
l.Outf(logger.Default, "")
l.Outf(logger.Default, "")
}
func PrintTask(l *logger.Logger, t *taskfile.Task) {
@ -50,14 +50,14 @@ func printTaskSummary(l *logger.Logger, t *taskfile.Task) {
for i, line := range lines {
notLastLine := i+1 < len(lines)
if notLastLine || line != "" {
l.Outf(line)
l.Outf(logger.Default, line)
}
}
}
func printTaskName(l *logger.Logger, t *taskfile.Task) {
l.Outf("task: %s", t.Task)
l.Outf("")
l.Outf(logger.Default, "task: %s", t.Task)
l.Outf(logger.Default, "")
}
func hasDescription(t *taskfile.Task) bool {
@ -65,11 +65,11 @@ func hasDescription(t *taskfile.Task) bool {
}
func printTaskDescription(l *logger.Logger, t *taskfile.Task) {
l.Outf(t.Desc)
l.Outf(logger.Default, t.Desc)
}
func printNoDescriptionOrSummary(l *logger.Logger) {
l.Outf("(task does not have description or summary)")
l.Outf(logger.Default, "(task does not have description or summary)")
}
func printTaskDependencies(l *logger.Logger, t *taskfile.Task) {
@ -77,11 +77,11 @@ func printTaskDependencies(l *logger.Logger, t *taskfile.Task) {
return
}
l.Outf("")
l.Outf("dependencies:")
l.Outf(logger.Default, "")
l.Outf(logger.Default, "dependencies:")
for _, d := range t.Deps {
l.Outf(" - %s", d.Task)
l.Outf(logger.Default, " - %s", d.Task)
}
}
@ -90,14 +90,14 @@ func printTaskCommands(l *logger.Logger, t *taskfile.Task) {
return
}
l.Outf("")
l.Outf("commands:")
l.Outf(logger.Default, "")
l.Outf(logger.Default, "commands:")
for _, c := range t.Cmds {
isCommand := c.Cmd != ""
if isCommand {
l.Outf(" - %s", c.Cmd)
l.Outf(logger.Default, " - %s", c.Cmd)
} else {
l.Outf(" - Task: %s", c.Task)
l.Outf(logger.Default, " - Task: %s", c.Task)
}
}
}

10
task.go
View File

@ -194,7 +194,7 @@ func (e *Executor) RunTask(ctx context.Context, call taskfile.Call) error {
}
if upToDate {
if !e.Silent {
e.Logger.Errf(`task: Task "%s" is up to date`, t.Task)
e.Logger.Errf(logger.Magenta, `task: Task "%s" is up to date`, t.Task)
}
return nil
}
@ -203,11 +203,11 @@ func (e *Executor) RunTask(ctx context.Context, call taskfile.Call) error {
for i := range t.Cmds {
if err := e.runCommand(ctx, t, call, i); err != nil {
if err2 := e.statusOnError(t); err2 != nil {
e.Logger.VerboseErrf("task: error cleaning status on error: %v", err2)
e.Logger.VerboseErrf(logger.Yellow, "task: error cleaning status on error: %v", err2)
}
if execext.IsExitError(err) && t.IgnoreError {
e.Logger.VerboseErrf("task: task error ignored: %v", err)
e.Logger.VerboseErrf(logger.Yellow, "task: task error ignored: %v", err)
continue
}
@ -239,7 +239,7 @@ func (e *Executor) runCommand(ctx context.Context, t *taskfile.Task, call taskfi
return e.RunTask(ctx, taskfile.Call{Task: cmd.Task, Vars: cmd.Vars})
case cmd.Cmd != "":
if e.Verbose || (!cmd.Silent && !t.Silent && !e.Silent) {
e.Logger.Errf(cmd.Cmd)
e.Logger.Errf(logger.Green, "task: %s", cmd.Cmd)
}
if e.Dry {
@ -270,7 +270,7 @@ func (e *Executor) runCommand(ctx context.Context, t *taskfile.Task, call taskfi
Stderr: stdErr,
})
if execext.IsExitError(err) && cmd.IgnoreError {
e.Logger.VerboseErrf("task: command error ignored: %v", err)
e.Logger.VerboseErrf(logger.Yellow, "task: command error ignored: %v", err)
return nil
}
return err

View File

@ -470,7 +470,7 @@ func TestDry(t *testing.T) {
assert.NoError(t, e.Setup())
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "build"}))
assert.Equal(t, "touch file.txt", strings.TrimSpace(buff.String()))
assert.Equal(t, "task: touch file.txt", strings.TrimSpace(buff.String()))
if _, err := os.Stat(file); err == nil {
t.Errorf("File should not exist %s", file)
}

View File

@ -8,6 +8,7 @@ import (
"syscall"
"time"
"github.com/go-task/task/v2/internal/logger"
"github.com/go-task/task/v2/internal/taskfile"
"github.com/mattn/go-zglob"
"github.com/radovskyb/watcher"
@ -24,14 +25,14 @@ func (e *Executor) watchTasks(calls ...taskfile.Call) error {
for i, c := range calls {
tasks[i] = c.Task
}
e.Logger.Errf("task: Started watching for tasks: %s", strings.Join(tasks, ", "))
e.Logger.Errf(logger.Green, "task: Started watching for tasks: %s", strings.Join(tasks, ", "))
ctx, cancel := context.WithCancel(context.Background())
for _, c := range calls {
c := c
go func() {
if err := e.RunTask(ctx, c); err != nil && !isContextError(err) {
e.Logger.Errf("%v", err)
e.Logger.Errf(logger.Red, "%v", err)
}
}()
}
@ -49,7 +50,7 @@ func (e *Executor) watchTasks(calls ...taskfile.Call) error {
for {
select {
case event := <-w.Event:
e.Logger.VerboseErrf("task: received watch event: %v", event)
e.Logger.VerboseErrf(logger.Magenta, "task: received watch event: %v", event)
cancel()
ctx, cancel = context.WithCancel(context.Background())
@ -57,7 +58,7 @@ func (e *Executor) watchTasks(calls ...taskfile.Call) error {
c := c
go func() {
if err := e.RunTask(ctx, c); err != nil && !isContextError(err) {
e.Logger.Errf("%v", err)
e.Logger.Errf(logger.Red, "%v", err)
}
}()
}
@ -68,7 +69,7 @@ func (e *Executor) watchTasks(calls ...taskfile.Call) error {
w.TriggerEvent(watcher.Remove, nil)
}()
default:
e.Logger.Errf("%v", err)
e.Logger.Errf(logger.Red, "%v", err)
}
case <-w.Closed:
cancel()
@ -81,7 +82,7 @@ func (e *Executor) watchTasks(calls ...taskfile.Call) error {
// re-register each second because we can have new files
for {
if err := e.registerWatchedFiles(w, calls...); err != nil {
e.Logger.Errf("%v", err)
e.Logger.Errf(logger.Red, "%v", err)
}
time.Sleep(time.Second)
}