indent.rs

 1use crate::{motion::Motion, object::Object, Vim};
 2use collections::HashMap;
 3use editor::{display_map::ToDisplayPoint, Bias};
 4use gpui::WindowContext;
 5use language::SelectionGoal;
 6
 7#[derive(PartialEq, Eq)]
 8pub(super) enum IndentDirection {
 9    In,
10    Out,
11}
12
13pub fn indent_motion(
14    vim: &mut Vim,
15    motion: Motion,
16    times: Option<usize>,
17    dir: IndentDirection,
18    cx: &mut WindowContext,
19) {
20    vim.stop_recording();
21    vim.update_active_editor(cx, |_, editor, cx| {
22        let text_layout_details = editor.text_layout_details(cx);
23        editor.transact(cx, |editor, cx| {
24            let mut selection_starts: HashMap<_, _> = Default::default();
25            editor.change_selections(None, cx, |s| {
26                s.move_with(|map, selection| {
27                    let anchor = map.display_point_to_anchor(selection.head(), Bias::Right);
28                    selection_starts.insert(selection.id, anchor);
29                    motion.expand_selection(map, selection, times, false, &text_layout_details);
30                });
31            });
32            if dir == IndentDirection::In {
33                editor.indent(&Default::default(), cx);
34            } else {
35                editor.outdent(&Default::default(), cx);
36            }
37            editor.change_selections(None, cx, |s| {
38                s.move_with(|map, selection| {
39                    let anchor = selection_starts.remove(&selection.id).unwrap();
40                    selection.collapse_to(anchor.to_display_point(map), SelectionGoal::None);
41                });
42            });
43        });
44    });
45}
46
47pub fn indent_object(
48    vim: &mut Vim,
49    object: Object,
50    around: bool,
51    dir: IndentDirection,
52    cx: &mut WindowContext,
53) {
54    vim.stop_recording();
55    vim.update_active_editor(cx, |_, editor, cx| {
56        editor.transact(cx, |editor, cx| {
57            let mut original_positions: HashMap<_, _> = Default::default();
58            editor.change_selections(None, cx, |s| {
59                s.move_with(|map, selection| {
60                    let anchor = map.display_point_to_anchor(selection.head(), Bias::Right);
61                    original_positions.insert(selection.id, anchor);
62                    object.expand_selection(map, selection, around);
63                });
64            });
65            if dir == IndentDirection::In {
66                editor.indent(&Default::default(), cx);
67            } else {
68                editor.outdent(&Default::default(), cx);
69            }
70            editor.change_selections(None, cx, |s| {
71                s.move_with(|map, selection| {
72                    let anchor = original_positions.remove(&selection.id).unwrap();
73                    selection.collapse_to(anchor.to_display_point(map), SelectionGoal::None);
74                });
75            });
76        });
77    });
78}