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