tui_markup/generator/crossterm/
mod.rs

1//! Generator implementations for crossterm crate.
2
3mod 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/// Generator for [crossterm crate][crossterm], generated result is a series of it's [Command][crossterm::Command]s.
20///
21/// See [docs/tui-tags.ebnf] for supported tags.
22///
23/// ### Show output
24///
25/// Execute/Queue all the commands in the buffer where you want to print the result. For example, in stdout:
26///
27/// ```
28/// use std::io::Write;
29/// use crossterm::QueueableCommand;
30/// use tui_markup::{compile, generator::CrosstermCommandsGenerator};
31///
32/// let mut stdout = std::io::stdout();
33/// let spans = compile::<CrosstermCommandsGenerator>("I have a <green green text>").unwrap();
34/// for span in &spans {
35///     stdout.queue(span).unwrap();
36/// }
37/// stdout.flush().unwrap();
38/// ```
39///
40/// See [example/crossterm.rs] for a example code.
41///
42/// [docs/tui-tags.ebnf]: https://github.com/7sDream/tui-markup/blob/master/docs/tui-tags.ebnf
43/// [example/crossterm.rs]: https://github.com/7sDream/tui-markup/blob/master/example/crossterm.rs
44#[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    /// Create a new generator, with a custom tag parser.
60    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}