///|
pub(all) enum Command {
Build
Doctor
Check
Inspect
Plan
Verify
Help
Version
} derive(Eq, Debug)
///|
pub struct CliOptions {
command : Command
config : String
sdk : String?
abis : Array[String]
output : String
json : Bool
dry_run : Bool
cache : Bool
}
///|
pub(all) struct Diagnostic {
stage : String
code : String
message : String
context : Array[String]
}
///|
pub fn Diagnostic::to_json(self : Diagnostic) -> Json {
{
"stage": self.stage,
"code": self.code,
"message": self.message,
"context": self.context.to_json(),
}
}
///|
pub fn Diagnostic::render(self : Diagnostic) -> String {
let prefix = self.stage + " [" + self.code + "]: " + self.message
if self.context.is_empty() {
prefix
} else {
prefix + "\n " + self.context.join("\n ")
}
}
///|
pub fn command_name(command : Command) -> String {
match command {
Build => "build"
Doctor => "doctor"
Check => "check"
Inspect => "inspect"
Plan => "plan"
Verify => "verify"
Help => "help"
Version => "version"
}
}
///|
fn parse_command(text : String) -> Command raise ConfigError {
match text {
"build" => Build
"doctor" => Doctor
"check" => Check
"inspect" => Inspect
"plan" => Plan
"verify" => Verify
"--help" | "-h" => Help
"--version" => Version
_ => raise Invalid("unknown command: " + text)
}
}
///|
pub fn parse_abis(text : String) -> Array[String] raise ConfigError {
let result : Array[String] = []
for part in text.split(",") {
let abi = part.to_owned()
if abi != "arm64-v8a" && abi != "x86_64" {
raise Invalid("unsupported ABI: " + abi)
}
if result.contains(abi) {
raise Invalid("duplicate ABI: " + abi)
}
result.push(abi)
}
if result.is_empty() {
raise Invalid("at least one ABI is required")
}
result
}
///|
fn allowed_option(command : Command, option : String) -> Bool {
match option {
"--json" => command != Help && command != Version
"--config" => command != Verify && command != Help && command != Version
"--sdk" => command == Build || command == Doctor || command == Plan
"--abi" => command == Build || command == Plan
"--out" => command == Build || command == Verify
"--dry-run" | "--cache" => command == Build
_ => false
}
}
///|
/// Arguments exclude the executable name. Paths are resolved by the command.
pub fn parse_cli(args : Array[String]) -> CliOptions raise ConfigError {
let command = if args.is_empty() { Help } else { parse_command(args[0]) }
let mut config = "moonohos.json"
let mut sdk : String? = None
let mut abis = ["arm64-v8a", "x86_64"]
let mut output = "_build/moonohos/dist"
let mut json = false
let mut dry_run = false
let mut cache = false
let seen : Map[String, Bool] = Map([])
let mut index = 1
while index < args.length() {
let option = args[index]
if option == "--help" || option == "-h" {
return { command: Help, config, sdk, abis, output, json, dry_run, cache, }
}
if !allowed_option(command, option) {
raise Invalid(
"option " + option + " is not supported by " + command_name(command),
)
}
if seen.contains(option) {
raise Invalid("duplicate option: " + option)
}
seen[option] = true
match option {
"--json" => json = true
"--dry-run" => dry_run = true
"--cache" => cache = true
_ => {
if index + 1 >= args.length() || args[index + 1].has_prefix("--") {
raise Invalid("missing value for " + option)
}
index += 1
let value = args[index]
if value == "" {
raise Invalid("empty value for " + option)
}
match option {
"--config" => config = value
"--sdk" => sdk = Some(value)
"--abi" => abis = parse_abis(value)
"--out" => output = value
_ => raise Invalid("unknown option: " + option)
}
}
}
index += 1
}
if command == Build && sdk is None {
raise Invalid("build requires --sdk ")
}
{ command, config, sdk, abis, output, json, dry_run, cache, }
}
///|
pub fn success_report(command : String, result : Json) -> Json {
{ "command": command, "ok": true, "exitCode": 0, "result": result }
}
///|
pub fn failure_report(
command : String,
diagnostic : Diagnostic,
parameter? : Bool = false,
) -> Json {
{
"command": command,
"ok": false,
"exitCode": if parameter {
2
} else {
3
},
"diagnostics": [diagnostic.to_json()].to_json(),
}
}
///|
#deprecated
pub extend Command with Eq::{equal, not_equal}
///|
#deprecated
pub extend Command with @debug.Debug::{to_repr}