Argument parser’s help and error interception

I want to do multiple things in swift argument parser

  1. Modify default value of help and verstion abstract which shows on help command output
  2. Add example in parser error output, currently Error/usage/help is there, on same level want to add example also
  3. Want to change default footer string of help command output, in present it’s showing see for more information

How can I achieve these with minimal changes and native argument parser’s api help

I am not entirely sure what you are looking for, but I might suggest checking out the abstract, usage, and discussion parameters of CommandConfiguration as well as the ArgumentHelp passed to the help parameter of @Argument:

@main
struct Repeat: ParsableCommand {
    static var configuration = CommandConfiguration(
        abstract: "Repeats your input phrase.",
        usage: """
            repeat <phrase>
            repeat --count <count> <phrase>
            
            You can customize this usage string as you see fit.
            """,
        discussion: """
            Prints to stdout forever, or until you halt the program.
            
            EXAMPLES:
            
                Output 100 times:
            
                $ repeat --count 100 "I’m repeating this 100 times" 

                Output twice:
            
                $ repeat "I’m going to keep repeating this"
            
            You can custom this discussion string as you see fit.
            """
    )

    @Argument(
        help: ArgumentHelp("""
                You can customize this argument’s help string 
                to be whatever you want.
                """,
            discussion: """
                
                You can also add whatever discussion string for this argument
                to be whatever you want.
                """
        )
    )
    var phrase: String

    @Option(help: "How many times to repeat.")
    var count: Int? = nil

    mutating func run() throws {
        for _ in 0..<(count ?? 2) {
            print(phrase)
        }
    }
}

And then:

$ repeat --help
OVERVIEW: Repeats your input phrase.

Prints to stdout forever, or until you halt the program.

EXAMPLES:

    Output 100 times:

    $ repeat --count 100 "I’m repeating this 100 times" 

    Output twice:

    $ repeat "I’m going to keep repeating this"

You can custom this discussion string as you see fit.

USAGE: repeat <phrase>
       repeat --count <count> <phrase>

       You can customize this usage string as you see fit.

ARGUMENTS:
  <phrase>                You can customize this argument’s help string 
                          to be whatever you want.

        You can also add whatever discussion string for this argument
        to be whatever you want.

OPTIONS:
  --count <count>         How many times to repeat.
  -h, --help              Show help information.

Maybe these sorts of parameters get you close to what you are looking for. For more information, see ArgumentParser: Customizing Help for Commands.

If this isn’t quite doing what you want, maybe you can clarify by posting some examples of what you wanted to see.

Thanks for replying, so here is what I wanted

When we run help command on mycli , like this - mydesktop –help it’s giving this output

OVERVIEW: my Desktop Utility
USAGE: mydesktop 
OPTIONS:
--version Display the version information.
-h, --help Show this help message.
SUBCOMMANDS:
logs (default) Export logs for mydesktop Desktop processes.
uninstall Remove the my Desktop app, including associated data, services, CLI, defaults,
and keychain entries.
update-port Change the service port for my Desktop and restart the service.
proxy Configure proxy settings via CLI.
See 'mydesktop help ' for more information

Now i want to change

See 'mydesktop help ' for more information

To my text, something like.

For more details ‘mydesktop help’

And same in error output also, when error comes via validationerror, it’s have same footer, want to customize that too

I edited my reply

1 Like

I don’t see any obvious way to replace/customize that text string. Maybe someone else does. Sorry I couldn’t help.

Thanks for taking time to help

have one more change to do, errors is coming like this

Error: Missing expected argument '--time '
Help: --time (e.g. 10h, 30m, 2d).
Usage: mydesktop logs --time to add

Want to add example in error

Error: Missing expected argument '--time '
Help: --time (e.g. 10h, 30m, 2d).
Usage: mydesktop logs --time

example: mydesktop logs —time 30

One option would be to add these examples to your custom usage string for your subcommand:

