mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
This commit is contained in:
parent
71c519b711
commit
c63ad4390a
3 changed files with 33 additions and 78 deletions
|
|
@ -7,10 +7,11 @@ macro_rules! cmd_todo { ($msg:literal) => {{ println!($msg); None }}; }
|
||||||
handle!(TuiIn: |self: App, input|self.handle_tui_key_with_history(input));
|
handle!(TuiIn: |self: App, input|self.handle_tui_key_with_history(input));
|
||||||
impl App {
|
impl App {
|
||||||
fn handle_tui_key_with_history (&mut self, input: &TuiIn) -> Perhaps<bool> {
|
fn handle_tui_key_with_history (&mut self, input: &TuiIn) -> Perhaps<bool> {
|
||||||
Ok(if let Some(command) = self.config.keys.handle(self, input)? {
|
Ok(if let Some(binding) = self.config.keys.dispatch(input.event()) {
|
||||||
// FIXME failed commands not persisted in undo history
|
let binding = binding.clone();
|
||||||
let undo = command.clone().execute(self)?;
|
let undo = binding.command.clone().execute(self)?;
|
||||||
self.history.push((command, undo));
|
// FIXME failed commands are not persisted in undo history
|
||||||
|
//self.history.push((binding.command.clone(), undo));
|
||||||
Some(true)
|
Some(true)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use std::error::Error;
|
||||||
|
use Val::*;
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
pub struct App {
|
pub struct App {
|
||||||
/// Must not be dropped for the duration of the process
|
/// Must not be dropped for the duration of the process
|
||||||
|
|
@ -329,26 +331,28 @@ pub struct Configuration<T: Dsl> {
|
||||||
/// View definition
|
/// View definition
|
||||||
pub view: T,
|
pub view: T,
|
||||||
// Input keymap
|
// Input keymap
|
||||||
pub keys: EventMap<TuiEvent, T>,
|
pub keys: EventMap<TuiEvent, AppCommand>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Dsl> Configuration<T> {
|
impl<T: Dsl + From<T::Exp>> Configuration<T> {
|
||||||
pub fn from_path (path: &impl AsRef<Path>, _watch: bool) -> Usually<Self> where T: for<'a> From<&'a str> {
|
pub fn from_path (path: &impl AsRef<Path>, _watch: bool) -> Usually<Self> where T: for<'a> From<&'a str> {
|
||||||
let mut dsl = T::from(read_and_leak(path.as_ref())?);
|
let mut dsl = T::from(read_and_leak(path.as_ref())?);
|
||||||
let mut name: Option<T::Exp> = None;
|
let mut name: Option<T> = None;
|
||||||
let mut info: Option<T::Exp> = None;
|
let mut info: Option<T> = None;
|
||||||
let mut view: Option<T::Exp> = None;
|
let mut view: Option<T> = None;
|
||||||
let mut keys: Option<T::Exp> = None;
|
let mut keys: Option<T> = None;
|
||||||
dsl.exp_each(|form|Ok(match form.exp_head().dsl() {
|
while let Some(form) = dsl.exp_next() {
|
||||||
Val::Key(key) => match key.as_ref() {
|
match form.head().val() {
|
||||||
"name" => name = Some(form.exp_tail()),
|
Key(key) => match key.as_ref() {
|
||||||
"info" => info = Some(form.exp_tail()),
|
"name" => name = Some(form.tail().into()),
|
||||||
"keys" => keys = Some(form.exp_tail()),
|
"info" => info = Some(form.tail().into()),
|
||||||
"view" => view = Some(form.exp_tail()),
|
"keys" => keys = Some(form.tail().into()),
|
||||||
_ => return Err(format!("(e3) unexpected key {key:?} in {form:?}").into())
|
"view" => view = Some(form.tail().into()),
|
||||||
},
|
_ => return Err(format!("(e3) unexpected key {key:?} in {form:?}").into())
|
||||||
_ => return Err(format!("(e2) unexpected exp {form :?}").into())
|
},
|
||||||
}))?;
|
_ => return Err(format!("(e2) unexpected exp {form :?}").into())
|
||||||
|
}
|
||||||
|
}
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
path: path.as_ref().into(),
|
path: path.as_ref().into(),
|
||||||
info: info.map(Self::parse_info).flatten(),
|
info: info.map(Self::parse_info).flatten(),
|
||||||
|
|
@ -358,68 +362,18 @@ impl<T: Dsl> Configuration<T> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
fn parse_name (dsl: T) -> Option<Arc<str>> {
|
fn parse_name (dsl: T) -> Option<Arc<str>> {
|
||||||
dsl.str().map(Into::into)
|
dsl.str().map(|x|x.as_ref().into())
|
||||||
}
|
}
|
||||||
fn parse_info (dsl: T) -> Option<Arc<str>> {
|
fn parse_info (dsl: T) -> Option<Arc<str>> {
|
||||||
dsl.str().map(Into::into)
|
dsl.str().map(|x|x.as_ref().into())
|
||||||
}
|
}
|
||||||
fn parse_view (dsl: Option<T>) -> Usually<T> {
|
fn parse_view (dsl: Option<T>) -> Usually<T> {
|
||||||
match dsl { Some(view) => Ok(view), _ => Err(format!("missing view definition").into()) }
|
dsl.ok_or_else(||format!("missing view definition").into())
|
||||||
}
|
}
|
||||||
fn parse_keys (base: &impl AsRef<Path>, dsl: Option<T>) -> Usually<EventMap<TuiIn, T>> {
|
fn parse_keys (base: &impl AsRef<Path>, dsl: Option<T>) -> Usually<EventMap<TuiEvent, AppCommand>> {
|
||||||
let mut map = EventMap::default();
|
EventMap::from_dsl(dsl.ok_or_else(||->Box<dyn Error>{
|
||||||
let mut keys = if let Some(keys) = dsl { keys } else {
|
format!("missing keys definition").into()
|
||||||
return Err(format!("missing keys definition").into())
|
})?)
|
||||||
};
|
|
||||||
keys.exp_each(|form|Ok(match form.exp_head().dsl() {
|
|
||||||
Val::Sym(s) if s.as_ref() == "layer" =>
|
|
||||||
Self::parse_keys_layer(&mut map, base, form.exp_tail()),
|
|
||||||
Val::Sym(s) if s.as_ref() == "layer-if" =>
|
|
||||||
Self::parse_keys_layer_if(&mut map, base, form.exp_tail()),
|
|
||||||
x =>
|
|
||||||
return Err(format!("(e3) unexpected {x:?} in {form:?}").into())
|
|
||||||
}))?;
|
|
||||||
Ok(map)
|
|
||||||
}
|
|
||||||
fn parse_keys_layer (map: &mut EventMap<TuiIn, T>, base: &impl AsRef<Path>, exp: &T) {
|
|
||||||
let next = exp.peek().map(|x|x.val());
|
|
||||||
if let Some(Val::Str(path)) = next {
|
|
||||||
let path = base.as_ref().parent().unwrap().join(unquote(path));
|
|
||||||
if !std::fs::exists(&path)? {
|
|
||||||
return Err(format!("(e5) not found: {path:?}").into())
|
|
||||||
}
|
|
||||||
map.add_layer(read_and_leak(path)?.into());
|
|
||||||
print!("layer:\n path: {:?}...", exp.0.0.trim());
|
|
||||||
println!("ok");
|
|
||||||
} else {
|
|
||||||
return Err(format!("(e4) unexpected non-string {next:?}").into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn parse_keys_layer_if (map: &mut EventMap<TuiIn, T>, base: &impl AsRef<Path>, exp: &T) {
|
|
||||||
let next = exp.next().map(|x|x.val());
|
|
||||||
let cond = if let Some(Val::Sym(sym)) = next {
|
|
||||||
leak(sym)
|
|
||||||
} else {
|
|
||||||
return Err(format!("(e4) unexpected non-symbol {next:?}").into())
|
|
||||||
};
|
|
||||||
|
|
||||||
let next = exp.peek().map(|x|x.val());
|
|
||||||
if let Some(Val::Str(path)) = next {
|
|
||||||
let path = base.as_ref().parent().unwrap().join(unquote(path));
|
|
||||||
if !std::fs::exists(&path)? {
|
|
||||||
return Err(format!("(e5) not found: {path:?}").into())
|
|
||||||
}
|
|
||||||
print!("layer-if:\n cond: {cond}\n path: {path:?}...");
|
|
||||||
let keys = read_and_leak(path)?.into();
|
|
||||||
println!("ok");
|
|
||||||
//map.add_layer_if(
|
|
||||||
//Box::new(move |state: &App|Take::take_or_fail(
|
|
||||||
//state, exp, ||"missing input layer conditional"
|
|
||||||
//)), keys
|
|
||||||
//);
|
|
||||||
} else {
|
|
||||||
return Err(format!("(e4) unexpected non-symbol {next:?}").into())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
2
deps/tengri
vendored
2
deps/tengri
vendored
|
|
@ -1 +1 @@
|
||||||
Subproject commit 7b67d29c012f2d39a5d9d2fcd840417c90256503
|
Subproject commit d72a3b5b8f3f98573a194b45961b6dd5cc8f8e5f
|
||||||
Loading…
Add table
Add a link
Reference in a new issue