mirror of
https://codeberg.org/unspeaker/tengri.git
synced 2026-09-18 05:16:44 +02:00
parent
a9f2fa2cdd
commit
291ab63224
11 changed files with 98 additions and 96 deletions
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)),
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
/// # }
|
||||
/// ```
|
||||
|
|
|
|||
16
src/lib.rs
16
src/lib.rs
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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" {
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue