Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improve IsColorTerminal windows support #27

Merged
merged 1 commit into from
Nov 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
}
Loading