From 2fb854ccdae6f1f12b60441e5c3b283bdc81fb0a Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 7 Aug 2018 18:28:30 +0300 Subject: :tada: extend selection --- libeditor/src/extend_selection.rs | 36 ++++++++++++++++++++++++++++++++++++ libeditor/src/lib.rs | 29 +++++++++++++++++++++++++++-- 2 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 libeditor/src/extend_selection.rs (limited to 'libeditor/src') diff --git a/libeditor/src/extend_selection.rs b/libeditor/src/extend_selection.rs new file mode 100644 index 000000000..16d4bc084 --- /dev/null +++ b/libeditor/src/extend_selection.rs @@ -0,0 +1,36 @@ +use libsyntax2::{ + TextRange, SyntaxNodeRef, + SyntaxKind::WHITESPACE, + algo::{find_leaf_at_offset, find_covering_node, ancestors}, +}; + + +pub(crate) fn extend_selection(root: SyntaxNodeRef, range: TextRange) -> Option { + if range.is_empty() { + let offset = range.start(); + let mut leaves = find_leaf_at_offset(root, offset); + if let Some(leaf) = leaves.clone().find(|node| node.kind() != WHITESPACE) { + return Some(leaf.range()); + } + let ws = leaves.next()?; +// let ws_suffix = file.text().slice( +// TextRange::from_to(offset, ws.range().end()) +// ); +// if ws.text().contains("\n") && !ws_suffix.contains("\n") { +// if let Some(line_end) = file.text() +// .slice(TextSuffix::from(ws.range().end())) +// .find("\n") +// { +// let range = TextRange::from_len(ws.range().end(), line_end); +// return Some(find_covering_node(file.root(), range).range()); +// } +// } + return Some(ws.range()); + }; + let node = find_covering_node(root, range); + + match ancestors(node).skip_while(|n| n.range() == range).next() { + None => None, + Some(parent) => Some(parent.range()), + } +} diff --git a/libeditor/src/lib.rs b/libeditor/src/lib.rs index 091aed125..a0c003fb5 100644 --- a/libeditor/src/lib.rs +++ b/libeditor/src/lib.rs @@ -1,12 +1,13 @@ extern crate libsyntax2; -extern crate text_unit; + +mod extend_selection; use libsyntax2::{ SyntaxNodeRef, algo::walk, SyntaxKind::*, }; -use text_unit::TextRange; +pub use libsyntax2::{TextRange, TextUnit}; pub struct File { inner: libsyntax2::File @@ -71,6 +72,11 @@ impl File { .collect(); res // NLL :-( } + + pub fn extend_selection(&self, range: TextRange) -> Option { + let syntax = self.inner.syntax(); + extend_selection::extend_selection(syntax.as_ref(), range) + } } @@ -96,3 +102,22 @@ impl<'f> Declaration<'f> { self.0.range() } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_extend_selection() { + let text = r#"fn foo() { + 1 + 1 +} +"#; + let file = File::new(text); + let range = TextRange::offset_len(18.into(), 0.into()); + let range = file.extend_selection(range).unwrap(); + assert_eq!(range, TextRange::from_to(17.into(), 18.into())); + let range = file.extend_selection(range).unwrap(); + assert_eq!(range, TextRange::from_to(15.into(), 20.into())); + } +} -- cgit v1.2.3