smizzle
Some checks are pending
/ build (push) Waiting to run

This commit is contained in:
facile pop culture reference 2026-08-19 18:21:34 +03:00
parent a9f2fa2cdd
commit 291ab63224
11 changed files with 98 additions and 96 deletions

View file

@ -1,6 +1,9 @@
export CARGO_INCREMENTAL := '0'
export RUSTFLAGS := '-Zmacro-backtrace -Cinstrument-coverage'
export RUSTDOCFLAGS := '-Zmacro-backtrace -Cinstrument-coverage'
export LLVM_PROFILE_FILE := "cov/cargo-test-%p-%m.profraw"
grcov-binary := "--binary-path ./target/coverage/deps/"
grcov-ignore := "--ignore-not-existing --ignore '../*' --ignore \"/*\" --ignore 'target/*'"
grcov-binary := "--binary-path ./target/coverage/build/tengri"
grcov-ignore := ""#--ignore-not-existing --ignore '../*' --ignore \"/*\" --ignore 'target/*'"
[private]
default:
@ -10,23 +13,19 @@ bacon:
bacon -s
cov:
CARGO_INCREMENTAL=0 RUSTFLAGS='-Cinstrument-coverage' \
time cargo test -j4 --workspace --profile coverage
rm -rf target/coverage/html || true
time grcov . -s . {{grcov-binary}} {{grcov-ignore}} -t html -o target/coverage/html && reset
cov-md:
CARGO_INCREMENTAL=0 RUSTFLAGS='-Cinstrument-coverage' \
time cargo test -j4 --workspace --profile coverage
time grcov . -s . {{grcov-binary}} {{grcov-ignore}} -t markdown | sort
cov-md-ci:
CARGO_INCREMENTAL=0 RUSTFLAGS='-Cinstrument-coverage' \
time cargo test -j4 --workspace --profile coverage -- --skip test_tui_engine
time grcov . -s . {{grcov-binary}} {{grcov-ignore}} -t markdown | sort
doc:
CARGO_INCREMENTAL=0 RUSTFLAGS='-Cinstrument-coverage' RUSTDOCFLAGS='-Cinstrument-coverage' \
cargo doc
mode MODE:

View file

@ -1,14 +1,15 @@
default_job = "check-all"
default_job = "coverage"
env.CARGO_TERM_COLOR = "always"
env.RUSTFLAGS = "-Zmacro-backtrace"
[keybindings]
c = "job:check"
C = "job:clippy"
d = "job:doc"
D = "job:doc-open"
t = "job:test"
T = "job:nextest"
l = "job:clippy"
T = "job:coverage"
[jobs]
@ -27,6 +28,11 @@ command = ["cargo", "test"]
need_stdout = true
watch = ["tengri"]
[jobs.coverage]
command = ["just", "cov"]
need_stdout = true
watch = ["src", "proc"]
[jobs.doc]
command = ["cargo", "doc", "--no-deps"]
need_stdout = false

2
dizzle

@ -1 +1 @@
Subproject commit 648be30918bef0a975bd225c0499911aaa88bc13
Subproject commit 3c80e3bb8c1d104f61f212b4961d927ac845e289

View file

