You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
71 lines
1.2 KiB
71 lines
1.2 KiB
package cliutil
|
|
|
|
import (
|
|
"errors"
|
|
"flag"
|
|
"fmt"
|
|
"io"
|
|
)
|
|
|
|
const ContinueExecution = -1
|
|
|
|
type Builder[T any] func(program string, output io.Writer) (*flag.FlagSet, *T)
|
|
|
|
type Validator[T any] func(*T) error
|
|
|
|
func Parse[T any](
|
|
args []string,
|
|
program string,
|
|
stdout io.Writer,
|
|
stderr io.Writer,
|
|
build Builder[T],
|
|
validate Validator[T],
|
|
) (T, int) {
|
|
var zero T
|
|
|
|
if len(args) == 0 {
|
|
fs, _ := build(program, stdout)
|
|
fs.Usage()
|
|
return zero, 0
|
|
}
|
|
|
|
output := stderr
|
|
if hasHelpFlag(args) {
|
|
output = stdout
|
|
}
|
|
|
|
fs, opts := build(program, output)
|
|
if err := fs.Parse(args); err != nil {
|
|
if errors.Is(err, flag.ErrHelp) {
|
|
return zero, 0
|
|
}
|
|
return zero, 2
|
|
}
|
|
|
|
if validate != nil {
|
|
if err := validate(opts); err != nil {
|
|
Fprintln(stderr, "error:", err)
|
|
fs.Usage()
|
|
return zero, 2
|
|
}
|
|
}
|
|
|
|
return *opts, ContinueExecution
|
|
}
|
|
|
|
func Fprintf(w io.Writer, format string, args ...any) {
|
|
_, _ = fmt.Fprintf(w, format, args...)
|
|
}
|
|
|
|
func Fprintln(w io.Writer, args ...any) {
|
|
_, _ = fmt.Fprintln(w, args...)
|
|
}
|
|
|
|
func hasHelpFlag(args []string) bool {
|
|
for _, arg := range args {
|
|
if arg == "-h" || arg == "-help" || arg == "--help" {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|