From dd91090a1ae931a604c51b9c6d7d8c9b46761af4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Mon, 15 Mar 2021 17:09:18 +0900 Subject: [PATCH] Implement keep_selections (filter selections on regex). --- helix-core/src/selection.rs | 35 +++++++++++++++++++++++++++-------- helix-term/src/commands.rs | 10 +++++++++- helix-term/src/keymap.rs | 1 + helix-view/src/editor.rs | 1 - 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/helix-core/src/selection.rs b/helix-core/src/selection.rs index ee925cbc..c34dff31 100644 --- a/helix-core/src/selection.rs +++ b/helix-core/src/selection.rs @@ -273,14 +273,33 @@ impl Selection { // TODO: checkSelection -> check if valid for doc length +pub fn keep_matches( + text: RopeSlice, + selection: &Selection, + regex: &crate::regex::Regex, +) -> Option { + let result: SmallVec<_> = selection + .ranges() + .iter() + .filter(|range| regex.is_match(&range.fragment(text))) + .copied() + .collect(); + + // TODO: figure out a new primary index + if !result.is_empty() { + return Some(Selection::new(result, 0)); + } + None +} + pub fn select_on_matches( text: RopeSlice, - selections: &Selection, + selection: &Selection, regex: &crate::regex::Regex, ) -> Option { - let mut result = SmallVec::with_capacity(selections.ranges().len()); + let mut result = SmallVec::with_capacity(selection.ranges().len()); - for sel in selections.ranges() { + for sel in selection.ranges() { // TODO: can't avoid occasional allocations since Regex can't operate on chunks yet let fragment = sel.fragment(text); @@ -309,12 +328,12 @@ pub fn select_on_matches( // TODO: support to split on capture #N instead of whole match pub fn split_on_matches( text: RopeSlice, - selections: &Selection, + selection: &Selection, regex: &crate::regex::Regex, ) -> Selection { - let mut result = SmallVec::with_capacity(selections.ranges().len()); + let mut result = SmallVec::with_capacity(selection.ranges().len()); - for sel in selections.ranges() { + for sel in selection.ranges() { // TODO: can't avoid occasional allocations since Regex can't operate on chunks yet let fragment = sel.fragment(text); @@ -417,9 +436,9 @@ mod test { let text = Rope::from("abcd efg wrs xyz 123 456"); - let selections = Selection::new(smallvec![Range::new(0, 8), Range::new(10, 19),], 0); + let selection = Selection::new(smallvec![Range::new(0, 8), Range::new(10, 19),], 0); - let result = split_on_matches(text.slice(..), &selections, &Regex::new(r"\s+").unwrap()); + let result = split_on_matches(text.slice(..), &selection, &Regex::new(r"\s+").unwrap()); assert_eq!( result.ranges(), diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 36edde4c..d75fd694 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -1156,7 +1156,15 @@ pub fn join_selections(cx: &mut Context) { pub fn keep_selections(cx: &mut Context) { let doc = cx.doc(); // keep selections matching regex - // and another method for inverse + let prompt = ui::regex_prompt(cx, "keep:".to_string(), |doc, regex| { + let text = doc.text().slice(..); + + if let Some(selection) = selection::keep_matches(text, doc.selection(), ®ex) { + doc.set_selection(selection); + } + }); + + cx.push_layer(Box::new(prompt)); } // diff --git a/helix-term/src/keymap.rs b/helix-term/src/keymap.rs index 58a465fe..a365050f 100644 --- a/helix-term/src/keymap.rs +++ b/helix-term/src/keymap.rs @@ -207,6 +207,7 @@ pub fn default() -> Keymaps { key!('<') => commands::unindent, key!('=') => commands::format_selections, shift!('J') => commands::join_selections, + // TODO: conflicts hover/doc shift!('K') => commands::keep_selections, // key!('q') => commands::record_macro, diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index 01a2dac5..f79eadad 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -44,7 +44,6 @@ impl Editor { .and_then(|language| self.language_servers.get(language, &executor)); if let Some(language_server) = language_server { - // TODO: do this everywhere doc.set_language_server(Some(language_server.clone())); smol::block_on(language_server.text_document_did_open(