Port test_word_motion

This commit is contained in:
Johannes Altmanninger
2023-12-22 09:33:45 +01:00
parent afe9013b4c
commit e194f35a5e
2 changed files with 168 additions and 111 deletions

View File

@@ -1,7 +1,11 @@
use crate::redirection::RedirectionMode; use crate::redirection::RedirectionMode;
use crate::tokenizer::{PipeOrRedir, TokFlags, TokenType, Tokenizer, TokenizerError}; use crate::tokenizer::{
MoveWordStateMachine, MoveWordStyle, PipeOrRedir, TokFlags, TokenType, Tokenizer,
TokenizerError,
};
use crate::wchar::prelude::*; use crate::wchar::prelude::*;
use libc::{STDERR_FILENO, STDOUT_FILENO}; use libc::{STDERR_FILENO, STDOUT_FILENO};
use std::collections::HashSet;
#[test] #[test]
fn test_tokenizer() { fn test_tokenizer() {
@@ -139,3 +143,166 @@ macro_rules! get_redir_mode {
assert_eq!(get_redir_mode!("3<&0"), RedirectionMode::fd); assert_eq!(get_redir_mode!("3<&0"), RedirectionMode::fd);
assert_eq!(get_redir_mode!("3</tmp/filetxt"), RedirectionMode::input); assert_eq!(get_redir_mode!("3</tmp/filetxt"), RedirectionMode::input);
} }
/// Test word motion (forward-word, etc.). Carets represent cursor stops.
#[test]
fn test_word_motion() {
#[derive(Eq, PartialEq)]
pub enum Direction {
Left,
Right,
}
macro_rules! validate {
($direction:expr, $style:expr, $line:expr) => {
let mut command = WString::new();
let mut stops = HashSet::new();
// Carets represent stops and should be cut out of the command.
for c in $line.chars() {
if c == '^' {
stops.insert(command.len());
} else {
command.push(c);
}
}
let (mut idx, end) = if $direction == Direction::Left {
(stops.iter().max().unwrap().clone(), 0)
} else {
(stops.iter().min().unwrap().clone(), command.len())
};
stops.remove(&idx);
let mut sm = MoveWordStateMachine::new($style);
while idx != end {
let char_idx = if $direction == Direction::Left {
idx - 1
} else {
idx
};
let c = command.as_char_slice()[char_idx];
let will_stop = !sm.consume_char(c);
let expected_stop = stops.contains(&idx);
assert_eq!(will_stop, expected_stop);
// We don't expect to stop here next time.
if expected_stop {
stops.remove(&idx);
sm.reset();
} else {
if $direction == Direction::Left {
idx -= 1;
} else {
idx += 1;
}
}
}
};
}
validate!(
Direction::Left,
MoveWordStyle::move_word_style_punctuation,
"^echo ^hello_^world.^txt^"
);
validate!(
Direction::Right,
MoveWordStyle::move_word_style_punctuation,
"^echo^ hello^_world^.txt^"
);
validate!(
Direction::Left,
MoveWordStyle::move_word_style_punctuation,
"echo ^foo_^foo_^foo/^/^/^/^/^ ^"
);
validate!(
Direction::Right,
MoveWordStyle::move_word_style_punctuation,
"^echo^ foo^_foo^_foo^/^/^/^/^/ ^"
);
validate!(
Direction::Left,
MoveWordStyle::move_word_style_path_components,
"^/^foo/^bar/^baz/^"
);
validate!(
Direction::Left,
MoveWordStyle::move_word_style_path_components,
"^echo ^--foo ^--bar^"
);
validate!(
Direction::Left,
MoveWordStyle::move_word_style_path_components,
"^echo ^hi ^> ^/^dev/^null^"
);
validate!(
Direction::Left,
MoveWordStyle::move_word_style_path_components,
"^echo ^/^foo/^bar{^aaa,^bbb,^ccc}^bak/^"
);
validate!(
Direction::Left,
MoveWordStyle::move_word_style_path_components,
"^echo ^bak ^///^"
);
validate!(
Direction::Left,
MoveWordStyle::move_word_style_path_components,
"^aaa ^@ ^@^aaa^"
);
validate!(
Direction::Left,
MoveWordStyle::move_word_style_path_components,
"^aaa ^a ^@^aaa^"
);
validate!(
Direction::Left,
MoveWordStyle::move_word_style_path_components,
"^aaa ^@@@ ^@@^aa^"
);
validate!(
Direction::Left,
MoveWordStyle::move_word_style_path_components,
"^aa^@@ ^aa@@^a^"
);
validate!(
Direction::Right,
MoveWordStyle::move_word_style_punctuation,
"^a^ bcd^"
);
validate!(
Direction::Right,
MoveWordStyle::move_word_style_punctuation,
"a^b^ cde^"
);
validate!(
Direction::Right,
MoveWordStyle::move_word_style_punctuation,
"^ab^ cde^"
);
validate!(
Direction::Right,
MoveWordStyle::move_word_style_punctuation,
"^ab^&cd^ ^& ^e^ f^&"
);
validate!(
Direction::Right,
MoveWordStyle::move_word_style_whitespace,
"^^a-b-c^ d-e-f"
);
validate!(
Direction::Right,
MoveWordStyle::move_word_style_whitespace,
"^a-b-c^\n d-e-f^ "
);
validate!(
Direction::Right,
MoveWordStyle::move_word_style_whitespace,
"^a-b-c^\n\nd-e-f^ "
);
}

View File

@@ -736,115 +736,6 @@ static void test_abbreviations() {
} }
} }
// todo!("port this")
enum word_motion_t { word_motion_left, word_motion_right };
static void test_1_word_motion(word_motion_t motion, move_word_style_t style,
const wcstring &test) {
wcstring command;
std::set<size_t> stops;
// Carets represent stops and should be cut out of the command.
for (wchar_t wc : test) {
if (wc == L'^') {
stops.insert(command.size());
} else {
command.push_back(wc);
}
}
size_t idx, end;
if (motion == word_motion_left) {
idx = *std::max_element(stops.begin(), stops.end());
end = 0;
} else {
idx = *std::min_element(stops.begin(), stops.end());
end = command.size();
}
stops.erase(idx);
auto sm = new_move_word_state_machine(style);
while (idx != end) {
size_t char_idx = (motion == word_motion_left ? idx - 1 : idx);
wchar_t wc = command.at(char_idx);
bool will_stop = !sm->consume_char(wc);
// std::fwprintf(stdout, L"idx %lu, looking at %lu (%c): %d\n", idx, char_idx, (char)wc,
// will_stop);
bool expected_stop = (stops.count(idx) > 0);
if (will_stop != expected_stop) {
wcstring tmp = command;
tmp.insert(idx, L"^");
const char *dir = (motion == word_motion_left ? "left" : "right");
if (will_stop) {
err(L"Word motion: moving %s, unexpected stop at idx %lu: '%ls'", dir, idx,
tmp.c_str());
} else if (!will_stop && expected_stop) {
err(L"Word motion: moving %s, should have stopped at idx %lu: '%ls'", dir, idx,
tmp.c_str());
}
}
// We don't expect to stop here next time.
if (expected_stop) {
stops.erase(idx);
}
if (will_stop) {
sm->reset();
} else {
idx += (motion == word_motion_left ? -1 : 1);
}
}
}
// todo!("port this")
/// Test word motion (forward-word, etc.). Carets represent cursor stops.
static void test_word_motion() {
say(L"Testing word motion");
test_1_word_motion(word_motion_left, move_word_style_t::move_word_style_punctuation,
L"^echo ^hello_^world.^txt^");
test_1_word_motion(word_motion_right, move_word_style_t::move_word_style_punctuation,
L"^echo^ hello^_world^.txt^");
test_1_word_motion(word_motion_left, move_word_style_t::move_word_style_punctuation,
L"echo ^foo_^foo_^foo/^/^/^/^/^ ^");
test_1_word_motion(word_motion_right, move_word_style_t::move_word_style_punctuation,
L"^echo^ foo^_foo^_foo^/^/^/^/^/ ^");
test_1_word_motion(word_motion_left, move_word_style_t::move_word_style_path_components,
L"^/^foo/^bar/^baz/^");
test_1_word_motion(word_motion_left, move_word_style_t::move_word_style_path_components,
L"^echo ^--foo ^--bar^");
test_1_word_motion(word_motion_left, move_word_style_t::move_word_style_path_components,
L"^echo ^hi ^> ^/^dev/^null^");
test_1_word_motion(word_motion_left, move_word_style_t::move_word_style_path_components,
L"^echo ^/^foo/^bar{^aaa,^bbb,^ccc}^bak/^");
test_1_word_motion(word_motion_left, move_word_style_t::move_word_style_path_components,
L"^echo ^bak ^///^");
test_1_word_motion(word_motion_left, move_word_style_t::move_word_style_path_components,
L"^aaa ^@ ^@^aaa^");
test_1_word_motion(word_motion_left, move_word_style_t::move_word_style_path_components,
L"^aaa ^a ^@^aaa^");
test_1_word_motion(word_motion_left, move_word_style_t::move_word_style_path_components,
L"^aaa ^@@@ ^@@^aa^");
test_1_word_motion(word_motion_left, move_word_style_t::move_word_style_path_components,
L"^aa^@@ ^aa@@^a^");
test_1_word_motion(word_motion_right, move_word_style_t::move_word_style_punctuation,
L"^a^ bcd^");
test_1_word_motion(word_motion_right, move_word_style_t::move_word_style_punctuation,
L"a^b^ cde^");
test_1_word_motion(word_motion_right, move_word_style_t::move_word_style_punctuation,
L"^ab^ cde^");
test_1_word_motion(word_motion_right, move_word_style_t::move_word_style_punctuation,
L"^ab^&cd^ ^& ^e^ f^&");
test_1_word_motion(word_motion_right, move_word_style_t::move_word_style_whitespace,
L"^^a-b-c^ d-e-f");
test_1_word_motion(word_motion_right, move_word_style_t::move_word_style_whitespace,
L"^a-b-c^\n d-e-f^ ");
test_1_word_motion(word_motion_right, move_word_style_t::move_word_style_whitespace,
L"^a-b-c^\n\nd-e-f^ ");
}
// todo!("already ported, delete this") // todo!("already ported, delete this")
/// Testing colors. /// Testing colors.
static void test_colors() { static void test_colors() {
@@ -1173,7 +1064,6 @@ static const test_t s_tests[]{
{TEST_GROUP("convert_ascii"), test_convert_ascii}, {TEST_GROUP("convert_ascii"), test_convert_ascii},
{TEST_GROUP("iothread"), test_iothread}, {TEST_GROUP("iothread"), test_iothread},
{TEST_GROUP("lru"), test_lru}, {TEST_GROUP("lru"), test_lru},
{TEST_GROUP("word_motion"), test_word_motion},
{TEST_GROUP("colors"), test_colors}, {TEST_GROUP("colors"), test_colors},
{TEST_GROUP("input"), test_input}, {TEST_GROUP("input"), test_input},
{TEST_GROUP("completion_insertions"), test_completion_insertions}, {TEST_GROUP("completion_insertions"), test_completion_insertions},