aboutsummaryrefslogtreecommitdiff
path: root/rprt-engine/src/selection_functions/function_character.rs
diff options
context:
space:
mode:
authortslil <tslil@posteo.de>2026-08-24 20:39:57 +0100
committertslil <tslil@posteo.de>2026-08-24 21:39:25 +0100
commitf3acb5cc0faf739f09112607bb98b6594184bd8b (patch)
tree9f60aeda21a775f9d34ed8a70fffd9be638f27ce /rprt-engine/src/selection_functions/function_character.rs
parent72a5e0fc968e2bea9f7d348c7189ebc15a5b15d3 (diff)
The big transposition-ing: move from functions as data to data of functionsHEADmain
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.rs298
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)
+ }
+ }
+}