///|
pub(all) suberror CliError {
HelpRequested
MissingSpec
MissingUninstallName
UnknownFlag(String)
MissingFlagValue(String)
InvalidTarget(String)
UnexpectedArg(String)
} derive(Eq, Show)
///|
pub struct InstallArgs {
spec : String
name : String?
target : Target
} derive(Eq, Show)
///|
pub enum Command {
Install(InstallArgs)
Uninstall(String)
} derive(Eq, Show)
///|
pub fn parse_cli_args(args : Array[String]) -> Result[Command, CliError] {
if args.length() == 0 {
return Err(CliError::MissingSpec)
}
if args[0] == "--help" || args[0] == "-h" {
return Err(CliError::HelpRequested)
}
if args[0] == "uninstall" {
if args.length() == 1 {
return Err(CliError::MissingUninstallName)
}
if args[1] == "--help" || args[1] == "-h" {
return Err(CliError::HelpRequested)
}
if args[1].has_prefix("-") {
return Err(CliError::UnknownFlag(args[1]))
}
if args.length() > 2 {
return Err(CliError::UnexpectedArg(args[2]))
}
return Ok(Command::Uninstall(args[1]))
}
for i = 0, spec = "", name = None, target = Target::Native; i < args.length(); {
let arg = args[i]
if arg == "--help" || arg == "-h" {
return Err(CliError::HelpRequested)
}
match strip_prefix(arg, "--name=") {
Some(value) => continue i + 1, spec, Some(value), target
None => ()
}
match strip_prefix(arg, "--target=") {
Some(value) =>
match Target::from_string(value) {
Some(t) => continue i + 1, spec, name, t
None => return Err(CliError::InvalidTarget(value))
}
None => ()
}
if arg == "--name" {
if i + 1 >= args.length() {
return Err(CliError::MissingFlagValue("--name"))
}
continue i + 2, spec, Some(args[i + 1]), target
}
if arg == "--target" {
if i + 1 >= args.length() {
return Err(CliError::MissingFlagValue("--target"))
}
let value = args[i + 1]
match Target::from_string(value) {
Some(t) => continue i + 2, spec, name, t
None => return Err(CliError::InvalidTarget(value))
}
}
if arg.has_prefix("-") {
return Err(CliError::UnknownFlag(arg))
}
if spec.length() == 0 {
continue i + 1, arg, name, target
}
return Err(CliError::UnexpectedArg(arg))
} else {
if spec.length() == 0 {
Err(CliError::MissingSpec)
} else {
Ok(Command::Install({ spec, name, target }))
}
}
}
///|
fn strip_prefix(s : String, prefix : StringView) -> String? {
if s.has_prefix(prefix) {
let prefix_len = prefix.length()
try s[prefix_len:] catch {
_ => None
} noraise {
view => Some(view.to_string())
}
} else {
None
}
}