Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

write_long_help is wonky on get_subcommands_mut values #3602

Closed
2 tasks done
Gankra opened this issue Apr 2, 2022 · 4 comments
Closed
2 tasks done

write_long_help is wonky on get_subcommands_mut values #3602

Gankra opened this issue Apr 2, 2022 · 4 comments
Labels
C-bug Category: Updating dependencies

Comments

@Gankra
Copy link

Gankra commented Apr 2, 2022

Please complete the following tasks

Rust Version

rustc 1.61.0-nightly (458262b13 2022-03-09)

Clap Version

3.1.8

Minimal reproducible code

The main thing is just:

    // Cli is derive(Parser)
    let mut full_command = Cli::command();
    let mut todo = vec![&mut full_command];

    while let Some(command) = todo.pop() {
        // Get the long help for this (sub)command
        let mut help_buf = Vec::new();
        command.write_long_help(&mut help_buf).unwrap();

        // print help_buf...

        // Add subcommands to working queue
        todo.extend(command.get_subcommands_mut());
    }

But the "complete" program is all of this:

use std::{io::Write, error::Error};

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

#[derive(Parser)]
#[clap(version, about, long_about = None)]
#[clap(propagate_version = true)]
struct Cli {
    // Subcommands
    #[clap(subcommand)]
    command: Option<Commands>,

    // Some random flags 
    #[clap(long)]
    locked: bool,
    #[clap(long)]
    log_file: Option<String>,
}

#[derive(Subcommand)]
enum Commands {
    /// initialize buggyhelp for your project
    #[clap(disable_version_flag = true)]
    Init(InitArgs),

    /// Fetch the source of `$crate $version`
    #[clap(disable_version_flag = true)]
    Fetch(FetchArgs),

    /// Print --help as markdown (for generating docs)
    #[clap(disable_version_flag = true)]
    #[clap(hide = true)]
    HelpMarkdown(HelpMarkdownArgs),
}

#[derive(clap::Args)]
struct InitArgs {}

#[derive(clap::Args)]
struct FetchArgs {
    krate: String,
    version: String,
}

#[derive(clap::Args)]
struct HelpMarkdownArgs {}


fn main() -> Result<(), Box<dyn Error>>  {
    let cli = Cli::parse();

    match &cli.command {
        Some(Commands::HelpMarkdown(..)) => cmd_help_markdown()?,
        _ => unimplemented!(),
    }

    Ok(())
}

fn cmd_help_markdown() -> Result<(), Box<dyn Error>> {
    let mut full_command = Cli::command();
    let mut todo = vec![&mut full_command];

    while let Some(command) = todo.pop() {
        let mut help_buf = Vec::new();

        command.write_long_help(&mut help_buf).unwrap();
        let help = String::from_utf8(help_buf).unwrap();
        println!("{}", help);

        todo.extend(command.get_subcommands_mut());
    }

    Ok(())
}

Steps to reproduce the bug with the above code

cargo run -- help-markdown

Actual Behaviour

The long_help outputs for the subcommands are weirdly different from myapp subcommand --help:

  • USAGE is subcommand ... instead of myapp subcommand ...
  • ARGS have weird amounts of padding
fetch 0.1.0
Fetch the source of `$crate $version`

USAGE:
    fetch <KRATE> <VERSION>

ARGS:
    <KRATE>


    <VERSION>


OPTIONS:
    -h, --help
            Print help information

Expected Behaviour

It's not obvious why this would produce substantially different output from the "normal" way to get --help on the CLI.

Additional Context

The reason I am doing these crimes is that I have a secret command that mangles the --help output into a usable markdown form to add to the end of a README.md: https://gist.github.com/Gankra/349dcf6732262ed33b2aa216243a75be

Debug Output

No response

@Gankra Gankra added the C-bug Category: Updating dependencies label Apr 2, 2022
@epage
Copy link
Member

epage commented Apr 3, 2022

This is most likely due to an under-developed part of clap. To work around it, you should call full_command._build_all(); before doing anything else.

#2911 is the issue for improving this.

@epage
Copy link
Member

epage commented Apr 19, 2022

Without any activity on this, I'm assuming the solution provided is sufficient. If not, let us know and we can re-open!

@epage epage closed this as completed Apr 19, 2022
@Gankra
Copy link
Author

Gankra commented Apr 19, 2022

oh yes sorry, I patched around the issue by just "expecting" the wonky output, I haven't had a chance to look at _build_all() (leading underscore has me suspicious that this is no better than me hacking around it...).

epage added a commit to epage/clap that referenced this issue Apr 19, 2022
`Command::_build_all` started as an internal function for
`clap_complete` as a stopgap until clap-rs#2911.  Overtime, we've been finding
more cases where this function needs to be called, so now we're going to
fully embrace it until clap-rs#2911 so people aren't scrared off by the hidden
implementation from using it.

This was inspired by clap-rs#3602
epage added a commit to epage/clap that referenced this issue Apr 19, 2022
`Command::_build_all` started as an internal function for
`clap_complete` as a stopgap until clap-rs#2911.  Overtime, we've been finding
more cases where this function needs to be called, so now we're going to
fully embrace it until clap-rs#2911 so people aren't scrared off by the hidden
implementation from using it.

This was inspired by clap-rs#3602

Comptibility: Though this adds a deprecation which we general reserve
for minor or major versions, this is enough of a corner case that I'm
fine doing this in a patch release.
@epage
Copy link
Member

epage commented Apr 19, 2022

I've released v3.1.10 with Command::build so people don't have to feel bad for using it until we've replaced it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: Updating dependencies
Projects
None yet
Development

No branches or pull requests

2 participants