How to Detect If Current Terminal Supports 16-Color or 256-Color in Go?

1.3k Views Asked by At

We got many popular packages in Go to render colorized text in terminal, like fatih/color, gookit/color, lucasb-eyer/go-colorful.

However I'm facing a problem that --- apart from seeing with my own eyes, how to detect if current terminal supports 16-Color or 256-Color programmatically in Go (even on Windows)?

1

There are 1 best solutions below

0
VonC On BEST ANSWER

As mentioned in "Determine whether the current Linux console supports 256 colours?" (and that is on Linux, the same portability issue would exist on Windows)

As an example of non-portable option, you could use curses (on Linux), as discussed here and implemented in curses.go:

Looking at tput colors and tigetnum('colors') (which return numbers like 1, 8, 256, or greater) are more along the lines of feature testing, which is less hacky and more future-proof.

func Init(theme *ColorTheme, black bool, mouse bool) {
    {
        in, err := os.OpenFile("/dev/tty", syscall.O_RDONLY, 0)
        if err != nil {
            panic("Failed to open /dev/tty")
        }
        _in = in
        // Break STDIN
        // syscall.Dup2(int(in.Fd()), int(os.Stdin.Fd()))
    }

    C.setlocale(C.LC_ALL, C.CString(""))
    _screen = C.c_newterm()
    if _screen == nil {
        fmt.Println("Invalid $TERM: " + os.Getenv("TERM"))
        os.Exit(2)
    }
    C.set_term(_screen)
    if mouse {
        C.mousemask(C.ALL_MOUSE_EVENTS, nil)
    }
    C.noecho()
    C.raw() // stty dsusp undef

    if theme != nil {
        C.start_color()
        var baseTheme *ColorTheme
        if C.tigetnum(C.CString("colors")) >= 256 {
            baseTheme = Dark256
        } else {
            baseTheme = Default16
        }
        initPairs(baseTheme, theme, black)
        _color = attrColored
    } else {
        _color = attrMono
    }
}