This commit is contained in:
alice pellerin
2026-03-18 04:05:43 -05:00
parent 98f4c56852
commit 11075723d8
7 changed files with 87 additions and 5 deletions
+14 -1
View File
@@ -1,6 +1,6 @@
use std::{cmp::min, mem::swap}; 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)] #[derive(Clone, Copy)]
pub enum Action { pub enum Action {
@@ -40,6 +40,8 @@ pub enum Action {
ExtendLineBelow, ExtendLineBelow,
ExtendLineAbove, ExtendLineAbove,
Delete,
} }
impl App { impl App {
@@ -81,6 +83,8 @@ impl App {
Action::ExtendLineBelow => self.extend_line_below(), Action::ExtendLineBelow => self.extend_line_below(),
Action::ExtendLineAbove => self.extend_line_above(), 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); 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 // helpers
+18 -2
View File
@@ -1,21 +1,29 @@
use std::{env, fs::File, io::Read, path::PathBuf, process::exit}; use std::{env, fs::File, io::Read, path::PathBuf, process::exit};
use crossterm::{event::{self, Event, KeyEvent}, terminal::window_size}; use crossterm::{event::{self, Event, KeyEvent}, terminal::window_size};
use ratatui::style::Color; use ratatui::style::Color;
use crate::{config::Config, cursor::Cursor, edit_action::EditAction};
use crate::{config::Config, cursor::Cursor};
mod widget; mod widget;
pub struct App { pub struct App {
pub config: Config, pub config: Config,
pub file_name: String, pub file_name: String,
pub contents: Vec<u8>, pub contents: Vec<u8>,
pub window_rows: usize, pub window_rows: usize,
pub scroll_position: usize, pub scroll_position: usize,
pub cursor: Cursor, pub cursor: Cursor,
pub should_quit: bool, pub should_quit: bool,
pub mode: Mode, pub mode: Mode,
pub partial_action: Option<PartialAction>, pub partial_action: Option<PartialAction>,
pub edit_history: Vec<EditAction>,
// some index to keep track of where we are? edit_prophecy?
pub logs: Vec<String>, pub logs: Vec<String>,
} }
@@ -77,14 +85,22 @@ impl App {
Self { Self {
config: Config::default(), config: Config::default(),
file_name: file_path.file_name().unwrap().to_str().unwrap().to_owned(), file_name: file_path.file_name().unwrap().to_str().unwrap().to_owned(),
contents, contents,
// -1 because of the status line // -1 because of the status line
window_rows: window_size().unwrap().rows as usize - 1, window_rows: window_size().unwrap().rows as usize - 1,
scroll_position: 0, scroll_position: 0,
cursor: Cursor::default(), cursor: Cursor::default(),
should_quit: false, should_quit: false,
mode: Mode::Normal, mode: Mode::Normal,
partial_action: None, partial_action: None,
edit_history: Vec::new(),
logs: Vec::new(), logs: Vec::new(),
} }
} }
+10 -1
View File
@@ -361,7 +361,8 @@ mod status_line {
Line::from_iter([ Line::from_iter([
self.render_mode(), self.render_mode(),
" ".into(), " ".into(),
self.render_file_name() self.render_file_name(),
self.modified_indicator()
]) ])
) )
.bg(Color::ui_grey()) .bg(Color::ui_grey())
@@ -376,6 +377,14 @@ mod status_line {
fn render_file_name(&self) -> Span<'_> { fn render_file_name(&self) -> Span<'_> {
Span::from(&self.file_name) Span::from(&self.file_name)
} }
fn modified_indicator(&self) -> Span<'static> {
if self.edit_history.is_empty() {
"".into()
} else {
" [+]".into()
}
}
} }
} }
+4
View File
@@ -131,6 +131,8 @@ impl Default for Config {
("x".try_into().unwrap(), Action::ExtendLineBelow), ("x".try_into().unwrap(), Action::ExtendLineBelow),
("X".try_into().unwrap(), Action::ExtendLineAbove), ("X".try_into().unwrap(), Action::ExtendLineAbove),
("d".try_into().unwrap(), Action::Delete),
].into()), ].into()),
(Some(PartialAction::Goto), [ (Some(PartialAction::Goto), [
("j".try_into().unwrap(), Action::GotoLineStart), ("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::ExtendLineBelow),
("X".try_into().unwrap(), Action::ExtendLineAbove), ("X".try_into().unwrap(), Action::ExtendLineAbove),
("d".try_into().unwrap(), Action::Delete),
].into()) ].into())
].into()) ].into())
].into() ].into()
+11 -1
View File
@@ -1,4 +1,6 @@
#[derive(Debug, Default, PartialEq, Eq)] use std::ops::RangeInclusive;
#[derive(Clone, Copy, Default, PartialEq, Eq)]
pub struct Cursor { pub struct Cursor {
pub head: usize, pub head: usize,
pub tail: usize pub tail: usize
@@ -39,6 +41,14 @@ impl Cursor {
self.tail = self.tail.clamp(scroll_position, max_row); self.tail = self.tail.clamp(scroll_position, max_row);
} }
pub const fn range(&self) -> RangeInclusive<usize> {
if self.head < self.tail {
self.head..=self.tail
} else {
self.tail..=self.head
}
}
pub fn move_to_next_word(&mut self, max: usize) { pub fn move_to_next_word(&mut self, max: usize) {
if self.head == max { return } if self.head == max { return }
+29
View File
@@ -0,0 +1,29 @@
use std::cmp::min;
use crate::{app::App, cursor::Cursor};
pub enum EditAction {
Delete {
cursor: Cursor,
data: Vec<u8>
}
}
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();
}
}
+1
View File
@@ -10,6 +10,7 @@ mod app;
mod config; mod config;
mod cursor; mod cursor;
mod action; mod action;
mod edit_action;
const BYTES_PER_LINE: usize = 0x10; const BYTES_PER_LINE: usize = 0x10;
const BYTES_PER_CHUNK: usize = 4; const BYTES_PER_CHUNK: usize = 4;