use super::*; pub type Modes = Arc, Arc>>>>>; /// A set of currently active view and keys definitions, /// with optional name and description. #[derive(Default, Debug)] pub struct Mode { pub path: PathBuf, pub name: Vec, pub info: Vec, pub view: Vec, pub keys: Vec, pub modes: Modes, } impl Draw for Mode { fn draw (&self, to: &mut TuiOut) { self.content().draw(to) } } impl Mode> { pub fn load_into (modes: &Modes, name: &impl AsRef, body: &impl Dsl) -> Usually<()> { let mut mode = Self::default(); println!("Mode::load_into: {}: {body:?}", name.as_ref()); body.each(|item|mode.load_one(item))?; modes.write().unwrap().insert(name.as_ref().into(), Arc::new(mode)); Ok(()) } fn load_one (&mut self, dsl: impl Dsl) -> Usually<()> { Ok(if let Ok(Some(expr)) = dsl.expr() && let Ok(Some(head)) = expr.head() { println!("Mode::load_one: {head} {:?}", expr.tail()); let tail = expr.tail()?.map(|x|x.trim()).unwrap_or(""); match head { "name" => self.name.push(tail.into()), "info" => self.info.push(tail.into()), "view" => self.view.push(tail.into()), "keys" => tail.each(|expr|{self.keys.push(expr.trim().into()); Ok(())})?, "mode" => if let Some(id) = tail.head()? { Self::load_into(&self.modes, &id, &tail.tail())?; } else { return Err(format!("Mode::load_one: self: incomplete: {expr:?}").into()); }, _ => { return Err(format!("Mode::load_one: unexpected expr: {head:?} {tail:?}").into()) }, }; } else if let Ok(Some(word)) = dsl.word() { self.view.push(word.into()); } else { return Err(format!("Mode::load_one: unexpected: {dsl:?}").into()); }) } }