EdTUI

repository·main·Indexed 40 days ago

https://github.com/preiter93/edtui

A text editor widget for the Ratatui ecosystem providing Vim-inspired or Emacs-inspired editing experiences. Version 0.11.7 features include customizable themes, line numbering, syntax highlighting, mouse event handling, and the ability to open content in an external system editor.

Tokens
12.5K
Snippets
42
Records
53
Agent score
50%

What's inside EdTUI

  1. Quickstart: Render and handle events in EdTUI

    main

    To use EdTUI in a Ratatui application, you need to manage an EditorState for the data, an EditorView for rendering, and an EditorEventHandler for processing input. By default, the editor uses Vim-inspired keybindings.

    Rendering

    Create an EditorState and pass a mutable reference to EditorView::new() during the render loop.

    Handling Events (Vim Mode)

    Use EditorEventHandler::default() to handle keyboard events in Vim mode.

    Handling Events (Emacs Mode)

    Use EditorEventHandler::emacs_mode() for modeless editing.

    // Rendering
    use edtui::{EditorState, EditorView};
    use ratatui::widgets::Widget;
    
    let mut state = EditorState::default();
    EditorView::new(&mut state).render(area, buf);
    
    // Handling Events (Vim mode)
    use edtui::EditorEventHandler;
    
    let mut event_handler = EditorEventHandler::default();
    event_handler.on_key_event(key_event, &mut state);
    
    // Handling Events (Emacs mode)
    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);
  2. Enable Clipboard Paste Support

    main

    To enable pasting (via ctrl+y or cmd+y), you must explicitly enable bracketed paste mode in your application using crossterm at startup and disable it during cleanup.

    // At app start
    use ratatui::crossterm::event::EnableBracketedPaste;
    let mut stdout = std::io::stdout();
    ratatui::crossterm::execute!(stdout, EnableBracketedPaste);
    
    // During cleanup
    use ratatui::crossterm::event::DisableBracketedPaste;
    ratatui::crossterm::execute!(std::io::stdout(), DisableBracketedPaste);
  3. Use the System Editor

    main

    With the system-editor feature enabled, users can open the editor content in an external editor (like nvim) using Ctrl+e (Vim) or Alt+e (Emacs).

    Because the system editor is decoupled from the event handler, you must manually check if a request is pending and call system_editor::open.

    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)?;
    }
  4. Understand EdTUI clipboard modes and features

    main

    EdTUI's clipboard behavior depends on the arboard feature flag:

    • With arboard feature enabled (Default): EdTUI uses the arboard crate, allowing copy and paste operations between the system clipboard and the editor.
    • Without arboard feature: EdTUI uses an InternalClipboard. This is a lighter option that only supports copying and pasting within the editor itself, without interacting with the system clipboard.
  5. How to use Emacs mode (modeless editing)

    main

    If you prefer Emacs-style keybindings instead of the default Vim mode, initialize the EditorEventHandler using .emacs_mode(). You can also initialize the EditorState with specific content using Lines::from("...").

    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);
    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);
  6. Use the System Editor (requires `system-editor` feature)

    main

    With the system-editor feature enabled, users can open the editor content in an external editor (like nvim) using Ctrl+e in Vim mode or Alt+e in Emacs mode.

    Because the system editor is decoupled from the event handler, you must manually check if a request is pending and call open.

    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 is determined by the VISUAL or EDITOR environment variables.

    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)?;
    }
  7. Enable Paste Support

    main

    To enable pasting (via ctrl+y or cmd+y), you must explicitly enable bracketed paste mode in your application using ratatui::crossterm at startup and disable it during cleanup.

    Startup:

    use ratatui::crossterm::event::EnableBracketedPaste;
    let mut stdout = std::io::stdout();
    ratatui::crossterm::execute!(stdout, EnableBracketedPaste);

    Cleanup:

    use ratatui::crossterm::event::DisableBracketedPaste;
    ratatui::crossterm::execute!(std::io::stdout(), DisableBracketedPaste);
  8. Initialize and configure the EditorView

    main

    The EditorView is the primary widget used to render the editor in a ratatui application. It requires a mutable reference to an EditorState to manage the text content, cursor, and view settings. You can chain configuration methods to set the theme, syntax highlighting, line numbers, and other display behaviors.

    To use EditorView, create an EditorState, then instantiate the view using EditorView::new(&mut state) and apply your desired settings.

    use edtui::EditorState;
    use edtui::EditorTheme;
    use edtui::EditorView;
    
    let theme = EditorTheme::default();
    let mut state = EditorState::default();
    
    EditorView::new(&mut state)
        .wrap(true)
        .theme(theme);
  9. Open editor content in an external system editor

    main

    To allow a user to edit the current buffer in an external system editor (like Vim or Nano), you must follow a two-step process: first, trigger the request via an action, and second, call the open function to perform the actual transition.

    1. Triggering the request

    In standard modes, the request is triggered by:

    • Vim mode: Ctrl+e in normal mode.
    • Emacs mode: Alt+e.

    Internally, this is handled by the OpenSystemEditor action, which sets a flag in the EditorState.

    2. Executing the transition

    You must call open to handle the terminal state changes, launch the external editor, and update the editor state with the new content.

    Important: Terminal Mode Restoration open only restores raw mode and the alternate screen. If your application uses other terminal modes (such as mouse capture or bracketed paste), you must re-enable them manually after open returns.

    Workflow Example

    After processing user events, check if a request is pending using is_pending and then call open:

    // 1. Handle events (which might trigger OpenSystemEditor)
    event_handler.on_event(event, &mut state);
    
    // 2. Check and execute the system editor transition
    if system_editor::is_pending(&state) {
        system_editor::open(&mut state, &mut terminal)?;
    }
    if system_editor::is_pending(&state) {
        system_editor::open(&mut state, &mut terminal)?;
    }
  10. Basic usage of EdTUI

    main

    To use EdTUI in a Ratatui application, you need to manage an EditorState and render it using an EditorView. By default, the editor uses Vim-style keybindings.

    1. Create an EditorState.
    2. Create an EditorView passing a mutable reference to the state.
    3. Call .render(area, buf) during your Ratatui draw loop.
    4. Handle events using an EditorEventHandler.
    use edtui::{EditorState, EditorView};
    use ratatui::widgets::Widget;
    
    // In your app state/loop:
    let mut state = EditorState::default();
    EditorView::new(&mut state).render(area, buf);
    
    // In your event loop:
    use edtui::EditorEventHandler;
    let mut event_handler = EditorEventHandler::default();
    event_handler.on_key_event(key_event, &mut state);
  11. Enable Single-Line Mode

    main

    For search boxes or single-line input fields, use .single_line(true) on the EditorView. This blocks newline insertion and replaces newlines in pasted text with spaces.

    use edtui::{EditorState, EditorView};
    
    let mut state = EditorState::default();
    EditorView::new(&mut state)
            .single_line(true)
            .render(area, buf);
  12. Enable Syntax Highlighting

    main

    Syntax highlighting requires the syntax-highlighting feature. You can provide a SyntaxHighlighter to the EditorView. You can use built-in themes or custom ones via SyntaxHighlighter::new(theme_name, language).

    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);