in src/main.rs [2637:2764]
fn cmd_help_md(
out: &Arc<dyn Out>,
_cfg: &PartialConfig,
_sub_args: &HelpMarkdownArgs,
) -> Result<(), miette::Report> {
let app_name = "cargo-vet";
let pretty_app_name = "cargo vet";
// Make a new App to get the help message this time.
writeln!(out, "# {pretty_app_name} CLI manual");
writeln!(out);
writeln!(
out,
"> This manual can be regenerated with `{pretty_app_name} help-markdown`"
);
writeln!(out);
let mut fake_cli = FakeCli::command().term_width(0);
let full_command = fake_cli.get_subcommands_mut().next().unwrap();
full_command.build();
let mut todo = vec![full_command];
let mut is_full_command = true;
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();
// First line is --version
let mut lines = help.lines();
let version_line = lines.next().unwrap();
let subcommand_name = command.get_name();
if is_full_command {
writeln!(out, "Version: `{version_line}`");
writeln!(out);
} else {
// Give subcommands some breathing room
writeln!(out, "<br><br><br>");
writeln!(out, "## {pretty_app_name} {subcommand_name}");
}
let mut in_subcommands_listing = false;
let mut in_usage = false;
let mut in_global_options = false;
for line in lines {
// Use a trailing colon to indicate a heading
if let Some(heading) = line.strip_suffix(':') {
if !line.starts_with(' ') {
// SCREAMING headers are Main headings
if heading.to_ascii_uppercase() == heading {
in_subcommands_listing = heading == "SUBCOMMANDS";
in_usage = heading == "USAGE";
in_global_options = heading == "GLOBAL OPTIONS";
writeln!(out, "### {heading}");
if in_global_options && !is_full_command {
writeln!(
out,
"This subcommand accepts all the [global options](#global-options)"
);
}
} else {
writeln!(out, "### {heading}");
}
continue;
}
}
if in_global_options && !is_full_command {
// Skip global options for non-primary commands
continue;
}
if in_subcommands_listing && !line.starts_with(" ") {
// subcommand names are list items
let own_subcommand_name = line.trim();
write!(
out,
"* [{own_subcommand_name}](#{app_name}-{own_subcommand_name}): "
);
continue;
}
// The rest is indented, get rid of that
let line = line.trim();
// Usage strings get wrapped in full code blocks
if in_usage && line.starts_with(pretty_app_name) {
writeln!(out, "```");
writeln!(out, "{line}");
writeln!(out, "```");
continue;
}
// argument names are subheadings
if line.starts_with('-') || line.starts_with('<') {
writeln!(out, "#### `{line}`");
continue;
}
// escape default/value strings
if line.starts_with('[') {
writeln!(out, "\\{line} ");
continue;
}
// Normal paragraph text
writeln!(out, "{line}");
}
writeln!(out);
// The todo list is a stack, and processed in reverse-order, append
// these commands to the end in reverse-order so the first command is
// processed first (i.e. at the end of the list).
todo.extend(
command
.get_subcommands_mut()
.filter(|cmd| !cmd.is_hide_set())
.collect::<Vec<_>>()
.into_iter()
.rev(),
);
is_full_command = false;
}
Ok(())
}