diff --git a/src/action.rs b/src/action.rs index aacb7ee..fcc61f0 100644 --- a/src/action.rs +++ b/src/action.rs @@ -1,6 +1,6 @@ use std::{cmp::min, mem::swap}; -use crate::{BYTES_PER_LINE, app::{App, Mode, PartialAction}}; +use crate::{BYTES_PER_LINE, app::{App, Mode, PartialAction}, edit_action::EditAction}; #[derive(Clone, Copy)] pub enum Action { @@ -40,6 +40,8 @@ pub enum Action { ExtendLineBelow, ExtendLineAbove, + + Delete, } impl App { @@ -81,6 +83,8 @@ impl App { Action::ExtendLineBelow => self.extend_line_below(), Action::ExtendLineAbove => self.extend_line_above(), + + Action::Delete => self.delete(), } } @@ -273,6 +277,15 @@ impl App { self.cursor.tail += BYTES_PER_LINE - 1 - (self.cursor.tail % BYTES_PER_LINE); } } + + fn delete(&mut self) { + self.execute_and_add( + EditAction::Delete { + cursor: self.cursor, + data: self.contents[self.cursor.range()].into() + } + ); + } } // helpers diff --git a/src/app/mod.rs b/src/app/mod.rs index c8e2e1c..7e07759 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -1,21 +1,29 @@ use std::{env, fs::File, io::Read, path::PathBuf, process::exit}; use crossterm::{event::{self, Event, KeyEvent}, terminal::window_size}; use ratatui::style::Color; - -use crate::{config::Config, cursor::Cursor}; +use crate::{config::Config, cursor::Cursor, edit_action::EditAction}; mod widget; pub struct App { pub config: Config, pub file_name: String, + pub contents: Vec, + pub window_rows: usize, + pub scroll_position: usize, pub cursor: Cursor, + pub should_quit: bool, + pub mode: Mode, pub partial_action: Option, + + pub edit_history: Vec, + // some index to keep track of where we are? edit_prophecy? + pub logs: Vec, } @@ -77,14 +85,22 @@ impl App { Self { config: Config::default(), file_name: file_path.file_name().unwrap().to_str().unwrap().to_owned(), + contents, + // -1 because of the status line window_rows: window_size().unwrap().rows as usize - 1, + scroll_position: 0, cursor: Cursor::default(), + should_quit: false, + mode: Mode::Normal, partial_action: None, + + edit_history: Vec::new(), + logs: Vec::new(), } } diff --git a/src/app/widget.rs b/src/app/widget.rs index 9bcbb98..bc801ff 100644 --- a/src/app/widget.rs +++ b/src/app/widget.rs @@ -361,7 +361,8 @@ mod status_line { Line::from_iter([ self.render_mode(), " ".into(), - self.render_file_name() + self.render_file_name(), + self.modified_indicator() ]) ) .bg(Color::ui_grey()) @@ -376,6 +377,14 @@ mod status_line { fn render_file_name(&self) -> Span<'_> { Span::from(&self.file_name) } + + fn modified_indicator(&self) -> Span<'static> { + if self.edit_history.is_empty() { + "".into() + } else { + " [+]".into() + } + } } } diff --git a/src/config.rs b/src/config.rs index 8bb351a..f98a622 100644 --- a/src/config.rs +++ b/src/config.rs @@ -131,6 +131,8 @@ impl Default for Config { ("x".try_into().unwrap(), Action::ExtendLineBelow), ("X".try_into().unwrap(), Action::ExtendLineAbove), + + ("d".try_into().unwrap(), Action::Delete), ].into()), (Some(PartialAction::Goto), [ ("j".try_into().unwrap(), Action::GotoLineStart), @@ -171,6 +173,8 @@ impl Default for Config { ("x".try_into().unwrap(), Action::ExtendLineBelow), ("X".try_into().unwrap(), Action::ExtendLineAbove), + + ("d".try_into().unwrap(), Action::Delete), ].into()) ].into()) ].into() diff --git a/src/cursor.rs b/src/cursor.rs index bda4be7..1fb9fca 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -1,4 +1,6 @@ -#[derive(Debug, Default, PartialEq, Eq)] +use std::ops::RangeInclusive; + +#[derive(Clone, Copy, Default, PartialEq, Eq)] pub struct Cursor { pub head: usize, pub tail: usize @@ -39,6 +41,14 @@ impl Cursor { self.tail = self.tail.clamp(scroll_position, max_row); } + pub const fn range(&self) -> RangeInclusive { + if self.head < self.tail { + self.head..=self.tail + } else { + self.tail..=self.head + } + } + pub fn move_to_next_word(&mut self, max: usize) { if self.head == max { return } diff --git a/src/edit_action.rs b/src/edit_action.rs new file mode 100644 index 0000000..c402b6e --- /dev/null +++ b/src/edit_action.rs @@ -0,0 +1,29 @@ +use std::cmp::min; +use crate::{app::App, cursor::Cursor}; + +pub enum EditAction { + Delete { + cursor: Cursor, + data: Vec + } +} + +impl App { + pub fn execute_and_add(&mut self, edit_action: EditAction) { + self.execute_edit(&edit_action); + self.edit_history.push(edit_action); + } + + fn execute_edit(&mut self, edit_action: &EditAction) { + match edit_action { + EditAction::Delete { cursor, .. } => self.delete_at(*cursor), + } + } + + fn delete_at(&mut self, cursor: Cursor) { + self.contents.drain(cursor.range()); + + self.cursor.head = min(cursor.head, cursor.tail); + self.cursor.collapse(); + } +} diff --git a/src/main.rs b/src/main.rs index 5072bc6..189d7ec 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,6 +10,7 @@ mod app; mod config; mod cursor; mod action; +mod edit_action; const BYTES_PER_LINE: usize = 0x10; const BYTES_PER_CHUNK: usize = 4;