diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 1c84425..0fe3c59 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -23,7 +23,7 @@ jobs: - name: Lint uses: golangci/golangci-lint-action@v9 with: - version: v2.9 + version: v2.13 - name: Spelling uses: streetsidesoftware/cspell-action@v8 continue-on-error: true diff --git a/examples/http/main.go b/examples/http/main.go index 3ad4b77..1559465 100644 --- a/examples/http/main.go +++ b/examples/http/main.go @@ -12,8 +12,6 @@ import ( "syscall" "time" - "github.com/google/uuid" - "github.com/brandon1024/cmder" "github.com/brandon1024/cmder/getopt" ) @@ -122,7 +120,7 @@ func (c *ServerCommand) Initialize(ctx context.Context, args []string) error { if c.auth && c.basicAuth == "" { var ( user = "admin" - pass = uuid.New().String() + pass = "admin" ) slog.Info("no credentials configured: using generated basic auth credentials", "user", user, "pass", pass) @@ -144,6 +142,7 @@ func (c *ServerCommand) Run(ctx context.Context, args []string) error { slog.Info("starting web server", "addr", c.addr) + //nolint:gosec // gosec:disable G118 -- Parent context is cancelled when this shutdown routine executes. go func() { <-ctx.Done() diff --git a/getopt/alias.go b/getopt/alias.go index c74e7fe..87364c1 100644 --- a/getopt/alias.go +++ b/getopt/alias.go @@ -6,7 +6,10 @@ import ( ) // Alias is a simple utility for registering flag aliases. A new flag is registered in fs with name alias and the -// [flag.Value] of a flag named name. +// [flag.Value] of a flag named name. This is functionally equivalent to: +// +// flg := fs.Lookup(name) +// fs.Var(flg.Value, alias, flg.Usage) // // If flag name doesn't exist in fs, panic. func Alias(fs *flag.FlagSet, name, alias string) { diff --git a/getopt/countervar.go b/getopt/countervar.go index 234f07f..97ec7ef 100644 --- a/getopt/countervar.go +++ b/getopt/countervar.go @@ -21,7 +21,7 @@ type CounterVar[T CounterType] struct { value *T } -// Counter Initializes a [CounterVar] with an initial value. +// Counter initializes a [CounterVar] with an initial value. func Counter[T CounterType](value *T) *CounterVar[T] { return &CounterVar[T]{ value: value, diff --git a/getopt/example_alias_test.go b/getopt/example_alias_test.go new file mode 100644 index 0000000..73cf701 --- /dev/null +++ b/getopt/example_alias_test.go @@ -0,0 +1,42 @@ +package getopt_test + +import ( + "flag" + "fmt" + "os" + + "github.com/brandon1024/cmder/getopt" +) + +// This example demonstrates the usage of [getopt.Alias]. +func ExampleAlias() { + var ( + count uint + output string + ) + + fs := getopt.NewPosixFlagSet("alias", flag.ContinueOnError) + + fs.UintVar(&count, "count", 12, "`number` of results") + fs.StringVar(&output, "output", "-", "output `file`") + + getopt.Alias(fs.FlagSet, "count", "c") + getopt.Alias(fs.FlagSet, "output", "o") + + fs.SetOutput(os.Stdout) + fs.PrintDefaults() + + if err := fs.Parse([]string{"-c", "2025", "-o", "output.txt"}); err != nil { + panic(err) + } + + fmt.Printf("values: %d %s\n", count, output) + + // Output: + // -c , --count= (default 12) + // number of results + // + // -o , --output= (default -) + // output file + // values: 2025 output.txt +} diff --git a/getopt/example_negatedboolvar_test.go b/getopt/example_negatedboolvar_test.go index 4f7cc1d..8505a88 100644 --- a/getopt/example_negatedboolvar_test.go +++ b/getopt/example_negatedboolvar_test.go @@ -3,6 +3,7 @@ package getopt_test import ( "flag" "fmt" + "os" "github.com/brandon1024/cmder/getopt" ) @@ -14,7 +15,7 @@ func ExampleNegatedBoolVar() { verify bool ) - fs := flag.NewFlagSet("custom", flag.ContinueOnError) + fs := getopt.NewPosixFlagSet("custom", flag.ContinueOnError) // option 1: using NegatedBoolVar directly fs.BoolVar(&sign, "gpg-sign", false, "gpg sign the input") @@ -24,9 +25,12 @@ func ExampleNegatedBoolVar() { fs.BoolVar(&verify, "verify", false, "verify the result") fs.Var(getopt.NegatedBool(&verify), "no-verify", "skip result verification") + fs.SetOutput(os.Stdout) + fs.PrintDefaults() + args := []string{ - "-gpg-sign", "-no-gpg-sign", - "-no-verify=false", + "--gpg-sign", "--no-gpg-sign", + "--no-verify=false", } if err := fs.Parse(args); err != nil { @@ -36,6 +40,11 @@ func ExampleNegatedBoolVar() { fmt.Printf("sign: %v\n", sign) fmt.Printf("verify: %v\n", verify) // Output: + // --gpg-sign, --no-gpg-sign + // gpg sign the input + // + // --verify, --no-verify + // verify the result // sign: false // verify: true } diff --git a/getopt/flagset.go b/getopt/flagset.go index d261541..f2b6ab8 100644 --- a/getopt/flagset.go +++ b/getopt/flagset.go @@ -448,7 +448,7 @@ func (f *PosixFlagSet) group() map[string][]*flag.Flag { groups[flg.Name] = []*flag.Flag{flg} // traverse the flags again and find (and remove) any which match flg - for i := len(collected) - 1; i >= 0; i-- { + for i := range slices.Backward(collected) { other := collected[i] if areSame(flg.Value, other.Value) { diff --git a/getopt/bool.go b/getopt/negatedboolvar.go similarity index 100% rename from getopt/bool.go rename to getopt/negatedboolvar.go diff --git a/go.mod b/go.mod index aa4977c..e2ff530 100644 --- a/go.mod +++ b/go.mod @@ -1,33 +1,30 @@ module github.com/brandon1024/cmder -go 1.25.0 +go 1.26.0 -toolchain go1.26.5 +toolchain go1.27.0 tool ( golang.org/x/tools/cmd/goimports gotest.tools/gotestsum ) -require ( - github.com/google/go-cmp v0.7.0 - github.com/google/uuid v1.6.0 -) +require github.com/google/go-cmp v0.7.0 require ( - github.com/bitfield/gotestdox v0.2.2 // indirect + github.com/bitfield/gotestdox v0.2.3 // indirect github.com/dnephin/pflag v1.0.7 // indirect github.com/fatih/color v1.19.0 // indirect github.com/fsnotify/fsnotify v1.10.1 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/mattn/go-colorable v0.1.15 // indirect - github.com/mattn/go-isatty v0.0.22 // indirect - golang.org/x/mod v0.36.0 // indirect - golang.org/x/sync v0.20.0 // indirect - golang.org/x/sys v0.45.0 // indirect - golang.org/x/telemetry v0.0.0-20260527142108-59979362b252 // indirect - golang.org/x/term v0.43.0 // indirect - golang.org/x/text v0.37.0 // indirect - golang.org/x/tools v0.45.0 // indirect + github.com/mattn/go-isatty v0.0.24 // indirect + golang.org/x/mod v0.40.0 // indirect + golang.org/x/sync v0.22.0 // indirect + golang.org/x/sys v0.47.0 // indirect + golang.org/x/telemetry v0.0.0-20260824150023-1f5465a7b7fb // indirect + golang.org/x/term v0.45.0 // indirect + golang.org/x/text v0.41.0 // indirect + golang.org/x/tools v0.49.0 // indirect gotest.tools/gotestsum v1.13.0 // indirect ) diff --git a/go.sum b/go.sum index 1eca91b..0cbf2b3 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -github.com/bitfield/gotestdox v0.2.2 h1:x6RcPAbBbErKLnapz1QeAlf3ospg8efBsedU93CDsnE= -github.com/bitfield/gotestdox v0.2.2/go.mod h1:D+gwtS0urjBrzguAkTM2wodsTQYFHdpx8eqRJ3N+9pY= +github.com/bitfield/gotestdox v0.2.3 h1:H8Wy07kYacr3YSF5aJON/m9ASE+PGKOSufXkTjqQGb8= +github.com/bitfield/gotestdox v0.2.3/go.mod h1:bq/HemlNNqEvjOzy7brevVhzZD8WTGFDGq59DOIsHqI= github.com/dnephin/pflag v1.0.7 h1:oxONGlWxhmUct0YzKTgrpQv9AUA1wtPBn7zuSjJqptk= github.com/dnephin/pflag v1.0.7/go.mod h1:uxE91IoWURlOiTUIA8Mq5ZZkAv3dPUfZNaT80Zm7OQE= github.com/fatih/color v1.19.0 h1:Zp3PiM21/9Ld6FzSKyL5c/BULoe/ONr9KlbYVOfG8+w= @@ -10,28 +10,26 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/mattn/go-colorable v0.1.15 h1:+u9SLTRGnXv73cEsnsmoZBom+dMU88B2M0aDcWy0/jY= github.com/mattn/go-colorable v0.1.15/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= -github.com/mattn/go-isatty v0.0.22 h1:j8l17JJ9i6VGPUFUYoTUKPSgKe/83EYU2zBC7YNKMw4= -github.com/mattn/go-isatty v0.0.22/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4= +github.com/mattn/go-isatty v0.0.24 h1:tGZZoVgT/KiqK1c8ocVLeDS8BSWMRd47J3Lbz7vsReI= +github.com/mattn/go-isatty v0.0.24/go.mod h1:nMCL3Zebbrt45jsMDgnfIwz6ydEQApk5oEI3HqDio6A= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= -golang.org/x/mod v0.36.0 h1:JJjpVx6myfUsUdAzZuOSTTmRE0PfZeNWzzvKrP7amb4= -golang.org/x/mod v0.36.0/go.mod h1:moc6ELqsWcOw5Ef3xVprK5ul/MvtVvkIXLziUOICjUQ= -golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= -golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= -golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY= -golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= -golang.org/x/telemetry v0.0.0-20260527142108-59979362b252 h1:uqWbB1NVuonFfz1UgfdXW1kk6p+3XTFDVGBHOQkfwjg= -golang.org/x/telemetry v0.0.0-20260527142108-59979362b252/go.mod h1:Eqhaxk/wZsWEH8CRxLwj6xzEJbz7k1EFGqx7nyCoabE= -golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4= -golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk= -golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= -golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= -golang.org/x/tools v0.45.0 h1:18qN3FAooORvApf5XjCXgsuayZOEtXf6JK18I3+ONa8= -golang.org/x/tools v0.45.0/go.mod h1:LuUGqqaXcXMEFEruIVJVm5mgDD8vww/z/SR1gQ4uE/0= +golang.org/x/mod v0.40.0 h1:hUv+3cXcdRHz08UmSiOob7sadHig73uo5bkXxQ/tvUs= +golang.org/x/mod v0.40.0/go.mod h1:0/weTWkPWGBikyTWAX3dkjVztMmBA5hM0DH6BElSupE= +golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek= +golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs= +golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/telemetry v0.0.0-20260824150023-1f5465a7b7fb h1:u2wx6smkicd2/as9DfdcyWweWaV7tGvybRQdvPQ74Bw= +golang.org/x/telemetry v0.0.0-20260824150023-1f5465a7b7fb/go.mod h1:/KSYFnLndIrA1A+Rs5r6vSifQhuFz75BPNN3J/hvzN0= +golang.org/x/term v0.45.0 h1:NwWyBmoJCbfTHpxrWoZ9C6/VxOf7ic219I8xZZFdrf0= +golang.org/x/term v0.45.0/go.mod h1:9aqxs0blBcrm/n0L9QW0aRVD+ktan8ssZromtqJC43w= +golang.org/x/text v0.41.0 h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8= +golang.org/x/text v0.41.0/go.mod h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M= +golang.org/x/tools v0.49.0 h1:3NI7VXzL9+1WZD52Dx2ttoPwD5DWrFGpl9mFZDlmisI= +golang.org/x/tools v0.49.0/go.mod h1:SJNXV9DBKT0UbdttsQjbfJlAE/q+y36++zo3uL3N0Oo= gotest.tools/gotestsum v1.13.0 h1:+Lh454O9mu9AMG1APV4o0y7oDYKyik/3kBOiCqiEpRo= gotest.tools/gotestsum v1.13.0/go.mod h1:7f0NS5hFb0dWr4NtcsAsF0y1kzjEFfAil0HiBQJE03Q= gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=