diff --git a/helix-core/src/selection.rs b/helix-core/src/selection.rs index ee925cbc2..c34dff31c 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 36edde4c4..d75fd694c 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 58a465fe5..a365050f0 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 01a2dac57..f79eadad8 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(