Fix 0 used in a count

This commit is contained in:
Conrad Irwin 2023-09-12 09:56:23 -06:00
parent c2c521015a
commit 7daed1b2c3
15 changed files with 73 additions and 29 deletions

View file

@ -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| {

View file

@ -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),

View file

@ -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 {

View file

@ -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();

View file

@ -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]

View file

@ -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));
}) })
} }

View file

@ -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| {

View file

@ -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)
}) })
}); });

View file

@ -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");
} }

View file

@ -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;
}

View file

@ -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;

View file

@ -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);
} }

View file

@ -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"}}

View file

@ -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"}}

View 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"}}