///|
/// Generate the help message
pub fn Parser::gen_help_message(
self : Parser,
subcmd_chains : Array[String],
global_args : Map[String, Arg],
) -> String {
let builder = StringBuilder::new(size_hint=32)
builder.write_string("Usage: ")
let mut args = self.args
let mut subcmds = self.subcmds
builder.write_string(subcmd_chains[0])
builder.write_char(' ')
for subcmd_name in subcmd_chains[1:] {
builder.write_string(subcmd_name)
builder.write_char(' ')
let subcmd = subcmds.get(subcmd_name).unwrap()
args = subcmd.args
subcmds = subcmd.subcmds
}
builder.write_string("[OPTIONS]")
if not(subcmds.is_empty()) {
builder.write_char(' ')
builder.write_string("")
}
let arg_pos_mark = if args
.iter()
.find_first(fn(pair) { pair.1 is Positional(..) })
is Some((name, arg)) {
let name_upper = name.to_upper()
let nargs = arg.nargs().unwrap()
let label = if nargs is Nargs::Fixed(1) {
"<\{name_upper}>"
} else if nargs.is_exceeded(2) {
"[\{name_upper}]"
} else {
"[\{name_upper}]..."
}
builder.write_char(' ')
builder.write_string(label)
Some((label, arg.common().help))
} else {
None
}
builder.write_char('\n')
builder.write_char('\n')
if not(subcmds.is_empty()) {
builder.write_string("Commands:\n")
let max_length = subcmds
.iter()
.map(fn(pair) { pair.0.char_length() })
.maximum()
.unwrap()
for name, subcmd in subcmds.iter2() {
builder.write_string(" \{name} ")
for _ in 0..<(max_length - name.char_length()) {
builder.write_char(' ')
}
builder.write_string(subcmd.help)
builder.write_char('\n')
}
builder.write_char('\n')
}
if arg_pos_mark is Some((label, help)) {
builder.write_string("Arguments:\n")
builder.write_string(" \{label} \{help}\n\n")
}
write_args(builder, "Options", args, {}, true)
if not(global_args.is_empty()) {
builder.write_char('\n')
write_args(builder, "Common Options", global_args, args, false)
}
builder.to_string()
}
///|
fn write_args(
builder : StringBuilder,
title : String,
the_args : Map[String, Arg],
cull_args : Map[String, Arg],
include_help : Bool,
) -> Unit {
builder.write_string("\{title}:\n")
let options = []
for name, arg in the_args.iter2() {
guard not(cull_args.contains(name)) else { continue }
guard not(arg is Positional(..)) else { continue }
let short_string = match arg.short() {
Some(short) => "-\{short},"
None => " "
}
let long_string = if arg is Flag(_) {
"--\{name}"
} else {
"--\{name} <\{name.to_upper()}>"
}
let length = short_string.char_length() + long_string.char_length()
options.push((short_string, long_string, length, arg.common().help))
}
if include_help {
options.push(("-h,", "--help", 9, "Print help"))
}
let max_length = options.iter().map(fn(item) { item.2 }).maximum().unwrap()
for item in options {
let (short_string, long_string, length, help) = item
builder.write_string(" \{short_string} \{long_string} ")
for _ in 0..<(max_length - length) {
builder.write_char(' ')
}
builder.write_string(help)
builder.write_char('\n')
}
}