-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathflags.go
More file actions
105 lines (90 loc) · 2.96 KB
/
Copy pathflags.go
File metadata and controls
105 lines (90 loc) · 2.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// Copyright (c) 2026 Paweł Zaremba
// SPDX-License-Identifier: MIT
package x
import (
"encoding"
"flag"
"fmt"
"strings"
"time"
)
// FlagsArgs parses command-line arguments and returns the remaining non-flag arguments after parsing.
// It creates a new FlagSet with the provided options, parses the args, and returns unparsed arguments and any error.
func FlagsArgs(args []string, extras ...FlagOption) ([]string, error) {
extras = append(extras, FlagSetErrorHandling(flag.ContinueOnError))
fs := flagSet(extras...)
return fs.Args(), fs.Parse(args)
}
// FlagsParse parses command-line arguments into a flag.FlagSet,
// applying customizations via provided FlagOption functions.
func FlagsParse(args []string, extras ...FlagOption) error {
extras = append(extras, FlagSetErrorHandling(flag.ContinueOnError))
return flagSet(extras...).Parse(args)
}
// flagSet creates a new flag.FlagSet.
func flagSet(extras ...FlagOption) *flag.FlagSet {
flags := flag.NewFlagSet("", flag.PanicOnError)
for _, e := range extras {
e(flags)
}
return flags
}
// FlagOption is a function type used to customize a flag.FlagSet during its initialization.
type FlagOption func(*flag.FlagSet)
// FlagSetName changes the name in the flag.FlagSet.
func FlagSetName(name string) FlagOption {
return func(flags *flag.FlagSet) {
flags.Init(name, flags.ErrorHandling())
}
}
// FlagSetErrorHandling changes the name in the flag.FlagSet.
func FlagSetErrorHandling(errorHandling flag.ErrorHandling) FlagOption {
return func(flags *flag.FlagSet) {
flags.Init(flags.Name(), errorHandling)
}
}
// flaggables is a type constraint that holds all types supported by [Flag].
type flaggables interface {
bool | int | int64 | uint | uint64 | string | float64 | []string | time.Duration
}
func Flag[T flaggables](p *T, name, usage string) FlagOption {
return func(flags *flag.FlagSet) {
switch v := any(p).(type) {
case *bool:
flags.BoolVar(v, name, *v, usage)
case *int:
flags.IntVar(v, name, *v, usage)
case *int64:
flags.Int64Var(v, name, *v, usage)
case *uint:
flags.UintVar(v, name, *v, usage)
case *uint64:
flags.Uint64Var(v, name, *v, usage)
case *string:
flags.StringVar(v, name, *v, usage)
case *float64:
flags.Float64Var(v, name, *v, usage)
case *[]string:
flags.Var((*stringSlice)(v), name, usage)
case *time.Duration:
flags.DurationVar(v, name, *v, usage)
default:
panic(fmt.Sprintf("unsupported type: %T", v))
}
}
}
var _ flag.Value = (*stringSlice)(nil)
type stringSlice []string
func (f *stringSlice) String() string {
return fmt.Sprint([]string(*f))
}
func (f *stringSlice) Set(value string) error {
*f = append(*f, strings.Split(value, ",")...)
return nil
}
// FlagText defines a flag with a custom TextMarshaler and TextUnmarshaler to parse and format its value.
func FlagText(p encoding.TextUnmarshaler, name string, value encoding.TextMarshaler, usage string) FlagOption {
return func(flags *flag.FlagSet) {
flags.TextVar(p, name, value, usage)
}
}