///|
fn usage() -> Unit {
println("MoonSpell " + @lib.version())
println("Usage:")
println(" moonspell validate ")
println(" moonspell check ...")
println(" moonspell suggest [--limit N]")
println(" moonspell check-file ")
println(" moonspell suggest-file [--limit N]")
println(" moonspell stem ")
println(" moonspell analyze [--format text|json]")
println(
" moonspell explain [--limit N] [--format text|json]",
)
}
///|
fn read_file(path : String) -> String? {
Some(@lib.strip_bom(@fs.read_file_to_string(path))) catch {
_ => None
}
}
///|
fn read_bytes(path : String) -> Bytes? {
Some(@fs.read_file_to_bytes(path)) catch {
_ => None
}
}
///|
fn parse_limit(args : Array[String]) -> Int {
for i in 5.. String {
for i in 5.. (@lib.AffixConfig, @lib.Dictionary)? {
let aff_encoding = match read_bytes(aff_path) {
Some(bytes) => @lib.detect_aff_encoding(bytes)
None => {
println("Failed to read affix file: " + aff_path)
return None
}
}
let aff_text = match read_bytes(aff_path) {
Some(bytes) => @lib.decode_bytes(bytes, aff_encoding)
None => {
println("Failed to read affix file: " + aff_path)
return None
}
}
let config = match @lib.parse_aff(aff_text) {
Ok(value) => value
Err(_) => {
println("Failed to parse affix file: " + aff_path)
return None
}
}
let dictionary = match read_bytes(dic_path) {
Some(bytes) => {
let dic_text = @lib.decode_bytes(bytes, aff_encoding)
match @lib.parse_dic(dic_text) {
Ok(value) => value
Err(_) => {
println("Failed to parse dictionary file: " + dic_path)
return None
}
}
}
None => {
println("Failed to read dictionary file: " + dic_path)
return None
}
}
Some((config, dictionary))
}
///|
fn validate(args : Array[String]) -> Unit {
if args.length() < 4 {
usage()
return
}
match load(args[2], args[3]) {
Some((config, dictionary)) => {
println(
"affix directives parsed: " +
config.prefixes.length().to_string() +
" prefixes, " +
config.suffixes.length().to_string() +
" suffixes",
)
println(
"dictionary entries parsed: " + dictionary.entries.length().to_string(),
)
}
None => ()
}
}
///|
fn check(args : Array[String]) -> Unit {
if args.length() < 5 {
usage()
return
}
match load(args[2], args[3]) {
Some((config, dictionary)) =>
for i in 4.. ()
}
}
///|
fn suggest(args : Array[String]) -> Unit {
if args.length() < 5 {
usage()
return
}
match load(args[2], args[3]) {
Some((config, dictionary)) => {
let word = args[4]
let limit = parse_limit(args)
let suggestions = @lib.suggest(dictionary, config, word, limit)
if suggestions.length() == 0 {
println("No suggestions")
} else {
for suggestion in suggestions {
println(suggestion.word + " " + suggestion.distance.to_string())
}
}
}
None => ()
}
}
///|
fn check_file(args : Array[String]) -> Unit {
if args.length() < 5 {
usage()
return
}
match load(args[2], args[3]) {
Some((config, dictionary)) => {
let text = match read_file(args[4]) {
Some(value) => value
None => {
println("Failed to read word file: " + args[4])
return
}
}
for line in text.split("\n") {
let word = line.trim().to_owned()
if !word.is_empty() {
let status = if @lib.spell(dictionary, config, word).accepted {
"accepted"
} else {
"rejected"
}
println(word + "\t" + status)
}
}
}
None => ()
}
}
///|
fn suggest_file(args : Array[String]) -> Unit {
if args.length() < 5 {
usage()
return
}
match load(args[2], args[3]) {
Some((config, dictionary)) => {
let text = match read_file(args[4]) {
Some(value) => value
None => {
println("Failed to read word file: " + args[4])
return
}
}
let limit = parse_limit(args)
for line in text.split("\n") {
let word = line.trim().to_owned()
if !word.is_empty() {
let suggestions = @lib.suggest(dictionary, config, word, limit)
let words : Array[String] = []
for suggestion in suggestions {
words.push(suggestion.word)
}
println(word + "\t" + words.join(", "))
}
}
}
None => ()
}
}
///|
fn stem_cmd(args : Array[String]) -> Unit {
if args.length() < 5 {
usage()
return
}
match load(args[2], args[3]) {
Some((config, dictionary)) =>
match @lib.stem(dictionary, config, args[4]) {
Some(value) => println(value)
None => println("No stem")
}
None => ()
}
}
///|
fn analyze_cmd(args : Array[String]) -> Unit {
if args.length() < 5 {
usage()
return
}
match load(args[2], args[3]) {
Some((config, dictionary)) => {
let items = @lib.analyze(dictionary, config, args[4])
if parse_format(args) == "json" {
println(@lib.analyses_to_json(items))
} else if items.length() == 0 {
println("No analysis")
} else {
for item in items {
let stem = match item.stem {
Some(value) => value
None => "-"
}
println(stem + "\tflags=" + item.flags + "\tmorph=" + item.morphology)
}
}
}
None => ()
}
}
///|
fn explain_cmd(args : Array[String]) -> Unit {
if args.length() < 5 {
usage()
return
}
match load(args[2], args[3]) {
Some((config, dictionary)) => {
let limit = parse_limit(args)
let item = @lib.explain(dictionary, config, args[4], limit)
if parse_format(args) == "json" {
println(@lib.explanation_to_json(item))
} else {
for step in item.steps {
println(step)
}
for suggestion in item.suggestions {
println("suggest: " + suggestion.word)
}
}
}
None => ()
}
}
///|
fn main {
let args = @env.args()
if args.length() < 2 {
usage()
return
}
match args[1] {
"validate" => validate(args)
"check" => check(args)
"suggest" => suggest(args)
"check-file" => check_file(args)
"suggest-file" => suggest_file(args)
"stem" => stem_cmd(args)
"analyze" => analyze_cmd(args)
"explain" => explain_cmd(args)
"version" | "--version" | "-v" => println("MoonSpell " + @lib.version())
_ => usage()
}
}