Renderer

Struct Renderer 

Source
pub struct Renderer<W: Write> { /* private fields */ }
Expand description

A struct that outputs lines to a writer.

Implementations§

Source§

impl<W: Write> Renderer<W>

Source

pub fn new(writer: W) -> Self

Creates a new Renderer that writes to the given writer.

Examples found in repository?
examples/input.rs (line 15)
13fn main() -> std::io::Result<()> {
14    let stdout = std::io::stdout().into_raw_mode()?;
15    let mut r = Renderer::new(stdout);
16
17    let mut name = String::new();
18
19    let mut events = std::io::stdin().events();
20    loop {
21        r.reset()?
22            .render((
23                "Enter your name: ".into_element(),
24                (name.into_element(), Cursor, Gap(1))
25                    .fixed_width(20)
26                    .truncated(Direction::Left)
27                    .styled(Style::bg(240)),
28            ))?
29            .finish()?;
30
31        let Some(event) = events.next().transpose()? else {
32            break;
33        };
34        match event {
35            Event::Key(Key::Char(ch)) if !ch.is_ascii_control() => name.push(ch),
36            Event::Key(Key::Char('\n' | '\r')) => break,
37            Event::Key(Key::Backspace) => {
38                name.pop();
39            }
40            _ => {}
41        }
42    }
43
44    r.clear()?;
45    drop(r);
46    println!("Your name is {name:?}");
47    Ok(())
48}
More examples
Hide additional examples
examples/tic_tac_toe.rs (line 71)
69fn main() -> io::Result<()> {
70    let stdout = io::stdout().into_raw_mode()?;
71    let mut r = Renderer::new(stdout);
72    let mut events = std::io::stdin().events();
73
74    let mut game = TicTacToe::default();
75    let (mut row, mut col): (usize, usize) = (1, 1);
76    loop {
77        // Render the grid
78        r.reset()?;
79        for (i, line) in game.grid.iter().enumerate() {
80            if i != 0 {
81                r.render("--+---+--".into_element())?;
82            }
83            r.render((
84                ((row, col) == (i, 0)).then_some(Cursor),
85                render_player(line[0]),
86                " | ".into_element(),
87                ((row, col) == (i, 1)).then_some(Cursor),
88                render_player(line[1]),
89                " | ".into_element(),
90                ((row, col) == (i, 2)).then_some(Cursor),
91                render_player(line[2]),
92            ))?;
93        }
94
95        // Check if someone won
96        let result = game.check_win();
97        match result {
98            Some(Some(winner)) => {
99                r.render((
100                    "The winner is ".into_element(),
101                    render_player(Some(winner)),
102                    "!".into_element(),
103                ))?;
104            }
105            Some(None) => {
106                r.render("The game is a draw.".into_element())?;
107            }
108            _ => {}
109        }
110
111        r.finish()?;
112        if result.is_some() {
113            r.leave()?;
114            break;
115        }
116
117        // Poll an input
118        let Some(event) = events.next() else {
119            break;
120        };
121        match event? {
122            Event::Key(Key::Up) => row = row.checked_sub(1).unwrap_or(2),
123            Event::Key(Key::Down) => row = (row + 1) % 3,
124            Event::Key(Key::Left) => col = col.checked_sub(1).unwrap_or(2),
125            Event::Key(Key::Right) => col = (col + 1) % 3,
126            Event::Key(Key::Char(' ' | '\n' | '\r')) => game.place(row, col),
127            _ => {}
128        }
129    }
130
131    Ok(())
132}
Source

pub fn reset(&mut self) -> Result<&mut Self>

Resets the cursor position, allowing rendering to start over.

