swift-argument-parser
swift-argument-parser copied to clipboard
Support option in children and parent with the same name
My use case is an example from git.
Potentially linked discussion: https://forums.swift.org/t/supporting-subcommands-with-same-option-name-as-reused-parent-command
Let’s consider git commit specifically which has the -C option to specify a commit from which to reuse the log message and other.
git by itself also has a -C option, to change the repository path.
Thus, we can legally call git with:
git -C my_path commit -C my_commit
If I’m not mistaken, this setup is currently impossible to describe using ArgumentParser.
Ideally, I think this:
struct GlobalOptions : ParsableArguments {
@Option(name: .customShort("C"))
var path: String
}
struct Git : ParsableCommand {
static var configuration = CommandConfiguration(
abstract: "…",
subcommands: [
GitCommit.self
]
)
@OptionGroup()
var globalOptions: GlobalOptions
}
struct GitCommit : ParsableCommand {
static var configuration = CommandConfiguration(abstract: "…")
@OptionGroup()
var globalOptions: GlobalOptions
@Option(name: .customShort("C"))
var commitFrom: String
func run() throws {
print(globalOptions.path)
print(commitFrom)
}
}
When called like this:
git -C path commit -C commit
Should print:
path
commit
Currently it says there is a missing -C argument.
@natecook1000
Would you happen to have an update on this issue 👀 Ran into this today but when trying to create a command like swift run which allows forwarding arguments to an executable.
For example: Creating a command like: mycli run --path /path/to/bin foo --path /path/to/elsewhere. In this case, the run command has a path option to run an executable at some given path, and the executable foo also has a --path as part of its possible arguments. In this case only the first --path is read and the --path to foo is dropped. Looking for the same behavior as swift run essentially.
I'd be happy to help contribute this if needed!
Edit:
I see now that https://github.com/apple/swift-argument-parser/pull/304 might fix this!
Actually think #304 is just for option arrays.
Here is an example where this support is missing:
struct RunCommand: ParsableCommand {
@Option()
var path: String?
@Argument(parsing: .unconditionalRemaining)
var arguments: [String] = []
func run() throws {
print(path)
print(arguments)
}
}
Running: mycli run run --path firstPath Arg1 Arg2 Arg3 --path secondPath results in:
secondPath
Arg1 Arg2 Arg3
But I would expect:
firstPath
[Arg1, Arg2, Arg3, --path, secondPath]
@natecook1000 Would this be an enhancement or a bug given parsing: .unconditionalRemaining?