diff options
| author | tslil <tslil@posteo.de> | 2026-08-24 20:39:57 +0100 |
|---|---|---|
| committer | tslil <tslil@posteo.de> | 2026-08-24 21:39:25 +0100 |
| commit | f3acb5cc0faf739f09112607bb98b6594184bd8b (patch) | |
| tree | 9f60aeda21a775f9d34ed8a70fffd9be638f27ce /rprt-engine/src/selection_functions/function_character.rs | |
| parent | 72a5e0fc968e2bea9f7d348c7189ebc15a5b15d3 (diff) | |
Basically Rust will fight you all the way if you treat it like Haskell, instead work with traits and impls on ZSTs.
Diffstat (limited to 'rprt-engine/src/selection_functions/function_character.rs')
| -rw-r--r-- | rprt-engine/src/selection_functions/function_character.rs | 298 |
1 files changed, 228 insertions, 70 deletions
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<usize> for Character { + const NAME: &'static str = "character"; + + fn niladic( + &self, + param: &usize, + es: &EditorState, + ) -> Result<Selection, SelectionFunctionError> { 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<Selection, SelectionFunctionError> { + Ok(Selection::Scalar { buffer_id, pos }) + } + + fn monadic_rank1( + &self, + param: &usize, + _es: &EditorState, + buffer_id: BufferID, + interval: &Interval, + ) -> Result<Selection, SelectionFunctionError> { + 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<usize> for SequentialCharacter { + const NAME: &'static str = "sequential_character"; + + fn niladic( + &self, + _param: &usize, + _es: &EditorState, + ) -> Result<Selection, SelectionFunctionError> { + Err(SelectionFunctionError::NoNiladicForm(";n")) + } + + fn monadic_rank0( + &self, + param: &usize, + es: &EditorState, + buffer_id: BufferID, + pos: usize, + ) -> Result<Selection, SelectionFunctionError> { 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<Selection, SelectionFunctionError> { 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<usize> 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<Selection, SelectionFunctionError> { 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<Selection, SelectionFunctionError> { + Ok(Selection::Scalar { buffer_id, pos }) + } + + fn monadic_rank1( + &self, + param: &usize, + _es: &EditorState, + buffer_id: BufferID, + interval: &Interval, + ) -> Result<Selection, SelectionFunctionError> { + Ok(Selection::Scalar { + buffer_id, + pos: if *param < interval.end { + interval.end - *param + } else { + 0 + }, + }) + } +} + +pub struct SequentialReverseCharacter; + +impl SelectionFunction<usize> for SequentialReverseCharacter { + const NAME: &'static str = "sequential_reverse_character"; + + fn niladic( + &self, + _param: &usize, + _es: &EditorState, + ) -> Result<Selection, SelectionFunctionError> { + Err(SelectionFunctionError::NoNiladicForm(";'n")) + } + + fn monadic_rank0( + &self, + param: &usize, + _es: &EditorState, + buffer_id: BufferID, + pos: usize, + ) -> Result<Selection, SelectionFunctionError> { + 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<Selection, SelectionFunctionError> { + Ok(Selection::Scalar { + buffer_id, + pos: if *param < interval.end { + interval.end - *param + } else { 0 + }, + }) + } +} + +pub struct ReverseSequentialCharacter; + +impl SelectionFunction<usize> for ReverseSequentialCharacter { + const NAME: &'static str = "reverse_sequential_character"; + + fn niladic( + &self, + _param: &usize, + _es: &EditorState, + ) -> Result<Selection, SelectionFunctionError> { + Err(SelectionFunctionError::NoNiladicForm("';n")) + } + + fn monadic_rank0( + &self, + param: &usize, + _es: &EditorState, + buffer_id: BufferID, + pos: usize, + ) -> Result<Selection, SelectionFunctionError> { + 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<Selection, SelectionFunctionError> { + 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<pos {pos - *param} else {0}}) - }, - monadic_rank1: |(param, _), buffer_id, int| { - Ok(Selection::Scalar {buffer_id, pos: if *param<int.end {int.end - *param} else {0}}) - } -); - -selection_function!( - name: reverse_sequential_character, - param_type: usize, - niladic: |_| Err(SFError::NoNiladicForm("';n").into()), - monadic_rank0: |(param, _), buffer_id, pos| { - Ok(Selection::Scalar {buffer_id, pos: if *param<pos {pos - *param} else {0}}) - }, - monadic_rank1: |(param, _), buffer_id, int| { - Ok(Selection::Scalar {buffer_id, pos: if *param<int.start {int.start - *param} else {0}}) - } -); - -dispatch_selection_function!( - name: selection_function_character, - param_type: usize, - base: character, - sequential: sequential_character, - reverse: reverse_character, - sequential_reverse: sequential_reverse_character, - reverse_sequential: reverse_sequential_character, -); + } +} + +/// Dispatch on the search modifier and apply the matching character-family +/// function to the supplied selections. +pub fn selection_function_character( + offset: usize, + es: &EditorState, + left: Option<&Selection>, + right: Option<&Selection>, + search_mod: Option<SearchModifier>, +) -> Result<Selection, SelectionFunctionError> { + 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) + } + } +} |
