tek/crates/tek_core/src/lib.rs

119 lines
3.4 KiB
Rust

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<T> = Result<T, Box<dyn Error>>;
/// Standard optional result type.
pub type Perhaps<T> = Result<Option<T>, Box<dyn Error>>;
/// 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<dyn Component<'a, T, U>> 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<dyn ExitableComponent<'a, T, U>> 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 <R> (state: Arc<RwLock<R>>) -> Usually<Arc<RwLock<R>>>
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)
}