-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathterminal_windows.go
More file actions
94 lines (79 loc) · 2.53 KB
/
Copy pathterminal_windows.go
File metadata and controls
94 lines (79 loc) · 2.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
//go:build windows
package zlog
import (
"os"
"syscall"
"unsafe"
)
const (
// Windows console mode flags
ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004
ENABLE_PROCESSED_OUTPUT = 0x0001
)
var (
kernel32 = syscall.NewLazyDLL("kernel32.dll")
procGetConsoleMode = kernel32.NewProc("GetConsoleMode")
procSetConsoleMode = kernel32.NewProc("SetConsoleMode")
procGetStdHandle = kernel32.NewProc("GetStdHandle")
virtualTerminalSupported bool
virtualTerminalSupportChecked bool
)
// isTerminal returns true if the file descriptor is a terminal and enables colors if supported
func isTerminal(fd uintptr) bool {
var mode uint32
r, _, _ := procGetConsoleMode.Call(fd, uintptr(unsafe.Pointer(&mode)))
if r == 0 {
return false
}
// Try to enable virtual terminal processing for ANSI color support
if !virtualTerminalSupportChecked {
virtualTerminalSupportChecked = true
// Try to enable virtual terminal processing
newMode := mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING | ENABLE_PROCESSED_OUTPUT
r, _, _ = procSetConsoleMode.Call(fd, uintptr(newMode))
if r != 0 {
virtualTerminalSupported = true
}
}
// On older Windows versions without virtual terminal support,
// we should disable colors even if it's a terminal
if !virtualTerminalSupported {
// Check Windows version - Windows 10 build 14393 and later support VT
if !checkWindowsVersion() {
return false // Disable colors on older Windows
}
}
return true
}
// checkWindowsVersion checks if Windows supports ANSI colors (Windows 10 1607+)
func checkWindowsVersion() bool {
// Get Windows version
dll := syscall.NewLazyDLL("ntdll.dll")
proc := dll.NewProc("RtlGetVersion")
type osversioninfoexw struct {
dwOSVersionInfoSize uint32
dwMajorVersion uint32
dwMinorVersion uint32
dwBuildNumber uint32
dwPlatformId uint32
szCSDVersion [128]uint16
}
var info osversioninfoexw
info.dwOSVersionInfoSize = uint32(unsafe.Sizeof(info))
ret, _, _ := proc.Call(uintptr(unsafe.Pointer(&info)))
if ret == 0 {
// Windows 10 is version 10.0, build 14393+ supports ANSI
if info.dwMajorVersion > 10 || (info.dwMajorVersion == 10 && info.dwBuildNumber >= 14393) {
return true
}
}
// Fallback: check if TERM environment variable is set (Git Bash, WSL, etc.)
if os.Getenv("TERM") != "" {
return true
}
return false
}
// Alternative simple check for standard outputs
func isTerminalSimple(fd uintptr) bool {
return fd == uintptr(os.Stdout.Fd()) || fd == uintptr(os.Stderr.Fd())
}