Flag: Negatable
Negatable Flag with `--no-` prefix
Negatable Flag
Normal Style
b.Flg("warning", "w").
Description("negatable flag: <code>--no-warning</code> is available", "").
Group("Negatable").
Negatable(true).
Default(false).
Build()A negatable flag like --warning has a companion buddy --no-warning.
The two flags are just the opposite.
While end user typed --no-warning, the app.cmd.no-warning key in the Store will be set to true, on the contrary, app.cmd.warning key will be set to false.
Internally, these two flags are in a same Toggleable Group.
A negatable Flag always holds a boolean Default value, in generally,
-W Style
This new feature starts since cmdr v2.1.16.
parent.Flg("warnings", "W").
Description("gcc-style negatable flag: <code>-Wunused-variable</code> and -Wno-unused-variable", "").
Group("Negatable").
Negatable(true, "unused-variable", "unused-parameter", "unused-function", "unused-but-set-variable", "unused-private-field", "unused-label").
Default(false).
Build()A -W-style negatable flag allows you provide a set of child items.
cmdr will create a pair of toggable group flags for these child items. For example, the above sample code will make these child flags: --warnings.unused-variable/-Wunused-variable and --warnings.no-unused-variable/-Wno-unused-variable, and so on.
This -W-style negatable flag is covered from gcc -Waddress -Wno-address of GNU GCC command line options.
$ go run ./examples/negatable --warnings.unused-function
...
--warnings, -W:
> TG: "false"
> TG.selected: ["warnings.no-unused-function"]
unused-variable: false, (no-): true
unused-parameter: false, (no-): true
unused-function: true, (no-): false
unused-but-set-variable: false, (no-): true
unused-private-field: false, (no-): true
unused-label: false, (no-): true
...
$ go run ./examples/negatable --warnings.no-unused-function
...
--warnings, -W:
> TG: "false"
> TG.selected: ["warnings.no-unused-function"]
unused-variable: false, (no-): true
unused-parameter: false, (no-): true
unused-function: false, (no-): true
unused-but-set-variable: false, (no-): true
unused-private-field: false, (no-): true
unused-label: false, (no-): true
...End-user can pass command-line arguments with -Wunused-variable to enable warnings.unused-variable option (above), or disable it with -Wno-unused-variable. Another way is using short flag -Wunused-variable and -Wno-unused-variable.
In the latest version of cmdr.v2, we also improved the help screen of a negatable flag, just like the following sample:
$ go run ./examples/negatable --help -w
00:04:15.042866Z| c/[cmdr][1] [WRN] FlagBy() return nil querying title="warnings" ./cli/worker/pre.go:301 worker.(*workerS).commandsToStoreR.func3.1
negatable v2.1.63 ~ Copyright © 2025 by negatable Authors ~ All Rights Reserved.
Usage:
$ negatable [Options...][files...]
Description:
a sample to demo negatable flag.
Examples:
Try to use negatable flag,
$ negatable --no-warning
cmd.Store().MustBool("no-warning") will be 'true'.
$ negatable --warning
cmd.Store().MustBool("warning") will be 'true'.
$ negatable -Wunused-variable -Wno-unused-parameter
1. cmd.Store().MustBool("warnings.unused-variable") will be 'true',
2. cmd.Store().MustBool("warnings.no-unused-parameter") will be 'true'.
cmd.Store().MustBool("warnings.unused-parameter") will be 'false'.
$ negatable -Wno-unused-function -Wunused-but-set-variable
1. cmd.Store().MustBool("warnings.unused-function") will be 'false',
cmd.Store().MustBool("warnings.no-unused-function") will be 'true',
2. cmd.Store().MustBool("warnings.unused-but-set-variable") will be 'true'.
$ negatable +warning
cmd.Store().MustBool("warning") will be 'true'.
Global Flags:
[Negatable]
-w, --warning [x] negatable flag: --no-warning is available (Default: true)(negatable)
-W, --warnings [ ] gcc-style negatable flag: -Wunused-variable and -Wno-unused-variable (Default: false)(negatable)
- unused-variable, no-unused-variable
- unused-parameter, no-unused-parameter
- unused-function, no-unused-function
- unused-but-set-variable, no-unused-but-set-variable
- unused-private-field, no-unused-private-field
- unused-label, no-unused-label
[Misc]
-h, --help,--info,--usage Show this help screen (-?) [Env: HELP] (Default: true)
Type '-h'/'-?' or '--help' to get this help screen (254x25/46).
More: '-D'/'--debug', '-V'/'--version', '-#'/'--build-info', '--no-color'...You've seen -W flag has the extra lines to list all of its sub-items.
Tip
Tip
When displaying a help screen (--help), specifying some flags and you've get their updated default-values to show there.
For example like above, we specified -w in the command-line, so its default-value has been updated to true in the help screen.
BTW, since a negatable flag would be implemented as a togglable flag internally, its right-part description will be leading with [x] or [ ], which the first form means a true-state choiced, and the last form means a false-state kept.
Define
To define negatable flag by .Negatable(true).Default(false) call.
And by .Negatable(true, "a","b","c").Default(false) call, a -W-style flag(-set) can be defined.
package main
import (
"context"
"os"
"github.com/hedzr/cmdr/v2"
"github.com/hedzr/cmdr/v2/cli"
"github.com/hedzr/cmdr/v2/examples/common"
"github.com/hedzr/cmdr/v2/examples/devmode"
// logz "github.com/hedzr/logg/slog"
)
const (
appName = "negatable"
desc = `a sample to demo negatable flag.`
version = cmdr.Version
author = ``
)
func main() {
app := cmdr.Create(appName, version, author, desc).
With(func(app cli.App) { logz.Debug("in dev mode?", "mode", devmode.InDevelopmentMode()) }).
WithBuilders(common.AddNegatableFlag).
WithAdders().
// override the onAction defined in common.AddNegatableFlag()
OnAction(func(ctx context.Context, cmd cli.Cmd, args []string) (err error) {
// logz.PrintlnContext(ctx, cmd.Set().Dump())
// v := cmd.Store().MustBool("warning")
// w := cmd.Store().MustBool("no-warning")
// println("warning flag: ", v)
// println("no-warning flag: ", w)
// wf := cmd.FlagBy("warning")
// if wf != nil && wf.LeadingPlusSign() {
// println("warning flag with leading plus sign: +w FOUND.")
// }
// return
println("Dumping Store ----------\n", cmdr.Set().Dump())
cmd.App().DoBuiltinAction(ctx, cli.ActionDefault)
cs := cmd.Store()
v := cs.MustBool("warning")
w := cs.MustBool("no-warning")
println("warning toggle group: ", cs.MustString("warning"))
println(" warning flag: ", v)
println(" no-warning flag: ", w)
wf := cmd.FlagBy("warning")
if wf != nil && wf.LeadingPlusSign() {
println()
println("NOTABLE: a flag with leading plus sign: +w FOUND.")
} else {
logz.WarnContext(ctx, "cannot found flag 'warning'")
}
sw1 := cs.MustBool("warnings.unused-variable")
sw2 := cs.MustBool("warnings.unused-parameter")
sw3 := cs.MustBool("warnings.unused-function")
sw4 := cs.MustBool("warnings.unused-but-set-variable")
sw5 := cs.MustBool("warnings.unused-private-field")
sw6 := cs.MustBool("warnings.unused-label")
fmt.Printf(`
--warnings, -W:
> TG: %q
> TG.selected: %q
unused-variable: %v, (no-): %v
unused-parameter: %v, (no-): %v
unused-function: %v, (no-): %v
unused-but-set-variable: %v, (no-): %v
unused-private-field: %v, (no-): %v
unused-label: %v, (no-): %v
selected items: %v
`,
cs.MustString("warnings"),
cs.MustStringSlice("warnings.selected"),
sw1, cs.MustBool("warnings.no-unused-variable"),
sw2, cs.MustBool("warnings.no-unused-parameter"),
sw3, cs.MustBool("warnings.no-unused-function"),
sw4, cs.MustBool("warnings.no-unused-but-set-variable"),
sw5, cs.MustBool("warnings.no-unused-private-field"),
sw6, cs.MustBool("warnings.no-unused-label"),
cs.MustStringSlice("warnings.selected"),
)
return
}).
Build()
ctx := context.Background()
if err := app.Run(ctx); err != nil {
logz.ErrorContext(ctx, "Application Error:", "err", err) // stacktrace if in debug mode/build
os.Exit(app.SuggestRetCode())
} else if rc := app.SuggestRetCode(); rc != 0 {
os.Exit(rc)
}
}package examples
import (
"context"
"github.com/hedzr/cmdr/v2/cli"
)
func AddNegatableFlag(parent cli.CommandBuilder) { AddNegatableFlagImpl(parent) }
func AddNegatableFlagWithoutCmd(parent cli.CommandBuilder) { AddNegatableFlagImpl(parent, true) }
func AddNegatableFlagImpl(parent cli.CommandBuilder, dontHandlingParentCmd ...bool) { //nolint:revive
parent.Flg("warning", "w").
Description("negatable flag: <code>--no-warning</code> is available", "").
Group("Negatable").
LeadingPlusSign(true).
Negatable(true).
Default(false).
Build()
parent.Flg("warnings", "W").
Description("gcc-style negatable flag: <code>-Wunused-variable</code> and -Wno-unused-variable", "").
Group("Negatable").
Negatable(true, "unused-variable", "unused-parameter", "unused-function", "unused-but-set-variable", "unused-private-field", "unused-label").
Default(false).
Build()
var noHpc bool
for _, p := range dontHandlingParentCmd {
if p {
noHpc = true
}
}
if !noHpc {
// give root command an action to handle it
action := func(ctx context.Context, cmd cli.Cmd, args []string) (err error) {
println("Dumping Store\n", cmd.App().Store().Dump())
cs := cmd.Store()
v := cs.MustBool("warning")
w := cs.MustBool("no-warning")
println("warning flag: ", v)
println("no-warning flag: ", w)
wf := cmd.FlagBy("warning")
if wf != nil && wf.LeadingPlusSign() {
println("warning flag with leading plus sign: +w FOUND.")
}
sw1 := cs.MustBool("warnings.unused-variable")
sw2 := cs.MustBool("warnings.unused-parameter")
sw3 := cs.MustBool("warnings.unused-function")
sw4 := cs.MustBool("warnings.unused-but-set-variable")
sw5 := cs.MustBool("warnings.unused-private-field")
sw6 := cs.MustBool("warnings.unused-label")
fmt.Printf(`
--warnings, -W:
unused-variable: %v, (no-): %v
unused-parameter: %v, (no-): %v
unused-function: %v, (no-): %v
unused-but-set-variable: %v, (no-): %v
unused-private-field: %v, (no-): %v
unused-label: %v, (no-): %v
selected items: %v
`,
sw1, cs.MustBool("warnings.no-unused-variable"),
sw2, cs.MustBool("warnings.no-unused-parameter"),
sw3, cs.MustBool("warnings.no-unused-function"),
sw4, cs.MustBool("warnings.no-unused-but-set-variable"),
sw5, cs.MustBool("warnings.no-unused-private-field"),
sw6, cs.MustBool("warnings.no-unused-label"),
cs.MustStringSlice("warnings.selected"),
)
return
}
parent.OnAction(action)
}
parent.Examples(`Try to use negatable flag,
$ $APP --no-warning
<code>cmd.Store().MustBool("no-warning")</code> will be 'true'.
$ $APP --warning
<code>cmd.Store().MustBool("warning")</code> will be 'true'.
`)
}Run
The example app has these following outputs:
$ go run ./examples/negatable --no-warning
warning toggle group: no-warning
warning flag: false
no-warning flag: true
...
$ go run ./examples/negatable --warning
warning toggle group: true
warning flag: true
no-warning flag: false
...
$
$ go run ./examples/negatable +w -Wunused-variable -Wunused-function -h
negatable v2.1.16 ~ Copyright © 2025 by negatable Authors ~ All Rights Reserved.
Usage:
$ negatable [Options...][files...]
Description:
a sample to demo negatable flag.
Examples:
Try to use negatable flag,
$ negatable --no-warning
cmd.Store().MustBool("no-warning") will be 'true'.
$ negatable --warning
cmd.Store().MustBool("warning") will be 'true'.
Global Flags:
[Negatable]
-w, --warning [x] negatable flag: --no-warning is available (Default: true)
-W, --warnings [ ] gcc-style negatable flag: -Wunused-variable and -Wno-unused-variable (Default: false)
[Misc]
-h, --help,--info,--usage Show this help screen (-?) [Env: HELP] (Default: false)
Type '-h'/'-?' or '--help' to get command help screen.
More: '-D'/'--debug', '-V'/'--version', '-#'/'--build-info', '--no-color'...
$
$ go run ./examples/negatable +w -Wunused-variable -Wunused-function
...
--warnings, -W:
> TG: "false"
> TG.selected: ["warnings.unused-variable" "warnings.unused-function"]
unused-variable: true, (no-): false
unused-parameter: false, (no-): true
unused-function: true, (no-): false
unused-but-set-variable: false, (no-): true
unused-private-field: false, (no-): true
unused-label: false, (no-): true
$
$ go run ./examples/negatable +w -Wunused-variable -Wno-unused-function --warnings.unused-label
...
--warnings, -W:
> TG: "false"
> TG.selected: ["warnings.unused-variable" "warnings.no-unused-function" "warnings.unused-label"]
unused-variable: true, (no-): false
unused-parameter: false, (no-): true
unused-function: false, (no-): true
unused-but-set-variable: false, (no-): true
unused-private-field: false, (no-): true
unused-label: true, (no-): false
$额外的话题
What is Next?
How is this guide?
Last updated on