A readline replacement written in Rust

GitHub Crates.io docs.rs GitHub Workflow Status Discord

Introduction

Reedline is a project to create a line editor (like bash's readline or zsh's zle) that supports many of the modern conveniences of CLIs, including syntax highlighting, completions, multiline support, Unicode support, and more. It is currently primarily developed as the interactive editor for nushell (starting with v0.60) striving to provide a pleasant interactive experience.

Outline

Examples

For the full documentation visit https://docs.rs/reedline. The examples should highlight how you enable the most important features or which traits can be implemented for language-specific behavior.

Basic example

```rust,no_run // Create a default reedline object to handle user input

use reedline::{DefaultPrompt, Reedline, Signal};

let mut line_editor = Reedline::create(); let prompt = DefaultPrompt::default();

loop { let sig = lineeditor.readline(&prompt); match sig { Ok(Signal::Success(buffer)) => { println!("We processed: {}", buffer); } Ok(Signal::CtrlD) | Ok(Signal::CtrlC) => { println!("\nAborted!"); break; } x => { println!("Event: {:?}", x); } } } ```

Integrate with custom keybindings

```rust // Configure reedline with custom keybindings

//Cargo.toml // [dependencies] // crossterm = "*"

use { crossterm::event::{KeyCode, KeyModifiers}, reedline::{defaultemacskeybindings, EditCommand, Reedline, Emacs, ReedlineEvent}, };

let mut keybindings = defaultemacskeybindings(); keybindings.addbinding( KeyModifiers::ALT, KeyCode::Char('m'), ReedlineEvent::Edit(vec![EditCommand::BackspaceWord]), ); let editmode = Box::new(Emacs::new(keybindings));

let mut lineeditor = Reedline::create().witheditmode(editmode); ```

Integrate with History

```rust,no_run // Create a reedline object with history support, including history size limits

use reedline::{FileBackedHistory, Reedline};

let history = Box::new( FileBackedHistory::withfile(5, "history.txt".into()) .expect("Error configuring history with file"), ); let mut lineeditor = Reedline::create() .with_history(history); ```

Integrate with custom syntax Highlighter

```rust // Create a reedline object with highlighter support

use reedline::{ExampleHighlighter, Reedline};

let commands = vec![ "test".into(), "hello world".into(), "hello world reedline".into(), "this is the reedline crate".into(), ]; let mut lineeditor = Reedline::create().withhighlighter(Box::new(ExampleHighlighter::new(commands))); ```

Integrate with custom tab completion

```rust // Create a reedline object with tab completions support

use reedline::{defaultemacskeybindings, ColumnarMenu, DefaultCompleter, Emacs, KeyCode, KeyModifiers, Reedline, ReedlineEvent, ReedlineMenu};

let commands = vec![ "test".into(), "hello world".into(), "hello world reedline".into(), "this is the reedline crate".into(), ]; let completer = Box::new(DefaultCompleter::newwithwordlen(commands.clone(), 2)); // Use the interactive menu to select options from the completer let completionmenu = Box::new(ColumnarMenu::default().withname("completionmenu")); // Set up the required keybindings let mut keybindings = defaultemacskeybindings(); keybindings.addbinding( KeyModifiers::NONE, KeyCode::Tab, ReedlineEvent::UntilFound(vec![ ReedlineEvent::Menu("completionmenu".tostring()), ReedlineEvent::MenuNext, ]), );

let edit_mode = Box::new(Emacs::new(keybindings));

let mut lineeditor = Reedline::create() .withcompleter(completer) .withmenu(ReedlineMenu::EngineCompleter(completionmenu)) .witheditmode(edit_mode); ```

Integrate with Hinter for fish-style history autosuggestions

```rust // Create a reedline object with in-line hint support

//Cargo.toml // [dependencies] // nu-ansi-term = "*"

use { nuansiterm::{Color, Style}, reedline::{DefaultHinter, Reedline}, };

let mut lineeditor = Reedline::create().withhinter(Box::new( DefaultHinter::default() .with_style(Style::new().italic().fg(Color::LightGray)), )); ```

Integrate with custom line completion Validator

```rust // Create a reedline object with line completion validation support

use reedline::{DefaultValidator, Reedline};

let validator = Box::new(DefaultValidator);

let mut lineeditor = Reedline::create().withvalidator(validator); ```

Use custom EditMode

```rust // Create a reedline object with custom edit mode // This can define a keybinding setting or enable vi-emulation

use reedline::{ defaultviinsertkeybindings, defaultvinormalkeybindings, EditMode, Reedline, Vi, };

let mut lineeditor = Reedline::create().witheditmode(Box::new(Vi::new( defaultviinsertkeybindings(), defaultvinormal_keybindings(), ))); ```

Crate features

Are we prompt yet? (Development status)

Reedline has now all the basic features to become the primary line editor for nushell

Areas for future improvements

For more ideas check out the feature discussion or hop on the #reedline channel of the nushell discord.

Development history

If you want to follow along with the history of how reedline got started, you can watch the recordings of JT's live-coding streams.

Playlist: Creating a line editor in Rust

Alternatives

For currently more mature Rust line editing check out: