///|
/// Command-line options for the governance report executable.
struct CliOptions {
mut input : String?
mut format : String
mut dataset_name : String
mut task : @core.TaskType
mut schema_labels : Array[String]
}
///|
fn split_schema(value : String) -> Array[String] {
let labels = []
for item in value.split(",") {
let label = item.trim().to_owned()
if label != "" {
labels.push(label)
}
}
labels
}
///|
fn default_options() -> CliOptions {
{
input: None,
format: "demo",
dataset_name: "MoonLabelKit_Dataset",
task: @core.TaskType::Classification,
schema_labels: [],
}
}
///|
fn print_help() -> Unit {
println(
(
#|MoonLabelKit data governance CLI
#|
#|Usage:
#| moon run cmd -- --input FILE [options]
#| moon run cmd # run the built-in demo
#|
#|Options:
#| --input FILE JSONL, CSV or TSV file to inspect
#| --format FORMAT auto, jsonl, csv or tsv (default: auto)
#| --name NAME dataset name shown in the report
#| --task TASK classification or sequence (JSONL only)
#| --schema A,B,C allowed labels used for schema checks
#| --help show this help
),
)
}
///|
fn parse_cli(args : Array[String]) -> CliOptions? {
let options = default_options()
let mut index = 1
while index < args.length() {
let arg = args[index]
if arg == "--help" || arg == "-h" {
print_help()
return None
} else if arg == "--input" {
if index + 1 >= args.length() {
println("Error: --input requires a file path")
return None
}
options.input = Some(args[index + 1])
options.format = "auto"
index += 2
} else if arg == "--format" {
if index + 1 >= args.length() {
println("Error: --format requires auto, jsonl, csv or tsv")
return None
}
options.format = args[index + 1].to_lower()
index += 2
} else if arg == "--name" {
if index + 1 >= args.length() {
println("Error: --name requires a value")
return None
}
options.dataset_name = args[index + 1]
index += 2
} else if arg == "--task" {
if index + 1 >= args.length() {
println("Error: --task requires classification or sequence")
return None
}
let task = args[index + 1].to_lower()
options.task = if task == "sequence" || task == "sequencelabeling" {
@core.TaskType::SequenceLabeling
} else {
@core.TaskType::Classification
}
index += 2
} else if arg == "--schema" {
if index + 1 >= args.length() {
println("Error: --schema requires a comma-separated label list")
return None
}
options.schema_labels = split_schema(args[index + 1])
index += 2
} else {
println("Error: unknown argument `{arg}`; use --help for usage")
return None
}
}
Some(options)
}
///|
fn infer_format(path : String) -> String {
let lower = path.to_lower()
if lower.has_suffix(".jsonl") || lower.has_suffix(".json") {
"jsonl"
} else if lower.has_suffix(".tsv") {
"tsv"
} else {
"csv"
}
}
///|
fn resolve_format(options : CliOptions, path : String) -> String {
if options.format == "auto" {
infer_format(path)
} else {
options.format
}
}
///|
fn parse_input(
content : String,
options : CliOptions,
format : String,
) -> @core.Dataset raise @core.GovernanceError {
if format == "jsonl" {
@parser.parse_jsonl_dataset(
content,
options.dataset_name,
options.task,
options.schema_labels,
)
} else if format == "csv" || format == "tsv" {
let delimiter = if format == "tsv" { '\t' } else { ',' }
@parser.parse_tabular_dataset(
content,
options.dataset_name,
options.schema_labels,
delimiter~,
)
} else {
raise @core.GovernanceError::ParserError(
"format must be auto, jsonl, csv or tsv", 0,
)
}
}