Examples found in repository?
examples/input.rs (line 21)
13fn main() -> std::io::Result<()> {
14    let stdout = std::io::stdout().into_raw_mode()?;
15    let mut r = Renderer::new(stdout);
16
17    let mut name = String::new();
18
19    let mut events = std::io::stdin().events();
20    loop {
21        r.reset()?
22            .render((
23                "Enter your name: ".into_element(),
24                (name.into_element(), Cursor, Gap(1))
25                    .fixed_width(20)
26                    .truncated(Direction::Left)
27                    .styled(Style::bg(240)),
28            ))?
29            .finish()?;
30
31        let Some(event) = events.next().transpose()? else {
32            break;
33        };
34        match event {
35            Event::Key(Key::Char(ch)) if !ch.is_ascii_control() => name.push(ch),
36            Event::Key(Key::Char('\n' | '\r')) => break,
37            Event::Key(Key::Backspace) => {
38                name.pop();
39            }
40            _ => {}
41        }
42    }
43
44    r.clear()?;
45    drop(r);
46    println!("Your name is {name:?}");
47    Ok(())
48}
More examples
Hide additional examples
examples/tic_tac_toe.rs (line 78)
69fn main() -> io::Result<()> {
70    let stdout = io::stdout().into_raw_mode()?;
71    let mut r = Renderer::new(stdout);
72    let mut events = std::io::stdin().events();
73
74    let mut game = TicTacToe::default();
75    let (mut row, mut col): (usize, usize) = (1, 1);
76    loop {
77        // Render the grid
78        r.reset()?;
79        for (i, line) in game.grid.iter().enumerate() {
80            if i != 0 {
81                r.render("--+---+--".into_element())?;
82            }
83            r.render((
84                ((row, col) == (i, 0)).then_some(Cursor),
85                render_player(line[0]),
86                " | ".into_element(),
87                ((row, col) == (i, 1)).then_some(Cursor),
88                render_player(line[1]),
89                " | ".into_element(),
90                ((row, col) == (i, 2)).then_some(Cursor),
91                render_player(line[2]),
92            ))?;
93        }
94
95        // Check if someone won
96        let result = game.check_win();
97        match result {
98            Some(Some(winner)) => {
99                r.render((
100                    "The winner is ".into_element(),
101                    render_player(Some(winner)),
102                    "!".into_element(),
103                ))?;
104            }
105            Some(None) => {
106                r.render("The game is a draw.".into_element())?;
107            }
108            _ => {}
109        }
110
111        r.finish()?;
112        if result.is_some() {
113            r.leave()?;
114            break;
115        }
116
117        // Poll an input
118        let Some(event) = events.next() else {
119            break;
120        };
121        match event? {
122            Event::Key(Key::Up) => row = row.checked_sub(1).unwrap_or(2),
123            Event::Key(Key::Down) => row = (row + 1) % 3,
124            Event::Key(Key::Left) => col = col.checked_sub(1).unwrap_or(2),
125            Event::Key(Key::Right) => col = (col + 1) % 3,
126            Event::Key(Key::Char(' ' | '\n' | '\r')) => game.place(row, col),
127            _ => {}
128        }
129    }
130
131    Ok(())
132}
Source

pub fn clear(&mut self) -> Result<()>

Clears the UI, resetting the terminal back to its initial state.

Note that this method is automatically called when the Renderer is dropped.

Examples found in repository?
examples/input.rs (line 44)
13fn main() -> std::io::Result<()> {
14    let stdout = std::io::stdout().into_raw_mode()?;
15    let mut r = Renderer::new(stdout);
16
17    let mut name = String::new();
18
19    let mut events = std::io::stdin().events();
20    loop {
21        r.reset()?
22            .render((
23                "Enter your name: ".into_element(),
24                (name.into_element(), Cursor, Gap(1))
25                    .fixed_width(20)
26                    .truncated(Direction::Left)
27                    .styled(Style::bg(240)),
28            ))?
29            .finish()?;
30
31        let Some(event) = events.next().transpose()? else {
32            break;
33        };
34        match event {
35            Event::Key(Key::Char(ch)) if !ch.is_ascii_control() => name.push(ch),
36            Event::Key(Key::Char('\n' | '\r')) => break,
37            Event::Key(Key::Backspace) => {
38                name.pop();
39            }
40            _ => {}
41        }
42    }
43
44    r.clear()?;
45    drop(r);
46    println!("Your name is {name:?}");
47    Ok(())
48}
Source

pub fn render<'s, E: Element<'s>>(&mut self, line: E) -> Result<&mut Self>

Renders a line.

