mirror of
https://codeberg.org/unspeaker/tek.git
synced 2026-10-08 18:56:42 +02:00
axis config: bring failure under test
This commit is contained in:
parent
5aaa0f3e4e
commit
a355e482c7
16 changed files with 1328 additions and 1149 deletions
151
src/conf/mode.rs
Normal file
151
src/conf/mode.rs
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
use crate::*;
|
||||
|
||||
impl_as_mut!(Mode: |self: Mode| self);
|
||||
|
||||
/// Collection of UI modes.
|
||||
///
|
||||
/// ```
|
||||
/// # use tek::*;
|
||||
/// // Empty mode registry:
|
||||
/// let mut state = Modes::default();
|
||||
/// assert_eq!(state.modes_count(), 0);
|
||||
/// assert!(state.modes_get("Foo").is_none());
|
||||
///
|
||||
/// // Add a mode:
|
||||
/// let _ = state.modes_add(&"Foo (name Foo) (info Bar)").unwrap();
|
||||
/// assert_eq!(state.modes_count(), 1);
|
||||
/// assert!(state.modes_get("Foo").is_some());
|
||||
/// ```
|
||||
#[derive(Default, Debug, Clone)]
|
||||
pub struct Modes(pub Arc<RwLock<BTreeMap<Arc<str>, Arc<Mode>>>>);
|
||||
|
||||
/// Group of view and keys definitions.
|
||||
///
|
||||
/// ```
|
||||
/// let mode = tek::Mode::default();
|
||||
/// ```
|
||||
#[derive(Default, Debug)]
|
||||
pub struct Mode {
|
||||
pub path: PathBuf,
|
||||
pub name: Vec<Arc<str>>,
|
||||
pub info: Vec<Arc<str>>,
|
||||
pub view: Vec<Arc<View<Tui, App>>>,
|
||||
pub keys: Vec<Arc<str>>,
|
||||
pub axis: BTreeMap<Arc<str>, (Arc<str>, Arc<str>)>,
|
||||
pub modes: Modes,
|
||||
}
|
||||
|
||||
impl Mode {
|
||||
|
||||
/// Add a definition to the mode.
|
||||
///
|
||||
/// Supported definitions:
|
||||
///
|
||||
/// - (name ...) -> name
|
||||
/// - (info ...) -> description
|
||||
/// - (keys ...) -> key bindings
|
||||
/// - (mode ...) -> submode
|
||||
/// - ... -> view
|
||||
///
|
||||
/// ```
|
||||
/// let mut mode = tek::Mode::default().add("(name hello)").unwrap();
|
||||
/// ```
|
||||
pub fn add (&mut self, dsl: impl Language) -> Usually<&mut Self> {
|
||||
Ok(if let Ok(Some(expr)) = dsl.expr() && let Ok(Some(head)) = expr.head() {
|
||||
let tail = expr.tail()?.map(|x|x.trim()).unwrap_or("");
|
||||
match head {
|
||||
"self" => self.add_mode(tail)?,
|
||||
"bind" => self.add_bind(tail)?,
|
||||
"axis" => self.add_axis(tail)?,
|
||||
"name" => { self.name.push(tail.into()); self },
|
||||
"info" => { self.info.push(tail.into()); self },
|
||||
"view" => { self.view.push(View::new(tail)?.into()); self },
|
||||
_ => { self.view.push(View::new(tail)?.into()); self },
|
||||
}
|
||||
} else if let Ok(Some(word)) = dsl.word() {
|
||||
self.view.push(View::new(word)?.into());
|
||||
self
|
||||
} else {
|
||||
return Err(format!("Mode::add: unexpected: {dsl:?}").into());
|
||||
})
|
||||
}
|
||||
|
||||
fn add_mode (&mut self, tail: &str) -> Usually<&mut Self> {
|
||||
let name = tail.head()?.ok_or("submode: missing name")?;
|
||||
let body = tail.tail()?.ok_or("submode: missing body")?;
|
||||
let mut submode = Mode::default();
|
||||
body.each(&mut submode, |c, s|c.add(s))?;
|
||||
let modes = self.modes.clone();
|
||||
modes.0.write().insert(name.into(), Arc::new(submode));
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
fn add_bind (&mut self, tail: &str) -> Usually<&mut Self> {
|
||||
tail.each(self, |mode: &mut Self, expr: &str|{
|
||||
mode.keys.push(expr.trim().into());
|
||||
Ok(mode)
|
||||
})
|
||||
}
|
||||
|
||||
fn add_axis (&mut self, tail: &str) -> Usually<&mut Self> {
|
||||
let mut axis: Option<Arc<str>> = None;
|
||||
let mut dec: Option<Arc<str>> = None;
|
||||
let mut inc: Option<Arc<str>> = None;
|
||||
tail.each(0, |index: usize, src: &str|if index == 0 {
|
||||
axis = Some(src.into());
|
||||
Ok(1)
|
||||
} else if index == 1 {
|
||||
dec = Some(src.into());
|
||||
Ok(2)
|
||||
} else if index == 2 {
|
||||
inc = Some(src.into());
|
||||
Ok(3)
|
||||
} else {
|
||||
err!("expected (mode (axis [Name] [command] [command])), got: {tail}")
|
||||
})?;
|
||||
if let Some(axis) = axis && let Some(dec) = dec && let Some(inc) = inc {
|
||||
self.keys.push(format!("((dec {axis}) {dec})").into());
|
||||
self.keys.push(format!("((inc {axis}) {inc})").into());
|
||||
Ok(self)
|
||||
} else {
|
||||
err!("expected (mode (axis X Decrement Increment)), got: {tail}")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl ControlAxis {
|
||||
pub fn get_axis <'a> (_: &App, src: impl Language) -> Perhaps<ControlAxis> {
|
||||
eval_word(src, |word|Ok(ControlAxis(word.into())))
|
||||
}
|
||||
}
|
||||
|
||||
impl HasModes for App {
|
||||
fn modes (&self) -> &RwLock<BTreeMap<Arc<str>, Arc<Mode>>> {
|
||||
&self.config.config.modes.0
|
||||
}
|
||||
}
|
||||
|
||||
impl HasModes for ConfigWatcher {
|
||||
fn modes (&self) -> &RwLock<BTreeMap<Arc<str>, Arc<Mode>>> {
|
||||
&self.config.modes.0
|
||||
}
|
||||
}
|
||||
|
||||
impl HasModes for Config {
|
||||
fn modes (&self) -> &RwLock<BTreeMap<Arc<str>, Arc<Mode>>> {
|
||||
&self.modes.0
|
||||
}
|
||||
}
|
||||
|
||||
impl HasModes for Modes {
|
||||
fn modes (&self) -> &RwLock<BTreeMap<Arc<str>, Arc<Mode>>> {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl HasModes for Mode {
|
||||
fn modes (&self) -> &RwLock<BTreeMap<Arc<str>, Arc<Mode>>> {
|
||||
&self.modes.0
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue