Support multiple strings in a token
This commit is contained in:
parent
7890424ea9
commit
80425f9aff
|
@ -8,16 +8,37 @@ pub enum Token {
|
||||||
CharPad(Box<Token>, char, usize),
|
CharPad(Box<Token>, char, usize),
|
||||||
Fg(Box<Token>, Color),
|
Fg(Box<Token>, Color),
|
||||||
Bg(Box<Token>, Color),
|
Bg(Box<Token>, Color),
|
||||||
String(String),
|
String(Box<Token>, String),
|
||||||
|
End,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<String> for Token {
|
impl From<String> for Token {
|
||||||
fn from(value: String) -> Self {
|
fn from(value: String) -> Self {
|
||||||
Token::String(value)
|
Self::text(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&str> for Token {
|
||||||
|
fn from(value: &str) -> Self {
|
||||||
|
Self::text(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Token {
|
impl Token {
|
||||||
|
pub fn text<T>(t: T) -> Self
|
||||||
|
where
|
||||||
|
T: Into<String>,
|
||||||
|
{
|
||||||
|
Self::End.string(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn string<S>(self, s: S) -> Self
|
||||||
|
where
|
||||||
|
S: Into<String>,
|
||||||
|
{
|
||||||
|
Token::String(Box::new(self), s.into())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn centered(self) -> Self {
|
pub fn centered(self) -> Self {
|
||||||
Self::Centered(Box::new(self))
|
Self::Centered(Box::new(self))
|
||||||
}
|
}
|
||||||
|
@ -31,7 +52,17 @@ impl Token {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn str_len(&self) -> usize {
|
pub fn str_len(&self) -> usize {
|
||||||
self.walk_to_end().len()
|
match self {
|
||||||
|
Token::String(t, s) => s.len() + t.str_len(),
|
||||||
|
Token::Fg(t, _) => t.str_len(),
|
||||||
|
Token::Bg(t, _) => t.str_len(),
|
||||||
|
Token::Centered(t) => t.str_len(),
|
||||||
|
Token::Limited(t, lim) => (*lim).min(t.str_len()),
|
||||||
|
Token::CharPad(t, _, pad_to) => {
|
||||||
|
(*pad_to).max(t.str_len())
|
||||||
|
}
|
||||||
|
Token::End => 0,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pad_char(self, c: char, pad_to: usize) -> Self {
|
pub fn pad_char(self, c: char, pad_to: usize) -> Self {
|
||||||
|
@ -46,38 +77,25 @@ impl Token {
|
||||||
Self::Bg(Box::new(self), c)
|
Self::Bg(Box::new(self), c)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn walk_to_end(&self) -> &String {
|
|
||||||
match self {
|
|
||||||
Token::String(s) => s,
|
|
||||||
Token::Fg(t, _) => t.walk_to_end(),
|
|
||||||
Token::Bg(t, _) => t.walk_to_end(),
|
|
||||||
Token::Centered(t) => t.walk_to_end(),
|
|
||||||
Token::Limited(t, _) => t.walk_to_end(),
|
|
||||||
Token::CharPad(t, _, _) => t.walk_to_end(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn with_width(self, width: usize) -> Vec<Component> {
|
fn with_width(self, width: usize) -> Vec<Component> {
|
||||||
match self {
|
match self {
|
||||||
Token::String(s) => vec![Component::String(s)],
|
Token::String(t, s) => vec![Component::String(s)]
|
||||||
Token::Centered(cnt) => cnt
|
|
||||||
.with_width(width)
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|comp| {
|
.chain(t.with_width(width))
|
||||||
if let Component::String(s) = comp {
|
|
||||||
let str_len = s.len();
|
|
||||||
let x = if str_len > width {
|
|
||||||
0
|
|
||||||
} else {
|
|
||||||
(width - str_len) / 2
|
|
||||||
};
|
|
||||||
vec![Component::X(x), Component::String(s)]
|
|
||||||
} else {
|
|
||||||
vec![comp]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.flatten()
|
|
||||||
.collect(),
|
.collect(),
|
||||||
|
Token::Centered(cnt) => {
|
||||||
|
let mut str_len = cnt.str_len();
|
||||||
|
let components = if str_len > width {
|
||||||
|
str_len = width;
|
||||||
|
cnt.limited(width).with_width(width)
|
||||||
|
} else {
|
||||||
|
cnt.with_width(width)
|
||||||
|
};
|
||||||
|
vec![Component::X((width - str_len) / 2)]
|
||||||
|
.into_iter()
|
||||||
|
.chain(components)
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
Token::Limited(s, lim) => s
|
Token::Limited(s, lim) => s
|
||||||
.with_width(width)
|
.with_width(width)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -116,6 +134,7 @@ impl Token {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain(t.with_width(width))
|
.chain(t.with_width(width))
|
||||||
.collect(),
|
.collect(),
|
||||||
|
Token::End => vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -130,29 +149,25 @@ mod tests {
|
||||||
vec![
|
vec![
|
||||||
(
|
(
|
||||||
"string -> string",
|
"string -> string",
|
||||||
Token::String("hello".into()),
|
Token::text("hello"),
|
||||||
vec![Component::String("hello".into())],
|
vec![Component::String("hello".into())],
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"string -> limited",
|
"string -> limited",
|
||||||
Token::String(
|
Token::text("This string is too long for this!")
|
||||||
"This string is too long for this!".into(),
|
.limited(4),
|
||||||
)
|
|
||||||
.limited(4),
|
|
||||||
vec![Component::String("This".into())],
|
vec![Component::String("This".into())],
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"string -> limit -> pad_to",
|
"string -> limit -> pad_to",
|
||||||
Token::String(
|
Token::text("This string is too long, but some")
|
||||||
"This string is too long, but some".into(),
|
.limited(10)
|
||||||
)
|
.padded(15),
|
||||||
.limited(10)
|
|
||||||
.padded(15),
|
|
||||||
vec![Component::String("This strin ".into())],
|
vec![Component::String("This strin ".into())],
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"center limited string",
|
"center limited string",
|
||||||
Token::String("Ahhh this won't go far".into())
|
Token::text("Ahhh this won't go far")
|
||||||
.limited(10)
|
.limited(10)
|
||||||
.centered(),
|
.centered(),
|
||||||
vec![
|
vec![
|
||||||
|
@ -162,9 +177,7 @@ mod tests {
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"padded string with underscores is centered",
|
"padded string with underscores is centered",
|
||||||
Token::String("It was...".into())
|
Token::text("It was...").pad_char('_', 15).centered(),
|
||||||
.pad_char('_', 15)
|
|
||||||
.centered(),
|
|
||||||
vec![
|
vec![
|
||||||
Component::X((WIDTH - 15) / 2),
|
Component::X((WIDTH - 15) / 2),
|
||||||
Component::String("It was...______".into()),
|
Component::String("It was...______".into()),
|
||||||
|
@ -172,7 +185,7 @@ mod tests {
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"prefixes color",
|
"prefixes color",
|
||||||
Token::String("this is red".into()).fg(Color::RED),
|
Token::text("this is red").fg(Color::RED),
|
||||||
vec![
|
vec![
|
||||||
Component::Fg(Color::RED),
|
Component::Fg(Color::RED),
|
||||||
Component::String("this is red".into()),
|
Component::String("this is red".into()),
|
||||||
|
@ -180,9 +193,7 @@ mod tests {
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"color at beginning of line",
|
"color at beginning of line",
|
||||||
Token::String("colored".into())
|
Token::text("colored").centered().bg(Color::RED),
|
||||||
.centered()
|
|
||||||
.bg(Color::RED),
|
|
||||||
vec![
|
vec![
|
||||||
Component::Bg(Color::RED),
|
Component::Bg(Color::RED),
|
||||||
Component::X((WIDTH - 7) / 2),
|
Component::X((WIDTH - 7) / 2),
|
||||||
|
@ -191,7 +202,7 @@ mod tests {
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"color isnt part of limit",
|
"color isnt part of limit",
|
||||||
Token::String("ten chars!".into())
|
Token::text("ten chars!")
|
||||||
.bg(Color::RED)
|
.bg(Color::RED)
|
||||||
.fg(Color::GREEN)
|
.fg(Color::GREEN)
|
||||||
.bg(Color::BLUE)
|
.bg(Color::BLUE)
|
||||||
|
@ -205,6 +216,25 @@ mod tests {
|
||||||
Component::String("ten chars!".into()),
|
Component::String("ten chars!".into()),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
"multicolor string centered",
|
||||||
|
Token::text("end")
|
||||||
|
.fg(Color::RED)
|
||||||
|
.string("mid")
|
||||||
|
.fg(Color::BLUE)
|
||||||
|
.string("start")
|
||||||
|
.fg(Color::GREEN)
|
||||||
|
.centered(),
|
||||||
|
vec![
|
||||||
|
Component::X(0),
|
||||||
|
Component::Fg(Color::GREEN),
|
||||||
|
Component::String("start".into()),
|
||||||
|
Component::Fg(Color::BLUE),
|
||||||
|
Component::String("mid".into()),
|
||||||
|
Component::Fg(Color::RED),
|
||||||
|
Component::String("end".into()),
|
||||||
|
],
|
||||||
|
),
|
||||||
]
|
]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.for_each(|test| {
|
.for_each(|test| {
|
||||||
|
|
Loading…
Reference in New Issue