项目文件夹

文件
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

165 行
4.6 KiB
Go

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
package progress
import (
"strings"
"github.com/charmbracelet/lipgloss"
)
// The gortex mark is a 5×5 dot-matrix "G": an open ring with a tongue in the
// middle row whose tip — the accent dot — always renders in brand green. The
// live renderer lights the remaining dots progressively as work completes, so
// the logo itself is the coarse progress gauge; banners render it fully lit.
type gDot struct {
r, c int
accent bool
}
// gDots lists the mark's dots in row-major order — the order they light up.
var gDots = buildGDots()
func buildGDots() []gDot {
const cells = 5
mid := cells / 2
var dots []gDot
for r := 0; r < cells; r++ {
for c := 0; c < cells; c++ {
onTop := r == 0 && c >= 1 && c <= cells-2
onBot := r == cells-1 && c >= 1 && c <= cells-2
onLeft := c == 0 && r >= 1 && r <= cells-2
onTongue := r == mid && c >= mid && c <= cells-1
onTopRight := c == cells-1 && r == 1
onBotRight := c == cells-1 && r == cells-2
if onTop || onBot || onLeft || onTongue || onTopRight || onBotRight {
dots = append(dots, gDot{r: r, c: c, accent: r == mid && c == cells-1})
}
}
}
return dots
}
// litDotCount is the number of dots that participate in progressive lighting
// (every dot except the always-lit accent tip).
func litDotCount() int { return len(gDots) - 1 }
// logoLines renders the mark as 5 rows. frac in [0,1] lights that fraction of
// the dots bottom-up in row-major order; frac < 0 selects the indeterminate
// marquee — a short lit window orbiting the mark at the given tick. glint, when
// >= 0, additionally paints dot (glint % len) in accent green: the traveling
// highlight used by animated banners over a fully lit mark.
func logoLines(lit, dim, accent lipgloss.Style, g glyphSet, frac float64, tick, glint int) [5]string {
const cells = 5
byPos := make(map[[2]int]int, len(gDots))
for i, d := range gDots {
byPos[[2]int{d.r, d.c}] = i
}
litN := -1
if frac >= 0 {
if frac > 1 {
frac = 1
}
litN = int(frac*float64(litDotCount()) + 0.5)
}
// Non-accent ordinal per dot index, for both fill and marquee windows.
ordinal := make([]int, len(gDots))
ord := 0
for i, d := range gDots {
if d.accent {
ordinal[i] = -1
continue
}
ordinal[i] = ord
ord++
}
const marqueeWindow = 4
var lines [5]string
for r := 0; r < cells; r++ {
var row strings.Builder
for c := 0; c < cells; c++ {
if c > 0 {
row.WriteString(" ")
}
idx, isDot := byPos[[2]int{r, c}]
if !isDot {
row.WriteString(" ")
continue
}
d := gDots[idx]
switch {
case d.accent:
row.WriteString(accent.Render(g.Dot))
case glint >= 0 && idx == glint%len(gDots):
row.WriteString(accent.Render(g.Dot))
case litN >= 0 && ordinal[idx] < litN:
row.WriteString(lit.Render(g.Dot))
case litN < 0 && marqueeHit(ordinal[idx], tick, marqueeWindow):
row.WriteString(lit.Render(g.Dot))
default:
row.WriteString(dim.Render(g.DotDim))
}
}
lines[r] = row.String()
}
return lines
}
// marqueeHit reports whether the dot with the given non-accent ordinal falls
// inside the lit window at this tick.
func marqueeHit(ord, tick, window int) bool {
n := litDotCount()
if ord < 0 || n == 0 {
return false
}
start := tick % n
for i := 0; i < window; i++ {
if (start+i)%n == ord {
return true
}
}
return false
}
// MeshLogo renders one static frame of the gortex mark, fully lit, styled
// with the package palette. A positive tick adds a traveling green glint —
// animated banners (the wizard dashboard) pass a rising tick; static banners
// pass 0 for the pure mark.
func MeshLogo(tick int) string {
glint := -1
if tick > 0 {
glint = tick
}
lines := logoLines(stylePerim, styleInner, styleAccent, activeGlyphs(), 1, tick, glint)
return strings.Join(lines[:], "\n")
}
// MeshFrame returns the gortex mark with label (bold) and sub (dim) beside
// it. Used by watch loops or custom views that want the brand block without
// owning a live tracker.
func MeshFrame(tick int, label, sub string) string {
mesh := MeshLogo(tick)
if label == "" && sub == "" {
return mesh + "\n"
}
right := lipgloss.JoinVertical(
lipgloss.Left,
"",
styleLabel.Render(label),
"",
styleSub.Render(sub),
"",
)
return lipgloss.JoinHorizontal(lipgloss.Top, mesh, " ", right) + "\n"
}
// MeshLogoLines returns the number of vertical rows the mark occupies.
// Exported so wizard / dashboard layouts can reserve space without re-counting
// the constant.
func MeshLogoLines() int { return 5 }
// MeshLogoWidth returns the rendered visual width of the mark in cells.
// 5 cells × "● " spacing = 9 chars.
func MeshLogoWidth() int { return 9 }