helix: Apply modification (e.g. switch case) on a single character only in helix mode (#38119)
Romans Malinovskis
and
Jakub Konka
created 1 month ago
Closes #34192
Without selection, only current character would be affected.
Also if #38117 is merged too, then transformations in SelectMode behave
correctly too and selection is not collapsed.
Release Notes:
- helix: Implemented `~`, `` ` ``, `` Alt-` `` correctly in normal and
select modes
---------
Co-authored-by: Jakub Konka <kubkon@jakubkonka.com>
Change summary
assets/keymaps/vim.json | 5 ++---
crates/vim/src/normal/convert.rs | 24 +++++++++++++++++-------
2 files changed, 19 insertions(+), 10 deletions(-)
Detailed changes
@@ -442,9 +442,8 @@
">": "vim::Indent",
"<": "vim::Outdent",
"=": "vim::AutoIndent",
- "g u": "vim::PushLowercase",
- "g shift-u": "vim::PushUppercase",
- "g ~": "vim::PushOppositeCase",
+ "`": "vim::ConvertToLowerCase",
+ "alt-`": "vim::ConvertToUpperCase",
"g q": "vim::PushRewrap",
"g w": "vim::PushRewrap",
"insert": "vim::InsertBefore",
@@ -214,11 +214,10 @@ impl Vim {
Mode::HelixNormal | Mode::HelixSelect => {
if selection.is_empty() {
- // Handle empty selection by operating on the whole word
- let (word_range, _) = snapshot.surrounding_word(selection.start, false);
- let word_start = snapshot.offset_to_point(word_range.start);
- let word_end = snapshot.offset_to_point(word_range.end);
- ranges.push(word_start..word_end);
+ // Handle empty selection by operating on single character
+ let start = selection.start;
+ let end = snapshot.clip_point(start + Point::new(0, 1), Bias::Right);
+ ranges.push(start..end);
cursor_positions.push(selection.start..selection.start);
} else {
ranges.push(selection.start..selection.end);
@@ -445,15 +444,26 @@ mod test {
cx.simulate_keystrokes("~");
cx.assert_state("«HELLO WORLDˇ»", Mode::HelixNormal);
- // Cursor-only (empty) selection
+ // Cursor-only (empty) selection - switch case
cx.set_state("The ˇquick brown", Mode::HelixNormal);
cx.simulate_keystrokes("~");
- cx.assert_state("The ˇQUICK brown", Mode::HelixNormal);
+ cx.assert_state("The ˇQuick brown", Mode::HelixNormal);
+ cx.simulate_keystrokes("~");
+ cx.assert_state("The ˇquick brown", Mode::HelixNormal);
+
+ // Cursor-only (empty) selection - switch to uppercase and lowercase explicitly
+ cx.set_state("The ˇquick brown", Mode::HelixNormal);
+ cx.simulate_keystrokes("alt-`");
+ cx.assert_state("The ˇQuick brown", Mode::HelixNormal);
+ cx.simulate_keystrokes("`");
+ cx.assert_state("The ˇquick brown", Mode::HelixNormal);
// With `e` motion (which extends selection to end of word in Helix)
cx.set_state("The ˇquick brown fox", Mode::HelixNormal);
cx.simulate_keystrokes("e");
cx.simulate_keystrokes("~");
cx.assert_state("The «QUICKˇ» brown fox", Mode::HelixNormal);
+
+ // Cursor-only
}
}