use std::fmt::Write as _;
use clap::CommandFactory;
use crate::cli::Cli;
pub(crate) const DOTS_HINT: &str = "...";
const DOTS_ABOUT: &str = "See all commands with --list";
pub(crate) fn prepare_top_level_command() -> clap::Command {
let mut cmd = Cli::command();
cmd.build();
let cmd = cmd.mut_subcommand("help", |sub| sub.hide(true)).subcommand(
clap::Command::new(DOTS_HINT)
.about(DOTS_ABOUT)
.disable_help_subcommand(true),
);
let mut after_help = format_commands_block(&cmd);
after_help.push('\n');
after_help.push_str("See 'cabin help <command>' for more information on a specific command.\n");
cmd.after_help(after_help)
}
fn format_commands_block(cmd: &clap::Command) -> String {
struct Row {
tokens: Vec<String>,
about: String,
}
let rows: Vec<Row> = cmd
.get_subcommands()
.filter(|sub| !sub.is_hide_set())
.map(|sub| {
let mut tokens = vec![sub.get_name().to_owned()];
for alias in sub.get_visible_aliases() {
tokens.push(alias.to_string());
}
let about = sub
.get_about()
.map(|s| s.to_string().lines().next().unwrap_or("").trim().to_owned())
.unwrap_or_default();
Row { tokens, about }
})
.collect();
let width = rows
.iter()
.map(|row| row.tokens.join(", ").len())
.max()
.unwrap_or(0);
let mut out = String::new();
let _ = writeln!(out, "\x1b[1m\x1b[92mCommands:\x1b[0m");
for row in &rows {
out.push_str(" ");
let plain_width: usize = row.tokens.join(", ").len();
for (i, token) in row.tokens.iter().enumerate() {
if i > 0 {
out.push_str(", ");
}
let _ = write!(out, "\x1b[1m\x1b[96m{token}\x1b[0m");
}
if row.about.is_empty() {
out.push('\n');
} else {
let padding = width.saturating_sub(plain_width);
for _ in 0..padding {
out.push(' ');
}
let _ = writeln!(out, " {about}", about = row.about);
}
}
out
}