extern crate simpla_vortaro as sv;
extern crate clap;
extern crate colored;
extern crate itertools;
extern crate textwrap;
use clap::{App, Arg};
use colored::Colorize;
use itertools::Itertools;
use textwrap::{Wrapper, termwidth};
use std::borrow::Cow;
use std::iter;
fn main() {
let cli = App::new("sv")
.version("0.1.0")
.author("panicbit <panicbit.dev@gmail.com>")
.arg(Arg::with_name("VORTO")
.required(true)
.index(1)
.help("La vorton kion vi volas serĉi")
)
.arg(Arg::with_name("difinu")
.short("d")
.long("difinu")
.help("Akiri difino de VORTO anstataŭ serĉi ĝin")
)
.get_matches();
let vorto = cli.value_of("VORTO").unwrap();
let mut width = termwidth();
if width >= 2 {
width -= 2;
}
let res = match cli.is_present("difinu") {
false => sercxi(vorto, width),
true => difinu(vorto, width),
};
if let Err(e) = res {
println!("{}", e);
}
}
fn print_header(text: &str) {
println!("\n{}", text.bold());
}
fn sercxi(vorto: &str, width: usize) -> sv::Result<()> {
let trovo = sv::trovi(vorto)?;
if !trovo.preciza.is_empty() {
print_header(" Preciza serĉo");
println!();
for preciza in &trovo.preciza {
println!(" {}", preciza.bold().bright_green());
}
}
if !trovo.malpreciza.is_empty() {
let initial_indent = create_indent(4);
let subsequent_indent = create_indent(4);
let mut wrapper = Wrapper::new(width);
wrapper.initial_indent = &initial_indent;
wrapper.subsequent_indent = &subsequent_indent;
print_header(" Malpreciza serĉo");
println!();
let mut vortoj = trovo.malpreciza.iter().map(|v| v.bold().bright_green());
let text = format!("{}", vortoj.join(", "));
for text in wrapper.wrap_iter(&text) {
println!("{}", text);
}
}
if !trovo.vortfarado.is_empty() {
print_header(" Vortfarada serĉo");
println!();
for vortfarado in &trovo.vortfarado {
let rezulto = vortfarado.rezulto.green();
let mut partoj = vortfarado.partoj.iter().flat_map(|p| &p.vorto).map(|v| v.bold().bright_green());
println!(" {} ({})", rezulto, partoj.join(", "));
}
}
if !trovo.tradukoj.is_empty() {
print_header(" Alialingva serĉo");
}
print_translations(&trovo.tradukoj, 4, width);
println!();
Ok(())
}
fn create_indent(len: usize) -> Cow<'static, str> {
const INDENT: &str = " ";
if len <= INDENT.len() {
return INDENT[..len].into()
}
iter::repeat(' ').take(len).collect()
}
fn difinu(vorto: &str, width: usize) -> sv::Result<()> {
let mut width_l1 = width;
let mut width_l2 = width;
if width_l1 > 2 { width_l1 -= 2 }
if width_l2 > 4 { width_l2 -= 4 }
let vorto = match sv::vorto(vorto)? {
None => return Ok(()),
Some(vorto) => vorto,
};
println!();
for (i, difino) in vorto.difinoj.iter().enumerate() {
let i = i + 1;
let index = format!("{}. ", i);
let text = format!("{}{}", index, difino.difino.as_ref().map(|s| &**s).unwrap_or(""));
let subsequent_indent = create_indent(2 + index.chars().count());
let mut wrapper = Wrapper::new(width_l1);
wrapper.initial_indent = " ";
wrapper.subsequent_indent = &subsequent_indent;
for (i, text) in wrapper.wrap_iter(&text).enumerate() {
let mut text = text.as_ref();
if i == 0 {
let pivot = wrapper.initial_indent.len() + index.len();
let (index, rest) = text.split_at(pivot);
print!("{}", index.bold().bright_green());
text = rest;
}
println!("{}", text);
}
print_examples(&difino.ekzemploj, index.chars().count() + 2, width);
print_translations(&difino.tradukoj, index.chars().count() + 2, width);
for (j, pludifino) in difino.pludifinoj.iter().enumerate() {
let j = j + 1;
let initial_indent = create_indent(2 + index.chars().count());
let index = format!("{}.{}. ", i, j);
let text = format!("{}{}", index, pludifino.difino);
let subsequent_indent = create_indent(initial_indent.chars().count() + index.chars().count());
let mut wrapper = Wrapper::new(width_l2);
wrapper.initial_indent = &initial_indent;
wrapper.subsequent_indent = &subsequent_indent;
println!();
for (i, text) in wrapper.wrap_iter(&text).enumerate() {
let mut text = text.as_ref();
if i == 0 {
let pivot = wrapper.initial_indent.len() + index.len();
let (index, rest) = text.split_at(pivot);
print!("{}", index.bold().magenta());
text = rest;
}
println!("{}", text);
}
print_examples(&pludifino.ekzemploj, index.chars().count() + 2, width);
}
println!();
}
Ok(())
}
fn print_translations(tradukoj: &[sv::Traduko], indent: usize, width: usize) {
if !tradukoj.is_empty() {
let tradukoj = tradukoj.iter().sorted_by_key(|tra| tra.lingvo.clone());
let tradukoj = tradukoj.iter().group_by(|tra| &tra.lingvo);
let indent = create_indent(indent);
println!();
for (lingvo, traduko) in &tradukoj {
let mut vortoj = traduko.map(|tra| if let Some(ref vorto) = tra.vorto {
format!("{} ({})", vorto.bold().bright_green(), tra.traduko.bold().magenta())
} else {
format!("{}", tra.traduko.bold().magenta())
});
println!("{}{}: {}", indent, lingvo, vortoj.join(", "));
}
}
}
fn print_examples(ekzemploj: &[sv::Ekzemplo], indent: usize, width: usize) {
if !ekzemploj.is_empty() {
let initial_indent = create_indent(indent);
let subsequent_indent = create_indent(indent + 2);
let mut wrapper = Wrapper::new(width);
wrapper.initial_indent = &initial_indent;
wrapper.subsequent_indent = &subsequent_indent;
println!();
for ekzemplo in ekzemploj {
use std::fmt::Write;
let mut text = format!("- {}", ekzemplo.ekzemplo);
if let Some(ref fonto) = ekzemplo.fonto {
write!(text, " [{}]", fonto).unwrap();
}
for text in wrapper.wrap_iter(&text) {
println!("{}", text.blue());
}
}
}
}