1

How can I rename the placeholder <COMMAND> of a subcommand when using clap_derive?

Here's an MRE: Cargo.toml

[package]
name = "clap_test_subcommand_placeholder"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
clap = { version = "4.4.0", features = ["derive"] }

src/main.rs

use clap::{Parser, Subcommand};

#[derive(Debug, Parser)]
#[command(author, version, about, long_about = "Frobnicate the fizzbuzz")]
struct Args {
    #[arg(index = 1, name = "xml_file", help = "The base XML file to operate on")]
    file: String,
    #[command(subcommand, name = "action")]
    action: Action,
}

#[derive(Clone, Debug, Subcommand)]
pub enum Action {
    #[command(long_about = "Add a new type")]
    Add,
    #[command(long_about = "Display the selected type's properties")]
    Find,
}

fn main() {
    Args::parse();
}

The flag name is accepted by the compiler, but does not seem to have an effect:

〉cargo run                                                                                                                      2023-08-27 11:35:07
   Compiling clap_test_subcommand_placeholder v0.1.0 (/home/rne/clap_test_subcommand_placeholder)
    Finished dev [unoptimized + debuginfo] target(s) in 0.65s
     Running `target/debug/clap_test_subcommand_placeholder`
Usage: clap_test_subcommand_placeholder <xml_file> <COMMAND>

Commands:
  add   Add a new type
  find  Display the selected type's properties
  help  Print this message or the help of the given subcommand(s)

Arguments:
  <xml_file>  The base XML file to operate on

Options:
  -h, --help     Print help (see more with '--help')
  -V, --version  Print version

It still says <COMMAND> instead of <action>.

Richard Neumann
  • 2,986
  • 2
  • 25
  • 50

1 Answers1

3

You need to set subcommand_value_name = "action" in the #[command]:

use clap::{Parser, Subcommand};

#[derive(Debug, Parser)]
#[command(
    author,
    version,
    about,
    long_about = "Frobnicate the fizzbuzz",
    subcommand_value_name = "action"
)]
struct Args {
    #[arg(index = 1, name = "xml_file", help = "The base XML file to operate on")]
    file: String,
    #[command(subcommand, name = "action")]
    action: Action,
}

#[derive(Clone, Debug, Subcommand)]
pub enum Action {
    #[command(long_about = "Add a new type")]
    Add,
    #[command(long_about = "Display the selected type's properties")]
    Find,
}

fn main() {
    Args::parse();
}

Output:

Usage: playground <xml_file> <action>

Commands:
  add   Add a new type
  find  Display the selected type's properties
  help  Print this message or the help of the given subcommand(s)

Arguments:
  <xml_file>  The base XML file to operate on

Options:
  -h, --help     Print help (see more with '--help')
  -V, --version  Print version

Playground


You can change the Commands: in the help message to Actions: with subcommand_help_heading:

#[command(
    author,
    version,
    about,
    long_about = "Frobnicate the fizzbuzz",
    subcommand_help_heading = "Actions",
    subcommand_value_name = "action"
)]

Output:

Usage: playground <xml_file> <action>

Actions:
  add   Add a new type
  find  Display the selected type's properties
  help  Print this message or the help of the given subcommand(s)

Arguments:
  <xml_file>  The base XML file to operate on

Options:
  -h, --help     Print help (see more with '--help')
  -V, --version  Print version
Dogbert
  • 212,659
  • 41
  • 396
  • 397