diff --git a/src/action.rs b/src/action.rs index 3616322..b4f0c81 100644 --- a/src/action.rs +++ b/src/action.rs @@ -1,11 +1,10 @@ use std::{cmp::min, fs::File, io::Write, mem::{replace, swap}}; -use ratatui::{style::Stylize, text::Span}; use crate::{BYTES_PER_LINE, app::WindowSize, buffer::{Buffer, Mode, PartialAction}, edit_action::EditAction}; #[derive(Clone, Copy)] pub enum Action { - CloseIfSaved, - Close, + QuitIfSaved, + Quit, NormalMode, SelectMode, @@ -60,11 +59,17 @@ pub enum Action { Save, } +// actions that act on the app as a whole, not just one buffer +pub enum AppAction { + QuitIfSaved, + Quit, +} + impl Buffer { - pub fn execute(&mut self, action: Action, window_size: WindowSize) { + pub fn execute(&mut self, action: Action, window_size: WindowSize) -> Option { match action { - Action::CloseIfSaved => self.close_if_saved(), - Action::Close => self.close(), + Action::QuitIfSaved => return Some(AppAction::QuitIfSaved), + Action::Quit => return Some(AppAction::Quit), Action::NormalMode => self.normal_mode(), Action::SelectMode => self.select_mode(), @@ -118,20 +123,8 @@ impl Buffer { Action::Save => self.save(), } - } - - fn close_if_saved(&mut self) { - if self.all_changes_saved() { - self.close(); - } else { - self.alert_message = Span::from( - "there are unsaved changes, use Q to override" - ).red(); - } - } - - const fn close(&mut self) { - self.should_close = true; + + None } const fn normal_mode(&mut self) { diff --git a/src/app/mod.rs b/src/app/mod.rs index cb41a4b..0c23eac 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -1,6 +1,7 @@ -use std::{cmp::min, env, process::exit}; +use std::{env, process::exit}; use crossterm::{event::{self, Event, KeyEvent}, terminal::window_size}; -use crate::{BYTES_PER_LINE, buffer::Buffer, config::Config}; +use ratatui::{style::Stylize, text::Span}; +use crate::{BYTES_PER_LINE, action::AppAction, buffer::Buffer, config::Config}; mod widget; @@ -70,24 +71,35 @@ impl App { } fn handle_key(&mut self, key_event: KeyEvent) { - self.buffers[self.current_buffer_index] - .handle_key(key_event, &self.config, self.window_size); + let maybe_app_action = self.buffers[self.current_buffer_index].handle_key( + key_event, + &self.config, + self.window_size + ); - if self.current_buffer().should_close { - self.buffers.remove(self.current_buffer_index); - - if self.buffers.is_empty() { - self.should_quit = true; - } else { - self.current_buffer_index = min( - self.current_buffer_index, - self.buffers.len() - 1 - ); + if let Some(app_action) = maybe_app_action { + match app_action { + AppAction::QuitIfSaved => self.quit_if_saved(), + AppAction::Quit => self.quit(), } } } - fn current_buffer(&self) -> &Buffer { + fn quit_if_saved(&mut self) { + if self.buffers.iter().all(Buffer::all_changes_saved) { + self.quit(); + } else { + self.buffers[self.current_buffer_index].alert_message = Span::from( + "there are unsaved changes, use Q to override" + ).red(); + } + } + + const fn quit(&mut self) { + self.should_quit = true; + } + + pub fn current_buffer(&self) -> &Buffer { &self.buffers[self.current_buffer_index] } } diff --git a/src/app/widget.rs b/src/app/widget.rs index 8a54e74..0ed95df 100644 --- a/src/app/widget.rs +++ b/src/app/widget.rs @@ -20,18 +20,18 @@ impl App { self.buffers .iter() .enumerate() - .map(|(index, buffer)| self.tab_for(buffer, index == self.current_buffer_index)) + .map(|(index, buffer)| tab_for(buffer, index == self.current_buffer_index)) .collect() } - - fn tab_for(&self, buffer: &Buffer, is_active: bool) -> Span<'static> { - let background = if is_active { - Color::select_grey() - } else { - Color::ui_grey() - }; - - Span::from(format!(" {} ", buffer.file_name)) - .bg(background) - } +} + +fn tab_for(buffer: &Buffer, is_active: bool) -> Span<'static> { + let background = if is_active { + Color::select_grey() + } else { + Color::ui_grey() + }; + + Span::from(format!(" {} ", buffer.file_name)) + .bg(background) } diff --git a/src/buffer/mod.rs b/src/buffer/mod.rs index b47f2a9..1cb6004 100644 --- a/src/buffer/mod.rs +++ b/src/buffer/mod.rs @@ -1,7 +1,7 @@ use std::{fs::File, io::Read, path::PathBuf}; use crossterm::event::KeyEvent; use ratatui::{style::Color, text::Span}; -use crate::{app::WindowSize, config::Config, cursor::Cursor, edit_action::EditAction}; +use crate::{action::AppAction, app::WindowSize, config::Config, cursor::Cursor, edit_action::EditAction}; mod widget; @@ -25,8 +25,6 @@ pub struct Buffer { pub time_traveling: Option, // the index *after* the last saved edit action pub last_saved_at: Option, - - pub should_close: bool, } #[derive(Clone, Copy, Hash, PartialEq, Eq)] @@ -92,8 +90,6 @@ impl Buffer { edit_history: Vec::new(), time_traveling: None, last_saved_at: Some(0), - - should_close: false, } } @@ -102,9 +98,11 @@ impl Buffer { event: KeyEvent, config: &Config, window_size: WindowSize - ) { + ) -> Option { self.alert_message = "".into(); + let mut app_action = None; + if self.partial_action == Some(PartialAction::Replace) { if let Some(hex_character) = event.code.as_char() && let Some(nybble) = nybble_from_hex(hex_character) @@ -132,13 +130,15 @@ impl Buffer { let Some(keybinds) = mode_config.0.get(&self.partial_action) && let Some(action) = keybinds.0.get(&event.into()) { - self.execute(*action, window_size); + app_action = self.execute(*action, window_size); } if should_reset_partial { self.partial_action = None; } } + + app_action } pub const fn has_unsaved_changes(&self) -> bool { diff --git a/src/config.rs b/src/config.rs index 5bf5ad8..45b06c0 100644 --- a/src/config.rs +++ b/src/config.rs @@ -99,8 +99,8 @@ impl Default for Config { [ (Mode::Normal, [ (None, [ - ("q".try_into().unwrap(), Action::CloseIfSaved), - ("Q".try_into().unwrap(), Action::Close), + ("q".try_into().unwrap(), Action::QuitIfSaved), + ("Q".try_into().unwrap(), Action::Quit), ("v".try_into().unwrap(), Action::SelectMode), @@ -151,8 +151,8 @@ impl Default for Config { ].into()), (Mode::Select, [ (None, [ - ("q".try_into().unwrap(), Action::CloseIfSaved), - ("Q".try_into().unwrap(), Action::Close), + ("q".try_into().unwrap(), Action::QuitIfSaved), + ("Q".try_into().unwrap(), Action::Quit), ("v".try_into().unwrap(), Action::NormalMode),