diff --git a/parsing/src/lib.rs b/parsing/src/lib.rs index 0c5e32b..c588ba9 100644 --- a/parsing/src/lib.rs +++ b/parsing/src/lib.rs @@ -11,7 +11,7 @@ pub use crate::{ autocomplete_helper::compile_hashmap, parsing::{process_func_str, BackingFunction}, suggestions::{ - generate_hint, get_last_term, split_function, split_function_chars, Hint, HINT_EMPTY, - SUPPORTED_FUNCTIONS, + generate_hint, get_last_term, split_function, split_function_chars, AutoComplete, Hint, + Movement, HINT_EMPTY, SUPPORTED_FUNCTIONS, }, }; diff --git a/parsing/src/suggestions.rs b/parsing/src/suggestions.rs index ad9da8c..70d6ffa 100644 --- a/parsing/src/suggestions.rs +++ b/parsing/src/suggestions.rs @@ -253,3 +253,110 @@ impl<'a> Hint<'a> { } include!(concat!(env!("OUT_DIR"), "/codegen.rs")); + +#[derive(PartialEq, Debug)] +pub enum Movement { + Complete, + #[allow(dead_code)] + Down, + #[allow(dead_code)] + Up, + None, +} + +impl Movement { + pub const fn is_none(&self) -> bool { matches!(&self, Self::None) } +} + +impl const Default for Movement { + fn default() -> Self { Self::None } +} + +#[derive(Clone)] +pub struct AutoComplete<'a> { + pub i: usize, + pub hint: &'a Hint<'a>, + pub string: String, +} + +impl<'a> const Default for AutoComplete<'a> { + fn default() -> AutoComplete<'a> { AutoComplete::EMPTY } +} + +impl<'a> AutoComplete<'a> { + const EMPTY: AutoComplete<'a> = Self { + i: 0, + hint: &HINT_EMPTY, + string: String::new(), + }; + + #[allow(dead_code)] + pub fn update_string(&mut self, string: &str) { + if self.string != string { + // catch empty strings here to avoid call to `generate_hint` and unnecessary logic + if string.is_empty() { + *self = Self::EMPTY; + } else { + self.string = string.to_owned(); + self.do_update_logic(); + } + } + } + + /// Runs update logic assuming that a change to `self.string` has been made + fn do_update_logic(&mut self) { + self.i = 0; + self.hint = generate_hint(&self.string); + } + + #[allow(dead_code)] + pub fn register_movement(&mut self, movement: &Movement) { + if movement.is_none() { + return; + } + + match self.hint { + Hint::Many(hints) => { + // Impossible for plural hints to be singular or non-existant + unsafe { + assume(hints.len() > 1); + assume(!hints.is_empty()); + } + + match movement { + Movement::Up => { + // if self.i is below 1, it's at + match self.i { + 0 => self.i = hints.len() - 1, + _ => self.i -= 1, + } + } + Movement::Down => { + // add one, if resulting value is above maximum i value, set i to 0 + self.i += 1; + if self.i > (hints.len() - 1) { + self.i = 0; + } + } + Movement::Complete => { + unsafe { assume(hints.len() >= (self.i + 1)) } + + self.apply_hint(hints[self.i]); + } + _ => unreachable!(), + } + } + Hint::Single(hint) => { + if movement == &Movement::Complete { + self.apply_hint(hint); + } + } + _ => unreachable!(), + } + } + + pub fn apply_hint(&mut self, hint: &str) { + self.string.push_str(hint); + self.do_update_logic(); + } +} diff --git a/src/function_entry.rs b/src/function_entry.rs index cbcef0c..d90f260 100644 --- a/src/function_entry.rs +++ b/src/function_entry.rs @@ -2,13 +2,13 @@ use crate::math_app::AppSettings; use crate::misc::*; -use crate::widgets::AutoComplete; use egui::{ plot::{BarChart, PlotUi, Value}, widgets::plot::Bar, Checkbox, Context, }; use epaint::Color32; +use parsing::AutoComplete; use parsing::{process_func_str, BackingFunction}; use std::{ fmt::{self, Debug}, diff --git a/src/function_manager.rs b/src/function_manager.rs index 50f8f6f..470f4bd 100644 --- a/src/function_manager.rs +++ b/src/function_manager.rs @@ -1,9 +1,10 @@ use crate::consts::is_mobile; use crate::function_entry::FunctionEntry; -use crate::widgets::{widgets_ontop, Movement}; +use crate::widgets::widgets_ontop; use egui::{Button, Id, Key, Modifiers, TextEdit, WidgetText}; use emath::vec2; use parsing::Hint; +use parsing::Movement; use std::ops::BitXorAssign; use uuid::Uuid; diff --git a/src/lib.rs b/src/lib.rs index f871d62..f787792 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,7 +27,6 @@ pub use crate::{ decimal_round, option_vec_printer, resolution_helper, storage_create, storage_read, SteppedVector, }, - widgets::{AutoComplete, Movement}, }; cfg_if::cfg_if! { diff --git a/src/widgets.rs b/src/widgets.rs index b8eaeae..809e702 100644 --- a/src/widgets.rs +++ b/src/widgets.rs @@ -1,111 +1,3 @@ -use std::intrinsics::assume; - -use parsing::{generate_hint, Hint, HINT_EMPTY}; - -#[derive(PartialEq, Debug)] -pub enum Movement { - Complete, - Down, - Up, - None, -} - -impl Movement { - pub const fn is_none(&self) -> bool { matches!(&self, Self::None) } -} - -impl const Default for Movement { - fn default() -> Self { Self::None } -} - -#[derive(Clone)] -pub struct AutoComplete<'a> { - pub i: usize, - pub hint: &'a Hint<'a>, - pub string: String, -} - -impl<'a> const Default for AutoComplete<'a> { - fn default() -> AutoComplete<'a> { AutoComplete::EMPTY } -} - -impl<'a> AutoComplete<'a> { - const EMPTY: AutoComplete<'a> = Self { - i: 0, - hint: &HINT_EMPTY, - string: String::new(), - }; - - #[allow(dead_code)] - pub fn update_string(&mut self, string: &str) { - if self.string != string { - // catch empty strings here to avoid call to `generate_hint` and unnecessary logic - if string.is_empty() { - *self = Self::EMPTY; - } else { - self.string = string.to_owned(); - self.do_update_logic(); - } - } - } - - /// Runs update logic assuming that a change to `self.string` has been made - fn do_update_logic(&mut self) { - self.i = 0; - self.hint = generate_hint(&self.string); - } - - pub fn register_movement(&mut self, movement: &Movement) { - if movement.is_none() { - return; - } - - match self.hint { - Hint::Many(hints) => { - // Impossible for plural hints to be singular or non-existant - unsafe { - assume(hints.len() > 1); - assume(!hints.is_empty()); - } - - match movement { - Movement::Up => { - // if self.i is below 1, it's at - match self.i { - 0 => self.i = hints.len() - 1, - _ => self.i -= 1, - } - } - Movement::Down => { - // add one, if resulting value is above maximum i value, set i to 0 - self.i += 1; - if self.i > (hints.len() - 1) { - self.i = 0; - } - } - Movement::Complete => { - unsafe { assume(hints.len() >= (self.i + 1)) } - - self.apply_hint(hints[self.i]); - } - _ => unreachable!(), - } - } - Hint::Single(hint) => { - if movement == &Movement::Complete { - self.apply_hint(hint); - } - } - _ => unreachable!(), - } - } - - pub fn apply_hint(&mut self, hint: &str) { - self.string.push_str(hint); - self.do_update_logic(); - } -} - pub fn widgets_ontop( ui: &egui::Ui, id: String, re: &egui::Response, y_offset: f32, add_contents: impl FnOnce(&mut egui::Ui) -> R, diff --git a/tests/autocomplete.rs b/tests/autocomplete.rs index 45ad833..9bdc227 100644 --- a/tests/autocomplete.rs +++ b/tests/autocomplete.rs @@ -1,5 +1,4 @@ -use parsing::Hint; -use ytbn_graphing_software::{AutoComplete, Movement}; +use parsing::{AutoComplete, Hint, Movement}; enum Action<'a> { AssertIndex(usize),