Add support for u and U in vim visual mode

This commit is contained in:
Brooks Swinnerton 2024-01-28 15:13:09 -05:00
parent b213458803
commit c0c0abae56
No known key found for this signature in database
GPG Key ID: 72743B7DE552E25A
5 changed files with 103 additions and 10 deletions

View File

@ -400,7 +400,8 @@
{
"context": "Editor && vim_mode == visual && !VimWaiting && !VimObject",
"bindings": {
"u": "editor::Undo",
"u": "vim::ConvertToLowerCase",
"U": "vim::ConvertToUpperCase",
"o": "vim::OtherEnd",
"shift-o": "vim::OtherEnd",
"d": "vim::VisualDelete",

View File

@ -26,7 +26,7 @@ use log::error;
use workspace::Workspace;
use self::{
case::change_case,
case::{change_case, convert_to_lower_case, convert_to_upper_case},
change::{change_motion, change_object},
delete::{delete_motion, delete_object},
yank::{yank_motion, yank_object},
@ -48,6 +48,8 @@ actions!(
Yank,
YankLine,
ChangeCase,
ConvertToUpperCase,
ConvertToLowerCase,
JoinLines,
]
);
@ -60,6 +62,8 @@ pub(crate) fn register(workspace: &mut Workspace, cx: &mut ViewContext<Workspace
workspace.register_action(insert_line_above);
workspace.register_action(insert_line_below);
workspace.register_action(change_case);
workspace.register_action(convert_to_upper_case);
workspace.register_action(convert_to_lower_case);
workspace.register_action(yank_line);
workspace.register_action(|_: &mut Workspace, _: &DeleteLeft, cx| {

View File

@ -3,9 +3,40 @@ use gpui::ViewContext;
use language::{Bias, Point};
use workspace::Workspace;
use crate::{normal::ChangeCase, state::Mode, Vim};
use crate::{
normal::ChangeCase, normal::ConvertToLowerCase, normal::ConvertToUpperCase, state::Mode, Vim,
};
pub fn change_case(_: &mut Workspace, _: &ChangeCase, cx: &mut ViewContext<Workspace>) {
transform_case(cx, |c| {
if c.is_lowercase() {
c.to_uppercase().collect::<Vec<char>>()
} else {
c.to_lowercase().collect::<Vec<char>>()
}
})
}
pub fn convert_to_upper_case(
_: &mut Workspace,
_: &ConvertToUpperCase,
cx: &mut ViewContext<Workspace>,
) {
transform_case(cx, |c| c.to_uppercase().collect::<Vec<char>>())
}
pub fn convert_to_lower_case(
_: &mut Workspace,
_: &ConvertToLowerCase,
cx: &mut ViewContext<Workspace>,
) {
transform_case(cx, |c| c.to_lowercase().collect::<Vec<char>>())
}
fn transform_case<F>(cx: &mut ViewContext<Workspace>, transform: F)
where
F: Fn(char) -> Vec<char> + Copy,
{
Vim::update(cx, |vim, cx| {
vim.record_current_action(cx);
let count = vim.take_count(cx).unwrap_or(1) as u32;
@ -54,13 +85,7 @@ pub fn change_case(_: &mut Workspace, _: &ChangeCase, cx: &mut ViewContext<Works
let text = snapshot
.text_for_range(range.start..range.end)
.flat_map(|s| s.chars())
.flat_map(|c| {
if c.is_lowercase() {
c.to_uppercase().collect::<Vec<char>>()
} else {
c.to_lowercase().collect::<Vec<char>>()
}
})
.flat_map(|c| transform(c))
.collect::<String>();
buffer.edit([(range, text)], None, cx)
@ -74,6 +99,7 @@ pub fn change_case(_: &mut Workspace, _: &ChangeCase, cx: &mut ViewContext<Works
vim.switch_mode(Mode::Normal, true, cx)
})
}
#[cfg(test)]
mod test {
use crate::{state::Mode, test::NeovimBackedTestContext};
@ -113,4 +139,42 @@ mod test {
cx.simulate_keystroke("~");
cx.assert_state("aSSˇcdˇE\n", Mode::Normal);
}
#[gpui::test]
async fn test_convert_to_upper_case(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await;
// works in visual mode
cx.set_shared_state("a😀C«dÉ1*fˇ»\n").await;
cx.simulate_shared_keystrokes(["U"]).await;
cx.assert_shared_state("a😀CˇDÉ1*F\n").await;
// works with line selections
cx.set_shared_state("abˇC\n").await;
cx.simulate_shared_keystrokes(["shift-v", "U"]).await;
cx.assert_shared_state("ˇABC\n").await;
// works in visual block mode
cx.set_shared_state("ˇaa\nbb\ncc").await;
cx.simulate_shared_keystrokes(["ctrl-v", "j", "U"]).await;
cx.assert_shared_state("ˇAa\nBb\ncc").await;
}
#[gpui::test]
async fn test_convert_to_lower_case(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await;
// works in visual mode
cx.set_shared_state("A😀c«DÉ1*fˇ»\n").await;
cx.simulate_shared_keystrokes(["u"]).await;
cx.assert_shared_state("A😀cˇdé1*f\n").await;
// works with line selections
cx.set_shared_state("ABˇc\n").await;
cx.simulate_shared_keystrokes(["shift-v", "u"]).await;
cx.assert_shared_state("ˇabc\n").await;
// works in visual block mode
cx.set_shared_state("ˇAa\nBb\nCc").await;
cx.simulate_shared_keystrokes(["ctrl-v", "j", "u"]).await;
cx.assert_shared_state("ˇaa\nbb\nCc").await;
}
}

View File

@ -0,0 +1,12 @@
{"Put":{"state":"A😀c«DÉ1*fˇ»\n"}}
{"Key":"u"}
{"Get":{"state":"A😀cˇdé1*f\n","mode":"Normal"}}
{"Put":{"state":"ABˇc\n"}}
{"Key":"shift-v"}
{"Key":"u"}
{"Get":{"state":"ˇabc\n","mode":"Normal"}}
{"Put":{"state":"ˇAa\nBb\nCc"}}
{"Key":"ctrl-v"}
{"Key":"j"}
{"Key":"u"}
{"Get":{"state":"ˇaa\nbb\nCc","mode":"Normal"}}

View File

@ -0,0 +1,12 @@
{"Put":{"state":"a😀C«dÉ1*fˇ»\n"}}
{"Key":"U"}
{"Get":{"state":"a😀CˇDÉ1*F\n","mode":"Normal"}}
{"Put":{"state":"abˇC\n"}}
{"Key":"shift-v"}
{"Key":"U"}
{"Get":{"state":"ˇABC\n","mode":"Normal"}}
{"Put":{"state":"ˇaa\nbb\ncc"}}
{"Key":"ctrl-v"}
{"Key":"j"}
{"Key":"U"}
{"Get":{"state":"ˇAa\nBb\ncc","mode":"Normal"}}