Examples found in repository?
examples/input.rs (lines 22-28)
13fn main() -> std::io::Result<()> {
14    let stdout = std::io::stdout().into_raw_mode()?;
15    let mut r = Renderer::new(stdout);
16
17    let mut name = String::new();
18
19    let mut events = std::io::stdin().events();
20    loop {
21        r.reset()?
22            .render((
23                "Enter your name: ".into_element(),
24                (name.into_element(), Cursor, Gap(1))
25                    .fixed_width(20)
26                    .truncated(Direction::Left)
27                    .styled(Style::bg(240)),
28            ))?
29            .finish()?;
30
31        let Some(event) = events.next().transpose()? else {
32            break;
33        };
34        match event {
35            Event::Key(Key::Char(ch)) if !ch.is_ascii_control() => name.push(ch),
36            Event::Key(Key::Char('\n' | '\r')) => break,
37            Event::Key(Key::Backspace) => {
38                name.pop();
39            }
40            _ => {}
41        }
42    }
43
44    r.clear()?;
45    drop(r);
46    println!("Your name is {name:?}");
47    Ok(())
48}
More examples
Hide additional examples
examples/tic_tac_toe.rs (line 81)
69fn main() -> io::Result<()> {
70    let stdout = io::stdout().into_raw_mode()?;
71    let mut r = Renderer::new(stdout);
72    let mut events = std::io::stdin().events();
73
74    let mut game = TicTacToe::default();
75    let (mut row, mut col): (usize, usize) = (1, 1);
76    loop {
77        // Render the grid
78        r.reset()?;
79        for (i, line) in game.grid.iter().enumerate() {
80            if i != 0 {
81                r.render("--+---+--".into_element())?;
82            }
83            r.render((
84                ((row, col) == (i, 0)).then_some(Cursor),
85                render_player(line[0]),
86                " | ".into_element(),
87                ((row, col) == (i, 1)).then_some(Cursor),
88                render_player(line[1]),
89                " | ".into_element(),
90                ((row, col) == (i, 2)).then_some(Cursor),
91                render_player(line[2]),
92            ))?;
93        }
94
95        // Check if someone won
96        let result = game.check_win();
97        match result {
98            Some(Some(winner)) => {
99                r.render((
100                    "The winner is ".into_element(),
101                    render_player(Some(winner)),
102                    "!".into_element(),
103                ))?;
104            }
105            Some(None) => {
106                r.render("The game is a draw.".into_element())?;
107            }
108            _ => {}
109        }
110
111        r.finish()?;
112        if result.is_some() {
113            r.leave()?;
114            break;
115        }
116
117        // Poll an input
118        let Some(event) = events.next() else {
119            break;
120        };
121        match event? {
122            Event::Key(Key::Up) => row = row.checked_sub(1).unwrap_or(2),
123            Event::Key(Key::Down) => row = (row + 1) % 3,
124            Event::Key(Key::Left) => col = col.checked_sub(1).unwrap_or(2),
125            Event::Key(Key::Right) => col = (col + 1) % 3,
126            Event::Key(Key::Char(' ' | '\n' | '\r')) => game.place(row, col),
127            _ => {}
128        }
129    }
130
131    Ok(())
132}
Source

pub fn finish(&mut self) -> Result<()>

Finishes rendering. This should be called immediately after the render calls are complete.

Examples found in repository?
examples/input.rs (line 29)
13fn main() -> std::io::Result<()> {
14    let stdout = std::io::stdout().into_raw_mode()?;
15    let mut r = Renderer::new(stdout);
16
17    let mut name = String::new();
18
19    let mut events = std::io::stdin().events();
20    loop {
21        r.reset()?
22            .render((
23                "Enter your name: ".into_element(),
24                (name.into_element(), Cursor, Gap(1))
25                    .fixed_width(20)
26                    .truncated(Direction::Left)
27                    .styled(Style::bg(240)),
28            ))?
29            .finish()?;
30
31        let Some(event) = events.next().transpose()? else {
32            break;
33        };
34        match event {
35            Event::Key(Key::Char(ch)) if !ch.is_ascii_control() => name.push(ch),
36            Event::Key(Key::Char('\n' | '\r')) => break,
37            Event::Key(Key::Backspace) => {
38                name.pop();
39            }
40            _ => {}
41        }
42    }
43
44    r.clear()?;
45    drop(r);
46    println!("Your name is {name:?}");
47    Ok(())
48}
More examples
Hide additional examples
examples/tic_tac_toe.rs (line 111)
69fn main() -> io::Result<()> {
70    let stdout = io::stdout().into_raw_mode()?;
71    let mut r = Renderer::new(stdout);
72    let mut events = std::io::stdin().events();
73
74    let mut game = TicTacToe::default();
75    let (mut row, mut col): (usize, usize) = (1, 1);
76    loop {
77        // Render the grid
78        r.reset()?;
79        for (i, line) in game.grid.iter().enumerate() {
80            if i != 0 {
81                r.render("--+---+--".into_element())?;
82            }
83            r.render((
84                ((row, col) == (i, 0)).then_some(Cursor),
85                render_player(line[0]),
86                " | ".into_element(),
87                ((row, col) == (i, 1)).then_some(Cursor),
88                render_player(line[1]),
89                " | ".into_element(),
90                ((row, col) == (i, 2)).then_some(Cursor),
91                render_player(line[2]),
92            ))?;
93        }
94
95        // Check if someone won
96        let result = game.check_win();
97        match result {
98            Some(Some(winner)) => {
99                r.render((
100                    "The winner is ".into_element(),
101                    render_player(Some(winner)),
102                    "!".into_element(),
103                ))?;
104            }
105            Some(None) => {
106                r.render("The game is a draw.".into_element())?;
107            }
108            _ => {}
109        }
110
111        r.finish()?;
112        if result.is_some() {
113            r.leave()?;
114            break;
115        }
116
117        // Poll an input
118        let Some(event) = events.next() else {
119            break;
120        };
121        match event? {
122            Event::Key(Key::Up) => row = row.checked_sub(1).unwrap_or(2),
123            Event::Key(Key::Down) => row = (row + 1) % 3,
124            Event::Key(Key::Left) => col = col.checked_sub(1).unwrap_or(2),
125            Event::Key(Key::Right) => col = (col + 1) % 3,
126            Event::Key(Key::Char(' ' | '\n' | '\r')) => game.place(row, col),
127            _ => {}
128        }
129    }
130
131    Ok(())
132}
Source

