Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrong executable name reported in usage. #570

Open
2 tasks done
dabrahams opened this issue May 20, 2023 · 3 comments
Open
2 tasks done

Wrong executable name reported in usage. #570

dabrahams opened this issue May 20, 2023 · 3 comments
Labels
bug Something isn't working help wanted Extra attention is needed

Comments

@dabrahams
Copy link

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

  • If possible, I've reproduced the issue using the main branch of this package
  • 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.

@rauhul
Copy link
Contributor

rauhul commented May 20, 2023

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 rauhul added bug Something isn't working help wanted Extra attention is needed labels May 20, 2023
@natecook1000
Copy link
Member

See also #295

@natikgadzhi
Copy link

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?

dcantah added a commit to dcantah/swift-argument-parser that referenced this issue May 31, 2024
Fixes: apple#633 apple#570 apple#295

This seems like the "correct" default. If your root command had the same name
as the resulting binary you produce, this was never an issue, however if
your root command was named anything else, then the current Usage/help text was
kind of odd.

If you don't specify an explicit commandName in CommandConfiguration, we would
take the root command name and generate a command name for you out of hyphens.
So, `RootCommand` would become `root-command` and this is what would be displayed
in the usage text for `/path/to/cool-binary --help`, even though intuitively you'd
expect to see `USAGE: cool-binary`.

The current behavior was also strange for binaries that are classically invoked
via symlinks as the same thing would happen. In this case imagine the struct name
matched the actual binaries name, but because the symlink is what users actually
invoke you could end up seeing an unfamiliar name in help text regardless. Using
argv[0] solves most of these problems.

The downside here is a LOT of tests need to change. I went with foregoing the
new approach if the user explicitly provides a command name, so most of the existing
tests that check for exact string matches of help text either need to replace the
command name with the first argument of the binary that is running the test (xctest,
but it doesn't really matter what it is as I've added a helper to plop in the first
argument for all of these tests), or they need to define
CommandConfiguration(commandName: "name-we-want"). For any tests that implemented
ParsableCommand I mostly went with the latter to make as few changes as possible.

Given this seems like mostly a UX change, I hope this seems sane.

Signed-off-by: Danny Canter <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

4 participants