https://github.com/preiter93/edtui
A vim-inspired editor widget for ratatui
https://github.com/preiter93/edtui
Last synced: 11 days ago
JSON representation
A vim-inspired editor widget for ratatui
- Host: GitHub
- URL: https://github.com/preiter93/edtui
- Owner: preiter93
- License: mit
- Created: 2023-11-28T12:44:52.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2026-03-08T08:44:02.000Z (11 days ago)
- Last Synced: 2026-03-08T12:53:27.558Z (11 days ago)
- Language: Rust
- Homepage:
- Size: 14.3 MB
- Stars: 125
- Watchers: 3
- Forks: 16
- Open Issues: 9
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE.md
Awesome Lists containing this project
- awesome-ratatui - edtui - A TUI based vim-inspired editor widget for ratatui. (📦 Libraries / 🧩 Widgets)
README
### `EdTUI`
[![Crate Badge]](https://crates.io/crates/edtui) [](https://github.com/preiter93/edtui/actions/workflows/ci.yml) [](https://deps.rs/repo/github/preiter93/edtui) [![License Badge]](./LICENSE)
### Overview
`EdTUI` is a text editor widget for the [Ratatui](https://github.com/ratatui-org/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`.
You can customize the theme, enable line wrapping, syntax highlight the text or set the tab
width:
```rust
use edtui::{EditorState, EditorTheme, EditorView};
use ratatui::widgets::Widget;
let mut state = EditorState::default();
EditorView::new(&mut state)
.theme(EditorTheme::default())
.wrap(true)
.syntax_highlighter(None)
.tab_width(2)
.render(area, buf);
```
Handle events (Vim mode by default):
```rust
use edtui::EditorEventHandler;
let mut event_handler = EditorEventHandler::default();
event_handler.on_key_event(key_event, &mut state);
```
Or use Emacs mode (modeless editing):
```rust
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:
```rust
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);
```
### Demo

### Features
- 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-editor` feature).
### Theming
Customize the editor `EditorTheme`:
```rust
use edtui::{EditorTheme, EditorStatusLine};
use ratatui::style::{Style, Color};
use ratatui::widgets::Block;
let theme = EditorTheme::default()
.block(Block::default())
.base(Style::default().bg(Color::Black).fg(Color::White))
.cursor_style(Style::default().bg(Color::White).fg(Color::Black))
.selection_style(Style::default().bg(Color::Yellow).fg(Color::Black))
.hide_status_line(); // or use `.status_line(..)` for styling the status line
```
### Line Numbers
Display absolute or relative line numbers:
```rust
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);
```

### Single-Line Mode
For search boxes and single-line input fields, enable single-line mode to block newline insertion:
```rust
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.
### Mouse Events
`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`:
```rust
let event_handler = EditorEventHandler::default();
event_handler.on_event(event, &mut state); // handles mouse events too
```
If you want finer control you can handle mouse events explicitly using `on_mouse_event`:
```rust
event_handler.on_mouse_event(mouse_event, &mut state);
```
### Syntax highlighting
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](https://github.com/trishume/syntect)
for more details about themes and extensions.
```rust
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);
```

### Paste Support
If you want to enable paste (via ctrl+y or cmd+y) you must explicitly enable it at the start of your app:
```rust
use ratatui::crossterm::event::EnableBracketedPaste;
let mut stdout = std::io::stdout();
ratatui::crossterm::xecute!(stdout, EnableBracketedPaste);
```
and disable it during cleanup:
```rust
use ratatui::crossterm::event::DisableBracketedPaste;
ratatui::crossterm::execute!(std::io::stdout(), DisableBracketedPaste);
```
See `examples/app/term.rs` for a an example.
### System Editor
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:
```rust
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.
### Keybindings
`EdTUI` offers Vim keybindings by default and Emacs keybindings as an alternative.
#### Vim Mode (default)
##### Normal Mode:
| 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 |
| `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 |
| `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 |
| `D` | Delete to the end of the line |
| `viw` | Select between word. |
| `ciw` | Change between word. |
| `vi` + `", ', (, [ or {` | Select between delimiter `", ', (, [ or {` |
| `ci` + `", ', (, [ or {` | Change between delimiter `", ', (, [ or {` |
| `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 |
| `Home` | Move cursor to start of line |
| `End` | Move cursor to end of line |
| `ctrl+e` | Open in system editor (requires `system-editor` feature) |
##### Insert Mode:
| 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
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 |
#### Roadmap
- [ ] Support termwiz and termion
[Crate Badge]: https://img.shields.io/crates/v/edtui?logo=rust&style=flat-square&logoColor=E05D44&color=E05D44
[License Badge]: https://img.shields.io/crates/l/edtui?style=flat-square&color=1370D3
License: MIT