Skip to main content

Markdown

Struct Markdown 

Source
pub struct Markdown { /* private fields */ }
Expand description

A parsed Markdown document with support for live in-place terminal rendering.

Markdown parses markdown text into an internal element tree, then renders it with ANSI escape codes. It tracks line counts between renders so subsequent calls to render overwrite the previous output in-place using terminal cursor control sequences.

§Examples

use smart_markdown::{Markdown, ThemeMode};

let mut md = Markdown::parse("## Status\n\n**Running...**")
    .theme_mode(ThemeMode::Dark)
    .code_theme("base16-ocean.dark");

md.render(); // outputs to stdout

// Update a table cell and re-render
md.set_cell_content(0, 1, "new data");
md.render(); // overwrites previous output in-place

Implementations§

Source§

impl Markdown

Source

pub fn parse(text: &str) -> Self

Parse a markdown string into a Markdown document.

Supports: headings (ATX and setext), paragraphs, fenced/indented code blocks, blockquotes, ordered/unordered/task lists, tables, definition lists, horizontal rules, HTML blocks, footnotes, and reference links.

Examples found in repository?
examples/simple.rs (line 4)
3fn main() -> Result<(), Box<dyn std::error::Error>> {
4    let mut md = Markdown::parse(MARKDOWN);
5    md.render();
6
7    Ok(())
8}
More examples
Hide additional examples
examples/streaming.rs (lines 7-25)
6fn main() -> Result<(), Box<dyn std::error::Error>> {
7    let mut md = Markdown::parse(
8        "## Build Pipeline\n\n\
9         | Task    | Status  | Details                         |\n\
10         |---------|---------|---------------------------------|\n\
11         | build   | pending |                                 |\n\
12         | test    | pending |                                 |\n\
13         | deploy  | pending |                                 |\n\
14         \n\
15         _Live streaming table update demo_\n\n\
16         \n\
17         ### Task Status\n\n\
18         - [x] Compile source\n\
19         - [x] Run unit tests\n\
20         - [ ] Integration tests\n\
21         - [ ] Deploy to staging\n\
22         \n\
23         See the pipeline logs or visit <https://ci.example.com>\n\
24         for detailed build output.\n",
25    );
26
27    println!("\nStreaming Markdown Demo\n-----------------------\n");
28    md.render();
29    io::stdout().flush()?;
30    thread::sleep(Duration::from_millis(800));
31
32    md.append_to_cell(0, 2, "compiling source");
33    md.render();
34    io::stdout().flush()?;
35    thread::sleep(Duration::from_millis(800));
36
37    md.append_to_cell(0, 2, " files...");
38    md.render();
39    io::stdout().flush()?;
40    thread::sleep(Duration::from_millis(800));
41
42    md.append_to_cell(1, 2, "running unit tests across all crates");
43    md.render();
44    io::stdout().flush()?;
45    thread::sleep(Duration::from_millis(800));
46
47    md.set_cell_content(0, 1, "done");
48    md.render();
49    io::stdout().flush()?;
50    thread::sleep(Duration::from_millis(800));
51
52    md.set_cell_content(1, 1, "running");
53    md.append_to_cell(1, 2, " with coverage instrumentation enabled for llvm-cov");
54    md.render();
55    io::stdout().flush()?;
56    thread::sleep(Duration::from_millis(1200));
57
58    md.set_cell_content(2, 1, "queued");
59    md.append_to_cell(0, 2, " and linking final binary artifact");
60    md.render();
61    io::stdout().flush()?;
62    thread::sleep(Duration::from_millis(800));
63
64    md.set_cell_content(2, 1, "done");
65    md.set_cell_content(2, 2, "release published to registry");
66    md.render();
67    io::stdout().flush()?;
68    thread::sleep(Duration::from_millis(800));
69
70    println!();
71
72    Ok(())
73}
Source

pub fn theme_mode(self, mode: ThemeMode) -> Self

Set the syntax highlighting theme mode.

When the syntax-highlight feature is enabled (on by default), this controls which syntect color theme is used for fenced code blocks.

  • ThemeMode::Dark — “Base16 Eighties Dark”
  • ThemeMode::Light — “Solarized (light)”
  • ThemeMode::Auto — detects terminal background color at render time
Source

pub fn code_theme(self, theme: &str) -> Self

