swift-argument-parser
swift-argument-parser copied to clipboard
Wrong executable name reported in `usage`.
Executable name in usage messages is synthesized from the @main
struct name. That's incorrect by almost any measure: no executable by that name exists in most cases. IMO the right behavior is to report the executable name as CommandLine.arguments.first!
. There are at least several command-line packages that are installed as a family of symlinks to a single executable, where the behavior of the command may actually depend on the name of the symlink through which it was invoked.
Replace this paragraph with a short description of the incorrect incorrect behavior. If this is a regression, please note the last version that the behavior was correct in addition to your current version.
ArgumentParser version: 1.2.2 Swift version: swift-driver version: 1.75.2 Apple Swift version 5.8 (swiftlang-5.8.0.124.2 clang-1403.0.22.11.100) Target: arm64-apple-macosx13.0
Checklist
- [x] If possible, I've reproduced the issue using the
main
branch of this package - [x] I've searched for existing GitHub issues
Steps to Reproduce
Use this source to create a command-line tool with executable named "foo," then run the tool with no arguments
import ArgumentParser
import Foundation
@main
struct TesterOfThings: ParsableCommand {
@Argument(help: "Paths.", transform: URL.init(fileURLWithPath:))
var files: [URL]
func run() throws {
print(CommandLine.arguments)
}
}
Expected behavior
A message is printed that describes the usage of the foo
command.
Actual behavior
A message is printed that describes the usage of the nonexistent tester-of-things
command.
Definitely a bug, I haven't taken a look at the command cluster support (e.g. git-x
invocable as git x
) code in a while so I'm not sure how much work this will take to fix offhand, though my guess is that this shouldn't be too hard.
See also https://github.com/apple/swift-argument-parser/issues/295
It looks like if the ParsableCommand
has configuration
that contains usage
or commandName
, those will be used instead of defaulting to ParsableCommand.Type
.
HelpGenerator
builds toolName
from ParsableCommand.Type
, and then we pass that into UsageGenerator
.
But, we can call UsageGenerator
without providing the toolName
, and it'll automatically use CommandLine.arguments.first!
as @dabrahams suggests, even cleans it up a bit.
We could just invoke UsageGenerator
without the toolName
, and seemingly that would fix this particular bug. But that behavior also happens in a few other scenarios, like generating conde completions.
@natecook1000, I'm just learning things, but working on a fix. I wonder what approach would be better:
- Fix this particular bug by not providing
toolName
toUsageGenerator
- Try and work on how
ParsableCommand._commandName
is being set. That's not clear, because we can't assume that a particular ParsableCommand is a root-level command, and that it's name should be taken from argv? - First approach, plus other spots where necessary, plus documentation on how _commandName is set, and how to use argv instead?