tui_markup/lib.rs
1#![warn(clippy::all, clippy::pedantic)]
2#![warn(missing_docs, missing_debug_implementations)]
3#![deny(warnings)]
4#![allow(clippy::module_name_repetitions)]
5#![cfg_attr(not(test), forbid(unsafe_code))]
6#![cfg_attr(docsrs, feature(doc_cfg))]
7
8//! # tui markup
9//!
10//! This crate provides a markup language to
11//! quickly write colorful and styled terminal text in plain text.
12//!
13//! I suggest to check [examples/help.txt], which generated this self-describing syntax help document:
14//!
15//! ![][help-text-screenshot]
16//!
17//! For formal syntax specification, see [docs/syntax.ebnf].
18//!
19//! ## How to use
20//!
21//! ```ignore
22//! let output = tui_markup::compile::<Generator>("<bg:blue,green,b hello>").unwrap();
23//! ```
24//!
25//! The string wrapped in `<>`(like the `bg:blue,green,b` in above example) is called a element,
26//! start with a tag list(comma separated), those tags add styles to inner items.
27//!
28//! Usable tags are vary depending on the the [Generator] you use,
29//! and generator will ignore all tags it does not understand.
30//!
31//! So it's better checkout their document before write your markup text.
32//!
33//! ### Builtin generators
34//!
35//! The builtin generators are under feature gates:
36//!
37//! feature     | Target                                                              | generator type
38//! :---------- | :------------------------------------------------------------------ | :-------------
39//! `ansi`      | Direct print into stdout when using an asni compatible terminal     | [`ANSIStringsGenerator`][generator::ANSIStringsGenerator]
40//! `ratatui`   | Integrated with the [ratatui] crate                                 | [`RatatuiTextGenerator`][generator::RatatuiTextGenerator]
41//! `crossterm` | Integrated with [crossterm] crate                                   | [`CrosstermCommandsGenerator`][generator::CrosstermCommandsGenerator]
42//!
43//! The example screenshot above is using the `ratatui` generator, print in Windows Terminal.
44//!
45//! If you want write your own generator, please checkout documents of [Generator] trait.
46//!
47//! [docs/syntax.ebnf]: https://github.com/7sDream/tui-markup/blob/master/docs/syntax.ebnf
48//! [help-text-screenshot]: https://rikka.7sdre.am/files/ee68d36d-b1e7-4575-bb13-e37ba7ead044.png
49//! [examples/help.txt]: https://github.com/7sDream/tui-markup/blob/master/examples/help.txt
50
51mod error;
52pub mod generator;
53pub mod parser;
54
55pub use error::{Error, LocatedError};
56
57use generator::{Generator, TagConvertor};
58
59/// Parse markup language source, then generate final output using the default configure of a generator type.
60///
61/// See document of generator type for examples.
62///
63/// ## Errors
64///
65/// If input source contains invalid syntax or generator failed.
66pub fn compile<'a, G>(s: &'a str) -> Result<G::Output, Error<'a, G::Err>>
67where
68    G: Generator<'a> + Default,
69{
70    compile_with(s, G::default())
71}
72
73/// Parse markup language source, then generate final output using the provided generator.
74///
75/// See document of generator type for examples.
76///
77/// ## Errors
78///
79/// If input source contains invalid syntax or generator failed.
80pub fn compile_with<'a, G>(s: &'a str, mut gen: G) -> Result<G::Output, Error<'a, G::Err>>
81where
82    G: Generator<'a>,
83{
84    let ast = parser::parse(s)?;
85    let ir = gen.convertor().convert_ast(ast);
86    match gen.generate(ir) {
87        Ok(result) => Ok(result),
88        Err(err) => Err(err.into()),
89    }
90}