pub fn leave(&mut self) -> Result<()>

Leaves the currently-rendered text, making it impossible to clear.

This method may be used if you want to dispose of this Renderer without clearing the currently-rendered text. This should be called after finish.

Examples found in repository?
examples/tic_tac_toe.rs (line 113)
69fn main() -> io::Result<()> {
70    let stdout = io::stdout().into_raw_mode()?;
71    let mut r = Renderer::new(stdout);
72    let mut events = std::io::stdin().events();
73
74    let mut game = TicTacToe::default();
75    let (mut row, mut col): (usize, usize) = (1, 1);
76    loop {
77        // Render the grid
78        r.reset()?;
79        for (i, line) in game.grid.iter().enumerate() {
80            if i != 0 {
81                r.render("--+---+--".into_element())?;
82            }
83            r.render((
84                ((row, col) == (i, 0)).then_some(Cursor),
85                render_player(line[0]),
86                " | ".into_element(),
87                ((row, col) == (i, 1)).then_some(Cursor),
88                render_player(line[1]),
89                " | ".into_element(),
90                ((row, col) == (i, 2)).then_some(Cursor),
91                render_player(line[2]),
92            ))?;
93        }
94
95        // Check if someone won
96        let result = game.check_win();
97        match result {
98            Some(Some(winner)) => {
99                r.render((
100                    "The winner is ".into_element(),
101                    render_player(Some(winner)),
102                    "!".into_element(),
103                ))?;
104            }
105            Some(None) => {
106                r.render("The game is a draw.".into_element())?;
107            }
108            _ => {}
109        }
110
111        r.finish()?;
112        if result.is_some() {
113            r.leave()?;
114            break;
115        }
116
117        // Poll an input
118        let Some(event) = events.next() else {
119            break;
120        };
121        match event? {
122            Event::Key(Key::Up) => row = row.checked_sub(1).unwrap_or(2),
123            Event::Key(Key::Down) => row = (row + 1) % 3,
124            Event::Key(Key::Left) => col = col.checked_sub(1).unwrap_or(2),
125            Event::Key(Key::Right) => col = (col + 1) % 3,
126            Event::Key(Key::Char(' ' | '\n' | '\r')) => game.place(row, col),
127            _ => {}
128        }
129    }
130
131    Ok(())
132}

Trait Implementations§

Source§

impl<W: Write> Drop for Renderer<W>

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more

Auto Trait Implementations§

§

impl<W> Freeze for Renderer<W>
where W: Freeze,

§

impl<W> RefUnwindSafe for Renderer<W>
where W: RefUnwindSafe,

§

impl<W> Send for Renderer<W>
where W: Send,

§

impl<W> Sync for Renderer<W>
where W: Sync,

§

impl<W> Unpin for Renderer<W>
where W: Unpin,

§

impl<W> UnwindSafe for Renderer<W>
where W: UnwindSafe,

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.