From f99398d9d5e47e28f3749c7903df67b9030ac6e0 Mon Sep 17 00:00:00 2001 From: Simon Vandel Sillesen Date: Sun, 6 Jan 2019 00:58:03 +0100 Subject: indent on typing dot. fixes #439 --- crates/ra_editor/src/lib.rs | 2 +- crates/ra_editor/src/typing.rs | 54 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 52 insertions(+), 4 deletions(-) (limited to 'crates/ra_editor/src') 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::{ line_index::{LineCol, LineIndex}, line_index_utils::translate_offset_with_edit, structure::{file_structure, StructureNode}, - typing::{join_lines, on_enter, on_eq_typed}, + typing::{join_lines, on_enter, on_dot_typed, on_eq_typed}, diagnostics::diagnostics }; 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 @@ use std::mem; +use itertools::Itertools; use ra_syntax::{ algo::{find_covering_node, find_leaf_at_offset, LeafAtOffset}, ast, @@ -9,9 +10,8 @@ use ra_syntax::{ SyntaxNodeRef, TextRange, TextUnit, }; use ra_text_edit::text_utils::contains_offset_nonstrict; -use itertools::Itertools; -use crate::{find_node_at_offset, TextEditBuilder, LocalEdit}; +use crate::{find_node_at_offset, LocalEdit, TextEditBuilder}; pub fn join_lines(file: &SourceFileNode, range: TextRange) -> LocalEdit { let range = if range.is_empty() { @@ -136,6 +136,27 @@ pub fn on_eq_typed(file: &SourceFileNode, offset: TextUnit) -> Option }) } +pub fn on_dot_typed(file: &SourceFileNode, offset: TextUnit) -> Option { + let before_dot_offset = offset - TextUnit::of_char('.'); + + let whitespace = find_leaf_at_offset(file.syntax(), before_dot_offset) + .left_biased() + .and_then(ast::Whitespace::cast)?; + + // whitespace found just left of the dot + // TODO: indent is always 4 spaces now. A better heuristic could look on the previous line(s) + let indent = " ".to_string(); + + let cursor_position = offset + TextUnit::of_str(&indent);; + let mut edit = TextEditBuilder::default(); + edit.insert(before_dot_offset, indent); + Some(LocalEdit { + label: "indent dot".to_string(), + edit: edit.finish(), + cursor_position: Some(cursor_position), + }) +} + fn remove_newline( edit: &mut TextEditBuilder, node: SyntaxNodeRef, @@ -283,7 +304,9 @@ fn compute_ws(left: SyntaxNodeRef, right: SyntaxNodeRef) -> &'static str { #[cfg(test)] mod tests { use super::*; - use crate::test_utils::{add_cursor, check_action, extract_offset, extract_range, assert_eq_text}; + use crate::test_utils::{ + add_cursor, assert_eq_text, check_action, extract_offset, extract_range, + }; fn check_join_lines(before: &str, after: &str) { check_action(before, after, |file, offset| { @@ -614,6 +637,31 @@ fn foo() { // "); } + #[test] + fn test_on_dot_typed() { + fn do_check(before: &str, after: &str) { + let (offset, before) = extract_offset(before); + let file = SourceFileNode::parse(&before); + let result = on_dot_typed(&file, offset).unwrap(); + let actual = result.edit.apply(&before); + assert_eq_text!(after, &actual); + } + do_check( + r" + pub fn child(&self, db: &impl HirDatabase, name: &Name) -> Cancelable> { + self.child_impl(db, name) + .<|> + } +", + r" + pub fn child(&self, db: &impl HirDatabase, name: &Name) -> Cancelable> { + self.child_impl(db, name) + . + } +", + ); + } + #[test] fn test_on_enter() { fn apply_on_enter(before: &str) -> Option { -- cgit v1.2.3