Skip to content

Latest commit

 

History

History
631 lines (449 loc) · 16 KB

File metadata and controls

631 lines (449 loc) · 16 KB

LLE - Lush Line Editor

The native line editor that makes Lush different


Table of Contents

  1. Why LLE Exists
  2. Editing Modes
  3. Emacs Mode Reference
  4. Vi Mode
  5. Completion System
  6. Syntax Highlighting
  7. History Integration
  8. Multi-Line Editing
  9. Kill Ring
  10. Customization
  11. Troubleshooting

Why LLE Exists

Every major shell wraps GNU Readline or implements something similar. Bash uses Readline. Zsh has ZLE. Fish has its own editor. They all follow the same pattern: a text input library adapted for shell use.

Lush took a different approach. LLE (Lush Line Editor) is a line editor designed from the ground up for interactive shell use. This isn't academic distinction - it enables capabilities that bolted-on solutions can't provide:

  • Deep completion integration: LLE's completion system understands shell syntax at a fundamental level. It doesn't just complete filenames - it knows what arguments each of the 45 shell builtins accepts and presents context-appropriate options.

  • Real-time syntax highlighting: Every character you type is tokenized and colored. Commands are validated as you type. You see errors before pressing Enter.

  • Unified editing experience: Multi-line editing, history navigation, and completion all work together without the seams you feel in other shells.

  • Foundation for the future: Features like the integrated debugger, hook system, and shell modes all build on LLE's architecture.

LLE is not readline. It doesn't load .inputrc. It doesn't try to be compatible with readline's API. It's a purpose-built editor for a purpose-built shell.


Editing Modes

LLE supports two editing paradigms:

Emacs Mode (Default, Complete)

Emacs-style editing is the default and provides complete functionality. All 44 keybinding actions are implemented and production-ready.

Vi Mode (In Development)

Vi mode has the framework in place - mode switching, state machine, command parsing - but is not yet wired to editing operations. This is targeted for completion in the v1.4.0 release cycle.

To check the current mode:

display lle diagnostics

Emacs Mode Reference

LLE implements 44 GNU Readline-compatible keybinding actions.

Cursor Movement

Keybinding Action Description
Ctrl-A Beginning of line Move to start of current line
Ctrl-E End of line Move to end of current line
Ctrl-F Forward char Move forward one character
Ctrl-B Backward char Move backward one character
Alt-F Forward word Move forward one word
Alt-B Backward word Move backward one word
Ctrl-P / Up Previous history Previous history entry (or previous line in multi-line)
Ctrl-N / Down Next history Next history entry (or next line in multi-line)
Alt-< Beginning of history Go to first history entry
Alt-> End of history Go to last history entry / current input

Text Deletion

Keybinding Action Description
Ctrl-D Delete char Delete character at cursor (EOF on empty line)
Backspace Backward delete Delete character before cursor
Ctrl-K Kill line Kill from cursor to end of line
Ctrl-U Backward kill line Kill from beginning of line to cursor
Alt-D Kill word Kill from cursor to end of word
Ctrl-W Backward kill word Kill from beginning of word to cursor
Alt-Backspace Backward kill word Same as Ctrl-W

Kill Ring (Cut/Paste)

Keybinding Action Description
Ctrl-Y Yank Paste most recent kill
Alt-Y Yank pop After Ctrl-Y, cycle through kill ring

Text Transformation

Keybinding Action Description
Ctrl-T Transpose chars Swap character at cursor with previous
Alt-T Transpose words Swap word at cursor with previous word
Alt-U Upcase word Uppercase from cursor to end of word
Alt-L Downcase word Lowercase from cursor to end of word
Alt-C Capitalize word Capitalize first char, lowercase rest

Completion

Keybinding Action Description
Tab Complete Trigger completion
Alt-? Possible completions List all possible completions
Alt-* Insert completions Insert all possible completions

History Search

Keybinding Action Description
Ctrl-R Reverse search Incremental reverse history search
Ctrl-S Forward search Incremental forward history search
Ctrl-G Abort Cancel search, return to original line

Undo

Keybinding Action Description
Ctrl-_ Undo Undo last editing action
Ctrl-X Ctrl-U Undo Same as Ctrl-_

Control

Keybinding Action Description
Ctrl-L Clear screen Clear terminal, redraw prompt
Ctrl-C Interrupt Send SIGINT, cancel current input
Ctrl-Z Suspend Send SIGTSTP, suspend shell
Ctrl-D EOF On empty line: exit shell
Enter Accept line Execute the current line

Miscellaneous

Keybinding Action Description
Ctrl-Q Quoted insert Insert next character literally
Ctrl-V Quoted insert Insert next character literally
Alt-# Insert comment Comment out line, add to history
Ctrl-X Ctrl-E Edit and execute Open in $EDITOR, execute on save

Vi Mode

Vi mode is in active development. The framework includes:

  • Mode state machine (normal, insert, command-line)
  • Motion commands parser
  • Operator-pending mode
  • Count prefixes

Target: Full vi mode in the v1.4.0 release.

When complete, vi mode will support:

Normal Mode

  • h j k l - Movement
  • w b e - Word movement
  • 0 $ ^ - Line movement
  • x X - Delete character
  • d - Delete operator
  • c - Change operator
  • y - Yank operator
  • p P - Paste
  • i a I A - Enter insert mode
  • u Ctrl-R - Undo/redo
  • / ? - Search
  • n N - Search repeat

Insert Mode

  • All text input
  • Escape - Return to normal mode
  • Ctrl-[ - Return to normal mode

Completion System

LLE's completion system is context-aware. It understands what you're typing and provides appropriate completions.

Completion Types

Type Description Example
Command Executables in $PATH gi<Tab> -> git
Builtin Shell builtins ec<Tab> -> echo
File Files and directories /etc/pa<Tab> -> /etc/passwd
Variable Shell variables $HO<Tab> -> $HOME
Option Command options ls --co<Tab> -> ls --color

Context-Aware Builtin Completions

All 45 completable shell builtins have specific completion logic:

# set builtin knows its options
set -o <Tab>        # Shows: errexit nounset xtrace ...

# config builtin knows its structure  
config set <Tab>    # Shows: shell completion display ...
config set shell.<Tab>  # Shows: errexit nounset pipefail ...

# debug builtin knows its subcommands
debug <Tab>         # Shows: on off vars print trace profile

# display builtin knows its arguments
display <Tab>       # Shows: lle features themes status stats
display lle <Tab>   # Shows: diagnostics status info

Menu Navigation

When multiple completions are available, a menu appears:

Key Action
Up / Ctrl-P Move up in menu
Down / Ctrl-N Move down in menu
Left / Ctrl-B Move left (multi-column)
Right / Ctrl-F Move right (multi-column)
Tab Accept selection
Enter Accept and execute
Escape Cancel completion

Completing External Commands

When an external command shadows a builtin (like /usr/bin/echo vs the echo builtin), selecting the external command inserts its full path so you explicitly use the external version.


Syntax Highlighting

LLE tokenizes your input in real-time and applies colors based on token types.

Token Types

LLE recognizes 45 distinct token types:

Commands

  • Valid external command (green)
  • Invalid command (red)
  • Shell builtin (cyan)
  • Alias (cyan)
  • Function (blue)

Strings

  • Single-quoted string
  • Double-quoted string
  • ANSI-C quoted string ($'...')
  • Backtick command substitution

Variables

  • Variable reference ($var, ${var})
  • Special variables ($?, $#, $@, $$, $!)

Paths

  • Valid file/directory path (underlined green)
  • Invalid path (underlined red)

Operators

  • Pipe (|)
  • Redirections (>, <, >>, 2>, &>)
  • Background (&)
  • Command separator (;)
  • Logical AND/OR (&&, ||)
  • Subshell parentheses
  • Brace groups

Other

  • Keywords (if, then, else, fi, for, while, do, done, case, esac)
  • Comments (# ...)
  • Options (-v, --verbose)
  • Glob patterns (*, ?, [...])
  • Here-documents
  • Process substitution
  • Arithmetic expansion
  • Errors

Command Validation

LLE checks whether commands exist as you type:

  • Commands that exist appear in green
  • Commands that don't exist appear in red
  • Builtins appear in cyan
  • Aliases and functions have their own colors

This validation uses a cache for performance - commands are only checked once per session unless the cache is cleared.

Theme Integration

Syntax highlighting colors come from the current theme:

# List available themes
theme list

# Switch themes
theme set dark

# Colors update immediately

History Integration

LLE integrates with Lush's history system.

Navigation

Key Action
Up / Ctrl-P Previous history entry
Down / Ctrl-N Next history entry
Alt-< First history entry
Alt-> Last entry / current line

Incremental Search

Key Action
Ctrl-R Start reverse search
Ctrl-S Start forward search
Type text Narrow search
Ctrl-R again Find previous match
Ctrl-S again Find next match
Enter Accept match
Ctrl-G Cancel, restore original

History Expansion

Standard history expansion works:

!!              # Last command
!$              # Last argument of last command
!^              # First argument of last command
!*              # All arguments of last command
!n              # Command number n
!-n             # n commands ago
!string         # Most recent command starting with string
!?string?       # Most recent command containing string

Multi-Line History

Multi-line commands are stored as single history entries. Navigating to a multi-line command displays all lines.

Deduplication

LLE can deduplicate adjacent identical history entries:

config set history.dedup_navigation true

With this enabled, pressing Up will skip repeated commands.


Multi-Line Editing

LLE handles multi-line input naturally.

Automatic Continuation

When a line is syntactically incomplete, LLE provides a continuation prompt:

$ for i in 1 2 3; do
>     echo "Number: $i"
> done
Number: 1
Number: 2
Number: 3

Incomplete constructs that trigger continuation:

  • Unclosed quotes
  • Unclosed parentheses/braces
  • if/then/else/fi blocks
  • for/while/do/done loops
  • case/esac statements
  • Backslash at end of line

Editing Within Multi-Line

Key Action
Up Move to previous line (not history)
Down Move to next line (not history)
Ctrl-A Start of current line
Ctrl-E End of current line
Alt-< Start of buffer
Alt-> End of buffer

LLE maintains column position when moving between lines (sticky column).

Explicit Newline

To insert a newline without executing:

  • Backslash at end of line: \<Enter>
  • Within quotes, just press Enter

Kill Ring

LLE maintains a kill ring for cut/paste operations.

Adding to Kill Ring

These operations add to the kill ring:

  • Ctrl-K - Kill to end of line
  • Ctrl-U - Kill to beginning of line
  • Alt-D - Kill word forward
  • Ctrl-W / Alt-Backspace - Kill word backward

Yanking

Key Action
Ctrl-Y Yank (paste) most recent kill
Alt-Y After Ctrl-Y, cycle through older kills

Kill Ring Behavior

  • Consecutive kill commands append to the same entry
  • The ring holds multiple entries (typically 10)
  • Alt-Y only works immediately after Ctrl-Y

Customization

Keybinding Configuration

LLE keybindings can be configured through the config system:

# View current bindings
config show keybindings

# Modify a binding (example syntax)
config set keybindings.ctrl_a beginning_of_line

Completion Configuration

# Enable/disable completion
config set completion.enabled true

# Case sensitivity
config set completion.case_sensitive false

# Menu display
config set completion.menu_complete true

Syntax Highlighting Configuration

# Enable/disable
config set display.syntax_highlighting true

# Command validation
config set display.validate_commands true

# Path validation  
config set display.validate_paths true

History Configuration

# History size
config set history.size 10000

# Deduplication
config set history.dedup_navigation true

# Ignore patterns
config set history.ignore_patterns "^\\s*$"

Troubleshooting

Display Issues

Problem: Colors don't appear

# Check terminal color support
echo $TERM
tput colors

# Ensure color is enabled
config set display.syntax_highlighting true

Problem: Characters display incorrectly

# Check locale
echo $LANG $LC_ALL

# LLE requires UTF-8
export LANG=en_US.UTF-8

Problem: Width calculation wrong

# Force terminal size refresh
# Resize terminal window, or:
kill -WINCH $$

Completion Issues

Problem: No completions appear

# Check completion is enabled
config get completion.enabled

# Check for errors
display lle diagnostics

Problem: Wrong completions

# Clear completion cache
# (Rebuilds command cache)

History Issues

Problem: History not saving

# Check history file permissions
ls -la ~/.lush_history

# Check history size
config get history.size

Performance Issues

Problem: Slow response

# Check display stats
display stats

# Disable expensive features temporarily
config set display.validate_paths false
config set display.validate_commands false

Getting Diagnostics

# Full LLE status
display lle diagnostics

# Performance statistics
display stats

# Feature status
display features

Technical Details

Architecture

LLE is composed of several subsystems:

Subsystem Responsibility
Buffer Text storage, cursor management
Input Key parsing, sequence detection
Keybinding Action dispatch
Completion Context analysis, candidate generation
History Storage, navigation, search
Display Rendering, syntax highlighting
Terminal ANSI output, capability detection

Unicode Support

LLE fully supports Unicode:

  • UTF-8 input and output
  • Grapheme cluster handling (emoji, combining characters)
  • Correct cursor positioning for wide characters
  • Unicode-aware word boundaries

Memory Management

LLE uses:

  • Arena allocators for temporary data
  • Memory pools for frequent allocations
  • Reference counting for shared data

Zero memory leaks on normal operation (verified with macOS leaks tool).

Thread Safety

LLE is not thread-safe. All operations must occur on the main thread. The async worker (for completion) uses careful synchronization.


See Also