From f3acb5cc0faf739f09112607bb98b6594184bd8b Mon Sep 17 00:00:00 2001 From: tslil Date: Mon, 24 Aug 2026 20:39:57 +0100 Subject: The big transposition-ing: move from functions as data to data of functions Basically Rust will fight you all the way if you treat it like Haskell, instead work with traits and impls on ZSTs. --- .../src/selection_functions/function_character.rs | 298 ++++++++++++++++----- 1 file changed, 228 insertions(+), 70 deletions(-) (limited to 'rprt-engine/src/selection_functions/function_character.rs') diff --git a/rprt-engine/src/selection_functions/function_character.rs b/rprt-engine/src/selection_functions/function_character.rs index b4bbf0f..4b41297 100644 --- a/rprt-engine/src/selection_functions/function_character.rs +++ b/rprt-engine/src/selection_functions/function_character.rs @@ -1,91 +1,249 @@ use crate::{ - dispatch_selection_function, - selection::Selection, - selection_function, - selection_functions::types::{SFArguments, SFError, SFResult, get_buffer}, + buffer::BufferID, + expression::SearchModifier, + selection::{Interval, Selection}, + selection_functions::types::{SelectionFunction, SelectionFunctionError, get_buffer}, state::EditorState, }; -selection_function! { - name: character, - param_type: usize, - niladic: |(param, es): (usize, &EditorState)| { +pub struct Character; + +impl SelectionFunction for Character { + const NAME: &'static str = "character"; + + fn niladic( + &self, + param: &usize, + es: &EditorState, + ) -> Result { let buf = get_buffer(es, es.current_buffer_id)?; Ok(Selection::Scalar { buffer_id: es.current_buffer_id, - pos: usize::min(param, buf.max_pos()) + pos: usize::min(*param, buf.max_pos()), + }) + } - }) }, - monadic_rank0: |_, buffer_id, pos| Ok(Selection::Scalar {buffer_id, pos}), - monadic_rank1: |(param, _), buffer_id, int| Ok( - Selection::Scalar {buffer_id, pos: usize::min(int.end, *param)} - ) + fn monadic_rank0( + &self, + _param: &usize, + _es: &EditorState, + buffer_id: BufferID, + pos: usize, + ) -> Result { + Ok(Selection::Scalar { buffer_id, pos }) + } + + fn monadic_rank1( + &self, + param: &usize, + _es: &EditorState, + buffer_id: BufferID, + interval: &Interval, + ) -> Result { + Ok(Selection::Scalar { + buffer_id, + pos: usize::min(interval.start + *param, interval.end), + }) + } } -selection_function!( - name: sequential_character, - param_type: usize, - niladic: |_| Err(SFError::NoNiladicForm(";n").into()), - monadic_rank0: |(param, es), buffer_id, pos| { +pub struct SequentialCharacter; + +impl SelectionFunction for SequentialCharacter { + const NAME: &'static str = "sequential_character"; + + fn niladic( + &self, + _param: &usize, + _es: &EditorState, + ) -> Result { + Err(SelectionFunctionError::NoNiladicForm(";n")) + } + + fn monadic_rank0( + &self, + param: &usize, + es: &EditorState, + buffer_id: BufferID, + pos: usize, + ) -> Result { let buf = get_buffer(es, buffer_id)?; - Ok(Selection::Scalar {buffer_id, pos: usize::min(pos+*param, buf.max_pos())}) - }, - monadic_rank1: |(param, es), buffer_id, int| { + Ok(Selection::Scalar { + buffer_id, + pos: usize::min(pos + *param, buf.max_pos()), + }) + } + + fn monadic_rank1( + &self, + param: &usize, + es: &EditorState, + buffer_id: BufferID, + interval: &Interval, + ) -> Result { let buf = get_buffer(es, buffer_id)?; - Ok(Selection::Scalar {buffer_id, pos: usize::min(int.end+*param, buf.max_pos())}) + Ok(Selection::Scalar { + buffer_id, + pos: usize::min(interval.end + *param, buf.max_pos()), + }) } -); +} + +pub struct ReverseCharacter; + +impl SelectionFunction for ReverseCharacter { + const NAME: &'static str = "reverse_character"; -selection_function!( - name: reverse_character, - param_type: usize, - niladic: |(param, es): (usize, &EditorState)| { + fn niladic( + &self, + param: &usize, + es: &EditorState, + ) -> Result { let buf = get_buffer(es, es.current_buffer_id)?; Ok(Selection::Scalar { buffer_id: es.current_buffer_id, - pos: if buf.max_pos() < param { + pos: if buf.max_pos() < *param { + 0 + } else { + buf.max_pos() - *param + }, + }) + } + + fn monadic_rank0( + &self, + _param: &usize, + _es: &EditorState, + buffer_id: BufferID, + pos: usize, + ) -> Result { + Ok(Selection::Scalar { buffer_id, pos }) + } + + fn monadic_rank1( + &self, + param: &usize, + _es: &EditorState, + buffer_id: BufferID, + interval: &Interval, + ) -> Result { + Ok(Selection::Scalar { + buffer_id, + pos: if *param < interval.end { + interval.end - *param + } else { + 0 + }, + }) + } +} + +pub struct SequentialReverseCharacter; + +impl SelectionFunction for SequentialReverseCharacter { + const NAME: &'static str = "sequential_reverse_character"; + + fn niladic( + &self, + _param: &usize, + _es: &EditorState, + ) -> Result { + Err(SelectionFunctionError::NoNiladicForm(";'n")) + } + + fn monadic_rank0( + &self, + param: &usize, + _es: &EditorState, + buffer_id: BufferID, + pos: usize, + ) -> Result { + Ok(Selection::Scalar { + buffer_id, + pos: if *param < pos { pos - *param } else { 0 }, + }) + } + + fn monadic_rank1( + &self, + param: &usize, + _es: &EditorState, + buffer_id: BufferID, + interval: &Interval, + ) -> Result { + Ok(Selection::Scalar { + buffer_id, + pos: if *param < interval.end { + interval.end - *param + } else { 0 + }, + }) + } +} + +pub struct ReverseSequentialCharacter; + +impl SelectionFunction for ReverseSequentialCharacter { + const NAME: &'static str = "reverse_sequential_character"; + + fn niladic( + &self, + _param: &usize, + _es: &EditorState, + ) -> Result { + Err(SelectionFunctionError::NoNiladicForm("';n")) + } + + fn monadic_rank0( + &self, + param: &usize, + _es: &EditorState, + buffer_id: BufferID, + pos: usize, + ) -> Result { + Ok(Selection::Scalar { + buffer_id, + pos: if *param < pos { pos - *param } else { 0 }, + }) + } + + fn monadic_rank1( + &self, + param: &usize, + _es: &EditorState, + buffer_id: BufferID, + interval: &Interval, + ) -> Result { + Ok(Selection::Scalar { + buffer_id, + pos: if *param < interval.start { + interval.start - *param } else { - buf.max_pos() - param + 0 }, }) - }, - monadic_rank0: |_, buffer_id, pos| Ok(Selection::Scalar {buffer_id, pos}), - monadic_rank1: |(param, _), buffer_id, int| Ok( - Selection::Scalar {buffer_id, pos: usize::min(int.end, *param)} - ) -); - -selection_function!( - name: sequential_reverse_character, - param_type: usize, - niladic: |_| Err(SFError::NoNiladicForm(";'n").into()), - monadic_rank0: |(param, _), buffer_id, pos| { - Ok(Selection::Scalar {buffer_id, pos: if *param, + right: Option<&Selection>, + search_mod: Option, +) -> Result { + match search_mod { + None => Character.apply(&offset, es, left, right), + Some(SearchModifier::Sequential) => SequentialCharacter.apply(&offset, es, left, right), + Some(SearchModifier::Reverse) => ReverseCharacter.apply(&offset, es, left, right), + Some(SearchModifier::SequentialReverse) => { + SequentialReverseCharacter.apply(&offset, es, left, right) + } + Some(SearchModifier::ReverseSequential) => { + ReverseSequentialCharacter.apply(&offset, es, left, right) + } + } +} -- cgit v1.2.3