Skip to content

Commit 5638a62

Browse files
joshkasayanarijit
authored andcommitted
feat: rewrite crossterm example
Fix up crossterm code by: - ensure errors when rendering / reading do not prevent restoring terminal - handle accept / cancel of the prompt - add a label (change logic to prompt for a name, and greet the person) - import crossterm instead of ratatui::crossterm to make it clear that this is not a ratatui example - remove mouse input - decompose into logical functions - add comments
1 parent bee29c3 commit 5638a62

File tree

2 files changed

+58
-32
lines changed

2 files changed

+58
-32
lines changed

Cargo.toml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,13 @@ termion = ["dep:termion"]
2020

2121
[dependencies]
2222
ratatui = { version = "0.29", optional = true }
23-
serde = { version = "1.0.213", optional = true, features = ["derive"] }
24-
termion = { version = "4.0.3", optional = true }
23+
serde = { version = "1.0.218", optional = true, features = ["derive"] }
24+
termion = { version = "4.0.4", optional = true }
2525
unicode-width = "0.2.0"
2626

27+
[dev-dependencies]
28+
crossterm = { version = "0.28.1" }
29+
2730
[[example]]
2831
name = "crossterm_input"
2932
path = "./examples/crossterm_input.rs"

examples/crossterm_input.rs

Lines changed: 53 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,75 @@
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,
512
terminal::{
613
disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen,
714
},
815
};
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+
};
1320

14-
fn main() -> Result<()> {
21+
fn main() -> io::Result<()> {
1522
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)?;
1925

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)?;
2349

2450
loop {
2551
let event = read()?;
26-
2752
if let Event::Key(KeyEvent { code, .. }) = event {
2853
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())),
3256
_ => {
3357
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)?;
4259
}
4360
}
4461
}
4562
}
4663
}
64+
}
4765

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()?;
5174
Ok(())
5275
}

0 commit comments

Comments
 (0)