mirror of
https://codeberg.org/unspeaker/tengri.git
synced 2026-07-17 15:56:57 +02:00
try to sort TuiKey/TuiEvent mess
This commit is contained in:
parent
dd7091bda1
commit
53c9438f7d
3 changed files with 108 additions and 113 deletions
139
src/term.rs
139
src/term.rs
|
|
@ -1,7 +1,7 @@
|
|||
mod border;
|
||||
pub use self::border::*;
|
||||
|
||||
use crate::{*, lang::*, draw::*, task::*};
|
||||
use crate::{*, lang::*, draw::*, task::*, exit::*};
|
||||
//use unicode_width::{UnicodeWidthStr, UnicodeWidthChar};
|
||||
//use rand::distributions::uniform::UniformSampler;
|
||||
use ::{
|
||||
|
|
@ -22,69 +22,84 @@ use ::{
|
|||
//event::{poll, read, Event, KeyEvent, KeyCode, KeyModifiers, KeyEventKind, KeyEventState},
|
||||
}
|
||||
},
|
||||
crossterm::event::{
|
||||
read, Event, KeyEvent, KeyModifiers, KeyCode, KeyEventKind, KeyEventState
|
||||
},
|
||||
};
|
||||
|
||||
/// Implement standard [main] entrypoint for TUI apps.
|
||||
#[macro_export] macro_rules! tui_main {
|
||||
($state:expr) => {
|
||||
pub fn main () -> Usually<()> {
|
||||
use ::{
|
||||
std::sync::{
|
||||
Arc,
|
||||
RwLock
|
||||
},
|
||||
std::panic::{
|
||||
set_hook,
|
||||
PanicHookInfo,
|
||||
},
|
||||
std::time::{
|
||||
Duration
|
||||
},
|
||||
better_panic::{
|
||||
Settings,
|
||||
Verbosity
|
||||
},
|
||||
ratatui::{
|
||||
backend::{
|
||||
Backend,
|
||||
CrosstermBackend
|
||||
},
|
||||
crossterm::{
|
||||
ExecutableCommand,
|
||||
terminal::{
|
||||
disable_raw_mode,
|
||||
LeaveAlternateScreen
|
||||
}
|
||||
}
|
||||
},
|
||||
tengri::{
|
||||
exit::Exit,
|
||||
keys::tui_input,
|
||||
term::tui_output,
|
||||
}
|
||||
};
|
||||
let panic = Settings::auto()
|
||||
.verbosity(Verbosity::Full)
|
||||
.create_panic_handler();
|
||||
set_hook(Box::new(move |info: &PanicHookInfo|{
|
||||
stdout().execute(LeaveAlternateScreen).unwrap();
|
||||
CrosstermBackend::new(stdout()).show_cursor().unwrap();
|
||||
disable_raw_mode().unwrap();
|
||||
panic(info);
|
||||
}));
|
||||
Exit::run(|exit|{
|
||||
let state = Arc::new(RwLock::new($state));
|
||||
let scan = Duration::from_millis(100);
|
||||
let input = tui_input(exit.as_ref(), &state, scan)?;
|
||||
let frame = Duration::from_millis(10);
|
||||
let output = tui_output(stdout(), exit.as_ref(), &state, frame)?;
|
||||
output.join();
|
||||
stdout().execute(LeaveAlternateScreen)?;
|
||||
CrosstermBackend::new(stdout()).show_cursor()?;
|
||||
disable_raw_mode()?;
|
||||
Ok(())
|
||||
})
|
||||
($state:expr) => { pub fn main () -> Usually<()> { tui_run_main($state) } }
|
||||
}
|
||||
|
||||
pub fn tui_run_main <T> (state: T) -> Usually<()> where
|
||||
T: View<Tui> + Apply<TuiEvent, Usually<()>> + Send + Sync + 'static
|
||||
{
|
||||
tui_setup_panic();
|
||||
Exit::run(|exit|{
|
||||
let state = Arc::new(RwLock::new(state));
|
||||
let scan = Duration::from_millis(100);
|
||||
let input = tui_input(exit.as_ref(), &state, scan)?;
|
||||
let frame = Duration::from_millis(10);
|
||||
let output = tui_output(exit.as_ref(), &state, frame, std::io::stdout())?;
|
||||
output.join();
|
||||
stdout().execute(LeaveAlternateScreen)?;
|
||||
CrosstermBackend::new(stdout()).show_cursor()?;
|
||||
disable_raw_mode()?;
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
pub fn tui_setup_panic () {
|
||||
use ::std::panic::{set_hook, PanicHookInfo};
|
||||
use ::better_panic::{Settings, Verbosity};
|
||||
let panic = Settings::auto()
|
||||
.verbosity(Verbosity::Full)
|
||||
.create_panic_handler();
|
||||
set_hook(Box::new(move |info: &PanicHookInfo|{
|
||||
stdout().execute(LeaveAlternateScreen).unwrap();
|
||||
CrosstermBackend::new(stdout()).show_cursor().unwrap();
|
||||
disable_raw_mode().unwrap();
|
||||
panic(info);
|
||||
}));
|
||||
}
|
||||
|
||||
/// Enable TUI keyboard input for main state struct.
|
||||
#[macro_export] macro_rules! tui_keys {
|
||||
(|$self:ident:$State:ty,$input:ident|$body:block) => {
|
||||
impl Apply<TuiEvent, Usually<()>> for $State {
|
||||
fn apply (&mut $self, $input: &TuiEvent) -> Usually<()> $body
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Spawn the TUI input thread which reads keys from the terminal.
|
||||
pub fn tui_input <T: Apply<TuiEvent, Usually<()>> + Send + Sync + 'static> (
|
||||
exited: &Arc<AtomicBool>, state: &Arc<RwLock<T>>, poll: Duration
|
||||
) -> Result<Task, std::io::Error> {
|
||||
let exited = exited.clone();
|
||||
let state = state.clone();
|
||||
Task::new_poll(exited.clone(), poll, move |_| {
|
||||
let event = read().unwrap();
|
||||
match event {
|
||||
|
||||
// Hardcoded exit.
|
||||
Event::Key(KeyEvent {
|
||||
modifiers: KeyModifiers::CONTROL,
|
||||
code: KeyCode::Char('c'),
|
||||
kind: KeyEventKind::Press,
|
||||
state: KeyEventState::NONE
|
||||
}) => { exited.store(true, Relaxed); },
|
||||
|
||||
// Handle all other events by the state:
|
||||
event => {
|
||||
if let Err(e) = state.write().unwrap().apply(&TuiEvent(event)) {
|
||||
panic!("{e}")
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Enable TUI output for state struct.
|
||||
|
|
@ -549,6 +564,8 @@ use self::colors::*; mod colors {
|
|||
pub const fn tui_yellow () -> Color { Color::Rgb(255,255,0) }
|
||||
}
|
||||
|
||||
/// Terminal keyboard input.
|
||||
#[cfg(feature = "term")] pub mod event;
|
||||
#[cfg(feature = "term")] pub use self::event::*;
|
||||
|
||||
#[cfg(feature = "term")] pub mod keys;
|
||||
#[cfg(feature = "term")] pub use self::keys::*;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue