gowebbuild/vendor/github.com/evanw/esbuild/internal/logger/logger_windows.go

137 lines
3.9 KiB
Go
Raw Normal View History

//go:build windows
// +build windows
package logger
import (
"os"
"strings"
"syscall"
"unsafe"
)
const SupportsColorEscapes = true
var kernel32 = syscall.NewLazyDLL("kernel32.dll")
var getConsoleMode = kernel32.NewProc("GetConsoleMode")
var setConsoleTextAttribute = kernel32.NewProc("SetConsoleTextAttribute")
var getConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo")
type consoleScreenBufferInfo struct {
dwSizeX int16
dwSizeY int16
dwCursorPositionX int16
dwCursorPositionY int16
wAttributes uint16
srWindowLeft int16
srWindowTop int16
srWindowRight int16
srWindowBottom int16
dwMaximumWindowSizeX int16
dwMaximumWindowSizeY int16
}
func GetTerminalInfo(file *os.File) TerminalInfo {
fd := file.Fd()
// Is this file descriptor a terminal?
var unused uint32
isTTY, _, _ := syscall.Syscall(getConsoleMode.Addr(), 2, fd, uintptr(unsafe.Pointer(&unused)), 0)
// Get the width of the window
var info consoleScreenBufferInfo
syscall.Syscall(getConsoleScreenBufferInfo.Addr(), 2, fd, uintptr(unsafe.Pointer(&info)), 0)
return TerminalInfo{
IsTTY: isTTY != 0,
Width: int(info.dwSizeX) - 1,
Height: int(info.dwSizeY) - 1,
UseColorEscapes: !hasNoColorEnvironmentVariable(),
}
}
const (
FOREGROUND_BLUE uint8 = 1 << iota
FOREGROUND_GREEN
FOREGROUND_RED
FOREGROUND_INTENSITY
BACKGROUND_BLUE
BACKGROUND_GREEN
BACKGROUND_RED
BACKGROUND_INTENSITY
)
var windowsEscapeSequenceMap = map[string]uint8{
TerminalColors.Reset: FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
TerminalColors.Dim: FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
TerminalColors.Bold: FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
// Apparently underlines only work with the CJK locale on Windows :(
TerminalColors.Underline: FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
TerminalColors.Red: FOREGROUND_RED,
TerminalColors.Green: FOREGROUND_GREEN,
TerminalColors.Blue: FOREGROUND_BLUE,
TerminalColors.Cyan: FOREGROUND_GREEN | FOREGROUND_BLUE,
TerminalColors.Magenta: FOREGROUND_RED | FOREGROUND_BLUE,
TerminalColors.Yellow: FOREGROUND_RED | FOREGROUND_GREEN,
TerminalColors.RedBgRed: FOREGROUND_RED | BACKGROUND_RED,
TerminalColors.RedBgWhite: FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | BACKGROUND_RED,
TerminalColors.GreenBgGreen: FOREGROUND_GREEN | BACKGROUND_GREEN,
TerminalColors.GreenBgWhite: FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | BACKGROUND_GREEN,
TerminalColors.BlueBgBlue: FOREGROUND_BLUE | BACKGROUND_BLUE,
TerminalColors.BlueBgWhite: FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | BACKGROUND_BLUE,
TerminalColors.CyanBgCyan: FOREGROUND_GREEN | FOREGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_BLUE,
TerminalColors.CyanBgBlack: BACKGROUND_GREEN | BACKGROUND_BLUE,
TerminalColors.MagentaBgMagenta: FOREGROUND_RED | FOREGROUND_BLUE | BACKGROUND_RED | BACKGROUND_BLUE,
TerminalColors.MagentaBgBlack: BACKGROUND_RED | BACKGROUND_BLUE,
TerminalColors.YellowBgYellow: FOREGROUND_RED | FOREGROUND_GREEN | BACKGROUND_RED | BACKGROUND_GREEN,
TerminalColors.YellowBgBlack: BACKGROUND_RED | BACKGROUND_GREEN,
}
func writeStringWithColor(file *os.File, text string) {
fd := file.Fd()
i := 0
for i < len(text) {
// Find the escape
if text[i] != 033 {
i++
continue
}
// Find the 'm'
window := text[i:]
if len(window) > 8 {
window = window[:8]
}
m := strings.IndexByte(window, 'm')
if m == -1 {
i++
continue
}
m += i + 1
// Find the escape sequence
attributes, ok := windowsEscapeSequenceMap[text[i:m]]
if !ok {
i++
continue
}
// Write out the text before the escape sequence
file.WriteString(text[:i])
// Apply the escape sequence
text = text[m:]
i = 0
setConsoleTextAttribute.Call(fd, uintptr(attributes))
}
// Write out the remaining text
file.WriteString(text)
}