refactor(ui): standardize on lipgloss semantic color system
Replace all fatih/color usages with internal/ui package that provides: - Semantic color tokens (Pass, Warn, Fail, Accent, Muted) - Adaptive light/dark mode support via Lipgloss AdaptiveColor - Ayu theme colors for consistent, accessible output - Tufte-inspired data-ink ratio principles Files migrated: 35 command files in cmd/bd/ Add docs/ui-philosophy.md documenting: - Semantic token usage guidelines - Light/dark terminal optimization rationale - Tufte and perceptual UI/UX theory application - When to use (and not use) color in CLI output
This commit is contained in:
@@ -11,7 +11,6 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/steveyegge/beads/cmd/bd/doctor"
|
||||
"github.com/steveyegge/beads/internal/beads"
|
||||
@@ -21,12 +20,14 @@ import (
|
||||
"github.com/steveyegge/beads/internal/storage/sqlite"
|
||||
"github.com/steveyegge/beads/internal/syncbranch"
|
||||
"github.com/steveyegge/beads/internal/types"
|
||||
"github.com/steveyegge/beads/internal/ui"
|
||||
"github.com/steveyegge/beads/internal/utils"
|
||||
)
|
||||
|
||||
var initCmd = &cobra.Command{
|
||||
Use: "init",
|
||||
Short: "Initialize bd in the current directory",
|
||||
Use: "init",
|
||||
GroupID: "setup",
|
||||
Short: "Initialize bd in the current directory",
|
||||
Long: `Initialize bd in the current directory by creating a .beads/ directory
|
||||
and database file. Optionally specify a custom issue prefix.
|
||||
|
||||
@@ -225,15 +226,12 @@ With --stealth: configures global git settings for invisible beads usage:
|
||||
}
|
||||
|
||||
if !quiet {
|
||||
green := color.New(color.FgGreen).SprintFunc()
|
||||
cyan := color.New(color.FgCyan).SprintFunc()
|
||||
|
||||
fmt.Printf("\n%s bd initialized successfully in --no-db mode!\n\n", green("✓"))
|
||||
fmt.Printf(" Mode: %s\n", cyan("no-db (JSONL-only)"))
|
||||
fmt.Printf(" Issues file: %s\n", cyan(jsonlPath))
|
||||
fmt.Printf(" Issue prefix: %s\n", cyan(prefix))
|
||||
fmt.Printf(" Issues will be named: %s\n\n", cyan(prefix+"-<hash> (e.g., "+prefix+"-a3f2dd)"))
|
||||
fmt.Printf("Run %s to get started.\n\n", cyan("bd --no-db quickstart"))
|
||||
fmt.Printf("\n%s bd initialized successfully in --no-db mode!\n\n", ui.RenderPass("✓"))
|
||||
fmt.Printf(" Mode: %s\n", ui.RenderAccent("no-db (JSONL-only)"))
|
||||
fmt.Printf(" Issues file: %s\n", ui.RenderAccent(jsonlPath))
|
||||
fmt.Printf(" Issue prefix: %s\n", ui.RenderAccent(prefix))
|
||||
fmt.Printf(" Issues will be named: %s\n\n", ui.RenderAccent(prefix+"-<hash> (e.g., "+prefix+"-a3f2dd)"))
|
||||
fmt.Printf("Run %s to get started.\n\n", ui.RenderAccent("bd --no-db quickstart"))
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -427,9 +425,8 @@ With --stealth: configures global git settings for invisible beads usage:
|
||||
// Install by default unless --skip-hooks is passed
|
||||
if !skipHooks && isGitRepo() && !hooksInstalled() {
|
||||
if err := installGitHooks(); err != nil && !quiet {
|
||||
yellow := color.New(color.FgYellow).SprintFunc()
|
||||
fmt.Fprintf(os.Stderr, "\n%s Failed to install git hooks: %v\n", yellow("⚠"), err)
|
||||
fmt.Fprintf(os.Stderr, "You can try again with: %s\n\n", color.New(color.FgCyan).Sprint("bd doctor --fix"))
|
||||
fmt.Fprintf(os.Stderr, "\n%s Failed to install git hooks: %v\n", ui.RenderWarn("⚠"), err)
|
||||
fmt.Fprintf(os.Stderr, "You can try again with: %s\n\n", ui.RenderAccent("bd doctor --fix"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -437,9 +434,8 @@ With --stealth: configures global git settings for invisible beads usage:
|
||||
// Install by default unless --skip-merge-driver is passed
|
||||
if !skipMergeDriver && isGitRepo() && !mergeDriverInstalled() {
|
||||
if err := installMergeDriver(); err != nil && !quiet {
|
||||
yellow := color.New(color.FgYellow).SprintFunc()
|
||||
fmt.Fprintf(os.Stderr, "\n%s Failed to install merge driver: %v\n", yellow("⚠"), err)
|
||||
fmt.Fprintf(os.Stderr, "You can try again with: %s\n\n", color.New(color.FgCyan).Sprint("bd doctor --fix"))
|
||||
fmt.Fprintf(os.Stderr, "\n%s Failed to install merge driver: %v\n", ui.RenderWarn("⚠"), err)
|
||||
fmt.Fprintf(os.Stderr, "You can try again with: %s\n\n", ui.RenderAccent("bd doctor --fix"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -454,14 +450,11 @@ With --stealth: configures global git settings for invisible beads usage:
|
||||
return
|
||||
}
|
||||
|
||||
green := color.New(color.FgGreen).SprintFunc()
|
||||
cyan := color.New(color.FgCyan).SprintFunc()
|
||||
|
||||
fmt.Printf("\n%s bd initialized successfully!\n\n", green("✓"))
|
||||
fmt.Printf(" Database: %s\n", cyan(initDBPath))
|
||||
fmt.Printf(" Issue prefix: %s\n", cyan(prefix))
|
||||
fmt.Printf(" Issues will be named: %s\n\n", cyan(prefix+"-<hash> (e.g., "+prefix+"-a3f2dd)"))
|
||||
fmt.Printf("Run %s to get started.\n\n", cyan("bd quickstart"))
|
||||
fmt.Printf("\n%s bd initialized successfully!\n\n", ui.RenderPass("✓"))
|
||||
fmt.Printf(" Database: %s\n", ui.RenderAccent(initDBPath))
|
||||
fmt.Printf(" Issue prefix: %s\n", ui.RenderAccent(prefix))
|
||||
fmt.Printf(" Issues will be named: %s\n\n", ui.RenderAccent(prefix+"-<hash> (e.g., "+prefix+"-a3f2dd)"))
|
||||
fmt.Printf("Run %s to get started.\n\n", ui.RenderAccent("bd quickstart"))
|
||||
|
||||
// Run bd doctor diagnostics to catch setup issues early (bd-zwtq)
|
||||
doctorResult := runDiagnostics(cwd)
|
||||
@@ -474,15 +467,14 @@ With --stealth: configures global git settings for invisible beads usage:
|
||||
}
|
||||
}
|
||||
if hasIssues {
|
||||
yellow := color.New(color.FgYellow).SprintFunc()
|
||||
fmt.Printf("%s Setup incomplete. Some issues were detected:\n", yellow("⚠"))
|
||||
fmt.Printf("%s Setup incomplete. Some issues were detected:\n", ui.RenderWarn("⚠"))
|
||||
// Show just the warnings/errors, not all checks
|
||||
for _, check := range doctorResult.Checks {
|
||||
if check.Status != statusOK {
|
||||
fmt.Printf(" • %s: %s\n", check.Name, check.Message)
|
||||
}
|
||||
}
|
||||
fmt.Printf("\nRun %s to see details and fix these issues.\n\n", cyan("bd doctor --fix"))
|
||||
fmt.Printf("\nRun %s to see details and fix these issues.\n\n", ui.RenderAccent("bd doctor --fix"))
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -592,9 +584,7 @@ func detectExistingHooks() []hookInfo {
|
||||
|
||||
// promptHookAction asks user what to do with existing hooks
|
||||
func promptHookAction(existingHooks []hookInfo) string {
|
||||
yellow := color.New(color.FgYellow).SprintFunc()
|
||||
|
||||
fmt.Printf("\n%s Found existing git hooks:\n", yellow("⚠"))
|
||||
fmt.Printf("\n%s Found existing git hooks:\n", ui.RenderWarn("⚠"))
|
||||
for _, hook := range existingHooks {
|
||||
if hook.exists && !hook.isBdHook {
|
||||
hookType := "custom script"
|
||||
@@ -646,7 +636,6 @@ func installGitHooks() error {
|
||||
// Determine installation mode
|
||||
chainHooks := false
|
||||
if hasExistingHooks {
|
||||
cyan := color.New(color.FgCyan).SprintFunc()
|
||||
choice := promptHookAction(existingHooks)
|
||||
switch choice {
|
||||
case "1", "":
|
||||
@@ -665,7 +654,7 @@ func installGitHooks() error {
|
||||
}
|
||||
case "3":
|
||||
fmt.Printf("Skipping git hooks installation.\n")
|
||||
fmt.Printf("You can install manually later with: %s\n", cyan("./examples/git-hooks/install.sh"))
|
||||
fmt.Printf("You can install manually later with: %s\n", ui.RenderAccent("./examples/git-hooks/install.sh"))
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("invalid choice: %s", choice)
|
||||
@@ -971,8 +960,7 @@ exit 0
|
||||
}
|
||||
|
||||
if chainHooks {
|
||||
green := color.New(color.FgGreen).SprintFunc()
|
||||
fmt.Printf("%s Chained bd hooks with existing hooks\n", green("✓"))
|
||||
fmt.Printf("%s Chained bd hooks with existing hooks\n", ui.RenderPass("✓"))
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -1400,12 +1388,10 @@ func setupStealthMode(verbose bool) error {
|
||||
}
|
||||
|
||||
if verbose {
|
||||
green := color.New(color.FgGreen).SprintFunc()
|
||||
cyan := color.New(color.FgCyan).SprintFunc()
|
||||
fmt.Printf("\n%s Stealth mode configured successfully!\n\n", green("✓"))
|
||||
fmt.Printf(" Global gitignore: %s\n", cyan(projectPath+"/.beads/ ignored"))
|
||||
fmt.Printf(" Claude settings: %s\n\n", cyan("configured with bd onboard instruction"))
|
||||
fmt.Printf("Your beads setup is now %s - other repo collaborators won't see any beads-related files.\n\n", cyan("invisible"))
|
||||
fmt.Printf("\n%s Stealth mode configured successfully!\n\n", ui.RenderPass("✓"))
|
||||
fmt.Printf(" Global gitignore: %s\n", ui.RenderAccent(projectPath+"/.beads/ ignored"))
|
||||
fmt.Printf(" Claude settings: %s\n\n", ui.RenderAccent("configured with bd onboard instruction"))
|
||||
fmt.Printf("Your beads setup is now %s - other repo collaborators won't see any beads-related files.\n\n", ui.RenderAccent("invisible"))
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -1550,9 +1536,6 @@ func checkExistingBeadsData(prefix string) error {
|
||||
// Check for existing database file
|
||||
dbPath := filepath.Join(beadsDir, beads.CanonicalDatabaseName)
|
||||
if _, err := os.Stat(dbPath); err == nil {
|
||||
yellow := color.New(color.FgYellow).SprintFunc()
|
||||
cyan := color.New(color.FgCyan).SprintFunc()
|
||||
|
||||
return fmt.Errorf(`
|
||||
%s Found existing database: %s
|
||||
|
||||
@@ -1564,7 +1547,7 @@ To use the existing database:
|
||||
To completely reinitialize (data loss warning):
|
||||
rm -rf .beads && bd init --prefix %s
|
||||
|
||||
Aborting.`, yellow("⚠"), dbPath, cyan("bd list"), prefix)
|
||||
Aborting.`, ui.RenderWarn("⚠"), dbPath, ui.RenderAccent("bd list"), prefix)
|
||||
}
|
||||
|
||||
// Fresh clones (JSONL exists but no database) are allowed - init will
|
||||
@@ -1646,8 +1629,7 @@ bd sync # Sync with git
|
||||
return fmt.Errorf("failed to create %s: %w", filename, err)
|
||||
}
|
||||
if verbose {
|
||||
green := color.New(color.FgGreen).SprintFunc()
|
||||
fmt.Printf(" %s Created %s with landing-the-plane instructions\n", green("✓"), filename)
|
||||
fmt.Printf(" %s Created %s with landing-the-plane instructions\n", ui.RenderPass("✓"), filename)
|
||||
}
|
||||
return nil
|
||||
} else if err != nil {
|
||||
@@ -1674,8 +1656,7 @@ bd sync # Sync with git
|
||||
return fmt.Errorf("failed to update %s: %w", filename, err)
|
||||
}
|
||||
if verbose {
|
||||
green := color.New(color.FgGreen).SprintFunc()
|
||||
fmt.Printf(" %s Added landing-the-plane instructions to %s\n", green("✓"), filename)
|
||||
fmt.Printf(" %s Added landing-the-plane instructions to %s\n", ui.RenderPass("✓"), filename)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user