GREATLY improve autocomplete tests + fix known autocomplete issues

This commit is contained in:
Simon Gardling 2022-04-12 10:04:14 -04:00
parent e7d30e7213
commit 2e0569fe2e
4 changed files with 149 additions and 68 deletions

View File

@ -91,7 +91,7 @@ impl FunctionEntry {
self.autocomplete.ui(ui, i); self.autocomplete.ui(ui, i);
let output_string = self.autocomplete.string.clone(); let output_string = self.autocomplete.string.clone();
self.update_string(output_string.as_str()); self.update_string(&output_string);
} }
/// Get function's cached test result /// Get function's cached test result

View File

@ -326,15 +326,11 @@ impl MathApp {
#[cfg(not(threading))] #[cfg(not(threading))]
tracing::info!("Threading: Disabled"); tracing::info!("Threading: Disabled");
tracing::info!( tracing::info!("Integration name: {}", cc.integration_info.name);
"Integration name: {} Url: {:?}",
cc.integration_info.name, if let Some(url) = &cc.integration_info.web_info {
if let Some(url) = &cc.integration_info.web_info { tracing::info!("Url: {:?}", url);
&url.location.url }
} else {
"N/A"
}
);
tracing::info!("egui app initialized."); tracing::info!("egui app initialized.");
Self::default() // initialize `MathApp` Self::default() // initialize `MathApp`

View File

@ -98,6 +98,7 @@ mod tests {
("cos", HintEnum::Many(&["(", "h("])), ("cos", HintEnum::Many(&["(", "h("])),
("sin(", HintEnum::Single(")")), ("sin(", HintEnum::Single(")")),
("sqrt", HintEnum::Single("(")), ("sqrt", HintEnum::Single("(")),
("ln(x)", HintEnum::None),
]); ]);
for (key, value) in values { for (key, value) in values {

View File

@ -35,6 +35,7 @@ impl<'a> Default for AutoComplete<'a> {
impl<'a> AutoComplete<'a> { impl<'a> AutoComplete<'a> {
pub fn update(&mut self, string: &str) { pub fn update(&mut self, string: &str) {
if &self.string != string { if &self.string != string {
self.i = 0;
self.string = string.to_string(); self.string = string.to_string();
self.hint = generate_hint(string); self.hint = generate_hint(string);
} }
@ -48,7 +49,7 @@ impl<'a> AutoComplete<'a> {
match self.hint { match self.hint {
HintEnum::Many(hints) => { HintEnum::Many(hints) => {
if movement == &Movement::Complete { if movement == &Movement::Complete {
self.string += hints[self.i]; self.apply_hint(hints[self.i]);
return; return;
} }
@ -72,24 +73,33 @@ impl<'a> AutoComplete<'a> {
} }
HintEnum::Single(hint) => { HintEnum::Single(hint) => {
if movement == &Movement::Complete { if movement == &Movement::Complete {
self.string += hint; self.apply_hint(hint);
} }
} }
HintEnum::None => {} HintEnum::None => {}
} }
} }
fn apply_hint(&mut self, hint: &str) {
let new_string = self.string.clone() + hint;
self.update(&new_string);
}
pub fn ui(&mut self, ui: &mut egui::Ui, func_i: i32) { pub fn ui(&mut self, ui: &mut egui::Ui, func_i: i32) {
let mut movement: Movement = Movement::default(); let mut movement: Movement = Movement::default();
let mut func_edit = egui::TextEdit::singleline(&mut self.string) let mut new_string = self.string.clone();
.hint_forward(true) // Make the hint appear after the last text in the textbox
.lock_focus(true);
let te_id = ui.make_persistent_id(format!("text_edit_ac_{}", func_i)); let te_id = ui.make_persistent_id(format!("text_edit_ac_{}", func_i));
let mut func_edit = egui::TextEdit::singleline(&mut new_string)
.hint_forward(true) // Make the hint appear after the last text in the textbox
.lock_focus(true)
.id(te_id);
if self.hint.is_none() { if self.hint.is_none() {
let _ = func_edit.id(te_id).ui(ui); let _ = func_edit.ui(ui);
self.update(&new_string);
return; return;
} }
@ -104,7 +114,9 @@ impl<'a> AutoComplete<'a> {
func_edit = func_edit.hint_text(*single_hint); func_edit = func_edit.hint_text(*single_hint);
} }
let re = func_edit.id(te_id).ui(ui); let re = func_edit.ui(ui);
self.update(&new_string);
if !self.hint.is_single() { if !self.hint.is_single() {
if ui.input().key_pressed(Key::ArrowDown) { if ui.input().key_pressed(Key::ArrowDown) {
@ -132,7 +144,7 @@ impl<'a> AutoComplete<'a> {
}); });
if clicked { if clicked {
self.string += hints[self.i]; self.apply_hint(hints[self.i]);
// don't need this here as it simply won't be display next frame // don't need this here as it simply won't be display next frame
// ui.memory().close_popup(); // ui.memory().close_popup();
@ -164,67 +176,139 @@ impl<'a> AutoComplete<'a> {
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod autocomplete_tests {
use super::*; use super::*;
fn auto_complete_helper(string: &str, movement: Movement) -> (AutoComplete, String) { enum Action<'a> {
let mut auto_complete = AutoComplete::default(); AssertI(usize),
auto_complete.update(string); AssertString(&'a str),
auto_complete.interact_back(&movement); AssertHint(&'a str),
SetString(&'a str),
Move(Movement),
}
let output_string = auto_complete.clone().string; fn ac_tester(actions: &[Action]) {
(auto_complete, output_string) let mut ac = AutoComplete::default();
for action in actions.iter() {
match action {
Action::AssertI(target_i) => {
if &ac.i != target_i {
panic!(
"AssertI failed: Current: '{}' Expected: '{}'",
ac.i, target_i
)
}
}
Action::AssertString(target_string) => {
if &ac.string != target_string {
panic!(
"AssertString failed: Current: '{}' Expected: '{}'",
ac.string, target_string
)
}
}
Action::AssertHint(target_hint) => match ac.hint {
HintEnum::None => {
if !target_hint.is_empty() {
panic!(
"AssertHint failed on `HintEnum::None`: Expected: {}",
target_hint
);
}
}
HintEnum::Many(hints) => {
let hint = hints[ac.i];
if &hint != target_hint {
panic!(
"AssertHint failed on `HintEnum::Many`: Current: '{}' (index: {}) Expected: '{}'",
hint, ac.i, target_hint
)
}
}
HintEnum::Single(hint) => {
if hint != target_hint {
panic!(
"AssertHint failed on `HintEnum::Single`: Current: '{}' Expected: '{}'",
hint, target_hint
)
}
}
},
Action::SetString(target_string) => {
ac.update(target_string);
}
Action::Move(target_movement) => {
ac.interact_back(target_movement);
}
}
}
} }
#[test] #[test]
fn auto_complete_single_still() { fn single() {
let (_, string) = auto_complete_helper("", Movement::None); ac_tester(&[
Action::SetString(""),
assert_eq!(&*string, ""); Action::AssertHint("x^2"),
Action::Move(Movement::Up),
Action::AssertI(0),
Action::AssertString(""),
Action::AssertHint("x^2"),
Action::Move(Movement::Down),
Action::AssertI(0),
Action::AssertString(""),
Action::AssertHint("x^2"),
Action::Move(Movement::Complete),
Action::AssertString("x^2"),
Action::AssertHint(""),
Action::AssertI(0),
]);
} }
#[test] #[test]
fn auto_complete_single_complete() { fn multi() {
let (_, string) = auto_complete_helper("", Movement::Complete); ac_tester(&[
Action::SetString("s"),
assert_eq!(&*string, "x^2"); Action::AssertHint("in("),
Action::Move(Movement::Up),
Action::AssertI(3),
Action::AssertString("s"),
Action::AssertHint("ignum("),
Action::Move(Movement::Down),
Action::AssertI(0),
Action::AssertString("s"),
Action::AssertHint("in("),
Action::Move(Movement::Down),
Action::AssertI(1),
Action::AssertString("s"),
Action::AssertHint("qrt("),
Action::Move(Movement::Up),
Action::AssertI(0),
Action::AssertString("s"),
Action::AssertHint("in("),
Action::Move(Movement::Complete),
Action::AssertString("sin("),
Action::AssertHint(")"),
Action::AssertI(0),
]);
} }
#[test] #[test]
fn auto_complete_single_down() { fn parens() {
let (_, string) = auto_complete_helper("", Movement::Down); ac_tester(&[
Action::SetString("sin(x"),
assert_eq!(&*string, ""); Action::AssertHint(")"),
} Action::Move(Movement::Up),
Action::AssertI(0),
#[test] Action::AssertString("sin(x"),
fn auto_complete_single_up() { Action::AssertHint(")"),
let (_, string) = auto_complete_helper("", Movement::Up); Action::Move(Movement::Down),
Action::AssertI(0),
assert_eq!(&*string, ""); Action::AssertString("sin(x"),
} Action::AssertHint(")"),
Action::Move(Movement::Complete),
#[test] Action::AssertString("sin(x)"),
fn auto_complete_multi_up() { Action::AssertHint(""),
let (auto_complete, string) = auto_complete_helper("s", Movement::Up); Action::AssertI(0),
]);
assert!(auto_complete.i > 0);
assert_eq!(&*string, "s");
}
#[test]
fn auto_complete_multi_down() {
let (auto_complete, string) = auto_complete_helper("s", Movement::Down);
assert_eq!(auto_complete.i, 1);
assert_eq!(&*string, "s");
}
#[test]
fn auto_complete_multi_complete() {
let (auto_complete, string) = auto_complete_helper("s", Movement::Complete);
assert_eq!(auto_complete.i, 0);
assert_eq!(&*string, "sin(");
} }
} }