aboutsummaryrefslogtreecommitdiff
path: root/rprt-engine/src/state.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rprt-engine/src/state.rs')
-rw-r--r--rprt-engine/src/state.rs153
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>);