1769 lines · 53.7 KB · Rust
RawDownload
use editor::{    display_map::{DisplaySnapshot, FoldPoint, ToDisplayPoint},    movement::{        self, find_boundary, find_preceding_boundary_display_point, FindRange, TextLayoutDetails,    },    Bias, DisplayPoint, ToOffset,};use gpui::{actions, impl_actions, px, ViewContext, WindowContext};use language::{char_kind, CharKind, Point, Selection, SelectionGoal};use serde::Deserialize;use workspace::Workspace; use crate::{    normal::normal_motion,    state::{Mode, Operator},    utils::coerce_punctuation,    visual::visual_motion,    Vim,}; #[derive(Clone, Debug, PartialEq, Eq)]pub enum Motion {    Left,    Backspace,    Down {        display_lines: bool,    },    Up {        display_lines: bool,    },    Right,    Space,    NextWordStart {        ignore_punctuation: bool,    },    NextWordEnd {        ignore_punctuation: bool,    },    PreviousWordStart {        ignore_punctuation: bool,    },    PreviousWordEnd {        ignore_punctuation: bool,    },    FirstNonWhitespace {        display_lines: bool,    },    CurrentLine,    StartOfLine {        display_lines: bool,    },    EndOfLine {        display_lines: bool,    },    StartOfParagraph,    EndOfParagraph,    StartOfDocument,    EndOfDocument,    Matching,    FindForward {        before: bool,        char: char,        mode: FindRange,    },    FindBackward {        after: bool,        char: char,        mode: FindRange,    },    RepeatFind {        last_find: Box<Motion>,    },    RepeatFindReversed {        last_find: Box<Motion>,    },    NextLineStart,    StartOfLineDownward,    EndOfLineDownward,    GoToColumn,    WindowTop,    WindowMiddle,    WindowBottom,} #[derive(Clone, Deserialize, PartialEq)]#[serde(rename_all = "camelCase")]struct NextWordStart {    #[serde(default)]    ignore_punctuation: bool,} #[derive(Clone, Deserialize, PartialEq)]#[serde(rename_all = "camelCase")]struct NextWordEnd {    #[serde(default)]    ignore_punctuation: bool,} #[derive(Clone, Deserialize, PartialEq)]#[serde(rename_all = "camelCase")]struct PreviousWordStart {    #[serde(default)]    ignore_punctuation: bool,} #[derive(Clone, Deserialize, PartialEq)]#[serde(rename_all = "camelCase")]struct PreviousWordEnd {    #[serde(default)]    ignore_punctuation: bool,} #[derive(Clone, Deserialize, PartialEq)]#[serde(rename_all = "camelCase")]pub(crate) struct Up {    #[serde(default)]    pub(crate) display_lines: bool,} #[derive(Clone, Deserialize, PartialEq)]#[serde(rename_all = "camelCase")]pub(crate) struct Down {    #[serde(default)]    pub(crate) display_lines: bool,} #[derive(Clone, Deserialize, PartialEq)]#[serde(rename_all = "camelCase")]struct FirstNonWhitespace {    #[serde(default)]    display_lines: bool,} #[derive(Clone, Deserialize, PartialEq)]#[serde(rename_all = "camelCase")]struct EndOfLine {    #[serde(default)]    display_lines: bool,} #[derive(Clone, Deserialize, PartialEq)]#[serde(rename_all = "camelCase")]pub struct StartOfLine {    #[serde(default)]    pub(crate) display_lines: bool,} impl_actions!(    vim,    [        StartOfLine,        EndOfLine,        FirstNonWhitespace,        Down,        Up,        PreviousWordStart,        PreviousWordEnd,        NextWordEnd,        NextWordStart    ]); actions!(    vim,    [        Left,        Backspace,        Right,        Space,        CurrentLine,        StartOfParagraph,        EndOfParagraph,        StartOfDocument,        EndOfDocument,        Matching,        NextLineStart,        StartOfLineDownward,        EndOfLineDownward,        GoToColumn,        RepeatFind,        RepeatFindReversed,        WindowTop,        WindowMiddle,        WindowBottom,    ]); pub fn register(workspace: &mut Workspace, _: &mut ViewContext<Workspace>) {    workspace.register_action(|_: &mut Workspace, _: &Left, cx: _| motion(Motion::Left, cx));    workspace        .register_action(|_: &mut Workspace, _: &Backspace, cx: _| motion(Motion::Backspace, cx));    workspace.register_action(|_: &mut Workspace, action: &Down, cx: _| {        motion(            Motion::Down {                display_lines: action.display_lines,            },            cx,        )    });    workspace.register_action(|_: &mut Workspace, action: &Up, cx: _| {        motion(            Motion::Up {                display_lines: action.display_lines,            },            cx,        )    });    workspace.register_action(|_: &mut Workspace, _: &Right, cx: _| motion(Motion::Right, cx));    workspace.register_action(|_: &mut Workspace, _: &Space, cx: _| motion(Motion::Space, cx));    workspace.register_action(|_: &mut Workspace, action: &FirstNonWhitespace, cx: _| {        motion(            Motion::FirstNonWhitespace {                display_lines: action.display_lines,            },            cx,        )    });    workspace.register_action(|_: &mut Workspace, action: &StartOfLine, cx: _| {        motion(            Motion::StartOfLine {                display_lines: action.display_lines,            },            cx,        )    });    workspace.register_action(|_: &mut Workspace, action: &EndOfLine, cx: _| {        motion(            Motion::EndOfLine {                display_lines: action.display_lines,            },            cx,        )    });    workspace.register_action(|_: &mut Workspace, _: &CurrentLine, cx: _| {        motion(Motion::CurrentLine, cx)    });    workspace.register_action(|_: &mut Workspace, _: &StartOfParagraph, cx: _| {        motion(Motion::StartOfParagraph, cx)    });    workspace.register_action(|_: &mut Workspace, _: &EndOfParagraph, cx: _| {        motion(Motion::EndOfParagraph, cx)    });    workspace.register_action(|_: &mut Workspace, _: &StartOfDocument, cx: _| {        motion(Motion::StartOfDocument, cx)    });    workspace.register_action(|_: &mut Workspace, _: &EndOfDocument, cx: _| {        motion(Motion::EndOfDocument, cx)    });    workspace        .register_action(|_: &mut Workspace, _: &Matching, cx: _| motion(Motion::Matching, cx));     workspace.register_action(        |_: &mut Workspace, &NextWordStart { ignore_punctuation }: &NextWordStart, cx: _| {            motion(Motion::NextWordStart { ignore_punctuation }, cx)        },    );    workspace.register_action(        |_: &mut Workspace, &NextWordEnd { ignore_punctuation }: &NextWordEnd, cx: _| {            motion(Motion::NextWordEnd { ignore_punctuation }, cx)        },    );    workspace.register_action(        |_: &mut Workspace,         &PreviousWordStart { ignore_punctuation }: &PreviousWordStart,         cx: _| { motion(Motion::PreviousWordStart { ignore_punctuation }, cx) },    );    workspace.register_action(|_: &mut Workspace, &NextLineStart, cx: _| {        motion(Motion::NextLineStart, cx)    });    workspace.register_action(|_: &mut Workspace, &StartOfLineDownward, cx: _| {        motion(Motion::StartOfLineDownward, cx)    });    workspace.register_action(|_: &mut Workspace, &EndOfLineDownward, cx: _| {        motion(Motion::EndOfLineDownward, cx)    });    workspace        .register_action(|_: &mut Workspace, &GoToColumn, cx: _| motion(Motion::GoToColumn, cx));     workspace.register_action(|_: &mut Workspace, _: &RepeatFind, cx: _| {        if let Some(last_find) = Vim::read(cx)            .workspace_state            .last_find            .clone()            .map(Box::new)        {            motion(Motion::RepeatFind { last_find }, cx);        }    });     workspace.register_action(|_: &mut Workspace, _: &RepeatFindReversed, cx: _| {        if let Some(last_find) = Vim::read(cx)            .workspace_state            .last_find            .clone()            .map(Box::new)        {            motion(Motion::RepeatFindReversed { last_find }, cx);        }    });    workspace.register_action(|_: &mut Workspace, &WindowTop, cx: _| motion(Motion::WindowTop, cx));    workspace.register_action(|_: &mut Workspace, &WindowMiddle, cx: _| {        motion(Motion::WindowMiddle, cx)    });    workspace.register_action(|_: &mut Workspace, &WindowBottom, cx: _| {        motion(Motion::WindowBottom, cx)    });    workspace.register_action(        |_: &mut Workspace, &PreviousWordEnd { ignore_punctuation }, cx: _| {            motion(Motion::PreviousWordEnd { ignore_punctuation }, cx)        },    );} pub(crate) fn motion(motion: Motion, cx: &mut WindowContext) {    if let Some(Operator::FindForward { .. }) | Some(Operator::FindBackward { .. }) =        Vim::read(cx).active_operator()    {        Vim::update(cx, |vim, cx| vim.pop_operator(cx));    }     let count = Vim::update(cx, |vim, cx| vim.take_count(cx));    let operator = Vim::read(cx).active_operator();    match Vim::read(cx).state().mode {        Mode::Normal => normal_motion(motion, operator, count, cx),        Mode::Visual | Mode::VisualLine | Mode::VisualBlock => visual_motion(motion, count, cx),        Mode::Insert => {            // Shouldn't execute a motion in insert mode. Ignoring        }    }    Vim::update(cx, |vim, cx| vim.clear_operator(cx));} // Motion handling is specified here:// https://github.com/vim/vim/blob/master/runtime/doc/motion.txtimpl Motion {    pub fn linewise(&self) -> bool {        use Motion::*;        match self {            Down { .. }            | Up { .. }            | StartOfDocument            | EndOfDocument            | CurrentLine            | NextLineStart            | StartOfLineDownward            | StartOfParagraph            | WindowTop            | WindowMiddle            | WindowBottom            | EndOfParagraph => true,            EndOfLine { .. }            | NextWordEnd { .. }            | Matching            | FindForward { .. }            | Left            | Backspace            | Right            | Space            | StartOfLine { .. }            | EndOfLineDownward            | GoToColumn            | NextWordStart { .. }            | PreviousWordStart { .. }            | PreviousWordEnd { .. }            | FirstNonWhitespace { .. }            | FindBackward { .. }            | RepeatFind { .. }            | RepeatFindReversed { .. } => false,        }    }     pub fn infallible(&self) -> bool {        use Motion::*;        match self {            StartOfDocument | EndOfDocument | CurrentLine => true,            Down { .. }            | Up { .. }            | EndOfLine { .. }            | NextWordEnd { .. }            | Matching            | FindForward { .. }            | RepeatFind { .. }            | Left            | Backspace            | Right            | Space            | StartOfLine { .. }            | StartOfParagraph            | EndOfParagraph            | StartOfLineDownward            | EndOfLineDownward            | GoToColumn            | NextWordStart { .. }            | PreviousWordStart { .. }            | FirstNonWhitespace { .. }            | FindBackward { .. }            | RepeatFindReversed { .. }            | WindowTop            | WindowMiddle            | WindowBottom            | PreviousWordEnd { .. }            | NextLineStart => false,        }    }     pub fn inclusive(&self) -> bool {        use Motion::*;        match self {            Down { .. }            | Up { .. }            | StartOfDocument            | EndOfDocument            | CurrentLine            | EndOfLine { .. }            | EndOfLineDownward            | NextWordEnd { .. }            | Matching            | FindForward { .. }            | WindowTop            | WindowMiddle            | WindowBottom            | PreviousWordEnd { .. }            | NextLineStart => true,            Left            | Backspace            | Right            | Space            | StartOfLine { .. }            | StartOfLineDownward            | StartOfParagraph            | EndOfParagraph            | GoToColumn            | NextWordStart { .. }            | PreviousWordStart { .. }            | FirstNonWhitespace { .. }            | FindBackward { .. } => false,            RepeatFind { last_find: motion } | RepeatFindReversed { last_find: motion } => {                motion.inclusive()            }        }    }     pub fn move_point(        &self,        map: &DisplaySnapshot,        point: DisplayPoint,        goal: SelectionGoal,        maybe_times: Option<usize>,        text_layout_details: &TextLayoutDetails,    ) -> Option<(DisplayPoint, SelectionGoal)> {        let times = maybe_times.unwrap_or(1);        use Motion::*;        let infallible = self.infallible();        let (new_point, goal) = match self {            Left => (left(map, point, times), SelectionGoal::None),            Backspace => (backspace(map, point, times), SelectionGoal::None),            Down {                display_lines: false,            } => up_down_buffer_rows(map, point, goal, times as isize, &text_layout_details),            Down {                display_lines: true,            } => down_display(map, point, goal, times, &text_layout_details),            Up {                display_lines: false,            } => up_down_buffer_rows(map, point, goal, 0 - times as isize, &text_layout_details),            Up {                display_lines: true,            } => up_display(map, point, goal, times, &text_layout_details),            Right => (right(map, point, times), SelectionGoal::None),            Space => (space(map, point, times), SelectionGoal::None),            NextWordStart { ignore_punctuation } => (                next_word_start(map, point, *ignore_punctuation, times),                SelectionGoal::None,            ),            NextWordEnd { ignore_punctuation } => (                next_word_end(map, point, *ignore_punctuation, times),                SelectionGoal::None,            ),            PreviousWordStart { ignore_punctuation } => (                previous_word_start(map, point, *ignore_punctuation, times),                SelectionGoal::None,            ),            PreviousWordEnd { ignore_punctuation } => (                previous_word_end(map, point, *ignore_punctuation, times),                SelectionGoal::None,            ),            FirstNonWhitespace { display_lines } => (                first_non_whitespace(map, *display_lines, point),                SelectionGoal::None,            ),            StartOfLine { display_lines } => (                start_of_line(map, *display_lines, point),                SelectionGoal::None,            ),            EndOfLine { display_lines } => (                end_of_line(map, *display_lines, point, times),                SelectionGoal::None,            ),            StartOfParagraph => (                movement::start_of_paragraph(map, point, times),

Lines 1–500 of 1769.