pub use ratatui; pub use crossterm; pub use jack; pub use midly; pub use clap; pub use std::sync::{Arc, Mutex, LockResult, RwLock, RwLockReadGuard, RwLockWriteGuard}; pub use std::collections::BTreeMap; pub use crossterm::event::{Event, KeyEvent, KeyCode, KeyModifiers}; pub use ratatui::prelude::{Rect, Style, Color, Buffer}; pub use ratatui::style::Stylize; pub use clojure_reader::{edn::{read, Edn}, error::Error as EdnError}; pub use once_cell::sync::Lazy; pub use std::sync::atomic::{Ordering, AtomicBool}; pub use std::rc::Rc; pub use std::cell::RefCell; pub(crate) use std::error::Error; pub(crate) use std::io::{stdout}; pub(crate) use std::thread::{spawn, JoinHandle}; pub(crate) use std::time::Duration; pub(crate) use atomic_float::*; //pub(crate) use std::path::PathBuf; //pub(crate) use std::fs::read_dir; //pub(crate) use std::ffi::OsString; // Non-stdlib dependencies: //pub(crate) use microxdg::XdgApp; //pub(crate) use midly::{MidiMessage, live::LiveEvent, num::u7}; pub(crate) use crossterm::{ExecutableCommand}; use better_panic::{Settings, Verbosity}; use crossterm::terminal::{ EnterAlternateScreen, LeaveAlternateScreen, enable_raw_mode, disable_raw_mode }; /// Define and reexport submodules. #[macro_export] macro_rules! submod { ($($name:ident)*) => { $(mod $name; pub use self::$name::*;)* }; } /// Define and reexport public modules. #[macro_export] macro_rules! pubmod { ($($name:ident)*) => { $(pub mod $name;)* }; } submod! { exit focus handle handle_keymap jack_core jack_device jack_event jack_ports render render_axis render_buffer render_collect render_layered render_split render_tui render_tui_theme render_tui_border time_base time_note time_tick } /// EDN parsing helper. #[macro_export] macro_rules! edn { ($edn:ident { $($pat:pat => $expr:expr),* $(,)? }) => { match $edn { $($pat => $expr),* } }; ($edn:ident in $args:ident { $($pat:pat => $expr:expr),* $(,)? }) => { for $edn in $args { edn!($edn { $($pat => $expr),* }) } }; } /// Standard result type. pub type Usually = Result>; /// Standard optional result type. pub type Perhaps = Result, Box>; /// A UI component. pub trait Component<'a, T, U>: Render<'a, T, U> + Handle + Sync { /// Perform type erasure for collecting heterogeneous components. fn boxed (self) -> Box> where Self: Sized + 'static { Box::new(self) } } impl<'a, C, T, U> Component<'a, T, U> for C where C: Render<'a, T, U> + Handle + Sync {} /// Marker trait for [Component]s that can [Exit] pub trait ExitableComponent<'a, T, U>: Exit + Component<'a, T, U> { /// Perform type erasure for collecting heterogeneous components. fn boxed (self) -> Box> where Self: Sized + 'static { Box::new(self) } } impl<'a, E: Exit + Component<'a, T, U>, T, U> ExitableComponent<'a, T, U> for E {} /// Run the main loop. pub fn run (state: Arc>) -> Usually>> where R: for <'a> Render<'a, TuiOutput<'a>, Rect> + Handle + Sized + 'static { let exited = Arc::new(AtomicBool::new(false)); let _input_thread = input_thread(&exited, &state); terminal_setup()?; panic_hook_setup(); let main_thread = tui_render_thread(&exited, &state)?; main_thread.join().expect("main thread failed"); terminal_teardown()?; Ok(state) }