From 6834194b9e16a7b5ee68b539ceb1a99b8f1ff90b Mon Sep 17 00:00:00 2001 From: Silas Bartha Date: Thu, 2 May 2024 02:53:51 -0400 Subject: [PATCH] Added ratatui integration + logger redirect --- Cargo.toml | 7 ++++- README.md | 10 +++---- doc/screenshot.png | Bin 20289 -> 48326 bytes src/components.rs | 2 ++ src/lib.rs | 68 ++++++++++++++++++++++++++++++++------------- src/resources.rs | 58 ++++++++++++++++++++++++++++++++++++-- src/systems.rs | 63 +++++++++++++++++++++++++---------------- 7 files changed, 155 insertions(+), 53 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a271dde..81d1710 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "grex_terminal_display" -version = "0.1.0" +version = "0.1.1" edition = "2021" [dependencies] @@ -17,3 +17,8 @@ tag = "v0.1.0" [dependencies.grex_dither_post_process] git = "https://github.com/exvacuum/grex_dither_post_process" tag = "v0.1.2" + +[dependencies.ratatui] +version = "0.26.2" +features = ["unstable-widget-ref"] + diff --git a/README.md b/README.md index a8e1687..64ce199 100644 --- a/README.md +++ b/README.md @@ -10,11 +10,9 @@ Features Include: - Post-process dithers colors to pure black and white, which are then printed as braille characters to the terminal - Responsiveness to terminal window resizing - `TerminalInput` resource which keeps track of pressed & released keys -- Keyboard input enhancements using kitty protocol - -Future Goals: -- Find a way to integrate into a TUI library like ratatui for more interaction options. -- Move kitty enhancements to a feature maybe +- `TerminalUI` resource for rendering ratatui TUI widgets +- `TerminalWidget` trait for creating custom TUI widget components +- Logging redirected to `output.log` ## Screenshots ![](./doc/screenshot.png) @@ -42,7 +40,7 @@ use grex_terminal_display; fn main() { App::new() .add_plugins(( - DefaultPlugins.build().disable::(), + DefaultPlugins.build().disable::().disable::, ScheduleRunnerPlugin::run_loop(Duration::from_secs_f32(1.0 / 60.0)), grex_terminal_display::TerminalDisplayPlugin, )) diff --git a/doc/screenshot.png b/doc/screenshot.png index d5c9de3cb6dcc6440db04d1e723a8e18e0e953aa..dd91418ef202c0cd109cc53c79b2aabc03e03ee3 100644 GIT binary patch literal 48326 zcmd43d0dm%x;7l!TKBF~sR9ZL6|0uHqR5=I1w=$ZkTCf8K!yMTyFFE86q!_n zR0WYCL52WfNF0Dj7$RU2AV8EDB7_h_AdrN>_XOL0Z1;K3>Dll1$II_$B+sy(weEG_ z*L~gBS`XJxyEtt9LgNb%2(;Dlgq=GG^jQT6^y$xk`y4o8sVPPQ|NZ^q3EyZCXj_N! z--dksZJHp^*C0o`A3WmyX2%mB8;vbNcpm>fZyNl-<~) z;-`|_-I259v+ZAQIOh2!=S!`xzPe&?@Dq_9_1@PeUc0`%?qKn4AZ*`fr$bft`XBro zEZ)HH#~(9p7+u-+)sGtOQ`Yko8~#KL6VVeBTsi@KqS+uwfW8?O>55*12yp za5VIqvuf5cQ{lVVd(CzDXdk9EaPUdEulK%Sgt)o`ZP->VYxZtW0gk@*hsFF5OqXkq zqxHM0XX3pHNZ{yYu$QL?l%DJmSCV!lU@zZCzI*7H)(+qd{2P`}?{5CBu2I^_;%k#H zd?@COWEpfRNgT=&0q4I*vb@guE{QTs**
tRN4gT&CDEMdTHi-O(CzE$^|blwf@ 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 F{{;h?Af5mK diff --git a/src/components.rs b/src/components.rs index 560ad89..3ebf507 100644 --- a/src/components.rs +++ b/src/components.rs @@ -1,3 +1,4 @@ + use bevy::{ prelude::*, render::render_resource::{ @@ -70,3 +71,4 @@ impl TerminalDisplayBundle { self.image_handle.clone() } } + diff --git a/src/lib.rs b/src/lib.rs index 3ad98f4..ac093de 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,13 +1,22 @@ -use std::io::stdout; +use std::{io::stdout, fs::OpenOptions}; -use bevy::prelude::*; +use bevy::{ + log::{ + tracing_subscriber::{self, Registry, prelude::*}, + LogPlugin, Level, + }, + prelude::*, utils::tracing::level_filters::LevelFilter, +}; use crossterm::{ - event::PopKeyboardEnhancementFlags, terminal::disable_raw_mode, ExecutableCommand, + event::DisableMouseCapture, + terminal::{disable_raw_mode, LeaveAlternateScreen}, + ExecutableCommand, }; use grex_dither_post_process::DitherPostProcessPlugin; use grex_framebuffer_extract::FramebufferExtractPlugin; -pub use crossterm::event::KeyCode; +pub use crossterm; +pub use ratatui; pub mod components; pub mod events; @@ -18,26 +27,47 @@ pub struct TerminalDisplayPlugin; impl Plugin for TerminalDisplayPlugin { fn build(&self, app: &mut App) { - app.add_plugins((DitherPostProcessPlugin, FramebufferExtractPlugin)) - .add_systems(Startup, systems::setup) - .add_systems( - Update, - ( - systems::input_handling, - systems::resize_handling, - systems::print_to_terminal, - ), - ) - .insert_resource(resources::EventQueue::default()) - .insert_resource(resources::TerminalInput::default()) - .add_event::(); + app.add_plugins(( + DitherPostProcessPlugin, + FramebufferExtractPlugin, + LogPlugin { + update_subscriber: Some(|_| { + let log_file = OpenOptions::new() + .write(true) + .create(true) + .open("debug.log") + .unwrap(); + let file_layer = tracing_subscriber::fmt::Layer::new() + .with_writer(log_file) + .with_filter(LevelFilter::from_level(Level::INFO)); + Box::new(Registry::default().with(file_layer)) + }), + ..Default::default() + }, + )) + .add_systems(Startup, systems::setup) + .add_systems( + Update, + ( + systems::input_handling, + systems::resize_handling, + systems::print_to_terminal, + systems::widget_input_handling, + ), + ) + .insert_resource(resources::Terminal::default()) + .insert_resource(resources::EventQueue::default()) + .insert_resource(resources::TerminalInput::default()) + .insert_resource(resources::TerminalUI::default()) + .add_event::(); } } impl Drop for TerminalDisplayPlugin { fn drop(&mut self) { let mut stdout = stdout(); - stdout.execute(PopKeyboardEnhancementFlags).unwrap(); - disable_raw_mode().unwrap(); + let _ = stdout.execute(DisableMouseCapture); + let _ = stdout.execute(LeaveAlternateScreen); + let _ = disable_raw_mode(); } } diff --git a/src/resources.rs b/src/resources.rs index 343967d..e8fb946 100644 --- a/src/resources.rs +++ b/src/resources.rs @@ -1,7 +1,10 @@ -use std::sync::{Arc, Mutex}; +use std::{sync::{Arc, Mutex}, io::{stdout, Stdout}, fs::{File, OpenOptions}}; -use bevy::{prelude::*, utils::HashSet}; -use crossterm::event::{Event, KeyCode}; +use bevy::{prelude::*, utils::{HashSet, Uuid, HashMap, tracing::{subscriber, level_filters::LevelFilter}}, log::tracing_subscriber}; +use crossterm::{event::{Event, KeyCode, EnableMouseCapture}, terminal::{EnterAlternateScreen, enable_raw_mode}, ExecutableCommand}; +use ratatui::{backend::CrosstermBackend, Frame, layout::Rect}; + +use crate::events::TerminalInputEvent; #[derive(Resource, Default)] pub struct TerminalInput { @@ -36,3 +39,52 @@ impl TerminalInput { #[derive(Resource, Default)] pub(super) struct EventQueue(pub(super) Arc>>); + +#[derive(Resource)] +pub struct Terminal(pub ratatui::Terminal>); + +impl Default for Terminal { + fn default() -> Self { + stdout().execute(EnterAlternateScreen).unwrap(); + stdout().execute(EnableMouseCapture).unwrap(); + enable_raw_mode().unwrap(); + let mut terminal = ratatui::Terminal::new(CrosstermBackend::new(stdout())).expect("Failed to create terminal"); + terminal.clear().expect("Failed to clear terminal"); + Self(terminal) + } +} + +#[derive(Resource, Default)] +pub struct TerminalUI { + widgets: HashMap> +} + +impl TerminalUI { + pub fn insert_widget(&mut self, widget: Box) -> Uuid { + let id = Uuid::new_v4(); + self.widgets.insert(id, widget); + id + } + + pub fn get_widget(&mut self, id: Uuid) -> Option<&mut Box> { + self.widgets.get_mut(&id) + } + + pub fn destroy_widget(&mut self, id: Uuid) { + self.widgets.remove(&id); + } + + pub fn widgets(&mut self) -> Vec<&mut Box> { + let mut vec = self.widgets.values_mut().collect::>(); + vec.sort_by(|a, b| { a.depth().cmp(&b.depth()).reverse() }); + vec + } +} + +pub trait TerminalWidget { + fn init(&mut self) {} + fn update(&mut self) {} + fn render(&mut self, frame: &mut Frame, rect: Rect); + fn handle_events(&mut self, _event: &TerminalInputEvent) {} + fn depth(&self) -> u32 { 0 } +} diff --git a/src/systems.rs b/src/systems.rs index 77b8d11..e1a9bef 100644 --- a/src/systems.rs +++ b/src/systems.rs @@ -1,25 +1,20 @@ -use std::{ - io::{stdout, Write}, - usize, -}; - use bevy::{ prelude::*, render::render_resource::{Extent3d, TextureFormat}, }; -use crossterm::{ - cursor::{self, MoveTo}, - event::{read, Event, KeyEventKind, KeyboardEnhancementFlags, PushKeyboardEnhancementFlags}, - terminal::enable_raw_mode, - ExecutableCommand, QueueableCommand, -}; +use crossterm::event::{read, Event, KeyEventKind}; use grex_framebuffer_extract::{ components::FramebufferExtractDestination, render_assets::FramebufferExtractSource, }; use crate::{ events::TerminalInputEvent, - resources::{EventQueue, TerminalInput}, + resources::{EventQueue, Terminal, TerminalInput, TerminalUI}, +}; + +use ratatui::{ + prelude::*, + widgets::{Paragraph, Wrap}, }; const BRAILLE_CODE_MIN: u16 = 0x2800; @@ -41,16 +36,13 @@ pub fn setup(event_queue: Res) { } } }); - - let mut stdout = stdout(); - enable_raw_mode().expect("Failed to put terminal into raw mode"); - let _ = stdout.execute(PushKeyboardEnhancementFlags( - KeyboardEnhancementFlags::REPORT_EVENT_TYPES, - )); - let _ = stdout.execute(cursor::Hide); } -pub fn print_to_terminal(image_exports: Query<&FramebufferExtractDestination>) { +pub fn print_to_terminal( + mut terminal: ResMut, + mut terminal_ui: ResMut, + image_exports: Query<&FramebufferExtractDestination>, +) { for image_export in image_exports.iter() { let mut image = image_export .0 @@ -93,10 +85,22 @@ pub fn print_to_terminal(image_exports: Query<&FramebufferExtractDestination>) { } let string = output_buffer.into_iter().collect::(); - let mut stdout = stdout(); - stdout.queue(MoveTo(0, 0)).unwrap(); - stdout.write_all(string.as_bytes()).unwrap(); - stdout.flush().unwrap(); + terminal + .0 + .draw(|frame| { + let area = frame.size(); + frame.render_widget( + Paragraph::new(string) + .white() + .bold() + .wrap(Wrap { trim: true }), + area, + ); + for widget in terminal_ui.widgets().iter_mut() { + widget.render(frame, area); + } + }) + .expect("Failed to draw terminal frame"); } } @@ -112,6 +116,17 @@ fn braille_char(mask: u8) -> char { } } +pub fn widget_input_handling( + mut terminal_ui: ResMut, + mut event_reader: EventReader, +) { + for event in event_reader.read() { + for widget in terminal_ui.widgets().iter_mut() { + widget.handle_events(event); + } + } +} + pub fn input_handling( event_queue: Res, mut input: ResMut,