EdTUI is a text editor widget for the Ratatui ecosystem.
It is designed to provide a user experience inspired by Vim. Edtui is developed to be used as an
editor in ratatui apps. It is not supposed to be a stand-alone code editor.
Create a new EditorState and render it using EditorView:
use edtui::{EditorState, EditorView};
use ratatui::widgets::Widget;
let mut state = EditorState::default();
EditorView::new(&mut state).render(area, buf);The view is configured through builder methods, see Customization.
Handle events (Vim mode by default):
use edtui::EditorEventHandler;
let mut event_handler = EditorEventHandler::default();
event_handler.on_key_event(key_event, &mut state);Or use Emacs mode (modeless editing):
use edtui::{EditorState, EditorEventHandler, Lines};
let mut state = EditorState::new(Lines::from("Hello World"));
let mut event_handler = EditorEventHandler::emacs_mode();
event_handler.on_key_event(key_event, &mut state);Or customize keybindings:
let mut key_handler = KeyEventHandler::vim_mode();
key_handler.insert(
KeyEventRegister::n(vec![KeyInput::ctrl('x')]),
SwitchMode(EditorMode::Insert),
);
let event_handler = EditorEventHandler::new(key_handler);EditorView is configured through builder methods:
| Method | Description |
|---|---|
.theme(EditorTheme) |
Sets the editor theme (see Theming). |
.wrap(bool) |
Enables line wrapping. |
.tab_width(usize) |
Number of spaces used to render a tab. |
.line_numbers(LineNumbers) |
Shows absolute or relative line numbers. |
.single_line(bool) |
Restricts the editor to a single line. |
.syntax_highlighter(Option<SyntaxHighlighter>) |
Enables syntax highlighting (syntax-highlighting feature). |
- Custom theming.
- Mouse events.
- Vim and Emacs keybindings.
- Copy paste using the systems clipboard.
- Line wrapping.
- Syntax highlighting.
- Line numbers (absolute and relative).
- System editor support (optional, via
system-editorfeature).
Customize the editor with EditorTheme:
use edtui::EditorTheme;
use ratatui::style::{Style, Color};
let theme = EditorTheme::default()
.base(Style::default().bg(Color::Black).fg(Color::White));The following builder methods are available:
| Method | Description |
|---|---|
.base(Style) |
Base text style. |
.block(Block) |
Surrounding block / border. |
.cursor_style(Style) |
Cursor style. |
.hide_cursor() |
Hides the cursor. |
.selection_style(Style) |
Style of the selected text. |
.line_numbers_style(Style) |
Style of the line numbers. |
.status_line(EditorStatusLine) |
Sets and styles the status line. |
.hide_status_line() |
Hides the status line. |
Display absolute or relative line numbers:
use edtui::{EditorView, EditorState, EditorTheme, LineNumbers};
use ratatui::style::{Style, Color};
EditorView::new(&mut EditorState::default())
.theme(EditorTheme::default().line_numbers_style(Style::default().fg(Color::DarkGray)))
.line_numbers(LineNumbers::Absolute) // or LineNumbers::Relative
.render(area, buf);For search boxes and single-line input fields, enable single-line mode to block newline insertion:
use edtui::{EditorState, EditorView};
let mut state = EditorState::default();
EditorView::new(&mut state)
.single_line(true)
.render(area, buf);When enabled, newline insertion is blocked and pasting text with newlines will replace them with spaces.
Edtui supports mouse input for moving the cursor and selecting text.
Mouse handling is enabled by default via a feature toggle.
Typically, mouse events are processed automatically when you call on_event:
let event_handler = EditorEventHandler::default();
event_handler.on_event(event, &mut state); // handles mouse events tooIf you want finer control you can handle mouse events explicitly using on_mouse_event:
event_handler.on_mouse_event(mouse_event, &mut state);Syntax highlighting was added in version 0.8.4.
Edtui offers a number of custom themes, see [SyntaxHighlighter::theme] for a complete list.
If you want to use a custom theme, see [SyntaxHighlighter::custom_theme]. Check syntect
for more details about themes and extensions.
use edtui::{EditorView, EditorState, SyntaxHighlighter};
let syntax_highlighter = SyntaxHighlighter::new("dracula", "rs");
EditorView::new(&mut EditorState::default())
.syntax_highlighter(Some(syntax_highlighter))
.render(area, buf);If you want to enable paste (via ctrl+y or cmd+y) you must explicitly enable it at the start of your app:
use ratatui::crossterm::event::EnableBracketedPaste;
let mut stdout = std::io::stdout();
ratatui::crossterm::xecute!(stdout, EnableBracketedPaste);and disable it during cleanup:
use ratatui::crossterm::event::DisableBracketedPaste;
ratatui::crossterm::execute!(std::io::stdout(), DisableBracketedPaste);See examples/app/term.rs for a an example.
With the system-editor feature enabled you can open the editor content in an external
text editor (e.g., nvim) using Ctrl+e in normal mode (or Alt+e in Emacs mode).
The system editor is decoupled from the event handler. After handling events, check
if a system editor request is pending and call open yourself:
use edtui::system_editor;
event_handler.on_event(event, &mut state);
if system_editor::is_pending(&state) {
system_editor::open(&mut state, &mut terminal)?;
// Re-enable mouse capture or other terminal modes if necessary
// crossterm::execute!(stdout(), EnableMouseCapture, EnableBracketedPaste)?;
}The editor used is determined by the VISUAL or EDITOR environment variables,
falling back to a platform-specific default if neither is set.
EdTUI offers Vim keybindings by default and Emacs keybindings as an alternative.
| Keybinding | Description |
|---|---|
i |
Enter Insert mode |
v |
Enter Visual mode |
h, j, k, l |
Navigate left, down, up, and right |
w |
Move forward to the start of a word |
e |
Move forward to the end of a word |
b |
Move backward to the start of a word |
f + <char> |
Move to the next occurrence of <char> on the line |
t + <char> |
Move just before the next occurrence of <char> |
ctrl+d |
Jump a half page down |
ctrl+u |
Jump a half page up |
PageDown |
Jump a full page down |
PageUp |
Jump a full page up |
x |
Delete the character under the cursor |
u, ctrl+r |
Undo/Redo last action |
Esc |
Escape Visual mode |
0 |
Move cursor to start of line |
_ |
Move cursor to first non-blank character |
$ |
Move cursor to end of line |
gg |
Move cursor to the first row |
G |
Move cursor to the last row |
% |
Move cursor to closing/opening bracket |
{,} |
Move cursor to next/previous paragraph |
a |
Append after the cursor |
A |
Append at the end of the line |
o |
Add a new line below and enter Insert mode |
O |
Add a new line above and enter Insert mode |
J |
Join current line with the line below |
d |
Delete the selection (Visual mode) |
dd |
Delete the current line |
dw |
Delete word forward |
dW |
Delete WORD forward (whitespace-delimited) |
diw |
Delete inner word |
diW |
Delete inner WORD (whitespace-delimited) |
df + <char> |
Delete up to and including the next <char> on the line |
dt + <char> |
Delete up to (but not including) the next <char> |
cw |
Change to the end of the word |
cW |
Change to the end of the WORD (whitespace-delimited) |
cf + <char> |
Change up to and including the next <char> on the line |
ct + <char> |
Change up to (but not including) the next <char> |
D |
Delete to the end of the line |
viw |
Select between word. |
ciw |
Change between word. |
ciW |
Change between WORD (whitespace-delimited) |
vi + ", ', (, [ or { |
Select between delimiter ", ', (, [ or { |
di + ", ', (, [ or { |
Delete between delimiter ", ', (, [ or { |
ci + ", ', (, [ or { |
Change between delimiter ", ', (, [ or { |
. |
Repeat the last change |
u |
Undo the last change |
r |
Redo the last undone action |
y |
Copy the selected text in visual mode |
yy |
Copy the current line in normal mode |
p |
Paste the copied text after the cursor |
P |
Paste the copied text before the cursor |
Home |
Move cursor to start of line |
End |
Move cursor to end of line |
ctrl+e |
Open in system editor (requires system-editor feature) |
| Keybinding | Description |
|---|---|
Esc |
Return to Normal mode |
Backspace |
Delete the previous character |
Delete |
Delete the character after the cursor |
Enter |
Insert line break |
Arrows |
Navigation |
Home |
Move cursor to start of line |
End |
Move cursor to end of line |
Ctrl+Left |
Move backward to the start of a word |
Ctrl+Right |
Move forward to the start of a word |
PageDown |
Jump a full page down |
PageUp |
Jump a full page up |
ctrl+u |
Delete until first character |
Emacs Mode was added in version 0.10.1.
Note that Emacs Mode is less feature complete and less tested than vim mode.
| Keybinding | Description |
|---|---|
Ctrl+f |
Move forward |
Ctrl+b |
Move backward |
Ctrl+n |
Move to next line |
Ctrl+p |
Move to previous line |
Ctrl+a |
Move to start of line |
Ctrl+e |
Move to end of line |
Ctrl+v |
Half page down |
Alt+v |
Half page up |
PageDown |
Full page down |
PageUp |
Full page up |
Alt+f |
Forward word |
Alt+b |
Backward word |
Alt+< |
Beginning of buffer |
Alt+> |
End of buffer |
Ctrl+d |
Delete character forward |
Ctrl+h |
Delete character backward |
Alt+d |
Delete word forward |
Alt+Backspace |
Delete word backward |
Ctrl+k |
Delete to end of line |
Alt+u |
Delete to start of line |
Ctrl+o |
Open line (insert newline, stay) |
Ctrl+j |
Newline |
Ctrl+y |
Paste |
Ctrl+u |
Undo |
Ctrl+r |
Redo |
Ctrl+g |
Cancel search |
Enter |
Insert line break |
Backspace |
Delete previous character |
Arrows |
Navigation |
Home |
Move to start of line |
End |
Move to end of line |
Ctrl+Left |
Move backward to the start of a word |
Ctrl+Right |
Move forward to the start of a word |
Alt+e |
Open in system editor (requires system-editor feature) |
Ctrl+s |
Start search |
Ctrl+s |
Search mode: Go to next match |
Ctrl+r |
Search mode: Go to previous match |
Enter |
Search mode: Select current match |
License: MIT


