diff options
Diffstat (limited to 'helix-stdx')
-rw-r--r-- | helix-stdx/Cargo.toml | 1 | ||||
-rw-r--r-- | helix-stdx/src/rope.rs | 45 |
2 files changed, 44 insertions, 2 deletions
diff --git a/helix-stdx/Cargo.toml b/helix-stdx/Cargo.toml index 540a1b99..5ac7c011 100644 --- a/helix-stdx/Cargo.toml +++ b/helix-stdx/Cargo.toml @@ -16,6 +16,7 @@ dunce = "1.0" etcetera = "0.8" ropey = { version = "1.6.1", default-features = false } which = "6.0" +regex-cursor = "0.1.3" [dev-dependencies] tempfile = "3.10" diff --git a/helix-stdx/src/rope.rs b/helix-stdx/src/rope.rs index 4ee39d4a..7b4edda4 100644 --- a/helix-stdx/src/rope.rs +++ b/helix-stdx/src/rope.rs @@ -1,11 +1,22 @@ +use std::ops::{Bound, RangeBounds}; + +pub use regex_cursor::engines::meta::{Builder as RegexBuilder, Regex}; +pub use regex_cursor::regex_automata::util::syntax::Config; +use regex_cursor::{Input as RegexInput, RopeyCursor}; use ropey::RopeSlice; -pub trait RopeSliceExt: Sized { +pub trait RopeSliceExt<'a>: Sized { fn ends_with(self, text: &str) -> bool; fn starts_with(self, text: &str) -> bool; + fn regex_input(self) -> RegexInput<RopeyCursor<'a>>; + fn regex_input_at_bytes<R: RangeBounds<usize>>( + self, + byte_range: R, + ) -> RegexInput<RopeyCursor<'a>>; + fn regex_input_at<R: RangeBounds<usize>>(self, char_range: R) -> RegexInput<RopeyCursor<'a>>; } -impl RopeSliceExt for RopeSlice<'_> { +impl<'a> RopeSliceExt<'a> for RopeSlice<'a> { fn ends_with(self, text: &str) -> bool { let len = self.len_bytes(); if len < text.len() { @@ -23,4 +34,34 @@ impl RopeSliceExt for RopeSlice<'_> { self.get_byte_slice(..len - text.len()) .map_or(false, |start| start == text) } + + fn regex_input(self) -> RegexInput<RopeyCursor<'a>> { + RegexInput::new(self) + } + + fn regex_input_at<R: RangeBounds<usize>>(self, char_range: R) -> RegexInput<RopeyCursor<'a>> { + let start_bound = match char_range.start_bound() { + Bound::Included(&val) => Bound::Included(self.char_to_byte(val)), + Bound::Excluded(&val) => Bound::Excluded(self.char_to_byte(val)), + Bound::Unbounded => Bound::Unbounded, + }; + let end_bound = match char_range.end_bound() { + Bound::Included(&val) => Bound::Included(self.char_to_byte(val)), + Bound::Excluded(&val) => Bound::Excluded(self.char_to_byte(val)), + Bound::Unbounded => Bound::Unbounded, + }; + self.regex_input_at_bytes((start_bound, end_bound)) + } + fn regex_input_at_bytes<R: RangeBounds<usize>>( + self, + byte_range: R, + ) -> RegexInput<RopeyCursor<'a>> { + let input = match byte_range.start_bound() { + Bound::Included(&pos) | Bound::Excluded(&pos) => { + RegexInput::new(RopeyCursor::at(self, pos)) + } + Bound::Unbounded => RegexInput::new(self), + }; + input.range(byte_range) + } } |