* fix(docs): respect workspace.yaml packages_dir setting (fixes #46) * fix(workspace): improve config loading logic (CR feedback) - Expand ~ before resolving relative paths in cmd_registry - Handle LoadWorkspaceConfig errors properly - Update Repo.Path when PackagesDir overrides default - Validate workspace config version - Add unit tests for workspace config loading * docs: add comments and increase test coverage (CR feedback) - Add docstrings to exported functions in pkg/cli - Add unit tests for Semantic Output (pkg/cli/output.go) - Add unit tests for CheckBuilder (pkg/cli/check.go) - Add unit tests for IPC Query/Perform (pkg/framework/core) * fix(test): fix panics and failures in php package tests - Fix panic in TestLookupLinuxKit_Bad by mocking paths - Fix assertion errors in TestGetSSLDir_Bad and TestGetPackageInfo_Bad - Fix formatting in test files * fix(test): correct syntax in services_extended_test.go * fix(ci): point coverage workflow to go.mod instead of go.work * fix(ci): build CLI before running coverage * fix(ci): run go generate for updater package in coverage workflow * fix(github): allow dry-run publish without gh CLI authentication Moves validation check after dry-run check so tests can verify dry-run behavior in CI environments.
125 lines
No EOL
2.4 KiB
Go
125 lines
No EOL
2.4 KiB
Go
package cli
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// ANSI escape codes
|
|
const (
|
|
ansiReset = "\033[0m"
|
|
ansiBold = "\033[1m"
|
|
ansiDim = "\033[2m"
|
|
ansiItalic = "\033[3m"
|
|
ansiUnderline = "\033[4m"
|
|
)
|
|
|
|
// AnsiStyle represents terminal text styling.
|
|
// Use NewStyle() to create, chain methods, call Render().
|
|
type AnsiStyle struct {
|
|
bold bool
|
|
dim bool
|
|
italic bool
|
|
underline bool
|
|
fg string
|
|
bg string
|
|
}
|
|
|
|
// NewStyle creates a new empty style.
|
|
func NewStyle() *AnsiStyle {
|
|
return &AnsiStyle{}
|
|
}
|
|
|
|
// Bold enables bold text.
|
|
func (s *AnsiStyle) Bold() *AnsiStyle {
|
|
s.bold = true
|
|
return s
|
|
}
|
|
|
|
// Dim enables dim text.
|
|
func (s *AnsiStyle) Dim() *AnsiStyle {
|
|
s.dim = true
|
|
return s
|
|
}
|
|
|
|
// Italic enables italic text.
|
|
func (s *AnsiStyle) Italic() *AnsiStyle {
|
|
s.italic = true
|
|
return s
|
|
}
|
|
|
|
// Underline enables underlined text.
|
|
func (s *AnsiStyle) Underline() *AnsiStyle {
|
|
s.underline = true
|
|
return s
|
|
}
|
|
|
|
// Foreground sets foreground color from hex string.
|
|
func (s *AnsiStyle) Foreground(hex string) *AnsiStyle {
|
|
s.fg = fgColorHex(hex)
|
|
return s
|
|
}
|
|
|
|
// Background sets background color from hex string.
|
|
func (s *AnsiStyle) Background(hex string) *AnsiStyle {
|
|
s.bg = bgColorHex(hex)
|
|
return s
|
|
}
|
|
|
|
// Render applies the style to text.
|
|
func (s *AnsiStyle) Render(text string) string {
|
|
if s == nil {
|
|
return text
|
|
}
|
|
|
|
var codes []string
|
|
if s.bold {
|
|
codes = append(codes, ansiBold)
|
|
}
|
|
if s.dim {
|
|
codes = append(codes, ansiDim)
|
|
}
|
|
if s.italic {
|
|
codes = append(codes, ansiItalic)
|
|
}
|
|
if s.underline {
|
|
codes = append(codes, ansiUnderline)
|
|
}
|
|
if s.fg != "" {
|
|
codes = append(codes, s.fg)
|
|
}
|
|
if s.bg != "" {
|
|
codes = append(codes, s.bg)
|
|
}
|
|
|
|
if len(codes) == 0 {
|
|
return text
|
|
}
|
|
|
|
return strings.Join(codes, "") + text + ansiReset
|
|
}
|
|
|
|
// fgColorHex converts a hex string to an ANSI foreground color code.
|
|
func fgColorHex(hex string) string {
|
|
r, g, b := hexToRGB(hex)
|
|
return fmt.Sprintf("\033[38;2;%d;%d;%dm", r, g, b)
|
|
}
|
|
|
|
// bgColorHex converts a hex string to an ANSI background color code.
|
|
func bgColorHex(hex string) string {
|
|
r, g, b := hexToRGB(hex)
|
|
return fmt.Sprintf("\033[48;2;%d;%d;%dm", r, g, b)
|
|
}
|
|
|
|
// hexToRGB converts a hex string to RGB values.
|
|
func hexToRGB(hex string) (int, int, int) {
|
|
hex = strings.TrimPrefix(hex, "#")
|
|
if len(hex) != 6 {
|
|
return 255, 255, 255
|
|
}
|
|
r, _ := strconv.ParseInt(hex[0:2], 16, 64)
|
|
g, _ := strconv.ParseInt(hex[2:4], 16, 64)
|
|
b, _ := strconv.ParseInt(hex[4:6], 16, 64)
|
|
return int(r), int(g), int(b)
|
|
} |