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, }, DeleteBuffer { buffer: BufferID, }, } impl StateChange { pub fn invert(&self) -> Option { 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, buffer_to_file: HashMap>, history: Vec, 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, ) -> 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) { for change in changes { self.commit(change); } } } pub type EvaluationResult = (Selection, Vec);