116 lines
2.3 KiB
Rust
116 lines
2.3 KiB
Rust
use std::{env, process::exit};
|
|
use crossterm::{event::{self, Event, KeyEvent}, terminal::window_size};
|
|
use ratatui::{style::Stylize, text::Span};
|
|
use crate::{BYTES_PER_LINE, action::AppAction, buffer::Buffer, config::Config};
|
|
|
|
mod widget;
|
|
|
|
pub struct App {
|
|
pub config: Config,
|
|
|
|
pub buffers: Vec<Buffer>,
|
|
pub current_buffer_index: usize,
|
|
|
|
pub window_size: WindowSize,
|
|
|
|
pub should_quit: bool,
|
|
|
|
pub logs: Vec<String>,
|
|
}
|
|
|
|
#[derive(Clone, Copy)]
|
|
pub struct WindowSize {
|
|
pub rows: usize,
|
|
pub covered_rows: usize,
|
|
}
|
|
|
|
impl App {
|
|
pub fn new() -> Self {
|
|
let buffers: Vec<Buffer> = env::args()
|
|
.skip(1)
|
|
.map(Into::into)
|
|
.map(Buffer::new)
|
|
.collect();
|
|
|
|
if buffers.is_empty() {
|
|
println!("please provide at least one file as input");
|
|
exit(1);
|
|
}
|
|
|
|
Self {
|
|
config: Config::default(),
|
|
|
|
buffers,
|
|
current_buffer_index: 0,
|
|
|
|
window_size: WindowSize {
|
|
rows: window_size().unwrap().rows as usize,
|
|
// 1 because of the status line
|
|
covered_rows: 1,
|
|
},
|
|
|
|
should_quit: false,
|
|
|
|
logs: Vec::new(),
|
|
}
|
|
}
|
|
|
|
#[allow(clippy::too_many_lines)]
|
|
pub fn handle_events(&mut self) {
|
|
#[allow(clippy::collapsible_match)]
|
|
match event::read().unwrap() {
|
|
Event::Resize(_, height) => {
|
|
self.window_size.rows = height as usize;
|
|
}
|
|
Event::Key(key_event) => self.handle_key(key_event),
|
|
// Event::Mouse(mouse_event) => {
|
|
// mouse_event.kind
|
|
// },
|
|
_ => {}
|
|
}
|
|
}
|
|
|
|
fn handle_key(&mut self, key_event: KeyEvent) {
|
|
let maybe_app_action = self.buffers[self.current_buffer_index].handle_key(
|
|
key_event,
|
|
&self.config,
|
|
self.window_size
|
|
);
|
|
|
|
if let Some(app_action) = maybe_app_action {
|
|
match app_action {
|
|
AppAction::QuitIfSaved => self.quit_if_saved(),
|
|
AppAction::Quit => self.quit(),
|
|
}
|
|
}
|
|
}
|
|
|
|
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]
|
|
}
|
|
}
|
|
|
|
impl WindowSize {
|
|
pub const fn visible_byte_count(&self) -> usize {
|
|
self.hex_rows() * BYTES_PER_LINE
|
|
}
|
|
|
|
pub const fn hex_rows(&self) -> usize {
|
|
self.rows - self.covered_rows
|
|
}
|
|
}
|