From 5fde013747e9cec3460d04b77a8d52729c051602 Mon Sep 17 00:00:00 2001 From: rhysd Date: Fri, 17 Jun 2022 02:07:12 +0900 Subject: [PATCH] add `single_line` example --- Cargo.toml | 4 ++ README.md | 3 ++ examples/single_line.rs | 88 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 95 insertions(+) create mode 100644 examples/single_line.rs diff --git a/Cargo.toml b/Cargo.toml index ec44c31..0ddc75d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,3 +28,7 @@ required-features = ["crossterm"] [[example]] name = "multi" required-features = ["crossterm"] + +[[example]] +name = "single_line" +required-features = ["crossterm"] diff --git a/README.md b/README.md index 565ad15..20de35c 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,7 @@ cargo run --example minimal - [minimal](./examples/minimal.rs): Minimal usage with [crossterm][] support - [termion](./examples/termion.rs): Minimal usage with [termion][] support - [multi](./examples/multi.rs): Two split textareas in a screen and switch them +- [single_line](./examples/single_line.rs): Single line input form with float number validation - [editor](./examples/editor.rs): Simple text editor to edit multiple files ## Minimal Usage @@ -284,6 +285,8 @@ loop { let text = textarea.into_lines().remove(0); // Get input text ``` +See [`single_line` example](./examples/single_line.rs) for working example. + ### Define your own key mappings All editor operations are defined as public methods of `TextArea`. To move cursor, use `tui_textarea::CursorMove` to diff --git a/examples/single_line.rs b/examples/single_line.rs new file mode 100644 index 0000000..b47aa0a --- /dev/null +++ b/examples/single_line.rs @@ -0,0 +1,88 @@ +use crossterm::event::{DisableMouseCapture, EnableMouseCapture}; +use crossterm::terminal::{ + disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen, +}; +use std::io; +use tui::backend::CrosstermBackend; +use tui::layout::{Constraint, Layout}; +use tui::style::{Color, Style}; +use tui::widgets::{Block, Borders}; +use tui::Terminal; +use tui_textarea::{Input, Key, TextArea}; + +fn update(textarea: &mut TextArea) -> bool { + if let Err(err) = textarea.lines()[0].parse::() { + textarea.set_style(Style::default().fg(Color::LightRed)); + textarea.set_block( + Block::default() + .borders(Borders::ALL) + .title(format!("ERROR: {}", err)), + ); + false + } else { + textarea.set_style(Style::default().fg(Color::LightGreen)); + textarea.set_block(Block::default().borders(Borders::ALL).title("OK")); + true + } +} + +fn main() -> io::Result<()> { + let stdout = io::stdout(); + let mut stdout = stdout.lock(); + + enable_raw_mode()?; + crossterm::execute!(stdout, EnterAlternateScreen, EnableMouseCapture)?; + let backend = CrosstermBackend::new(stdout); + let mut term = Terminal::new(backend)?; + + let mut textarea = TextArea::default(); + textarea.set_block( + Block::default() + .borders(Borders::ALL) + .title("Single Line Input"), + ); + textarea.set_cursor_line_style(Style::default()); + let layout = + Layout::default().constraints([Constraint::Length(3), Constraint::Min(1)].as_slice()); + let mut is_valid = update(&mut textarea); + + loop { + term.draw(|f| { + let chunks = layout.split(f.size()); + let widget = textarea.widget(); + f.render_widget(widget, chunks[0]); + })?; + + match Input::from(crossterm::event::read()?) { + Input { key: Key::Esc, .. } => break, + Input { + key: Key::Enter, .. + } if is_valid => break, + Input { + key: Key::Char('m'), + ctrl: true, + .. + } + | Input { + key: Key::Enter, .. + } => {} + input => { + // TextArea::input returns if the input modified its text + if textarea.input(input) { + is_valid = update(&mut textarea); + } + } + } + } + + disable_raw_mode()?; + crossterm::execute!( + term.backend_mut(), + LeaveAlternateScreen, + DisableMouseCapture + )?; + term.show_cursor()?; + + println!("Input: {:?}", textarea.lines()[0]); + Ok(()) +}