#input #tui #ratatui #terminal #input-event

terminput

TUI input parser/encoder and abstraction over input backends

4 releases

new 0.2.1 Jan 22, 2025
0.2.0 Jan 22, 2025
0.1.1 Jan 22, 2025
0.1.0 Jan 22, 2025

#275 in Command-line interface

Download history 423/week @ 2025-01-19

423 downloads per month

MIT/Apache

155KB
3.5K SLoC

terminput

crates.io docs.rs Dependency Status license CI codecov GitHub repo size Lines of Code

A library to abstract over various backends that provide input events, such as key presses and mouse clicks. This was mainly created as a common interface to the terminal backends that Ratatui supports.

Many TUI libraries want to support input from multiple backends, but mapping each backend's input structure into a common interface can be tedious. This library aims to provide a uniform interface to these types.

Additionally, we supply methods for parsing and encoding ANSI escape sequences for events.

Usage

Use try_into to convert to and from terminput's event types.

use crossterm::event::read;
use std::io;
use terminput::Event;

fn main() -> io::Result<()> {
    let crossterm_event = read()?;
    let event: Result<Event, _> = crossterm_event.try_into();
    println!("{event:?}");

    if let Ok(event) = event {
        // Conversions work both ways
        let event2: Result<crossterm::event::Event, _> = event.try_into();
        println!("{event2:?}");
    }

    Ok(())
}

Backends

The following backends are currently supported. All backends are disabled by default and each can be enabled with a feature flag of the same name.

The Event struct provided by this library is an attempt to create a superset of all supported backend functionality that TUI apps may be interested in.

The following table shows the matrix of supported features:

crossterm termion termwiz egui
key press
key release/repeat
mouse down
mouse up
mouse move
mouse drag
focus
paste
resize

Parsing

Use the Event::parse_from method to parse an ANSI-encoded sequence of bytes into an event struct. This can be helpful for usage with SSH or other situations where you need to read raw input from something other than a normal TTY device.

The input parser used here was extracted from crossterm's implementation.

use terminput::Event;

fn read_input(input: &[u8]) {
    let event = Event::parse_from(input);

    match event {
        Ok(Some(event)) => {
            println!("Successfully parsed input: {event:?}");
        }
        Ok(None) => {
            println!("More input required");
        }
        Err(e) => {
            println!("Unable to parse input: {e:?}");
        }
    }
}

Encoding

Input structs can also be encoded into ANSI escape sequences using Event::encode. This can be useful if you're controlling a child pty and need to send it some encoded input.

use terminput::{Encoding, Event, KeyCode, KeyEvent, KittyFlags};

let event = Event::Key(KeyEvent::new(KeyCode::Char('a')));
let mut buf = [0; 16];

// Legacy encoding
let written = event.encode(&mut buf, Encoding::Xterm);
if let Ok(written) = written {
    println!("Encoded: {:?}", &buf[..written]);
}

// Kitty encoding
let mut buf = [0; 16];
let written = event.encode(&mut buf, Encoding::Kitty(KittyFlags::all()));
if let Ok(written) = written {
    println!("Encoded: {:?}", &buf[..written]);
}

Dependencies

~0–13MB
~181K SLoC