vim: Implement <count>%
motion (#25839)
Closes https://github.com/zed-industries/zed/discussions/25665 > Currently Zed is missing quite an useful Vim motion: <count>% (go to {count} percentage in the file). Description: {count}% - Go to {count} percentage in the file, on the first non-blank in the line linewise. To compute the new line number this formula is used: ({count} * number-of-lines + 99) / 100 . > [Link](https://neovim.io/doc/user/motion.html#N%25). Release Notes: - vim: Added `<count>%` motion --------- Co-authored-by: Conrad Irwin <conrad@zed.dev>
This commit is contained in:
parent
314ad5dd5f
commit
22b1a02e23
3 changed files with 152 additions and 1 deletions
|
@ -247,7 +247,8 @@
|
|||
"context": "VimControl && VimCount",
|
||||
"bindings": {
|
||||
"0": ["vim::Number", 0],
|
||||
":": "vim::CountCommand"
|
||||
":": "vim::CountCommand",
|
||||
"%": "vim::GoToPercentage"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
@ -74,6 +74,7 @@ pub enum Motion {
|
|||
StartOfDocument,
|
||||
EndOfDocument,
|
||||
Matching,
|
||||
GoToPercentage,
|
||||
UnmatchedForward {
|
||||
char: char,
|
||||
},
|
||||
|
@ -281,6 +282,7 @@ actions!(
|
|||
StartOfDocument,
|
||||
EndOfDocument,
|
||||
Matching,
|
||||
GoToPercentage,
|
||||
NextLineStart,
|
||||
PreviousLineStart,
|
||||
StartOfLineDownward,
|
||||
|
@ -402,6 +404,9 @@ pub fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
|
|||
Vim::action(editor, cx, |vim, _: &Matching, window, cx| {
|
||||
vim.motion(Motion::Matching, window, cx)
|
||||
});
|
||||
Vim::action(editor, cx, |vim, _: &GoToPercentage, window, cx| {
|
||||
vim.motion(Motion::GoToPercentage, window, cx)
|
||||
});
|
||||
Vim::action(
|
||||
editor,
|
||||
cx,
|
||||
|
@ -643,6 +648,7 @@ impl Motion {
|
|||
| PreviousMethodEnd
|
||||
| NextComment
|
||||
| PreviousComment
|
||||
| GoToPercentage
|
||||
| Jump { line: true, .. } => true,
|
||||
EndOfLine { .. }
|
||||
| Matching
|
||||
|
@ -701,6 +707,7 @@ impl Motion {
|
|||
| StartOfLineDownward
|
||||
| EndOfLineDownward
|
||||
| GoToColumn
|
||||
| GoToPercentage
|
||||
| NextWordStart { .. }
|
||||
| NextWordEnd { .. }
|
||||
| PreviousWordStart { .. }
|
||||
|
@ -745,6 +752,7 @@ impl Motion {
|
|||
| EndOfLine { .. }
|
||||
| EndOfLineDownward
|
||||
| Matching
|
||||
| GoToPercentage
|
||||
| UnmatchedForward { .. }
|
||||
| UnmatchedBackward { .. }
|
||||
| FindForward { .. }
|
||||
|
@ -886,6 +894,7 @@ impl Motion {
|
|||
SelectionGoal::None,
|
||||
),
|
||||
Matching => (matching(map, point), SelectionGoal::None),
|
||||
GoToPercentage => (go_to_percentage(map, point, times), SelectionGoal::None),
|
||||
UnmatchedForward { char } => (
|
||||
unmatched_forward(map, point, *char, times),
|
||||
SelectionGoal::None,
|
||||
|
@ -2194,6 +2203,22 @@ fn matching(map: &DisplaySnapshot, display_point: DisplayPoint) -> DisplayPoint
|
|||
}
|
||||
}
|
||||
|
||||
// Go to {count} percentage in the file, on the first
|
||||
// non-blank in the line linewise. To compute the new
|
||||
// line number this formula is used:
|
||||
// ({count} * number-of-lines + 99) / 100
|
||||
//
|
||||
// https://neovim.io/doc/user/motion.html#N%25
|
||||
fn go_to_percentage(map: &DisplaySnapshot, point: DisplayPoint, count: usize) -> DisplayPoint {
|
||||
let total_lines = map.buffer_snapshot.max_point().row + 1;
|
||||
let target_line = (count * total_lines as usize + 99) / 100;
|
||||
let target_point = DisplayPoint::new(
|
||||
DisplayRow(target_line.saturating_sub(1) as u32),
|
||||
point.column(),
|
||||
);
|
||||
map.clip_point(target_point, Bias::Left)
|
||||
}
|
||||
|
||||
fn unmatched_forward(
|
||||
map: &DisplaySnapshot,
|
||||
mut display_point: DisplayPoint,
|
||||
|
@ -3470,4 +3495,103 @@ mod test {
|
|||
Mode::Normal,
|
||||
);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_go_to_percentage(cx: &mut gpui::TestAppContext) {
|
||||
let mut cx = NeovimBackedTestContext::new(cx).await;
|
||||
// Normal mode
|
||||
cx.set_shared_state(indoc! {"
|
||||
The ˇquick brown
|
||||
fox jumps over
|
||||
the lazy dog
|
||||
The quick brown
|
||||
fox jumps over
|
||||
the lazy dog
|
||||
The quick brown
|
||||
fox jumps over
|
||||
the lazy dog"})
|
||||
.await;
|
||||
cx.simulate_shared_keystrokes("2 0 %").await;
|
||||
cx.shared_state().await.assert_eq(indoc! {"
|
||||
The quick brown
|
||||
fox ˇjumps over
|
||||
the lazy dog
|
||||
The quick brown
|
||||
fox jumps over
|
||||
the lazy dog
|
||||
The quick brown
|
||||
fox jumps over
|
||||
the lazy dog"});
|
||||
|
||||
cx.simulate_shared_keystrokes("2 5 %").await;
|
||||
cx.shared_state().await.assert_eq(indoc! {"
|
||||
The quick brown
|
||||
fox jumps over
|
||||
the ˇlazy dog
|
||||
The quick brown
|
||||
fox jumps over
|
||||
the lazy dog
|
||||
The quick brown
|
||||
fox jumps over
|
||||
the lazy dog"});
|
||||
|
||||
cx.simulate_shared_keystrokes("7 5 %").await;
|
||||
cx.shared_state().await.assert_eq(indoc! {"
|
||||
The quick brown
|
||||
fox jumps over
|
||||
the lazy dog
|
||||
The quick brown
|
||||
fox jumps over
|
||||
the lazy dog
|
||||
The ˇquick brown
|
||||
fox jumps over
|
||||
the lazy dog"});
|
||||
|
||||
// Visual mode
|
||||
cx.set_shared_state(indoc! {"
|
||||
The ˇquick brown
|
||||
fox jumps over
|
||||
the lazy dog
|
||||
The quick brown
|
||||
fox jumps over
|
||||
the lazy dog
|
||||
The quick brown
|
||||
fox jumps over
|
||||
the lazy dog"})
|
||||
.await;
|
||||
cx.simulate_shared_keystrokes("v 5 0 %").await;
|
||||
cx.shared_state().await.assert_eq(indoc! {"
|
||||
The «quick brown
|
||||
fox jumps over
|
||||
the lazy dog
|
||||
The quick brown
|
||||
fox jˇ»umps over
|
||||
the lazy dog
|
||||
The quick brown
|
||||
fox jumps over
|
||||
the lazy dog"});
|
||||
|
||||
cx.set_shared_state(indoc! {"
|
||||
The ˇquick brown
|
||||
fox jumps over
|
||||
the lazy dog
|
||||
The quick brown
|
||||
fox jumps over
|
||||
the lazy dog
|
||||
The quick brown
|
||||
fox jumps over
|
||||
the lazy dog"})
|
||||
.await;
|
||||
cx.simulate_shared_keystrokes("v 1 0 0 %").await;
|
||||
cx.shared_state().await.assert_eq(indoc! {"
|
||||
The «quick brown
|
||||
fox jumps over
|
||||
the lazy dog
|
||||
The quick brown
|
||||
fox jumps over
|
||||
the lazy dog
|
||||
The quick brown
|
||||
fox jumps over
|
||||
the lˇ»azy dog"});
|
||||
}
|
||||
}
|
||||
|
|
26
crates/vim/test_data/test_go_to_percentage.json
Normal file
26
crates/vim/test_data/test_go_to_percentage.json
Normal file
|
@ -0,0 +1,26 @@
|
|||
{"Put":{"state":"The ˇquick brown\nfox jumps over\nthe lazy dog\nThe quick brown\nfox jumps over\nthe lazy dog\nThe quick brown\nfox jumps over\nthe lazy dog"}}
|
||||
{"Key":"2"}
|
||||
{"Key":"0"}
|
||||
{"Key":"%"}
|
||||
{"Get":{"state":"The quick brown\nfox ˇjumps over\nthe lazy dog\nThe quick brown\nfox jumps over\nthe lazy dog\nThe quick brown\nfox jumps over\nthe lazy dog","mode":"Normal"}}
|
||||
{"Key":"2"}
|
||||
{"Key":"5"}
|
||||
{"Key":"%"}
|
||||
{"Get":{"state":"The quick brown\nfox jumps over\nthe ˇlazy dog\nThe quick brown\nfox jumps over\nthe lazy dog\nThe quick brown\nfox jumps over\nthe lazy dog","mode":"Normal"}}
|
||||
{"Key":"7"}
|
||||
{"Key":"5"}
|
||||
{"Key":"%"}
|
||||
{"Get":{"state":"The quick brown\nfox jumps over\nthe lazy dog\nThe quick brown\nfox jumps over\nthe lazy dog\nThe ˇquick brown\nfox jumps over\nthe lazy dog","mode":"Normal"}}
|
||||
{"Put":{"state":"The ˇquick brown\nfox jumps over\nthe lazy dog\nThe quick brown\nfox jumps over\nthe lazy dog\nThe quick brown\nfox jumps over\nthe lazy dog"}}
|
||||
{"Key":"v"}
|
||||
{"Key":"5"}
|
||||
{"Key":"0"}
|
||||
{"Key":"%"}
|
||||
{"Get":{"state":"The «quick brown\nfox jumps over\nthe lazy dog\nThe quick brown\nfox jˇ»umps over\nthe lazy dog\nThe quick brown\nfox jumps over\nthe lazy dog","mode":"Visual"}}
|
||||
{"Put":{"state":"The ˇquick brown\nfox jumps over\nthe lazy dog\nThe quick brown\nfox jumps over\nthe lazy dog\nThe quick brown\nfox jumps over\nthe lazy dog"}}
|
||||
{"Key":"v"}
|
||||
{"Key":"1"}
|
||||
{"Key":"0"}
|
||||
{"Key":"0"}
|
||||
{"Key":"%"}
|
||||
{"Get":{"state":"The «quick brown\nfox jumps over\nthe lazy dog\nThe quick brown\nfox jumps over\nthe lazy dog\nThe quick brown\nfox jumps over\nthe lˇ»azy dog","mode":"Visual"}}
|
Loading…
Add table
Add a link
Reference in a new issue