Split 6 files exceeding 800 lines by extracting cohesive function groups: - show.go (1592→578): extracted show_thread.go, close.go, edit.go, update.go - doctor.go (1295→690): extracted doctor_fix.go, doctor_health.go, doctor_pollution.go - sync.go (1201→749): extracted sync_git.go - compact.go (1199→775): extracted compact_tombstone.go, compact_rpc.go - linear.go (1190→641): extracted linear_sync.go, linear_conflict.go - main.go (1148→800): extracted main_help.go, main_errors.go, main_daemon.go All files now under 800-line acceptance criteria. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
137 lines
4.6 KiB
Go
137 lines
4.6 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"github.com/spf13/cobra"
|
|
"github.com/steveyegge/beads/internal/ui"
|
|
)
|
|
|
|
// colorizedHelpFunc wraps Cobra's default help with semantic coloring
|
|
// Applies subtle accent color to group headers for visual hierarchy
|
|
func colorizedHelpFunc(cmd *cobra.Command, args []string) {
|
|
// Build full help output: Long description + Usage
|
|
var output strings.Builder
|
|
|
|
// Include Long description first (like Cobra's default help)
|
|
if cmd.Long != "" {
|
|
output.WriteString(cmd.Long)
|
|
output.WriteString("\n\n")
|
|
} else if cmd.Short != "" {
|
|
output.WriteString(cmd.Short)
|
|
output.WriteString("\n\n")
|
|
}
|
|
|
|
// Add the usage string which contains commands, flags, etc.
|
|
output.WriteString(cmd.UsageString())
|
|
|
|
// Apply semantic coloring
|
|
result := colorizeHelpOutput(output.String())
|
|
fmt.Print(result)
|
|
}
|
|
|
|
// colorizeHelpOutput applies semantic colors to help text
|
|
// - Group headers get accent color for visual hierarchy
|
|
// - Section headers (Examples:, Flags:) get accent color
|
|
// - Command names get subtle styling for scanability
|
|
// - Flag names get bold styling, types get muted
|
|
// - Default values get muted styling
|
|
func colorizeHelpOutput(help string) string {
|
|
// Match group header lines (e.g., "Working With Issues:")
|
|
// These are standalone lines ending with ":" and followed by commands
|
|
groupHeaderRE := regexp.MustCompile(`(?m)^([A-Z][A-Za-z &]+:)\s*$`)
|
|
|
|
result := groupHeaderRE.ReplaceAllStringFunc(help, func(match string) string {
|
|
// Trim whitespace, colorize, then restore
|
|
trimmed := strings.TrimSpace(match)
|
|
return ui.RenderAccent(trimmed)
|
|
})
|
|
|
|
// Match section headers in subcommand help (Examples:, Flags:, etc.)
|
|
sectionHeaderRE := regexp.MustCompile(`(?m)^(Examples|Flags|Usage|Global Flags|Aliases|Available Commands):`)
|
|
result = sectionHeaderRE.ReplaceAllStringFunc(result, func(match string) string {
|
|
return ui.RenderAccent(match)
|
|
})
|
|
|
|
// Match command lines: " command Description text"
|
|
// Commands are indented with 2 spaces, followed by spaces, then description
|
|
// Pattern matches: indent + command-name (with hyphens) + spacing + description
|
|
cmdLineRE := regexp.MustCompile(`(?m)^( )([a-z][a-z0-9]*(?:-[a-z0-9]+)*)(\s{2,})(.*)$`)
|
|
|
|
result = cmdLineRE.ReplaceAllStringFunc(result, func(match string) string {
|
|
parts := cmdLineRE.FindStringSubmatch(match)
|
|
if len(parts) != 5 {
|
|
return match
|
|
}
|
|
indent := parts[1]
|
|
cmdName := parts[2]
|
|
spacing := parts[3]
|
|
description := parts[4]
|
|
|
|
// Colorize command references in description (e.g., 'comments add')
|
|
description = colorizeCommandRefs(description)
|
|
|
|
// Highlight entry point hints (e.g., "(start here)")
|
|
description = highlightEntryPoints(description)
|
|
|
|
// Subtle styling on command name for scanability
|
|
return indent + ui.RenderCommand(cmdName) + spacing + description
|
|
})
|
|
|
|
// Match flag lines: " -f, --file string Description"
|
|
// Pattern: indent + flags + spacing + optional type + description
|
|
flagLineRE := regexp.MustCompile(`(?m)^(\s+)(-\w,\s+--[\w-]+|--[\w-]+)(\s+)(string|int|duration|bool)?(\s*.*)$`)
|
|
result = flagLineRE.ReplaceAllStringFunc(result, func(match string) string {
|
|
parts := flagLineRE.FindStringSubmatch(match)
|
|
if len(parts) < 6 {
|
|
return match
|
|
}
|
|
indent := parts[1]
|
|
flags := parts[2]
|
|
spacing := parts[3]
|
|
typeStr := parts[4]
|
|
desc := parts[5]
|
|
|
|
// Mute default values in description
|
|
desc = muteDefaults(desc)
|
|
|
|
if typeStr != "" {
|
|
return indent + ui.RenderCommand(flags) + spacing + ui.RenderMuted(typeStr) + desc
|
|
}
|
|
return indent + ui.RenderCommand(flags) + spacing + desc
|
|
})
|
|
|
|
return result
|
|
}
|
|
|
|
// muteDefaults applies muted styling to default value annotations
|
|
func muteDefaults(text string) string {
|
|
defaultRE := regexp.MustCompile(`(\(default[^)]*\))`)
|
|
return defaultRE.ReplaceAllStringFunc(text, func(match string) string {
|
|
return ui.RenderMuted(match)
|
|
})
|
|
}
|
|
|
|
// highlightEntryPoints applies accent styling to entry point hints like "(start here)"
|
|
func highlightEntryPoints(text string) string {
|
|
entryRE := regexp.MustCompile(`(\(start here\))`)
|
|
return entryRE.ReplaceAllStringFunc(text, func(match string) string {
|
|
return ui.RenderAccent(match)
|
|
})
|
|
}
|
|
|
|
// colorizeCommandRefs applies command styling to references in text
|
|
// Matches patterns like 'command name' or 'bd command'
|
|
func colorizeCommandRefs(text string) string {
|
|
// Match 'command words' in single quotes (e.g., 'comments add')
|
|
cmdRefRE := regexp.MustCompile(`'([a-z][a-z0-9 -]+)'`)
|
|
|
|
return cmdRefRE.ReplaceAllStringFunc(text, func(match string) string {
|
|
// Extract the command name without quotes
|
|
inner := match[1 : len(match)-1]
|
|
return "'" + ui.RenderCommand(inner) + "'"
|
|
})
|
|
}
|