Files
xlgo-core/console/console_windows.go
2026-07-14 10:24:10 +08:00

70 lines
2.2 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//go:build windows
package console
import (
"fmt"
"os"
"syscall"
"unsafe"
)
var kernel32 = syscall.NewLazyDLL("kernel32.dll")
// 颜色映射:ANSI -> Windows控制台颜色
// 0 黑色, 1 蓝色, 2 绿色, 3 青色, 4 红色, 5 紫色, 6 黄色, 7 淡灰色
// 8 灰色, 9 亮蓝色, 10 亮绿色, 11 亮青色, 12 亮红色, 13 亮紫色, 14 亮黄色, 15 白色
var colorMap = map[string]uintptr{
"0;36": 11, // 青色 -> 亮青色
"0;37": 15, // 白色 -> 白色
"0;92": 10, // 亮绿色
"1;93": 14, // 亮黄色
"1;31": 12, // 亮红色
}
// printColor 彩色打印。
//
// 修复 M17:原实现对 syscall.Stdout 设置颜色、却把文本写到 c.output——
// 当 c.output 非 stdout(如 WithOutput 指向文件)时,颜色落到错误句柄、文本落文件,
// 二者分裂。现按 c.output 实际类型取句柄:*os.File 用其 Fd(),否则放弃着色只写文本。
func (c *Console) printColor(code, msg string) {
color := colorMap[code]
if color == 0 {
color = 7 // 默认淡灰色
}
handle, ok := consoleHandle(c.output)
if !ok {
// 非 *os.File(如 bytes.Buffer/文件),无法设置控制台属性,退化为纯文本。
fmt.Fprintln(c.output, msg)
return
}
proc := kernel32.NewProc("SetConsoleTextAttribute")
_, _, _ = proc.Call(handle, color)
fmt.Fprintln(c.output, msg)
_, _, _ = proc.Call(handle, 7) // 恢复默认颜色
}
// consoleHandle 从 io.Writer 取 Windows 控制台句柄;非 *os.File 返回 (0, false)。
func consoleHandle(w interface{ Write([]byte) (int, error) }) (uintptr, bool) {
f, ok := w.(*os.File)
if !ok {
return 0, false
}
fd := f.Fd()
switch fd {
case uintptr(syscall.Stdout), uintptr(syscall.Stderr), uintptr(syscall.Stdin):
return fd, true
default:
// 重定向到文件/管道的 *os.FileSetConsoleTextAttribute 无意义,退化为纯文本。
return 0, false
}
}
// M17:原 EnableVirtualTerminal 为死代码且从未被调用,已移除。
// Windows 10+ 默认支持 ANSI/VT 着色;需要 VT 的调用方应自行调 kernel32。)
// 保留 unsafe 引用以备将来 VT 扩展;当前 printColor 不再需要,故显式抑制未用告警。
var _ = unsafe.Sizeof(uintptr(0))