@ -27,7 +27,7 @@ tui_keys!(self: State, input {
});
tui_view!(self: State {
let title = "Demo [Mode 01]";
let title = "Demo [Mode 01";
let items = self.history.iter().take(10).map(|x|format!("{x:?}")).join("\n");
let history = format!("History: {}\n{items}", self.history.len());
let cursor = format!("Counter: {}", self.cursor);

View file

@ -23,7 +23,7 @@ tui_view!(self: State {
let heading = format!("Demo [Mode 02]\nExample {}/{}\nSize {:?}", index, VIEWS.len(), &wh);
let title = bg(Color::Rgb(60, 10, 10), heading);
let code = bg(Color::Rgb(10, 60, 10), format!("Source:\n{}", src).max_h(10));
let widget = draw(move|to: &mut Tui|self.interpret(to, &src)); // FIXME this forcefills
let widget = draw(move|to: &mut Tui|self.interpret(to, src)); // FIXME this forcefills
let sidebar = bg(Color::Rgb(20, 20, 20), north(code, title)).max_w(40);
let content = bg(Color::Rgb(64, 64, 64), widget);
east(sidebar, ShowSizeOf(content))
@ -31,22 +31,8 @@ tui_view!(self: State {
//self.size.of(bg(Color::Rgb(10, 10, 10), east(sidebar, content)).full_w())
});
impl_keywords!(Tui, XYWH<u16>, State [
kw_when,
kw_either,
kw_split,
kw_align,
kw_exact,
kw_min,
kw_max,
kw_push,
kw_tui_text,
kw_tui_fg,
kw_tui_bg
]);
impl<'a> Interpret<'a, Tui, Option<XYWH<u16>>> for State {
fn interpret_word <L: Language<'a> + ?Sized> (&'a self, to: &mut Tui, lang: &'a L)
fn interpret_word <L: Language + ?Sized> (&'a self, to: &mut Tui, lang: &'a L)
-> Drawn<'a, u16>
{
match lang.src()? {
@ -56,13 +42,20 @@ impl<'a> Interpret<'a, Tui, Option<XYWH<u16>>> for State {
src => todo!("src: {src:?}")
}
}
fn interpret_expr <L: Language<'a> + ?Sized> (&self, to: &mut Tui, src: &'a L)
fn interpret_expr <L: Language + ?Sized> (&'a self, to: &mut Tui, src: &'a L)
-> Drawn<'a, u16>
{
if let Some(area) = self.keyword(to, src)? {
Ok(Some(area))
if let Some(src) = src.src()? {
interpret_keyword!(self, to, src, [
kw_when, kw_either,
kw_split, kw_align,
kw_exact, kw_min, kw_max,
kw_push, kw_pull,
kw_tui_text, kw_tui_fg, kw_tui_bg
]);
Err(format!("interpret_expr: unexpected: {src:?}").into())
} else {
Err(format!("App::interpret_expr: unexpected: {src:?}").into())
Err(format!("interpret_expr: no keyword: {src:?}").into())
}
}
}

View file

@ -29,12 +29,12 @@ pub enum Pad<'a, S: Screen, I: Draw<'a, S>, X: Into<Option<S::Unit>>> {
}
/// ```
/// # fn test_layout_full () -> Usually<()> {
/// # use ::tengri::*; fn test_layout_full () -> Usually<()> {
/// assert_eq!(check_layout("1")?, Some(XYWH(1u16, 1, 1, 1)));
/// assert_eq!(check_layout("1".full_w())?, Some(XYWH(1u16, 1, 80, 1)));
/// assert_eq!(check_layout("1".full_h())?, Some(XYWH(1u16, 1, 1, 25)));
/// assert_eq!(check_layout("1".full_wh())?, Some(XYWH(1u16, 1, 80, 25)));
/// # Ok(()) }}
/// # Ok(()) }
/// ```
pub trait LayoutFull<'a, S: Screen>: Draw<'a, S> + Sized {
fn full_w (self) -> Full<'a, S, Self> { Full::W(self) }
@ -43,12 +43,12 @@ pub trait LayoutFull<'a, S: Screen>: Draw<'a, S> + Sized {
}
/// ```
/// # fn test_layout_exact () -> Usually<()> {
/// # use ::tengri::*; fn test_layout_exact () -> Usually<()> {
/// assert_eq!(check_layout("FOOBAR\nKILROY")?, Some(XYWH(1, 1, 6, 2)));
/// assert_eq!(check_layout("FOOBAR\nKILROY".exact_w(3))?, Some(XYWH(1, 1, 3, 2)));
/// assert_eq!(check_layout("FOOBAR\nKILROY".exact_h(1))?, Some(XYWH(1, 1, 6, 1)));
/// assert_eq!(check_layout("FOOBAR\nKILROY".exact_wh(2, 1))?, Some(XYWH(1, 1, 2, 1)));
/// # Ok(()) }}
/// # Ok(()) }
/// ```
pub trait LayoutExact<'a, S: Screen>: Draw<'a, S> + Sized {
fn exact_w <X: Into<Option<S::Unit>> + Copy> (self, w: X)
@ -60,12 +60,12 @@ pub trait LayoutExact<'a, S: Screen>: Draw<'a, S> + Sized {
}
/// ```
/// # fn test_layout_min () -> Usually<()> {
/// # use ::tengri::*; fn test_layout_min () -> Usually<()> {
/// assert_eq!(check_layout("1".min_w(5))?, Some(XYWH(1u16, 1, 5, 1)));
/// assert_eq!(check_layout("1".min_h(5))?, Some(XYWH(1u16, 1, 1, 5)));
/// assert_eq!(check_layout("1".min_wh(5, 5))?, Some(XYWH(1u16, 1, 5, 5)));
/// assert_eq!(check_layout("123456".min_w(5))?, Some(XYWH(1u16, 1, 6, 1)));
/// # Ok(()) }}
/// # Ok(()) }
/// ```
pub trait LayoutMin<'a, S: Screen>: Draw<'a, S> + Sized {
fn min_w <X: Into<Option<S::Unit>> + Copy> (self, w: X)
@ -95,7 +95,7 @@ pub trait LayoutPad<'a, S: Screen>: Draw<'a, S> + Sized {
}
/// ```
/// # fn test_layout_pull () -> Usually<()> {
/// # use ::tengri::*; fn test_layout_pull () -> Usually<()> {
/// assert_eq!(check_layout("1")?, Some(XYWH(1u16, 1, 1, 1)));
/// assert_eq!(check_layout("1".push_x(1))?, Some(XYWH(2u16, 1, 1, 1)));
/// assert_eq!(check_layout("1".push_y(1))?, Some(XYWH(1u16, 2, 1, 1)));
@ -112,7 +112,7 @@ pub trait LayoutPush<'a, S: Screen>: Draw<'a, S> + Sized {
}
/// ```
/// # fn test_layout_push () -> Usually<()> {
/// # use ::tengri::*; fn test_layout_push () -> Usually<()> {
/// assert_eq!(check_layout("1")?, Some(XYWH(1u16, 1, 1, 1)));
/// assert_eq!(check_layout("1".pull_x(1))?, Some(XYWH(0u16, 1, 1, 1)));
/// assert_eq!(check_layout("1".pull_y(1))?, Some(XYWH(1u16, 0, 1, 1)));
@ -160,14 +160,14 @@ where
let thunk = draw(move|screen|ok_flat(expr.last()?.map(|x: &'a str|state.interpret(screen, x))));
Ok(match expr.head()? {
Some("exact/w") => thunk.exact_w(
state.namespace(expr.nth(1)?)?
state.namespace(&expr.nth(1)?)?
).draw(to)?,
Some("exact/h") => thunk.exact_h(
state.namespace(expr.nth(1)?)?
state.namespace(&expr.nth(1)?)?
).draw(to)?,
Some("exact/wh") => thunk.exact_wh(
state.namespace(expr.nth(1)?)?,
state.namespace(expr.nth(2)?)?,
state.namespace(&expr.nth(1)?)?,
state.namespace(&expr.nth(2)?)?,
).draw(to)?,
_ => return Err(format!("invalid variant: {:?}", expr.head()?).into())
})
@ -186,14 +186,14 @@ where
let thunk = draw(move|screen|ok_flat(expr.last()?.map(|x: &'a str|state.interpret(screen, x))));
Ok(match expr.head()? {
Some("min/w") => thunk.min_w(
state.namespace(expr.nth(1)?)?
state.namespace(&expr.nth(1)?)?
).draw(to)?,
Some("min/h") => thunk.min_h(
state.namespace(expr.nth(1)?)?
state.namespace(&expr.nth(1)?)?
).draw(to)?,
Some("min/wh") => thunk.min_wh(
state.namespace(expr.nth(1)?)?,
state.namespace(expr.nth(2)?)?,
state.namespace(&expr.nth(1)?)?,
state.namespace(&expr.nth(2)?)?,
).draw(to)?,
_ => return Err(format!("invalid variant: {:?}", expr.head()?).into())
})
@ -212,14 +212,14 @@ where
let thunk = draw(move|screen|ok_flat(expr.last()?.map(|x: &'a str|state.interpret(screen, x))));
Ok(match expr.head()? {
Some("max/w") => thunk.max_w(
state.namespace(expr.nth(1)?)?
state.namespace(&expr.nth(1)?)?
).draw(to)?,
Some("max/h") => thunk.max_h(
state.namespace(expr.nth(1)?)?
state.namespace(&expr.nth(1)?)?
).draw(to)?,
Some("max/wh") => thunk.max_wh(
state.namespace(expr.nth(1)?)?,
state.namespace(expr.nth(2)?)?,
state.namespace(&expr.nth(1)?)?,
state.namespace(&expr.nth(2)?)?,
).draw(to)?,
_ => return Err(format!("invalid variant: {:?}", expr.head()?).into())
})
@ -237,9 +237,12 @@ where
{
let thunk = draw(move|screen|ok_flat(expr.last()?.map(|x: &'a str|state.interpret(screen, x))));
Ok(match expr.head()? {
Some("push/w") => thunk.push_x(state.namespace(expr.nth(1)?)?).draw(to)?,
Some("push/h") => thunk.push_y(state.namespace(expr.nth(1)?)?).draw(to)?,
Some("push/wh") => thunk.push_xy(state.namespace(expr.nth(1)?)?, state.namespace(expr.nth(2)?)?,).draw(to)?,
Some("push/w") => thunk.push_x(state.namespace(&expr.nth(1)?)?).draw(to)?,
Some("push/h") => thunk.push_y(state.namespace(&expr.nth(1)?)?).draw(to)?,
Some("push/wh") => thunk.push_xy(
state.namespace(&expr.nth(1)?)?,
state.namespace(&expr.nth(2)?)?,
).draw(to)?,
_ => return Err(format!("invalid variant: {:?}", expr.head()?).into())
})
}
@ -256,9 +259,12 @@ where
{
let thunk = draw(move|screen|ok_flat(expr.last()?.map(|x: &'a str|state.interpret(screen, x))));
Ok(match expr.head()? {
Some("pull/w") => thunk.pull_x(state.namespace(expr.nth(1)?)?).draw(to)?,
Some("pull/h") => thunk.pull_y(state.namespace(expr.nth(1)?)?).draw(to)?,
Some("pull/wh") => thunk.pull_xy(state.namespace(expr.nth(1)?)?, state.namespace(expr.nth(2)?)?,).draw(to)?,
Some("pull/w") => thunk.pull_x(state.namespace(&expr.nth(1)?)?).draw(to)?,
Some("pull/h") => thunk.pull_y(state.namespace(&expr.nth(1)?)?).draw(to)?,
Some("pull/wh") => thunk.pull_xy(
state.namespace(&expr.nth(1)?)?,
state.namespace(&expr.nth(2)?)?,
).draw(to)?,
_ => return Err(format!("invalid variant: {:?}", expr.head()?).into())
})
}
@ -276,14 +282,14 @@ where
let thunk = draw(move|screen|ok_flat(expr.last()?.map(|x: &'a str|state.interpret(screen, x))));
Ok(match expr.head()? {
Some("pad/w") => thunk.pad_w(
state.namespace(expr.nth(1)?)?
state.namespace(&expr.nth(1)?)?
).draw(to)?,
Some("pad/h") => thunk.pad_h(
state.namespace(expr.nth(1)?)?
state.namespace(&expr.nth(1)?)?
).draw(to)?,
Some("pad/wh") => thunk.pad_wh(
state.namespace(expr.nth(1)?)?,
state.namespace(expr.nth(2)?)?,
state.namespace(&expr.nth(1)?)?,
state.namespace(&expr.nth(2)?)?,
).draw(to)?,
_ => return Err(format!("invalid variant: {:?}", expr.head()?).into())
})
@ -438,6 +444,6 @@ impl<'a, S: Screen, T: Draw<'a, S>> LayoutPull<'a, S> for T {}
impl<'a, S: Screen, T: Draw<'a, S>> LayoutPad<'a, S> for T {}
#[cfg(test)] fn check_layout <'a> (t: impl Draw<'a, Tui>) -> Drawn<'a, u16> {
pub fn check_layout <'a> (t: impl Draw<'a, Tui>) -> Drawn<'a, u16> {
Tui::Layout(XYWH(1u16, 1, 80, 25)).size(None, t)
}

View file

@ -185,8 +185,9 @@ pub struct Pair<A, B>(Split, A, B);
/// ```
/// # fn test_split_stack () -> Usually<()> {
/// use ::tengri::*;
/// use Split::*;
/// fn size_of <A: Draw<Tui>, B: Draw<Tui>> (stack: &Pair<Tui, A, B>) -> Drawn<'a, S::Unit> {
/// fn size_of <'a, A: Draw<'a, Tui>, B: Draw<'a, Tui>> (stack: &Pair<Tui, A, B>) -> Drawn<'a, S::Unit> {
/// Tui::Layout(XYWH(0, 0, 80, 25)).size(None, stack)
/// }
/// assert_eq!(size_of(&split(East, "foo", "bar"))?, Some(XYWH(0, 0, 6, 1)));
@ -238,7 +239,7 @@ fn draw_stacks <'a, S: Screen> (
}
/// ```
/// # fn test_stack_areas () -> Usually<()> {
/// # use ::tengri::*; fn test_stack_areas () -> Usually<()> {
/// let area = XYWH(0u16, 0, 80, 25);
/// assert_eq!(stack_areas(&Split::East, &mut Tui::Layout(area), &"foo", &"bar")?, (
/// Some(XYWH(0u16, 0, 3, 1)),

View file

@ -3,15 +3,14 @@ use crate::*;
fn_kw_layout!(kw_when |state, output, expr| {
let thunk = draw(move|screen|ok_flat(expr.nth(2)?.map(|x: &'a str|state.interpret(screen, x))));
ok_flat(matches!(expr.head()?, Some("when")).then(||{
when(state.namespace(expr.nth(1)?)?.unwrap(), thunk) .draw(output)
when(state.namespace(&expr.nth(1)?)?.unwrap(), thunk) .draw(output)
}))
});
/// Only render when condition is true.
///
/// ```
/// # use tengri::*;
/// # fn test () -> impl Draw<Tui> {
/// # use ::tengri::*; fn test <'a> () -> impl Draw<'a, Tui> {
/// when(true, "Yes")
/// # }
/// ```
@ -23,15 +22,14 @@ fn_kw_layout!(kw_either |state, output, expr| {
let thunk_a = draw(move|screen|ok_flat(expr.nth(2)?.map(|x: &'a str|state.interpret(screen, x))));
let thunk_b = draw(move|screen|ok_flat(expr.nth(3)?.map(|x: &'a str|state.interpret(screen, x))));
ok_flat(matches!(expr.head()?, Some("either")).then(||{
either(state.namespace(expr.nth(1)?)?.unwrap(), thunk_a, thunk_b).draw(output)
either(state.namespace(&expr.nth(1)?)?.unwrap(), thunk_a, thunk_b).draw(output)
}))
});
/// Render one thing if a condition is true and another false.
///
/// ```
/// # use tengri::*;
/// # fn test () -> impl Draw<Tui> {
/// # use ::tengri::*; fn test <'a> () -> impl Draw<'a, Tui> {
/// either(true, "Yes", "No")
/// # }
/// ```

View file

@ -1797,19 +1797,19 @@ pub trait AsMutOpt<T> { fn as_mut_opt (&mut self) -> Option<&mut T>; }
-> UsuallyRef<'a, Self>;
}
impl<'a, T: Language<'a> + 'a> ColorDsl<'a, T> for Color {
impl<'a, T: Language + 'a> ColorDsl<'a, T> for Color {
fn new_g (expr: &'a T, try_to_u8: impl Fn(PerhapsRef<'a, &'a str>)->PerhapsRef<'a, u8>)
-> Result<Self, Box<dyn Error + 'a>>
{
let n = try_to_u8(expr.tail().map_err(Into::into))?.ok_or(Domain("not gray"))?;
let n = try_to_u8(expr.tail().map_err(Into::into))?.ok_or(LanguageError::domain("not gray"))?;
Ok(Self::Rgb(n, n, n))
}
fn new_rgb (expr: &'a T, try_to_u8: impl Fn(PerhapsRef<'a, &str>)->PerhapsRef<'a, u8>)
-> Result<Self, Box<dyn Error + 'a>>
{
let r = try_to_u8(expr.nth(1).map_err(Into::into))?.ok_or(Domain("not red"))?;
let g = try_to_u8(expr.nth(2).map_err(Into::into))?.ok_or(Domain("not green"))?;
let b = try_to_u8(expr.nth(3).map_err(Into::into))?.ok_or(Domain("not blue"))?;
let r = try_to_u8(expr.nth(1).map_err(Into::into))?.ok_or(LanguageError::domain("not red"))?;
let g = try_to_u8(expr.nth(2).map_err(Into::into))?.ok_or(LanguageError::domain("not green"))?;
let b = try_to_u8(expr.nth(3).map_err(Into::into))?.ok_or(LanguageError::domain("not blue"))?;
Ok(Color::Rgb(r, g, b))
}
}
@ -1935,8 +1935,8 @@ pub trait AsMutOpt<T> { fn as_mut_opt (&mut self) -> Option<&mut T>; }
/// # Ok(()) }
/// ```
pub trait Keywords <U, V>: 'static {
fn keywords () -> impl Iterator<Item = fn(&Self, &mut U, &str) -> Perhaps<V>>;
fn keyword <'a> (&self, to: &mut U, expr: &'a impl Language<'a>) -> PerhapsRef<'a, V> {
fn keywords <'a> () -> impl Iterator<Item = fn(&Self, &mut U, &str) -> PerhapsRef<'a, V>>;
fn keyword <'a> (&self, to: &mut U, expr: &'a (impl Language + ?Sized)) -> PerhapsRef<'a, V> {
if let Some(expr) = expr.src()? {
for keyword in Self::keywords() {
if let Some(result) = keyword(self, to, &expr)? {
@ -1951,7 +1951,7 @@ pub trait AsMutOpt<T> { fn as_mut_opt (&mut self) -> Option<&mut T>; }
#[macro_export] macro_rules! impl_keywords {
($T:ty, $U:ty, $V:ty [ $($kw:ident),* ]) => {
impl Keywords<$T, $U> for $V {
fn keywords () -> impl Iterator<Item = fn(&Self, &mut $T, &str) -> Perhaps<$U>> {
fn keywords <'a> () -> impl Iterator<Item = fn(&Self, &mut $T, &str) -> PerhapsRef<'a, $U>> {
[ $($kw),* ].into_iter()
}
}

View file

@ -70,7 +70,7 @@ impl TuiKey {
}
#[cfg(feature = "lang")]
pub fn from_dsl <'a> (dsl: &'a impl Language<'a>) -> UsuallyRef<'a, Self> {
pub fn from_dsl <'a> (dsl: &'a impl Language) -> UsuallyRef<'a, Self> {
if let Some(word) = dsl.word()? {
let word = word.trim();
Ok(if word == ":char" {

View file

@ -4,7 +4,7 @@ use Color::*;
fn_kw_layout_tui!(kw_tui_fg |state, output, expr| {
let thunk = draw(move|screen|ok_flat(expr.nth(2)?.map(|x: &'a str|state.interpret(screen, x))));
Ok(matches!(expr.head()?, Some("fg")).then(||{
if let Some(color) = state.namespace(expr.nth(1)?.expect("fg: expected arg 0 (color)"))? {
if let Some(color) = state.namespace(&expr.nth(1)?.expect("fg: expected arg 0 (color)"))? {
fg(color, thunk).draw(output)
} else {
return Err(format!("fg: {:?}: not a color", expr.nth(1)).into())
@ -15,7 +15,7 @@ fn_kw_layout_tui!(kw_tui_fg |state, output, expr| {
fn_kw_layout_tui!(kw_tui_bg |state, output, expr| {
let thunk = draw(move|screen|ok_flat(expr.nth(2)?.map(|x: &'a str|state.interpret(screen, x))));
Ok(matches!(expr.head()?, Some("bg")).then(||{
if let Some(color) = state.namespace(expr.nth(1)?.expect("bg: expected arg 0 (color)"))? {
if let Some(color) = state.namespace(&expr.nth(1)?.expect("bg: expected arg 0 (color)"))? {
bg(color, thunk).draw(output)
} else {
return Err(format!("bg: {:?}: not a color", expr.nth(1)?).into())
@ -24,23 +24,21 @@ fn_kw_layout_tui!(kw_tui_bg |state, output, expr| {
});
impl Tui {
pub fn eval_color_expr <'a> (state: &impl Namespace<u8>, src: &'a impl Language<'a>)
-> Result<Option<Color>, Box<dyn Error + 'a>>
{
pub fn eval_color_expr <'a> (
state: &'a impl Namespace<u8>,
src: &'a impl Language
) -> Result<Option<Color>, Box<dyn Error>> {
if let Some(expr) = src.expr()? {
match (expr.head()?, expr.tail()?) {
(Some("g"), Some(tail)) => {
let n: u8 = state.namespace(tail.head().map_err(Into::into))?
.ok_or(LanguageError::Domain("not gray"))?;
let n: u8 = state.namespace(&tail.head()?)?.ok_or(LanguageError::domain("not gray"))?;
Ok(Some(Color::Rgb(n, n, n)))
},
(Some("rgb"), Some(tail)) => {
let r: u8 = state.namespace(tail.head().map_err(Into::into))?
.ok_or(LanguageError::Domain("not red"))?;
let g: u8 = state.namespace(tail.tail().head().map_err(Into::into))?
.ok_or(LanguageError::Domain("not green"))?;
let b: u8 = state.namespace(tail.tail().tail().head().map_err(Into::into))?
.ok_or(LanguageError::Domain("not blue"))?;
let r: u8 = state.namespace(&tail.nth(0)?)?.ok_or(LanguageError::domain("not red"))?;
let g: u8 = state.namespace(&tail.nth(1)?)?.ok_or(LanguageError::domain("not green"))?;
let b: u8 = state.namespace(&tail.nth(2)?)?.ok_or(LanguageError::domain("not blue"))?;
Ok(Some(Color::Rgb(r, g, b)))
},
(Some(_), _) => return Err(
@ -54,6 +52,7 @@ impl Tui {
Ok(None)
}
}
}
/// Apply foreground color.