editor_utils.rs

  1use editor::{display_map::DisplaySnapshot, Bias, DisplayPoint, Editor};
  2use gpui::ViewContext;
  3use language::{Selection, SelectionGoal};
  4
  5pub trait VimEditorExt {
  6    fn adjust_selections(self: &mut Self, cx: &mut ViewContext<Self>);
  7    fn adjusted_move_selections(
  8        self: &mut Self,
  9        cx: &mut ViewContext<Self>,
 10        move_selection: impl Fn(&DisplaySnapshot, &mut Selection<DisplayPoint>),
 11    );
 12    fn adjusted_move_selection_heads(
 13        &mut self,
 14        cx: &mut ViewContext<Self>,
 15        update_head: impl Fn(
 16            &DisplaySnapshot,
 17            DisplayPoint,
 18            SelectionGoal,
 19        ) -> (DisplayPoint, SelectionGoal),
 20    );
 21    fn adjusted_move_cursors(
 22        self: &mut Self,
 23        cx: &mut ViewContext<Self>,
 24        update_cursor_position: impl Fn(
 25            &DisplaySnapshot,
 26            DisplayPoint,
 27            SelectionGoal,
 28        ) -> (DisplayPoint, SelectionGoal),
 29    );
 30}
 31
 32pub fn adjust_display_point(
 33    map: &DisplaySnapshot,
 34    mut display_point: DisplayPoint,
 35) -> DisplayPoint {
 36    let next_char = map.chars_at(display_point).next();
 37    if next_char == Some('\n') || next_char == None {
 38        *display_point.column_mut() = display_point.column().saturating_sub(1);
 39        display_point = map.clip_point(display_point, Bias::Left);
 40    }
 41    display_point
 42}
 43
 44impl VimEditorExt for Editor {
 45    fn adjust_selections(self: &mut Self, cx: &mut ViewContext<Self>) {
 46        self.move_selections(cx, |map, selection| {
 47            if selection.is_empty() {
 48                let adjusted_cursor = adjust_display_point(map, selection.start);
 49                selection.collapse_to(adjusted_cursor, selection.goal);
 50            } else {
 51                let adjusted_head = adjust_display_point(map, selection.head());
 52                selection.set_head(adjusted_head, selection.goal);
 53            }
 54        })
 55    }
 56
 57    fn adjusted_move_selections(
 58        self: &mut Self,
 59        cx: &mut ViewContext<Self>,
 60        move_selection: impl Fn(&DisplaySnapshot, &mut Selection<DisplayPoint>),
 61    ) {
 62        self.move_selections(cx, |map, selection| {
 63            move_selection(map, selection);
 64            let adjusted_head = adjust_display_point(map, selection.head());
 65            selection.set_head(adjusted_head, selection.goal);
 66        })
 67    }
 68
 69    fn adjusted_move_selection_heads(
 70        &mut self,
 71        cx: &mut ViewContext<Self>,
 72        update_head: impl Fn(
 73            &DisplaySnapshot,
 74            DisplayPoint,
 75            SelectionGoal,
 76        ) -> (DisplayPoint, SelectionGoal),
 77    ) {
 78        self.adjusted_move_selections(cx, |map, selection| {
 79            let (new_head, new_goal) = update_head(map, selection.head(), selection.goal);
 80            let adjusted_head = adjust_display_point(map, new_head);
 81            selection.set_head(adjusted_head, new_goal);
 82        });
 83    }
 84
 85    fn adjusted_move_cursors(
 86        self: &mut Self,
 87        cx: &mut ViewContext<Self>,
 88        update_cursor_position: impl Fn(
 89            &DisplaySnapshot,
 90            DisplayPoint,
 91            SelectionGoal,
 92        ) -> (DisplayPoint, SelectionGoal),
 93    ) {
 94        self.move_selections(cx, |map, selection| {
 95            let (cursor, new_goal) = update_cursor_position(map, selection.head(), selection.goal);
 96            let adjusted_cursor = adjust_display_point(map, cursor);
 97            selection.collapse_to(adjusted_cursor, new_goal);
 98        });
 99    }
100}