Skip to main content

tui_markup/generator/crossterm/
mod.rs

1//! Generator implementations for crossterm crate.
2
3mod span;
4mod tag;
5
6use crossterm::style::{ContentStyle, Print};
7pub use span::Span;
8pub use tag::CrosstermTagConvertor;
9
10use crate::{
11    generator::{
12        Generator,
13        helper::{CustomTagParser, GeneratorInfallible, NoopCustomTagParser, flatten},
14    },
15    parser::ItemG,
16};
17
18/// Generator for [crossterm crate][crossterm], generated result is a series of it's
19/// [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
26/// stdout:
27///
28/// ```
29/// use std::io::Write;
30///
31/// use crossterm::QueueableCommand;
32/// use tui_markup::{compile, generator::CrosstermCommandsGenerator};
33///
34/// let mut stdout = std::io::stdout();
35/// let spans = compile::<CrosstermCommandsGenerator>("I have a <green green text>").unwrap();
36/// for span in &spans {
37///     stdout.queue(span).unwrap();
38/// }
39/// stdout.flush().unwrap();
40/// ```
41///
42/// See [example/crossterm.rs] for a example code.
43///
44/// [docs/tui-tags.ebnf]: https://github.com/7sDream/tui-markup/blob/master/docs/tui-tags.ebnf
45/// [example/crossterm.rs]: https://github.com/7sDream/tui-markup/blob/master/example/crossterm.rs
46#[derive(Debug)]
47pub struct CrosstermCommandsGenerator<P = NoopCustomTagParser<ContentStyle>> {
48    convertor: CrosstermTagConvertor<P>,
49}
50
51impl<P> Default for CrosstermCommandsGenerator<P> {
52    fn default() -> Self {
53        Self {
54            convertor: CrosstermTagConvertor::<P>::default(),
55        }
56    }
57}
58
59impl<P> CrosstermCommandsGenerator<P> {
60    /// Create a new generator, with a custom tag parser.
61    pub fn new(p: P) -> Self {
62        Self {
63            convertor: CrosstermTagConvertor::new(p),
64        }
65    }
66}
67
68impl<'a, P> Generator<'a> for CrosstermCommandsGenerator<P>
69where
70    P: CustomTagParser<Output = ContentStyle>,
71{
72    type Convertor = CrosstermTagConvertor<P>;
73    type Err = GeneratorInfallible;
74    type Output = Vec<Span<'a>>;
75
76    fn convertor(&mut self) -> &mut Self::Convertor {
77        &mut self.convertor
78    }
79
80    fn generate(&mut self, markup: Vec<Vec<ItemG<'a, Self>>>) -> Result<Self::Output, Self::Err> {
81        let mut spans = Vec::with_capacity(markup.len());
82        for (i, line) in markup.into_iter().enumerate() {
83            if i > 0 {
84                spans.push(Span::NoStyle(Print("\n")));
85            }
86            spans.extend(flatten(line));
87        }
88        Ok(spans)
89    }
90}