ruterm
1use crate::{
2cursor::{
3self,
4Direction,
5},
6error::Result,
7io::write_to,
8};
9use std::io::{
10self,
11Write,
12};
13
14pub const END: &str = "\n";
15
16/// Writes `text` to `output` in rendered form.
17///
18/// # Usage
19///
20/// ```no_run
21/// use ruterm::render::{
22/// render_to,
23/// END, // moves to the newline
24/// };
25/// use std::io;
26///
27/// let mut output = io::stdout();
28/// render_to(&mut output, vec!["* *", END, " * ", END, "* *", END]).unwrap();
29/// ```
30///
31/// You can apply style to the text:
32/// ```no_run
33/// use ruterm::{
34/// render::{
35/// render_to,
36/// END,
37/// },
38/// style::{
39/// color::fore,
40/// RESET,
41/// },
42/// };
43/// use std::io;
44///
45/// let mut output = io::stdout();
46/// render_to(
47/// &mut output,
48/// vec![
49/// fore::RED,
50/// "red",
51/// END,
52/// fore::GREEN,
53/// "green",
54/// END,
55/// fore::BLUE,
56/// "blue",
57/// RESET, // don't forget to reset style!
58/// ],
59/// ).unwrap();
60/// ```
61pub fn render_to<T>(output: &mut dyn Write, text: Vec<T>) -> Result<()>
62where
63T: ToString,
64{
65let mut shift = 0;
66for line in text {
67let line = line.to_string();
68match line.as_str() {
69END => {
70cursor::move_(Direction::Down, 1)?;
71cursor::move_(Direction::Left, shift)?;
72shift = 0;
73}
74_ => {
75write_to(output, line.as_bytes())?;
76if !line.starts_with("\x1b") {
77shift += line.len() as u16;
78}
79}
80}
81}
82Ok(())
83}
84
85/// Writes `text` to stdout in rendered form. Same as `render_to`.
86pub fn render<T>(text: Vec<T>) -> Result<()>
87where
88T: ToString,
89{
90render_to(&mut io::stdout(), text)
91}
92