From a2c4205c5c3640e6f3ebdb889460b3064bf64bde Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 28 Mar 2022 11:17:19 +0200 Subject: [PATCH] Make indent and outdent explicit actions and unify `tab`bing logic --- crates/editor/src/editor.rs | 49 +++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index f9327ee2519d0521fd6fb05b812411b81c9abc3a..7cb50167b698d305326264491f2f6f60973e4cf8 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -68,7 +68,8 @@ action!(Backspace); action!(Delete); action!(Input, String); action!(Newline); -action!(Tab); +action!(Tab, Direction); +action!(Indent); action!(Outdent); action!(DeleteLine); action!(DeleteToPreviousWordStart); @@ -171,13 +172,13 @@ pub fn init(cx: &mut MutableAppContext) { Some("Editor && showing_code_actions"), ), Binding::new("enter", ConfirmRename, Some("Editor && renaming")), - Binding::new("tab", Tab, Some("Editor")), + Binding::new("tab", Tab(Direction::Next), Some("Editor")), + Binding::new("shift-tab", Tab(Direction::Prev), Some("Editor")), Binding::new( "tab", ConfirmCompletion(None), Some("Editor && showing_completions"), ), - Binding::new("shift-tab", Outdent, Some("Editor")), Binding::new("ctrl-shift-K", DeleteLine, Some("Editor")), Binding::new("alt-backspace", DeleteToPreviousWordStart, Some("Editor")), Binding::new("alt-h", DeleteToPreviousWordStart, Some("Editor")), @@ -304,7 +305,8 @@ pub fn init(cx: &mut MutableAppContext) { cx.add_action(Editor::newline); cx.add_action(Editor::backspace); cx.add_action(Editor::delete); - cx.add_action(Editor::tab); + cx.add_action(Editor::handle_tab); + cx.add_action(Editor::indent); cx.add_action(Editor::outdent); cx.add_action(Editor::delete_line); cx.add_action(Editor::delete_to_previous_word_start); @@ -2861,18 +2863,34 @@ impl Editor { }); } - pub fn tab(&mut self, _: &Tab, cx: &mut ViewContext) { - if self.move_to_next_snippet_tabstop(cx) { - return; + pub fn handle_tab(&mut self, &Tab(direction): &Tab, cx: &mut ViewContext) { + match direction { + Direction::Prev => { + if !self.snippet_stack.is_empty() { + self.move_to_prev_snippet_tabstop(cx); + return; + } + + self.outdent(&Outdent, cx); + } + Direction::Next => { + if self.move_to_next_snippet_tabstop(cx) { + return; + } + + self.tab(false, cx); + } } + } + pub fn tab(&mut self, force_indentation: bool, cx: &mut ViewContext) { let tab_size = cx.global::().tab_size; let mut selections = self.local_selections::(cx); self.transact(cx, |this, cx| { let mut last_indent = None; this.buffer.update(cx, |buffer, cx| { for selection in &mut selections { - if selection.is_empty() { + if selection.is_empty() && !force_indentation { let char_column = buffer .read(cx) .text_for_range(Point::new(selection.start.row, 0)..selection.start) @@ -2938,12 +2956,11 @@ impl Editor { }); } - pub fn outdent(&mut self, _: &Outdent, cx: &mut ViewContext) { - if !self.snippet_stack.is_empty() { - self.move_to_prev_snippet_tabstop(cx); - return; - } + pub fn indent(&mut self, _: &Indent, cx: &mut ViewContext) { + self.tab(true, cx); + } + pub fn outdent(&mut self, _: &Outdent, cx: &mut ViewContext) { let tab_size = cx.global::().tab_size; let selections = self.local_selections::(cx); let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); @@ -7458,7 +7475,7 @@ mod tests { ); // indent from mid-tabstop to full tabstop - view.tab(&Tab, cx); + view.tab(false, cx); assert_eq!(view.text(cx), " one two\nthree\n four"); assert_eq!( view.selected_display_ranges(cx), @@ -7483,7 +7500,7 @@ mod tests { view.select_display_ranges(&[DisplayPoint::new(1, 1)..DisplayPoint::new(2, 0)], cx); // indent and outdent affect only the preceding line - view.tab(&Tab, cx); + view.tab(false, cx); assert_eq!(view.text(cx), "one two\n three\n four"); assert_eq!( view.selected_display_ranges(cx), @@ -7498,7 +7515,7 @@ mod tests { // Ensure that indenting/outdenting works when the cursor is at column 0. view.select_display_ranges(&[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)], cx); - view.tab(&Tab, cx); + view.tab(false, cx); assert_eq!(view.text(cx), "one two\n three\n four"); assert_eq!( view.selected_display_ranges(cx),