Something went wrong. Try again.
npx ccusage
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140use std::{path::Path, process};
use crate::parser::command_tokens;
struct HelpPage { path: &'static [&'static str], description: &'static str, usage: &'static str, options: Option<&'static str>, commands: &'static [(&'static str, &'static str)],}
include!(concat!(env!("OUT_DIR"), "/cli-help.rs"));
pub(crate) fn print_version_and_exit(version: &str) -> ! { println!("ccusage {version}"); process::exit(0);}
pub(crate) fn print_help_and_exit(args: &[String]) -> ! { println!("{}", help_text_for_args(args)); process::exit(0);}
#[cfg(test)]pub(crate) fn help_text() -> String { root_help_text()}
pub(crate) fn help_text_for_args(args: &[String]) -> String { let args = strip_program_name(args); let tokens = command_tokens(args); help_text_for_tokens(&tokens)}
fn strip_program_name(args: &[String]) -> &[String] { if args.first().is_some_and(|arg| is_program_name(arg)) { &args[1..] } else { args }}
fn is_program_name(arg: &str) -> bool { let name = Path::new(arg) .file_name() .and_then(|name| name.to_str()) .unwrap_or(arg) .rsplit('\\') .next() .unwrap_or(arg); matches!(name, "ccusage" | "ccusage.exe")}
fn help_text_for_tokens(tokens: &[String]) -> String { find_help_page(tokens).map_or_else(root_help_text, render_help_page)}
fn find_help_page(tokens: &[String]) -> Option<&'static HelpPage> { HELP_PAGES.iter().find(|page| { page.path.len() == tokens.len() && page .path .iter() .zip(tokens) .all(|(expected, actual)| *expected == actual) })}
fn root_help_text() -> String { let mut lines = vec!["USAGE:".to_string()]; for usage in ROOT_USAGE { lines.push(format!(" {usage}")); } lines.push(String::new()); lines.push("COMMANDS:".to_string()); lines.extend(render_command_lines(ROOT_COMMANDS, 26)); lines.push(String::new()); lines.push("For more info, run any command with the `--help` flag:".to_string()); for (command, _) in ROOT_COMMANDS { lines.push(format!(" ccusage {command} --help")); } lines.push(String::new()); lines.push(all_agent_options().to_string()); lines.join("\n")}
fn render_help_page(page: &HelpPage) -> String { if page.commands.is_empty() { return command_help( page.description, page.usage, page.options .expect("command help pages with no subcommands require options"), ); }
let mut lines = vec![ page.description.to_string(), String::new(), "USAGE:".to_string(), format!(" {}", page.usage), String::new(), "COMMANDS:".to_string(), ]; lines.extend(render_command_lines(page.commands, 11)); lines.push(String::new()); lines.push("For more info, run any command with the `--help` flag:".to_string()); let prefix = page.usage.trim_end_matches(" <COMMANDS>"); for (command, _) in page.commands { lines.push(format!(" {prefix} {command} --help")); } lines.join("\n")}
fn render_command_lines(commands: &[(&str, &str)], min_width: usize) -> Vec<String> { let width = commands .iter() .map(|(command, _)| command.len()) .max() .unwrap_or(min_width) .max(min_width); commands .iter() .map(|(command, description)| format!(" {command:<width$} {description}")) .collect()}
fn command_help(description: &str, usage: &str, options: &str) -> String { [ description, "", "USAGE:", &format!(" {usage}"), "", options, ] .join("\n")}