zutils/cmd/help.go

275 lines
7.1 KiB
Go
Raw Normal View History

package cmd
import (
"fmt"
"strings"
"github.com/zemenawi/zutils/pkg/colors"
)
type CommandHelp struct {
Name string
Help string
Examples []string
}
var readHelp = CommandHelp{
Name: "read",
Help: "Read and display file with smart detection.\n" +
"Automatically detects file type:\n" +
" - Markdown (.md) - Renders with colored headings, lists, code blocks\n" +
" - Code files - Syntax highlighting with line numbers\n" +
" - Other files - Plain text display",
Examples: []string{
"z read README.md # Read markdown file",
"z read main.go # Read code with syntax highlighting",
"z read package.json # Read JSON file",
},
}
var sysHelp = CommandHelp{
Name: "sys",
Help: "Show system overview including CPU, memory, disk usage, and top processes.\n" +
"Useful for quick system diagnostics.",
Examples: []string{
"z sys # Show full system overview",
},
}
var findHelp = CommandHelp{
Name: "find",
Help: "Find files matching criteria.\n" +
"Supports glob patterns, size filters, modification time, and depth limits.",
Examples: []string{
"z find . -name '*.go' # Find all Go files",
"z find . -mtime 7 # Files modified in last 7 days",
"z find . -size +1m # Files larger than 1MB",
"z find . -type d # Directories only",
},
}
var searchHelp = CommandHelp{
Name: "search",
Help: "Search for a pattern in files.\n" +
"A user-friendly alternative to grep with colored output.",
Examples: []string{
"z search func cmd/ # Search for 'func' in cmd directory",
"z search -i 'error' . # Case-insensitive search",
"z search -w 'import' *.go # Whole word match",
"z search -C 2 'TODO' . # Show 2 lines of context",
},
}
var usageHelp = CommandHelp{
Name: "usage",
Help: "Show resource usage (CPU, memory) for processes matching a name.\n" +
"Useful for monitoring specific applications or services.",
Examples: []string{
"z usage cron # Show cron process usage",
"z usage mongod # Show MongoDB usage",
"z usage chrome # Show all Chrome processes",
"z usage postgres # Show PostgreSQL usage",
},
}
var junksHelp = CommandHelp{
Name: "junks",
Help: "Find and clean junk files (caches, temporary files).\n" +
"Shows storage taken by build outputs, caches, and temporary files.\n" +
"Safe to clean: build outputs, caches, temporary files.\n" +
"Not cleanable: runtime version files (require manual cleanup).",
Examples: []string{
"z junks # List junk files and space usage",
"z junks clean # Preview what will be cleaned",
"z junks clean --force # Actually clean junk files",
},
}
var portsHelp = CommandHelp{
Name: "ports",
Help: "Show all listening ports and the processes using them.\n" +
"Useful for debugging network services and finding port conflicts.",
Examples: []string{
"z ports # Show listening ports",
"z ports -a # Show all ports (including established)",
"z ports 8080 # Filter by specific port",
},
}
var usagesHelp = CommandHelp{
Name: "usages",
Help: "Show all running processes sorted by resource usage.\n" +
"By default sorts by CPU usage. Use -m to sort by memory.",
Examples: []string{
"z usages # Top processes by CPU",
"z usages -m # Top processes by memory",
"z usages -n=50 # Show top 50 processes",
"z usages chrome # Filter processes by name",
},
}
var networkHelp = CommandHelp{
Name: "network",
Help: "Show network information including:\n" +
" - Local IP addresses\n" +
" - Public IP\n" +
" - DNS servers\n" +
" - Active network connections",
Examples: []string{
"z network # Show network overview",
},
}
var treeHelp = CommandHelp{
Name: "tree",
Help: "Display directory tree with file sizes and gitignore support.\n" +
"Shows [ignored by git] label for gitignored files.\n" +
"File sizes shown in parentheses for regular files.",
Examples: []string{
"z tree # Show current directory tree",
"z tree /path/to/dir # Show specific directory",
"z tree -a # Show hidden files",
"z tree -i # Show gitignored files",
},
}
func PrintErrorAndHelp(name string, err error) {
help := getHelpForCommand(name)
fmt.Printf("\n %s✖ Error: %s%s\n\n", colors.Red, err, colors.Reset)
if help != nil {
fmt.Printf(" %sUsage:%s z %s %s\n\n", colors.Bold, colors.Reset, help.Name, getUsageHint(help.Name))
if help.Help != "" {
fmt.Printf(" %sDescription:%s\n", colors.Bold, colors.Reset)
lines := splitIntoLines(help.Help, 60)
for _, line := range lines {
fmt.Printf(" %s%s%s\n", colors.Reset, line, colors.Reset)
}
fmt.Printf("\n")
}
if len(help.Examples) > 0 {
fmt.Printf(" %sExamples:%s\n", colors.Bold, colors.Reset)
for _, ex := range help.Examples {
fmt.Printf(" %s%s%s\n", colors.Green, ex, colors.Reset)
}
fmt.Printf("\n")
}
}
}
func getHelpForCommand(name string) *CommandHelp {
switch name {
case "read":
return &readHelp
case "sys":
return &sysHelp
case "find":
return &findHelp
case "search":
return &searchHelp
case "usage":
return &usageHelp
case "junks":
return &junksHelp
case "ports":
return &portsHelp
case "usages":
return &usagesHelp
case "network":
return &networkHelp
case "tree":
return &treeHelp
}
return nil
}
func getUsageHint(name string) string {
switch name {
case "read":
return "<file>"
case "sys":
return ""
case "find":
return "[path] [options]"
case "search":
return "<pattern> [path]"
case "usage":
return "<process-name>"
case "junks":
return "[clean]"
case "ports":
return "[-a] [port]"
case "usages":
return "[-m] [-n=N]"
case "network":
return ""
case "tree":
return "[path] [-a] [-i]"
case "info":
return "<file|dir|network>"
}
return ""
}
func splitIntoLines(text string, maxLen int) []string {
var lines []string
paragraphs := splitIntoParagraphs(text)
for _, para := range paragraphs {
if para == "" {
lines = append(lines, "")
continue
}
words := strings.Fields(para)
currentLine := ""
for _, word := range words {
if currentLine == "" {
currentLine = word
} else if len(currentLine)+len(word)+1 <= maxLen {
currentLine += " " + word
} else {
lines = append(lines, currentLine)
currentLine = word
}
}
if currentLine != "" {
lines = append(lines, currentLine)
}
}
return lines
}
func splitIntoParagraphs(text string) []string {
var paragraphs []string
lines := strings.Split(text, "\n")
current := ""
for _, line := range lines {
trimmed := strings.TrimSpace(line)
if trimmed == "" {
if current != "" {
paragraphs = append(paragraphs, current)
current = ""
}
} else {
if current != "" {
current += " "
}
current += trimmed
}
}
if current != "" {
paragraphs = append(paragraphs, current)
}
return paragraphs
}