use crate::buffer::WordAtCaret;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Edit {
pub backspaces: usize,
pub deletes: usize,
pub insert: String,
}
pub fn plan_word_replacement(at: &WordAtCaret, correction: &str) -> Option<Edit> {
if correction == at.word {
return None;
}
let trailing_chars = at.trailing.chars().count();
Some(Edit {
backspaces: at.chars_before_caret + trailing_chars,
deletes: at.chars_after_caret,
insert: format!("{correction}{}", at.trailing),
})
}
#[cfg(test)]
mod tests {
use super::*;
fn word_at_end(word: &str, trailing: &str) -> WordAtCaret {
WordAtCaret {
word: word.to_string(),
trailing: trailing.to_string(),
chars_before_caret: word.chars().count(),
chars_after_caret: 0,
}
}
#[test]
fn replaces_word_and_keeps_the_trailing_space() {
let edit = plan_word_replacement(&word_at_end("vernuer", " "), "veneer").unwrap();
assert_eq!(
edit,
Edit {
backspaces: 8,
deletes: 0,
insert: "veneer ".to_string(),
}
);
}
#[test]
fn replaces_word_with_no_trailing_whitespace() {
let edit = plan_word_replacement(&word_at_end("vernuer", ""), "veneer").unwrap();
assert_eq!(edit.backspaces, 7);
assert_eq!(edit.deletes, 0);
assert_eq!(edit.insert, "veneer");
}
#[test]
fn no_edit_when_the_word_is_already_correct() {
assert_eq!(
plan_word_replacement(&word_at_end("veneer", " "), "veneer"),
None
);
}
#[test]
fn backspace_count_covers_all_trailing_whitespace() {
let edit = plan_word_replacement(&word_at_end("x", " "), "y").unwrap();
assert_eq!(edit.backspaces, 4);
assert_eq!(edit.deletes, 0);
assert_eq!(edit.insert, "y ");
}
#[test]
fn caret_inside_word_splits_into_backspaces_plus_deletes() {
let at = WordAtCaret {
word: "vernuer".to_string(),
trailing: String::new(),
chars_before_caret: 3,
chars_after_caret: 4,
};
let edit = plan_word_replacement(&at, "veneer").unwrap();
assert_eq!(edit.backspaces, 3);
assert_eq!(edit.deletes, 4);
assert_eq!(edit.insert, "veneer");
}
#[test]
fn count_is_in_characters_not_bytes() {
let edit = plan_word_replacement(&word_at_end("café", " "), "coffee").unwrap();
assert_eq!(edit.backspaces, 5);
assert_eq!(edit.insert, "coffee ");
}
}