Expand description
reedline \|/
A readline replacement written in Rust
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.
Basic example
// 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 = line_editor.read_line(&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
// Configure reedline with custom keybindings
//Cargo.toml
// [dependencies]
// crossterm = "*"
use {
crossterm::event::{KeyCode, KeyModifiers},
reedline::{default_emacs_keybindings, EditCommand, Reedline, Emacs, ReedlineEvent},
};
let mut keybindings = default_emacs_keybindings();
keybindings.add_binding(
KeyModifiers::ALT,
KeyCode::Char('m'),
ReedlineEvent::Edit(vec![EditCommand::BackspaceWord]),
);
let edit_mode = Box::new(Emacs::new(keybindings));
let mut line_editor = Reedline::create().with_edit_mode(edit_mode);
Integrate with History
// Create a reedline object with history support, including history size limits
use reedline::{FileBackedHistory, Reedline};
let history = Box::new(
FileBackedHistory::with_file(5, "history.txt".into())
.expect("Error configuring history with file"),
);
let mut line_editor = Reedline::create()
.with_history(history);
Integrate with custom syntax Highlighter
// 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 line_editor =
Reedline::create().with_highlighter(Box::new(ExampleHighlighter::new(commands)));
Integrate with custom tab completion
// Create a reedline object with tab completions support
use reedline::{ColumnarMenu, DefaultCompleter, Reedline, ReedlineMenu};
let commands = vec![
"test".into(),
"hello world".into(),
"hello world reedline".into(),
"this is the reedline crate".into(),
];
let completer = Box::new(DefaultCompleter::new_with_wordlen(commands.clone(), 2));
// Use the interactive menu to select options from the completer
let completion_menu = Box::new(ColumnarMenu::default().with_name("completion_menu"));
let mut line_editor =
Reedline::create().with_completer(completer).with_menu(ReedlineMenu::EngineCompleter(completion_menu));
Integrate with Hinter
for fish-style history autosuggestions
// Create a reedline object with in-line hint support
//Cargo.toml
// [dependencies]
// nu-ansi-term = "*"
use {
nu_ansi_term::{Color, Style},
reedline::{DefaultHinter, Reedline},
};
let mut line_editor = Reedline::create().with_hinter(Box::new(
DefaultHinter::default()
.with_style(Style::new().italic().fg(Color::LightGray)),
));
Integrate with custom line completion Validator
// Create a reedline object with line completion validation support
use reedline::{DefaultValidator, Reedline};
let validator = Box::new(DefaultValidator);
let mut line_editor = Reedline::create().with_validator(validator);
Use custom EditMode
// Create a reedline object with custom edit mode
// This can define a keybinding setting or enable vi-emulation
use reedline::{
default_vi_insert_keybindings, default_vi_normal_keybindings, EditMode, Reedline, Vi,
};
let mut line_editor = Reedline::create().with_edit_mode(Box::new(Vi::new(
default_vi_insert_keybindings(),
default_vi_normal_keybindings(),
)));
Crate features
clipboard
: Enable support to use theSystemClipboard
. Enabling this feature will return aSystemClipboard
instead of a local clipboard when callingget_default_clipboard()
.bashisms
: Enable support for special text sequences that recall components from the history. e.g.!!
and!$
. For use in shells likebash
ornushell
.sqlite
: Provides theSqliteBackedHistory
to store richer information in the history. Statically links the required sqlite version.sqlite-dynlib
: Alternative to the featuresqlite
. Will not statically link. Requiressqlite >= 3.38
to link dynamically!external_printer
: Experimental: Thread-safeExternalPrinter
handle to print lines from concurrently running threads.
Are we prompt yet? (Development status)
Nushell has now all the basic features to become the primary line editor for nushell
- General editing functionality, that should feel familiar coming from other shells (e.g. bash, fish, zsh).
- Configurable keybindings (emacs-style bindings and basic vi-style).
- Configurable prompt
- Content-aware syntax highlighting.
- Autocompletion (With graphical selection menu or simple cycling inline).
- History with interactive search options (optionally persists to file, can support multilple sessions accessing the same file)
- Fish-style history autosuggestion hints
- Undo support.
- Clipboard integration
- Line completeness validation for seamless entry of multiline command sequences.
Areas for future improvements
- Support for Unicode beyond simple left-to-right scripts
- Easier keybinding configuration
- Support for more advanced vi commands
- Visual selection
- Smooth experience if completion or prompt content takes long to compute
- Support for a concurrent output stream from background tasks to be displayed, while the input prompt is active. (“Full duplex” mode)
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 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:
Modules
Structs
Prompt
displaying the current working directory and the time above the entry line.LineBuffer
HistoryItem
History
History
Event
s like a Vi-Style editorEnums
History
History
SearchQuery
Reedline::read_line()
can returnUndoBehavior
tag, which can be used to
calculate how the change should be reflected on the undo stackConstants
FileBackedHistory
used when calling FileBackedHistory::default()
Traits
StyledText
object, which represents the contents of the original line as styled stringsJSONL
file, in a SQLite
databaseFunctions
Vec<(String, String, String, String)>
where String 1 is mode
, String 2 is key_modifiers
, String 3 is key_code
, and
Sting 4 is event
Vec<String>
of the Reedline EditCommand
sVec
of the Reedline Keybinding ModifiersVec<String>
of the Reedline KeyCode
sVec<String>
of the Reedline PromptEditMode
sVec<String>
of the Reedline ReedlineEvent
s