termimad/lib.rs
1/*! This crate lets you display simple markdown snippets
2or scrollable wrapped markdown texts in the terminal.
3
4In order to use Termimad you typically need
5* some *markdown*: a string which you can have loaded or dynamically built
6* a *skin*: which defines the colors and style attributes of every parts
7
8Additionnaly, you might define an *area* of the screen in which to draw (and maybe scroll).
9
10# The skin
11
12It's an instance of [`MadSkin`](struct.MadSkin.html) whose fields you customize according
13to your tastes or (better) to your application's configuration.
14
15
16```rust
17use termimad::crossterm::style::{Color::*, Attribute::*};
18use termimad::*;
19
20// start with the default skin
21let mut skin = MadSkin::default();
22// let's decide bold is in light gray
23skin.bold.set_fg(gray(20));
24// let's make strikeout not striked out but red, with no specific background, and bold
25skin.strikeout = CompoundStyle::new(Some(Red), None, Bold.into());
26```
27
28**Beware:**
29* you may define colors in full [`rgb`](fn.rgb.html) but this will limit compatibility with old terminals. It's recommended to stick to [Ansi colors](fn.ansi.html), [gray levels](fn.gray.html), or [Crossterm predefined values](https://docs.rs/crossterm/0.9.6/crossterm/enum.Color.html).
30* styles are composed. For example a word may very well be italic, bold and striked out. It might not be wise to have them differ only by their background color for example.
31
32# Display a simple inline snippet
33
34
35```
36# use termimad::*;
37// with the default skin, nothing simpler:
38termimad::print_inline("value: **52**");
39```
40# Print a text
41
42A multi-line markdown string can be printed the same way than an *inline* snippet, but you usually want it to be wrapped according to the available terminal width.
43
44```rust,no_run
45# use termimad::*;
46# let skin = MadSkin::default();
47# let my_markdown = "#title\n* item 1\n* item 2";
48eprintln!("{}", skin.term_text(my_markdown));
49```
50
51[`MadSkin`](struct.MadSkin.html) contains other functions to prepare a text for no specific size or for one which isn't the terminal's width. It also offers several functions to print it either on `stdout` or on a given `Write`.
52
53# Display a text, maybe scroll it
54
55A terminal application often uses an *alternate* screen instead of just dumping its text to stdout, and you often want to display in a specific rect of that screen, with adequate wrapping and not writing outside that rect.
56
57You may also want to display a scrollbar if the text doesn't fit the area. A [`MadView`](struct.MadView.html) makes that simple:
58
59```
60# use termimad::*;
61# let markdown = String::from("#title\n* item 1\n* item 2");
62# let skin = MadSkin::default();
63let area = Area::new(0, 0, 10, 12);
64let mut view = MadView::from(markdown, area, skin);
65view.write().unwrap();
66```
67
68If you don't want to give ownership of the skin, markdown and area, you may prefer to use a [`TextView`](struct.TextView.html).
69
70You may see how to write a text viewer responding to key inputs to scroll a markdown text in [the scrollable example](https://github.com/Canop/termimad/blob/master/examples/scrollable/main.rs).
71
72# Templates
73
74In order to separate the rendering format from the content, the `format!` macro is not always a good solution because you may not be sure the content is free of characters which may mess the markdown.
75
76A solution is to use one of the templating functions or macros.
77
78Example:
79
80```
81# #[macro_use] extern crate minimad;
82# use termimad::*;
83# let skin = MadSkin::default();
84mad_print_inline!(
85 &skin,
86 "**$0 formula:** *$1*", // the markdown template, interpreted once
87 "Disk", // fills $0
88 "2*π*r", // fills $1. Note that the stars don't mess the markdown
89);
90```
91
92Main difference with using `print!(format!( ... ))`:
93* the markdown parsing and template building are done only once (using `once_cell` internally)
94* the given values aren't interpreted as markdown fragments and don't impact the style
95* arguments can be omited, repeated, given in any order
96* no support for fmt parameters or arguments other than `&str` *(in the current version)*
97
98You'll find more examples and advice in the *templates* example.
99
100# Examples
101
102The repository contains several other examples, which hopefully cover the whole API while being simple enough. It's recommended you start by trying them or at least glance at their code.
103
104*/
105
106mod area;
107mod ask;
108mod code;
109mod color;
110mod composite;
111mod composite_kind;
112mod compound_style;
113mod displayable_line;
114mod errors;
115mod events;
116mod fit;
117mod inline;
118mod line;
119mod line_style;
120mod list_indentation;
121mod macros;
122mod parse;
123mod rect;
124mod scrollbar_style;
125mod serde;
126mod skin;
127mod spacing;
128mod styled_char;
129mod table_border_chars;
130mod tbl;
131mod text;
132mod tokens;
133mod views;
134
135pub use {
136 area::{
137 compute_scrollbar,
138 terminal_size,
139 Area,
140 },
141 ask::*,
142 color::*,
143 composite::FmtComposite,
144 composite_kind::*,
145 compound_style::*,
146 coolor,
147 crokey::crossterm,
148 crossbeam,
149 displayable_line::DisplayableLine,
150 errors::Error,
151 events::{
152 EventSource,
153 EventSourceOptions,
154 TickBeamId,
155 Ticker,
156 TimedEvent,
157 },
158 fit::*,
159 inline::FmtInline,
160 line::FmtLine,
161 line_style::LineStyle,
162 list_indentation::*,
163 minimad::{
164 self,
165 Alignment,
166 },
167 parse::*,
168 rect::*,
169 scrollbar_style::ScrollBarStyle,
170 skin::MadSkin,
171 spacing::Spacing,
172 styled_char::StyledChar,
173 table_border_chars::*,
174 text::FmtText,
175 tbl::*,
176 views::{
177 InputField,
178 ListView,
179 ListViewCell,
180 ListViewColumn,
181 MadView,
182 ProgressBar,
183 TextView,
184 },
185};
186
187use tokens::*;
188
189/// Return a reference to the global skin
190///
191/// If you want a new default skin so that you can set
192/// colors or styles, get a separate instance
193/// with `Skin::default()` instead.
194pub fn get_default_skin() -> &'static MadSkin {
195 use minimad::once_cell::sync::Lazy;
196 static DEFAULT_SKIN: Lazy<MadSkin> = Lazy::new(MadSkin::default);
197 &DEFAULT_SKIN
198}
199
200/// Return a formatted line, which implements Display.
201///
202/// This uses the default skin.
203/// Don't use if you expect your markdown to be several lines.
204pub fn inline(src: &str) -> FmtInline<'_, '_> {
205 get_default_skin().inline(src)
206}
207
208/// Return an unwrapped formatted text, implementing Display.
209///
210/// This uses the default skin and doesn't wrap the lines
211/// at all. Most often you'll prefer to use `term_text`
212/// which makes a text wrapped for the current terminal.
213pub fn text(src: &str) -> FmtText<'_, '_> {
214 get_default_skin().text(src, None)
215}
216
217/// Return a terminal wrapped formatted text, implementing Display.
218///
219/// This uses the default skin and the terminal's width
220pub fn term_text(src: &str) -> FmtText<'_, '_> {
221 get_default_skin().term_text(src)
222}
223
224/// Write a string interpreted as markdown with the default skin.
225pub fn print_inline(src: &str) {
226 get_default_skin().print_inline(src);
227}
228
229/// Write a text interpreted as markdown with the default skin.
230pub fn print_text(src: &str) {
231 get_default_skin().print_text(src);
232}