use std::collections::HashMap;
use crate::auxiliary;
use crate::errors::LibError;
use crate::input;
use crate::ops;
use crate::config::Configuration;
use crate::output::{Output,OutputValue};
use crate::range;
use crate::ColorScheme;
pub fn list_all_ops(_conf: &Configuration) -> Output {
let mut results = HashMap::new();
for (fn_name, fn_desc, _, _, _, _) in ops::INDEX {
results.insert(OutputValue::from_str(fn_name()), OutputValue::from_str(fn_desc()));
}
Output::Association { data: results, notes: vec![] }
}
pub fn list_matching_ops(conf: &Configuration, args: &input::Args) -> Vec<(&'static str, &'static str)> {
let mut fns = vec![];
for (fn_name, fn_desc, _fn_usage, fn_args, fn_priority, _fn_impl) in ops::INDEX {
if !fn_args().has(args.len()) {
continue;
}
if let Ok(prio) = fn_priority(args, conf) {
if prio > 0.0 && !prio.is_nan() {
fns.push((fn_name(), fn_desc(), prio));
}
}
}
fns.sort_by_key(|e| (-1000.0 * e.2) as i32);
fns.iter().map(|e| { (e.0, e.1) }).collect::<Vec<(&'static str, &'static str)>>()
}
pub fn run_op(conf: &Configuration, args: &input::Args, op_name: &str) -> Result<(&'static str, Output), LibError> {
if let Some((name, usage, acceptable_range)) = find_op_by_exact_name(conf, args, op_name) {
if !acceptable_range.has(args.len()) {
return Err(LibError::ArgumentCountError(acceptable_range, args.len(), Some(usage.to_owned())));
}
return Ok((name, run_op_by_name(conf, args, op_name)?));
}
let mut names_and_similarity = vec![];
for (fn_name, _, _, _, _, _) in ops::INDEX {
names_and_similarity.push((fn_name(), auxiliary::string_similarity(fn_name(), op_name)));
}
names_and_similarity.sort_by_key(|e| (1000.0 * e.1) as i32);
if let Some((last, _)) = names_and_similarity.last() {
eprintln!("Did you mean ‘{}’?", last);
}
Err(LibError::UnknownOp(op_name.to_owned()))
}
fn find_op_by_exact_name(_conf: &Configuration, _args: &input::Args, op_name: &str) -> Option<(&'static str, &'static str, range::Range)> {
for (fn_name, _fn_desc, fn_usage, fn_args, _fn_priority, _fn_impl) in ops::INDEX {
if fn_name() != op_name {
continue;
}
return Some((fn_name(), fn_usage(), fn_args()));
}
None
}
fn run_op_by_name(conf: &Configuration, args: &input::Args, op_name: &str) -> Result<Output, LibError> {
for (fn_name, _fn_desc, _fn_usage, _fn_args, _fn_priority, fn_impl) in ops::INDEX {
if fn_name() != op_name {
continue;
}
return fn_impl(args, conf);
}
Err(LibError::UnknownOp(op_name.to_owned()))
}
pub fn run_matching_ops(conf: &Configuration, args: &input::Args) -> Result<(), LibError> {
let mut priority_per_function: Vec<(&'static str, f32)> = vec![];
for (fn_name, _fn_desc, _fn_usage, fn_args, fn_priority, _fn_impl) in ops::INDEX {
let name: &'static str = fn_name();
if !fn_args().has(args.len()) {
continue;
}
if let Ok(prio) = fn_priority(args, conf) {
if prio > 0.0 && !prio.is_nan() {
priority_per_function.push((name, prio));
}
}
}
priority_per_function.sort_by(|a, b| a.1.partial_cmp(&b.1).unwrap().reverse());
for (op_name, _) in priority_per_function {
conf.color_scheme.op_section(op_name)?;
for (fn_name, _fn_desc, _fn_usage, _fn_args, _fn_priority, fn_impl) in ops::INDEX {
let name: &'static str = fn_name();
if name != op_name {
continue;
}
match fn_impl(args, conf) {
Ok(output) => { output.print(conf)?; },
Err(e) => {
conf.color_scheme.error_label("ERROR")?;
eprintln!(": {}", e);
},
}
}
}
Ok(())
}
pub fn list_color_schemes(_conf: &Configuration) -> Result<Output, LibError> {
let mut cs_list = vec![];
for cs in ColorScheme::all_as_slice() {
cs_list.push(OutputValue::from_str(&cs.to_string()));
}
Ok(Output::HomogeneousList { data: cs_list, notes: vec![] })
}