diff options
| author | tslil <tslil@posteo.de> | 2025-10-22 21:02:01 +0100 |
|---|---|---|
| committer | tslil <tslil@posteo.de> | 2025-10-22 21:52:43 +0100 |
| commit | 20674aa65148558fb849eb1bb9c8a5e4a0cf483d (patch) | |
| tree | d2b54ae8b20ca0a7041b9d29f19f50944f47ed35 /rprt-engine | |
| parent | 9f3e21628231f3fa91ab8ff45872a76e7e11fcc4 (diff) | |
Implement two basic selection functions
Diffstat (limited to 'rprt-engine')
| -rw-r--r-- | rprt-engine/src/selection.rs | 110 | ||||
| -rw-r--r-- | rprt-engine/src/selection_function.rs | 77 | ||||
| -rw-r--r-- | rprt-engine/src/state.rs | 12 |
3 files changed, 132 insertions, 67 deletions
diff --git a/rprt-engine/src/selection.rs b/rprt-engine/src/selection.rs index c15512d..ee83294 100644 --- a/rprt-engine/src/selection.rs +++ b/rprt-engine/src/selection.rs @@ -45,15 +45,15 @@ impl Interval { #[derive(Debug, Clone)] pub enum Selection { Position { + buffer_id: BufferID, pos: usize, - buffer: BufferID, }, Range { - buffer: BufferID, + buffer_id: BufferID, interval: Interval, }, Ranges { - buffer: BufferID, + buffer_id: BufferID, ranges: Vec<Interval>, }, MultiRanges { @@ -91,33 +91,23 @@ impl Selection { } } - pub fn ranges_disjoint(ranges: &[Interval]) -> bool { - if ranges.len() < 1 { - return true; + fn normalise(&mut self) { + if let Self::MultiRanges { multi_ranges } = self { + multi_ranges.retain(|_, v| !v.is_empty()) } - - let mut sorted_by_start: Vec<&Interval> = ranges.iter().collect::<Vec<_>>(); - sorted_by_start.sort_by_key(|i| i.start); - sorted_by_start.windows(2).all(|w| w[0].is_disjoint(&w[1])) } - pub fn is_disjoint(&self) -> bool { + pub fn is_empty(&mut self) -> bool { + self.normalise(); match self { - Self::Position { .. } => true, - Self::Range { .. } => true, - Self::Ranges { ranges, .. } => Self::ranges_disjoint(ranges), - Self::MultiRanges { multi_ranges } => { - for (_, intervals) in multi_ranges { - if !Self::ranges_disjoint(intervals) { - return false; - } - } - true - } + Self::Position { .. } => return false, + Self::Range { .. } => return false, + Self::Ranges { ranges, .. } => ranges.is_empty(), + Self::MultiRanges { multi_ranges } => multi_ranges.is_empty(), } } - pub fn rank(&self) -> Rank { + fn rank(&self) -> Rank { match self { Self::Position { .. } => Rank::Zero, Self::Range { .. } => Rank::One, @@ -126,7 +116,7 @@ impl Selection { } } - pub fn promote(&self, to_rank: Rank) -> Result<Self, SelectionError> { + fn promote(&self, to_rank: Rank) -> Result<Self, SelectionError> { use Rank::*; match (self, to_rank) { @@ -136,26 +126,26 @@ impl Selection { (Self::MultiRanges { .. }, Three) => Ok(self.clone()), // Position - (Self::Position { pos, buffer }, One) => Ok(Self::Range { + (Self::Position { pos, buffer_id }, One) => Ok(Self::Range { interval: Interval { start: pos + 0, end: pos + 1, capture_groups: Vec::new(), }, - buffer: *buffer, + buffer_id: *buffer_id, }), - (Self::Position { pos, buffer }, Two) => Ok(Self::Ranges { + (Self::Position { pos, buffer_id }, Two) => Ok(Self::Ranges { ranges: vec![Interval { start: pos + 0, end: pos + 1, capture_groups: Vec::new(), }], - buffer: *buffer, + buffer_id: *buffer_id, }), - (Self::Position { pos, buffer }, Three) => { + (Self::Position { pos, buffer_id }, Three) => { let mut map = HashMap::new(); map.insert( - *buffer, + *buffer_id, vec![Interval { start: pos + 0, end: pos + 1, @@ -166,20 +156,32 @@ impl Selection { } // Range promotions - (Self::Range { interval, buffer }, Two) => Ok(Self::Ranges { + ( + Self::Range { + interval, + buffer_id, + }, + Two, + ) => Ok(Self::Ranges { ranges: vec![interval.clone()], - buffer: *buffer, + buffer_id: *buffer_id, }), - (Self::Range { interval, buffer }, Three) => { + ( + Self::Range { + interval, + buffer_id, + }, + Three, + ) => { let mut map = HashMap::new(); - map.insert(*buffer, vec![interval.clone()]); + map.insert(*buffer_id, vec![interval.clone()]); Ok(Self::MultiRanges { multi_ranges: map }) } // Ranges promotion - (Self::Ranges { ranges, buffer }, Three) => { + (Self::Ranges { ranges, buffer_id }, Three) => { let mut map = HashMap::new(); - map.insert(*buffer, ranges.clone()); + map.insert(*buffer_id, ranges.clone()); Ok(Self::MultiRanges { multi_ranges: map }) } @@ -191,11 +193,11 @@ impl Selection { } } - pub fn buffers(&self) -> Vec<BufferID> { + fn buffers(&self) -> Vec<BufferID> { match self { - Self::Position { buffer, .. } => vec![*buffer], - Self::Range { buffer, .. } => vec![*buffer], - Self::Ranges { buffer, .. } => vec![*buffer], + Self::Position { buffer_id, .. } => vec![*buffer_id], + Self::Range { buffer_id, .. } => vec![*buffer_id], + Self::Ranges { buffer_id, .. } => vec![*buffer_id], Self::MultiRanges { multi_ranges } => multi_ranges.keys().copied().collect(), } } @@ -229,7 +231,7 @@ impl Selection { match max_rank { Rank::Two => { let mut all_intervals = Vec::new(); - let buffer = *all_buffers.iter().next().unwrap(); + let buffer_id = *all_buffers.iter().next().unwrap(); for sel in &promoted { match sel { @@ -240,7 +242,7 @@ impl Selection { Ok(Self::Ranges { ranges: all_intervals, - buffer, + buffer_id, }) } Rank::Three => { @@ -272,8 +274,8 @@ 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, + 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>> where E: std::error::Error + 'static, @@ -281,27 +283,29 @@ impl Selection { // look at this mess! use VectoriseError::{ProcessingError, SelectionError}; move |state: &S, selection: &Selection| { - let do_rank_one = |b: &usize, rs: &Vec<Interval>| { + 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, pos } => { - fn_rank_zero(state, buffer, *pos).map_err(ProcessingError) - } - Self::Range { buffer, interval } => { - fn_rank_one(state, buffer, interval).map_err(VectoriseError::ProcessingError) + &Self::Position { buffer_id, pos } => { + fn_rank_zero(state, buffer_id, pos).map_err(ProcessingError) } - Self::Ranges { buffer, ranges } => { - let results = do_rank_one(buffer, ranges)?; + 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, ranges)| do_rank_one(buffer, ranges)) + .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(); diff --git a/rprt-engine/src/selection_function.rs b/rprt-engine/src/selection_function.rs index 6f05650..3da61c9 100644 --- a/rprt-engine/src/selection_function.rs +++ b/rprt-engine/src/selection_function.rs @@ -4,12 +4,15 @@ use crate::state::EditorState; use thiserror::Error; #[derive(Error, Debug)] -pub enum SFError {} +pub enum SFError { + #[error("Could not find buffer {0}")] + BufferNotFound(BufferID), +} 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>>, + 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>>>, } @@ -31,13 +34,71 @@ impl From<SFComponents> for SelectionFunction<VectoriseError<SFError>> { } 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)); Self { - niladic: Box::new(move |editor_state: &EditorState| { - (sfc.niladic)(editor_state).map_err(VectoriseError::ProcessingError) + niladic, + monadic, + dyadic, + } + } +} + +impl SelectionFunction<VectoriseError<SFError>> { + pub fn empty() -> Self { + SFComponents { + niladic: Box::new(|_| Ok(Selection::empty())), + monadic_rank0: Box::new(|_, _, _| Ok(Selection::empty())), + monadic_rank1: Box::new(|_, _, _| Ok(Selection::empty())), + dyadic: None, + } + .into() + } + + pub fn end_sequential() -> Self { + fn get_end_position(es: &EditorState, buffer_id: BufferID) -> Result<Selection, SFError> { + if let Some(buf) = es.get_buffer(buffer_id) { + Ok(Selection::Position { + buffer_id: buffer_id, + pos: buf.max_pos(), + }) + } else { + Err(SFError::BufferNotFound(buffer_id)) + } + } + + SFComponents { + niladic: Box::new(|es| get_end_position(es, es.current_buffer_id)), + monadic_rank0: Box::new(|es, buffer_id, _| get_end_position(es, buffer_id)), + monadic_rank1: Box::new(|es, buffer_id, _| get_end_position(es, buffer_id)), + dyadic: None, + } + .into() + } + + pub fn end_structural() -> Self { + SFComponents { + niladic: Box::new(|es| { + if let Some(buf) = es.current_buffer() { + Ok(Selection::Position { + buffer_id: es.current_buffer_id, + pos: buf.max_pos(), + }) + } else { + Err(SFError::BufferNotFound(es.current_buffer_id)) + } + }), + monadic_rank0: Box::new(|_, buffer_id, pos| Ok(Selection::Position { buffer_id, pos })), + monadic_rank1: Box::new(|_, buffer_id, int| { + Ok(Selection::Position { + buffer_id, + pos: int.end, + }) }), - monadic: Box::new(Selection::vectorise(sfc.monadic_rank0, sfc.monadic_rank1)), - dyadic: dyadic, + dyadic: None, } + .into() } } diff --git a/rprt-engine/src/state.rs b/rprt-engine/src/state.rs index bc6fbb6..68283d0 100644 --- a/rprt-engine/src/state.rs +++ b/rprt-engine/src/state.rs @@ -65,7 +65,7 @@ impl StateChange { #[derive(Debug)] pub struct EditorState { - current_buffer: BufferID, + pub current_buffer_id: BufferID, current_selection: Selection, buffers: HashMap<BufferID, Buffer>, buffer_to_file: HashMap<BufferID, Option<PathBuf>>, @@ -76,7 +76,7 @@ pub struct EditorState { impl EditorState { pub fn new() -> Self { Self { - current_buffer: 0, + current_buffer_id: 0, current_selection: Selection::empty(), buffers: HashMap::new(), buffer_to_file: HashMap::new(), @@ -106,12 +106,12 @@ impl EditorState { buffer_id } - pub fn get_buffer(&self, buffer_id: BufferID) -> Option<&Buffer> { - self.buffers.get(&buffer_id) + pub fn current_buffer(&self) -> Option<&Buffer> { + self.buffers.get(&self.current_buffer_id) } - pub fn get_buffer_mut(&mut self, buffer_id: BufferID) -> Option<&mut Buffer> { - self.buffers.get_mut(&buffer_id) + pub fn get_buffer(&self, buffer_id: BufferID) -> Option<&Buffer> { + self.buffers.get(&buffer_id) } pub fn commit(&mut self, change: StateChange) { |