@main
struct MyDesktop: ParsableCommand {
    static var configuration = CommandConfiguration(
        commandName: "mydesktop",
        abstract: "My Desktop Utility",
        discussion: "A utility for managing my Desktop app.",
        subcommands: [Logs.self, UpdatePort.self, Uninstall.self, Proxy.self]
    )

    // If you must supply a subcommand, just omit `run` for the `ParsableCommand`.
    //
    // Needless to say, if there is some default behavior, you’d either provide a
    // `defaultCommand` above, or implement `run`, whichever makes sense for your app.
}

extension MyDesktop {
    struct Logs: ParsableCommand {
        static var configuration = CommandConfiguration(
            abstract: "Export logs for mydesktop Desktop processes.",
            usage: """
                mydesktop logs --time <time>
                
                Examples:
                
                    $ mydesktop logs --time 10h
                    $ mydesktop logs -t 30m
                
                """
        )

        @Option(
            name: [.short, .long],
            help: ArgumentHelp(
                "Time period for logs (e.g. 10h, 30m, 2d)",
            )
        )
        var time: String

        mutating func run() {…}
    }

    struct UpdatePort: ParsableCommand {…}

    struct Uninstall: ParsableCommand {…}

    struct Proxy: ParsableCommand {…}
}

That produces, for example:

$ ./mydesktop
OVERVIEW: My Desktop Utility

A utility for managing my Desktop app.

USAGE: mydesktop <subcommand>

OPTIONS:
  -h, --help              Show help information.

SUBCOMMANDS:
  logs                    Export logs for mydesktop Desktop processes.
  update-port             Change the service port for my Desktop and restart the service.
  uninstall               Remove the my Desktop app, including associated data, services, CLI, defaults.
  proxy                   Configure proxy settings via CLI.

  See 'mydesktop help <subcommand>' for detailed help.

And if you omit --time for the logs subcommand:

$ ./mydesktop logs
Error: Missing expected argument '--time <time>'
Help:  -t <time>  Time period for logs (e.g. 10h, 30m, 2d)
Usage: mydesktop logs --time <time>

       Examples:

           $ mydesktop logs --time 10h
           $ mydesktop logs -t 30m

  See 'mydesktop logs --help' for more information.

Personally, I'd leave these examples to be discovered in “help”, rather than in the “usage” string:

struct Logs: ParsableCommand {
    static var configuration = CommandConfiguration(
        abstract: "Export logs for mydesktop Desktop processes."
    )

    @Option(
        name: [.short, .long],
        help: ArgumentHelp(
            "Time period for logs (e.g. 10h, 30m, 2d)",
            discussion: """
            
                              EXAMPLES:
                                  mydesktop logs --time 10h
                                  mydesktop logs -t 30d
            
            """
        )
    )
    var time: String

    mutating func run() {…}
}

Yielding:

$ ./mydesktop logs
Error: Missing expected argument '--time <time>'
Help:  -t <time>  Time period for logs (e.g. 10h, 30m, 2d)
Usage: mydesktop logs --time <time>
  See 'mydesktop logs --help' for more information.

$ ./mydesktop logs --help
OVERVIEW: Export logs for mydesktop Desktop processes.

USAGE: mydesktop logs --time <time>

OPTIONS:
  -t, --time <time>       Time period for logs (e.g. 10h, 30m, 2d)

                          EXAMPLES:
                              mydesktop logs --time 10h
                              mydesktop logs -t 30d

  -h, --help              Show help information.

Personally, I think a long discussion of various examples for a particular option belongs in the “help” text, not in an error message. But you can obviously do whatever you want.

By the way, I outlined two options:

  1. Put it in the Logs “usage” string; and
  2. Put it in the “discussion” of the --time option.

But there are other options, too:

  1. Put the examples in the main “help” text of the --time option; and
  2. Put it in the “discussion” of the CommandConfiguration for your main ParsableCommand (e.g., MyDesktop in my example).

There are lots of alternatives. These all have their own pros and cons, so try them out and see which you prefer.