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_end.rs | 204 ++++++++++++++++----- 1 file changed, 156 insertions(+), 48 deletions(-) (limited to 'rprt-engine/src/selection_functions/function_end.rs') diff --git a/rprt-engine/src/selection_functions/function_end.rs b/rprt-engine/src/selection_functions/function_end.rs index 75b4c96..ad161d2 100644 --- a/rprt-engine/src/selection_functions/function_end.rs +++ b/rprt-engine/src/selection_functions/function_end.rs @@ -1,57 +1,142 @@ 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, UnparameterisedSelectionFunction, get_buffer, + }, state::EditorState, }; -selection_function! { - name: end, - param_type: (), - niladic: |(_, es): ((), &EditorState)| { +pub struct End; + +impl UnparameterisedSelectionFunction for End { + const NAME: &'static str = "end"; + + fn niladic(&self, es: &EditorState) -> Result { let buf = get_buffer(es, es.current_buffer_id)?; Ok(Selection::Scalar { buffer_id: es.current_buffer_id, pos: buf.max_pos(), }) - }, - monadic_rank0: |_, buffer_id, pos | Ok(Selection::Scalar { buffer_id, pos }), - monadic_rank1: |_, buffer_id, int | Ok(Selection::Scalar { buffer_id, pos: int.end }) + } + + fn monadic_rank0( + &self, + _es: &EditorState, + buffer_id: BufferID, + pos: usize, + ) -> Result { + Ok(Selection::Scalar { buffer_id, pos }) + } + + fn monadic_rank1( + &self, + _es: &EditorState, + buffer_id: BufferID, + interval: &Interval, + ) -> Result { + Ok(Selection::Scalar { + buffer_id, + pos: interval.end, + }) + } } -selection_function! { - name: reverse_end, - param_type: (), - niladic: |(_, es): ((), &EditorState)| { +pub struct ReverseEnd; + +impl UnparameterisedSelectionFunction for ReverseEnd { + const NAME: &'static str = "reverse_end"; + + fn niladic(&self, es: &EditorState) -> Result { Ok(Selection::Scalar { buffer_id: es.current_buffer_id, pos: 0, }) - }, - monadic_rank0: |_, buffer_id, pos | Ok(Selection::Scalar { buffer_id, pos }), - monadic_rank1: |_, buffer_id, int | Ok(Selection::Scalar { buffer_id, pos: int.start }) + } + + fn monadic_rank0( + &self, + _es: &EditorState, + buffer_id: BufferID, + pos: usize, + ) -> Result { + Ok(Selection::Scalar { buffer_id, pos }) + } + + fn monadic_rank1( + &self, + _es: &EditorState, + buffer_id: BufferID, + interval: &Interval, + ) -> Result { + Ok(Selection::Scalar { + buffer_id, + pos: interval.start, + }) + } } -selection_function! { - name: sequential_end, - param_type: (), - niladic: |_| Err(SFError::NoNiladicForm(";$").into()), - monadic_rank0: |_, buffer_id, pos| Ok(Selection::Scalar { buffer_id, pos }), - monadic_rank1: |(_, es), buffer_id, _| { +pub struct SequentialEnd; + +impl UnparameterisedSelectionFunction for SequentialEnd { + const NAME: &'static str = "sequential_end"; + + fn niladic(&self, _es: &EditorState) -> Result { + Err(SelectionFunctionError::NoNiladicForm(";$")) + } + + fn monadic_rank0( + &self, + es: &EditorState, + buffer_id: BufferID, + _pos: usize, + ) -> Result { + let buf = get_buffer(es, buffer_id)?; + Ok(Selection::Scalar { + buffer_id, + pos: buf.max_pos(), + }) + } + + fn monadic_rank1( + &self, + es: &EditorState, + buffer_id: BufferID, + _interval: &Interval, + ) -> Result { let buf = get_buffer(es, buffer_id)?; - Ok(Selection::Scalar { buffer_id, pos: buf.max_pos() }) + Ok(Selection::Scalar { + buffer_id, + pos: buf.max_pos(), + }) } } -selection_function! { - name: sequential_reverse_end, - param_type: (), - niladic: |_| Err(SFError::NoNiladicForm(";'$").into()), - monadic_rank0: |_, buffer_id, pos| { +pub struct SequentialReverseEnd; + +impl UnparameterisedSelectionFunction for SequentialReverseEnd { + const NAME: &'static str = "sequential_reverse_end"; + + fn niladic(&self, _es: &EditorState) -> Result { + Err(SelectionFunctionError::NoNiladicForm(";'$")) + } + + fn monadic_rank0( + &self, + _es: &EditorState, + buffer_id: BufferID, + pos: usize, + ) -> Result { Ok(Selection::Scalar { buffer_id, pos }) - }, - monadic_rank1: |_, buffer_id, interval| { + } + + fn monadic_rank1( + &self, + _es: &EditorState, + buffer_id: BufferID, + interval: &Interval, + ) -> Result { Ok(Selection::Scalar { buffer_id, pos: interval.end, @@ -59,14 +144,30 @@ selection_function! { } } -selection_function! { - name: reverse_sequential_end, - param_type: (), - niladic: |_| Err(SFError::NoNiladicForm("';$").into()), - monadic_rank0: |_, buffer_id, pos| { +pub struct ReverseSequentialEnd; + +impl UnparameterisedSelectionFunction for ReverseSequentialEnd { + const NAME: &'static str = "reverse_sequential_end"; + + fn niladic(&self, _es: &EditorState) -> Result { + Err(SelectionFunctionError::NoNiladicForm("';$")) + } + + fn monadic_rank0( + &self, + _es: &EditorState, + buffer_id: BufferID, + pos: usize, + ) -> Result { Ok(Selection::Scalar { buffer_id, pos }) - }, - monadic_rank1: |_, buffer_id, interval| { + } + + fn monadic_rank1( + &self, + _es: &EditorState, + buffer_id: BufferID, + interval: &Interval, + ) -> Result { Ok(Selection::Scalar { buffer_id, pos: interval.end, @@ -74,12 +175,19 @@ selection_function! { } } -dispatch_selection_function!( - name: selection_function_end, - param_type: (), - base: end, - sequential: sequential_end, - reverse: reverse_end, - sequential_reverse: sequential_reverse_end, - reverse_sequential: reverse_sequential_end, -); +/// Dispatch on the search modifier and apply the matching end-family +/// function to the supplied selections. +pub fn selection_function_end( + es: &EditorState, + left: Option<&Selection>, + right: Option<&Selection>, + search_mod: Option, +) -> Result { + match search_mod { + None => End.apply(&(), es, left, right), + Some(SearchModifier::Sequential) => SequentialEnd.apply(&(), es, left, right), + Some(SearchModifier::Reverse) => ReverseEnd.apply(&(), es, left, right), + Some(SearchModifier::SequentialReverse) => SequentialReverseEnd.apply(&(), es, left, right), + Some(SearchModifier::ReverseSequential) => ReverseSequentialEnd.apply(&(), es, left, right), + } +} -- cgit v1.2.3