mod common; use crossterm::event::{DisableMouseCapture, EnableMouseCapture}; use crossterm::terminal::{ EnterAlternateScreen, LeaveAlternateScreen, disable_raw_mode, enable_raw_mode, }; use ratatui::Terminal; use ratatui::backend::CrosstermBackend; use ratatui::layout::{Constraint, Direction, Layout}; use ratatui::widgets::{Block, Borders}; use std::cmp; use std::io; use tui_textarea::{Input, Key, TextArea}; fn main() -> io::Result<()> { let stdout = io::stdout(); let mut stdout = stdout.lock(); enable_raw_mode()?; crossterm::execute!(stdout, EnterAlternateScreen, EnableMouseCapture)?; let recording = common::maybe_force_recording_size(&mut stdout)?; 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("Textarea with Variable Height"), ); loop { term.draw(|f| { const MIN_HEIGHT: usize = 3; let measure = textarea.measure(f.area().width); let height = cmp::max(measure.preferred_rows as usize, MIN_HEIGHT) as u16; let chunks = Layout::default() .direction(Direction::Vertical) .constraints([Constraint::Length(height), Constraint::Min(0)]) .split(f.area()); f.render_widget(&textarea, chunks[0]); })?; match crossterm::event::read()?.into() { Input { key: Key::Esc, .. } => break, input => { textarea.input(input); } } } disable_raw_mode()?; crossterm::execute!( term.backend_mut(), LeaveAlternateScreen, DisableMouseCapture )?; recording.restore(term.backend_mut())?; term.show_cursor()?; println!("Lines: {:?}", textarea.lines()); Ok(()) }