From ef5fec510a621bf37cfd1da5439a5793eb7d20dc Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Thu, 13 Jun 2024 14:34:06 +0200 Subject: [PATCH 1/5] Add tests for 'c-movement' for vi normal mode --- src/edit_mode/vi/parser.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/edit_mode/vi/parser.rs b/src/edit_mode/vi/parser.rs index d3d9289d..3f20a7b7 100644 --- a/src/edit_mode/vi/parser.rs +++ b/src/edit_mode/vi/parser.rs @@ -510,6 +510,13 @@ mod tests { #[case(&['d', 'e'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutWordRight])]))] #[case(&['d', 'b'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutWordLeft])]))] #[case(&['d', 'B'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutBigWordLeft])]))] + #[case(&['c', 'c'], ReedlineEvent::Multiple(vec![ + ReedlineEvent::Edit(vec![EditCommand::CutCurrentLine]), ReedlineEvent::Repaint]))] + #[case(&['c', 'w'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutWordRight]), ReedlineEvent::Repaint]))] + #[case(&['c', 'W'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutBigWordRight]), ReedlineEvent::Repaint]))] + #[case(&['c', 'e'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutWordRight]), ReedlineEvent::Repaint]))] + #[case(&['c', 'b'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutWordLeft]), ReedlineEvent::Repaint]))] + #[case(&['c', 'B'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutBigWordLeft]), ReedlineEvent::Repaint]))] fn test_reedline_move(#[case] input: &[char], #[case] expected: ReedlineEvent) { let mut vi = Vi::default(); let res = vi_parse(input); @@ -518,6 +525,17 @@ mod tests { assert_eq!(output, expected); } + #[rstest] + #[case(&['c', 'w'], &['c', 'e'])] + #[case(&['c', 'W'], &['c', 'E'])] + fn test_reedline_move_synonm(#[case] synonym: &[char], #[case] original: &[char]) { + let mut vi = Vi::default(); + let output = vi_parse(synonym).to_reedline_event(&mut vi); + let expected = vi_parse(original).to_reedline_event(&mut vi); + + assert_eq!(output, expected); + } + #[rstest] #[case(&['2', 'k'], ReedlineEvent::Multiple(vec![ReedlineEvent::UntilFound(vec![ ReedlineEvent::MenuUp, From 9efd97b974a8543ee655c0be1815847aca070f55 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Thu, 13 Jun 2024 20:00:38 +0200 Subject: [PATCH 2/5] Complete d-movement tests --- src/edit_mode/vi/parser.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/edit_mode/vi/parser.rs b/src/edit_mode/vi/parser.rs index 3f20a7b7..fae042a0 100644 --- a/src/edit_mode/vi/parser.rs +++ b/src/edit_mode/vi/parser.rs @@ -511,12 +511,28 @@ mod tests { #[case(&['d', 'b'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutWordLeft])]))] #[case(&['d', 'B'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutBigWordLeft])]))] #[case(&['c', 'c'], ReedlineEvent::Multiple(vec![ - ReedlineEvent::Edit(vec![EditCommand::CutCurrentLine]), ReedlineEvent::Repaint]))] + //ReedlineEvent::Edit(vec![EditCommand::CutCurrentLine]), ReedlineEvent::Repaint]))] + ReedlineEvent::Edit(vec![EditCommand::MoveToStart{select: false}]), ReedlineEvent::Edit(vec![EditCommand::ClearToLineEnd]), ReedlineEvent::Repaint]))] #[case(&['c', 'w'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutWordRight]), ReedlineEvent::Repaint]))] #[case(&['c', 'W'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutBigWordRight]), ReedlineEvent::Repaint]))] #[case(&['c', 'e'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutWordRight]), ReedlineEvent::Repaint]))] #[case(&['c', 'b'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutWordLeft]), ReedlineEvent::Repaint]))] #[case(&['c', 'B'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutBigWordLeft]), ReedlineEvent::Repaint]))] + #[case(&['d', 'h'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::Backspace])]))] + #[case(&['d', 'l'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::Delete])]))] + #[case(&['2', 'd', 'd'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutCurrentLine]), ReedlineEvent::Edit(vec![EditCommand::CutCurrentLine])]))] + // #[case(&['d', 'j'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutCurrentLine]), ReedlineEvent::Edit(vec![EditCommand::CutCurrentLine])]))] + // #[case(&['d', 'k'], ReedlineEvent::Multiple(vec![ReedlineEvent::Up, ReedlineEvent::Edit(vec![EditCommand::CutCurrentLine]), ReedlineEvent::Edit(vec![EditCommand::CutCurrentLine])]))] + #[case(&['d', 'E'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutBigWordRight])]))] + #[case(&['d', '0'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutFromLineStart])]))] + #[case(&['d', '^'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutFromLineStart])]))] + #[case(&['d', '$'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutToLineEnd])]))] + #[case(&['d', 'f', 'a'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutRightUntil('a')])]))] + #[case(&['d', 't', 'a'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutRightBefore('a')])]))] + #[case(&['d', 'F', 'a'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutLeftUntil('a')])]))] + #[case(&['d', 'T', 'a'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutLeftBefore('a')])]))] + // #[case(&['d', 'f', 'a', 'd', ';'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutRightUntil('a')]), ReedlineEvent::Edit(vec![EditCommand::CutRightUntil('a')])]))] + // #[case(&['d', 'f', 'a', 'd', ','], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutRightUntil('a')]), ReedlineEvent::Edit(vec![EditCommand::CutLeftUntil('a')])]))] fn test_reedline_move(#[case] input: &[char], #[case] expected: ReedlineEvent) { let mut vi = Vi::default(); let res = vi_parse(input); From d9198e36a651c0a4eb16cbfb04642209e36f7e99 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Wed, 17 Jul 2024 18:55:18 +0200 Subject: [PATCH 3/5] Complete c-movement tests --- src/edit_mode/vi/parser.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/edit_mode/vi/parser.rs b/src/edit_mode/vi/parser.rs index fae042a0..81d0e396 100644 --- a/src/edit_mode/vi/parser.rs +++ b/src/edit_mode/vi/parser.rs @@ -533,6 +533,14 @@ mod tests { #[case(&['d', 'T', 'a'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutLeftBefore('a')])]))] // #[case(&['d', 'f', 'a', 'd', ';'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutRightUntil('a')]), ReedlineEvent::Edit(vec![EditCommand::CutRightUntil('a')])]))] // #[case(&['d', 'f', 'a', 'd', ','], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutRightUntil('a')]), ReedlineEvent::Edit(vec![EditCommand::CutLeftUntil('a')])]))] + #[case(&['c', 'E'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutBigWordRight]), ReedlineEvent::Repaint]))] + #[case(&['c', '0'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutFromLineStart]), ReedlineEvent::Repaint]))] + #[case(&['c', '^'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutFromLineStart]), ReedlineEvent::Repaint]))] + #[case(&['c', '$'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutToLineEnd]), ReedlineEvent::Repaint]))] + #[case(&['c', 'f', 'a'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutRightUntil('a')]), ReedlineEvent::Repaint]))] + #[case(&['c', 't', 'a'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutRightBefore('a')]), ReedlineEvent::Repaint]))] + #[case(&['c', 'F', 'a'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutLeftUntil('a')]), ReedlineEvent::Repaint]))] + #[case(&['c', 'T', 'a'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutLeftBefore('a')]), ReedlineEvent::Repaint]))] fn test_reedline_move(#[case] input: &[char], #[case] expected: ReedlineEvent) { let mut vi = Vi::default(); let res = vi_parse(input); From adfb86d699210f6dabc0be603eb24f123d1368ec Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Wed, 17 Jul 2024 20:41:04 +0200 Subject: [PATCH 4/5] Fix cc anc c$ in vi-mode in vim the deleted text can be pasted, while previously that didn't happen in reedline --- src/edit_mode/vi/command.rs | 6 +++--- src/edit_mode/vi/parser.rs | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/edit_mode/vi/command.rs b/src/edit_mode/vi/command.rs index e7bf0426..9c4f0711 100644 --- a/src/edit_mode/vi/command.rs +++ b/src/edit_mode/vi/command.rs @@ -212,10 +212,10 @@ impl Command { }, Self::Change => { let op = match motion { - Motion::End => Some(vec![ReedlineOption::Edit(EditCommand::ClearToLineEnd)]), + Motion::End => Some(vec![ReedlineOption::Edit(EditCommand::CutToLineEnd)]), Motion::Line => Some(vec![ - ReedlineOption::Edit(EditCommand::MoveToStart { select: false }), - ReedlineOption::Edit(EditCommand::ClearToLineEnd), + ReedlineOption::Edit(EditCommand::MoveToLineStart { select: false }), + ReedlineOption::Edit(EditCommand::CutToLineEnd), ]), Motion::NextWord => Some(vec![ReedlineOption::Edit(EditCommand::CutWordRight)]), Motion::NextBigWord => { diff --git a/src/edit_mode/vi/parser.rs b/src/edit_mode/vi/parser.rs index 81d0e396..5d554ce8 100644 --- a/src/edit_mode/vi/parser.rs +++ b/src/edit_mode/vi/parser.rs @@ -511,8 +511,7 @@ mod tests { #[case(&['d', 'b'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutWordLeft])]))] #[case(&['d', 'B'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutBigWordLeft])]))] #[case(&['c', 'c'], ReedlineEvent::Multiple(vec![ - //ReedlineEvent::Edit(vec![EditCommand::CutCurrentLine]), ReedlineEvent::Repaint]))] - ReedlineEvent::Edit(vec![EditCommand::MoveToStart{select: false}]), ReedlineEvent::Edit(vec![EditCommand::ClearToLineEnd]), ReedlineEvent::Repaint]))] + ReedlineEvent::Edit(vec![EditCommand::MoveToLineStart { select: false }]), ReedlineEvent::Edit(vec![EditCommand::CutToLineEnd]), ReedlineEvent::Repaint]))] #[case(&['c', 'w'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutWordRight]), ReedlineEvent::Repaint]))] #[case(&['c', 'W'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutBigWordRight]), ReedlineEvent::Repaint]))] #[case(&['c', 'e'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutWordRight]), ReedlineEvent::Repaint]))] From ab5c99ff426b178303c1e216f35875489734d556 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Thu, 18 Jul 2024 20:48:45 +0200 Subject: [PATCH 5/5] Add tests for ";" and "," in vi mode --- src/edit_mode/vi/parser.rs | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/edit_mode/vi/parser.rs b/src/edit_mode/vi/parser.rs index 5d554ce8..149b5eb9 100644 --- a/src/edit_mode/vi/parser.rs +++ b/src/edit_mode/vi/parser.rs @@ -530,8 +530,6 @@ mod tests { #[case(&['d', 't', 'a'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutRightBefore('a')])]))] #[case(&['d', 'F', 'a'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutLeftUntil('a')])]))] #[case(&['d', 'T', 'a'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutLeftBefore('a')])]))] - // #[case(&['d', 'f', 'a', 'd', ';'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutRightUntil('a')]), ReedlineEvent::Edit(vec![EditCommand::CutRightUntil('a')])]))] - // #[case(&['d', 'f', 'a', 'd', ','], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutRightUntil('a')]), ReedlineEvent::Edit(vec![EditCommand::CutLeftUntil('a')])]))] #[case(&['c', 'E'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutBigWordRight]), ReedlineEvent::Repaint]))] #[case(&['c', '0'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutFromLineStart]), ReedlineEvent::Repaint]))] #[case(&['c', '^'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutFromLineStart]), ReedlineEvent::Repaint]))] @@ -548,6 +546,31 @@ mod tests { assert_eq!(output, expected); } + #[rstest] + #[case(&['f', 'a'], &[';'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::MoveRightUntil{c: 'a',select: false}])]))] + #[case(&['f', 'a'], &[','], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::MoveLeftUntil{c: 'a', select: false}])]))] + #[case(&['F', 'a'], &[','], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::MoveRightUntil{c: 'a', select: false}])]))] + #[case(&['F', 'a'], &[';'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::MoveLeftUntil{c: 'a', select: false}])]))] + #[case(&['f', 'a'], &['d', ';'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutRightUntil('a')])]))] + #[case(&['f', 'a'], &['d', ','], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutLeftUntil('a')])]))] + #[case(&['F', 'a'], &['d', ','], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutRightUntil('a')])]))] + #[case(&['F', 'a'], &['d', ';'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutLeftUntil('a')])]))] + #[case(&['f', 'a'], &['c', ';'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutRightUntil('a')]), ReedlineEvent::Repaint]))] + #[case(&['f', 'a'], &['c', ','], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutLeftUntil('a')]), ReedlineEvent::Repaint]))] + #[case(&['F', 'a'], &['c', ','], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutRightUntil('a')]), ReedlineEvent::Repaint]))] + #[case(&['F', 'a'], &['c', ';'], ReedlineEvent::Multiple(vec![ReedlineEvent::Edit(vec![EditCommand::CutLeftUntil('a')]), ReedlineEvent::Repaint]))] + fn test_reedline_memory_move( + #[case] before: &[char], + #[case] now: &[char], + #[case] expected: ReedlineEvent, + ) { + let mut vi = Vi::default(); + let _ = vi_parse(before).to_reedline_event(&mut vi); + let output = vi_parse(now).to_reedline_event(&mut vi); + + assert_eq!(output, expected); + } + #[rstest] #[case(&['c', 'w'], &['c', 'e'])] #[case(&['c', 'W'], &['c', 'E'])]