mirror of
https://codeberg.org/unspeaker/tek.git
synced 2026-09-18 12:56:42 +02:00
prettyprint error from main; fix some doctests
This commit is contained in:
parent
ab6959a84f
commit
30b3802b56
4 changed files with 67 additions and 63 deletions
|
|
@ -88,6 +88,12 @@ pub fn modes_add <'a> (modes: &Modes, expr: impl Language) -> UsuallyRef<'a, ()>
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AsMut<Mode> for Mode {
|
||||||
|
fn as_mut (&mut self) -> &mut Self {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Add a definition to the mode.
|
/// Add a definition to the mode.
|
||||||
///
|
///
|
||||||
/// Supported definitions:
|
/// Supported definitions:
|
||||||
|
|
@ -99,10 +105,9 @@ pub fn modes_add <'a> (modes: &Modes, expr: impl Language) -> UsuallyRef<'a, ()>
|
||||||
/// - ... -> view
|
/// - ... -> view
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let mut mode: tek::Mode<std::sync::Arc<str>> = Default::default();
|
/// let mut mode: tek::Mode = tek::mode_add(tek::Mode::default(), "(name hello)").unwrap();
|
||||||
/// mode.add("(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() {
|
Ok(if let Ok(Some(expr)) = dsl.expr() && let Ok(Some(head)) = expr.head() {
|
||||||
//println!("Mode::add: {head} {:?}", expr.tail());
|
//println!("Mode::add: {head} {:?}", expr.tail());
|
||||||
let tail = expr.tail()?.map(|x|x.trim()).unwrap_or("");
|
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 body = tail.tail()?.ok_or("submode: missing body")?;
|
||||||
let submode = Mode::default();
|
let submode = Mode::default();
|
||||||
let submode = body.each(submode, |c,s|mode_add(c,s))?;
|
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));
|
modes.0.try_write().unwrap().insert(name.into(), Arc::new(submode));
|
||||||
mode
|
mode
|
||||||
},
|
},
|
||||||
"keys" => {
|
"keys" => {
|
||||||
tail.each(mode, |mut mode: Mode, expr: &str|{
|
tail.each(mode, |mut mode: T, expr: &str|{
|
||||||
mode.keys.push(expr.trim().into());
|
mode.as_mut().keys.push(expr.trim().into());
|
||||||
Ok(mode)
|
Ok(mode)
|
||||||
})?
|
})?
|
||||||
},
|
},
|
||||||
"name" => { mode.name.push(tail.into()); mode },
|
"name" => { mode.as_mut().name.push(tail.into()); mode },
|
||||||
"info" => { mode.info.push(tail.into()); mode },
|
"info" => { mode.as_mut().info.push(tail.into()); mode },
|
||||||
"view" => { mode.view.push(View::new(tail)?.into()); mode },
|
"view" => { mode.as_mut().view.push(View::new(tail)?.into()); mode },
|
||||||
_ => { mode.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() {
|
} 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
|
mode
|
||||||
} else {
|
} else {
|
||||||
return Err(format!("Mode::add: unexpected: {dsl:?}").into());
|
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("");
|
let body = expr.tail()?.unwrap_or("");
|
||||||
binds.try_write().unwrap().insert(name.into(), {
|
binds.try_write().unwrap().insert(name.into(), {
|
||||||
let mut map = Bind::new();
|
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
|
// TODO
|
||||||
Ok(())
|
Ok(())
|
||||||
} else if let Ok(Some(_word)) = item.expr().head().word() {
|
} 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.
|
/// Configuration: mode, view, and bind definitions.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let config = tek::Config::default();
|
/// let source = stringify!(
|
||||||
/// ```
|
/// (mode :menu (name Menu)
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// // Some dizzle.
|
|
||||||
/// // What indentation to use here lol?
|
|
||||||
/// let source = stringify!((mode :menu (name Menu)
|
|
||||||
/// (info Mode selector.) (keys :axis/y :confirm)
|
/// (info Mode selector.) (keys :axis/y :confirm)
|
||||||
/// (view (bg (g 0) (bsp/s :ports/out
|
/// (view (bg (g 0) (bsp/s :ports/out
|
||||||
/// (bsp/n :ports/in
|
/// (bsp/n :ports/in
|
||||||
/// (bg (g 30) (bsp/s (fixed/y 7 :logo)
|
/// (bg (g 30) (bsp/s (fixed/y 7 :logo)
|
||||||
/// (fill :dialog/menu)))))))));
|
/// (fill :dialog/menu)))))))));
|
||||||
/// // Add this definition to the config and try to load it.
|
/// let config: tek::Config = tek::modes_add(tek::Config::default(), source).unwrap();
|
||||||
/// // A "mode" is basically a state machine
|
/// let mode: tek::Mode = config.get_mode(":menu").unwrap();
|
||||||
/// // with associated input and output definitions.
|
|
||||||
/// tek::Config::default().add(&source).unwrap().get_mode(":menu").unwrap();
|
|
||||||
/// ```
|
/// ```
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
|
|
@ -221,7 +219,7 @@ pub struct Modes(Arc<RwLock<BTreeMap<Arc<str>, Arc<Mode>>>>);
|
||||||
/// Group of view and keys definitions.
|
/// Group of view and keys definitions.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let mode = tek::Mode::<std::sync::Arc<str>>::default();
|
/// let mode = tek::Mode::default();
|
||||||
/// ```
|
/// ```
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
pub struct Mode {
|
pub struct Mode {
|
||||||
|
|
@ -279,6 +277,7 @@ impl View<Tui, App> {
|
||||||
Usually<Arc<Box<dyn Fn(&App, &mut Tui)->Drawn<u16> + Send + Sync>>>
|
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() {
|
Ok(Arc::new(if let Some(head) = expr.head()? && let Some(ns) = head.split('/').next() {
|
||||||
|
|
||||||
match ns {
|
match ns {
|
||||||
|
|
||||||
"when" => {
|
"when" => {
|
||||||
|
|
@ -452,27 +451,31 @@ impl View<Tui, App> {
|
||||||
},
|
},
|
||||||
|
|
||||||
"fg" | "bg" => {
|
"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"))?)?;
|
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" => {
|
"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())
|
_ => return Err(format!("compile_expr: unexpected: {expr:?}").into())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return Err(format!("compile_expr: invalid expression: {expr:?}").into())
|
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(":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(":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(":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(":device") => Self::boxed(move|state, to|view_device(state).draw(to)),
|
||||||
Some(":status") => Self::boxed(move|state, to|"TODO: Status Bar".draw(to)),
|
Some(":status") => Self::boxed(move|_, to|"TODO: Status Bar".draw(to)),
|
||||||
Some(":editor") => Self::boxed(move|state, to|"TODO Editor".draw(to)),
|
Some(":editor") => Self::boxed(move|_, to|"TODO Editor".draw(to)),
|
||||||
Some(":transport") => Self::boxed(move|state, to|view_transport(true, "", "", "").draw(to)),
|
Some(":transport") => Self::boxed(move|_, to|view_transport(true, "", "", "").draw(to)),
|
||||||
Some(":debug") => Self::boxed(move|state, to|format!("[{:?}]", to.area()).exact_h(1).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()) {
|
Some(_) => Self::boxed(move|state, to|if let Some(view) = state.config.get_view(word.as_ref()) {
|
||||||
(view.render)(state, to)
|
(view.render)(state, to)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -632,7 +635,9 @@ mod bind {
|
||||||
/// An map of input events (e.g. [TuiEvent]) to [Binding]s.
|
/// 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();
|
/// 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(&'x'.into()).map(|x|x.len()), Some(1));
|
||||||
/// //assert_eq!(bind.query(&'y'.into()).map(|x|x.len()), Some(2));
|
/// //assert_eq!(bind.query(&'y'.into()).map(|x|x.len()), Some(2));
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
(view :logo (text tek))
|
(view :logo (text tek))
|
||||||
|
|
||||||
(view :browse (bsp/s
|
(view :browse (bsp/s
|
||||||
(padding 3 1 :browse-title)
|
(pad 3 1 :browse-title)
|
||||||
(enclose (fg (g 96)) browser)))
|
(fg (g 96) browser))
|
||||||
|
|
||||||
(mode :transport
|
(mode :transport
|
||||||
(name Transport)
|
(name Transport)
|
||||||
|
|
|
||||||
15
src/tek.rs
15
src/tek.rs
|
|
@ -26,11 +26,11 @@ fn main () -> Usually<()> {
|
||||||
_guard
|
_guard
|
||||||
};
|
};
|
||||||
tengri::Tui::setup_panic();
|
tengri::Tui::setup_panic();
|
||||||
#[cfg(feature = "cli")] {
|
#[cfg(feature = "cli")] let outcome = Config::watched(crate::cli::run_with_config);
|
||||||
Config::watched(crate::cli::run_with_config)?;
|
#[cfg(not(feature = "cli"))] let outcome = Config::watched(run_new_plain);
|
||||||
}
|
if let Err(e) = outcome {
|
||||||
#[cfg(not(feature = "cli"))] {
|
println!("{e:#?}");
|
||||||
Config::watched(run_new_plain)?;
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -335,9 +335,8 @@ mod app {
|
||||||
/// ```
|
/// ```
|
||||||
/// let mut proj = tek::Arrangement::default();
|
/// let mut proj = tek::Arrangement::default();
|
||||||
/// proj.jack = tek::tengri::Jack::new(&"test_tek").expect("failed to connect to jack");
|
/// proj.jack = tek::tengri::Jack::new(&"test_tek").expect("failed to connect to jack");
|
||||||
/// let mut conf = std::sync::Arc::new(tek::Config::default());
|
/// let mut conf = tek::config_load(tek::Config::default(), "(mode hello)").unwrap();
|
||||||
/// conf.add("(mode hello)");
|
/// let tek = tek::App::new(None, proj, conf.into(), "hello");
|
||||||
/// let tek = tek::App::new(None, proj, conf, "hello");
|
|
||||||
/// ```
|
/// ```
|
||||||
pub fn new (
|
pub fn new (
|
||||||
exit: Option<Exit>,
|
exit: Option<Exit>,
|
||||||
|
|
|
||||||
2
tengri
2
tengri
|
|
@ -1 +1 @@
|
||||||
Subproject commit 8e7286e409ec6d4ac4382856ff93767a4758e11e
|
Subproject commit 7f067b848fb504feb312033bf0a485bb2ccacef6
|
||||||
Loading…
Add table
Add a link
Reference in a new issue