///|
fn parser() -> @clap.Parser {
@clap.Parser::new(
prog="uc",
description="Convert unit-bearing quantities with LunarUnits.",
args={
"format": @clap.Arg::named(
short='f',
nargs=Fixed(1),
choices=@hashset.from_array(["ascii", "si", "latex"]),
defaults=["ascii"],
global=true,
help="Output format: ascii, si, or latex",
),
},
subcmds={
"convert": @clap.SubCommand::new(
args={
"input": @clap.Arg::positional(
nargs=Fixed(2),
help="Quantity expression and target unit",
),
},
help="Convert a quantity to a target unit",
),
"parse": @clap.SubCommand::new(
args={
"expr": @clap.Arg::positional(
nargs=Fixed(1),
help="Quantity expression",
),
},
help="Parse a quantity expression",
),
"parse-unit": @clap.SubCommand::new(
args={
"expr": @clap.Arg::positional(nargs=Fixed(1), help="Unit expression"),
},
help="Parse a unit expression",
),
"inspect": @clap.SubCommand::new(
args={
"symbol": @clap.Arg::positional(nargs=Fixed(1), help="Unit symbol"),
},
help="Inspect a unit symbol",
),
},
)
}
///|
fn args_without_program() -> Array[String] {
let args = @env.args()
if args.length() > 0 &&
(
args[0].contains("/") ||
args[0].contains("\\") ||
args[0].contains(".exe")
) {
let trimmed = []
for i in 1.. Bool {
arg == "convert" || arg == "parse" || arg == "parse-unit" || arg == "inspect"
}
///|
fn extract_format(args : Array[String]) -> (String, Array[String]) {
let mut format = "ascii"
let rest = []
let mut i = 0
while i < args.length() {
if (args[i] == "--format" || args[i] == "-f") && i + 1 < args.length() {
format = args[i + 1]
i = i + 2
} else {
rest.push(args[i])
i = i + 1
}
}
(format, rest)
}
///|
fn should_use_clap(args : Array[String]) -> Bool {
args.is_empty() || is_known_subcommand(args[0])
}
///|
fn run_convert_shortcut(args : Array[String]) -> @lib.CliResult {
let (format, rest) = extract_format(args)
guard rest.length() == 2 else {
return Err("usage: uc [--format ascii|si|latex] ")
}
@lib.run_convert(rest[0], rest[1], format~)
}
///|
fn root_help() -> String {
(
#|Usage: uc [OPTIONS]
#| uc [OPTIONS]
#|
#|Commands:
#| convert Convert a quantity to a target unit
#| parse Parse a quantity expression
#| parse-unit Parse a unit expression
#| inspect Inspect a unit symbol
#|
#|Options:
#| -f, --format Output format: ascii, si, or latex
#| -h, --help Print help
#|
)
}
///|
fn print_result(result : @lib.CliResult) -> Unit {
match result {
Ok(output) => println(output)
Err(message) => println("error: \{message}")
}
}
///|
fn selected_format(value : @clap.SimpleValue) -> String {
value.get_option("format").unwrap_or("ascii") catch {
_ => "ascii"
}
}
///|
fn run(value : @clap.SimpleValue) -> @lib.CliResult {
let format = selected_format(value)
match value.subcmd {
Some(subcmd) =>
match subcmd.name {
"convert" => {
let args : Array[String] = subcmd.get_positional() catch {
err => return Err("invalid convert arguments: \{err}")
}
@lib.run_convert(args[0], args[1], format~)
}
"parse" => {
let args : Array[String] = subcmd.get_positional() catch {
err => return Err("invalid parse arguments: \{err}")
}
@lib.run_parse(args[0], format~)
}
"parse-unit" => {
let args : Array[String] = subcmd.get_positional() catch {
err => return Err("invalid parse-unit arguments: \{err}")
}
@lib.run_parse_unit(args[0], format~)
}
"inspect" => {
let args : Array[String] = subcmd.get_positional() catch {
err => return Err("invalid inspect arguments: \{err}")
}
@lib.run_inspect(args[0], format~)
}
_ => Err("unknown subcommand: \{subcmd.name}")
}
None => Err("usage: uc ")
}
}
///|
fn main {
let raw_args = args_without_program()
if raw_args.length() == 1 && (raw_args[0] == "--help" || raw_args[0] == "-h") {
println(root_help())
return
}
if !should_use_clap(raw_args) {
print_result(run_convert_shortcut(raw_args))
return
}
let parser = parser()
let value = @clap.SimpleValue::new("uc")
let help = parser.parse(value, raw_args) catch {
err => {
println("error: \{err}")
return
}
}
match help {
Some(message) => println(message)
None => print_result(run(value))
}
}