rustclap

How to rename subcommand placeholder in clap_derive?


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>.


Solution

  • 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