Add | as a bracket and a motion

Although vim/nvim doesn't have | as brackets, it's common in langauges like Rust
and Ruby, and I expect it to work.
This commit is contained in:
Conrad Irwin 2023-10-22 22:04:55 -06:00
parent 9589f5573d
commit 3cf98c4fae
4 changed files with 119 additions and 181 deletions

View File

@ -39,6 +39,7 @@
"w": "vim::NextWordStart", "w": "vim::NextWordStart",
"{": "vim::StartOfParagraph", "{": "vim::StartOfParagraph",
"}": "vim::EndOfParagraph", "}": "vim::EndOfParagraph",
"|": "vim::GoToColumn",
"shift-w": [ "shift-w": [
"vim::NextWordStart", "vim::NextWordStart",
{ {
@ -97,14 +98,8 @@
"ctrl-o": "pane::GoBack", "ctrl-o": "pane::GoBack",
"ctrl-i": "pane::GoForward", "ctrl-i": "pane::GoForward",
"ctrl-]": "editor::GoToDefinition", "ctrl-]": "editor::GoToDefinition",
"escape": [ "escape": ["vim::SwitchMode", "Normal"],
"vim::SwitchMode", "ctrl+[": ["vim::SwitchMode", "Normal"],
"Normal"
],
"ctrl+[": [
"vim::SwitchMode",
"Normal"
],
"v": "vim::ToggleVisual", "v": "vim::ToggleVisual",
"shift-v": "vim::ToggleVisualLine", "shift-v": "vim::ToggleVisualLine",
"ctrl-v": "vim::ToggleVisualBlock", "ctrl-v": "vim::ToggleVisualBlock",
@ -233,123 +228,36 @@
} }
], ],
// Count support // Count support
"1": [ "1": ["vim::Number", 1],
"vim::Number", "2": ["vim::Number", 2],
1 "3": ["vim::Number", 3],
], "4": ["vim::Number", 4],
"2": [ "5": ["vim::Number", 5],
"vim::Number", "6": ["vim::Number", 6],
2 "7": ["vim::Number", 7],
], "8": ["vim::Number", 8],
"3": [ "9": ["vim::Number", 9],
"vim::Number",
3
],
"4": [
"vim::Number",
4
],
"5": [
"vim::Number",
5
],
"6": [
"vim::Number",
6
],
"7": [
"vim::Number",
7
],
"8": [
"vim::Number",
8
],
"9": [
"vim::Number",
9
],
// window related commands (ctrl-w X) // window related commands (ctrl-w X)
"ctrl-w left": [ "ctrl-w left": ["workspace::ActivatePaneInDirection", "Left"],
"workspace::ActivatePaneInDirection", "ctrl-w right": ["workspace::ActivatePaneInDirection", "Right"],
"Left" "ctrl-w up": ["workspace::ActivatePaneInDirection", "Up"],
], "ctrl-w down": ["workspace::ActivatePaneInDirection", "Down"],
"ctrl-w right": [ "ctrl-w h": ["workspace::ActivatePaneInDirection", "Left"],
"workspace::ActivatePaneInDirection", "ctrl-w l": ["workspace::ActivatePaneInDirection", "Right"],
"Right" "ctrl-w k": ["workspace::ActivatePaneInDirection", "Up"],
], "ctrl-w j": ["workspace::ActivatePaneInDirection", "Down"],
"ctrl-w up": [ "ctrl-w ctrl-h": ["workspace::ActivatePaneInDirection", "Left"],
"workspace::ActivatePaneInDirection", "ctrl-w ctrl-l": ["workspace::ActivatePaneInDirection", "Right"],
"Up" "ctrl-w ctrl-k": ["workspace::ActivatePaneInDirection", "Up"],
], "ctrl-w ctrl-j": ["workspace::ActivatePaneInDirection", "Down"],
"ctrl-w down": [ "ctrl-w shift-left": ["workspace::SwapPaneInDirection", "Left"],
"workspace::ActivatePaneInDirection", "ctrl-w shift-right": ["workspace::SwapPaneInDirection", "Right"],
"Down" "ctrl-w shift-up": ["workspace::SwapPaneInDirection", "Up"],
], "ctrl-w shift-down": ["workspace::SwapPaneInDirection", "Down"],
"ctrl-w h": [ "ctrl-w shift-h": ["workspace::SwapPaneInDirection", "Left"],
"workspace::ActivatePaneInDirection", "ctrl-w shift-l": ["workspace::SwapPaneInDirection", "Right"],
"Left" "ctrl-w shift-k": ["workspace::SwapPaneInDirection", "Up"],
], "ctrl-w shift-j": ["workspace::SwapPaneInDirection", "Down"],
"ctrl-w l": [
"workspace::ActivatePaneInDirection",
"Right"
],
"ctrl-w k": [
"workspace::ActivatePaneInDirection",
"Up"
],
"ctrl-w j": [
"workspace::ActivatePaneInDirection",
"Down"
],
"ctrl-w ctrl-h": [
"workspace::ActivatePaneInDirection",
"Left"
],
"ctrl-w ctrl-l": [
"workspace::ActivatePaneInDirection",
"Right"
],
"ctrl-w ctrl-k": [
"workspace::ActivatePaneInDirection",
"Up"
],
"ctrl-w ctrl-j": [
"workspace::ActivatePaneInDirection",
"Down"
],
"ctrl-w shift-left": [
"workspace::SwapPaneInDirection",
"Left"
],
"ctrl-w shift-right": [
"workspace::SwapPaneInDirection",
"Right"
],
"ctrl-w shift-up": [
"workspace::SwapPaneInDirection",
"Up"
],
"ctrl-w shift-down": [
"workspace::SwapPaneInDirection",
"Down"
],
"ctrl-w shift-h": [
"workspace::SwapPaneInDirection",
"Left"
],
"ctrl-w shift-l": [
"workspace::SwapPaneInDirection",
"Right"
],
"ctrl-w shift-k": [
"workspace::SwapPaneInDirection",
"Up"
],
"ctrl-w shift-j": [
"workspace::SwapPaneInDirection",
"Down"
],
"ctrl-w g t": "pane::ActivateNextItem", "ctrl-w g t": "pane::ActivateNextItem",
"ctrl-w ctrl-g t": "pane::ActivateNextItem", "ctrl-w ctrl-g t": "pane::ActivateNextItem",
"ctrl-w g shift-t": "pane::ActivatePrevItem", "ctrl-w g shift-t": "pane::ActivatePrevItem",
@ -371,14 +279,8 @@
"ctrl-w ctrl-q": "pane::CloseAllItems", "ctrl-w ctrl-q": "pane::CloseAllItems",
"ctrl-w o": "workspace::CloseInactiveTabsAndPanes", "ctrl-w o": "workspace::CloseInactiveTabsAndPanes",
"ctrl-w ctrl-o": "workspace::CloseInactiveTabsAndPanes", "ctrl-w ctrl-o": "workspace::CloseInactiveTabsAndPanes",
"ctrl-w n": [ "ctrl-w n": ["workspace::NewFileInDirection", "Up"],
"workspace::NewFileInDirection", "ctrl-w ctrl-n": ["workspace::NewFileInDirection", "Up"]
"Up"
],
"ctrl-w ctrl-n": [
"workspace::NewFileInDirection",
"Up"
]
} }
}, },
{ {
@ -393,21 +295,12 @@
"context": "Editor && vim_mode == normal && vim_operator == none && !VimWaiting", "context": "Editor && vim_mode == normal && vim_operator == none && !VimWaiting",
"bindings": { "bindings": {
".": "vim::Repeat", ".": "vim::Repeat",
"c": [ "c": ["vim::PushOperator", "Change"],
"vim::PushOperator",
"Change"
],
"shift-c": "vim::ChangeToEndOfLine", "shift-c": "vim::ChangeToEndOfLine",
"d": [ "d": ["vim::PushOperator", "Delete"],
"vim::PushOperator",
"Delete"
],
"shift-d": "vim::DeleteToEndOfLine", "shift-d": "vim::DeleteToEndOfLine",
"shift-j": "vim::JoinLines", "shift-j": "vim::JoinLines",
"y": [ "y": ["vim::PushOperator", "Yank"],
"vim::PushOperator",
"Yank"
],
"shift-y": "vim::YankLine", "shift-y": "vim::YankLine",
"i": "vim::InsertBefore", "i": "vim::InsertBefore",
"shift-i": "vim::InsertFirstNonWhitespace", "shift-i": "vim::InsertFirstNonWhitespace",
@ -443,10 +336,7 @@
"backwards": true "backwards": true
} }
], ],
"r": [ "r": ["vim::PushOperator", "Replace"],
"vim::PushOperator",
"Replace"
],
"s": "vim::Substitute", "s": "vim::Substitute",
"shift-s": "vim::SubstituteLine", "shift-s": "vim::SubstituteLine",
"> >": "editor::Indent", "> >": "editor::Indent",
@ -458,10 +348,7 @@
{ {
"context": "Editor && VimCount", "context": "Editor && VimCount",
"bindings": { "bindings": {
"0": [ "0": ["vim::Number", 0]
"vim::Number",
0
]
} }
}, },
{ {
@ -497,12 +384,15 @@
"'": "vim::Quotes", "'": "vim::Quotes",
"`": "vim::BackQuotes", "`": "vim::BackQuotes",
"\"": "vim::DoubleQuotes", "\"": "vim::DoubleQuotes",
"|": "vim::VerticalBars",
"(": "vim::Parentheses", "(": "vim::Parentheses",
")": "vim::Parentheses", ")": "vim::Parentheses",
"b": "vim::Parentheses",
"[": "vim::SquareBrackets", "[": "vim::SquareBrackets",
"]": "vim::SquareBrackets", "]": "vim::SquareBrackets",
"{": "vim::CurlyBrackets", "{": "vim::CurlyBrackets",
"}": "vim::CurlyBrackets", "}": "vim::CurlyBrackets",
"shift-b": "vim::CurlyBrackets",
"<": "vim::AngleBrackets", "<": "vim::AngleBrackets",
">": "vim::AngleBrackets" ">": "vim::AngleBrackets"
} }
@ -548,22 +438,10 @@
"shift-i": "vim::InsertBefore", "shift-i": "vim::InsertBefore",
"shift-a": "vim::InsertAfter", "shift-a": "vim::InsertAfter",
"shift-j": "vim::JoinLines", "shift-j": "vim::JoinLines",
"r": [ "r": ["vim::PushOperator", "Replace"],
"vim::PushOperator", "ctrl-c": ["vim::SwitchMode", "Normal"],
"Replace" "escape": ["vim::SwitchMode", "Normal"],
], "ctrl+[": ["vim::SwitchMode", "Normal"],
"ctrl-c": [
"vim::SwitchMode",
"Normal"
],
"escape": [
"vim::SwitchMode",
"Normal"
],
"ctrl+[": [
"vim::SwitchMode",
"Normal"
],
">": "editor::Indent", ">": "editor::Indent",
"<": "editor::Outdent", "<": "editor::Outdent",
"i": [ "i": [
@ -602,14 +480,8 @@
"bindings": { "bindings": {
"tab": "vim::Tab", "tab": "vim::Tab",
"enter": "vim::Enter", "enter": "vim::Enter",
"escape": [ "escape": ["vim::SwitchMode", "Normal"],
"vim::SwitchMode", "ctrl+[": ["vim::SwitchMode", "Normal"]
"Normal"
],
"ctrl+[": [
"vim::SwitchMode",
"Normal"
]
} }
}, },
{ {

View File

@ -40,6 +40,7 @@ pub enum Motion {
NextLineStart, NextLineStart,
StartOfLineDownward, StartOfLineDownward,
EndOfLineDownward, EndOfLineDownward,
GoToColumn,
} }
#[derive(Clone, Deserialize, PartialEq)] #[derive(Clone, Deserialize, PartialEq)]
@ -119,6 +120,7 @@ actions!(
NextLineStart, NextLineStart,
StartOfLineDownward, StartOfLineDownward,
EndOfLineDownward, EndOfLineDownward,
GoToColumn,
] ]
); );
impl_actions!( impl_actions!(
@ -215,6 +217,7 @@ pub fn init(cx: &mut AppContext) {
cx.add_action(|_: &mut Workspace, &EndOfLineDownward, cx: _| { cx.add_action(|_: &mut Workspace, &EndOfLineDownward, cx: _| {
motion(Motion::EndOfLineDownward, cx) motion(Motion::EndOfLineDownward, cx)
}); });
cx.add_action(|_: &mut Workspace, &GoToColumn, cx: _| motion(Motion::GoToColumn, cx));
cx.add_action(|_: &mut Workspace, action: &RepeatFind, cx: _| { cx.add_action(|_: &mut Workspace, action: &RepeatFind, cx: _| {
repeat_motion(action.backwards, cx) repeat_motion(action.backwards, cx)
}) })
@ -292,6 +295,7 @@ impl Motion {
| Right | Right
| StartOfLine { .. } | StartOfLine { .. }
| EndOfLineDownward | EndOfLineDownward
| GoToColumn
| NextWordStart { .. } | NextWordStart { .. }
| PreviousWordStart { .. } | PreviousWordStart { .. }
| FirstNonWhitespace { .. } | FirstNonWhitespace { .. }
@ -317,6 +321,7 @@ impl Motion {
| EndOfParagraph | EndOfParagraph
| StartOfLineDownward | StartOfLineDownward
| EndOfLineDownward | EndOfLineDownward
| GoToColumn
| NextWordStart { .. } | NextWordStart { .. }
| PreviousWordStart { .. } | PreviousWordStart { .. }
| FirstNonWhitespace { .. } | FirstNonWhitespace { .. }
@ -346,6 +351,7 @@ impl Motion {
| StartOfLineDownward | StartOfLineDownward
| StartOfParagraph | StartOfParagraph
| EndOfParagraph | EndOfParagraph
| GoToColumn
| NextWordStart { .. } | NextWordStart { .. }
| PreviousWordStart { .. } | PreviousWordStart { .. }
| FirstNonWhitespace { .. } | FirstNonWhitespace { .. }
@ -429,6 +435,7 @@ impl Motion {
NextLineStart => (next_line_start(map, point, times), SelectionGoal::None), NextLineStart => (next_line_start(map, point, times), SelectionGoal::None),
StartOfLineDownward => (next_line_start(map, point, times - 1), SelectionGoal::None), StartOfLineDownward => (next_line_start(map, point, times - 1), SelectionGoal::None),
EndOfLineDownward => (next_line_end(map, point, times), SelectionGoal::None), EndOfLineDownward => (next_line_end(map, point, times), SelectionGoal::None),
GoToColumn => (go_to_column(map, point, times), SelectionGoal::None),
}; };
(new_point != point || infallible).then_some((new_point, goal)) (new_point != point || infallible).then_some((new_point, goal))
@ -919,6 +926,11 @@ fn next_line_start(map: &DisplaySnapshot, point: DisplayPoint, times: usize) ->
first_non_whitespace(map, false, correct_line) first_non_whitespace(map, false, correct_line)
} }
fn go_to_column(map: &DisplaySnapshot, point: DisplayPoint, times: usize) -> DisplayPoint {
let correct_line = start_of_relative_buffer_row(map, point, 0);
right(map, correct_line, times.saturating_sub(1))
}
pub(crate) fn next_line_end( pub(crate) fn next_line_end(
map: &DisplaySnapshot, map: &DisplaySnapshot,
mut point: DisplayPoint, mut point: DisplayPoint,

View File

@ -20,6 +20,7 @@ pub enum Object {
Quotes, Quotes,
BackQuotes, BackQuotes,
DoubleQuotes, DoubleQuotes,
VerticalBars,
Parentheses, Parentheses,
SquareBrackets, SquareBrackets,
CurlyBrackets, CurlyBrackets,
@ -40,6 +41,7 @@ actions!(
Quotes, Quotes,
BackQuotes, BackQuotes,
DoubleQuotes, DoubleQuotes,
VerticalBars,
Parentheses, Parentheses,
SquareBrackets, SquareBrackets,
CurlyBrackets, CurlyBrackets,
@ -64,6 +66,7 @@ pub fn init(cx: &mut AppContext) {
}); });
cx.add_action(|_: &mut Workspace, _: &CurlyBrackets, cx: _| object(Object::CurlyBrackets, cx)); cx.add_action(|_: &mut Workspace, _: &CurlyBrackets, cx: _| object(Object::CurlyBrackets, cx));
cx.add_action(|_: &mut Workspace, _: &AngleBrackets, cx: _| object(Object::AngleBrackets, cx)); cx.add_action(|_: &mut Workspace, _: &AngleBrackets, cx: _| object(Object::AngleBrackets, cx));
cx.add_action(|_: &mut Workspace, _: &VerticalBars, cx: _| object(Object::VerticalBars, cx));
} }
fn object(object: Object, cx: &mut WindowContext) { fn object(object: Object, cx: &mut WindowContext) {
@ -79,9 +82,11 @@ fn object(object: Object, cx: &mut WindowContext) {
impl Object { impl Object {
pub fn is_multiline(self) -> bool { pub fn is_multiline(self) -> bool {
match self { match self {
Object::Word { .. } | Object::Quotes | Object::BackQuotes | Object::DoubleQuotes => { Object::Word { .. }
false | Object::Quotes
} | Object::BackQuotes
| Object::VerticalBars
| Object::DoubleQuotes => false,
Object::Sentence Object::Sentence
| Object::Parentheses | Object::Parentheses
| Object::AngleBrackets | Object::AngleBrackets
@ -96,6 +101,7 @@ impl Object {
Object::Quotes Object::Quotes
| Object::BackQuotes | Object::BackQuotes
| Object::DoubleQuotes | Object::DoubleQuotes
| Object::VerticalBars
| Object::Parentheses | Object::Parentheses
| Object::SquareBrackets | Object::SquareBrackets
| Object::CurlyBrackets | Object::CurlyBrackets
@ -111,6 +117,7 @@ impl Object {
| Object::Quotes | Object::Quotes
| Object::BackQuotes | Object::BackQuotes
| Object::DoubleQuotes | Object::DoubleQuotes
| Object::VerticalBars
| Object::Parentheses | Object::Parentheses
| Object::SquareBrackets | Object::SquareBrackets
| Object::CurlyBrackets | Object::CurlyBrackets
@ -142,6 +149,9 @@ impl Object {
Object::DoubleQuotes => { Object::DoubleQuotes => {
surrounding_markers(map, relative_to, around, self.is_multiline(), '"', '"') surrounding_markers(map, relative_to, around, self.is_multiline(), '"', '"')
} }
Object::VerticalBars => {
surrounding_markers(map, relative_to, around, self.is_multiline(), '|', '|')
}
Object::Parentheses => { Object::Parentheses => {
surrounding_markers(map, relative_to, around, self.is_multiline(), '(', ')') surrounding_markers(map, relative_to, around, self.is_multiline(), '(', ')')
} }
@ -568,7 +578,10 @@ fn surrounding_markers(
mod test { mod test {
use indoc::indoc; use indoc::indoc;
use crate::test::{ExemptionFeatures, NeovimBackedTestContext}; use crate::{
state::Mode,
test::{ExemptionFeatures, NeovimBackedTestContext, VimTestContext},
};
const WORD_LOCATIONS: &'static str = indoc! {" const WORD_LOCATIONS: &'static str = indoc! {"
The quick ˇbrowˇnˇ The quick ˇbrowˇnˇ
@ -940,6 +953,47 @@ mod test {
.await; .await;
} }
#[gpui::test]
async fn test_vertical_bars(cx: &mut gpui::TestAppContext) {
let mut cx = VimTestContext::new(cx, true).await;
cx.set_state(
indoc! {"
fn boop() {
baz(ˇ|a, b| { bar(|j, k| { })})
}"
},
Mode::Normal,
);
cx.simulate_keystrokes(["c", "i", "|"]);
cx.assert_state(
indoc! {"
fn boop() {
baz(|ˇ| { bar(|j, k| { })})
}"
},
Mode::Insert,
);
cx.simulate_keystrokes(["escape", "1", "8", "|"]);
cx.assert_state(
indoc! {"
fn boop() {
baz(|| { bar(ˇ|j, k| { })})
}"
},
Mode::Normal,
);
cx.simulate_keystrokes(["v", "a", "|"]);
cx.assert_state(
indoc! {"
fn boop() {
baz(|| { bar(«|j, k| ˇ»{ })})
}"
},
Mode::Visual,
);
}
#[gpui::test] #[gpui::test]
async fn test_delete_surrounding_character_objects(cx: &mut gpui::TestAppContext) { async fn test_delete_surrounding_character_objects(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await; let mut cx = NeovimBackedTestContext::new(cx).await;

View File

@ -8,7 +8,7 @@
{"Key":"i"} {"Key":"i"}
{"Key":"{"} {"Key":"{"}
{"Get":{"state":"func empty(a string) bool {\n if a == \"\" {\n« return true\nˇ» }\n return false\n}","mode":"Visual"}} {"Get":{"state":"func empty(a string) bool {\n if a == \"\" {\n« return true\nˇ» }\n return false\n}","mode":"Visual"}}
{"Put":{"state":"func empty(a string) bool {\n if a == \"\" {\n ˇreturn true\n }\n return false\n}"}} {"Put":{"state":"func empty(a string) bool {\n if a == \"\" ˇ{\n return true\n }\n return false\n}"}}
{"Key":"v"} {"Key":"v"}
{"Key":"i"} {"Key":"i"}
{"Key":"{"} {"Key":"{"}