aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rprt-engine/src/selection.rs73
-rw-r--r--rprt-engine/src/selection_function.rs160
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 {