tui_markup/generator/crossterm/
mod.rs1mod span;
4mod tag;
5
6use crossterm::style::{ContentStyle, Print};
7
8use crate::{
9 generator::{
10 helper::{flatten, CustomTagParser, GeneratorInfallible, NoopCustomTagParser},
11 Generator,
12 },
13 parser::ItemG,
14};
15
16pub use span::Span;
17pub use tag::CrosstermTagConvertor;
18
19#[cfg_attr(docsrs, doc(cfg(feature = "crossterm")))]
45#[derive(Debug)]
46pub struct CrosstermCommandsGenerator<P = NoopCustomTagParser<ContentStyle>> {
47 convertor: CrosstermTagConvertor<P>,
48}
49
50impl<P> Default for CrosstermCommandsGenerator<P> {
51 fn default() -> Self {
52 Self {
53 convertor: CrosstermTagConvertor::<P>::default(),
54 }
55 }
56}
57
58impl<P> CrosstermCommandsGenerator<P> {
59 pub fn new(p: P) -> Self {
61 Self {
62 convertor: CrosstermTagConvertor::new(p),
63 }
64 }
65}
66
67impl<'a, P> Generator<'a> for CrosstermCommandsGenerator<P>
68where
69 P: CustomTagParser<Output = ContentStyle>,
70{
71 type Convertor = CrosstermTagConvertor<P>;
72
73 type Output = Vec<Span<'a>>;
74
75 type Err = GeneratorInfallible;
76
77 fn convertor(&mut self) -> &mut Self::Convertor {
78 &mut self.convertor
79 }
80
81 fn generate(&mut self, items: Vec<Vec<ItemG<'a, Self>>>) -> Result<Self::Output, Self::Err> {
82 Ok(items.into_iter().map(flatten).fold(vec![], |mut acc, line| {
83 if !acc.is_empty() {
84 acc.push(Span::NoStyle(Print("\n")));
85 }
86 acc.extend(line);
87 acc
88 }))
89 }
90}