From b178bd14f30c822352593af290c95f40e79b5d4f Mon Sep 17 00:00:00 2001 From: Alexandre Pasmantier Date: Sat, 12 Oct 2024 00:38:55 +0200 Subject: [PATCH] maybe getting there --- src/app.rs | 8 ++- src/components/finders.rs | 9 +++- src/main.rs | 3 +- src/render.rs | 16 ++++-- src/tui.rs | 101 ++++++++++++++++++++++++-------------- 5 files changed, 89 insertions(+), 48 deletions(-) diff --git a/src/app.rs b/src/app.rs index d794022..50b2ec7 100644 --- a/src/app.rs +++ b/src/app.rs @@ -62,7 +62,6 @@ use crate::{ config::Config, event::{Event, EventLoop, Key}, render::{render, RenderingTask}, - tui::Tui, }; pub struct App { @@ -117,14 +116,13 @@ impl App { } pub async fn run(&mut self) -> Result> { - let mut tui = Tui::new()?.frame_rate(self.frame_rate); - info!("Starting event loop"); + info!("Starting backend event loop"); let event_loop = EventLoop::new(self.tick_rate, true); - info!("Started event loop"); self.event_rx = event_loop.rx; self.event_abort_tx = event_loop.abort_tx; // Rendering loop + debug!("Starting rendering loop"); let (render_tx, render_rx) = mpsc::unbounded_channel(); self.render_tx = render_tx.clone(); let action_tx_r = self.action_tx.clone(); @@ -133,7 +131,6 @@ impl App { let frame_rate = self.frame_rate; tokio::spawn(async move { render( - &mut tui, render_rx, //render_tx, action_tx_r, @@ -145,6 +142,7 @@ impl App { }); // event handling loop + debug!("Starting event handling loop"); let action_tx = self.action_tx.clone(); loop { // handle event and convert to action diff --git a/src/components/finders.rs b/src/components/finders.rs index d774e28..45de7b2 100644 --- a/src/components/finders.rs +++ b/src/components/finders.rs @@ -29,7 +29,14 @@ impl Entry { } pub fn stdout_repr(&self) -> String { - self.name.clone() + &self.line_number.map_or(String::new(), |n| format!(":{n}")) + let mut repr = self.name.clone(); + if let Some(line_number) = self.line_number { + repr.push_str(&format!(":{}", line_number)); + } + if let Some(preview) = &self.preview { + repr.push_str(&format!("\n{}", preview)); + } + repr } } diff --git a/src/main.rs b/src/main.rs index 6145612..eb9bd4a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -use std::io::{stdout, IsTerminal, Write}; +use std::io::{stdout, Write}; use clap::Parser; use cli::Cli; @@ -27,6 +27,7 @@ async fn main() -> Result<()> { let mut app = App::new(args.channel, args.tick_rate, args.frame_rate)?; if let Some(entry) = app.run().await? { // print entry to stdout + stdout().flush()?; info!("{:?}", entry); stdout().write_all(entry.stdout_repr().as_bytes())?; } diff --git a/src/render.rs b/src/render.rs index d1ee350..0e92959 100644 --- a/src/render.rs +++ b/src/render.rs @@ -1,6 +1,7 @@ use color_eyre::Result; use ratatui::layout::Rect; use std::sync::Arc; +use tracing::debug; use tokio::{ select, @@ -14,6 +15,7 @@ use crate::{ tui::Tui, }; +#[derive(Debug)] pub enum RenderingTask { ClearScreen, Render, @@ -24,15 +26,18 @@ pub enum RenderingTask { } pub async fn render( - tui: &mut Tui, mut render_rx: mpsc::UnboundedReceiver, action_tx: mpsc::UnboundedSender, config: Config, television: Arc>, frame_rate: f64, ) -> Result<()> { + let mut tui = Tui::new()?.frame_rate(frame_rate); + + debug!("Entering tui"); tui.enter()?; + debug!("Registering action handler and config handler"); television .lock() .await @@ -51,17 +56,22 @@ pub async fn render( } maybe_task = render_rx.recv() => { if let Some(task) = maybe_task { + debug!("Received task: {:?}", task); match task { RenderingTask::ClearScreen => { tui.terminal.clear()?; } RenderingTask::Render => { let mut television = television.lock().await; - tui.terminal.draw(|frame| { + debug!("Drawing television"); + tui.terminal.try_draw(|frame| { + debug!("Drawing frame"); if let Err(err) = television.draw(frame, frame.area()) { + debug!("Failed to draw: {:?}", err); let _ = action_tx - .send(Action::Error(format!("Failed to draw: {:?}", err))); + .send(Action::Error(format!("Failed to draw: {err:?}"))); } + Ok::<() ,std::io::Error>(()) })?; } RenderingTask::Resize(w, h) => { diff --git a/src/tui.rs b/src/tui.rs index 755a4ea..6ea84ac 100644 --- a/src/tui.rs +++ b/src/tui.rs @@ -1,18 +1,39 @@ use std::{ - io::{stderr, BufWriter, Stderr}, + io::{stderr, stdout, BufWriter, Stderr, Write}, ops::{Deref, DerefMut}, }; use color_eyre::Result; use crossterm::{ cursor, - terminal::{EnterAlternateScreen, LeaveAlternateScreen}, + terminal::{ + disable_raw_mode, enable_raw_mode, is_raw_mode_enabled, EnterAlternateScreen, + LeaveAlternateScreen, + }, + ExecutableCommand, }; -use ratatui::backend::CrosstermBackend as Backend; +use ratatui::backend::CrosstermBackend; use tokio::task::JoinHandle; +use tracing::debug; + +#[derive(Copy, Clone, Debug, Default)] +enum IoStream { + #[default] + Stdout, + BlockBufferedStderr, +} + +impl IoStream { + fn as_stream(&self) -> Result> { + Ok(match self { + IoStream::Stdout => Box::new(stdout()), + IoStream::BlockBufferedStderr => Box::new(BufWriter::new(stderr())), + }) + } +} pub struct Tui { - pub terminal: ratatui::Terminal>>, + pub io_stream: Box, pub task: JoinHandle<()>, pub frame_rate: f64, } @@ -20,7 +41,7 @@ pub struct Tui { impl Tui { pub fn new() -> Result { Ok(Self { - terminal: ratatui::Terminal::new(Backend::new(BufWriter::new(stderr())))?, + io_stream: IoStream::BlockBufferedStderr.as_stream()?, task: tokio::spawn(async {}), frame_rate: 60.0, }) @@ -31,26 +52,27 @@ impl Tui { self } + pub fn size(&self) -> Result<(u16, u16)> { + Ok(crossterm::terminal::size()?) + } + pub fn enter(&mut self) -> Result<()> { - crossterm::terminal::enable_raw_mode()?; - crossterm::execute!( - self.terminal.backend_mut(), - EnterAlternateScreen, - cursor::Hide - )?; + enable_raw_mode()?; + + self.io_stream.execute(EnterAlternateScreen)?; + self.io_stream.execute(cursor::Hide)?; Ok(()) } pub fn exit(&mut self) -> Result<()> { - if crossterm::terminal::is_raw_mode_enabled()? { - self.flush()?; - crossterm::execute!( - self.terminal.backend_mut(), - cursor::Show, - LeaveAlternateScreen - )?; - crossterm::terminal::disable_raw_mode()?; + if is_raw_mode_enabled()? { + debug!("Exiting terminal"); + self.io_stream.flush()?; + self.io_stream.execute(cursor::Show)?; + self.io_stream.execute(LeaveAlternateScreen)?; + disable_raw_mode()?; } + Ok(()) } @@ -67,22 +89,25 @@ impl Tui { } } -impl Deref for Tui { - type Target = ratatui::Terminal>>; - - fn deref(&self) -> &Self::Target { - &self.terminal - } -} - -impl DerefMut for Tui { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.terminal - } -} - -impl Drop for Tui { - fn drop(&mut self) { - self.exit().unwrap(); - } -} +//impl Deref for Tui { +// type Target = ratatui::Terminal>; +// +// fn deref(&self) -> &Self::Target { +// &self.terminal +// } +//} +// +//impl DerefMut for Tui { +// fn deref_mut(&mut self) -> &mut Self::Target { +// &mut self.terminal +// } +//} +// +//impl Drop for Tui { +// fn drop(&mut self) { +// match self.exit() { +// Ok(_) => debug!("Successfully exited terminal"), +// Err(e) => debug!("Failed to exit terminal: {:?}", e), +// } +// } +//}