|
1 |
| -use ratatui::crossterm::{ |
2 |
| - cursor::{Hide, Show}, |
3 |
| - event::{read, DisableMouseCapture, EnableMouseCapture, Event, KeyCode, KeyEvent}, |
4 |
| - execute, |
| 1 | +//! This example demonstrates how to use the `tui_input` crate with the `crossterm` backend. |
| 2 | +//! The example prompts the user for their name and prints a greeting. |
| 3 | +//! The user can cancel the input by pressing `Esc` or accept the input by pressing `Enter`. |
| 4 | +
|
| 5 | +use std::io::{self, stdout, Write}; |
| 6 | + |
| 7 | +use crossterm::{ |
| 8 | + cursor::{Hide, MoveTo, Show}, |
| 9 | + event::{read, Event, KeyCode, KeyEvent}, |
| 10 | + execute, queue, |
| 11 | + style::Print, |
5 | 12 | terminal::{
|
6 | 13 | disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen,
|
7 | 14 | },
|
8 | 15 | };
|
9 |
| -use std::io::{stdout, Result, Write}; |
10 |
| -use tui_input::backend::crossterm as backend; |
11 |
| -use tui_input::backend::crossterm::EventHandler; |
12 |
| -use tui_input::Input; |
| 16 | +use tui_input::{ |
| 17 | + backend::crossterm::{self as backend, EventHandler}, |
| 18 | + Input, |
| 19 | +}; |
13 | 20 |
|
14 |
| -fn main() -> Result<()> { |
| 21 | +fn main() -> io::Result<()> { |
15 | 22 | enable_raw_mode()?;
|
16 |
| - let stdout = stdout(); |
17 |
| - let mut stdout = stdout.lock(); |
18 |
| - execute!(stdout, Hide, EnterAlternateScreen, EnableMouseCapture)?; |
| 23 | + let mut stdout = stdout().lock(); |
| 24 | + execute!(stdout, Hide, EnterAlternateScreen)?; |
19 | 25 |
|
20 |
| - let mut input: Input = "Hello ".into(); |
21 |
| - backend::write(&mut stdout, input.value(), input.cursor(), (0, 0), 15)?; |
22 |
| - stdout.flush()?; |
| 26 | + let name = get_user_name(&mut stdout); |
| 27 | + |
| 28 | + execute!(stdout, Show, LeaveAlternateScreen)?; |
| 29 | + disable_raw_mode()?; |
| 30 | + |
| 31 | + match name? { |
| 32 | + Some(name) => println!("Hello {name}!"), |
| 33 | + None => println!("Goodbye!"), |
| 34 | + } |
| 35 | + Ok(()) |
| 36 | +} |
| 37 | + |
| 38 | +/// Prompts the user for their name. |
| 39 | +/// |
| 40 | +/// Returns `None` if the user cancels the input otherwise returns the user's name. If the user |
| 41 | +/// presses `Esc` the input is cancelled. If the user presses `Enter` the input is accepted. |
| 42 | +/// |
| 43 | +/// # Errors |
| 44 | +/// |
| 45 | +/// Returns an error if reading or writing to the terminal fails. |
| 46 | +fn get_user_name(stdout: &mut impl Write) -> io::Result<Option<String>> { |
| 47 | + let mut input = Input::from("World"); |
| 48 | + render_prompt(stdout, &input)?; |
23 | 49 |
|
24 | 50 | loop {
|
25 | 51 | let event = read()?;
|
26 |
| - |
27 | 52 | if let Event::Key(KeyEvent { code, .. }) = event {
|
28 | 53 | match code {
|
29 |
| - KeyCode::Esc | KeyCode::Enter => { |
30 |
| - break; |
31 |
| - } |
| 54 | + KeyCode::Esc => return Ok(None), |
| 55 | + KeyCode::Enter => return Ok(Some(input.to_string())), |
32 | 56 | _ => {
|
33 | 57 | if input.handle_event(&event).is_some() {
|
34 |
| - backend::write( |
35 |
| - &mut stdout, |
36 |
| - input.value(), |
37 |
| - input.cursor(), |
38 |
| - (0, 0), |
39 |
| - 15, |
40 |
| - )?; |
41 |
| - stdout.flush()?; |
| 58 | + render_prompt(stdout, &input)?; |
42 | 59 | }
|
43 | 60 | }
|
44 | 61 | }
|
45 | 62 | }
|
46 | 63 | }
|
| 64 | +} |
47 | 65 |
|
48 |
| - execute!(stdout, Show, LeaveAlternateScreen, DisableMouseCapture)?; |
49 |
| - disable_raw_mode()?; |
50 |
| - println!("{}", input); |
| 66 | +fn render_prompt(stdout: &mut impl Write, input: &Input) -> io::Result<()> { |
| 67 | + const LABEL: &str = "Name: "; |
| 68 | + const POSITION: (u16, u16) = (LABEL.len() as u16, 0); |
| 69 | + const WIDTH: u16 = 15; |
| 70 | + |
| 71 | + queue!(stdout, MoveTo(0, 0), Print(LABEL))?; |
| 72 | + backend::write(stdout, input.value(), input.cursor(), POSITION, WIDTH)?; |
| 73 | + stdout.flush()?; |
51 | 74 | Ok(())
|
52 | 75 | }
|
0 commit comments