Fix 0 used in a count
This commit is contained in:
parent
c2c521015a
commit
7daed1b2c3
15 changed files with 73 additions and 29 deletions
|
@ -12,7 +12,7 @@ pub fn init(cx: &mut AppContext) {
|
||||||
|
|
||||||
fn normal_before(_: &mut Workspace, action: &NormalBefore, cx: &mut ViewContext<Workspace>) {
|
fn normal_before(_: &mut Workspace, action: &NormalBefore, cx: &mut ViewContext<Workspace>) {
|
||||||
let should_repeat = Vim::update(cx, |vim, cx| {
|
let should_repeat = Vim::update(cx, |vim, cx| {
|
||||||
let count = vim.take_count().unwrap_or(1);
|
let count = vim.take_count(cx).unwrap_or(1);
|
||||||
vim.stop_recording_immediately(action.boxed_clone());
|
vim.stop_recording_immediately(action.boxed_clone());
|
||||||
if count <= 1 || vim.workspace_state.replaying {
|
if count <= 1 || vim.workspace_state.replaying {
|
||||||
vim.update_active_editor(cx, |editor, cx| {
|
vim.update_active_editor(cx, |editor, cx| {
|
||||||
|
|
|
@ -229,7 +229,7 @@ pub(crate) fn motion(motion: Motion, cx: &mut WindowContext) {
|
||||||
Vim::update(cx, |vim, cx| vim.pop_operator(cx));
|
Vim::update(cx, |vim, cx| vim.pop_operator(cx));
|
||||||
}
|
}
|
||||||
|
|
||||||
let count = Vim::update(cx, |vim, _| vim.take_count());
|
let count = Vim::update(cx, |vim, cx| vim.take_count(cx));
|
||||||
let operator = Vim::read(cx).active_operator();
|
let operator = Vim::read(cx).active_operator();
|
||||||
match Vim::read(cx).state().mode {
|
match Vim::read(cx).state().mode {
|
||||||
Mode::Normal => normal_motion(motion, operator, count, cx),
|
Mode::Normal => normal_motion(motion, operator, count, cx),
|
||||||
|
|
|
@ -68,21 +68,21 @@ pub fn init(cx: &mut AppContext) {
|
||||||
cx.add_action(|_: &mut Workspace, _: &DeleteLeft, cx| {
|
cx.add_action(|_: &mut Workspace, _: &DeleteLeft, cx| {
|
||||||
Vim::update(cx, |vim, cx| {
|
Vim::update(cx, |vim, cx| {
|
||||||
vim.record_current_action(cx);
|
vim.record_current_action(cx);
|
||||||
let times = vim.take_count();
|
let times = vim.take_count(cx);
|
||||||
delete_motion(vim, Motion::Left, times, cx);
|
delete_motion(vim, Motion::Left, times, cx);
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
cx.add_action(|_: &mut Workspace, _: &DeleteRight, cx| {
|
cx.add_action(|_: &mut Workspace, _: &DeleteRight, cx| {
|
||||||
Vim::update(cx, |vim, cx| {
|
Vim::update(cx, |vim, cx| {
|
||||||
vim.record_current_action(cx);
|
vim.record_current_action(cx);
|
||||||
let times = vim.take_count();
|
let times = vim.take_count(cx);
|
||||||
delete_motion(vim, Motion::Right, times, cx);
|
delete_motion(vim, Motion::Right, times, cx);
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
cx.add_action(|_: &mut Workspace, _: &ChangeToEndOfLine, cx| {
|
cx.add_action(|_: &mut Workspace, _: &ChangeToEndOfLine, cx| {
|
||||||
Vim::update(cx, |vim, cx| {
|
Vim::update(cx, |vim, cx| {
|
||||||
vim.start_recording(cx);
|
vim.start_recording(cx);
|
||||||
let times = vim.take_count();
|
let times = vim.take_count(cx);
|
||||||
change_motion(
|
change_motion(
|
||||||
vim,
|
vim,
|
||||||
Motion::EndOfLine {
|
Motion::EndOfLine {
|
||||||
|
@ -96,7 +96,7 @@ pub fn init(cx: &mut AppContext) {
|
||||||
cx.add_action(|_: &mut Workspace, _: &DeleteToEndOfLine, cx| {
|
cx.add_action(|_: &mut Workspace, _: &DeleteToEndOfLine, cx| {
|
||||||
Vim::update(cx, |vim, cx| {
|
Vim::update(cx, |vim, cx| {
|
||||||
vim.record_current_action(cx);
|
vim.record_current_action(cx);
|
||||||
let times = vim.take_count();
|
let times = vim.take_count(cx);
|
||||||
delete_motion(
|
delete_motion(
|
||||||
vim,
|
vim,
|
||||||
Motion::EndOfLine {
|
Motion::EndOfLine {
|
||||||
|
@ -110,7 +110,7 @@ pub fn init(cx: &mut AppContext) {
|
||||||
cx.add_action(|_: &mut Workspace, _: &JoinLines, cx| {
|
cx.add_action(|_: &mut Workspace, _: &JoinLines, cx| {
|
||||||
Vim::update(cx, |vim, cx| {
|
Vim::update(cx, |vim, cx| {
|
||||||
vim.record_current_action(cx);
|
vim.record_current_action(cx);
|
||||||
let mut times = vim.take_count().unwrap_or(1);
|
let mut times = vim.take_count(cx).unwrap_or(1);
|
||||||
if vim.state().mode.is_visual() {
|
if vim.state().mode.is_visual() {
|
||||||
times = 1;
|
times = 1;
|
||||||
} else if times > 1 {
|
} else if times > 1 {
|
||||||
|
|
|
@ -8,7 +8,7 @@ use crate::{normal::ChangeCase, state::Mode, Vim};
|
||||||
pub fn change_case(_: &mut Workspace, _: &ChangeCase, cx: &mut ViewContext<Workspace>) {
|
pub fn change_case(_: &mut Workspace, _: &ChangeCase, cx: &mut ViewContext<Workspace>) {
|
||||||
Vim::update(cx, |vim, cx| {
|
Vim::update(cx, |vim, cx| {
|
||||||
vim.record_current_action(cx);
|
vim.record_current_action(cx);
|
||||||
let count = vim.take_count().unwrap_or(1) as u32;
|
let count = vim.take_count(cx).unwrap_or(1) as u32;
|
||||||
vim.update_active_editor(cx, |editor, cx| {
|
vim.update_active_editor(cx, |editor, cx| {
|
||||||
let mut ranges = Vec::new();
|
let mut ranges = Vec::new();
|
||||||
let mut cursor_positions = Vec::new();
|
let mut cursor_positions = Vec::new();
|
||||||
|
|
|
@ -60,7 +60,7 @@ pub(crate) fn repeat(cx: &mut WindowContext, from_insert_mode: bool) {
|
||||||
let Some(editor) = vim.active_editor.clone() else {
|
let Some(editor) = vim.active_editor.clone() else {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
let count = vim.take_count();
|
let count = vim.take_count(cx);
|
||||||
|
|
||||||
let selection = vim.workspace_state.recorded_selection.clone();
|
let selection = vim.workspace_state.recorded_selection.clone();
|
||||||
match selection {
|
match selection {
|
||||||
|
@ -253,7 +253,7 @@ mod test {
|
||||||
deterministic.run_until_parked();
|
deterministic.run_until_parked();
|
||||||
cx.simulate_shared_keystrokes(["."]).await;
|
cx.simulate_shared_keystrokes(["."]).await;
|
||||||
deterministic.run_until_parked();
|
deterministic.run_until_parked();
|
||||||
cx.set_shared_state("THE QUICK ˇbrown fox").await;
|
cx.assert_shared_state("THE QUICK ˇbrown fox").await;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
|
|
|
@ -48,7 +48,7 @@ pub fn init(cx: &mut AppContext) {
|
||||||
|
|
||||||
fn scroll(cx: &mut ViewContext<Workspace>, by: fn(c: Option<f32>) -> ScrollAmount) {
|
fn scroll(cx: &mut ViewContext<Workspace>, by: fn(c: Option<f32>) -> ScrollAmount) {
|
||||||
Vim::update(cx, |vim, cx| {
|
Vim::update(cx, |vim, cx| {
|
||||||
let amount = by(vim.take_count().map(|c| c as f32));
|
let amount = by(vim.take_count(cx).map(|c| c as f32));
|
||||||
vim.update_active_editor(cx, |editor, cx| scroll_editor(editor, &amount, cx));
|
vim.update_active_editor(cx, |editor, cx| scroll_editor(editor, &amount, cx));
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ fn search(workspace: &mut Workspace, action: &Search, cx: &mut ViewContext<Works
|
||||||
Direction::Next
|
Direction::Next
|
||||||
};
|
};
|
||||||
Vim::update(cx, |vim, cx| {
|
Vim::update(cx, |vim, cx| {
|
||||||
let count = vim.take_count().unwrap_or(1);
|
let count = vim.take_count(cx).unwrap_or(1);
|
||||||
pane.update(cx, |pane, cx| {
|
pane.update(cx, |pane, cx| {
|
||||||
if let Some(search_bar) = pane.toolbar().read(cx).item_of_type::<BufferSearchBar>() {
|
if let Some(search_bar) = pane.toolbar().read(cx).item_of_type::<BufferSearchBar>() {
|
||||||
search_bar.update(cx, |search_bar, cx| {
|
search_bar.update(cx, |search_bar, cx| {
|
||||||
|
@ -119,7 +119,7 @@ pub fn move_to_internal(
|
||||||
) {
|
) {
|
||||||
Vim::update(cx, |vim, cx| {
|
Vim::update(cx, |vim, cx| {
|
||||||
let pane = workspace.active_pane().clone();
|
let pane = workspace.active_pane().clone();
|
||||||
let count = vim.take_count().unwrap_or(1);
|
let count = vim.take_count(cx).unwrap_or(1);
|
||||||
pane.update(cx, |pane, cx| {
|
pane.update(cx, |pane, cx| {
|
||||||
if let Some(search_bar) = pane.toolbar().read(cx).item_of_type::<BufferSearchBar>() {
|
if let Some(search_bar) = pane.toolbar().read(cx).item_of_type::<BufferSearchBar>() {
|
||||||
let search = search_bar.update(cx, |search_bar, cx| {
|
let search = search_bar.update(cx, |search_bar, cx| {
|
||||||
|
|
|
@ -11,7 +11,7 @@ pub(crate) fn init(cx: &mut AppContext) {
|
||||||
cx.add_action(|_: &mut Workspace, _: &Substitute, cx| {
|
cx.add_action(|_: &mut Workspace, _: &Substitute, cx| {
|
||||||
Vim::update(cx, |vim, cx| {
|
Vim::update(cx, |vim, cx| {
|
||||||
vim.start_recording(cx);
|
vim.start_recording(cx);
|
||||||
let count = vim.take_count();
|
let count = vim.take_count(cx);
|
||||||
substitute(vim, count, vim.state().mode == Mode::VisualLine, cx);
|
substitute(vim, count, vim.state().mode == Mode::VisualLine, cx);
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
@ -22,7 +22,7 @@ pub(crate) fn init(cx: &mut AppContext) {
|
||||||
if matches!(vim.state().mode, Mode::VisualBlock | Mode::Visual) {
|
if matches!(vim.state().mode, Mode::VisualBlock | Mode::Visual) {
|
||||||
vim.switch_mode(Mode::VisualLine, false, cx)
|
vim.switch_mode(Mode::VisualLine, false, cx)
|
||||||
}
|
}
|
||||||
let count = vim.take_count();
|
let count = vim.take_count(cx);
|
||||||
substitute(vim, count, true, cx)
|
substitute(vim, count, true, cx)
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
|
@ -186,6 +186,7 @@ impl EditorState {
|
||||||
if self.active_operator().is_none() && self.pre_count.is_some()
|
if self.active_operator().is_none() && self.pre_count.is_some()
|
||||||
|| self.active_operator().is_some() && self.post_count.is_some()
|
|| self.active_operator().is_some() && self.post_count.is_some()
|
||||||
{
|
{
|
||||||
|
dbg!("VimCount");
|
||||||
context.add_identifier("VimCount");
|
context.add_identifier("VimCount");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -587,9 +587,34 @@ async fn test_clear_counts(cx: &mut gpui::TestAppContext) {
|
||||||
|
|
||||||
cx.simulate_shared_keystrokes(["4", "escape", "3", "d", "l"])
|
cx.simulate_shared_keystrokes(["4", "escape", "3", "d", "l"])
|
||||||
.await;
|
.await;
|
||||||
cx.set_shared_state(indoc! {"
|
cx.assert_shared_state(indoc! {"
|
||||||
The quick brown
|
The quick brown
|
||||||
fox juˇ over
|
fox juˇ over
|
||||||
the lazy dog"})
|
the lazy dog"})
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
async fn test_zero(cx: &mut gpui::TestAppContext) {
|
||||||
|
let mut cx = NeovimBackedTestContext::new(cx).await;
|
||||||
|
|
||||||
|
cx.set_shared_state(indoc! {"
|
||||||
|
The quˇick brown
|
||||||
|
fox jumps over
|
||||||
|
the lazy dog"})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
cx.simulate_shared_keystrokes(["0"]).await;
|
||||||
|
cx.assert_shared_state(indoc! {"
|
||||||
|
ˇThe quick brown
|
||||||
|
fox jumps over
|
||||||
|
the lazy dog"})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
cx.simulate_shared_keystrokes(["1", "0", "l"]).await;
|
||||||
|
cx.assert_shared_state(indoc! {"
|
||||||
|
The quick ˇbrown
|
||||||
|
fox jumps over
|
||||||
|
the lazy dog"})
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
|
|
@ -68,6 +68,8 @@ pub struct NeovimBackedTestContext<'a> {
|
||||||
|
|
||||||
last_set_state: Option<String>,
|
last_set_state: Option<String>,
|
||||||
recent_keystrokes: Vec<String>,
|
recent_keystrokes: Vec<String>,
|
||||||
|
|
||||||
|
is_dirty: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> NeovimBackedTestContext<'a> {
|
impl<'a> NeovimBackedTestContext<'a> {
|
||||||
|
@ -81,6 +83,7 @@ impl<'a> NeovimBackedTestContext<'a> {
|
||||||
|
|
||||||
last_set_state: None,
|
last_set_state: None,
|
||||||
recent_keystrokes: Default::default(),
|
recent_keystrokes: Default::default(),
|
||||||
|
is_dirty: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,6 +131,7 @@ impl<'a> NeovimBackedTestContext<'a> {
|
||||||
self.last_set_state = Some(marked_text.to_string());
|
self.last_set_state = Some(marked_text.to_string());
|
||||||
self.recent_keystrokes = Vec::new();
|
self.recent_keystrokes = Vec::new();
|
||||||
self.neovim.set_state(marked_text).await;
|
self.neovim.set_state(marked_text).await;
|
||||||
|
self.is_dirty = true;
|
||||||
context_handle
|
context_handle
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,6 +157,7 @@ impl<'a> NeovimBackedTestContext<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn assert_shared_state(&mut self, marked_text: &str) {
|
pub async fn assert_shared_state(&mut self, marked_text: &str) {
|
||||||
|
self.is_dirty = false;
|
||||||
let marked_text = marked_text.replace("•", " ");
|
let marked_text = marked_text.replace("•", " ");
|
||||||
let neovim = self.neovim_state().await;
|
let neovim = self.neovim_state().await;
|
||||||
let editor = self.editor_state();
|
let editor = self.editor_state();
|
||||||
|
@ -258,6 +263,7 @@ impl<'a> NeovimBackedTestContext<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn assert_state_matches(&mut self) {
|
pub async fn assert_state_matches(&mut self) {
|
||||||
|
self.is_dirty = false;
|
||||||
let neovim = self.neovim_state().await;
|
let neovim = self.neovim_state().await;
|
||||||
let editor = self.editor_state();
|
let editor = self.editor_state();
|
||||||
let initial_state = self
|
let initial_state = self
|
||||||
|
@ -383,6 +389,14 @@ impl<'a> DerefMut for NeovimBackedTestContext<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> Drop for NeovimBackedTestContext<'a> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if self.is_dirty {
|
||||||
|
panic!("Test context was dropped after set_shared_state before assert_shared_state")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use gpui::TestAppContext;
|
use gpui::TestAppContext;
|
||||||
|
|
|
@ -73,7 +73,7 @@ pub fn init(cx: &mut AppContext) {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
cx.add_action(|_: &mut Workspace, n: &Number, cx: _| {
|
cx.add_action(|_: &mut Workspace, n: &Number, cx: _| {
|
||||||
Vim::update(cx, |vim, _| vim.push_count_digit(n.0));
|
Vim::update(cx, |vim, cx| vim.push_count_digit(n.0, cx));
|
||||||
});
|
});
|
||||||
|
|
||||||
cx.add_action(|_: &mut Workspace, _: &Tab, cx| {
|
cx.add_action(|_: &mut Workspace, _: &Tab, cx| {
|
||||||
|
@ -228,13 +228,7 @@ impl Vim {
|
||||||
let editor = self.active_editor.clone()?.upgrade(cx)?;
|
let editor = self.active_editor.clone()?.upgrade(cx)?;
|
||||||
Some(editor.update(cx, update))
|
Some(editor.update(cx, update))
|
||||||
}
|
}
|
||||||
// ~, shift-j, x, shift-x, p
|
|
||||||
// shift-c, shift-d, shift-i, i, a, o, shift-o, s
|
|
||||||
// c, d
|
|
||||||
// r
|
|
||||||
|
|
||||||
// TODO: shift-j?
|
|
||||||
//
|
|
||||||
pub fn start_recording(&mut self, cx: &mut WindowContext) {
|
pub fn start_recording(&mut self, cx: &mut WindowContext) {
|
||||||
if !self.workspace_state.replaying {
|
if !self.workspace_state.replaying {
|
||||||
self.workspace_state.recording = true;
|
self.workspace_state.recording = true;
|
||||||
|
@ -309,7 +303,7 @@ impl Vim {
|
||||||
state.operator_stack.clear();
|
state.operator_stack.clear();
|
||||||
});
|
});
|
||||||
if mode != Mode::Insert {
|
if mode != Mode::Insert {
|
||||||
self.take_count();
|
self.take_count(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
cx.emit_global(VimEvent::ModeChanged { mode });
|
cx.emit_global(VimEvent::ModeChanged { mode });
|
||||||
|
@ -363,7 +357,7 @@ impl Vim {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_count_digit(&mut self, number: usize) {
|
fn push_count_digit(&mut self, number: usize, cx: &mut WindowContext) {
|
||||||
if self.active_operator().is_some() {
|
if self.active_operator().is_some() {
|
||||||
self.update_state(|state| {
|
self.update_state(|state| {
|
||||||
state.post_count = Some(state.post_count.unwrap_or(0) * 10 + number)
|
state.post_count = Some(state.post_count.unwrap_or(0) * 10 + number)
|
||||||
|
@ -373,9 +367,11 @@ impl Vim {
|
||||||
state.pre_count = Some(state.pre_count.unwrap_or(0) * 10 + number)
|
state.pre_count = Some(state.pre_count.unwrap_or(0) * 10 + number)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
// update the keymap so that 0 works
|
||||||
|
self.sync_vim_settings(cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn take_count(&mut self) -> Option<usize> {
|
fn take_count(&mut self, cx: &mut WindowContext) -> Option<usize> {
|
||||||
if self.workspace_state.replaying {
|
if self.workspace_state.replaying {
|
||||||
return self.workspace_state.recorded_count;
|
return self.workspace_state.recorded_count;
|
||||||
}
|
}
|
||||||
|
@ -390,6 +386,7 @@ impl Vim {
|
||||||
if self.workspace_state.recording {
|
if self.workspace_state.recording {
|
||||||
self.workspace_state.recorded_count = count;
|
self.workspace_state.recorded_count = count;
|
||||||
}
|
}
|
||||||
|
self.sync_vim_settings(cx);
|
||||||
count
|
count
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -415,7 +412,7 @@ impl Vim {
|
||||||
popped_operator
|
popped_operator
|
||||||
}
|
}
|
||||||
fn clear_operator(&mut self, cx: &mut WindowContext) {
|
fn clear_operator(&mut self, cx: &mut WindowContext) {
|
||||||
self.take_count();
|
self.take_count(cx);
|
||||||
self.update_state(|state| state.operator_stack.clear());
|
self.update_state(|state| state.operator_stack.clear());
|
||||||
self.sync_vim_settings(cx);
|
self.sync_vim_settings(cx);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,4 +4,4 @@
|
||||||
{"Key":"3"}
|
{"Key":"3"}
|
||||||
{"Key":"d"}
|
{"Key":"d"}
|
||||||
{"Key":"l"}
|
{"Key":"l"}
|
||||||
{"Put":{"state":"The quick brown\nfox juˇ over\nthe lazy dog"}}
|
{"Get":{"state":"The quick brown\nfox juˇ over\nthe lazy dog","mode":"Normal"}}
|
||||||
|
|
|
@ -35,4 +35,4 @@
|
||||||
{"Key":"."}
|
{"Key":"."}
|
||||||
{"Put":{"state":"THE QUIˇck brown fox"}}
|
{"Put":{"state":"THE QUIˇck brown fox"}}
|
||||||
{"Key":"."}
|
{"Key":"."}
|
||||||
{"Put":{"state":"THE QUICK ˇbrown fox"}}
|
{"Get":{"state":"THE QUICK ˇbrown fox","mode":"Normal"}}
|
||||||
|
|
7
crates/vim/test_data/test_zero.json
Normal file
7
crates/vim/test_data/test_zero.json
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
{"Put":{"state":"The quˇick brown\nfox jumps over\nthe lazy dog"}}
|
||||||
|
{"Key":"0"}
|
||||||
|
{"Get":{"state":"ˇThe quick brown\nfox jumps over\nthe lazy dog","mode":"Normal"}}
|
||||||
|
{"Key":"1"}
|
||||||
|
{"Key":"0"}
|
||||||
|
{"Key":"l"}
|
||||||
|
{"Get":{"state":"The quick ˇbrown\nfox jumps over\nthe lazy dog","mode":"Normal"}}
|
Loading…
Add table
Add a link
Reference in a new issue