diff --git a/src/im_gonna_try_better.rs b/src/im_gonna_try_better.rs deleted file mode 100644 index 500c956..0000000 --- a/src/im_gonna_try_better.rs +++ /dev/null @@ -1,277 +0,0 @@ -use std::{ - env::{self}, - fs, io, - path::PathBuf, -}; - -use crossterm::event::{self, Event, KeyCode, KeyEvent, KeyEventKind}; -use ratatui::{ - DefaultTerminal, Frame, - buffer::Buffer, - layout::{Constraint, Direction, Layout, Rect}, - style::{Color, Stylize}, - widgets::{Block, Borders, List, ListState, Padding, StatefulWidget}, -}; - -type E = std::io::Error; - -struct App<'a> { - window: Window<'a>, - preview: Preview<'a>, - exit: bool, -} - -impl App<'_> { - fn run(&mut self, terminal: &mut DefaultTerminal) -> io::Result<()> { - while !self.exit { - terminal.draw(|frame| self.draw(frame))?; - self.handle_events()?; - } - Ok(()) - } - - fn draw(&mut self, frame: &mut Frame) { - let main_area = Layout::default() - .direction(Direction::Horizontal) - .constraints(vec![Constraint::Percentage(50), Constraint::Percentage(50)]) - .split(frame.area()); - self.window.render(main_area[0], frame.buffer_mut()); - self.preview.render(main_area[1], frame.buffer_mut()); - } - - fn handle_events(&mut self) -> io::Result<()> { - match event::read()? { - Event::Key(key_event) if key_event.kind == KeyEventKind::Press => { - self.handle_key_events(key_event) - } - - _ => {} - }; - Ok(()) - } - - fn handle_key_events(&mut self, key_event: KeyEvent) { - match key_event.code { - KeyCode::Char('q') | KeyCode::Esc => self.exit(), - KeyCode::Down => { - self.window.state.select_next(); - self.preview.the_final_stretch(); - } - KeyCode::Up => { - self.window.state.select_previous(); - self.preview.the_final_stretch(); - } - KeyCode::Left => { - if &self.window.absolute_path != "/" { - self.preview.absolute_path = self.window.absolute_path.clone(); - } - self.window.absolute_path.pop(); - self.window.update(); - self.preview.state = self.window.state; - self.preview.muhehe(); - } - KeyCode::Right => { - if let Some(val) = self.window.state.selected() { - let current_dir = self - .window - .prepare_updated_list() - .expect("You should always be in a valid directory"); - - self.window.absolute_path.push(current_dir[val].clone()); - let output = self.window.update(); - if !output { - self.window.absolute_path.pop(); - } - } - } - _ => {} - } - } - - fn exit(&mut self) { - self.exit = true; - } -} - -struct Window<'a> { - widget: WindowWidget<'a>, - absolute_path: PathBuf, - state: ListState, -} - -impl Window<'_> { - fn new(absolute_path: PathBuf) -> Result { - Ok(Window { - widget: WindowWidget::new(Self::prepare_list(&absolute_path)?), - absolute_path, - state: ListState::default().with_selected(Some(0)), - }) - } - - fn render(&mut self, area: Rect, buf: &mut Buffer) { - self.widget.render(area, buf, &mut self.state); - } - - fn prepare_list(absolute_path: &PathBuf) -> Result, E> { - let entries = fs::read_dir(absolute_path)?; - let mut prepared_list = Vec::::new(); - - for item in entries { - match item { - Ok(entry) => { - let path_string = entry.path().display().to_string(); - prepared_list.push(path_string); - } - Err(err) => return Err(err), - } - } - - Ok(prepared_list) - } - - fn prepare_updated_list(&self) -> Result, E> { - Self::prepare_list(&self.absolute_path) - } - - fn update(&mut self) -> bool { - let values = self.prepare_updated_list(); - - if let Ok(val) = values { - self.widget.update(val); - self.state.select_first(); - return true; - } - - false - } -} - -struct WindowWidget<'a> { - list: List<'a>, -} - -impl WindowWidget<'_> { - fn update(&mut self, prepared_list: Vec) { - let block = Block::new() - .borders(Borders::ALL) - .padding(Padding::symmetric(1, 1)) - .fg(Color::Blue); - - self.list = List::new(prepared_list) - .block(block) - .highlight_style(Color::Cyan); - } - - fn new(prepared_list: Vec) -> Self { - let mut window_widget = WindowWidget { - list: List::new(Vec::::new()), - }; - - window_widget.update(prepared_list); - window_widget - } -} - -impl StatefulWidget for &mut WindowWidget<'_> { - type State = ListState; - - fn render(self, area: Rect, buf: &mut Buffer, state: &mut ListState) { - StatefulWidget::render(&self.list, area, buf, state); - } -} - -struct Preview<'a> { - widget: PreviewWidget<'a>, - absolute_path: PathBuf, - state: ListState, -} - -impl Preview<'_> { - fn the_final_stretch(&mut self) { - self.absolute_path.push( - Self::prepare_list(&self.absolute_path).unwrap()[self.state.selected().unwrap()] - .clone(), - ); - - self.widget - .update(Self::prepare_list(&self.absolute_path).unwrap()); - } - - fn muhehe(&mut self) { - self.widget - .update(Self::prepare_list(&self.absolute_path).unwrap()); - } - - fn prepare_list(absolute_path: &PathBuf) -> Result, E> { - let entries = fs::read_dir(absolute_path)?; - let mut prepared_list = Vec::::new(); - - for item in entries { - match item { - Ok(entry) => { - let path_string = entry.path().display().to_string(); - prepared_list.push(path_string); - } - Err(err) => return Err(err), - } - } - - Ok(prepared_list) - } - - fn render(&mut self, area: Rect, buf: &mut Buffer) { - self.widget.render(area, buf, &mut ListState::default()); - } -} - -struct PreviewWidget<'a> { - list: List<'a>, -} - -impl PreviewWidget<'_> { - fn update(&mut self, prepared_list: Vec) { - let block = Block::new() - .borders(Borders::ALL) - .padding(Padding::symmetric(1, 1)) - .fg(Color::Blue); - - self.list = List::new(prepared_list) - .block(block) - .highlight_style(Color::Cyan); - } - - fn new(prepared_list: Vec) -> Self { - let mut preview_widget = PreviewWidget { - list: List::new(Vec::::new()), - }; - - preview_widget.update(prepared_list); - preview_widget - } -} - -impl StatefulWidget for &mut PreviewWidget<'_> { - type State = ListState; - - fn render(self, area: Rect, buf: &mut Buffer, state: &mut ListState) { - StatefulWidget::render(&self.list, area, buf, state); - } -} - -fn main() -> io::Result<()> { - let mut terminal = ratatui::init(); - let dir = Window::new(env::current_dir()?)?; - let view = env::current_dir()?; - let app_result = App { - window: dir, - preview: Preview { - widget: PreviewWidget::new(Preview::prepare_list(&view).unwrap()), - absolute_path: view, - state: ListState::default(), - }, - exit: false, - } - .run(&mut terminal); - ratatui::restore(); - app_result -} diff --git a/src/main.rs b/src/main.rs index e3cd70a..385f2d0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,8 @@ -use std::{env, fs, io, path::PathBuf}; +use std::{ + env, fs, + io::{self, ErrorKind}, + path::PathBuf, +}; use crossterm::event::{self, Event, KeyCode, KeyEvent, KeyEventKind}; use ratatui::{ @@ -183,12 +187,26 @@ impl Preview<'_> { } fn see(&mut self, window: &Window) { - let a = Window::prepare_list(&window.absolute_path).unwrap(); - - self.widget.update( - Window::prepare_list(&PathBuf::from(a[window.state.selected().unwrap()].clone())) - .unwrap(), - ); + match Window::prepare_list(&window.absolute_path) { + Ok(prepared_list) => { + if let Some(state) = window.state.selected() + && state < prepared_list.len() + { + match Window::prepare_list(&PathBuf::from(&prepared_list[state])) { + Ok(everything_went_well) => { + self.widget.update(everything_went_well); + } + Err(err) => match err.kind() { + ErrorKind::NotADirectory => self.widget.not_a_dir(), + ErrorKind::PermissionDenied => self.widget.permission_denied(), + ErrorKind::NotFound => {} + _ => panic!("It's a different kind of error:\n{err:?}"), + }, + } + } + } + Err(_err) => {} + } } } @@ -216,6 +234,26 @@ impl PreviewWidget<'_> { preview_widget.update(prepared_list); preview_widget } + + fn not_a_dir(&mut self) { + let block = Block::new() + .borders(Borders::ALL) + .padding(Padding::symmetric(1, 1)) + .fg(Color::Blue); + + self.list = List::default().block(block) + } + + fn permission_denied(&mut self) { + let block = Block::new() + .borders(Borders::ALL) + .padding(Padding::symmetric(1, 1)) + .fg(Color::Blue); + + self.list = List::new(vec!["permission denied"]) + .block(block) + .style(Color::Red) + } } impl StatefulWidget for &mut PreviewWidget<'_> {