use std::{ops::Range, sync::Arc}; use editor::{ display_map::{DisplaySnapshot, ToDisplayPoint}, movement, scroll::Autoscroll, Anchor, Bias, DisplayPoint,};use gpui::WindowContext;use language::SelectionGoal; use crate::{ motion::{self, Motion}, Vim,}; pub fn create_mark(vim: &mut Vim, text: Arc<str>, tail: bool, cx: &mut WindowContext) { let Some(anchors) = vim.update_active_editor(cx, |_, editor, _| { editor .selections .disjoint_anchors() .iter() .map(|s| if tail { s.tail() } else { s.head() }) .collect::<Vec<_>>() }) else { return; }; vim.update_state(|state| state.marks.insert(text.to_string(), anchors)); vim.clear_operator(cx);} pub fn create_mark_after(vim: &mut Vim, text: Arc<str>, cx: &mut WindowContext) { let Some(anchors) = vim.update_active_editor(cx, |_, editor, cx| { let (map, selections) = editor.selections.all_display(cx); selections .into_iter() .map(|selection| { let point = movement::saturating_right(&map, selection.tail()); map.buffer_snapshot .anchor_before(point.to_offset(&map, Bias::Left)) }) .collect::<Vec<_>>() }) else { return; }; vim.update_state(|state| state.marks.insert(text.to_string(), anchors)); vim.clear_operator(cx);} pub fn create_mark_before(vim: &mut Vim, text: Arc<str>, cx: &mut WindowContext) { let Some(anchors) = vim.update_active_editor(cx, |_, editor, cx| { let (map, selections) = editor.selections.all_display(cx); selections .into_iter() .map(|selection| { let point = movement::saturating_left(&map, selection.head()); map.buffer_snapshot .anchor_before(point.to_offset(&map, Bias::Left)) }) .collect::<Vec<_>>() }) else { return; }; vim.update_state(|state| state.marks.insert(text.to_string(), anchors)); vim.clear_operator(cx);} pub fn jump(text: Arc<str>, line: bool, cx: &mut WindowContext) { let anchors = Vim::update(cx, |vim, cx| { vim.pop_operator(cx); match &*text { "{" | "}" => vim.update_active_editor(cx, |_, editor, cx| { let (map, selections) = editor.selections.all_display(cx); selections .into_iter() .map(|selection| { let point = if &*text == "{" { movement::start_of_paragraph(&map, selection.head(), 1) } else { movement::end_of_paragraph(&map, selection.head(), 1) }; map.buffer_snapshot .anchor_before(point.to_offset(&map, Bias::Left)) }) .collect::<Vec<Anchor>>() }), "." => vim.state().change_list.last().cloned(), _ => vim.state().marks.get(&*text).cloned(), } }); let Some(anchors) = anchors else { return }; let is_active_operator = Vim::read(cx).state().active_operator().is_some(); if is_active_operator { if let Some(anchor) = anchors.last() { motion::motion( Motion::Jump { anchor: *anchor, line, }, cx, ) } return; } else { Vim::update(cx, |vim, cx| { vim.update_active_editor(cx, |_, editor, cx| { let map = editor.snapshot(cx); let mut ranges: Vec<Range<Anchor>> = Vec::new(); for mut anchor in anchors { if line { let mut point = anchor.to_display_point(&map.display_snapshot); point = motion::first_non_whitespace(&map.display_snapshot, false, point); anchor = map .display_snapshot .buffer_snapshot .anchor_before(point.to_point(&map.display_snapshot)); } if ranges.last() != Some(&(anchor..anchor)) { ranges.push(anchor..anchor); } } editor.change_selections(Some(Autoscroll::fit()), cx, |s| { s.select_anchor_ranges(ranges) }) }); }) }} pub fn jump_motion( map: &DisplaySnapshot, anchor: Anchor, line: bool,) -> (DisplayPoint, SelectionGoal) { let mut point = anchor.to_display_point(map); if line { point = motion::first_non_whitespace(map, false, point) } (point, SelectionGoal::None)}
use std::{ops::Range, sync::Arc};
use editor::{
display_map::{DisplaySnapshot, ToDisplayPoint},
movement,
scroll::Autoscroll,
Anchor, Bias, DisplayPoint,
};
use gpui::WindowContext;
use language::SelectionGoal;
use crate::{
motion::{self, Motion},
Vim,
};
pub fn create_mark(vim: &mut Vim, text: Arc<str>, tail: bool, cx: &mut WindowContext) {
let Some(anchors) = vim.update_active_editor(cx, |_, editor, _| {
editor
.selections
.disjoint_anchors()
.iter()
.map(|s| if tail { s.tail() } else { s.head() })
.collect::<Vec<_>>()
}) else {
return;
};
vim.update_state(|state| state.marks.insert(text.to_string(), anchors));
vim.clear_operator(cx);
}
pub fn create_mark_after(vim: &mut Vim, text: Arc<str>, cx: &mut WindowContext) {
let Some(anchors) = vim.update_active_editor(cx, |_, editor, cx| {
let (map, selections) = editor.selections.all_display(cx);
selections
.into_iter()
.map(|selection| {
let point = movement::saturating_right(&map, selection.tail());
map.buffer_snapshot
.anchor_before(point.to_offset(&map, Bias::Left))
})
.collect::<Vec<_>>()
}) else {
return;
};
vim.update_state(|state| state.marks.insert(text.to_string(), anchors));
vim.clear_operator(cx);
}
pub fn create_mark_before(vim: &mut Vim, text: Arc<str>, cx: &mut WindowContext) {
let Some(anchors) = vim.update_active_editor(cx, |_, editor, cx| {
let (map, selections) = editor.selections.all_display(cx);
selections
.into_iter()
.map(|selection| {
let point = movement::saturating_left(&map, selection.head());
map.buffer_snapshot
.anchor_before(point.to_offset(&map, Bias::Left))
})
.collect::<Vec<_>>()
}) else {
return;
};
vim.update_state(|state| state.marks.insert(text.to_string(), anchors));
vim.clear_operator(cx);
}
pub fn jump(text: Arc<str>, line: bool, cx: &mut WindowContext) {
let anchors = Vim::update(cx, |vim, cx| {
vim.pop_operator(cx);
match &*text {
"{" | "}" => vim.update_active_editor(cx, |_, editor, cx| {
let (map, selections) = editor.selections.all_display(cx);
selections
.into_iter()
.map(|selection| {
let point = if &*text == "{" {
movement::start_of_paragraph(&map, selection.head(), 1)
} else {
movement::end_of_paragraph(&map, selection.head(), 1)
};
map.buffer_snapshot
.anchor_before(point.to_offset(&map, Bias::Left))
})
.collect::<Vec<Anchor>>()
}),
"." => vim.state().change_list.last().cloned(),
_ => vim.state().marks.get(&*text).cloned(),
}
});
let Some(anchors) = anchors else { return };
let is_active_operator = Vim::read(cx).state().active_operator().is_some();
if is_active_operator {
if let Some(anchor) = anchors.last() {
motion::motion(
Motion::Jump {
anchor: *anchor,
line,
},
cx,
)
}
return;
} else {
Vim::update(cx, |vim, cx| {
vim.update_active_editor(cx, |_, editor, cx| {
let map = editor.snapshot(cx);
let mut ranges: Vec<Range<Anchor>> = Vec::new();
for mut anchor in anchors {
if line {
let mut point = anchor.to_display_point(&map.display_snapshot);
point = motion::first_non_whitespace(&map.display_snapshot, false, point);
anchor = map
.display_snapshot
.buffer_snapshot
.anchor_before(point.to_point(&map.display_snapshot));
}
if ranges.last() != Some(&(anchor..anchor)) {
ranges.push(anchor..anchor);
}
}
editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
s.select_anchor_ranges(ranges)
})
});
})
}
}
pub fn jump_motion(
map: &DisplaySnapshot,
anchor: Anchor,
line: bool,
) -> (DisplayPoint, SelectionGoal) {
let mut point = anchor.to_display_point(map);
if line {
point = motion::first_non_whitespace(map, false, point)
}
(point, SelectionGoal::None)
}