Files
wehub-resource-sync a06f331eb8
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:33:42 +08:00

140 lines
3.9 KiB
Go

package progress
import (
"os"
"runtime"
"github.com/charmbracelet/lipgloss"
)
// glyphSet is the small set of display glyphs that differ between a UTF-8
// terminal and a legacy OEM / ASCII one: the success / failure markers, the
// status dot, the mid-dot separator, and the box-drawing charset. Gortex
// renders more box-drawing than a check/cross-only CLI (the rounded card
// border), so the ASCII fallback has to cover the whole border too. The
// live tracker adds the progress-bar cells, the pending marker, and the
// busy / ready status dots to the same fallback contract.
type glyphSet struct {
OK string
Fail string
Dot string
DotDim string
Pending string
Sep string
Dash string
Ellipsis string
BarFull string
BarEmpty string
StatusBusy string
StatusReady string
Border lipgloss.Border
}
var (
unicodeGlyphs = glyphSet{
OK: "✓",
Fail: "✗",
Dot: "●",
DotDim: "●",
Pending: "·",
Sep: "·",
Dash: "—",
Ellipsis: "…",
BarFull: "█",
BarEmpty: "░",
StatusBusy: "◐",
StatusReady: "●",
Border: lipgloss.RoundedBorder(),
}
asciiGlyphs = glyphSet{
OK: "+",
Fail: "x",
Dot: "*",
DotDim: "o",
Pending: ".",
Sep: "-",
Dash: "-",
Ellipsis: "...",
BarFull: "#",
BarEmpty: "-",
StatusBusy: "o",
StatusReady: "*",
Border: lipgloss.ASCIIBorder(),
}
brailleSpin = []string{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"}
asciiSpin = []string{"|", "/", "-", "\\"}
)
// activeGlyphs returns the glyph set appropriate to the current terminal:
// UTF-8 box-drawing / check glyphs when it can render them, ASCII otherwise.
// Resolved per call so a runtime override (or a test) takes effect immediately;
// the cost is a couple of env reads plus, on Windows only, one cheap codepage
// syscall.
func activeGlyphs() glyphSet {
if supportsUnicode() {
return unicodeGlyphs
}
return asciiGlyphs
}
// spinFrames returns the animated-spinner frame cycle. Braille frames need
// font coverage that the check / box-drawing glyphs don't: legacy conhost
// fonts (Consolas on a CP65001 console) render ✓ and █ but draw braille as
// boxes, so on Windows the braille cycle is reserved for terminals that
// declare themselves modern (Windows Terminal, ConEmu, an inherited TERM).
// Everything else animates with the four-frame ASCII cycle.
func spinFrames() []string {
if !supportsUnicode() {
return asciiSpin
}
if runtime.GOOS == "windows" && !windowsModernTerminal() {
return asciiSpin
}
return brailleSpin
}
// windowsModernTerminal reports whether the process runs under a Windows
// terminal with full glyph coverage: Windows Terminal (WT_SESSION), ConEmu
// (ConEmuANSI=ON), or an environment that carries a unix-style TERM (mintty,
// msys, ssh sessions).
func windowsModernTerminal() bool {
if os.Getenv("WT_SESSION") != "" {
return true
}
if os.Getenv("ConEmuANSI") == "ON" {
return true
}
return os.Getenv("TERM") != ""
}
// supportsUnicode reports whether the active terminal can render the UTF-8
// box-drawing / check glyphs. Explicit env overrides win (GORTEX_ASCII opt-out,
// GORTEX_UNICODE opt-in); a linux virtual console (TERM=linux, CP437-ish) and a
// non-UTF-8 Windows console codepage both fall back to ASCII. Every other
// terminal is assumed UTF-8-capable, the modern default.
func supportsUnicode() bool {
if envFlag("GORTEX_ASCII") {
return false
}
if envFlag("GORTEX_UNICODE") {
return true
}
if os.Getenv("TERM") == "linux" {
return false
}
if runtime.GOOS == "windows" {
return windowsConsoleUTF8()
}
return true
}
// envFlag reports whether the named env var is set to a truthy value.
func envFlag(name string) bool {
switch os.Getenv(name) {
case "1", "true", "TRUE", "yes", "on":
return true
}
return false
}