0xFR
0xFR

Reputation: 118

How can I define a default subcommand in Rust Clap?

I'm building a CLI in Rust to learn the language and I am using clap with the derive feature for the argument parsing. I would like to have a specific behavior of my CLI; specifically, it has some subcommands, and I want to execute one in particular (To) when not specified.

The code is this:

use clap::{Args, Parser, Subcommand};

#[derive(Parser)]
#[command(author, version, about, long_about = None)]
#[command(propagate_version = true)]
struct Cli {
    #[command(subcommand)]
    command: Commands,
}

#[derive(Subcommand)]
enum Commands {
    /// Goes to the reference
    To(GotoArgs),
    /// Adds reference to the json file
    Add(AddArgs),
    /// Deletes a reference in the json file
    Del(DelArgs),
    /// Lists all the references in the json file
    List,
}

I want my program to execute the to subcommand when no other commands are specified, and take the GotoArgs. How can I achieve this behavior?

Another way would be to define the parser as an enum, in order to say, for example, choose a command from Commands or take the arguments for the (implicit) To command. The problem is that I don't find a lot in the documentation and I don't know how and if I can do it.

EDIT: I want to be able to launch the program with binary GotoArgs, so with the possibility to omit the to subcommand.

Upvotes: 1

Views: 1259

Answers (1)

Finomnis
Finomnis

Reputation: 22738

I don't think this is possible with clap. It would create ambiguities.

Consider the following code:

use clap::{Args, Parser, Subcommand};

#[derive(Parser)]
#[command(author, version, about, long_about = None)]
#[command(propagate_version = true)]
struct Cli {
    #[command(subcommand)]
    command: Commands,
}

#[derive(Args)]
struct GotoArgs {
    val: String,
}

#[derive(Args)]
struct AddArgs {}

#[derive(Args)]
struct DelArgs {}

#[derive(Subcommand)]
enum Commands {
    /// Goes to the reference
    To(GotoArgs),
    /// Adds reference to the json file
    Add(AddArgs),
    /// Deletes a reference in the json file
    Del(DelArgs),
    /// Lists all the references in the json file
    List,
}

If To(GoToArgs) would now be the default, what would the following be?

./myapp add

Would that create this:

Cli {
   command: Commands::To(GotoArgs{
      val: "add"
   })
}

or this?

Cli {
   command: Commands::Add(AddArgs{})
}

Upvotes: 1

Related Questions