194 lines
4.6 KiB
Go
194 lines
4.6 KiB
Go
|
|
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",
|
||
|
|
},
|
||
|
|
}
|
||
|
|
|
||
|
|
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
|
||
|
|
}
|
||
|
|
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 "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
|
||
|
|
}
|