diff options
author | Simon Vandel Sillesen <[email protected]> | 2019-01-05 23:58:03 +0000 |
---|---|---|
committer | Simon Vandel Sillesen <[email protected]> | 2019-01-05 23:58:03 +0000 |
commit | f99398d9d5e47e28f3749c7903df67b9030ac6e0 (patch) | |
tree | 64168a90441da3d19ad725b1b80513deef5864f4 /crates/ra_editor/src | |
parent | 3e42a158787955ff9f2e81be43479dbe8f2b1bb6 (diff) |
indent on typing dot. fixes #439
Diffstat (limited to 'crates/ra_editor/src')
-rw-r--r-- | crates/ra_editor/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/ra_editor/src/typing.rs | 54 |
2 files changed, 52 insertions, 4 deletions
diff --git a/crates/ra_editor/src/lib.rs b/crates/ra_editor/src/lib.rs index ac283e2e0..a3c85ed5d 100644 --- a/crates/ra_editor/src/lib.rs +++ b/crates/ra_editor/src/lib.rs | |||
@@ -16,7 +16,7 @@ pub use self::{ | |||
16 | line_index::{LineCol, LineIndex}, | 16 | line_index::{LineCol, LineIndex}, |
17 | line_index_utils::translate_offset_with_edit, | 17 | line_index_utils::translate_offset_with_edit, |
18 | structure::{file_structure, StructureNode}, | 18 | structure::{file_structure, StructureNode}, |
19 | typing::{join_lines, on_enter, on_eq_typed}, | 19 | typing::{join_lines, on_enter, on_dot_typed, on_eq_typed}, |
20 | diagnostics::diagnostics | 20 | diagnostics::diagnostics |
21 | }; | 21 | }; |
22 | use ra_text_edit::TextEditBuilder; | 22 | use ra_text_edit::TextEditBuilder; |
diff --git a/crates/ra_editor/src/typing.rs b/crates/ra_editor/src/typing.rs index 1b568e96c..aaea858ea 100644 --- a/crates/ra_editor/src/typing.rs +++ b/crates/ra_editor/src/typing.rs | |||
@@ -1,5 +1,6 @@ | |||
1 | use std::mem; | 1 | use std::mem; |
2 | 2 | ||
3 | use itertools::Itertools; | ||
3 | use ra_syntax::{ | 4 | use ra_syntax::{ |
4 | algo::{find_covering_node, find_leaf_at_offset, LeafAtOffset}, | 5 | algo::{find_covering_node, find_leaf_at_offset, LeafAtOffset}, |
5 | ast, | 6 | ast, |
@@ -9,9 +10,8 @@ use ra_syntax::{ | |||
9 | SyntaxNodeRef, TextRange, TextUnit, | 10 | SyntaxNodeRef, TextRange, TextUnit, |
10 | }; | 11 | }; |
11 | use ra_text_edit::text_utils::contains_offset_nonstrict; | 12 | use ra_text_edit::text_utils::contains_offset_nonstrict; |
12 | use itertools::Itertools; | ||
13 | 13 | ||
14 | use crate::{find_node_at_offset, TextEditBuilder, LocalEdit}; | 14 | use crate::{find_node_at_offset, LocalEdit, TextEditBuilder}; |
15 | 15 | ||
16 | pub fn join_lines(file: &SourceFileNode, range: TextRange) -> LocalEdit { | 16 | pub fn join_lines(file: &SourceFileNode, range: TextRange) -> LocalEdit { |
17 | let range = if range.is_empty() { | 17 | let range = if range.is_empty() { |
@@ -136,6 +136,27 @@ pub fn on_eq_typed(file: &SourceFileNode, offset: TextUnit) -> Option<LocalEdit> | |||
136 | }) | 136 | }) |
137 | } | 137 | } |
138 | 138 | ||
139 | pub fn on_dot_typed(file: &SourceFileNode, offset: TextUnit) -> Option<LocalEdit> { | ||
140 | let before_dot_offset = offset - TextUnit::of_char('.'); | ||
141 | |||
142 | let whitespace = find_leaf_at_offset(file.syntax(), before_dot_offset) | ||
143 | .left_biased() | ||
144 | .and_then(ast::Whitespace::cast)?; | ||
145 | |||
146 | // whitespace found just left of the dot | ||
147 | // TODO: indent is always 4 spaces now. A better heuristic could look on the previous line(s) | ||
148 | let indent = " ".to_string(); | ||
149 | |||
150 | let cursor_position = offset + TextUnit::of_str(&indent);; | ||
151 | let mut edit = TextEditBuilder::default(); | ||
152 | edit.insert(before_dot_offset, indent); | ||
153 | Some(LocalEdit { | ||
154 | label: "indent dot".to_string(), | ||
155 | edit: edit.finish(), | ||
156 | cursor_position: Some(cursor_position), | ||
157 | }) | ||
158 | } | ||
159 | |||
139 | fn remove_newline( | 160 | fn remove_newline( |
140 | edit: &mut TextEditBuilder, | 161 | edit: &mut TextEditBuilder, |
141 | node: SyntaxNodeRef, | 162 | node: SyntaxNodeRef, |
@@ -283,7 +304,9 @@ fn compute_ws(left: SyntaxNodeRef, right: SyntaxNodeRef) -> &'static str { | |||
283 | #[cfg(test)] | 304 | #[cfg(test)] |
284 | mod tests { | 305 | mod tests { |
285 | use super::*; | 306 | use super::*; |
286 | use crate::test_utils::{add_cursor, check_action, extract_offset, extract_range, assert_eq_text}; | 307 | use crate::test_utils::{ |
308 | add_cursor, assert_eq_text, check_action, extract_offset, extract_range, | ||
309 | }; | ||
287 | 310 | ||
288 | fn check_join_lines(before: &str, after: &str) { | 311 | fn check_join_lines(before: &str, after: &str) { |
289 | check_action(before, after, |file, offset| { | 312 | check_action(before, after, |file, offset| { |
@@ -615,6 +638,31 @@ fn foo() { | |||
615 | } | 638 | } |
616 | 639 | ||
617 | #[test] | 640 | #[test] |
641 | fn test_on_dot_typed() { | ||
642 | fn do_check(before: &str, after: &str) { | ||
643 | let (offset, before) = extract_offset(before); | ||
644 | let file = SourceFileNode::parse(&before); | ||
645 | let result = on_dot_typed(&file, offset).unwrap(); | ||
646 | let actual = result.edit.apply(&before); | ||
647 | assert_eq_text!(after, &actual); | ||
648 | } | ||
649 | do_check( | ||
650 | r" | ||
651 | pub fn child(&self, db: &impl HirDatabase, name: &Name) -> Cancelable<Option<Module>> { | ||
652 | self.child_impl(db, name) | ||
653 | .<|> | ||
654 | } | ||
655 | ", | ||
656 | r" | ||
657 | pub fn child(&self, db: &impl HirDatabase, name: &Name) -> Cancelable<Option<Module>> { | ||
658 | self.child_impl(db, name) | ||
659 | . | ||
660 | } | ||
661 | ", | ||
662 | ); | ||
663 | } | ||
664 | |||
665 | #[test] | ||
618 | fn test_on_enter() { | 666 | fn test_on_enter() { |
619 | fn apply_on_enter(before: &str) -> Option<String> { | 667 | fn apply_on_enter(before: &str) -> Option<String> { |
620 | let (offset, before) = extract_offset(before); | 668 | let (offset, before) = extract_offset(before); |