Override the syntax highlighting theme by name.

See highlight::list_themes for available theme names. When the syntax-highlight feature is disabled, this has no effect.

Source

pub fn has_terminal_resized(&self) -> bool

Returns true if the terminal width has changed since the last render.

Useful for deciding whether to re-render on SIGWINCH.

Source

pub fn append_to_cell(&mut self, row: usize, col: usize, text: &str)

Append text to a table cell identified by row and column index.

Panics if the document doesn’t contain a table or the indices are out of bounds.

Examples found in repository?
examples/streaming.rs (line 32)
6fn main() -> Result<(), Box<dyn std::error::Error>> {
7    let mut md = Markdown::parse(
8        "## Build Pipeline\n\n\
9         | Task    | Status  | Details                         |\n\
10         |---------|---------|---------------------------------|\n\
11         | build   | pending |                                 |\n\
12         | test    | pending |                                 |\n\
13         | deploy  | pending |                                 |\n\
14         \n\
15         _Live streaming table update demo_\n\n\
16         \n\
17         ### Task Status\n\n\
18         - [x] Compile source\n\
19         - [x] Run unit tests\n\
20         - [ ] Integration tests\n\
21         - [ ] Deploy to staging\n\
22         \n\
23         See the pipeline logs or visit <https://ci.example.com>\n\
24         for detailed build output.\n",
25    );
26
27    println!("\nStreaming Markdown Demo\n-----------------------\n");
28    md.render();
29    io::stdout().flush()?;
30    thread::sleep(Duration::from_millis(800));
31
32    md.append_to_cell(0, 2, "compiling source");
33    md.render();
34    io::stdout().flush()?;
35    thread::sleep(Duration::from_millis(800));
36
37    md.append_to_cell(0, 2, " files...");
38    md.render();
39    io::stdout().flush()?;
40    thread::sleep(Duration::from_millis(800));
41
42    md.append_to_cell(1, 2, "running unit tests across all crates");
43    md.render();
44    io::stdout().flush()?;
45    thread::sleep(Duration::from_millis(800));
46
47    md.set_cell_content(0, 1, "done");
48    md.render();
49    io::stdout().flush()?;
50    thread::sleep(Duration::from_millis(800));
51
52    md.set_cell_content(1, 1, "running");
53    md.append_to_cell(1, 2, " with coverage instrumentation enabled for llvm-cov");
54    md.render();
55    io::stdout().flush()?;
56    thread::sleep(Duration::from_millis(1200));
57
58    md.set_cell_content(2, 1, "queued");
59    md.append_to_cell(0, 2, " and linking final binary artifact");
60    md.render();
61    io::stdout().flush()?;
62    thread::sleep(Duration::from_millis(800));
63
64    md.set_cell_content(2, 1, "done");
65    md.set_cell_content(2, 2, "release published to registry");
66    md.render();
67    io::stdout().flush()?;
68    thread::sleep(Duration::from_millis(800));
69
70    println!();
71
72    Ok(())
73}
Source

pub fn set_cell_content(&mut self, row: usize, col: usize, text: &str)

Replace the content of a table cell identified by row and column index.

Panics if the document doesn’t contain a table or the indices are out of bounds.

