diff options
Diffstat (limited to 'rprt-engine/src')
| -rw-r--r-- | rprt-engine/src/selection.rs | 73 | ||||
| -rw-r--r-- | rprt-engine/src/selection_function.rs | 160 |
2 files changed, 170 insertions, 63 deletions
diff --git a/rprt-engine/src/selection.rs b/rprt-engine/src/selection.rs index 1d1c557..9e619a4 100644 --- a/rprt-engine/src/selection.rs +++ b/rprt-engine/src/selection.rs @@ -37,6 +37,14 @@ pub struct Interval { } impl Interval { + pub fn new(start: usize, end: usize) -> Self { + Self { + start, + end, + capture_groups: Vec::new(), + } + } + pub fn is_disjoint(&self, other: &Interval) -> bool { self.start >= other.end || self.end <= other.start } @@ -61,7 +69,7 @@ pub enum Selection { }, } -// rust is stupid and i have to make a wrapper class and worse still _other +// rust is ... sigh. I have to make a wrapper class and worse still _other // people_ have to deal with my wrapper class! #[derive(Error, Debug)] pub enum VectoriseError<E> @@ -265,43 +273,42 @@ impl Selection { } pub fn vectorise<S, E>( - fn_rank_zero: impl Fn(&S, BufferID, usize) -> Result<Selection, E> + 'static, - fn_rank_one: impl Fn(&S, BufferID, &Interval) -> Result<Selection, E> + 'static, - ) -> impl Fn(&S, &Selection) -> Result<Selection, VectoriseError<E>> + fn_rank_zero: impl Fn(&S, BufferID, usize) -> Result<Selection, E>, + fn_rank_one: impl Fn(&S, BufferID, &Interval) -> Result<Selection, E>, + state: &S, + selection: &Selection, + ) -> Result<Selection, VectoriseError<E>> where E: std::error::Error + 'static, { // look at this mess! use VectoriseError::{ProcessingError, SelectionError}; - move |state: &S, selection: &Selection| { - let do_rank_one = |b: usize, rs: &Vec<Interval>| { - rs.iter() - .map(|int| fn_rank_one(state, b, int).map_err(ProcessingError)) - .collect::<Result<_, _>>() - }; - - match selection { - &Self::Position { buffer_id, pos } => { - fn_rank_zero(state, buffer_id, pos).map_err(ProcessingError) - } - Self::Range { - interval, - buffer_id, - } => fn_rank_one(state, *buffer_id, interval) - .map_err(VectoriseError::ProcessingError), - Self::Ranges { buffer_id, ranges } => { - let results = do_rank_one(*buffer_id, ranges)?; - Self::union(results).map_err(SelectionError) - } - Self::MultiRanges { multi_ranges } => { - let all_ok: Vec<Vec<Self>> = multi_ranges - .iter() - .map(|(buffer_id, ranges)| do_rank_one(*buffer_id, ranges)) - .collect::<Result<_, _>>()?; - // It would seem that Rust has no built in monadic flatten, or in general cannot lift things to operate on Result... :( - let results: Vec<Self> = all_ok.into_iter().flatten().collect(); - Self::union(results).map_err(SelectionError) - } + let do_rank_one = |b: usize, rs: &Vec<Interval>| { + rs.iter() + .map(|int| fn_rank_one(state, b, int).map_err(ProcessingError)) + .collect::<Result<_, _>>() + }; + + match selection { + &Self::Position { buffer_id, pos } => { + fn_rank_zero(state, buffer_id, pos).map_err(ProcessingError) + } + Self::Range { + interval, + buffer_id, + } => fn_rank_one(state, *buffer_id, interval).map_err(VectoriseError::ProcessingError), + Self::Ranges { buffer_id, ranges } => { + let results = do_rank_one(*buffer_id, ranges)?; + Self::union(results).map_err(SelectionError) + } + Self::MultiRanges { multi_ranges } => { + let all_ok: Vec<Vec<Self>> = multi_ranges + .iter() + .map(|(buffer_id, ranges)| do_rank_one(*buffer_id, ranges)) + .collect::<Result<_, _>>()?; + // It would seem that Rust has no built in monadic flatten, or in general cannot lift things to operate on Result... :( + let results: Vec<Self> = all_ok.into_iter().flatten().collect(); + Self::union(results).map_err(SelectionError) } } } diff --git a/rprt-engine/src/selection_function.rs b/rprt-engine/src/selection_function.rs index 0b6e98e..67f6ccc 100644 --- a/rprt-engine/src/selection_function.rs +++ b/rprt-engine/src/selection_function.rs @@ -10,34 +10,58 @@ pub enum SFError { } struct SFComponents { - niladic: Box<dyn Fn(&EditorState) -> Result<Selection, SFError>>, - monadic_rank0: Box<dyn Fn(&EditorState, BufferID, usize) -> Result<Selection, SFError>>, - monadic_rank1: Box<dyn Fn(&EditorState, BufferID, &Interval) -> Result<Selection, SFError>>, - dyadic: Option<Box<dyn Fn(&EditorState, &Selection, &Selection) -> Result<Selection, SFError>>>, + niladic: Box<dyn for<'a> Fn(&'a EditorState) -> Result<Selection, SFError>>, + monadic_rank0: + Box<dyn for<'a> Fn(&'a EditorState, BufferID, usize) -> Result<Selection, SFError>>, + monadic_rank1: Box< + dyn for<'a, 'b> Fn(&'a EditorState, BufferID, &'b Interval) -> Result<Selection, SFError>, + >, + dyadic: Option< + Box< + dyn for<'a, 'b, 'c> Fn( + &'a EditorState, + &'b Selection, + &'c Selection, + ) -> Result<Selection, SFError>, + >, + >, } pub struct SelectionFunction<E> { - niladic: Box<dyn Fn(&EditorState) -> Result<Selection, E>>, - monadic: Box<dyn Fn(&EditorState, &Selection) -> Result<Selection, E>>, - dyadic: Option<Box<dyn Fn(&EditorState, &Selection, &Selection) -> Result<Selection, E>>>, + niladic: Box<dyn for<'a> Fn(&'a EditorState) -> Result<Selection, E>>, + monadic: Box<dyn for<'a, 'b> Fn(&'a EditorState, &'b Selection) -> Result<Selection, E>>, + dyadic: Option< + Box< + dyn for<'a, 'b, 'c> Fn( + &'a EditorState, + &'b Selection, + &'c Selection, + ) -> Result<Selection, E>, + >, + >, } impl From<SFComponents> for SelectionFunction<VectoriseError<SFError>> { fn from(sfc: SFComponents) -> Self { - let dyadic: Option<Box<dyn Fn(&EditorState, &Selection, &Selection) -> _>> = - if let Some(func) = sfc.dyadic { - Some(Box::new( - move |editor_state: &EditorState, left: &Selection, right: &Selection| { - (func)(editor_state, left, right).map_err(VectoriseError::ProcessingError) - }, - )) - } else { - None - }; - let niladic = Box::new(move |editor_state: &EditorState| { - (sfc.niladic)(editor_state).map_err(VectoriseError::ProcessingError) - }); - let monadic = Box::new(Selection::vectorise(sfc.monadic_rank0, sfc.monadic_rank1)); + let dyadic: Option< + Box<dyn for<'a, 'b, 'c> Fn(&'a EditorState, &'b Selection, &'c Selection) -> _>, + > = if let Some(func) = sfc.dyadic { + Some(Box::new( + move |editor_state: &EditorState, left: &Selection, right: &Selection| { + (func)(editor_state, left, right).map_err(VectoriseError::ProcessingError) + }, + )) + } else { + None + }; + let niladic: Box<dyn for<'a> Fn(&'a EditorState) -> _> = + Box::new(move |editor_state: &EditorState| { + (sfc.niladic)(editor_state).map_err(VectoriseError::ProcessingError) + }); + let monadic: Box<dyn for<'a, 'b> Fn(&'a EditorState, &'b Selection) -> _> = + Box::new(move |es, left| { + Selection::vectorise(&*sfc.monadic_rank0, &*sfc.monadic_rank1, es, left) + }); Self { niladic, monadic, @@ -48,27 +72,25 @@ impl From<SFComponents> for SelectionFunction<VectoriseError<SFError>> { impl SelectionFunction<VectoriseError<SFError>> { pub fn transform_conditional(sf: Self) -> Self { - fn condition( - pred: Result<Selection, VectoriseError<SFError>>, - res: Selection, - ) -> Result<Selection, VectoriseError<SFError>> { - match pred { - Ok(mut sel) => Ok(if sel.is_empty() { sel } else { res }), - Err(e) => Err(e), + fn condition(mut pred: Selection, res: Selection) -> Selection { + if pred.is_empty() { + pred + } else { + res } } let dyadic: Option<Box<dyn Fn(&EditorState, &Selection, &Selection) -> Result<_, _>>> = if let Some(dyadic) = sf.dyadic { Some(Box::new(move |es, left, right| { - condition((dyadic)(es, left, right), left.clone()) + Ok(condition((dyadic)(es, left, right)?, left.clone())) })) } else { None }; let monadic: Box<dyn Fn(&EditorState, &Selection) -> Result<_, _>> = - Box::new(move |es, left| condition((sf.monadic)(es, left), left.clone())); + Box::new(move |es, left| Ok(condition((sf.monadic)(es, left)?, left.clone()))); SelectionFunction { niladic: sf.niladic, @@ -76,6 +98,84 @@ impl SelectionFunction<VectoriseError<SFError>> { dyadic, } } + + pub fn complement_transform(sf: Self) -> Self { + fn complement_rank0( + es: &EditorState, + buffer_id: BufferID, + pos: usize, + ) -> Result<Selection, SFError> { + if let Some(buf) = es.get_buffer(buffer_id) { + let mut ranges = Vec::new(); + if pos > 0 { + ranges.push(Interval::new(0, pos)); + } + let max_pos = buf.max_pos(); + if pos + 1 < max_pos { + ranges.push(Interval::new(pos + 1, max_pos)); + } + Ok(Selection::Ranges { buffer_id, ranges }) + } else { + Err(SFError::BufferNotFound(buffer_id)) + } + } + + fn complement_rank1( + es: &EditorState, + buffer_id: BufferID, + interval: &Interval, + ) -> Result<Selection, SFError> { + if let Some(buf) = es.get_buffer(buffer_id) { + let max_pos = buf.max_pos(); + if interval.start == 0 && interval.end >= max_pos { + return Ok(Selection::empty()); + } + + let mut ranges = Vec::new(); + if interval.start == 0 { + if interval.end < max_pos { + ranges.push(Interval::new(interval.end, max_pos)); + } + } else if interval.end == max_pos { + ranges.push(Interval::new(0, interval.start)); + } else { + ranges.push(Interval::new(0, interval.start)); + ranges.push(Interval::new(interval.end, max_pos)); + } + Ok(Selection::Ranges { buffer_id, ranges }) + } else { + Err(SFError::BufferNotFound(buffer_id)) + } + } + + fn complement( + es: &EditorState, + selection: Selection, + ) -> Result<Selection, VectoriseError<SFError>> { + Selection::vectorise(complement_rank0, complement_rank1, es, &selection) + } + + let dyadic: Option<Box<dyn Fn(&EditorState, &Selection, &Selection) -> Result<_, _>>> = + if let Some(dyadic) = sf.dyadic { + Some(Box::new(move |es, left, right| { + complement(es, (dyadic)(es, left, right)?) + })) + } else { + None + }; + + let monadic: Box<dyn Fn(&EditorState, &Selection) -> Result<_, _>> = + Box::new(move |es, left| complement(es, (sf.monadic)(es, left)?)); + + let niladic: Box<dyn Fn(&EditorState) -> Result<_, _>> = + Box::new(move |es| complement(es, (sf.niladic)(es)?)); + + SelectionFunction { + niladic, + monadic, + dyadic, + } + } // ---------------------------------------------------------------- pub fn empty_sequential() -> Self { SFComponents { |
