Recipe: Simple Text Editor
This recipe shows how to configure a clean, lightweight plain text editor and interact with its text buffer from your GPUI application.
Basic Setup
Initialize an Editor entity inside a GPUI window:
#![allow(unused)] fn main() { use gpui::*; use twrite::Editor; struct EditorApp { editor: Entity<Editor>, } impl EditorApp { pub fn new(cx: &mut Context<Self>) -> Self { let editor = cx.new(|cx| { let mut ed = Editor::new("Initial document text...\n", cx); // Configure editor display settings: ed.config.line_numbers = true; ed.config.cursor_blink = true; ed.config.font_size = px(15.0); ed.config.line_height = px(24.0); // Optional: override monospace font family (auto-selected by default): // ed.config.font_family = Some("JetBrains Mono".into()); ed }); Self { editor } } } }
Reading and Writing Buffer Content
The underlying text is held by ed.buffer (an EditorBuffer powered by a rope structure):
#![allow(unused)] fn main() { impl EditorApp { /// Reads the complete document text as a String. pub fn get_content(&self, cx: &App) -> String { self.editor.read(cx).buffer.text() } /// Replaces the document text cleanly (resets undo history). pub fn set_content(&mut self, text: &str, cx: &mut Context<Self>) { self.editor.update(cx, |ed, cx| { ed.buffer.set_text(text); cx.notify(); }); } /// Inspects document size without copying text. pub fn print_stats(&self, cx: &App) { let ed = self.editor.read(cx); println!("Lines: {}", ed.buffer.line_count()); println!("Characters: {}", ed.buffer.len_chars()); println!("Bytes: {}", ed.buffer.len_bytes()); println!("Edit Version: {}", ed.buffer.version()); } } }
Adding a Status Bar
To build a professional editor layout with a status line displaying cursor row, column, and match count:
#![allow(unused)] fn main() { impl Render for EditorApp { fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement { let ed = self.editor.read(cx); let point = ed.buffer.cursor_point(); let status = format!( "Ln {}, Col {} | {} lines", point.row + 1, point.col + 1, ed.buffer.line_count() ); div() .size_full() .flex() .flex_col() .bg(rgb(0x1e1e2e)) // Main editor area: .child(div().flex_1().child(self.editor.clone())) // Bottom status bar: .child( div() .h(px(24.0)) .bg(rgb(0x181825)) .border_t_1() .border_color(rgb(0x313244)) .px(px(8.0)) .flex() .items_center() .justify_between() .text_xs() .text_color(rgb(0xa6adc8)) .child(status), ) } } }
Built-In Keyboard Shortcuts
The basic editor comes equipped with standard desktop shortcuts out of the box:
- Arrow Keys: Move cursor by character / line.
- Ctrl+Left / Ctrl+Right (or Alt+Left / Alt+Right): Jump word-by-word.
- Home / End: Jump to line start or line end.
- Ctrl+Z: Undo edit.
- Ctrl+Y (or Ctrl+Shift+Z): Redo edit.
- Ctrl+A: Select all.
- Backspace / Delete: Single-character deletion.
- Ctrl+Backspace / Ctrl+Delete: Delete previous or next word.
- Double-click: Select word under mouse cursor.
- Triple-click: Select entire line.
- Click and Drag: Selection expands with boundary snapping.