Examples found in repository?
examples/streaming.rs (line 47)
6fn main() -> Result<(), Box<dyn std::error::Error>> {
7    let mut md = Markdown::parse(
8        "## Build Pipeline\n\n\
9         | Task    | Status  | Details                         |\n\
10         |---------|---------|---------------------------------|\n\
11         | build   | pending |                                 |\n\
12         | test    | pending |                                 |\n\
13         | deploy  | pending |                                 |\n\
14         \n\
15         _Live streaming table update demo_\n\n\
16         \n\
17         ### Task Status\n\n\
18         - [x] Compile source\n\
19         - [x] Run unit tests\n\
20         - [ ] Integration tests\n\
21         - [ ] Deploy to staging\n\
22         \n\
23         See the pipeline logs or visit <https://ci.example.com>\n\
24         for detailed build output.\n",
25    );
26
27    println!("\nStreaming Markdown Demo\n-----------------------\n");
28    md.render();
29    io::stdout().flush()?;
30    thread::sleep(Duration::from_millis(800));
31
32    md.append_to_cell(0, 2, "compiling source");
33    md.render();
34    io::stdout().flush()?;
35    thread::sleep(Duration::from_millis(800));
36
37    md.append_to_cell(0, 2, " files...");
38    md.render();
39    io::stdout().flush()?;
40    thread::sleep(Duration::from_millis(800));
41
42    md.append_to_cell(1, 2, "running unit tests across all crates");
43    md.render();
44    io::stdout().flush()?;
45    thread::sleep(Duration::from_millis(800));
46
47    md.set_cell_content(0, 1, "done");
48    md.render();
49    io::stdout().flush()?;
50    thread::sleep(Duration::from_millis(800));
51
52    md.set_cell_content(1, 1, "running");
53    md.append_to_cell(1, 2, " with coverage instrumentation enabled for llvm-cov");
54    md.render();
55    io::stdout().flush()?;
56    thread::sleep(Duration::from_millis(1200));
57
58    md.set_cell_content(2, 1, "queued");
59    md.append_to_cell(0, 2, " and linking final binary artifact");
60    md.render();
61    io::stdout().flush()?;
62    thread::sleep(Duration::from_millis(800));
63
64    md.set_cell_content(2, 1, "done");
65    md.set_cell_content(2, 2, "release published to registry");
66    md.render();
67    io::stdout().flush()?;
68    thread::sleep(Duration::from_millis(800));
69
70    println!();
71
72    Ok(())
73}
Source

pub fn render(&mut self)

Render the document to stdout with ANSI escape codes.

On first call, output is simply printed. On subsequent calls, the previous output is overwritten in-place using cursor-up and line-clear sequences. Lines that shrink between renders are properly cleared.

Examples found in repository?
examples/simple.rs (line 5)
3fn main() -> Result<(), Box<dyn std::error::Error>> {
4    let mut md = Markdown::parse(MARKDOWN);
5    md.render();
6
7    Ok(())
8}
More examples
Hide additional examples
examples/streaming.rs (line 28)
6fn main() -> Result<(), Box<dyn std::error::Error>> {
7    let mut md = Markdown::parse(
8        "## Build Pipeline\n\n\
9         | Task    | Status  | Details                         |\n\
10         |---------|---------|---------------------------------|\n\
11         | build   | pending |                                 |\n\
12         | test    | pending |                                 |\n\
13         | deploy  | pending |                                 |\n\
14         \n\
15         _Live streaming table update demo_\n\n\
16         \n\
17         ### Task Status\n\n\
18         - [x] Compile source\n\
19         - [x] Run unit tests\n\
20         - [ ] Integration tests\n\
21         - [ ] Deploy to staging\n\
22         \n\
23         See the pipeline logs or visit <https://ci.example.com>\n\
24         for detailed build output.\n",
25    );
26
27    println!("\nStreaming Markdown Demo\n-----------------------\n");
28    md.render();
29    io::stdout().flush()?;
30    thread::sleep(Duration::from_millis(800));
31
32    md.append_to_cell(0, 2, "compiling source");
33    md.render();
34    io::stdout().flush()?;
35    thread::sleep(Duration::from_millis(800));
36
37    md.append_to_cell(0, 2, " files...");
38    md.render();
39    io::stdout().flush()?;
40    thread::sleep(Duration::from_millis(800));
41
42    md.append_to_cell(1, 2, "running unit tests across all crates");
43    md.render();
44    io::stdout().flush()?;
45    thread::sleep(Duration::from_millis(800));
46
47    md.set_cell_content(0, 1, "done");
48    md.render();
49    io::stdout().flush()?;
50    thread::sleep(Duration::from_millis(800));
51
52    md.set_cell_content(1, 1, "running");
53    md.append_to_cell(1, 2, " with coverage instrumentation enabled for llvm-cov");
54    md.render();
55    io::stdout().flush()?;
56    thread::sleep(Duration::from_millis(1200));
57
58    md.set_cell_content(2, 1, "queued");
59    md.append_to_cell(0, 2, " and linking final binary artifact");
60    md.render();
61    io::stdout().flush()?;
62    thread::sleep(Duration::from_millis(800));
63
64    md.set_cell_content(2, 1, "done");
65    md.set_cell_content(2, 2, "release published to registry");
66    md.render();
67    io::stdout().flush()?;
68    thread::sleep(Duration::from_millis(800));
69
70    println!();
71
72    Ok(())
73}

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.