use crate::{ selection::{Selection, SelectionError}, state::{EditorState, EvaluationResult, GroupedChangeError}, }; pub enum EvaluationStrategy { Sequential, Grouped, } #[derive(Debug)] pub enum EvaluationError { Selection(SelectionError), GroupedChange(GroupedChangeError), } impl From for EvaluationError { fn from(err: SelectionError) -> Self { EvaluationError::Selection(err) } } impl From for EvaluationError { fn from(err: GroupedChangeError) -> Self { EvaluationError::GroupedChange(err) } } pub struct EditorStateMonad { func: Box EvaluationResult>, } impl EditorStateMonad { pub fn new(f: impl Fn(&EditorState) -> EvaluationResult + 'static) -> Self { Self { func: Box::new(f) } } pub fn run(&self, state: &EditorState) -> EvaluationResult { (self.func)(state) } pub fn run_with_strategy( monads: Vec, strategy: EvaluationStrategy, state: &mut EditorState, ) -> Result { match strategy { EvaluationStrategy::Sequential => { let mut last_selection = Selection::empty(); for monad in monads { let (sel, state_changes) = monad.run(state); state.commit_changes(state_changes); last_selection = sel; } Ok(last_selection) } EvaluationStrategy::Grouped => { let mut arms = Vec::new(); let mut all_selections = Vec::new(); for monad in monads { let (sel, state_changes) = monad.run(state); all_selections.push(sel); arms.push(state_changes); } state.commit_changes_grouped(arms)?; Ok(Selection::union(all_selections)?) } } } }