From f7c23142e8c73732fe3f75d03dc36e905f28715b Mon Sep 17 00:00:00 2001 From: tslil Date: Fri, 31 Oct 2025 11:29:08 +0000 Subject: Refactor selection functions into a module, one function per file --- rprt-engine/src/lib.rs | 4 +- rprt-engine/src/selection_function.rs | 242 --------------------- .../src/selection_functions/function_character.rs | 38 ++++ .../src/selection_functions/function_empty.rs | 10 + .../src/selection_functions/function_end.rs | 37 ++++ rprt-engine/src/selection_functions/mod.rs | 5 + .../selection_functions/result_transformation.rs | 77 +++++++ rprt-engine/src/selection_functions/types.rs | 78 +++++++ 8 files changed, 246 insertions(+), 245 deletions(-) delete mode 100644 rprt-engine/src/selection_function.rs create mode 100644 rprt-engine/src/selection_functions/function_character.rs create mode 100644 rprt-engine/src/selection_functions/function_empty.rs create mode 100644 rprt-engine/src/selection_functions/function_end.rs create mode 100644 rprt-engine/src/selection_functions/mod.rs create mode 100644 rprt-engine/src/selection_functions/result_transformation.rs create mode 100644 rprt-engine/src/selection_functions/types.rs (limited to 'rprt-engine') diff --git a/rprt-engine/src/lib.rs b/rprt-engine/src/lib.rs index 3eda2e4..8886578 100644 --- a/rprt-engine/src/lib.rs +++ b/rprt-engine/src/lib.rs @@ -1,10 +1,8 @@ -// RPRT Engine - Core text editing functionality - pub mod buffer; pub mod expression; pub mod monad; pub mod parser; pub mod selection; -pub mod selection_function; +pub mod selection_functions; pub mod state; pub mod token; diff --git a/rprt-engine/src/selection_function.rs b/rprt-engine/src/selection_function.rs deleted file mode 100644 index 95281ad..0000000 --- a/rprt-engine/src/selection_function.rs +++ /dev/null @@ -1,242 +0,0 @@ -use crate::buffer::BufferID; -use crate::selection::{Interval, Selection, VectoriseError}; -use crate::state::EditorState; -use thiserror::Error; - -#[derive(Error, Debug)] -pub enum SFError { - #[error("Could not find buffer {0}")] - BufferNotFound(BufferID), - #[error("Function {0} has no dyadic form")] - NoDyadicForm(&'static str), -} - -pub enum SFArguments<'a> { - Niladic { - es: &'a EditorState, - }, - Monadic { - es: &'a EditorState, - left: Selection, - }, - Dyadic { - es: &'a EditorState, - left: Selection, - right: Selection, - }, -} - -type SFResult = Result>; - -fn rust_has_an_annoying_issue(r: Result) -> SFResult { - r.map_err(Into::into) -} - -macro_rules! selection_function { - ( - name: $name:ident, - niladic: $niladic_body:expr, - monadic_rank0: $monadic_rank0_body:expr, - monadic_rank1: $monadic_rank1_body:expr - ) => { - pub fn $name(arg: SFArguments) -> SFResult { - match arg { - SFArguments::Niladic { es } => rust_has_an_annoying_issue({ $niladic_body(es) }), - SFArguments::Monadic { es, left } => { - left.vectorise(es, $monadic_rank0_body, $monadic_rank1_body) - } - SFArguments::Dyadic { .. } => Err(SFError::NoDyadicForm(stringify!($name)).into()), - } - } - }; -} - -macro_rules! selection_function_param { - ( - name: $name:ident, - param_type: $P:ty, - niladic: $niladic_body:expr, - monadic_rank0: $monadic_rank0_body:expr, - monadic_rank1: $monadic_rank1_body:expr - ) => { - pub fn $name(param: $P, arg: SFArguments) -> SFResult { - match arg { - SFArguments::Niladic { es } => { - rust_has_an_annoying_issue({ $niladic_body((param, es)) }) - } - SFArguments::Monadic { es, left } => { - left.vectorise(&(param, es), $monadic_rank0_body, $monadic_rank1_body) - } - SFArguments::Dyadic { .. } => Err(SFError::NoDyadicForm(stringify!($name)).into()), - } - } - }; -} - -// ---------------------------------------------------------------- -pub fn complement_transform(es: &EditorState, result: Selection, _: &SFArguments) -> SFResult { - fn complement_rank0( - es: &EditorState, - buffer_id: BufferID, - pos: usize, - ) -> Result { - 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 { - 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)) - } - } - - result.vectorise(es, complement_rank0, complement_rank1) -} - -pub fn conditional_transform( - _: &EditorState, - mut result: Selection, - arg: &SFArguments, -) -> SFResult { - if !result.is_empty() { - Ok(match arg { - // TODO: think about this niladic case? - SFArguments::Niladic { .. } => Selection::empty(), - SFArguments::Monadic { es: _, left } => left.clone(), - SFArguments::Dyadic { - es: _, - left, - right: _, - } => left.clone(), - }) - } else { - Ok(result) - } -} - -// ---------------------------------------------------------------- - -pub fn empty_sequential(_: SFArguments) -> SFResult { - Ok(Selection::empty()) -} - -pub fn empy_structural(_: SFArguments) -> SFResult { - Ok(Selection::empty()) -} - -selection_function! { - name: end_sequential, - niladic: |es: &EditorState| { - es.current_buffer().map(|buf| Selection::Position { - buffer_id: es.current_buffer_id, - pos: buf.max_pos() - }).ok_or(SFError::BufferNotFound(es.current_buffer_id)) - }, - monadic_rank0: |_, buffer_id, pos| { - Ok(Selection::Position { buffer_id, pos }) - }, - monadic_rank1: |_, buffer_id, interval| { - Ok(Selection::Position { - buffer_id, - pos: interval.end, - }) - } -} - -selection_function! { - name: end_structural, - niladic: |es: &EditorState| { - if let Some(buf) = es.current_buffer() { - Ok(Selection::Position { - buffer_id: es.current_buffer_id, - pos: buf.max_pos(), - }) - } else { - Err(SFError::BufferNotFound(es.current_buffer_id).into()) - } - }, - monadic_rank0: |_, buffer_id, pos | Ok(Selection::Position { buffer_id, pos }), - monadic_rank1: |_, buffer_id, int | Ok(Selection::Position { - buffer_id, - pos: int.end, - }) -} - -selection_function_param! { - name: character_structural, - param_type: usize, - niladic: |(param, es): (usize, &EditorState)| { - if let Some(buf) = es.current_buffer() { - Ok(Selection::Position { - buffer_id: es.current_buffer_id, - pos: usize::min(param, buf.max_pos()), - }) - } else { - Err(SFError::BufferNotFound(es.current_buffer_id).into()) - } - }, - monadic_rank0: |_, buffer_id, pos| Ok(Selection::Position {buffer_id, pos}), - monadic_rank1: |(param, _), buffer_id, int| Ok(Selection::Position {buffer_id, pos: usize::min(int.end, *param)}) -} - -selection_function_param! { - name: character_sequential, - param_type: usize, - niladic: |(param, es): (usize, &EditorState)| { - if let Some(buf) = es.current_buffer() { - Ok(Selection::Position { - buffer_id: es.current_buffer_id, - pos: usize::min(param, buf.max_pos()), - }) - } else { - Err(SFError::BufferNotFound(es.current_buffer_id).into()) - } - }, - monadic_rank0: |(param, es), buffer_id, pos| { - if let Some(buf) = es.get_buffer(buffer_id) { - Ok(Selection::Position {buffer_id, pos: usize::min(pos+*param, buf.max_pos())}) - } else { - Err(SFError::BufferNotFound(buffer_id).into()) - } - }, - monadic_rank1: |(param, es), buffer_id, int| { - if let Some(buf) = es.get_buffer(buffer_id) { - Ok(Selection::Position {buffer_id, pos: usize::min(int.end+*param, buf.max_pos())}) - } else { - Err(SFError::BufferNotFound(buffer_id).into()) - } - } -} diff --git a/rprt-engine/src/selection_functions/function_character.rs b/rprt-engine/src/selection_functions/function_character.rs new file mode 100644 index 0000000..3d9695f --- /dev/null +++ b/rprt-engine/src/selection_functions/function_character.rs @@ -0,0 +1,38 @@ +use crate::selection::Selection; +use crate::selection_function_param; +use crate::selection_functions::types::{get_buffer, SFArguments, SFError, SFResult}; +use crate::state::EditorState; + +selection_function_param! { + name: character_structural, + param_type: usize, + niladic: |(param, es): (usize, &EditorState)| { + let buf = get_buffer(es, es.current_buffer_id)?; + Ok(Selection::Position { + buffer_id: es.current_buffer_id, + pos: usize::min(param, buf.max_pos()) + + }) }, + monadic_rank0: |_, buffer_id, pos| Ok(Selection::Position {buffer_id, pos}), + monadic_rank1: |(param, _), buffer_id, int| Ok(Selection::Position {buffer_id, pos: usize::min(int.end, *param)}) +} + +selection_function_param! { + name: character_sequential, + param_type: usize, + niladic: |(param, es): (usize, &EditorState)| { + let buf = get_buffer(es, es.current_buffer_id)?; + Ok(Selection::Position { + buffer_id: es.current_buffer_id, + pos: usize::min(param, buf.max_pos()), + }) + }, + monadic_rank0: |(param, es), buffer_id, pos| { + let buf = get_buffer(es, buffer_id)?; + Ok(Selection::Position {buffer_id, pos: usize::min(pos+*param, buf.max_pos())}) + }, + monadic_rank1: |(param, es), buffer_id, int| { + let buf = get_buffer(es, buffer_id)?; + Ok(Selection::Position {buffer_id, pos: usize::min(int.end+*param, buf.max_pos())}) + } +} diff --git a/rprt-engine/src/selection_functions/function_empty.rs b/rprt-engine/src/selection_functions/function_empty.rs new file mode 100644 index 0000000..8290de3 --- /dev/null +++ b/rprt-engine/src/selection_functions/function_empty.rs @@ -0,0 +1,10 @@ +use crate::selection::Selection; +use crate::selection_functions::types::{SFArguments, SFResult}; + +pub fn empty_sequential(_: SFArguments) -> SFResult { + Ok(Selection::empty()) +} + +pub fn empy_structural(_: SFArguments) -> SFResult { + Ok(Selection::empty()) +} diff --git a/rprt-engine/src/selection_functions/function_end.rs b/rprt-engine/src/selection_functions/function_end.rs new file mode 100644 index 0000000..47cff79 --- /dev/null +++ b/rprt-engine/src/selection_functions/function_end.rs @@ -0,0 +1,37 @@ +use crate::selection::Selection; +use crate::selection_function; +use crate::selection_functions::types::{get_buffer, SFArguments, SFError, SFResult}; +use crate::state::EditorState; + +selection_function! { + name: end_sequential, + niladic: |es: &EditorState| { + let buf = get_buffer(es, es.current_buffer_id)?; + Ok(Selection::Position { + buffer_id: es.current_buffer_id, + pos: buf.max_pos() + }) + }, + monadic_rank0: |_, buffer_id, pos| { + Ok(Selection::Position { buffer_id, pos }) + }, + monadic_rank1: |_, buffer_id, interval| { + Ok(Selection::Position { + buffer_id, + pos: interval.end, + }) + } +} + +selection_function! { + name: end_structural, + niladic: |es: &EditorState| { + let buf = get_buffer(es, es.current_buffer_id)?; + Ok(Selection::Position { + buffer_id: es.current_buffer_id, + pos: buf.max_pos(), + }) + }, + monadic_rank0: |_, buffer_id, pos | Ok(Selection::Position { buffer_id, pos }), + monadic_rank1: |_, buffer_id, int | Ok(Selection::Position { buffer_id, pos: int.end }) +} diff --git a/rprt-engine/src/selection_functions/mod.rs b/rprt-engine/src/selection_functions/mod.rs new file mode 100644 index 0000000..3f64be4 --- /dev/null +++ b/rprt-engine/src/selection_functions/mod.rs @@ -0,0 +1,5 @@ +pub mod function_character; +pub mod function_empty; +pub mod function_end; +pub mod result_transformation; +pub mod types; diff --git a/rprt-engine/src/selection_functions/result_transformation.rs b/rprt-engine/src/selection_functions/result_transformation.rs new file mode 100644 index 0000000..89a071a --- /dev/null +++ b/rprt-engine/src/selection_functions/result_transformation.rs @@ -0,0 +1,77 @@ +use crate::buffer::BufferID; +use crate::selection::{Interval, Selection}; +use crate::selection_functions::types::{SFArguments, SFError, SFResult}; +use crate::state::EditorState; + +pub fn complement_transform(es: &EditorState, result: Selection, _: &SFArguments) -> SFResult { + fn complement_rank0( + es: &EditorState, + buffer_id: BufferID, + pos: usize, + ) -> Result { + 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 { + 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)) + } + } + + result.vectorise(es, complement_rank0, complement_rank1) +} + +pub fn conditional_transform( + _: &EditorState, + mut result: Selection, + arg: &SFArguments, +) -> SFResult { + if !result.is_empty() { + Ok(match arg { + // TODO: think about this niladic case? + SFArguments::Niladic { .. } => Selection::empty(), + SFArguments::Monadic { es: _, left } => left.clone(), + SFArguments::Dyadic { + es: _, + left, + right: _, + } => left.clone(), + }) + } else { + Ok(result) + } +} diff --git a/rprt-engine/src/selection_functions/types.rs b/rprt-engine/src/selection_functions/types.rs new file mode 100644 index 0000000..728d084 --- /dev/null +++ b/rprt-engine/src/selection_functions/types.rs @@ -0,0 +1,78 @@ +use crate::buffer::{Buffer, BufferID}; +use crate::selection::{Selection, VectoriseError}; +use crate::state::EditorState; +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum SFError { + #[error("Could not find buffer {0}")] + BufferNotFound(BufferID), + #[error("Function {0} has no dyadic form")] + NoDyadicForm(&'static str), +} + +pub enum SFArguments<'a> { + Niladic { + es: &'a EditorState, + }, + Monadic { + es: &'a EditorState, + left: Selection, + }, + Dyadic { + es: &'a EditorState, + left: Selection, + right: Selection, + }, +} + +pub type SFResult = Result>; + +#[macro_export] +macro_rules! selection_function { + ( + name: $name:ident, + niladic: $niladic_body:expr, + monadic_rank0: $monadic_rank0_body:expr, + monadic_rank1: $monadic_rank1_body:expr + ) => { + pub fn $name(arg: SFArguments) -> SFResult { + match arg { + SFArguments::Niladic { es } => $niladic_body(es), + SFArguments::Monadic { es, left } => { + left.vectorise(es, $monadic_rank0_body, $monadic_rank1_body) + } + SFArguments::Dyadic { .. } => Err(SFError::NoDyadicForm(stringify!($name)).into()), + } + } + }; +} + +#[macro_export] +macro_rules! selection_function_param { + ( + name: $name:ident, + param_type: $P:ty, + niladic: $niladic_body:expr, + monadic_rank0: $monadic_rank0_body:expr, + monadic_rank1: $monadic_rank1_body:expr + ) => { + pub fn $name(param: $P, arg: SFArguments) -> SFResult { + match arg { + SFArguments::Niladic { es } => $niladic_body((param, es)), + SFArguments::Monadic { es, left } => { + left.vectorise(&(param, es), $monadic_rank0_body, $monadic_rank1_body) + } + SFArguments::Dyadic { .. } => Err(SFError::NoDyadicForm(stringify!($name)).into()), + } + } + }; +} + +pub fn get_buffer(es: &EditorState, buffer_id: BufferID) -> Result<&Buffer, SFError> { + if let Some(buf) = es.get_buffer(buffer_id) { + Ok(buf) + } else { + Err(SFError::BufferNotFound(es.current_buffer_id)) + } +} -- cgit v1.2.3