prettyprint error from main; fix some doctests

This commit is contained in:
i do not exist 2026-08-30 20:18:29 +03:00
parent ab6959a84f
commit 30b3802b56
4 changed files with 67 additions and 63 deletions

View file

@ -88,6 +88,12 @@ pub fn modes_add <'a> (modes: &Modes, expr: impl Language) -> UsuallyRef<'a, ()>
Ok(())
}
impl AsMut<Mode> for Mode {
fn as_mut (&mut self) -> &mut Self {
self
}
}
/// Add a definition to the mode.
///
/// Supported definitions:
@ -99,10 +105,9 @@ pub fn modes_add <'a> (modes: &Modes, expr: impl Language) -> UsuallyRef<'a, ()>
/// - ... -> view
///
/// ```
/// let mut mode: tek::Mode<std::sync::Arc<str>> = Default::default();
/// mode.add("(name hello)").unwrap();
/// let mut mode: tek::Mode = tek::mode_add(tek::Mode::default(), "(name hello)").unwrap();
/// ```
pub fn mode_add (mut mode: Mode, dsl: impl Language) -> Usually<Mode> {
pub fn mode_add <T: AsMut<Mode>> (mut mode: T, dsl: impl Language) -> Usually<T> {
Ok(if let Ok(Some(expr)) = dsl.expr() && let Ok(Some(head)) = expr.head() {
//println!("Mode::add: {head} {:?}", expr.tail());
let tail = expr.tail()?.map(|x|x.trim()).unwrap_or("");
@ -112,23 +117,23 @@ pub fn mode_add (mut mode: Mode, dsl: impl Language) -> Usually<Mode> {
let body = tail.tail()?.ok_or("submode: missing body")?;
let submode = Mode::default();
let submode = body.each(submode, |c,s|mode_add(c,s))?;
let modes = mode.modes.clone();
let modes = mode.as_mut().modes.clone();
modes.0.try_write().unwrap().insert(name.into(), Arc::new(submode));
mode
},
"keys" => {
tail.each(mode, |mut mode: Mode, expr: &str|{
mode.keys.push(expr.trim().into());
tail.each(mode, |mut mode: T, expr: &str|{
mode.as_mut().keys.push(expr.trim().into());
Ok(mode)
})?
},
"name" => { mode.name.push(tail.into()); mode },
"info" => { mode.info.push(tail.into()); mode },
"view" => { mode.view.push(View::new(tail)?.into()); mode },
_ => { mode.view.push(View::new(tail)?.into()); mode },
"name" => { mode.as_mut().name.push(tail.into()); mode },
"info" => { mode.as_mut().info.push(tail.into()); mode },
"view" => { mode.as_mut().view.push(View::new(tail)?.into()); mode },
_ => { mode.as_mut().view.push(View::new(tail)?.into()); mode },
}
} else if let Ok(Some(word)) = dsl.word() {
mode.view.push(View::new(word)?.into());
mode.as_mut().view.push(View::new(word)?.into());
mode
} else {
return Err(format!("Mode::add: unexpected: {dsl:?}").into());
@ -141,7 +146,7 @@ pub fn load_bind <'a> (binds: &Binds, expr: impl Language) -> UsuallyRef<'a, ()>
let body = expr.tail()?.unwrap_or("");
binds.try_write().unwrap().insert(name.into(), {
let mut map = Bind::new();
body.each((), |_, item: &str|if item.expr().head() == Ok(Some("see")) {
body.each((), |_, item: &str|if matches!(item.expr().head(), Ok(Some("see"))) {
// TODO
Ok(())
} else if let Ok(Some(_word)) = item.expr().head().word() {
@ -172,22 +177,15 @@ pub fn load_bind <'a> (binds: &Binds, expr: impl Language) -> UsuallyRef<'a, ()>
/// Configuration: mode, view, and bind definitions.
///
/// ```
/// let config = tek::Config::default();
/// ```
///
/// ```
/// // Some dizzle.
/// // What indentation to use here lol?
/// let source = stringify!((mode :menu (name Menu)
/// (info Mode selector.) (keys :axis/y :confirm)
/// (view (bg (g 0) (bsp/s :ports/out
/// (bsp/n :ports/in
/// (bg (g 30) (bsp/s (fixed/y 7 :logo)
/// (fill :dialog/menu)))))))));
/// // Add this definition to the config and try to load it.
/// // A "mode" is basically a state machine
/// // with associated input and output definitions.
/// tek::Config::default().add(&source).unwrap().get_mode(":menu").unwrap();
/// let source = stringify!(
/// (mode :menu (name Menu)
/// (info Mode selector.) (keys :axis/y :confirm)
/// (view (bg (g 0) (bsp/s :ports/out
/// (bsp/n :ports/in
/// (bg (g 30) (bsp/s (fixed/y 7 :logo)
/// (fill :dialog/menu)))))))));
/// let config: tek::Config = tek::modes_add(tek::Config::default(), source).unwrap();
/// let mode: tek::Mode = config.get_mode(":menu").unwrap();
/// ```
#[derive(Default, Debug)]
pub struct Config {
@ -221,7 +219,7 @@ pub struct Modes(Arc<RwLock<BTreeMap<Arc<str>, Arc<Mode>>>>);
/// Group of view and keys definitions.
///
/// ```
/// let mode = tek::Mode::<std::sync::Arc<str>>::default();
/// let mode = tek::Mode::default();
/// ```
#[derive(Default, Debug)]
pub struct Mode {
@ -279,6 +277,7 @@ impl View<Tui, App> {
Usually<Arc<Box<dyn Fn(&App, &mut Tui)->Drawn<u16> + Send + Sync>>>
{
Ok(Arc::new(if let Some(head) = expr.head()? && let Some(ns) = head.split('/').next() {
match ns {
"when" => {
@ -452,27 +451,31 @@ impl View<Tui, App> {
},
"fg" | "bg" => {
let color = expr.nth(1)?.ok_or_else(||Box::<dyn Error>::from("{}: no arg1: color"))?;
let color = Arc::from(expr.nth(1)?.ok_or_else(||Box::<dyn Error>::from("{}: no arg1: color"))?);
let color = move|state: &App|state.namespace(&color);
let thunk = Self::compile(expr.nth(2)?.ok_or_else(||Box::<dyn Error>::from("either: no arg2: thunk"))?)?;
todo!()
match ns {
"fg" => Self::boxed(move|state, screen|fg(
color(state)?.unwrap_or_default(), draw(|screen|thunk(state, screen))
).draw(screen)),
"bg" => Self::boxed(move|state, screen|bg(
color(state)?.unwrap_or_default(), draw(|screen|thunk(state, screen))
).draw(screen)),
_ => unreachable!()
}
},
"text" => {
todo!()
let text: Arc<str> = Arc::from(expr.tail()?.unwrap_or_default());
Self::boxed(move|_state, screen|{
text.draw(screen)
})
},
//"align" => Self::boxed(move|state, screen|kw_align(state, screen, expr)),
//"full" => Self::boxed(move|state, screen|kw_full(state, screen, expr)),
//"exact" => Self::boxed(move|state, screen|kw_exact(state, screen, expr)),
//"min" => Self::boxed(move|state, screen|kw_min(state, screen, expr)),
//"max" => Self::boxed(move|state, screen|kw_max(state, screen, expr)),
//"push" => Self::boxed(move|state, screen|kw_push(state, screen, expr)),
//"pull" => Self::boxed(move|state, screen|kw_pull(state, screen, expr)),
//"text" => Self::boxed(move|state, screen|kw_tui_text(state, screen, expr)),
//"fg" => Self::boxed(move|state, screen|kw_tui_fg(state, screen, expr)),
//"bg" => Self::boxed(move|state, screen|kw_tui_bg(state, screen, expr)),
_ => return Err(format!("compile_expr: unexpected: {expr:?}").into())
}
} else {
return Err(format!("compile_expr: invalid expression: {expr:?}").into())
}))
@ -503,13 +506,13 @@ impl View<Tui, App> {
},
Some(":dialog") => Self::boxed(move|state, to|draw_dialog(to, word.split("/").skip(1), state)),
Some(":templates") => Self::boxed(move|state, to|view_templates(state).draw(to)),
Some(":sessions") => Self::boxed(move|state, to|view_sessions().draw(to)),
Some(":sessions") => Self::boxed(move|_, to|view_sessions().draw(to)),
Some(":browse/title") => Self::boxed(move|state, to|view_browse_title(state).draw(to)),
Some(":device") => Self::boxed(move|state, to|view_device(state).draw(to)),
Some(":status") => Self::boxed(move|state, to|"TODO: Status Bar".draw(to)),
Some(":editor") => Self::boxed(move|state, to|"TODO Editor".draw(to)),
Some(":transport") => Self::boxed(move|state, to|view_transport(true, "", "", "").draw(to)),
Some(":debug") => Self::boxed(move|state, to|format!("[{:?}]", to.area()).exact_h(1).draw(to)),
Some(":status") => Self::boxed(move|_, to|"TODO: Status Bar".draw(to)),
Some(":editor") => Self::boxed(move|_, to|"TODO Editor".draw(to)),
Some(":transport") => Self::boxed(move|_, to|view_transport(true, "", "", "").draw(to)),
Some(":debug") => Self::boxed(move|_, to|format!("[{:?}]", to.area()).exact_h(1).draw(to)),
Some(_) => Self::boxed(move|state, to|if let Some(view) = state.config.get_view(word.as_ref()) {
(view.render)(state, to)
} else {
@ -632,7 +635,9 @@ mod bind {
/// An map of input events (e.g. [TuiEvent]) to [Binding]s.
///
/// ```
/// let lang = "(@x (nop)) (@y (nop) (nop))";
/// let lang = stringify!(
/// (@x (nop))
/// (@y (nop) (nop)));
/// let bind = tek::Bind::<tek::tengri::TuiEvent, std::sync::Arc<str>>::load(&lang).unwrap();
/// assert_eq!(bind.query(&'x'.into()).map(|x|x.len()), Some(1));
/// //assert_eq!(bind.query(&'y'.into()).map(|x|x.len()), Some(2));

View file

@ -1,8 +1,8 @@
(view :logo (text tek))
(view :browse (bsp/s
(padding 3 1 :browse-title)
(enclose (fg (g 96)) browser)))
(pad 3 1 :browse-title)
(fg (g 96) browser))
(mode :transport
(name Transport)

View file

@ -26,11 +26,11 @@ fn main () -> Usually<()> {
_guard
};
tengri::Tui::setup_panic();
#[cfg(feature = "cli")] {
Config::watched(crate::cli::run_with_config)?;
}
#[cfg(not(feature = "cli"))] {
Config::watched(run_new_plain)?;
#[cfg(feature = "cli")] let outcome = Config::watched(crate::cli::run_with_config);
#[cfg(not(feature = "cli"))] let outcome = Config::watched(run_new_plain);
if let Err(e) = outcome {
println!("{e:#?}");
std::process::exit(1);
}
Ok(())
}
@ -334,16 +334,15 @@ mod app {
///
/// ```
/// let mut proj = tek::Arrangement::default();
/// proj.jack = tek::tengri::Jack::new(&"test_tek").expect("failed to connect to jack");
/// let mut conf = std::sync::Arc::new(tek::Config::default());
/// conf.add("(mode hello)");
/// let tek = tek::App::new(None, proj, conf, "hello");
/// proj.jack = tek::tengri::Jack::new(&"test_tek").expect("failed to connect to jack");
/// let mut conf = tek::config_load(tek::Config::default(), "(mode hello)").unwrap();
/// let tek = tek::App::new(None, proj, conf.into(), "hello");
/// ```
pub fn new (
exit: Option<Exit>,
exit: Option<Exit>,
project: Arrangement,
config: Arc<Config>,
mode: impl AsRef<str>
config: Arc<Config>,
mode: impl AsRef<str>
) -> Self {
App {
exit: exit.unwrap_or_default(),