122 lines
2.7 KiB
Go
122 lines
2.7 KiB
Go
package cli
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"os"
|
|
"runtime"
|
|
"strings"
|
|
"sync"
|
|
)
|
|
|
|
type Printer struct {
|
|
mutex sync.Mutex
|
|
Program string
|
|
Debugging bool
|
|
Color bool
|
|
}
|
|
|
|
func (printer *Printer) Debug(v ...any) {
|
|
if printer.Debugging {
|
|
printer.mutex.Lock()
|
|
fmt.Fprint(os.Stdout, "dbg ")
|
|
_, file, line, ok := runtime.Caller(2)
|
|
if ok {
|
|
lastSegment := strings.LastIndex(file, "/") + 1
|
|
fmt.Fprint(os.Stdout, "@ ", file[lastSegment:], ":", line, " ")
|
|
}
|
|
fmt.Fprintln(os.Stdout, v...)
|
|
printer.mutex.Unlock()
|
|
}
|
|
}
|
|
|
|
func fprintIndented(f *os.File, maxWidth int, indent int, value any) {
|
|
wrapped := wrap.Indents(indent, wrap.Wrap(fmt.Sprint(value), maxWidth-indent))
|
|
for _, line := range wrapped {
|
|
fmt.Fprintln(f, line)
|
|
}
|
|
}
|
|
|
|
func (printer *Printer) printErrorMessage(msg string, details ...error) {
|
|
termInfo := GetStderrInfo()
|
|
if termInfo.SupportsColor && printer.Color {
|
|
errorStyle(os.Stderr)
|
|
}
|
|
|
|
fmt.Fprintln(os.Stderr, "Error:", msg)
|
|
for _, detail := range details {
|
|
fprintIndented(os.Stderr, termInfo.Width, 3, detail)
|
|
}
|
|
|
|
if termInfo.SupportsColor && printer.Color {
|
|
resetStyle(os.Stderr)
|
|
}
|
|
}
|
|
|
|
func (printer *Printer) Error(msg string, details ...error) {
|
|
printer.mutex.Lock()
|
|
printer.printErrorMessage(msg, details...)
|
|
printer.mutex.Unlock()
|
|
}
|
|
|
|
func (printer *Printer) Fatal(msg string, reason ExitReason, details ...error) {
|
|
printer.mutex.Lock()
|
|
printer.printErrorMessage(msg, details...)
|
|
if reason == BadUsage {
|
|
fmt.Fprintf(os.Stdout, "run '%s --help' for usage\n", printer.Program)
|
|
}
|
|
os.Exit(int(reason))
|
|
}
|
|
|
|
var defaultPrinter Printer
|
|
|
|
func DefaultPrinter() *Printer {
|
|
return &defaultPrinter
|
|
}
|
|
|
|
func Debug(v ...any) {
|
|
defaultPrinter.Debug(v...)
|
|
}
|
|
|
|
func Error(msg string, details ...error) {
|
|
defaultPrinter.Error(msg, details...)
|
|
}
|
|
|
|
func Fatal(msg string, reason ExitReason, details ...error) {
|
|
defaultPrinter.Fatal(msg, reason, details...)
|
|
}
|
|
|
|
func InvalidArgs(errs ...error) {
|
|
Fatal("invalid command-line arguments", BadUsage, errs...)
|
|
}
|
|
|
|
func Show(msg string) {
|
|
termInfo := GetStdoutInfo()
|
|
wrapped := wrap.Wrap(msg, termInfo.Width)
|
|
for _, line := range wrapped {
|
|
fmt.Println(line)
|
|
}
|
|
}
|
|
|
|
func ShowUsage(explanation string, examples ...string) {
|
|
fmt.Print(explanation, "\n\nUsage:\n")
|
|
for _, line := range wrap.Indents(3, examples) {
|
|
fmt.Println(line)
|
|
}
|
|
}
|
|
|
|
func DescribeOption(name string, description string) {
|
|
name = " " + name + " "
|
|
termInfo := GetStdoutInfo()
|
|
wrapped := wrap.Indentfs(name, len(name), wrap.Wrap(description, termInfo.Width-len(name)))
|
|
for _, line := range wrapped {
|
|
fmt.Println(line)
|
|
}
|
|
}
|
|
|
|
func AskString(prompt string) string {
|
|
fmt.Print(prompt)
|
|
reader := bufio.NewReader(os.Stdin)
|
|
text, _ := reader.ReadString('\n')
|
|
return text
|
|
} |