Files
oak-gpui/crates/vim/src/normal/toggle_comments.rs
T
Peter Finn 08ce230bae vim: Add some forced motion support (#27991)
Closes https://github.com/zed-industries/zed/issues/20971

Added `v` input to yank and delete to override default motion. The
global vim state tracking if the forced motion flag was passed handled
the same way that the count is. [The main chunk of code maps the motion
kind from the default to the overridden
kind](https://github.com/zed-industries/zed/pull/27991/files#diff-2dca6b7d1673c912d14e4edc74e415abbe3a4e6d6b37e0e2006d30828bf4bb9cR1249-R1254).
To handle the case of deleting a single character (dv0) at the start of
a row I had to modify the control flow
[here](https://github.com/zed-industries/zed/pull/27991/files#diff-2dca6b7d1673c912d14e4edc74e415abbe3a4e6d6b37e0e2006d30828bf4bb9cR1240-R1244).
Then to handle an exclusive delete till the end of the row (dv$) I
[saturated the endpoint with a left
bias](https://github.com/zed-industries/zed/pull/27991/files#diff-2dca6b7d1673c912d14e4edc74e415abbe3a4e6d6b37e0e2006d30828bf4bb9cR1281-R1286).

Test case: dv0


https://github.com/user-attachments/assets/613cf9fb-9732-425c-9179-025f3e107584

Test case: yvjp


https://github.com/user-attachments/assets/550b7c77-1eb8-41c3-894b-117eb50b7a5d

Release Notes:

- Added some forced motion support for delete and yank
2025-04-11 11:12:30 -06:00

74 lines
3.0 KiB
Rust

use crate::{Vim, motion::Motion, object::Object};
use collections::HashMap;
use editor::{Bias, display_map::ToDisplayPoint};
use gpui::{Context, Window};
use language::SelectionGoal;
impl Vim {
pub fn toggle_comments_motion(
&mut self,
motion: Motion,
times: Option<usize>,
forced_motion: bool,
window: &mut Window,
cx: &mut Context<Self>,
) {
self.stop_recording(cx);
self.update_editor(window, cx, |_, editor, window, cx| {
let text_layout_details = editor.text_layout_details(window);
editor.transact(window, cx, |editor, window, cx| {
let mut selection_starts: HashMap<_, _> = Default::default();
editor.change_selections(None, window, cx, |s| {
s.move_with(|map, selection| {
let anchor = map.display_point_to_anchor(selection.head(), Bias::Right);
selection_starts.insert(selection.id, anchor);
motion.expand_selection(
map,
selection,
times,
&text_layout_details,
forced_motion,
);
});
});
editor.toggle_comments(&Default::default(), window, cx);
editor.change_selections(None, window, cx, |s| {
s.move_with(|map, selection| {
let anchor = selection_starts.remove(&selection.id).unwrap();
selection.collapse_to(anchor.to_display_point(map), SelectionGoal::None);
});
});
});
});
}
pub fn toggle_comments_object(
&mut self,
object: Object,
around: bool,
window: &mut Window,
cx: &mut Context<Self>,
) {
self.stop_recording(cx);
self.update_editor(window, cx, |_, editor, window, cx| {
editor.transact(window, cx, |editor, window, cx| {
let mut original_positions: HashMap<_, _> = Default::default();
editor.change_selections(None, window, cx, |s| {
s.move_with(|map, selection| {
let anchor = map.display_point_to_anchor(selection.head(), Bias::Right);
original_positions.insert(selection.id, anchor);
object.expand_selection(map, selection, around);
});
});
editor.toggle_comments(&Default::default(), window, cx);
editor.change_selections(None, window, cx, |s| {
s.move_with(|map, selection| {
let anchor = original_positions.remove(&selection.id).unwrap();
selection.collapse_to(anchor.to_display_point(map), SelectionGoal::None);
});
});
});
});
}
}