diff options
Diffstat (limited to 'rprt-engine/src/state.rs')
| -rw-r--r-- | rprt-engine/src/state.rs | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/rprt-engine/src/state.rs b/rprt-engine/src/state.rs new file mode 100644 index 0000000..7964876 --- /dev/null +++ b/rprt-engine/src/state.rs @@ -0,0 +1,153 @@ +use crate::buffer::{Buffer, BufferID}; +use crate::selection::Selection; +use std::collections::HashMap; +use std::path::PathBuf; + +#[derive(Debug, Clone)] +pub enum StateChange { + SetCurrentSelection { + old_selection: Selection, + new_selection: Selection, + }, + SetCurrentBuffer { + old_buffer: BufferID, + new_buffer: BufferID, + }, + ModifyBuffer { + buffer: BufferID, + old_start: usize, + old_end: usize, + old_content: String, + new_content: String, + }, + CreateBuffer { + buffer: BufferID, + file: Option<PathBuf>, + }, + DeleteBuffer { + buffer: BufferID, + }, +} + +impl StateChange { + pub fn invert(&self) -> Option<Self> { + match self { + StateChange::SetCurrentSelection { + old_selection, + new_selection, + } => Some(StateChange::SetCurrentSelection { + old_selection: new_selection.clone(), + new_selection: old_selection.clone(), + }), + StateChange::SetCurrentBuffer { + old_buffer, + new_buffer, + } => Some(StateChange::SetCurrentBuffer { + old_buffer: *new_buffer, + new_buffer: *old_buffer, + }), + StateChange::ModifyBuffer { .. } => None, // TODO: implement, irritating coordinate stuff + // TODO: Not supported? + StateChange::CreateBuffer { .. } => None, + StateChange::DeleteBuffer { .. } => None, + } + } +} + +#[derive(Debug)] +pub struct EditorState { + current_buffer: BufferID, + current_selection: Selection, + buffers: HashMap<BufferID, Buffer>, + buffer_to_file: HashMap<BufferID, Option<PathBuf>>, + history: Vec<StateChange>, + next_buffer_id: BufferID, +} + +impl EditorState { + pub fn new() -> Self { + Self { + current_buffer: 0, + current_selection: Selection::empty(), + buffers: HashMap::new(), + buffer_to_file: HashMap::new(), + history: Vec::new(), + next_buffer_id: 0, + } + } + + pub fn create_buffer( + &mut self, + name: String, + content: String, + file: Option<PathBuf>, + ) -> BufferID { + let buffer_id = self.next_buffer_id; + self.next_buffer_id += 1; + + let buffer = Buffer::new(name, content); + self.buffers.insert(buffer_id, buffer); + self.buffer_to_file.insert(buffer_id, file.clone()); + + self.history.push(StateChange::CreateBuffer { + buffer: buffer_id, + file, + }); + + buffer_id + } + + pub fn get_buffer(&self, buffer_id: BufferID) -> Option<&Buffer> { + self.buffers.get(&buffer_id) + } + + pub fn get_buffer_mut(&mut self, buffer_id: BufferID) -> Option<&mut Buffer> { + self.buffers.get_mut(&buffer_id) + } + + pub fn commit(&mut self, change: StateChange) { + match &change { + StateChange::SetCurrentSelection { new_selection, .. } => { + self.current_selection = new_selection.clone(); + } + StateChange::SetCurrentBuffer { new_buffer, .. } => { + self.current_buffer = *new_buffer; + } + StateChange::ModifyBuffer { + buffer, + old_start, + old_end, + new_content, + .. + } => { + if let Some(buf) = self.buffers.get_mut(buffer) { + buf.content = format!( + "{}{}{}", + &buf.content[..*old_start], + new_content, + &buf.content[*old_end..] + ); + } + } + StateChange::CreateBuffer { buffer, file } => { + // TODO: do we want this? + if !self.buffer_to_file.contains_key(buffer) { + self.buffer_to_file.insert(*buffer, file.clone()); + } + } + StateChange::DeleteBuffer { buffer } => { + self.buffers.remove(buffer); + self.buffer_to_file.remove(buffer); + } + } + self.history.push(change); + } + + pub fn commit_changes(&mut self, changes: Vec<StateChange>) { + for change in changes { + self.commit(change); + } + } +} + +pub type EvaluationResult = (Selection, Vec<StateChange>); |
