use editor::{ Anchor, Bias, BufferOffset, DisplayPoint, Editor, MultiBufferOffset, RowExt, ToOffset, display_map::{DisplayRow, DisplaySnapshot, FoldPoint, ToDisplayPoint}, movement::{ self, FindRange, TextLayoutDetails, find_boundary, find_preceding_boundary_display_point, },};use gpui::{Action, Context, Window, actions, px};use language::{CharKind, Point, Selection, SelectionGoal};use multi_buffer::MultiBufferRow;use schemars::JsonSchema;use serde::Deserialize;use std::{f64, ops::Range};use workspace::searchable::Direction; use crate::{ Vim, normal::mark, state::{Mode, Operator}, surrounds::SurroundsType,}; #[derive(Clone, Copy, Debug, PartialEq, Eq)]pub(crate) enum MotionKind { Linewise, Exclusive, Inclusive,} impl MotionKind { pub(crate) fn for_mode(mode: Mode) -> Self { match mode { Mode::VisualLine => MotionKind::Linewise, _ => MotionKind::Exclusive, } } pub(crate) fn linewise(&self) -> bool { matches!(self, MotionKind::Linewise) }} #[derive(Clone, Debug, PartialEq, Eq)]pub enum Motion { Left, WrappingLeft, Down { display_lines: bool, }, Up { display_lines: bool, }, Right, WrappingRight, NextWordStart { ignore_punctuation: bool, }, NextWordEnd { ignore_punctuation: bool, }, PreviousWordStart { ignore_punctuation: bool, }, PreviousWordEnd { ignore_punctuation: bool, }, NextSubwordStart { ignore_punctuation: bool, }, NextSubwordEnd { ignore_punctuation: bool, }, PreviousSubwordStart { ignore_punctuation: bool, }, PreviousSubwordEnd { ignore_punctuation: bool, }, FirstNonWhitespace { display_lines: bool, }, CurrentLine, StartOfLine { display_lines: bool, }, MiddleOfLine { display_lines: bool, }, EndOfLine { display_lines: bool, }, SentenceBackward, SentenceForward, StartOfParagraph, EndOfParagraph, StartOfDocument, EndOfDocument, Matching { match_quotes: bool, }, GoToPercentage, UnmatchedForward { char: char, }, UnmatchedBackward { char: char, }, FindForward { before: bool, char: char, mode: FindRange, smartcase: bool, }, FindBackward { after: bool, char: char, mode: FindRange, smartcase: bool, }, Sneak { first_char: char, second_char: char, smartcase: bool, }, SneakBackward { first_char: char, second_char: char, smartcase: bool, }, RepeatFind { last_find: Box<Motion>, }, RepeatFindReversed { last_find: Box<Motion>, }, NextLineStart, PreviousLineStart, StartOfLineDownward, EndOfLineDownward, GoToColumn, WindowTop, WindowMiddle, WindowBottom, NextSectionStart, NextSectionEnd, PreviousSectionStart, PreviousSectionEnd, NextMethodStart, NextMethodEnd, PreviousMethodStart, PreviousMethodEnd, NextComment, PreviousComment, PreviousLesserIndent, PreviousGreaterIndent, PreviousSameIndent, NextLesserIndent, NextGreaterIndent, NextSameIndent, // we don't have a good way to run a search synchronously, so // we handle search motions by running the search async and then // calling back into motion with this ZedSearchResult { prior_selections: Vec<Range<Anchor>>, new_selections: Vec<Range<Anchor>>, }, Jump { anchor: Anchor, line: bool, },} #[derive(Clone, Copy)]enum IndentType { Lesser, Greater, Same,} /// Moves to the start of the next word.#[derive(Clone, Deserialize, JsonSchema, PartialEq, Action)]#[action(namespace = vim)]#[serde(deny_unknown_fields)]struct NextWordStart { #[serde(default)] ignore_punctuation: bool,} /// Moves to the end of the next word.#[derive(Clone, Deserialize, JsonSchema, PartialEq, Action)]#[action(namespace = vim)]#[serde(deny_unknown_fields)]struct NextWordEnd { #[serde(default)] ignore_punctuation: bool,} /// Moves to the start of the previous word.#[derive(Clone, Deserialize, JsonSchema, PartialEq, Action)]#[action(namespace = vim)]#[serde(deny_unknown_fields)]struct PreviousWordStart { #[serde(default)] ignore_punctuation: bool,} /// Moves to the end of the previous word.#[derive(Clone, Deserialize, JsonSchema, PartialEq, Action)]#[action(namespace = vim)]#[serde(deny_unknown_fields)]struct PreviousWordEnd { #[serde(default)] ignore_punctuation: bool,} /// Moves to the start of the next subword.#[derive(Clone, Deserialize, JsonSchema, PartialEq, Action)]#[action(namespace = vim)]#[serde(deny_unknown_fields)]pub(crate) struct NextSubwordStart { #[serde(default)] pub(crate) ignore_punctuation: bool,} /// Moves to the end of the next subword.#[derive(Clone, Deserialize, JsonSchema, PartialEq, Action)]#[action(namespace = vim)]#[serde(deny_unknown_fields)]pub(crate) struct NextSubwordEnd { #[serde(default)] pub(crate) ignore_punctuation: bool,} /// Moves to the start of the previous subword.#[derive(Clone, Deserialize, JsonSchema, PartialEq, Action)]#[action(namespace = vim)]#[serde(deny_unknown_fields)]pub(crate) struct PreviousSubwordStart { #[serde(default)] pub(crate) ignore_punctuation: bool,} /// Moves to the end of the previous subword.#[derive(Clone, Deserialize, JsonSchema, PartialEq, Action)]#[action(namespace = vim)]#[serde(deny_unknown_fields)]pub(crate) struct PreviousSubwordEnd { #[serde(default)] pub(crate) ignore_punctuation: bool,} /// Moves cursor up by the specified number of lines.#[derive(Clone, Deserialize, JsonSchema, PartialEq, Action)]#[action(namespace = vim)]#[serde(deny_unknown_fields)]pub(crate) struct Up { #[serde(default)] pub(crate) display_lines: bool,} /// Moves cursor down by the specified number of lines.#[derive(Clone, Deserialize, JsonSchema, PartialEq, Action)]#[action(namespace = vim)]#[serde(deny_unknown_fields)]pub(crate) struct Down { #[serde(default)] pub(crate) display_lines: bool,} /// Moves to the first non-whitespace character on the current line.#[derive(Clone, Deserialize, JsonSchema, PartialEq, Action)]#[action(namespace = vim)]#[serde(deny_unknown_fields)]struct FirstNonWhitespace { #[serde(default)] display_lines: bool,} /// Moves to the matching bracket or delimiter.#[derive(Clone, Deserialize, JsonSchema, PartialEq, Action)]#[action(namespace = vim)]#[serde(deny_unknown_fields)]struct Matching { #[serde(default)] /// Whether to include quote characters (`'`, `"`, `` ` ``) when searching /// for matching pairs. When `false`, only brackets and parentheses are /// matched, which aligns with Neovim's default `%` behavior. match_quotes: bool,} /// Moves to the end of the current line.#[derive(Clone, Deserialize, JsonSchema, PartialEq, Action)]#[action(namespace = vim)]#[serde(deny_unknown_fields)]struct EndOfLine { #[serde(default)] display_lines: bool,} /// Moves to the start of the current line.#[derive(Clone, Deserialize, JsonSchema, PartialEq, Action)]#[action(namespace = vim)]#[serde(deny_unknown_fields)]pub struct StartOfLine { #[serde(default)] pub(crate) display_lines: bool,} /// Moves to the middle of the current line.#[derive(Clone, Deserialize, JsonSchema, PartialEq, Action)]#[action(namespace = vim)]#[serde(deny_unknown_fields)]struct MiddleOfLine { #[serde(default)] display_lines: bool,} /// Finds the next unmatched bracket or delimiter.#[derive(Clone, Deserialize, JsonSchema, PartialEq, Action)]#[action(namespace = vim)]#[serde(deny_unknown_fields)]struct UnmatchedForward { #[serde(default)] char: char,} /// Finds the previous unmatched bracket or delimiter.#[derive(Clone, Deserialize, JsonSchema, PartialEq, Action)]#[action(namespace = vim)]#[serde(deny_unknown_fields)]struct UnmatchedBackward { #[serde(default)] char: char,} actions!( vim, [ /// Moves cursor left one character. Left, /// Moves cursor left one character, wrapping to previous line. #[action(deprecated_aliases = ["vim::Backspace"])] WrappingLeft, /// Moves cursor right one character. Right, /// Moves cursor right one character, wrapping to next line. #[action(deprecated_aliases = ["vim::Space"])] WrappingRight, /// Selects the current line. CurrentLine, /// Moves to the start of the next sentence. SentenceForward, /// Moves to the start of the previous sentence. SentenceBackward, /// Moves to the start of the paragraph. StartOfParagraph, /// Moves to the end of the paragraph. EndOfParagraph, /// Moves to the start of the document. StartOfDocument, /// Moves to the end of the document. EndOfDocument, /// Goes to a percentage position in the file. GoToPercentage, /// Moves to the start of the next line. NextLineStart, /// Moves to the start of the previous line. PreviousLineStart, /// Moves to the start of a line downward. StartOfLineDownward, /// Moves to the end of a line downward. EndOfLineDownward, /// Goes to a specific column number. GoToColumn, /// Repeats the last character find. RepeatFind, /// Repeats the last character find in reverse. RepeatFindReversed, /// Moves to the top of the window. WindowTop, /// Moves to the middle of the window. WindowMiddle, /// Moves to the bottom of the window. WindowBottom, /// Moves to the start of the next section. NextSectionStart, /// Moves to the end of the next section. NextSectionEnd, /// Moves to the start of the previous section. PreviousSectionStart, /// Moves to the end of the previous section. PreviousSectionEnd, /// Moves to the start of the next method. NextMethodStart, /// Moves to the end of the next method. NextMethodEnd, /// Moves to the start of the previous method. PreviousMethodStart, /// Moves to the end of the previous method. PreviousMethodEnd, /// Moves to the next comment. NextComment, /// Moves to the previous comment. PreviousComment, /// Moves to the previous line with lesser indentation. PreviousLesserIndent, /// Moves to the previous line with greater indentation. PreviousGreaterIndent, /// Moves to the previous line with the same indentation. PreviousSameIndent, /// Moves to the next line with lesser indentation. NextLesserIndent, /// Moves to the next line with greater indentation. NextGreaterIndent, /// Moves to the next line with the same indentation. NextSameIndent, ]); pub fn register(editor: &mut Editor, cx: &mut Context<Vim>) { Vim::action(editor, cx, |vim, _: &Left, window, cx| { vim.motion(Motion::Left, window, cx) }); Vim::action(editor, cx, |vim, _: &WrappingLeft, window, cx| { vim.motion(Motion::WrappingLeft, window, cx) }); Vim::action(editor, cx, |vim, action: &Down, window, cx| { vim.motion( Motion::Down { display_lines: action.display_lines, }, window, cx, ) }); Vim::action(editor, cx, |vim, action: &Up, window, cx| { vim.motion( Motion::Up { display_lines: action.display_lines, }, window, cx, ) }); Vim::action(editor, cx, |vim, _: &Right, window, cx| { vim.motion(Motion::Right, window, cx) }); Vim::action(editor, cx, |vim, _: &WrappingRight, window, cx| { vim.motion(Motion::WrappingRight, window, cx) }); Vim::action( editor, cx, |vim, action: &FirstNonWhitespace, window, cx| { vim.motion( Motion::FirstNonWhitespace { display_lines: action.display_lines, }, window, cx, ) }, ); Vim::action(editor, cx, |vim, action: &StartOfLine, window, cx| { vim.motion( Motion::StartOfLine { display_lines: action.display_lines, }, window, cx, ) }); Vim::action(editor, cx, |vim, action: &MiddleOfLine, window, cx| { vim.motion( Motion::MiddleOfLine { display_lines: action.display_lines, }, window, cx, ) }); Vim::action(editor, cx, |vim, action: &EndOfLine, window, cx| { vim.motion( Motion::EndOfLine { display_lines: action.display_lines, }, window, cx, ) }); Vim::action(editor, cx, |vim, _: &CurrentLine, window, cx| { vim.motion(Motion::CurrentLine, window, cx) }); Vim::action(editor, cx, |vim, _: &StartOfParagraph, window, cx| { vim.motion(Motion::StartOfParagraph, window, cx) }); Vim::action(editor, cx, |vim, _: &EndOfParagraph, window, cx| { vim.motion(Motion::EndOfParagraph, window, cx) });Lines 1–500 of 5218. Load more
use editor::{ Anchor, Bias, BufferOffset, DisplayPoint, Editor, MultiBufferOffset, RowExt, ToOffset, display_map::{DisplayRow, DisplaySnapshot, FoldPoint, ToDisplayPoint}, movement::{ self, FindRange, TextLayoutDetails, find_boundary, find_preceding_boundary_display_point, }, }; use gpui::{Action, Context, Window, actions, px}; use language::{CharKind, Point, Selection, SelectionGoal}; use multi_buffer::MultiBufferRow; use schemars::JsonSchema; use serde::Deserialize; use std::{f64, ops::Range}; use workspace::searchable::Direction; use crate::{ Vim, normal::mark, state::{Mode, Operator}, surrounds::SurroundsType, }; #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub(crate) enum MotionKind { Linewise, Exclusive, Inclusive, } impl MotionKind { pub(crate) fn for_mode(mode: Mode) -> Self { match mode { Mode::VisualLine => MotionKind::Linewise, _ => MotionKind::Exclusive, } } pub(crate) fn linewise(&self) -> bool { matches!(self, MotionKind::Linewise) } } #[derive(Clone, Debug, PartialEq, Eq)] pub enum Motion { Left, WrappingLeft, Down { display_lines: bool, }, Up { display_lines: bool, }, Right, WrappingRight, NextWordStart { ignore_punctuation: bool, }, NextWordEnd { ignore_punctuation: bool, }, PreviousWordStart { ignore_punctuation: bool, }, PreviousWordEnd { ignore_punctuation: bool, }, NextSubwordStart { ignore_punctuation: bool, }, NextSubwordEnd { ignore_punctuation: bool, }, PreviousSubwordStart { ignore_punctuation: bool, }, PreviousSubwordEnd { ignore_punctuation: bool, }, FirstNonWhitespace { display_lines: bool, }, CurrentLine, StartOfLine { display_lines: bool, }, MiddleOfLine { display_lines: bool, }, EndOfLine { display_lines: bool, }, SentenceBackward, SentenceForward, StartOfParagraph, EndOfParagraph, StartOfDocument, EndOfDocument, Matching { match_quotes: bool, }, GoToPercentage, UnmatchedForward { char: char, }, UnmatchedBackward { char: char, }, FindForward { before: bool, char: char, mode: FindRange, smartcase: bool, }, FindBackward { after: bool, char: char, mode: FindRange, smartcase: bool, }, Sneak { first_char: char, second_char: char, smartcase: bool, }, SneakBackward { first_char: char, second_char: char, smartcase: bool, }, RepeatFind { last_find: Box<Motion>, }, RepeatFindReversed { last_find: Box<Motion>, }, NextLineStart, PreviousLineStart, StartOfLineDownward, EndOfLineDownward, GoToColumn, WindowTop, WindowMiddle, WindowBottom, NextSectionStart, NextSectionEnd, PreviousSectionStart, PreviousSectionEnd, NextMethodStart, NextMethodEnd, PreviousMethodStart, PreviousMethodEnd, NextComment, PreviousComment, PreviousLesserIndent, PreviousGreaterIndent, PreviousSameIndent, NextLesserIndent, NextGreaterIndent, NextSameIndent, // we don't have a good way to run a search synchronously, so // we handle search motions by running the search async and then // calling back into motion with this ZedSearchResult { prior_selections: Vec<Range<Anchor>>, new_selections: Vec<Range<Anchor>>, }, Jump { anchor: Anchor, line: bool, }, } #[derive(Clone, Copy)] enum IndentType { Lesser, Greater, Same, } /// Moves to the start of the next word. #[derive(Clone, Deserialize, JsonSchema, PartialEq, Action)] #[action(namespace = vim)] #[serde(deny_unknown_fields)] struct NextWordStart { #[serde(default)] ignore_punctuation: bool, } /// Moves to the end of the next word. #[derive(Clone, Deserialize, JsonSchema, PartialEq, Action)] #[action(namespace = vim)] #[serde(deny_unknown_fields)] struct NextWordEnd { #[serde(default)] ignore_punctuation: bool, } /// Moves to the start of the previous word. #[derive(Clone, Deserialize, JsonSchema, PartialEq, Action)] #[action(namespace = vim)] #[serde(deny_unknown_fields)] struct PreviousWordStart { #[serde(default)] ignore_punctuation: bool, } /// Moves to the end of the previous word. #[derive(Clone, Deserialize, JsonSchema, PartialEq, Action)] #[action(namespace = vim)] #[serde(deny_unknown_fields)] struct PreviousWordEnd { #[serde(default)] ignore_punctuation: bool, } /// Moves to the start of the next subword. #[derive(Clone, Deserialize, JsonSchema, PartialEq, Action)] #[action(namespace = vim)] #[serde(deny_unknown_fields)] pub(crate) struct NextSubwordStart { #[serde(default)] pub(crate) ignore_punctuation: bool, } /// Moves to the end of the next subword. #[derive(Clone, Deserialize, JsonSchema, PartialEq, Action)] #[action(namespace = vim)] #[serde(deny_unknown_fields)] pub(crate) struct NextSubwordEnd { #[serde(default)] pub(crate) ignore_punctuation: bool, } /// Moves to the start of the previous subword. #[derive(Clone, Deserialize, JsonSchema, PartialEq, Action)] #[action(namespace = vim)] #[serde(deny_unknown_fields)] pub(crate) struct PreviousSubwordStart { #[serde(default)] pub(crate) ignore_punctuation: bool, } /// Moves to the end of the previous subword. #[derive(Clone, Deserialize, JsonSchema, PartialEq, Action)] #[action(namespace = vim)] #[serde(deny_unknown_fields)] pub(crate) struct PreviousSubwordEnd { #[serde(default)] pub(crate) ignore_punctuation: bool, } /// Moves cursor up by the specified number of lines. #[derive(Clone, Deserialize, JsonSchema, PartialEq, Action)] #[action(namespace = vim)] #[serde(deny_unknown_fields)] pub(crate) struct Up { #[serde(default)] pub(crate) display_lines: bool, } /// Moves cursor down by the specified number of lines. #[derive(Clone, Deserialize, JsonSchema, PartialEq, Action)] #[action(namespace = vim)] #[serde(deny_unknown_fields)] pub(crate) struct Down { #[serde(default)] pub(crate) display_lines: bool, } /// Moves to the first non-whitespace character on the current line. #[derive(Clone, Deserialize, JsonSchema, PartialEq, Action)] #[action(namespace = vim)] #[serde(deny_unknown_fields)] struct FirstNonWhitespace { #[serde(default)] display_lines: bool, } /// Moves to the matching bracket or delimiter. #[derive(Clone, Deserialize, JsonSchema, PartialEq, Action)] #[action(namespace = vim)] #[serde(deny_unknown_fields)] struct Matching { #[serde(default)] /// Whether to include quote characters (`'`, `"`, `` ` ``) when searching /// for matching pairs. When `false`, only brackets and parentheses are /// matched, which aligns with Neovim's default `%` behavior. match_quotes: bool, } /// Moves to the end of the current line. #[derive(Clone, Deserialize, JsonSchema, PartialEq, Action)] #[action(namespace = vim)] #[serde(deny_unknown_fields)] struct EndOfLine { #[serde(default)] display_lines: bool, } /// Moves to the start of the current line. #[derive(Clone, Deserialize, JsonSchema, PartialEq, Action)] #[action(namespace = vim)] #[serde(deny_unknown_fields)] pub struct StartOfLine { #[serde(default)] pub(crate) display_lines: bool, } /// Moves to the middle of the current line. #[derive(Clone, Deserialize, JsonSchema, PartialEq, Action)] #[action(namespace = vim)] #[serde(deny_unknown_fields)] struct MiddleOfLine { #[serde(default)] display_lines: bool, } /// Finds the next unmatched bracket or delimiter. #[derive(Clone, Deserialize, JsonSchema, PartialEq, Action)] #[action(namespace = vim)] #[serde(deny_unknown_fields)] struct UnmatchedForward { #[serde(default)] char: char, } /// Finds the previous unmatched bracket or delimiter. #[derive(Clone, Deserialize, JsonSchema, PartialEq, Action)] #[action(namespace = vim)] #[serde(deny_unknown_fields)] struct UnmatchedBackward { #[serde(default)] char: char, } actions!( vim, [ /// Moves cursor left one character. Left, /// Moves cursor left one character, wrapping to previous line. #[action(deprecated_aliases = ["vim::Backspace"])] WrappingLeft, /// Moves cursor right one character. Right, /// Moves cursor right one character, wrapping to next line. #[action(deprecated_aliases = ["vim::Space"])] WrappingRight, /// Selects the current line. CurrentLine, /// Moves to the start of the next sentence. SentenceForward, /// Moves to the start of the previous sentence. SentenceBackward, /// Moves to the start of the paragraph. StartOfParagraph, /// Moves to the end of the paragraph. EndOfParagraph, /// Moves to the start of the document. StartOfDocument, /// Moves to the end of the document. EndOfDocument, /// Goes to a percentage position in the file. GoToPercentage, /// Moves to the start of the next line. NextLineStart, /// Moves to the start of the previous line. PreviousLineStart, /// Moves to the start of a line downward. StartOfLineDownward, /// Moves to the end of a line downward. EndOfLineDownward, /// Goes to a specific column number. GoToColumn, /// Repeats the last character find. RepeatFind, /// Repeats the last character find in reverse. RepeatFindReversed, /// Moves to the top of the window. WindowTop, /// Moves to the middle of the window. WindowMiddle, /// Moves to the bottom of the window. WindowBottom, /// Moves to the start of the next section. NextSectionStart, /// Moves to the end of the next section. NextSectionEnd, /// Moves to the start of the previous section. PreviousSectionStart, /// Moves to the end of the previous section. PreviousSectionEnd, /// Moves to the start of the next method. NextMethodStart, /// Moves to the end of the next method. NextMethodEnd, /// Moves to the start of the previous method. PreviousMethodStart, /// Moves to the end of the previous method. PreviousMethodEnd, /// Moves to the next comment. NextComment, /// Moves to the previous comment. PreviousComment, /// Moves to the previous line with lesser indentation. PreviousLesserIndent, /// Moves to the previous line with greater indentation. PreviousGreaterIndent, /// Moves to the previous line with the same indentation. PreviousSameIndent, /// Moves to the next line with lesser indentation. NextLesserIndent, /// Moves to the next line with greater indentation. NextGreaterIndent, /// Moves to the next line with the same indentation. NextSameIndent, ] ); pub fn register(editor: &mut Editor, cx: &mut Context<Vim>) { Vim::action(editor, cx, |vim, _: &Left, window, cx| { vim.motion(Motion::Left, window, cx) }); Vim::action(editor, cx, |vim, _: &WrappingLeft, window, cx| { vim.motion(Motion::WrappingLeft, window, cx) }); Vim::action(editor, cx, |vim, action: &Down, window, cx| { vim.motion( Motion::Down { display_lines: action.display_lines, }, window, cx, ) }); Vim::action(editor, cx, |vim, action: &Up, window, cx| { vim.motion( Motion::Up { display_lines: action.display_lines, }, window, cx, ) }); Vim::action(editor, cx, |vim, _: &Right, window, cx| { vim.motion(Motion::Right, window, cx) }); Vim::action(editor, cx, |vim, _: &WrappingRight, window, cx| { vim.motion(Motion::WrappingRight, window, cx) }); Vim::action( editor, cx, |vim, action: &FirstNonWhitespace, window, cx| { vim.motion( Motion::FirstNonWhitespace { display_lines: action.display_lines, }, window, cx, ) }, ); Vim::action(editor, cx, |vim, action: &StartOfLine, window, cx| { vim.motion( Motion::StartOfLine { display_lines: action.display_lines, }, window, cx, ) }); Vim::action(editor, cx, |vim, action: &MiddleOfLine, window, cx| { vim.motion( Motion::MiddleOfLine { display_lines: action.display_lines, }, window, cx, ) }); Vim::action(editor, cx, |vim, action: &EndOfLine, window, cx| { vim.motion( Motion::EndOfLine { display_lines: action.display_lines, }, window, cx, ) }); Vim::action(editor, cx, |vim, _: &CurrentLine, window, cx| { vim.motion(Motion::CurrentLine, window, cx) }); Vim::action(editor, cx, |vim, _: &StartOfParagraph, window, cx| { vim.motion(Motion::StartOfParagraph, window, cx) }); Vim::action(editor, cx, |vim, _: &EndOfParagraph, window, cx| { vim.motion(Motion::EndOfParagraph, window, cx) });