113 Commits

Author SHA1 Message Date
Alec Thomas 9bc3bf9925 chore: optionally allow parsing of hyphen-prefixied flag parameters
This allows for eg. `foo --number -10`, `foo --flag -bar`.

Fixes #478, #315.
2025-05-15 19:31:29 +10:00
Bob Lail 5b36573738 feat: Allow kong.Path to describe remaining unparsed args (#472)
As Kong traces a sequence of command line arguments, it parses them and appends them to the parsed `Path` sequence. For each element in `Path`, these is a corresponding sequence of unparsed arguments. This change enables `Path` to yield these.

I have a package that uses Kong's hooks to instrument Kong applications (to monitor usage, reliability, etc of internal tools). I would like to instrument the commandline arguments as well.

This change would enable it to work roughly as follows:
```golang
func (Foo) BeforeApply(app *kong.Kong, ctx *kong.Context, t *Tracker) error {
	command := []string{ctx.Model.Name}
	var args  []string

	for _, path := range ctx.Path {
		if path.Command != nil {
			command = append(command, path.Command.Name)
			args = path.Remainder()
		}
	}

	app.Exit = t.exit(app.Exit)

	t.WithCommand(strings.Join(command, " ")).WithArgs(args)
	return nil
}
```
2025-03-08 09:28:09 +11:00
Alec Thomas 0c495e4936 feat: add IgnoreDefault optional interface 2025-02-26 14:37:56 +11:00
Abhinav Gupta 3b9af5bdce feat: Support singleton providers (#501)
* feat: Support singleton providers

This change adds support for provider functions that are
not reinvoked even if requested by multiple other providers.
Instead, their value is cached and reused between invocations.

To make this possible, we change how bindings are stored:
instead of just a function reference, we now store a binding object
which records whether the binding is a singleton,
and records the resolved singleton value (if any).

Resolves #500

* refac(bindings): hide singleton status

Don't require callAnyFunction to be aware of
whether a binding is a singleton or not.
2025-02-17 17:44:03 +11:00
Alec Thomas 4e1757c0e8 feat: allow use of providers that don't return errors 2025-01-30 13:41:09 +11:00
Abhinav Gupta 7ca846736c fix(Context.Run): Don't panic on unselected root node (#484) 2025-01-04 11:13:14 +09:00
Alec Thomas a32b94b705 chore: interface{} -> any 2024-12-29 08:10:34 +09:00
Alec Thomas a14bb2072c fix: don't call Apply() twice
For some reason this was called by `Run()`. All tests pass without it,
so I'm not sure why it was there.

Fixes #481
2024-12-29 07:43:05 +09:00
Alec Thomas 388ba35f1a feat: add support for Provide*() (<type>, error) methods on commands 2024-12-07 17:09:03 +11:00
Alec Thomas 96647c30af feat: add old "passthrough" behaviour back in as an option
`passthrough:""` or `passthrough:"all"` (the default) will pass through
all further arguments including unrecognised flags.

`passthrough:"partial"` will validate flags up until the `--` or the
first positional argument, then pass through all subsequent flags and
arguments.
2024-12-01 20:02:03 +11:00
Alec Thomas 88e13d750a chore: fix all golangci-lint warnings 2024-12-01 11:12:48 +11:00
Alec Thomas 2544d3f008 feat: add AfterRun() hook
Fixes #288
2024-11-03 14:49:27 +11:00
Alec Thomas 1b9d57eec1 feat: support optionally passing kong.Context to Validate()
Fixes #340
2024-11-03 14:14:55 +11:00
Alec Thomas 64229c9fe7 fix: format enum value
Fixed in #415
2024-11-03 14:02:03 +11:00
Bob Lail 9924ec4461 fix!: Include -- in passthrough args (#436)
Given a grammar like this:

```golang
var cli struct {
        Args []string `arg:"" optional:"" passthrough:""`
}
```

If Kong parses `cli foo -- bar`, it will populate `Args` with `[]string{"foo", "--", "bar"}` (including "`--`").
However, if Kong parses `cli -- foo bar`, will populate `Args` with `[]string{"foo", "bar"}` (leaving off `"--"`).

This differs from the behavior of a passthrough Command, where `"--"` is included with the args in both cases.

There are 3 places where `c.endParsing()` is called
1. When `node.Passthrough` is true: https://github.com/alecthomas/kong/blob/5f9c5cc822bdb888a3671c44d4688a6f602ecb90/context.go#L366-L368
2. When `arg.Passthrough` is true: https://github.com/alecthomas/kong/blob/5f9c5cc822bdb888a3671c44d4688a6f602ecb90/context.go#L451-L453
3. When `"--"` is encountered: https://github.com/alecthomas/kong/blob/5f9c5cc822bdb888a3671c44d4688a6f602ecb90/context.go#L384-L387

The first two do not also pop any tokens. The third one does.

This commit makes `c.scan.Pop()` conditional, skipping it when the next positional argument is passthrough.

I believe this will cause Kong to behave a little more consistently — and from my perspective, `--` is relevant for args intended to be passed through! — but it will change the behavior of existing projects that use `arg:"" passthrough:""`.
2024-09-11 10:51:37 +10:00
Cam Hutchison 4ecb53599b Make negatable flag name customisable (#439)
* fix: Check if negatable duplicates another flag

Add a check for flags with the `negatable` option if the negative flag
conflicts with another tag, such as:

    Flag   bool `negatable:""`
    NoFlag bool

The flag `--no-flag` is ambiguous in this scenario.

* feat: Make negatable flag name customisable

Allow a value on the `negatable` tag to specify a flag name to use for
negation instead of using `--no-<flag-name>` as the flag.

e.g.

    Approve bool `default:"true",negatable:"deny"`

This example will allow `--deny` to set the `Approve` field to false.
2024-09-10 21:02:37 +10:00
Alec Thomas 2ad9498bdf chore: bump go + golangci-lint 2024-08-20 08:16:24 +10:00
Camilla ff6d5ba7d5 Feature: Add xand tag (#442)
* Feat: Add xand group and check for missing

* Fix: Split and combine err in TestMultiand for consistency

* Feat: Check missing required flags in xand groups

* Feat: Handle combined xor and xand

* Docs: Add info about combined xand and required use

* Docs: Fix language error in xand description

Co-authored-by: Stautis <thkrst@gmail.com>

* Feat: Rename xand to and

* Refactor: Switch from fmt.Sprintf to err.Error

* Refactor: Get requiredAndGroup map in separate function

---------

Co-authored-by: Stautis <thkrst@gmail.com>
2024-08-08 16:58:22 +10:00
Leo Antunes e864bb0220 feat: allow non-structs to be used as commands (#428)
* feat: allow non-structs to be used as commands

This small MR allows using the func-to-interface trick to implement a command (see commandFunc in kong_test.go).

This is useful e.g. for commands that have no flags or arguments of their own, but instead receive all required information via bound  parameters.

* fix: check DynamicCommand is runnable when adding
2024-07-05 22:51:38 +10:00
Bob Lail fcb5e05c07 fix: When a Grammar combines flags with passthrough args, see if an unrecognized flag may be treated as a positional argument (#435)
* ci: Add a test for positional args that are passthrough on a command that isn't passthrough

* fix: When a Grammar combines flags with passthrough args, see if an unrecognized flag may be treated as a positional argument

Given a grammar like this:
```golang
var cli struct {
	Args []string `arg:"" optional:"" passthrough:""`
}
```

The first positional argument implies that it was preceded by `--`, so subsequent flags are not parsed.

If Kong parses `cli 1 --unknown 3`, it will populate `Args` with `[]string{"1", "--unknown", "3"}`.
However, if Kong parses `cli --unknown 2 3`, it will fail saying that `--unknown` is an unrecognized flag.

This commit changes the parser so that if an unknown flag _could_ be treated as the first passthrough argument, it is.

After this change, if Kong parses `cli --unknown 2 3`, it will populate `Args` with `[]string{"--unknown", "2", "3"}`.

* ci: Skip the `maintidx` linter for `trace()`
2024-07-05 22:48:33 +10:00
Prashant Varanasi fa9b636997 Support aliases for flags (#409)
Aliases are currently only supported for sub-commands, but they're
useful for flags as well. E.g., when migrating from an old flag name
to a new flag name, while still supporting the old value.
2024-02-27 11:10:15 +11:00
Abhinav Gupta a86bda490b golangci-lint: Upgrade, fix issues (#397)
The golangci-lint being used was quite dated.
This change upgrades to the latest version.
Adds and updates exclusions based on new failures.

Note on revive:
I've included an opt-out for unused parameters for revive
because turning `newThing(required bool)` to `newThing(_ bool)`
is a loss of useful information.

The changes to the Go files are to fix the following issues:

```
camelcase.go:16: File is not `gofmt`-ed with `-s` (gofmt)
config_test.go:50:18: directive `//nolint: gosec` is unused for linter "gosec" (nolintlint)
defaults_test.go:28:25: G601: Implicit memory aliasing in for loop. (gosec)
doc.go:5: File is not `gofmt`-ed with `-s` (gofmt)
kong.go:446:18: directive `//nolint: gosec` is unused for linter "gosec" (nolintlint)
kong_test.go:503:20: G601: Implicit memory aliasing in for loop. (gosec)
model.go:493:10: composites: reflect.ValueError struct literal uses unkeyed fields (govet)
scanner.go:112: File is not `gofmt`-ed with `-s` (gofmt)
```

And to address broken nolint directives reported as follows by
golangci-lint.

```
[.. skipped .. ]
tag.go:65:1: directive `// nolint:gocyclo` should be written without leading space as `//nolint:gocyclo` (nolintlint)
tag.go:206:51: directive `// nolint: gocyclo` should be written without leading space as `//nolint: gocyclo` (nolintlint)
util_test.go:23:43: directive `// nolint: errcheck` should be written without leading space as `//nolint: errcheck` (nolintlint)
util_test.go:51:22: directive `// nolint: errcheck` should be written without leading space as `//nolint: errcheck` (nolintlint)
```
2023-12-11 09:37:07 +11:00
Alec Thomas 815ba68265 Revert "fix: set trailing positional arguments to active"
This reverts commit 575d5b1d34.
2023-12-10 08:21:36 +11:00
Alec Thomas 575d5b1d34 fix: set trailing positional arguments to active
This fixes an issue where existingfile et al would not correctly apply
to positional arguments with defaults.
2023-11-17 16:56:45 +11:00
Jan Heuermann 93d31e17f4 Drop automatic message prefix from command errors (#384) 2023-10-07 18:15:33 +11:00
Mitar 074ccd0906 fix: remove showing app name twice in errors (#368) 2023-07-21 22:08:56 +10:00
Denis Titusov 9610ed62d9 feat: support multiple env variables (#349) 2023-02-01 06:39:30 +11:00
Alec Thomas bf0cbf5d7c feat: Embed() option and Context.Call()
The former allows arbitrary structs to be embedded in the root of the
CLI, with optional tags.

The latter allows an arbitrary function to be called using Kong's
binding functionality.
2022-11-22 23:34:56 +11:00
Jacob Hochstetler 0c6a9f3a3d Merging issue 280 with master changes (#296) 2022-09-20 05:55:05 -07:00
pyqlsa a05a0c20ba Add Active member to Nodes and Values (#319) 2022-07-19 22:43:15 -07:00
Denis Titusov 89b2806f6a Switch to the standard errors API, that was introduced in 1.13 (#273)
* Switch to the standard errors API, that was introduced in 1.13

* Fix linter errors 🤦‍

* Remove withStackError

* fix: freeze go version to 1.17, since 1.18 introduced generics, which are not supported by linters yet

* fix: freeze go version to 1.17, since 1.18 introduced generics, which are not supported by linters yet
2022-03-18 18:54:29 +11:00
Ali Eren Öztürk cc81f03a38 Support listing enums in specified order (#274) 2022-02-21 21:36:14 +11:00
pyq-lsa ab085f771e fix required/xor behavior w/ > 2 flags 2022-01-30 09:13:18 +11:00
Denis Titusov e49700181c fix: Change the application flags order avoiding panics
This commit solves issue alecthomas/kong#264
2022-01-27 22:52:55 +11:00
Mitar a7d3850e80 Cmd can be passthrough now, too.
Fixes #253.
2022-01-05 18:58:37 +11:00
Alec Thomas 7533b11d06 Differentiate between omitted and empty default.
Fixes #250.
2021-12-13 19:03:23 +11:00
Grant Monroe 749d3f0752 Allow root application to have a Run(...) error method.
Issue #209
2021-10-15 15:47:17 +11:00
Stan Rozenraukh 74cb5130e3 Adds Context.BindToProvider (#201) 2021-08-31 06:47:02 +10:00
Simon Frei 5a9c9c7864 Bubble errors instead of panicking (#194) 2021-08-19 18:00:53 +10:00
Cam Hutchison 89315e74ad Allow default commands with cmds/args/flags (#188)
* Move default command validation to build

Move the validation of default commands - checking if a node has
multiple default commands or a default command has children - to the
build phase rather than tracing. These errors are with the structure of
the CLI ast and are detectable before parsing the command line.

Add a couple of tests for some of the default command error cases.

* Disallow positional args on a default command

Do not allow a default command to have positional arguments. The current
check is only for branching args, but the error message implies that
positional args are not allowed either. So add a check for positional
args too, and add a test case for it.

This is breaking change to the API but is unlikely to have ill-effect as
positional args on a default command cannot be used without explicitly
naming the command (i.e. not using it as a default).

* Allow default commands with cmds/args/flags

Allow default commands to have sub-commands, args and flags when tagged
with `default:"withargs"`. This makes specifying the name of the
command on the CLI completely optional as long as the args to that
command are not ambiguous with other commands.
2021-07-12 14:19:37 +10:00
Alec Thomas cfbe844aa4 Fix xor + required combo.
See #112.
2021-07-11 21:23:18 +10:00
Alec Thomas c494f8b8f3 Support required combined with xor groups.
Fixes #112.
2021-06-21 19:25:54 +09:30
Alec Thomas 54558f65e8 Allow multiple xor:"" groups to be defined.
Fixes #113.
2021-06-21 19:04:54 +09:30
Alec Thomas 8aa52739ea Don't fail on required positional arguments that have envars.
Fixes #153.
Fixes #120.
2021-06-21 17:13:39 +09:30
Alec Thomas 6cebaa7b85 Hermitise and bump golangci-lint. 2021-06-09 12:48:47 +10:00
Mary Fesenko 1f5bbd5559 Fix issue with negatable flag being negated twice (#171) 2021-05-22 21:50:50 +10:00
Franklin "Snaipe" Mathieu d4dd709445 tag: add passthrough for positional arguments
This new tag tells the parser to stop processing flags after the
positional argument is encountered.

This is particularly useful for subcommands that forward their arguments
to an external program, and makes it possible to implement commands
like `kubectl exec` or `docker run`.

Fixes #80.
2021-04-06 07:53:16 +10:00
Joe Schmitt ed24960916 Implement code review feedback 2021-03-02 10:36:13 +11:00
Joe Schmitt 454f2c067e Add test case for inverting the negation
Not sure why anyone would do this, but it's covered now.
2021-03-02 10:36:13 +11:00
Joe Schmitt 2fdddc4f51 Add negatable tag to set a bool to be negatable.
If negatable, add `--[no-]` prefix to help.
2021-03-02 10:36:13 +11:00