YTBN-Graphing-Software/src/suggestions.rs
2022-04-12 10:17:04 -04:00

123 lines
2.6 KiB
Rust

use crate::misc::chars_take;
pub const HINT_EMPTY: Hint = Hint::Single("x^2");
const HINT_CLOSED_PARENS: Hint = Hint::Single(")");
/// Generate a hint based on the input `input`, returns an `Option<String>`
pub fn generate_hint<'a>(input: &str) -> &'a Hint<'a> {
if input.is_empty() {
return &HINT_EMPTY;
}
let chars: Vec<char> = input.chars().collect::<Vec<char>>();
let mut open_parens: usize = 0;
let mut closed_parens: usize = 0;
chars.iter().for_each(|chr| match *chr {
'(' => open_parens += 1,
')' => closed_parens += 1,
_ => {}
});
if open_parens > closed_parens {
return &HINT_CLOSED_PARENS;
}
let len = chars.len();
for key in (1..=MAX_COMPLETION_LEN)
.rev()
.filter(|i| len >= *i)
.map(|i| chars_take(&chars, i))
.filter(|cut_string| !cut_string.is_empty())
{
if let Some(output) = COMPLETION_HASHMAP.get(&key) {
return output;
}
}
&Hint::None
}
#[derive(PartialEq)]
pub enum Hint<'a> {
Single(&'a str),
Many(&'a [&'a str]),
None,
}
impl<'a> std::fmt::Debug for Hint<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self) }
}
impl<'a> std::fmt::Display for Hint<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Hint::Single(single_data) => {
return write!(f, "{}", single_data);
}
Hint::Many(multi_data) => {
return write!(f, "{:?}", multi_data);
}
Hint::None => {
return write!(f, "None");
}
}
}
}
impl<'a> Hint<'a> {
pub fn is_none(&self) -> bool { matches!(self, Hint::None) }
#[allow(dead_code)]
pub fn is_some(&self) -> bool { !self.is_none() }
#[allow(dead_code)]
pub fn is_single(&self) -> bool { matches!(self, Hint::Single(_)) }
}
include!(concat!(env!("OUT_DIR"), "/codegen.rs"));
#[cfg(test)]
mod tests {
use std::collections::HashMap;
use super::*;
/// Tests to make sure hints are properly outputed based on input
#[test]
fn hint_test() {
let values = HashMap::from([
("", Hint::Single("x^2")),
("si", Hint::Many(&["n(", "nh(", "gnum("])),
("log", Hint::Many(&["2(", "10("])),
("cos", Hint::Many(&["(", "h("])),
("sin(", Hint::Single(")")),
("sqrt", Hint::Single("(")),
("ln(x)", Hint::None),
]);
for (key, value) in values {
println!("{} + {:?}", key, value);
assert_eq!(generate_hint(key), &value);
}
}
#[test]
fn hint_to_string_test() {
let values = HashMap::from([
("x^2", Hint::Single("x^2")),
(
r#"["n(", "nh(", "gnum("]"#,
Hint::Many(&["n(", "nh(", "gnum("]),
),
(r#"["n("]"#, Hint::Many(&["n("])),
("None", Hint::None),
]);
for (key, value) in values {
assert_eq!(value.to_string(), key);
}
}
}