const TEXT: &str = "first second, third.";
use super::*;
#[test]
fn format() {
let input: Input = TEXT.into();
println!("{}", input);
println!("{}", input);
}
#[test]
fn set_cursor() {
let mut input: Input = TEXT.into();
let req = InputRequest::SetCursor(3);
let resp = input.handle(req);
assert_eq!(
resp,
Some(StateChanged {
value: false,
cursor: true,
})
);
assert_eq!(input.value(), "first second, third.");
assert_eq!(input.cursor(), 3);
let req = InputRequest::SetCursor(30);
let resp = input.handle(req);
assert_eq!(input.cursor(), TEXT.chars().count());
assert_eq!(
resp,
Some(StateChanged {
value: false,
cursor: true,
})
);
let req = InputRequest::SetCursor(TEXT.chars().count());
let resp = input.handle(req);
assert_eq!(input.cursor(), TEXT.chars().count());
assert_eq!(resp, None);
}
#[test]
fn insert_char() {
let mut input: Input = TEXT.into();
let req = InputRequest::InsertChar('x');
let resp = input.handle(req);
assert_eq!(
resp,
Some(StateChanged {
value: true,
cursor: true,
})
);
assert_eq!(input.value(), "first second, third.x");
assert_eq!(input.cursor(), TEXT.chars().count() + 1);
input.handle(req);
assert_eq!(input.value(), "first second, third.xx");
assert_eq!(input.cursor(), TEXT.chars().count() + 2);
let mut input = input.with_cursor(3);
input.handle(req);
assert_eq!(input.value(), "firxst second, third.xx");
assert_eq!(input.cursor(), 4);
input.handle(req);
assert_eq!(input.value(), "firxxst second, third.xx");
assert_eq!(input.cursor(), 5);
}
#[test]
fn go_to_prev_char() {
let mut input: Input = TEXT.into();
let req = InputRequest::GoToPrevChar;
let resp = input.handle(req);
assert_eq!(
resp,
Some(StateChanged {
value: false,
cursor: true,
})
);
assert_eq!(input.value(), "first second, third.");
assert_eq!(input.cursor(), TEXT.chars().count() - 1);
let mut input = input.with_cursor(3);
input.handle(req);
assert_eq!(input.value(), "first second, third.");
assert_eq!(input.cursor(), 2);
input.handle(req);
assert_eq!(input.value(), "first second, third.");
assert_eq!(input.cursor(), 1);
}
#[test]
fn remove_unicode_chars() {
let mut input: Input = "Β‘testΒ‘".into();
let req = InputRequest::DeletePrevChar;
let resp = input.handle(req);
assert_eq!(
resp,
Some(StateChanged {
value: true,
cursor: true,
})
);
assert_eq!(input.value(), "Β‘test");
assert_eq!(input.cursor(), 5);
input.handle(InputRequest::GoToStart);
let req = InputRequest::DeleteNextChar;
let resp = input.handle(req);
assert_eq!(
resp,
Some(StateChanged {
value: true,
cursor: false,
})
);
assert_eq!(input.value(), "test");
assert_eq!(input.cursor(), 0);
}
#[test]
fn insert_unicode_chars() {
let mut input = Input::from("Β‘testΒ‘").with_cursor(5);
let req = InputRequest::InsertChar('β');
let resp = input.handle(req);
assert_eq!(
resp,
Some(StateChanged {
value: true,
cursor: true,
})
);
assert_eq!(input.value(), "Β‘testβΒ‘");
assert_eq!(input.cursor(), 6);
input.handle(InputRequest::GoToStart);
input.handle(InputRequest::GoToNextChar);
let req = InputRequest::InsertChar('β');
let resp = input.handle(req);
assert_eq!(
resp,
Some(StateChanged {
value: true,
cursor: true,
})
);
assert_eq!(input.value(), "Β‘βtestβΒ‘");
assert_eq!(input.cursor(), 2);
}
#[test]
fn multispace_characters() {
let input: Input = "οΌ¨ο½
ο½ο½ο½, ο½ο½ο½ο½ο½!".into();
assert_eq!(input.cursor(), 13);
assert_eq!(input.visual_cursor(), 23);
assert_eq!(input.visual_scroll(6), 18);
}
#[test]
fn yank_delete_line() {
let mut input: Input = TEXT.into();
input.handle(InputRequest::DeleteLine);
assert_eq!(input.value(), "");
assert_eq!(input.cursor(), 0);
assert_eq!(input.yank.as_str(), TEXT);
input.handle(InputRequest::Yank);
assert_eq!(input.value(), TEXT);
assert_eq!(input.cursor(), TEXT.chars().count());
assert_eq!(input.yank.as_str(), TEXT);
}
#[test]
fn yank_delete_till_end() {
let mut input = Input::from(TEXT).with_cursor(6);
input.handle(InputRequest::DeleteTillEnd);
assert_eq!(input.value(), "first ");
assert_eq!(input.cursor(), 6);
assert_eq!(input.yank.as_str(), "second, third.");
input.handle(InputRequest::Yank);
assert_eq!(input.value(), "first second, third.");
assert_eq!(input.cursor(), TEXT.chars().count());
assert_eq!(input.yank.as_str(), "second, third.");
}
#[test]
fn yank_delete_prev_word() {
let mut input = Input::from(TEXT).with_cursor(12);
input.handle(InputRequest::DeletePrevWord);
assert_eq!(input.value(), "first , third.");
assert_eq!(input.yank.as_str(), "second");
input.handle(InputRequest::Yank);
assert_eq!(input.value(), "first second, third.");
assert_eq!(input.yank.as_str(), "second");
}
#[test]
fn yank_delete_next_word() {
let mut input = Input::from(TEXT).with_cursor(6);
input.handle(InputRequest::DeleteNextWord);
assert_eq!(input.value(), "first third.");
assert_eq!(input.yank.as_str(), "second, ");
input.handle(InputRequest::Yank);
assert_eq!(input.value(), "first second, third.");
assert_eq!(input.yank.as_str(), "second, ");
}
#[test]
fn yank_empty() {
let mut input: Input = TEXT.into();
let result = input.handle(InputRequest::Yank);
assert_eq!(result, None);
assert_eq!(input.value(), TEXT);
assert_eq!(input.yank.as_str(), "");
}
#[test]
fn yank_at_middle() {
let mut input = Input::from(TEXT).with_cursor(6);
input.handle(InputRequest::DeleteTillEnd);
assert_eq!(input.value(), "first ");
assert_eq!(input.yank.as_str(), "second, third.");
input.handle(InputRequest::GoToStart);
input.handle(InputRequest::Yank);
assert_eq!(input.value(), "second, third.first ");
assert_eq!(input.cursor(), 14);
assert_eq!(input.yank.as_str(), "second, third.");
}
#[test]
fn yank_consecutive_delete_prev_word() {
let mut input = Input::from(TEXT).with_cursor(TEXT.chars().count());
input.handle(InputRequest::DeletePrevWord);
assert_eq!(input.value(), "first second, ");
assert_eq!(input.yank.as_str(), "third.");
input.handle(InputRequest::DeletePrevWord);
assert_eq!(input.value(), "first ");
assert_eq!(input.yank.as_str(), "second, third.");
input.handle(InputRequest::Yank);
assert_eq!(input.value(), "first second, third.");
}
#[test]
fn yank_consecutive_delete_next_word() {
let mut input = Input::from(TEXT).with_cursor(0);
input.handle(InputRequest::DeleteNextWord);
assert_eq!(input.value(), "second, third.");
assert_eq!(input.yank.as_str(), "first ");
input.handle(InputRequest::DeleteNextWord);
assert_eq!(input.value(), "third.");
assert_eq!(input.yank.as_str(), "first second, ");
input.handle(InputRequest::Yank);
assert_eq!(input.value(), "first second, third.");
}
#[test]
fn yank_insert_breaks_cut_sequence() {
let mut input = Input::from(TEXT).with_cursor(TEXT.chars().count());
input.handle(InputRequest::DeletePrevWord);
assert_eq!(input.yank.as_str(), "third.");
input.handle(InputRequest::InsertChar('x'));
input.handle(InputRequest::DeletePrevChar);
input.handle(InputRequest::DeletePrevWord);
assert_eq!(input.yank.as_str(), "second, ");
}
#[test]
fn yank_mixed_delete_word_and_line() {
let mut input = Input::from(TEXT).with_cursor(6);
input.handle(InputRequest::DeletePrevWord);
assert_eq!(input.value(), "second, third.");
assert_eq!(input.yank.as_str(), "first ");
input.handle(InputRequest::DeleteLine);
assert_eq!(input.value(), "");
assert_eq!(input.yank.as_str(), "first second, third.");
input.handle(InputRequest::Yank);
assert_eq!(input.value(), "first second, third.");
}
#[test]
fn yank_mixed_delete_word_and_line_from_end() {
let mut input = Input::from(TEXT).with_cursor(TEXT.chars().count());
input.handle(InputRequest::DeletePrevWord);
assert_eq!(input.value(), "first second, ");
assert_eq!(input.yank.as_str(), "third.");
input.handle(InputRequest::DeleteLine);
assert_eq!(input.value(), "");
assert_eq!(input.yank.as_str(), "first second, third.");
input.handle(InputRequest::Yank);
assert_eq!(input.value(), "first second, third.");
}
fn walk_grapheme(value: &str, positions: &[usize]) {
let end = *positions.last().unwrap();
let mut input: Input = value.into();
assert_eq!(input.cursor(), end);
for &pos in positions.iter().rev().skip(1) {
input.handle(InputRequest::GoToPrevChar);
assert_eq!(input.cursor(), pos);
}
for &pos in &positions[1..] {
input.handle(InputRequest::GoToNextChar);
assert_eq!(input.cursor(), pos);
}
for &pos in positions.iter().rev().skip(1) {
input.handle(InputRequest::DeletePrevChar);
assert_eq!(input.cursor(), pos);
}
assert_eq!(input.value(), "");
let mut input: Input = value.into();
input.handle(InputRequest::GoToStart);
for _ in 0..positions.len() - 1 {
input.handle(InputRequest::DeleteNextChar);
assert_eq!(input.cursor(), 0);
}
assert_eq!(input.value(), "");
}
#[test]
fn grapheme_combining_mark() {
walk_grapheme("xa\u{0301}y", &[0, 1, 3, 4]);
}
#[test]
fn grapheme_facepalm_emoji() {
walk_grapheme("xπ€¦πΌ\u{200D}β\u{FE0F}y", &[0, 1, 6, 7]);
}
#[test]
fn grapheme_flag_sequence() {
walk_grapheme("xπΊπΈy", &[0, 1, 3, 4]);
}
#[test]
fn word_movement_comprehensive() {
let mut input: Input = "Hello, world! π€¦πΌββοΈ ok".into();
input.handle(InputRequest::GoToStart);
input.handle(InputRequest::GoToNextWord);
assert_eq!(
input.value()[codepoint_to_byte(input.value(), input.cursor())..]
.chars()
.next(),
Some('w')
);
input.handle(InputRequest::GoToNextWord);
assert_eq!(
input.value()[codepoint_to_byte(input.value(), input.cursor())..]
.chars()
.next(),
Some('π€¦')
);
input.handle(InputRequest::GoToNextWord);
assert_eq!(
input.value()[codepoint_to_byte(input.value(), input.cursor())..]
.chars()
.next(),
Some('o')
);
input.handle(InputRequest::GoToPrevWord);
assert_eq!(
input.value()[codepoint_to_byte(input.value(), input.cursor())..]
.chars()
.next(),
Some('π€¦')
);
input.handle(InputRequest::GoToPrevWord);
assert_eq!(
input.value()[codepoint_to_byte(input.value(), input.cursor())..]
.chars()
.next(),
Some('w')
);
input.handle(InputRequest::GoToPrevWord);
assert_eq!(
input.value()[codepoint_to_byte(input.value(), input.cursor())..]
.chars()
.next(),
Some('H')
);
}
#[test]
fn delete_emoji_word() {
let mut input: Input = "abc π€¦πΌββοΈ def".into();
input.handle(InputRequest::GoToEnd);
input.handle(InputRequest::DeletePrevWord); assert_eq!(input.value(), "abc π€¦πΌββοΈ ");
input.handle(InputRequest::DeletePrevWord); assert_eq!(input.value(), "abc ");
input.handle(InputRequest::DeletePrevWord); assert_eq!(input.value(), "");
}
#[test]
fn delete_word_comprehensive() {
let mut input: Input = "abc def, ghi".into();
input.handle(InputRequest::GoToStart);
input.handle(InputRequest::GoToNextWord); input.handle(InputRequest::DeleteNextWord); assert_eq!(input.value(), "abc ghi");
assert_eq!(input.cursor(), 5);
input.handle(InputRequest::DeletePrevWord); assert_eq!(input.value(), "ghi");
assert_eq!(input.cursor(), 0);
}