tty-text 2.0.0

Provides agnostic text editing state management.
Documentation
use std::io::{stdout, Stdout, Write};

use crossterm::{
    cursor,
    event::{self, KeyCode, KeyModifiers},
    queue,
    style::Print,
    terminal::{self, enable_raw_mode},
    Result,
};
use tty_text::{Key, Text};

/// A simple, single-line CLI text editor built with crossterm.
fn main() {
    execute().expect("execute basic single-line example");
}

fn execute() -> Result<()> {
    let mut stdout = stdout();
    let mut text = Text::new(false);

    enable_raw_mode()?;
    render(&mut stdout, &text)?;

    loop {
        let event = event::read()?;

        if let event::Event::Key(key_event) = event {
            if key_event.modifiers == KeyModifiers::CONTROL && key_event.code == KeyCode::Char('c')
            {
                break;
            }

            match key_event.code {
                KeyCode::Esc => break,
                KeyCode::Char(ch) => text.handle_input(Key::Char(ch)),
                KeyCode::Backspace => text.handle_input(Key::Backspace),
                KeyCode::Left => text.handle_input(Key::Left),
                KeyCode::Right => text.handle_input(Key::Right),
                _ => {}
            }
        }

        render(&mut stdout, &text)?;
    }

    Ok(())
}

fn render(stdout: &mut Stdout, text: &Text) -> Result<()> {
    queue!(stdout, terminal::Clear(terminal::ClearType::All))?;

    queue!(stdout, cursor::MoveTo(0, 0))?;
    queue!(
        stdout,
        Print("Enter text (arrows to move cursor, Ctrl/Cmd+C or Esc to quit):")
    )?;

    queue!(stdout, cursor::MoveTo(0, 1))?;
    queue!(stdout, Print(text.value()))?;

    let position = text.cursor();
    let (x, y) = (position.0 as u16, position.1 as u16);
    queue!(stdout, cursor::MoveTo(x, y + 1))?;

    stdout.flush()?;

    Ok(())
}