From bca4eef166851a9f73196330b41dac8b7620f96b Mon Sep 17 00:00:00 2001 From: Sky Johnson Date: Thu, 5 Jun 2025 20:21:34 -0500 Subject: [PATCH] move color to top level, add windows support --- {utils/color => color}/color.go | 35 +++++++++++++++++++-------------- color/color_unix.go | 33 +++++++++++++++++++++++++++++++ color/color_windows.go | 29 +++++++++++++++++++++++++++ http/server.go | 2 +- moonshark.go | 2 +- runner/lualibs/env.go | 2 +- runner/lualibs/fs.go | 2 +- runner/sqlite/sqlite.go | 2 +- utils/logger/logger.go | 2 +- watchers/api.go | 2 +- 10 files changed, 89 insertions(+), 22 deletions(-) rename {utils/color => color}/color.go (82%) create mode 100644 color/color_unix.go create mode 100644 color/color_windows.go diff --git a/utils/color/color.go b/color/color.go similarity index 82% rename from utils/color/color.go rename to color/color.go index d0c133c..dc2bf2f 100644 --- a/utils/color/color.go +++ b/color/color.go @@ -3,12 +3,9 @@ package color import ( "os" "strings" - "syscall" - "unsafe" + "sync" ) -const ioctlReadTermios = 0x5401 - // ANSI color codes const ( resetCode = "\033[0m" @@ -22,7 +19,10 @@ const ( grayCode = "\033[90m" ) -var useColors = true +var ( + useColors bool + colorMu sync.RWMutex +) // Color function; makes a call to makeColorFunc with the associated color code var ( @@ -37,9 +37,17 @@ var ( Gray = makeColorFunc(grayCode) ) +func init() { + useColors = DetectShellColors() +} + func makeColorFunc(code string) func(string) string { return func(text string) string { - if useColors { + colorMu.RLock() + enabled := useColors + colorMu.RUnlock() + + if enabled { return code + text + resetCode } return text @@ -74,23 +82,20 @@ func DetectShellColors() bool { strings.Contains(term, "xterm") || strings.Contains(term, "screen") || strings.Contains(term, "tmux") || - term == "linux" + term == "linux" || + isWindowsTerminal() } // SetColors enables or disables colors globally func SetColors(enabled bool) { + colorMu.Lock() useColors = enabled + colorMu.Unlock() } // ColorsEnabled returns current global color setting func ColorsEnabled() bool { + colorMu.RLock() + defer colorMu.RUnlock() return useColors } - -// isTerminal checks if the file is a terminal -func isTerminal(f *os.File) bool { - fd := f.Fd() - var termios syscall.Termios - _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0) - return err == 0 -} diff --git a/color/color_unix.go b/color/color_unix.go new file mode 100644 index 0000000..3f63471 --- /dev/null +++ b/color/color_unix.go @@ -0,0 +1,33 @@ +//go:build !windows +// +build !windows + +package color + +import ( + "os" + "syscall" + "unsafe" +) + +const ioctlReadTermios = 0x5401 + +// isTerminal checks if the file is a terminal +func isTerminal(f *os.File) bool { + fd := f.Fd() + var termios syscall.Termios + + r1, _, errno := syscall.Syscall6( + syscall.SYS_IOCTL, + fd, + ioctlReadTermios, + uintptr(unsafe.Pointer(&termios)), + 0, 0, 0, + ) + + return r1 == 0 && errno == 0 +} + +// isWindowsTerminal always returns false on Unix +func isWindowsTerminal() bool { + return false +} diff --git a/color/color_windows.go b/color/color_windows.go new file mode 100644 index 0000000..059ed9f --- /dev/null +++ b/color/color_windows.go @@ -0,0 +1,29 @@ +//go:build windows +// +build windows + +package color + +import ( + "os" + "syscall" + "unsafe" +) + +var ( + kernel32 = syscall.NewLazyDLL("kernel32.dll") + procGetConsoleMode = kernel32.NewProc("GetConsoleMode") +) + +// isTerminal checks if the file is a terminal on Windows +func isTerminal(f *os.File) bool { + handle := syscall.Handle(f.Fd()) + var mode uint32 + + r1, _, _ := procGetConsoleMode.Call(uintptr(handle), uintptr(unsafe.Pointer(&mode))) + return r1 != 0 +} + +// isWindowsTerminal checks for Windows Terminal +func isWindowsTerminal() bool { + return os.Getenv("WT_SESSION") != "" +} diff --git a/http/server.go b/http/server.go index a5a6565..e1edc88 100644 --- a/http/server.go +++ b/http/server.go @@ -8,11 +8,11 @@ import ( "sync" "time" + "Moonshark/color" "Moonshark/router" "Moonshark/runner" "Moonshark/sessions" "Moonshark/utils" - "Moonshark/utils/color" "Moonshark/utils/config" "Moonshark/utils/logger" "Moonshark/utils/metadata" diff --git a/moonshark.go b/moonshark.go index d7682e0..55e2adb 100644 --- a/moonshark.go +++ b/moonshark.go @@ -13,12 +13,12 @@ import ( "syscall" "time" + "Moonshark/color" "Moonshark/http" "Moonshark/router" "Moonshark/runner" "Moonshark/runner/lualibs" "Moonshark/sessions" - "Moonshark/utils/color" "Moonshark/utils/config" "Moonshark/utils/logger" "Moonshark/utils/metadata" diff --git a/runner/lualibs/env.go b/runner/lualibs/env.go index 9557984..22bda06 100644 --- a/runner/lualibs/env.go +++ b/runner/lualibs/env.go @@ -10,7 +10,7 @@ import ( "strings" "sync" - "Moonshark/utils/color" + "Moonshark/color" "Moonshark/utils/logger" luajit "git.sharkk.net/Sky/LuaJIT-to-Go" diff --git a/runner/lualibs/fs.go b/runner/lualibs/fs.go index 132da66..d52acae 100644 --- a/runner/lualibs/fs.go +++ b/runner/lualibs/fs.go @@ -8,7 +8,7 @@ import ( "strings" "time" - "Moonshark/utils/color" + "Moonshark/color" "Moonshark/utils/logger" lru "git.sharkk.net/Go/LRU" diff --git a/runner/sqlite/sqlite.go b/runner/sqlite/sqlite.go index e35503a..b6e69d8 100644 --- a/runner/sqlite/sqlite.go +++ b/runner/sqlite/sqlite.go @@ -11,7 +11,7 @@ import ( sqlite "zombiezen.com/go/sqlite" "zombiezen.com/go/sqlite/sqlitex" - "Moonshark/utils/color" + "Moonshark/color" "Moonshark/utils/logger" luajit "git.sharkk.net/Sky/LuaJIT-to-Go" diff --git a/utils/logger/logger.go b/utils/logger/logger.go index 01a0dca..cde131e 100644 --- a/utils/logger/logger.go +++ b/utils/logger/logger.go @@ -9,7 +9,7 @@ import ( "sync/atomic" "time" - "Moonshark/utils/color" + "Moonshark/color" ) // Log levels diff --git a/watchers/api.go b/watchers/api.go index f35f9f7..3ef8dc4 100644 --- a/watchers/api.go +++ b/watchers/api.go @@ -5,9 +5,9 @@ import ( "strings" "sync" + "Moonshark/color" "Moonshark/router" "Moonshark/runner" - "Moonshark/utils/color" "Moonshark/utils/logger" )