From 7c36fb82df24cfa96ad2d2bf3fa769142c178fc1 Mon Sep 17 00:00:00 2001 From: tslil Date: Thu, 23 Oct 2025 20:58:39 +0100 Subject: One painful manual currying and Higher Rank Trait Bounds application later, i think complement transformations work now --- rprt-engine/src/selection_function.rs | 160 +++++++++++++++++++++++++++------- 1 file changed, 130 insertions(+), 30 deletions(-) (limited to 'rprt-engine/src/selection_function.rs') 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 Result>, - monadic_rank0: Box Result>, - monadic_rank1: Box Result>, - dyadic: Option Result>>, + niladic: Box Fn(&'a EditorState) -> Result>, + monadic_rank0: + Box Fn(&'a EditorState, BufferID, usize) -> Result>, + monadic_rank1: Box< + dyn for<'a, 'b> Fn(&'a EditorState, BufferID, &'b Interval) -> Result, + >, + dyadic: Option< + Box< + dyn for<'a, 'b, 'c> Fn( + &'a EditorState, + &'b Selection, + &'c Selection, + ) -> Result, + >, + >, } pub struct SelectionFunction { - niladic: Box Result>, - monadic: Box Result>, - dyadic: Option Result>>, + niladic: Box Fn(&'a EditorState) -> Result>, + monadic: Box Fn(&'a EditorState, &'b Selection) -> Result>, + dyadic: Option< + Box< + dyn for<'a, 'b, 'c> Fn( + &'a EditorState, + &'b Selection, + &'c Selection, + ) -> Result, + >, + >, } impl From for SelectionFunction> { fn from(sfc: SFComponents) -> Self { - let dyadic: Option _>> = - 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 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 Fn(&'a EditorState) -> _> = + Box::new(move |editor_state: &EditorState| { + (sfc.niladic)(editor_state).map_err(VectoriseError::ProcessingError) + }); + let monadic: Box 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 for SelectionFunction> { impl SelectionFunction> { pub fn transform_conditional(sf: Self) -> Self { - fn condition( - pred: Result>, - res: Selection, - ) -> Result> { - 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 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 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> { dyadic, } } + + pub fn complement_transform(sf: Self) -> Self { + fn complement_rank0( + es: &EditorState, + buffer_id: BufferID, + pos: usize, + ) -> Result { + 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 { + 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::vectorise(complement_rank0, complement_rank1, es, &selection) + } + + let dyadic: Option 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 Result<_, _>> = + Box::new(move |es, left| complement(es, (sf.monadic)(es, left)?)); + + let niladic: Box Result<_, _>> = + Box::new(move |es| complement(es, (sf.niladic)(es)?)); + + SelectionFunction { + niladic, + monadic, + dyadic, + } + } // ---------------------------------------------------------------- pub fn empty_sequential() -> Self { SFComponents { -- cgit v1.2.3