Is it possible to run a command from a parent command whenever a subcommand is run?

I've been playing around with ArgumentParser (thanks for all the awesome work on it!). I have two small questions that I've been playing around with.

struct MainCommand: ParseableCommand {
static let configuration = CommandConfiguration(
        version: "0.0.1",
        subcommands: [
            Foo.self,
            Bar.self,
            Baz.self
        ]
    )
}
  1. Is there any way to have some code in the main command run every time that a subcommand is invoked?

  2. What would be the best way to check if the command is out of date by version? I'm building this into compiled binary and then moving to /usr/local/bin, but there is a predictable way for this binary to access information from its original project folder to tell if the binary version is different from what is in the git repo?

Here's a short example below of sort of the desired output:

$ main_command bar 'foo.txt'
Frobnicating foo.text using bar
.
.
.
It looks like you're using MainCommand version 0.0.1 ... to update ....

That pattern isn’t directly supported, but you can achieve it a couple different ways by building on top of ParsableCommand. In the ArgumentParser adoption for SwiftPM, I’ve added a SwiftCommand protocol that creates an instance of the helper type that all the different subcommands work with and passes that into an overload of run():

You should be able to access the version of your built tool with <RootCommand>.configuration.version. To get the latest version of the tool, I imagine you’d want to query the GitHub API to see your list of releases, and then compare that to the version of the tool that’s executing.

Ahh, I see, so the super relevant part would be protocol SwiftCommand: ParseableCommand.

Would something along these lines be a sane approach?

protocol VersionCheckedCommand: ParsableCommand {
    func runCommandBody() throws
}

extension VersionCheckedCommand {
    public func run() throws {
        try runCommandBody()
        if someVersionCheckFails() {
            // display update instructions
        }
    }

Thanks for all your hard work on an awesome library :slight_smile:

1 Like