mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-27 23:59:52 +03:00
vim: Add }/{ for start/end of paragraph
Fixes: zed-industries/community#470
This commit is contained in:
parent
f6b64dc67a
commit
9ee2707d43
@ -37,6 +37,8 @@
|
||||
"$": "vim::EndOfLine",
|
||||
"shift-g": "vim::EndOfDocument",
|
||||
"w": "vim::NextWordStart",
|
||||
"{": "vim::StartOfParagraph",
|
||||
"}": "vim::EndOfParagraph",
|
||||
"shift-w": [
|
||||
"vim::NextWordStart",
|
||||
{
|
||||
|
@ -5120,7 +5120,7 @@ impl Editor {
|
||||
self.change_selections(Some(Autoscroll::fit()), cx, |s| {
|
||||
s.move_with(|map, selection| {
|
||||
selection.collapse_to(
|
||||
movement::start_of_paragraph(map, selection.head()),
|
||||
movement::start_of_paragraph(map, selection.head(), 1),
|
||||
SelectionGoal::None,
|
||||
)
|
||||
});
|
||||
@ -5140,7 +5140,7 @@ impl Editor {
|
||||
self.change_selections(Some(Autoscroll::fit()), cx, |s| {
|
||||
s.move_with(|map, selection| {
|
||||
selection.collapse_to(
|
||||
movement::end_of_paragraph(map, selection.head()),
|
||||
movement::end_of_paragraph(map, selection.head(), 1),
|
||||
SelectionGoal::None,
|
||||
)
|
||||
});
|
||||
@ -5159,7 +5159,10 @@ impl Editor {
|
||||
|
||||
self.change_selections(Some(Autoscroll::fit()), cx, |s| {
|
||||
s.move_heads_with(|map, head, _| {
|
||||
(movement::start_of_paragraph(map, head), SelectionGoal::None)
|
||||
(
|
||||
movement::start_of_paragraph(map, head, 1),
|
||||
SelectionGoal::None,
|
||||
)
|
||||
});
|
||||
})
|
||||
}
|
||||
@ -5176,7 +5179,10 @@ impl Editor {
|
||||
|
||||
self.change_selections(Some(Autoscroll::fit()), cx, |s| {
|
||||
s.move_heads_with(|map, head, _| {
|
||||
(movement::end_of_paragraph(map, head), SelectionGoal::None)
|
||||
(
|
||||
movement::end_of_paragraph(map, head, 1),
|
||||
SelectionGoal::None,
|
||||
)
|
||||
});
|
||||
})
|
||||
}
|
||||
|
@ -193,7 +193,11 @@ pub fn next_subword_end(map: &DisplaySnapshot, point: DisplayPoint) -> DisplayPo
|
||||
})
|
||||
}
|
||||
|
||||
pub fn start_of_paragraph(map: &DisplaySnapshot, display_point: DisplayPoint) -> DisplayPoint {
|
||||
pub fn start_of_paragraph(
|
||||
map: &DisplaySnapshot,
|
||||
display_point: DisplayPoint,
|
||||
mut count: usize,
|
||||
) -> DisplayPoint {
|
||||
let point = display_point.to_point(map);
|
||||
if point.row == 0 {
|
||||
return map.max_point();
|
||||
@ -203,7 +207,11 @@ pub fn start_of_paragraph(map: &DisplaySnapshot, display_point: DisplayPoint) ->
|
||||
for row in (0..point.row + 1).rev() {
|
||||
let blank = map.buffer_snapshot.is_line_blank(row);
|
||||
if found_non_blank_line && blank {
|
||||
return Point::new(row, 0).to_display_point(map);
|
||||
if count <= 1 {
|
||||
return Point::new(row, 0).to_display_point(map);
|
||||
}
|
||||
count -= 1;
|
||||
found_non_blank_line = false;
|
||||
}
|
||||
|
||||
found_non_blank_line |= !blank;
|
||||
@ -212,7 +220,11 @@ pub fn start_of_paragraph(map: &DisplaySnapshot, display_point: DisplayPoint) ->
|
||||
DisplayPoint::zero()
|
||||
}
|
||||
|
||||
pub fn end_of_paragraph(map: &DisplaySnapshot, display_point: DisplayPoint) -> DisplayPoint {
|
||||
pub fn end_of_paragraph(
|
||||
map: &DisplaySnapshot,
|
||||
display_point: DisplayPoint,
|
||||
mut count: usize,
|
||||
) -> DisplayPoint {
|
||||
let point = display_point.to_point(map);
|
||||
if point.row == map.max_buffer_row() {
|
||||
return DisplayPoint::zero();
|
||||
@ -222,7 +234,11 @@ pub fn end_of_paragraph(map: &DisplaySnapshot, display_point: DisplayPoint) -> D
|
||||
for row in point.row..map.max_buffer_row() + 1 {
|
||||
let blank = map.buffer_snapshot.is_line_blank(row);
|
||||
if found_non_blank_line && blank {
|
||||
return Point::new(row, 0).to_display_point(map);
|
||||
if count <= 1 {
|
||||
return Point::new(row, 0).to_display_point(map);
|
||||
}
|
||||
count -= 1;
|
||||
found_non_blank_line = false;
|
||||
}
|
||||
|
||||
found_non_blank_line |= !blank;
|
||||
|
@ -31,6 +31,8 @@ pub enum Motion {
|
||||
CurrentLine,
|
||||
StartOfLine,
|
||||
EndOfLine,
|
||||
StartOfParagraph,
|
||||
EndOfParagraph,
|
||||
StartOfDocument,
|
||||
EndOfDocument,
|
||||
Matching,
|
||||
@ -72,6 +74,8 @@ actions!(
|
||||
StartOfLine,
|
||||
EndOfLine,
|
||||
CurrentLine,
|
||||
StartOfParagraph,
|
||||
EndOfParagraph,
|
||||
StartOfDocument,
|
||||
EndOfDocument,
|
||||
Matching,
|
||||
@ -92,6 +96,12 @@ pub fn init(cx: &mut AppContext) {
|
||||
cx.add_action(|_: &mut Workspace, _: &StartOfLine, cx: _| motion(Motion::StartOfLine, cx));
|
||||
cx.add_action(|_: &mut Workspace, _: &EndOfLine, cx: _| motion(Motion::EndOfLine, cx));
|
||||
cx.add_action(|_: &mut Workspace, _: &CurrentLine, cx: _| motion(Motion::CurrentLine, cx));
|
||||
cx.add_action(|_: &mut Workspace, _: &StartOfParagraph, cx: _| {
|
||||
motion(Motion::StartOfParagraph, cx)
|
||||
});
|
||||
cx.add_action(|_: &mut Workspace, _: &EndOfParagraph, cx: _| {
|
||||
motion(Motion::EndOfParagraph, cx)
|
||||
});
|
||||
cx.add_action(|_: &mut Workspace, _: &StartOfDocument, cx: _| {
|
||||
motion(Motion::StartOfDocument, cx)
|
||||
});
|
||||
@ -142,7 +152,8 @@ impl Motion {
|
||||
pub fn linewise(&self) -> bool {
|
||||
use Motion::*;
|
||||
match self {
|
||||
Down | Up | StartOfDocument | EndOfDocument | CurrentLine | NextLineStart => true,
|
||||
Down | Up | StartOfDocument | EndOfDocument | CurrentLine | NextLineStart
|
||||
| StartOfParagraph | EndOfParagraph => true,
|
||||
EndOfLine
|
||||
| NextWordEnd { .. }
|
||||
| Matching
|
||||
@ -172,6 +183,8 @@ impl Motion {
|
||||
| Backspace
|
||||
| Right
|
||||
| StartOfLine
|
||||
| StartOfParagraph
|
||||
| EndOfParagraph
|
||||
| NextWordStart { .. }
|
||||
| PreviousWordStart { .. }
|
||||
| FirstNonWhitespace
|
||||
@ -197,6 +210,8 @@ impl Motion {
|
||||
| Backspace
|
||||
| Right
|
||||
| StartOfLine
|
||||
| StartOfParagraph
|
||||
| EndOfParagraph
|
||||
| NextWordStart { .. }
|
||||
| PreviousWordStart { .. }
|
||||
| FirstNonWhitespace
|
||||
@ -235,6 +250,14 @@ impl Motion {
|
||||
FirstNonWhitespace => (first_non_whitespace(map, point), SelectionGoal::None),
|
||||
StartOfLine => (start_of_line(map, point), SelectionGoal::None),
|
||||
EndOfLine => (end_of_line(map, point), SelectionGoal::None),
|
||||
StartOfParagraph => (
|
||||
movement::start_of_paragraph(map, point, times),
|
||||
SelectionGoal::None,
|
||||
),
|
||||
EndOfParagraph => (
|
||||
movement::end_of_paragraph(map, point, times),
|
||||
SelectionGoal::None,
|
||||
),
|
||||
CurrentLine => (end_of_line(map, point), SelectionGoal::None),
|
||||
StartOfDocument => (start_of_document(map, point, times), SelectionGoal::None),
|
||||
EndOfDocument => (
|
||||
@ -590,3 +613,96 @@ fn next_line_start(map: &DisplaySnapshot, point: DisplayPoint, times: usize) ->
|
||||
let new_row = (point.row() + times as u32).min(map.max_buffer_row());
|
||||
map.clip_point(DisplayPoint::new(new_row, 0), Bias::Left)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
mod test {
|
||||
|
||||
use crate::{state::Mode, test::VimTestContext};
|
||||
use indoc::indoc;
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_start_end_of_paragraph(cx: &mut gpui::TestAppContext) {
|
||||
let mut cx = VimTestContext::new(cx, true).await;
|
||||
|
||||
let initial_state = indoc! {r"ˇabc
|
||||
def
|
||||
|
||||
paragraph
|
||||
the second
|
||||
|
||||
|
||||
|
||||
third and
|
||||
final"};
|
||||
|
||||
// goes down once
|
||||
cx.set_state(initial_state, Mode::Normal);
|
||||
cx.simulate_keystrokes(["}"]);
|
||||
cx.assert_state(
|
||||
indoc! {r"abc
|
||||
def
|
||||
ˇ
|
||||
paragraph
|
||||
the second
|
||||
|
||||
|
||||
|
||||
third and
|
||||
final"},
|
||||
Mode::Normal,
|
||||
);
|
||||
|
||||
// goes up once
|
||||
cx.simulate_keystrokes(["{"]);
|
||||
cx.assert_state(initial_state, Mode::Normal);
|
||||
|
||||
// goes down twice
|
||||
cx.simulate_keystrokes(["2", "}"]);
|
||||
cx.assert_state(
|
||||
indoc! {r"abc
|
||||
def
|
||||
|
||||
paragraph
|
||||
the second
|
||||
ˇ
|
||||
|
||||
|
||||
third and
|
||||
final"},
|
||||
Mode::Normal,
|
||||
);
|
||||
|
||||
// goes down over multiple blanks
|
||||
cx.simulate_keystrokes(["}"]);
|
||||
cx.assert_state(
|
||||
indoc! {r"abc
|
||||
def
|
||||
|
||||
paragraph
|
||||
the second
|
||||
|
||||
|
||||
|
||||
third and
|
||||
finalˇ"},
|
||||
Mode::Normal,
|
||||
);
|
||||
|
||||
// goes up twice
|
||||
cx.simulate_keystrokes(["2", "{"]);
|
||||
cx.assert_state(
|
||||
indoc! {r"abc
|
||||
def
|
||||
ˇ
|
||||
paragraph
|
||||
the second
|
||||
|
||||
|
||||
|
||||
third and
|
||||
final"},
|
||||
Mode::Normal,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user