| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- //go:build windows
- // +build windows
- package termenv
- import (
- "fmt"
- "strconv"
- "golang.org/x/sys/windows"
- )
- func (o *Output) ColorProfile() Profile {
- if !o.isTTY() {
- return Ascii
- }
- if o.environ.Getenv("ConEmuANSI") == "ON" {
- return TrueColor
- }
- winVersion, _, buildNumber := windows.RtlGetNtVersionNumbers()
- if buildNumber < 10586 || winVersion < 10 {
- // No ANSI support before Windows 10 build 10586.
- if o.environ.Getenv("ANSICON") != "" {
- conVersion := o.environ.Getenv("ANSICON_VER")
- cv, err := strconv.ParseInt(conVersion, 10, 64)
- if err != nil || cv < 181 {
- // No 8 bit color support before v1.81 release.
- return ANSI
- }
- return ANSI256
- }
- return Ascii
- }
- if buildNumber < 14931 {
- // No true color support before build 14931.
- return ANSI256
- }
- return TrueColor
- }
- func (o Output) foregroundColor() Color {
- // default gray
- return ANSIColor(7)
- }
- func (o Output) backgroundColor() Color {
- // default black
- return ANSIColor(0)
- }
- // EnableWindowsANSIConsole enables virtual terminal processing on Windows
- // platforms. This allows the use of ANSI escape sequences in Windows console
- // applications. Ensure this gets called before anything gets rendered with
- // termenv.
- //
- // Returns the original console mode and an error if one occurred.
- func EnableWindowsANSIConsole() (uint32, error) {
- handle, err := windows.GetStdHandle(windows.STD_OUTPUT_HANDLE)
- if err != nil {
- return 0, err
- }
- var mode uint32
- err = windows.GetConsoleMode(handle, &mode)
- if err != nil {
- return 0, err
- }
- // See https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences
- if mode&windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING != windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING {
- vtpmode := mode | windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING
- if err := windows.SetConsoleMode(handle, vtpmode); err != nil {
- return 0, err
- }
- }
- return mode, nil
- }
- // RestoreWindowsConsole restores the console mode to a previous state.
- func RestoreWindowsConsole(mode uint32) error {
- handle, err := windows.GetStdHandle(windows.STD_OUTPUT_HANDLE)
- if err != nil {
- return err
- }
- return windows.SetConsoleMode(handle, mode)
- }
- // EnableVirtualTerminalProcessing enables virtual terminal processing on
- // Windows for o and returns a function that restores o to its previous state.
- // On non-Windows platforms, or if o does not refer to a terminal, then it
- // returns a non-nil no-op function and no error.
- func EnableVirtualTerminalProcessing(o *Output) (restoreFunc func() error, err error) {
- // There is nothing to restore until we set the console mode.
- restoreFunc = func() error {
- return nil
- }
- // If o is not a tty, then there is nothing to do.
- tty := o.TTY()
- if tty == nil {
- return
- }
- // Get the current console mode. If there is an error, assume that o is not
- // a terminal, discard the error, and return.
- var mode uint32
- if err2 := windows.GetConsoleMode(windows.Handle(tty.Fd()), &mode); err2 != nil {
- return
- }
- // If virtual terminal processing is already set, then there is nothing to
- // do and nothing to restore.
- if mode&windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING == windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING {
- return
- }
- // Enable virtual terminal processing. See
- // https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences
- if err2 := windows.SetConsoleMode(windows.Handle(tty.Fd()), mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING); err2 != nil {
- err = fmt.Errorf("windows.SetConsoleMode: %w", err2)
- return
- }
- // Set the restore function. We maintain a reference to the tty in the
- // closure (rather than just its handle) to ensure that the tty is not
- // closed by a finalizer.
- restoreFunc = func() error {
- return windows.SetConsoleMode(windows.Handle(tty.Fd()), mode)
- }
- return
- }
|