mirror of
https://codeberg.org/unspeaker/tengri.git
synced 2026-04-25 13:40:43 +02:00
and exits, weirdly. wonder what's up here
This commit is contained in:
parent
b0fb9f013d
commit
b44dc02f33
9 changed files with 110 additions and 80 deletions
|
|
@ -4,9 +4,10 @@ env.CARGO_TERM_COLOR = "always"
|
||||||
|
|
||||||
[keybindings]
|
[keybindings]
|
||||||
c = "job:check"
|
c = "job:check"
|
||||||
d = "job:doc-open"
|
d = "job:doc"
|
||||||
|
D = "job:doc-open"
|
||||||
t = "job:test"
|
t = "job:test"
|
||||||
n = "job:nextest"
|
T = "job:nextest"
|
||||||
l = "job:clippy"
|
l = "job:clippy"
|
||||||
|
|
||||||
[jobs]
|
[jobs]
|
||||||
|
|
|
||||||
2
dizzle
2
dizzle
|
|
@ -1 +1 @@
|
||||||
Subproject commit 192a1d8257a9f2ad43ebceacb7b5ca348c601471
|
Subproject commit e984fbb9fe8e588399744d50841d006454c16657
|
||||||
|
|
@ -1,31 +1,32 @@
|
||||||
use ::{
|
use ::{
|
||||||
std::{io::stdout, sync::{Arc, RwLock}},
|
std::{io::stdout, sync::{Arc, RwLock}},
|
||||||
tengri::{*, term::*, lang::*, keys::*, draw::*, space::*},
|
tengri::{*, term::*, lang::*, keys::*, draw::*, space::*, dizzle::*},
|
||||||
ratatui::style::Color,
|
ratatui::style::Color,
|
||||||
};
|
};
|
||||||
|
|
||||||
tui_main!(State { cursor: 10, ..Default::default() });
|
tui_main!(State {
|
||||||
|
cursor: 10,
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
|
||||||
impl Apply<TuiEvent, Usually<Self>> for State {
|
tui_keys!(|self: State, input| {
|
||||||
fn apply (&mut self, input: &TuiEvent) -> Usually<Self> {
|
todo!()
|
||||||
todo!()
|
});
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl View<Tui> for State {
|
tui_view!(|self: State| {
|
||||||
fn view (&self) -> impl Draw<Tui> {
|
let index = self.cursor + 1;
|
||||||
let index = self.cursor + 1;
|
let wh = (self.size.w(), self.size.h());
|
||||||
let wh = (self.size.w(), self.size.h());
|
let src = VIEWS.get(self.cursor).unwrap_or(&"");
|
||||||
let src = VIEWS.get(self.cursor).unwrap_or(&"");
|
let heading = format!("State {}/{} in {:?}", index, VIEWS.len(), &wh);
|
||||||
let heading = format!("State {}/{} in {:?}", index, VIEWS.len(), &wh);
|
let title = bg(Color::Rgb(60, 10, 10), y_push(1, align_n(heading)));
|
||||||
let title = bg(Color::Rgb(60, 10, 10), push_y(1, align_n(heading)));
|
let code = bg(Color::Rgb(10, 60, 10), y_push(2, align_n(format!("{}", src))));
|
||||||
let code = bg(Color::Rgb(10, 60, 10), push_y(2, align_n(format!("{}", src))));
|
//let content = ;//();//bg(Color::Rgb(10, 10, 60), View(self, CstIter::new(src)));
|
||||||
//let content = ;//();//bg(Color::Rgb(10, 10, 60), View(self, CstIter::new(src)));
|
let widget = thunk(move|to: &mut Tui|self.interpret(to, &src));
|
||||||
self.size.of(bsp_s(title, bsp_n(code, self.understand(to, &src).unwrap())))
|
self.size.of(south(title, north(code, widget)))
|
||||||
}
|
});
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Default)] struct State {
|
#[derive(Debug, Default)]
|
||||||
|
struct State {
|
||||||
/** Command history (undo/redo). */
|
/** Command history (undo/redo). */
|
||||||
history: Vec<Action>,
|
history: Vec<Action>,
|
||||||
/** User-controllable value. */
|
/** User-controllable value. */
|
||||||
|
|
@ -34,7 +35,9 @@ impl View<Tui> for State {
|
||||||
size: crate::space::Size,
|
size: crate::space::Size,
|
||||||
}
|
}
|
||||||
|
|
||||||
//impl_from!(Action: |input: &TuiIn| todo!());
|
impl Interpret<Tui, XYWH<u16>> for State {
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)] enum Action {
|
#[derive(Debug)] enum Action {
|
||||||
/** Increment cursor */
|
/** Increment cursor */
|
||||||
Next,
|
Next,
|
||||||
|
|
@ -42,6 +45,8 @@ impl View<Tui> for State {
|
||||||
Prev
|
Prev
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//impl_from!(Action: |input: &TuiIn| todo!());
|
||||||
|
|
||||||
fn draw_example (state: &State, to: &mut Tui) {
|
fn draw_example (state: &State, to: &mut Tui) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
{pkgs?import<nixpkgs>{}}:let
|
{pkgs?import<nixpkgs>{}}:let
|
||||||
stdenv = pkgs.clang19Stdenv;
|
stdenv = pkgs.clang19Stdenv;
|
||||||
name = "tengri";
|
name = "tengri";
|
||||||
nativeBuildInputs = [ pkgs.pkg-config pkgs.clang pkgs.libclang pkgs.mold ];
|
nativeBuildInputs = [ pkgs.pkg-config pkgs.clang pkgs.libclang pkgs.mold pkgs.bacon ];
|
||||||
buildInputs = [ pkgs.libclang pkgs.jack2 ];
|
buildInputs = [ pkgs.libclang pkgs.jack2 ];
|
||||||
LIBCLANG_PATH = "${pkgs.libclang.lib.outPath}/lib";
|
LIBCLANG_PATH = "${pkgs.libclang.lib.outPath}/lib";
|
||||||
LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath [];
|
LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath [];
|
||||||
|
|
|
||||||
36
src/eval.rs
36
src/eval.rs
|
|
@ -16,7 +16,7 @@ use dizzle::*;
|
||||||
/// struct State {/*app-specific*/}
|
/// struct State {/*app-specific*/}
|
||||||
/// impl<'b> Namespace<'b, bool> for State {}
|
/// impl<'b> Namespace<'b, bool> for State {}
|
||||||
/// impl<'b> Namespace<'b, u16> for State {}
|
/// impl<'b> Namespace<'b, u16> for State {}
|
||||||
/// impl Understand<Target, ()> for State {}
|
/// impl Interpret<Target, ()> for State {}
|
||||||
///
|
///
|
||||||
/// # fn main () -> tengri::Usually<()> {
|
/// # fn main () -> tengri::Usually<()> {
|
||||||
/// let state = State {};
|
/// let state = State {};
|
||||||
|
|
@ -30,7 +30,7 @@ use dizzle::*;
|
||||||
#[cfg(feature = "dsl")] pub fn eval_view <'a, O: Screen + 'a, S> (
|
#[cfg(feature = "dsl")] pub fn eval_view <'a, O: Screen + 'a, S> (
|
||||||
state: &S, output: &mut O, expr: &'a impl Expression
|
state: &S, output: &mut O, expr: &'a impl Expression
|
||||||
) -> Usually<bool> where
|
) -> Usually<bool> where
|
||||||
S: Understand<O, ()>
|
S: Interpret<O, ()>
|
||||||
+ for<'b>Namespace<'b, bool>
|
+ for<'b>Namespace<'b, bool>
|
||||||
+ for<'b>Namespace<'b, O::Unit>
|
+ for<'b>Namespace<'b, O::Unit>
|
||||||
{
|
{
|
||||||
|
|
@ -52,18 +52,18 @@ use dizzle::*;
|
||||||
|
|
||||||
Some("when") => output.place(&when(
|
Some("when") => output.place(&when(
|
||||||
state.namespace(arg0?)?.unwrap(),
|
state.namespace(arg0?)?.unwrap(),
|
||||||
move|output: &mut O|state.understand(output, &arg1)
|
move|output: &mut O|state.interpret(output, &arg1)
|
||||||
)),
|
)),
|
||||||
|
|
||||||
Some("either") => output.place(&either(
|
Some("either") => output.place(&either(
|
||||||
state.namespace(arg0?)?.unwrap(),
|
state.namespace(arg0?)?.unwrap(),
|
||||||
move|output: &mut O|state.understand(output, &arg1),
|
move|output: &mut O|state.interpret(output, &arg1),
|
||||||
move|output: &mut O|state.understand(output, &arg2),
|
move|output: &mut O|state.interpret(output, &arg2),
|
||||||
)),
|
)),
|
||||||
|
|
||||||
Some("bsp") => output.place(&{
|
Some("bsp") => output.place(&{
|
||||||
let a = move|output: &mut O|state.understand(output, &arg0);
|
let a = move|output: &mut O|state.interpret(output, &arg0);
|
||||||
let b = move|output: &mut O|state.understand(output, &arg1);
|
let b = move|output: &mut O|state.interpret(output, &arg1);
|
||||||
bsp(match frags.next() {
|
bsp(match frags.next() {
|
||||||
Some("n") => Alignment::N,
|
Some("n") => Alignment::N,
|
||||||
Some("s") => Alignment::S,
|
Some("s") => Alignment::S,
|
||||||
|
|
@ -76,7 +76,7 @@ use dizzle::*;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
Some("align") => output.place(&{
|
Some("align") => output.place(&{
|
||||||
let a = move|output: &mut O|state.understand(output, &arg0).unwrap();
|
let a = move|output: &mut O|state.interpret(output, &arg0).unwrap();
|
||||||
align(match frags.next() {
|
align(match frags.next() {
|
||||||
Some("c") => Alignment::Center,
|
Some("c") => Alignment::Center,
|
||||||
Some("n") => Alignment::N,
|
Some("n") => Alignment::N,
|
||||||
|
|
@ -90,7 +90,7 @@ use dizzle::*;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
Some("fill") => output.place(&{
|
Some("fill") => output.place(&{
|
||||||
let a = move|output: &mut O|state.understand(output, &arg0).unwrap();
|
let a = move|output: &mut O|state.interpret(output, &arg0).unwrap();
|
||||||
match frags.next() {
|
match frags.next() {
|
||||||
Some("xy") | None => fill_wh(a),
|
Some("xy") | None => fill_wh(a),
|
||||||
Some("x") => fill_w(a),
|
Some("x") => fill_w(a),
|
||||||
|
|
@ -102,7 +102,7 @@ use dizzle::*;
|
||||||
Some("exact") => output.place(&{
|
Some("exact") => output.place(&{
|
||||||
let axis = frags.next();
|
let axis = frags.next();
|
||||||
let arg = match axis { Some("x") | Some("y") => arg1, Some("xy") | None => arg2, _ => panic!("exact: unsupported axis {axis:?}") };
|
let arg = match axis { Some("x") | Some("y") => arg1, Some("xy") | None => arg2, _ => panic!("exact: unsupported axis {axis:?}") };
|
||||||
let cb = move|output: &mut O|state.understand(output, &arg).unwrap();
|
let cb = move|output: &mut O|state.interpret(output, &arg).unwrap();
|
||||||
match axis {
|
match axis {
|
||||||
Some("xy") | None => exact_wh(state.namespace(arg0?)?.unwrap(), state.namespace(arg1?)?.unwrap(), cb),
|
Some("xy") | None => exact_wh(state.namespace(arg0?)?.unwrap(), state.namespace(arg1?)?.unwrap(), cb),
|
||||||
Some("x") => exact_w(state.namespace(arg0?)?.unwrap(), cb),
|
Some("x") => exact_w(state.namespace(arg0?)?.unwrap(), cb),
|
||||||
|
|
@ -115,7 +115,7 @@ use dizzle::*;
|
||||||
Some("min") => output.place(&{
|
Some("min") => output.place(&{
|
||||||
let axis = frags.next();
|
let axis = frags.next();
|
||||||
let arg = match axis { Some("x") | Some("y") => arg1, Some("xy") | None => arg2, _ => panic!("min: unsupported axis {axis:?}") };
|
let arg = match axis { Some("x") | Some("y") => arg1, Some("xy") | None => arg2, _ => panic!("min: unsupported axis {axis:?}") };
|
||||||
let cb = move|output: &mut O|state.understand(output, &arg).unwrap();
|
let cb = move|output: &mut O|state.interpret(output, &arg).unwrap();
|
||||||
match axis {
|
match axis {
|
||||||
Some("xy") | None => min_wh(state.namespace(arg0?)?.unwrap(), state.namespace(arg1?)?.unwrap(), cb),
|
Some("xy") | None => min_wh(state.namespace(arg0?)?.unwrap(), state.namespace(arg1?)?.unwrap(), cb),
|
||||||
Some("x") => min_w(state.namespace(arg0?)?.unwrap(), cb),
|
Some("x") => min_w(state.namespace(arg0?)?.unwrap(), cb),
|
||||||
|
|
@ -127,7 +127,7 @@ use dizzle::*;
|
||||||
Some("max") => output.place(&{
|
Some("max") => output.place(&{
|
||||||
let axis = frags.next();
|
let axis = frags.next();
|
||||||
let arg = match axis { Some("x") | Some("y") => arg1, Some("xy") | None => arg2, _ => panic!("max: unsupported axis {axis:?}") };
|
let arg = match axis { Some("x") | Some("y") => arg1, Some("xy") | None => arg2, _ => panic!("max: unsupported axis {axis:?}") };
|
||||||
let cb = move|output: &mut O|state.understand(output, &arg).unwrap();
|
let cb = move|output: &mut O|state.interpret(output, &arg).unwrap();
|
||||||
match axis {
|
match axis {
|
||||||
Some("xy") | None => max_wh(state.namespace(arg0?)?.unwrap(), state.namespace(arg1?)?.unwrap(), cb),
|
Some("xy") | None => max_wh(state.namespace(arg0?)?.unwrap(), state.namespace(arg1?)?.unwrap(), cb),
|
||||||
Some("x") => max_w(state.namespace(arg0?)?.unwrap(), cb),
|
Some("x") => max_w(state.namespace(arg0?)?.unwrap(), cb),
|
||||||
|
|
@ -139,7 +139,7 @@ use dizzle::*;
|
||||||
Some("push") => output.place(&{
|
Some("push") => output.place(&{
|
||||||
let axis = frags.next();
|
let axis = frags.next();
|
||||||
let arg = match axis { Some("x") | Some("y") => arg1, Some("xy") | None => arg2, _ => panic!("push: unsupported axis {axis:?}") };
|
let arg = match axis { Some("x") | Some("y") => arg1, Some("xy") | None => arg2, _ => panic!("push: unsupported axis {axis:?}") };
|
||||||
let cb = move|output: &mut O|state.understand(output, &arg);
|
let cb = move|output: &mut O|state.interpret(output, &arg);
|
||||||
match axis {
|
match axis {
|
||||||
Some("xy") | None => push_xy(state.namespace(arg0?)?.unwrap(), state.namespace(arg1?)?.unwrap(), cb),
|
Some("xy") | None => push_xy(state.namespace(arg0?)?.unwrap(), state.namespace(arg1?)?.unwrap(), cb),
|
||||||
Some("x") => push_x(state.namespace(arg0?)?.unwrap(), cb),
|
Some("x") => push_x(state.namespace(arg0?)?.unwrap(), cb),
|
||||||
|
|
@ -157,13 +157,13 @@ use dizzle::*;
|
||||||
/// Interpret TUI-specific layout operation.
|
/// Interpret TUI-specific layout operation.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use tengri::{Namespace, Understand, Tui, ratatui::prelude::Color};
|
/// use tengri::{Namespace, Interpret, Tui, ratatui::prelude::Color};
|
||||||
///
|
///
|
||||||
/// struct State;
|
/// struct State;
|
||||||
/// impl<'b> Namespace<'b, bool> for State {}
|
/// impl<'b> Namespace<'b, bool> for State {}
|
||||||
/// impl<'b> Namespace<'b, u16> for State {}
|
/// impl<'b> Namespace<'b, u16> for State {}
|
||||||
/// impl<'b> Namespace<'b, Color> for State {}
|
/// impl<'b> Namespace<'b, Color> for State {}
|
||||||
/// impl Understand<Tui, ()> for State {}
|
/// impl Interpret<Tui, ()> for State {}
|
||||||
/// # fn main () -> tengri::Usually<()> {
|
/// # fn main () -> tengri::Usually<()> {
|
||||||
/// let state = State;
|
/// let state = State;
|
||||||
/// let mut out = Tui::default();
|
/// let mut out = Tui::default();
|
||||||
|
|
@ -177,7 +177,7 @@ use dizzle::*;
|
||||||
pub fn eval_view_tui <'a, S> (
|
pub fn eval_view_tui <'a, S> (
|
||||||
state: &S, output: &mut Tui, expr: impl Expression + 'a
|
state: &S, output: &mut Tui, expr: impl Expression + 'a
|
||||||
) -> Usually<bool> where
|
) -> Usually<bool> where
|
||||||
S: Understand<Tui, ()>
|
S: Interpret<Tui, ()>
|
||||||
+ for<'b>Namespace<'b, bool>
|
+ for<'b>Namespace<'b, bool>
|
||||||
+ for<'b>Namespace<'b, u16>
|
+ for<'b>Namespace<'b, u16>
|
||||||
+ for<'b>Namespace<'b, Color>
|
+ for<'b>Namespace<'b, Color>
|
||||||
|
|
@ -201,7 +201,7 @@ pub fn eval_view_tui <'a, S> (
|
||||||
let arg0 = arg0?.expect("fg: expected arg 0 (color)");
|
let arg0 = arg0?.expect("fg: expected arg 0 (color)");
|
||||||
let color = Namespace::namespace(state, arg0)?.unwrap_or_else(||panic!("fg: {arg0:?}: not a color"));
|
let color = Namespace::namespace(state, arg0)?.unwrap_or_else(||panic!("fg: {arg0:?}: not a color"));
|
||||||
output.place(&fg(color, thunk(move|output: &mut Tui|{
|
output.place(&fg(color, thunk(move|output: &mut Tui|{
|
||||||
state.understand(output, &arg1)?;
|
state.interpret(output, &arg1)?;
|
||||||
// FIXME?: don't max out the used area?
|
// FIXME?: don't max out the used area?
|
||||||
Ok(output.area().into())
|
Ok(output.area().into())
|
||||||
})))
|
})))
|
||||||
|
|
@ -211,7 +211,7 @@ pub fn eval_view_tui <'a, S> (
|
||||||
let arg0 = arg0?.expect("bg: expected arg 0 (color)");
|
let arg0 = arg0?.expect("bg: expected arg 0 (color)");
|
||||||
let color = Namespace::namespace(state, arg0)?.unwrap_or_else(||panic!("bg: {arg0:?}: not a color"));
|
let color = Namespace::namespace(state, arg0)?.unwrap_or_else(||panic!("bg: {arg0:?}: not a color"));
|
||||||
output.place(&bg(color, thunk(move|output: &mut Tui|{
|
output.place(&bg(color, thunk(move|output: &mut Tui|{
|
||||||
state.understand(output, &arg1)?;
|
state.interpret(output, &arg1)?;
|
||||||
// FIXME?: don't max out the used area?
|
// FIXME?: don't max out the used area?
|
||||||
Ok(output.area().into())
|
Ok(output.area().into())
|
||||||
})))
|
})))
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,6 @@ pub(crate) use ::{
|
||||||
|
|
||||||
#[cfg(feature = "sing")] pub extern crate jack;
|
#[cfg(feature = "sing")] pub extern crate jack;
|
||||||
#[cfg(feature = "sing")] pub mod sing;
|
#[cfg(feature = "sing")] pub mod sing;
|
||||||
#[cfg(feature = "sing")] pub use ::jack::{*, contrib::{*, ClosureProcessHandler}};
|
|
||||||
|
|
||||||
#[cfg(feature = "draw")] pub mod draw;
|
#[cfg(feature = "draw")] pub mod draw;
|
||||||
#[cfg(feature = "draw")] pub mod space;
|
#[cfg(feature = "draw")] pub mod space;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
|
pub use ::jack::{*, contrib::{*, ClosureProcessHandler}};
|
||||||
use crate::{*, time::PerfModel};
|
use crate::{*, time::PerfModel};
|
||||||
use ::jack::*;
|
|
||||||
use JackState::*;
|
use JackState::*;
|
||||||
|
|
||||||
/// Trait for thing that has a JACK process callback.
|
/// Trait for thing that has a JACK process callback.
|
||||||
|
|
|
||||||
|
|
@ -136,6 +136,9 @@ impl Origin {
|
||||||
pub fn align <T: Screen> (origin: Origin, a: impl Draw<T>) -> impl Draw<T> {
|
pub fn align <T: Screen> (origin: Origin, a: impl Draw<T>) -> impl Draw<T> {
|
||||||
thunk(move|to: &mut T| { todo!() })
|
thunk(move|to: &mut T| { todo!() })
|
||||||
}
|
}
|
||||||
|
pub fn align_n <T: Screen> (a: impl Draw<T>) -> impl Draw<T> {
|
||||||
|
align(Origin::N, a)
|
||||||
|
}
|
||||||
|
|
||||||
/// A numeric type that can be used as coordinate.
|
/// A numeric type that can be used as coordinate.
|
||||||
///
|
///
|
||||||
|
|
|
||||||
92
src/term.rs
92
src/term.rs
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{*, lang::*, draw::*, space::{*, Split::*}, color::*, text::*, task::*};
|
use crate::{*, lang::*, draw::*, space::{*, Split::*}, color::*, text::*, task::*};
|
||||||
use unicode_width::{UnicodeWidthStr, UnicodeWidthChar};
|
//use unicode_width::{UnicodeWidthStr, UnicodeWidthChar};
|
||||||
use rand::distributions::uniform::UniformSampler;
|
//use rand::distributions::uniform::UniformSampler;
|
||||||
use ::{
|
use ::{
|
||||||
std::{
|
std::{
|
||||||
io::{stdout, Write},
|
io::{stdout, Write},
|
||||||
|
|
@ -18,26 +18,72 @@ use ::{
|
||||||
crossterm::{
|
crossterm::{
|
||||||
ExecutableCommand,
|
ExecutableCommand,
|
||||||
terminal::{EnterAlternateScreen, LeaveAlternateScreen, enable_raw_mode, disable_raw_mode},
|
terminal::{EnterAlternateScreen, LeaveAlternateScreen, enable_raw_mode, disable_raw_mode},
|
||||||
event::{poll, read, Event, KeyEvent, KeyCode, KeyModifiers, KeyEventKind, KeyEventState},
|
//event::{poll, read, Event, KeyEvent, KeyCode, KeyModifiers, KeyEventKind, KeyEventState},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#[macro_export] macro_rules! tui_main {
|
#[macro_export] macro_rules! tui_main {
|
||||||
($state:expr) => {
|
($state:expr) => {
|
||||||
pub fn main () -> Usually<()> {
|
pub fn main () -> Usually<()> {
|
||||||
tengri::exit::Exit::run(|exit|{
|
tengri::exit::Exit::run(|exit|{
|
||||||
let state = Arc::new(RwLock::new($state));
|
let state = Arc::new(RwLock::new($state));
|
||||||
Ok((
|
let input = ::tengri::keys::tui_input(
|
||||||
::tengri::keys::tui_input(
|
exit.as_ref(),
|
||||||
exit.as_ref(), &state, std::time::Duration::from_millis(100)
|
&state,
|
||||||
)?,
|
::std::time::Duration::from_millis(100)
|
||||||
::tengri::term::tui_output(
|
)?;
|
||||||
stdout(), exit.as_ref(), &state, std::time::Duration::from_millis(10)
|
let output = ::tengri::term::tui_output(
|
||||||
)?
|
stdout(),
|
||||||
))
|
exit.as_ref(),
|
||||||
|
&state,
|
||||||
|
::std::time::Duration::from_millis(10)
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[macro_export] macro_rules! tui_keys {
|
||||||
|
(|$self:ident:$State:ty,$input:ident|$body:block) => {
|
||||||
|
impl Apply<TuiEvent, Usually<Self>> for $State {
|
||||||
|
fn apply (&mut $self, $input: &TuiEvent) -> Usually<Self> $body
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export] macro_rules! tui_view {
|
||||||
|
(|$self:ident: $State:ty|$body:block) => {
|
||||||
|
impl View<Tui> for $State {
|
||||||
|
fn view (&$self) -> impl Draw<Tui> $body
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Spawn the TUI output thread which writes colored characters to the terminal.
|
||||||
|
pub fn tui_output <W: Write + Send + Sync + 'static, T: View<Tui> + Send + Sync + 'static> (
|
||||||
|
output: W,
|
||||||
|
exited: &Arc<AtomicBool>,
|
||||||
|
state: &Arc<RwLock<T>>,
|
||||||
|
sleep: Duration
|
||||||
|
) -> Usually<Task> {
|
||||||
|
let state = state.clone();
|
||||||
|
tui_setup()?;
|
||||||
|
let mut backend = CrosstermBackend::new(output);
|
||||||
|
let Size { width, height } = backend.size().expect("get size failed");
|
||||||
|
let mut buffer_a = Buffer::empty(Rect { x: 0, y: 0, width, height });
|
||||||
|
let mut buffer_b = Buffer::empty(Rect { x: 0, y: 0, width, height });
|
||||||
|
Ok(Task::new_sleep(exited.clone(), sleep, move |perf| {
|
||||||
|
let Size { width, height } = backend.size().expect("get size failed");
|
||||||
|
if let Ok(state) = state.try_read() {
|
||||||
|
tui_resize(&mut backend, &mut buffer_a, Rect { x: 0, y: 0, width, height });
|
||||||
|
tui_redraw(&mut backend, &mut buffer_a, &mut buffer_b);
|
||||||
|
}
|
||||||
|
let timer = format!("{:>3.3}ms", perf.used.load(Relaxed));
|
||||||
|
buffer_a.set_string(0, 0, &timer, Style::default());
|
||||||
|
})?)
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Tui(pub Buffer, pub XYWH<u16>);
|
pub struct Tui(pub Buffer, pub XYWH<u16>);
|
||||||
impl Screen for Tui { type Unit = u16; }
|
impl Screen for Tui { type Unit = u16; }
|
||||||
impl Deref for Tui { type Target = Buffer; fn deref (&self) -> &Buffer { &self.0 } }
|
impl Deref for Tui { type Target = Buffer; fn deref (&self) -> &Buffer { &self.0 } }
|
||||||
|
|
@ -520,30 +566,6 @@ fn y_scroll () -> impl Draw<Tui> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Spawn the TUI output thread which writes colored characters to the terminal.
|
|
||||||
pub fn tui_output <W: Write + Send + Sync + 'static, T: Draw<Tui> + Send + Sync + 'static> (
|
|
||||||
output: W,
|
|
||||||
exited: &Arc<AtomicBool>,
|
|
||||||
state: &Arc<RwLock<T>>,
|
|
||||||
sleep: Duration
|
|
||||||
) -> Usually<Task> {
|
|
||||||
let state = state.clone();
|
|
||||||
tui_setup()?;
|
|
||||||
let mut backend = CrosstermBackend::new(output);
|
|
||||||
let Size { width, height } = backend.size().expect("get size failed");
|
|
||||||
let mut buffer_a = Buffer::empty(Rect { x: 0, y: 0, width, height });
|
|
||||||
let mut buffer_b = Buffer::empty(Rect { x: 0, y: 0, width, height });
|
|
||||||
Ok(Task::new_sleep(exited.clone(), sleep, move |perf| {
|
|
||||||
let Size { width, height } = backend.size().expect("get size failed");
|
|
||||||
if let Ok(state) = state.try_read() {
|
|
||||||
tui_resize(&mut backend, &mut buffer_a, Rect { x: 0, y: 0, width, height });
|
|
||||||
tui_redraw(&mut backend, &mut buffer_a, &mut buffer_b);
|
|
||||||
}
|
|
||||||
let timer = format!("{:>3.3}ms", perf.used.load(Relaxed));
|
|
||||||
buffer_a.set_string(0, 0, &timer, Style::default());
|
|
||||||
})?)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn tui_redraw <'b, W: Write> (
|
pub fn tui_redraw <'b, W: Write> (
|
||||||
backend: &mut CrosstermBackend<W>,
|
backend: &mut CrosstermBackend<W>,
|
||||||
mut prev_buffer: &'b mut Buffer,
|
mut prev_buffer: &'b mut Buffer,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue