| 28 | } |
| 29 | |
| 30 | fn generate_markdown(cmd: &mut Command, heading_level: usize) -> String { |
| 31 | let mut out = String::new(); |
| 32 | |
| 33 | let heading = "#".repeat(heading_level); |
| 34 | out.push_str(&format!("{} `{}`\n\n", heading, cmd.get_name())); |
| 35 | |
| 36 | if let Some(long_about) = cmd.get_long_about() { |
| 37 | out.push_str(&format!("{}\n\n", long_about)); |
| 38 | } |
| 39 | |
| 40 | out.push_str(&format!("**Usage:**\n```bash\n{}\n```\n\n", cmd.render_usage())); |
| 41 | |
| 42 | let mut options = String::new(); |
| 43 | for arg in cmd.get_arguments() { |
| 44 | let mut names = arg |
| 45 | .get_long() |
| 46 | .map(|l| format!("--{}", l)) |
| 47 | .or_else(|| arg.get_short().map(|s| format!("-{}", s))) |
| 48 | .unwrap_or_else(|| arg.get_id().to_string()); |
| 49 | if let Some(value_names) = arg.get_value_names().filter(|_| arg.get_action().takes_values()) { |
| 50 | for value_name in value_names { |
| 51 | names.push_str(&format!(" <{value_name}>")); |
| 52 | } |
| 53 | } |
| 54 | let help = arg |
| 55 | .get_long_help() |
| 56 | .or_else(|| arg.get_help()) |
| 57 | .map(|help| help.to_string()) |
| 58 | .unwrap_or_else(|| { |
| 59 | eprintln!("Warning: argument `{}` is missing help text", arg.get_id()); |
| 60 | "".to_string() |
| 61 | }); |
| 62 | if help.is_empty() { |
| 63 | options.push_str(&format!("- `{names}`:\n")); |
| 64 | } else { |
| 65 | options.push_str(&format!( |
| 66 | "- `{}`: {}\n{}", |
| 67 | names, |
| 68 | help, |
| 69 | if help.lines().count() > 1 { "\n" } else { "" } |
| 70 | )); |
| 71 | } |
| 72 | } |
| 73 | |
| 74 | if !options.is_empty() { |
| 75 | out.push_str("**Options:**\n\n"); |
| 76 | out.push_str(&options); |
| 77 | out.push('\n'); |
| 78 | } |
| 79 | |
| 80 | for sub in cmd.get_subcommands_mut() { |
| 81 | out.push_str(&generate_markdown(sub, heading_level + 1)); |
| 82 | } |
| 83 | |
| 84 | out |
| 85 | } |