diff options
| -rw-r--r-- | Cargo.lock | 122 | ||||
| -rw-r--r-- | Cargo.toml | 1 | ||||
| -rw-r--r-- | src/frontend/app.rs | 82 | ||||
| -rw-r--r-- | src/frontend/event.rs | 17 | ||||
| -rw-r--r-- | src/frontend/handler.rs | 5 | ||||
| -rw-r--r-- | src/frontend/tui.rs | 37 | ||||
| -rw-r--r-- | src/main.rs | 31 |
7 files changed, 236 insertions, 59 deletions
@@ -96,6 +96,7 @@ version = "0.1.0" dependencies = [ "arboard", "biblatex", + "color-eyre", "crossterm", "futures", "itertools", @@ -198,6 +199,33 @@ dependencies = [ ] [[package]] +name = "color-eyre" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55146f5e46f237f7423d74111267d4597b59b0dad0ffaf7303bce9945d843ad5" +dependencies = [ + "backtrace", + "color-spantrace", + "eyre", + "indenter", + "once_cell", + "owo-colors", + "tracing-error", +] + +[[package]] +name = "color-spantrace" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd6be1b2a7e382e2b98b43b2adcca6bb0e465af0bdd38123873ae61eb17a72c2" +dependencies = [ + "once_cell", + "owo-colors", + "tracing-core", + "tracing-error", +] + +[[package]] name = "compact_str" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -341,6 +369,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a5d9305ccc6942a704f4335694ecd3de2ea531b114ac2d51f5f843750787a92f" [[package]] +name = "eyre" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" +dependencies = [ + "indenter", + "once_cell", +] + +[[package]] name = "fastrand" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -554,6 +592,12 @@ dependencies = [ ] [[package]] +name = "indenter" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" + +[[package]] name = "indexmap" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -595,6 +639,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" [[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] name = "libc" version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -867,6 +917,12 @@ dependencies = [ ] [[package]] +name = "owo-colors" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" + +[[package]] name = "parking_lot" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1072,6 +1128,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] name = "signal-hook" version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1216,6 +1281,16 @@ dependencies = [ ] [[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] name = "tiff" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1271,6 +1346,47 @@ dependencies = [ ] [[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-error" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" +dependencies = [ + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "sharded-slab", + "thread_local", + "tracing-core", +] + +[[package]] name = "tree_magic_mini" version = "3.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1329,6 +1445,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9df2af067a7953e9c3831320f35c1cc0600c30d44d9f7a12b01db1cd88d6b47" [[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] name = "version_check" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -8,6 +8,7 @@ edition = "2021" [dependencies] arboard = { version = "3.4.1", features = ["wayland-data-control"] } biblatex = "0.9.3" +color-eyre = "0.6.3" crossterm = { version = "0.28.1", features = ["event-stream"] } futures = "0.3.30" itertools = "0.13.0" diff --git a/src/frontend/app.rs b/src/frontend/app.rs index 72d1020..0e1c9b9 100644 --- a/src/frontend/app.rs +++ b/src/frontend/app.rs @@ -15,15 +15,28 @@ // along with this program. If not, see <https://www.gnu.org/licenses/>. ///// +use std::io; + +use crate::backend::cliargs::{self, CLIArgs}; +use ratatui::{backend::CrosstermBackend, Terminal}; + use crate::backend::{bib::*, search::BibiSearch}; +use crate::{ + frontend::event::{Event, EventHandler}, + frontend::handler::handle_key_events, + frontend::tui::Tui, +}; use std::{error, net::SocketAddr}; use arboard::Clipboard; +use color_eyre::eyre::{Ok, Result}; use itertools::Itertools; use ratatui::widgets::{ListState, TableState}; +use super::tui; + // Application result type. -pub type AppResult<T> = std::result::Result<T, Box<dyn error::Error>>; +// pub type AppResult<T> = std::result::Result<T, Box<dyn error::Error>>; // Areas in which actions are possible #[derive(Debug)] @@ -47,6 +60,8 @@ pub enum FormerArea { pub struct App { // Is the application running? pub running: bool, + // // tui initialization + // pub tui: Tui, // main bibliography pub main_biblio: BibiMain, // bibliographic data @@ -184,17 +199,45 @@ impl EntryTableItem { } } -impl Default for App { - fn default() -> Self { +// impl Default for App { +// fn default() -> Self { +// let running = true; +// let main_biblio = BibiMain::new(); +// let biblio_data = BibiData::new(&main_biblio.bibliography, &main_biblio.citekeys); +// let tag_list = TagList::from_iter(main_biblio.keyword_list.clone()); +// let search_struct = BibiSearch::default(); +// let entry_table = EntryTable::from_iter(biblio_data.entry_list.bibentries.clone()); +// let current_area = CurrentArea::EntryArea; +// Self { +// running, +// main_biblio, +// biblio_data, +// tag_list, +// search_struct, +// entry_table, +// scroll_info: 0, +// current_area, +// former_area: None, +// // search_string: String::new(), +// } +// } +// } + +impl App { + // Constructs a new instance of [`App`]. + pub fn new() -> Result<Self> { + // Self::default() let running = true; + // let tui = Tui::new()?; let main_biblio = BibiMain::new(); let biblio_data = BibiData::new(&main_biblio.bibliography, &main_biblio.citekeys); let tag_list = TagList::from_iter(main_biblio.keyword_list.clone()); let search_struct = BibiSearch::default(); let entry_table = EntryTable::from_iter(biblio_data.entry_list.bibentries.clone()); let current_area = CurrentArea::EntryArea; - Self { + Ok(Self { running, + // tui, main_biblio, biblio_data, tag_list, @@ -204,14 +247,33 @@ impl Default for App { current_area, former_area: None, // search_string: String::new(), + }) + } + + pub async fn run(&mut self) -> Result<()> { + // Initialize the terminal user interface. + // let backend = CrosstermBackend::new(io::stdout()); + // let terminal = Terminal::new(backend)?; + // let events = EventHandler::new(250); + let mut tui = tui::Tui::new()?; + tui.init()?; + + // Start the main loop. + while self.running { + // Render the user interface. + tui.draw(self)?; + // Handle events. + match tui.events.next().await? { + Event::Tick => self.tick(), + Event::Key(key_event) => handle_key_events(key_event, self)?, + Event::Mouse(_) => {} + Event::Resize(_, _) => {} + } } - } -} -impl App { - // Constructs a new instance of [`App`]. - pub fn new() -> Self { - Self::default() + // Exit the user interface. + tui.exit()?; + Ok(()) } // Handles the tick event of the terminal. diff --git a/src/frontend/event.rs b/src/frontend/event.rs index 27dd059..65b61f1 100644 --- a/src/frontend/event.rs +++ b/src/frontend/event.rs @@ -17,12 +17,11 @@ use std::time::Duration; +use color_eyre::eyre::{OptionExt, Result}; use crossterm::event::{Event as CrosstermEvent, KeyEvent, MouseEvent}; use futures::{FutureExt, StreamExt}; use tokio::sync::mpsc; -use crate::frontend::app::AppResult; - /// Terminal events. #[derive(Clone, Copy, Debug)] pub enum Event { @@ -102,13 +101,11 @@ impl EventHandler { /// /// This function will always block the current thread if /// there is no data available and it's possible for more data to be sent. - pub async fn next(&mut self) -> AppResult<Event> { - self.receiver - .recv() - .await - .ok_or(Box::new(std::io::Error::new( - std::io::ErrorKind::Other, - "This is an IO error", - ))) + pub async fn next(&mut self) -> Result<Event> { + self.receiver.recv().await.ok_or_eyre("This is an IO error") + // .ok_or(Box::new(std::io::Error::new( + // std::io::ErrorKind::Other, + // "This is an IO error", + // ))) } } diff --git a/src/frontend/handler.rs b/src/frontend/handler.rs index ad899e2..11c2652 100644 --- a/src/frontend/handler.rs +++ b/src/frontend/handler.rs @@ -15,13 +15,14 @@ // along with this program. If not, see <https://www.gnu.org/licenses/>. ///// -use crate::frontend::app::{App, AppResult}; +use crate::frontend::app::App; use crossterm::event::{KeyCode, KeyEvent, KeyModifiers}; use super::app::{CurrentArea, FormerArea}; +use color_eyre::eyre::Result; /// Handles the key events and updates the state of [`App`]. -pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> { +pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> Result<()> { // Keycodes activated for every area (high priority) match key_event.code { // Exit application on `ESC` or `q` diff --git a/src/frontend/tui.rs b/src/frontend/tui.rs index 477052f..add3e56 100644 --- a/src/frontend/tui.rs +++ b/src/frontend/tui.rs @@ -15,37 +15,50 @@ // along with this program. If not, see <https://www.gnu.org/licenses/>. ///// -use crate::frontend::app::{App, AppResult}; +use crate::frontend::app::App; use crate::frontend::event::EventHandler; +use color_eyre::eyre::Result; use crossterm::event::{DisableMouseCapture, EnableMouseCapture}; use crossterm::terminal::{self, EnterAlternateScreen, LeaveAlternateScreen}; -use ratatui::backend::Backend; +use ratatui::backend::{Backend, CrosstermBackend}; +// use ratatui::backend::CrosstermBackend as Backend; use ratatui::Terminal; -use std::io; +use std::io::{self, stdout, Stdout}; use std::panic; +use std::{ + ops::{Deref, DerefMut}, + time::Duration, +}; +// pub type IO = std::io::{{crossterm_io | title_case}}; +// pub fn io() -> IO { +// std::io::{{crossterm_io}}() +// } /// Representation of a terminal user interface. /// /// It is responsible for setting up the terminal, /// initializing the interface and handling the draw events. #[derive(Debug)] -pub struct Tui<B: Backend> { +pub struct Tui { /// Interface to the Terminal. - terminal: Terminal<B>, + terminal: ratatui::Terminal<CrosstermBackend<Stdout>>, /// Terminal event handler. pub events: EventHandler, } -impl<B: Backend> Tui<B> { +impl Tui { /// Constructs a new instance of [`Tui`]. - pub fn new(terminal: Terminal<B>, events: EventHandler) -> Self { - Self { terminal, events } + pub fn new() -> Result<Self> { + let backend = CrosstermBackend::new(stdout()); + let terminal = Terminal::new(backend)?; + let events = EventHandler::new(250); + Ok(Self { terminal, events }) } /// Initializes the terminal interface. /// /// It enables the raw mode and sets terminal properties. - pub fn init(&mut self) -> AppResult<()> { + pub fn init(&mut self) -> Result<()> { terminal::enable_raw_mode()?; crossterm::execute!(io::stdout(), EnterAlternateScreen, EnableMouseCapture)?; @@ -66,7 +79,7 @@ impl<B: Backend> Tui<B> { /// /// [`Draw`]: ratatui::Terminal::draw /// [`rendering`]: crate::ui::render - pub fn draw(&mut self, app: &mut App) -> AppResult<()> { + pub fn draw(&mut self, app: &mut App) -> Result<()> { // self.terminal.draw(|frame| ui::render(app, frame))?; self.terminal .draw(|frame| frame.render_widget(app, frame.area()))?; @@ -77,7 +90,7 @@ impl<B: Backend> Tui<B> { /// /// This function is also used for the panic hook to revert /// the terminal properties if unexpected errors occur. - fn reset() -> AppResult<()> { + fn reset() -> Result<()> { terminal::disable_raw_mode()?; crossterm::execute!(io::stdout(), LeaveAlternateScreen, DisableMouseCapture)?; Ok(()) @@ -86,7 +99,7 @@ impl<B: Backend> Tui<B> { /// Exits the terminal interface. /// /// It disables the raw mode and reverts back the terminal properties. - pub fn exit(&mut self) -> AppResult<()> { + pub fn exit(&mut self) -> Result<()> { Self::reset()?; self.terminal.show_cursor()?; Ok(()) diff --git a/src/main.rs b/src/main.rs index c7007ba..9fc9d17 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,17 +21,19 @@ use backend::cliargs::{self, CLIArgs}; use ratatui::{backend::CrosstermBackend, Terminal}; use crate::{ - frontend::app::{App, AppResult}, + frontend::app::App, frontend::event::{Event, EventHandler}, frontend::handler::handle_key_events, frontend::tui::Tui, }; +use color_eyre::eyre::Result; + pub mod backend; pub mod frontend; #[tokio::main] -async fn main() -> AppResult<()> { +async fn main() -> Result<()> { // Parse CLI arguments let parsed_args = CLIArgs::parse_cli_args(); @@ -48,29 +50,8 @@ async fn main() -> AppResult<()> { } // Create an application. - let mut app = App::new(); - - // Initialize the terminal user interface. - let backend = CrosstermBackend::new(io::stdout()); - let terminal = Terminal::new(backend)?; - let events = EventHandler::new(250); - let mut tui = Tui::new(terminal, events); - tui.init()?; - - // Start the main loop. - while app.running { - // Render the user interface. - tui.draw(&mut app)?; - // Handle events. - match tui.events.next().await? { - Event::Tick => app.tick(), - Event::Key(key_event) => handle_key_events(key_event, &mut app)?, - Event::Mouse(_) => {} - Event::Resize(_, _) => {} - } - } + let mut app = App::new()?; - // Exit the user interface. - tui.exit()?; + app.run().await?; Ok(()) } |
