@@ -27,6 +27,7 @@
"h": "vim::Left",
"backspace": "vim::Backspace",
"j": "vim::Down",
+ "enter": "vim::NextLineStart",
"k": "vim::Up",
"l": "vim::Right",
"$": "vim::EndOfLine",
@@ -36,6 +36,7 @@ pub enum Motion {
Matching,
FindForward { before: bool, text: Arc<str> },
FindBackward { after: bool, text: Arc<str> },
+ NextLineStart,
}
#[derive(Clone, Deserialize, PartialEq)]
@@ -74,6 +75,7 @@ actions!(
StartOfDocument,
EndOfDocument,
Matching,
+ NextLineStart,
]
);
impl_actions!(vim, [NextWordStart, NextWordEnd, PreviousWordStart]);
@@ -111,6 +113,7 @@ pub fn init(cx: &mut MutableAppContext) {
&PreviousWordStart { ignore_punctuation }: &PreviousWordStart,
cx: _| { motion(Motion::PreviousWordStart { ignore_punctuation }, cx) },
);
+ cx.add_action(|_: &mut Workspace, &NextLineStart, cx: _| motion(Motion::NextLineStart, cx))
}
pub(crate) fn motion(motion: Motion, cx: &mut MutableAppContext) {
@@ -138,15 +141,43 @@ pub(crate) fn motion(motion: Motion, cx: &mut MutableAppContext) {
impl Motion {
pub fn linewise(&self) -> bool {
use Motion::*;
- matches!(
- self,
- Down | Up | StartOfDocument | EndOfDocument | CurrentLine
- )
+ match self {
+ Down | Up | StartOfDocument | EndOfDocument | CurrentLine | NextLineStart => true,
+ EndOfLine
+ | NextWordEnd { .. }
+ | Matching
+ | FindForward { .. }
+ | Left
+ | Backspace
+ | Right
+ | StartOfLine
+ | NextWordStart { .. }
+ | PreviousWordStart { .. }
+ | FirstNonWhitespace
+ | FindBackward { .. } => false,
+ }
}
pub fn infallible(&self) -> bool {
use Motion::*;
- matches!(self, StartOfDocument | CurrentLine | EndOfDocument)
+ match self {
+ StartOfDocument | EndOfDocument | CurrentLine => true,
+ Down
+ | Up
+ | EndOfLine
+ | NextWordEnd { .. }
+ | Matching
+ | FindForward { .. }
+ | Left
+ | Backspace
+ | Right
+ | StartOfLine
+ | NextWordStart { .. }
+ | PreviousWordStart { .. }
+ | FirstNonWhitespace
+ | FindBackward { .. }
+ | NextLineStart => false,
+ }
}
pub fn inclusive(&self) -> bool {
@@ -160,7 +191,8 @@ impl Motion {
| EndOfLine
| NextWordEnd { .. }
| Matching
- | FindForward { .. } => true,
+ | FindForward { .. }
+ | NextLineStart => true,
Left
| Backspace
| Right
@@ -214,6 +246,7 @@ impl Motion {
find_backward(map, point, *after, text.clone(), times),
SelectionGoal::None,
),
+ NextLineStart => (next_line_start(map, point, times), SelectionGoal::None),
};
(new_point != point || infallible).then_some((new_point, goal))
@@ -543,3 +576,8 @@ fn find_backward(
})
.unwrap_or(from)
}
+
+fn next_line_start(map: &DisplaySnapshot, point: DisplayPoint, times: usize) -> DisplayPoint {
+ let new_row = (point.row() + times as u32).min(map.max_buffer_row());
+ map.clip_point(DisplayPoint::new(new_row, 0), Bias::Left)
+}
@@ -473,6 +473,7 @@ pub(crate) fn normal_replace(text: Arc<str>, cx: &mut MutableAppContext) {
#[cfg(test)]
mod test {
+ use gpui::TestAppContext;
use indoc::indoc;
use crate::{
@@ -515,15 +516,15 @@ mod test {
.await;
}
- // #[gpui::test]
- // async fn test_enter(cx: &mut gpui::TestAppContext) {
- // let mut cx = NeovimBackedTestContext::new(cx).await.binding(["enter"]);
- // cx.assert_all(indoc! {"
- // ˇThe qˇuick broˇwn
- // ˇfox jumps"
- // })
- // .await;
- // }
+ #[gpui::test]
+ async fn test_enter(cx: &mut gpui::TestAppContext) {
+ let mut cx = NeovimBackedTestContext::new(cx).await.binding(["enter"]);
+ cx.assert_all(indoc! {"
+ ˇThe qˇuick broˇwn
+ ˇfox jumps"
+ })
+ .await;
+ }
#[gpui::test]
async fn test_k(cx: &mut gpui::TestAppContext) {
@@ -1030,7 +1031,7 @@ mod test {
}
#[gpui::test]
- async fn test_percent(cx: &mut gpui::TestAppContext) {
+ async fn test_percent(cx: &mut TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["%"]);
cx.assert_all("ˇconsole.logˇ(ˇvaˇrˇ)ˇ;").await;
cx.assert_all("ˇconsole.logˇ(ˇ'var', ˇ[ˇ1, ˇ2, 3ˇ]ˇ)ˇ;")
@@ -0,0 +1 @@
+[{"Text":"The quick brown\nfox jumps"},{"Mode":"Normal"},{"Selection":{"start":[1,0],"end":[1,0]}},{"Mode":"Normal"},{"Text":"The quick brown\nfox jumps"},{"Mode":"Normal"},{"Selection":{"start":[1,0],"end":[1,0]}},{"Mode":"Normal"},{"Text":"The quick brown\nfox jumps"},{"Mode":"Normal"},{"Selection":{"start":[1,0],"end":[1,0]}},{"Mode":"Normal"},{"Text":"The quick brown\nfox jumps"},{"Mode":"Normal"},{"Selection":{"start":[1,0],"end":[1,0]}},{"Mode":"Normal"}]