Skip to content

Commit

Permalink
improve IsColorTerminal windows support
Browse files Browse the repository at this point in the history
  • Loading branch information
hermannm committed Nov 12, 2023
1 parent b51a57b commit eec3130
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 37 deletions.
7 changes: 4 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ go 1.16
require (
github.com/fatih/color v1.16.0
github.com/mattn/go-colorable v0.1.13
github.com/mattn/go-isatty v0.0.20
golang.org/x/sys v0.14.0
golang.org/x/term v0.14.0
)

require (
// Only used for test/benchmark/comparision.
// Only used for test/benchmark/comparison.
github.com/nwidger/jsoncolor v0.3.2
// Only used for test/benchmark/comparision.
// Only used for test/benchmark/comparison.
github.com/segmentio/encoding v0.3.6
github.com/stretchr/testify v1.8.4
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.14.0 h1:LGK9IlZ8T9jvdy6cTdfKUCltatMFOehAQo9SRC46UQ8=
golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww=
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.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Expand Down
36 changes: 2 additions & 34 deletions jsoncolor.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
package jsoncolor

import (
"io"
"os"
"strconv"

"github.com/mattn/go-isatty"
)

// Colors specifies colorization of JSON output. Each field
Expand Down Expand Up @@ -117,11 +113,11 @@ func (c *Colors) appendPunc(b []byte, v byte) []byte {
// Color is used to render terminal colors. In effect, Color is
// the bytes of the ANSI prefix code. The zero value is valid (results in
// no colorization). When Color is non-zero, the encoder writes the prefix,
//then the actual value, then the ANSI reset code.
// then the actual value, then the ANSI reset code.
//
// Example value:
//
// number := Color("\x1b[36m")
// number := Color("\x1b[36m")
type Color []byte

// ansiReset is the ANSI ansiReset escape code.
Expand All @@ -143,31 +139,3 @@ func DefaultColors() *Colors {
TextMarshaler: Color("\x1b[32m"), // Same as String
}
}

// IsColorTerminal returns true if w is a colorable terminal.
func IsColorTerminal(w io.Writer) bool {
// This logic could be pretty dodgy; use at your own risk.
if w == nil {
return false
}

f, ok := w.(*os.File)
if !ok {
return false
}
fd := f.Fd()

if !isatty.IsTerminal(fd) {
return false
}

if os.Getenv("TERM") == "dumb" {
return false
}

if isatty.IsCygwinTerminal(fd) {
return false
}

return true
}
42 changes: 42 additions & 0 deletions terminal.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//go:build !windows

package jsoncolor

import (
"io"
"os"

"golang.org/x/term"
)

// IsColorTerminal returns true if w is a colorable terminal.
// It respects [NO_COLOR], [FORCE_COLOR] and TERM=dumb environment variables.
//
// [NO_COLOR]: https://no-color.org/
// [FORCE_COLOR]: https://force-color.org/
func IsColorTerminal(w io.Writer) bool {
if os.Getenv("NO_COLOR") != "" {
return false
}
if os.Getenv("FORCE_COLOR") != "" {
return true
}
if os.Getenv("TERM") == "dumb" {
return false
}

if w == nil {
return false
}

f, ok := w.(*os.File)
if !ok {
return false
}

if !term.IsTerminal(int(f.Fd())) {
return false
}

return true
}
53 changes: 53 additions & 0 deletions terminal_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package jsoncolor

import (
"io"
"os"

"golang.org/x/sys/windows"
)

// IsColorTerminal returns true if w is a colorable terminal.
// It respects [NO_COLOR], [FORCE_COLOR] and TERM=dumb environment variables.
//
// [NO_COLOR]: https://no-color.org/
// [FORCE_COLOR]: https://force-color.org/
func IsColorTerminal(w io.Writer) bool {
if os.Getenv("NO_COLOR") != "" {
return false
}
if os.Getenv("FORCE_COLOR") != "" {
return true
}
if os.Getenv("TERM") == "dumb" {
return false
}

if w == nil {
return false
}

f, ok := w.(*os.File)
if !ok {
return false
}
fd := f.Fd()

console := windows.Handle(fd)
var mode uint32
if err := windows.GetConsoleMode(console, &mode); err != nil {
return false
}

var want uint32 = windows.ENABLE_PROCESSED_OUTPUT | windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING
if (mode & want) == want {
return true
}

mode |= want
if err := windows.SetConsoleMode(console, mode); err != nil {
return false
}

return true
}

0 comments on commit eec3130

Please sign in to comment.