mirror of
https://github.com/zed-industries/zed.git
synced 2025-02-03 08:54:04 +00:00
Add surround aliases (#20104)
Closes #19417 Release Notes: - vim : Added `r` and `a` as aliases for `[` and `<` text objects (copying vim-surround). - vim: (breaking change) rebound the function argument text object to `g`. - vim: Fixed surrounds to allow `b`/`B`/`r`/`a` anywhere you could use `(`, `{`, `[`, `<`. --- - vim: Added `b`, `B`, `r`, `s`, `a` as aliases for `()`, `{}`, `[]`, `<>` in vim surround mode. - Adds a new `surround_alias` function where aliases are defined. - This function is used in `find_surround_pairs` to substitute the chosen text with the alias - The keymap is also modified to add support for Square and Angle brackets when changing surrounds. These two were added to follow the example of Tim Pope's ubiquitous `vim-surround` plugin. - I had to overwrite the `vim::Argument` keybind in order to do this. I moved it to use the `g` modifier. I realize this is a breaking change and will happily move the `vim::AngleBracket` keymap to a different letter if you'd like to avoid this. I'm just trying to keep with convention. Ideally, Users would be able to define surround aliases themselves in the config file but that's a much bigger task than I'm able to do right now. - I also added tests for the new aliases. Thanks for making such a clean and organized codebase. I was able to find the relevant section of code rather quickly thanks to this.
This commit is contained in:
parent
4bbddcad31
commit
f0aeab7d00
3 changed files with 259 additions and 13 deletions
|
@ -364,12 +364,14 @@
|
|||
"b": "vim::Parentheses",
|
||||
"[": "vim::SquareBrackets",
|
||||
"]": "vim::SquareBrackets",
|
||||
"r": "vim::SquareBrackets",
|
||||
"{": "vim::CurlyBrackets",
|
||||
"}": "vim::CurlyBrackets",
|
||||
"shift-b": "vim::CurlyBrackets",
|
||||
"<": "vim::AngleBrackets",
|
||||
">": "vim::AngleBrackets",
|
||||
"a": "vim::Argument"
|
||||
"a": "vim::AngleBrackets",
|
||||
"g": "vim::Argument"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
@ -1402,7 +1402,7 @@ mod test {
|
|||
|
||||
// Generic arguments
|
||||
cx.set_state("fn boop<A: ˇDebug, B>() {}", Mode::Normal);
|
||||
cx.simulate_keystrokes("v i a");
|
||||
cx.simulate_keystrokes("v i g");
|
||||
cx.assert_state("fn boop<«A: Debugˇ», B>() {}", Mode::Visual);
|
||||
|
||||
// Function arguments
|
||||
|
@ -1410,11 +1410,11 @@ mod test {
|
|||
"fn boop(ˇarg_a: (Tuple, Of, Types), arg_b: String) {}",
|
||||
Mode::Normal,
|
||||
);
|
||||
cx.simulate_keystrokes("d a a");
|
||||
cx.simulate_keystrokes("d a g");
|
||||
cx.assert_state("fn boop(ˇarg_b: String) {}", Mode::Normal);
|
||||
|
||||
cx.set_state("std::namespace::test(\"strinˇg\", a.b.c())", Mode::Normal);
|
||||
cx.simulate_keystrokes("v a a");
|
||||
cx.simulate_keystrokes("v a g");
|
||||
cx.assert_state("std::namespace::test(«\"string\", ˇ»a.b.c())", Mode::Visual);
|
||||
|
||||
// Tuple, vec, and array arguments
|
||||
|
@ -1422,34 +1422,34 @@ mod test {
|
|||
"fn boop(arg_a: (Tuple, Ofˇ, Types), arg_b: String) {}",
|
||||
Mode::Normal,
|
||||
);
|
||||
cx.simulate_keystrokes("c i a");
|
||||
cx.simulate_keystrokes("c i g");
|
||||
cx.assert_state(
|
||||
"fn boop(arg_a: (Tuple, ˇ, Types), arg_b: String) {}",
|
||||
Mode::Insert,
|
||||
);
|
||||
|
||||
cx.set_state("let a = (test::call(), 'p', my_macro!{ˇ});", Mode::Normal);
|
||||
cx.simulate_keystrokes("c a a");
|
||||
cx.simulate_keystrokes("c a g");
|
||||
cx.assert_state("let a = (test::call(), 'p'ˇ);", Mode::Insert);
|
||||
|
||||
cx.set_state("let a = [test::call(ˇ), 300];", Mode::Normal);
|
||||
cx.simulate_keystrokes("c i a");
|
||||
cx.simulate_keystrokes("c i g");
|
||||
cx.assert_state("let a = [ˇ, 300];", Mode::Insert);
|
||||
|
||||
cx.set_state(
|
||||
"let a = vec![Vec::new(), vecˇ![test::call(), 300]];",
|
||||
Mode::Normal,
|
||||
);
|
||||
cx.simulate_keystrokes("c a a");
|
||||
cx.simulate_keystrokes("c a g");
|
||||
cx.assert_state("let a = vec![Vec::new()ˇ];", Mode::Insert);
|
||||
|
||||
// Cursor immediately before / after brackets
|
||||
cx.set_state("let a = [test::call(first_arg)ˇ]", Mode::Normal);
|
||||
cx.simulate_keystrokes("v i a");
|
||||
cx.simulate_keystrokes("v i g");
|
||||
cx.assert_state("let a = [«test::call(first_arg)ˇ»]", Mode::Visual);
|
||||
|
||||
cx.set_state("let a = [test::callˇ(first_arg)]", Mode::Normal);
|
||||
cx.simulate_keystrokes("v i a");
|
||||
cx.simulate_keystrokes("v i g");
|
||||
cx.assert_state("let a = [«test::call(first_arg)ˇ»]", Mode::Visual);
|
||||
}
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ impl Vim {
|
|||
newline: false,
|
||||
},
|
||||
};
|
||||
let surround = pair.end != *text;
|
||||
let surround = pair.end != surround_alias((*text).as_ref());
|
||||
let (display_map, display_selections) = editor.selections.all_adjusted_display(cx);
|
||||
let mut edits = Vec::new();
|
||||
let mut anchors = Vec::new();
|
||||
|
@ -245,7 +245,7 @@ impl Vim {
|
|||
newline: false,
|
||||
},
|
||||
};
|
||||
let surround = pair.end != *text;
|
||||
let surround = pair.end != surround_alias((*text).as_ref());
|
||||
let (display_map, selections) = editor.selections.all_adjusted_display(cx);
|
||||
let mut edits = Vec::new();
|
||||
let mut anchors = Vec::new();
|
||||
|
@ -393,7 +393,19 @@ impl Vim {
|
|||
}
|
||||
|
||||
fn find_surround_pair<'a>(pairs: &'a [BracketPair], ch: &str) -> Option<&'a BracketPair> {
|
||||
pairs.iter().find(|pair| pair.start == ch || pair.end == ch)
|
||||
pairs
|
||||
.iter()
|
||||
.find(|pair| pair.start == surround_alias(ch) || pair.end == surround_alias(ch))
|
||||
}
|
||||
|
||||
fn surround_alias(ch: &str) -> &str {
|
||||
match ch {
|
||||
"b" => ")",
|
||||
"B" => "}",
|
||||
"a" => ">",
|
||||
"r" => "]",
|
||||
_ => ch,
|
||||
}
|
||||
}
|
||||
|
||||
fn all_support_surround_pair() -> Vec<BracketPair> {
|
||||
|
@ -1171,4 +1183,236 @@ mod test {
|
|||
Mode::Normal,
|
||||
);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_surround_aliases(cx: &mut gpui::TestAppContext) {
|
||||
let mut cx = VimTestContext::new(cx, true).await;
|
||||
|
||||
// add aliases
|
||||
cx.set_state(
|
||||
indoc! {"
|
||||
The quˇick brown
|
||||
fox jumps over
|
||||
the lazy dog."},
|
||||
Mode::Normal,
|
||||
);
|
||||
cx.simulate_keystrokes("y s i w b");
|
||||
cx.assert_state(
|
||||
indoc! {"
|
||||
The ˇ(quick) brown
|
||||
fox jumps over
|
||||
the lazy dog."},
|
||||
Mode::Normal,
|
||||
);
|
||||
|
||||
cx.set_state(
|
||||
indoc! {"
|
||||
The quˇick brown
|
||||
fox jumps over
|
||||
the lazy dog."},
|
||||
Mode::Normal,
|
||||
);
|
||||
cx.simulate_keystrokes("y s i w B");
|
||||
cx.assert_state(
|
||||
indoc! {"
|
||||
The ˇ{quick} brown
|
||||
fox jumps over
|
||||
the lazy dog."},
|
||||
Mode::Normal,
|
||||
);
|
||||
|
||||
cx.set_state(
|
||||
indoc! {"
|
||||
The quˇick brown
|
||||
fox jumps over
|
||||
the lazy dog."},
|
||||
Mode::Normal,
|
||||
);
|
||||
cx.simulate_keystrokes("y s i w a");
|
||||
cx.assert_state(
|
||||
indoc! {"
|
||||
The ˇ<quick> brown
|
||||
fox jumps over
|
||||
the lazy dog."},
|
||||
Mode::Normal,
|
||||
);
|
||||
|
||||
cx.set_state(
|
||||
indoc! {"
|
||||
The quˇick brown
|
||||
fox jumps over
|
||||
the lazy dog."},
|
||||
Mode::Normal,
|
||||
);
|
||||
cx.simulate_keystrokes("y s i w r");
|
||||
cx.assert_state(
|
||||
indoc! {"
|
||||
The ˇ[quick] brown
|
||||
fox jumps over
|
||||
the lazy dog."},
|
||||
Mode::Normal,
|
||||
);
|
||||
|
||||
// change aliases
|
||||
cx.set_state(
|
||||
indoc! {"
|
||||
The {quˇick} brown
|
||||
fox jumps over
|
||||
the lazy dog."},
|
||||
Mode::Normal,
|
||||
);
|
||||
cx.simulate_keystrokes("c s { b");
|
||||
cx.assert_state(
|
||||
indoc! {"
|
||||
The ˇ(quick) brown
|
||||
fox jumps over
|
||||
the lazy dog."},
|
||||
Mode::Normal,
|
||||
);
|
||||
|
||||
cx.set_state(
|
||||
indoc! {"
|
||||
The (quˇick) brown
|
||||
fox jumps over
|
||||
the lazy dog."},
|
||||
Mode::Normal,
|
||||
);
|
||||
cx.simulate_keystrokes("c s ( B");
|
||||
cx.assert_state(
|
||||
indoc! {"
|
||||
The ˇ{quick} brown
|
||||
fox jumps over
|
||||
the lazy dog."},
|
||||
Mode::Normal,
|
||||
);
|
||||
|
||||
cx.set_state(
|
||||
indoc! {"
|
||||
The (quˇick) brown
|
||||
fox jumps over
|
||||
the lazy dog."},
|
||||
Mode::Normal,
|
||||
);
|
||||
cx.simulate_keystrokes("c s ( a");
|
||||
cx.assert_state(
|
||||
indoc! {"
|
||||
The ˇ<quick> brown
|
||||
fox jumps over
|
||||
the lazy dog."},
|
||||
Mode::Normal,
|
||||
);
|
||||
|
||||
cx.set_state(
|
||||
indoc! {"
|
||||
The <quˇick> brown
|
||||
fox jumps over
|
||||
the lazy dog."},
|
||||
Mode::Normal,
|
||||
);
|
||||
cx.simulate_keystrokes("c s < b");
|
||||
cx.assert_state(
|
||||
indoc! {"
|
||||
The ˇ(quick) brown
|
||||
fox jumps over
|
||||
the lazy dog."},
|
||||
Mode::Normal,
|
||||
);
|
||||
|
||||
cx.set_state(
|
||||
indoc! {"
|
||||
The (quˇick) brown
|
||||
fox jumps over
|
||||
the lazy dog."},
|
||||
Mode::Normal,
|
||||
);
|
||||
cx.simulate_keystrokes("c s ( r");
|
||||
cx.assert_state(
|
||||
indoc! {"
|
||||
The ˇ[quick] brown
|
||||
fox jumps over
|
||||
the lazy dog."},
|
||||
Mode::Normal,
|
||||
);
|
||||
|
||||
cx.set_state(
|
||||
indoc! {"
|
||||
The [quˇick] brown
|
||||
fox jumps over
|
||||
the lazy dog."},
|
||||
Mode::Normal,
|
||||
);
|
||||
cx.simulate_keystrokes("c s [ b");
|
||||
cx.assert_state(
|
||||
indoc! {"
|
||||
The ˇ(quick) brown
|
||||
fox jumps over
|
||||
the lazy dog."},
|
||||
Mode::Normal,
|
||||
);
|
||||
|
||||
// delete alias
|
||||
cx.set_state(
|
||||
indoc! {"
|
||||
The {quˇick} brown
|
||||
fox jumps over
|
||||
the lazy dog."},
|
||||
Mode::Normal,
|
||||
);
|
||||
cx.simulate_keystrokes("d s B");
|
||||
cx.assert_state(
|
||||
indoc! {"
|
||||
The ˇquick brown
|
||||
fox jumps over
|
||||
the lazy dog."},
|
||||
Mode::Normal,
|
||||
);
|
||||
|
||||
cx.set_state(
|
||||
indoc! {"
|
||||
The (quˇick) brown
|
||||
fox jumps over
|
||||
the lazy dog."},
|
||||
Mode::Normal,
|
||||
);
|
||||
cx.simulate_keystrokes("d s b");
|
||||
cx.assert_state(
|
||||
indoc! {"
|
||||
The ˇquick brown
|
||||
fox jumps over
|
||||
the lazy dog."},
|
||||
Mode::Normal,
|
||||
);
|
||||
|
||||
cx.set_state(
|
||||
indoc! {"
|
||||
The [quˇick] brown
|
||||
fox jumps over
|
||||
the lazy dog."},
|
||||
Mode::Normal,
|
||||
);
|
||||
cx.simulate_keystrokes("d s r");
|
||||
cx.assert_state(
|
||||
indoc! {"
|
||||
The ˇquick brown
|
||||
fox jumps over
|
||||
the lazy dog."},
|
||||
Mode::Normal,
|
||||
);
|
||||
|
||||
cx.set_state(
|
||||
indoc! {"
|
||||
The <quˇick> brown
|
||||
fox jumps over
|
||||
the lazy dog."},
|
||||
Mode::Normal,
|
||||
);
|
||||
cx.simulate_keystrokes("d s a");
|
||||
cx.assert_state(
|
||||
indoc! {"
|
||||
The ˇquick brown
|
||||
fox jumps over
|
||||
the lazy dog."},
|
||||
Mode::Normal,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue