line_editor.py

Headless line editor with history, auto-suggest, and grapheme-aware editing.

This module provides LineEditor for single-line input with readline-style editing and LineHistory for command recall.

class DisplayState(text: str = '', cursor: int = 0, suggestion: str = '', overflow_left: bool = False, overflow_right: bool = False, text_sgr: str = '', suggestion_sgr: str = '', bg_sgr: str = '', ellipsis_sgr: str = '')[source]

Current visual state of the editor for rendering.

text: str = ''

Visible buffer text (masked in password mode, clipped when scrolling).

cursor: int = 0

Cursor column within the visible window.

suggestion: str = ''

Auto-suggest suffix (rendered dim/grey after text).

overflow_left: bool = False

True when content extends beyond the left edge.

overflow_right: bool = False

True when content extends beyond the right edge.

text_sgr: str = ''

SGR sequence applied to buffer text.

suggestion_sgr: str = ''

SGR sequence applied to suggestion text.

bg_sgr: str = ''

SGR sequence applied to fill the background.

ellipsis_sgr: str = ''

SGR sequence applied to the ellipsis indicator.

class LineEditResult(line: str | None = None, eof: bool = False, interrupt: bool = False, changed: bool = False, bell: str = '')[source]

Result of processing a keystroke.

line: str | None = None

Accepted line text when Enter was pressed, otherwise None.

eof: bool = False

True when Ctrl+D pressed on an empty line.

interrupt: bool = False

True when Ctrl+C pressed.

changed: bool = False

True when the display needs redrawing.

bell: str = ''

Bell string to emit (e.g. "\\a"), empty when silent.

class LineHistory(max_entries: int = 5000)[source]

In-memory command history with navigation and prefix search.

Parameters:

max_entries – Maximum number of history entries retained.

Initialize history with given maximum capacity.

entries: List[str]

History entries list (most recent last).

add(line: str) None[source]

Append line to history, skipping empty and consecutive duplicates.

search_prefix(prefix: str) str | None[source]

Return the most recent entry starting with prefix, or None.

nav_start(current_line: str) None[source]

Begin history navigation, saving current_line.

nav_up() str | None[source]

Navigate to the previous (older) history entry.

nav_down() str | None[source]

Navigate to the next (newer) history entry.

class LineEditor(history: LineHistory | None = None, password: bool = False, password_char: str = '✻', max_width: int = 0, ellipsis: str = '…', limit: int = 2048, limit_bell: str = '\x07', scroll_jump: float = 0.5, text_sgr: str = '\x1b[38;2;230;225;220m', suggestion_sgr: str = '\x1b[30m', bg_sgr: str = '', ellipsis_sgr: str = '', keymap: Dict[str, Callable[[...], LineEditResult] | None] | None = None)[source]

Headless single-line editor with grapheme-aware cursor movement.

Feed keystrokes via feed_key(), read display state via display. Accepts blessed Keystroke objects directly (dispatching on .name), or plain strings for testing.

Custom keymap handlers must be callables accepting a single LineEditor argument and returning a LineEditResult:

def my_handler(editor: LineEditor) -> LineEditResult:
    ...

Initialize editor with optional history, display, and keymap settings.

password_char: str
max_width: int
ellipsis: str
limit: int
limit_bell: str
scroll_jump: float
text_sgr: str
suggestion_sgr: str
bg_sgr: str
ellipsis_sgr: str
keymap: Dict[str, Callable[[...], LineEditResult] | None]
property history: LineHistory

Return the attached LineHistory instance.

property line: str

Return the current buffer contents as a string.

property password_mode: bool

Return whether password mode is currently active.

property display: DisplayState

Return the current DisplayState for rendering.

render(term: Terminal, row: int, width: int, col: int = 0) str[source]

Build escape sequences to render the current display state.

Parameters:
  • term – Blessed Terminal instance for cursor/SGR.

  • row – Terminal row for the input line.

  • width – Available columns.

  • col – Starting column offset (default 0).

Returns:

Escape-sequence string; caller writes/encodes it.

render_insert(term: Terminal, row: int, grapheme: str) str | None[source]

Fast-path render for a single grapheme inserted at end of buffer.

Parameters:
  • term – Blessed Terminal instance.

  • row – Terminal row for the input line.

  • grapheme – The grapheme cluster just inserted.

Returns:

Escape-sequence string, or None if a full redraw is needed.

render_backspace(term: Terminal, row: int) str | None[source]

Fast-path render after a backspace at end of buffer.

Parameters:
  • term – Blessed Terminal instance.

  • row – Terminal row for the input line.

Returns:

Escape-sequence string, or None if a full redraw is needed.

feed_key(key: 'Keystroke' | str) LineEditResult[source]

Process one keystroke and return a LineEditResult.

insert_text(text: str) LineEditResult[source]

Insert text at cursor position (for bracketed paste).

clear() None[source]

Clear the buffer and reset cursor to start.

set_password_mode(enabled: bool) None[source]

Toggle password masking on or off.