swift-argument-parser icon indicating copy to clipboard operation
swift-argument-parser copied to clipboard

Wrong executable name reported in `usage`.

Open dabrahams opened this issue 1 year ago • 3 comments

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.

dabrahams avatar May 20 '23 00:05 dabrahams

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.

rauhul avatar May 20 '23 03:05 rauhul

See also https://github.com/apple/swift-argument-parser/issues/295

natecook1000 avatar May 22 '23 20:05 natecook1000

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:

  1. Fix this particular bug by not providing toolName to UsageGenerator
  2. 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?
  3. First approach, plus other spots where necessary, plus documentation on how _commandName is set, and how to use argv instead?

natikgadzhi avatar Jun 25 '23 05:06 natikgadzhi