diff --git a/Gopkg.lock b/Gopkg.lock index 036e204..b443ce7 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -614,6 +614,14 @@ revision = "f7279a603edee96fe7764d3de9c6ff8cf9970994" version = "1.0.4" +[[projects]] + digest = "1:0f51cee70b0d254dbc93c22666ea2abf211af81c1701a96d04e2284b408621db" + name = "github.com/konsorten/go-windows-terminal-sequences" + packages = ["."] + pruneopts = "" + revision = "f55edac94c9bbba5d6182a4be46d86a2c9b5b50e" + version = "v1.0.2" + [[projects]] branch = "master" digest = "1:ccc20cacf54eb16464dad02efa1c14fa7c0b9e124639b0d2a51dcc87b0154e4c" @@ -1608,12 +1616,14 @@ "github.com/gosuri/uitable", "github.com/hpcloud/tail", "github.com/jbrukh/bayesian", + "github.com/konsorten/go-windows-terminal-sequences", "github.com/oklog/ulid", "github.com/rjeczalik/notify", "github.com/sirupsen/logrus", "github.com/spf13/cobra", "github.com/spf13/pflag", "github.com/technosophos/moniker", + "golang.org/x/crypto/ssh/terminal", "golang.org/x/net/context", "google.golang.org/grpc", "k8s.io/api/core/v1", diff --git a/pkg/cmdline/cmdline.go b/pkg/cmdline/cmdline.go index 6b2ffe1..07adee0 100644 --- a/pkg/cmdline/cmdline.go +++ b/pkg/cmdline/cmdline.go @@ -2,7 +2,6 @@ package cmdline import ( "fmt" - "runtime" "strings" "sync" "time" @@ -37,7 +36,9 @@ func (cli *cmdline) Init(rootctx context.Context, opts ...Option) { for _, opt := range opts { opt(&cli.opts) } - if !consoleSupportsColor() { + if out := cli.opts.stdout; isTerminal(out) { + initTerminal(out) + } else { NoColor()(&cli.opts) } @@ -184,10 +185,3 @@ func concatStrAndEmoji(text string, emoji string, displayEmoji bool) string { } return concatStr.String() } - -func consoleSupportsColor() bool { - // We could try to detect the shell in use (and the mode for the Windows - // console), and see if it accepts VT100 escape sequences, but this is - // a good enough heuristic to start with! - return runtime.GOOS != "windows" -} diff --git a/pkg/cmdline/terminal_notwindows.go b/pkg/cmdline/terminal_notwindows.go new file mode 100644 index 0000000..f2a947f --- /dev/null +++ b/pkg/cmdline/terminal_notwindows.go @@ -0,0 +1,26 @@ +// +build !windows + +// NOTICE: This implementation comes from logrus, unfortunately they +// do not expose a public interface to call it. +// https://github.com/sirupsen/logrus/blob/master/terminal_check_notappengine.go +// https://github.com/sirupsen/logrus/blob/master/terminal_windows.go + +package cmdline + +import ( + "io" + "os" + + "golang.org/x/crypto/ssh/terminal" +) + +// initTerminal enables ANSI color escape sequences. On UNIX, they are always enabled. +func initTerminal(_ io.Writer) { +} + +func isTerminal(w io.Writer) bool { + if f, ok := w.(*os.File); ok { + return terminal.IsTerminal(int(f.Fd())) + } + return false +} diff --git a/pkg/cmdline/terminal_windows.go b/pkg/cmdline/terminal_windows.go new file mode 100644 index 0000000..a377841 --- /dev/null +++ b/pkg/cmdline/terminal_windows.go @@ -0,0 +1,33 @@ +// +build windows + +// NOTICE: This implementation comes from logrus, unfortunately they +// do not expose a public interface to call it. +// https://github.com/sirupsen/logrus/blob/master/terminal_check_notappengine.go +// https://github.com/sirupsen/logrus/blob/master/terminal_windows.go + +package cmdline + +import ( + "io" + "os" + "syscall" + + sequences "github.com/konsorten/go-windows-terminal-sequences" +) + +// initTerminal enables ANSI color escape on windows. Usually, this is done by logrus, +// but only after the first log message. So instead we take care of this ourselves. +func initTerminal(w io.Writer) { + if f, ok := w.(*os.File); ok { + sequences.EnableVirtualTerminalProcessing(syscall.Handle(f.Fd()), true) + } +} + +func isTerminal(w io.Writer) bool { + if f, ok := w.(*os.File); ok { + var mode uint32 + err := syscall.GetConsoleMode(syscall.Handle(f.Fd()), &mode) + return err == nil + } + return false +}