Dedicated to Neal Stephenson's vision of paper-like data safety.
Author: Larry Bruce Daniel. Assistance from Grok (xAI): grok-code-fast-1 on earlier versions, Grok 4.7 on 1.0.7.
- Data safety: unlimited undo/redo (10k cap), auto-save with versioned backups, crash recovery. Rejects files over
max_file_size_mb(default 10MB) or with null bytes, and files whose line cache would passmemory_limit_mb. Cuts lines atmax_line_length. - Editing: insert, newline, backspace/delete, tabs (spaces or
\t), word wrap (F3), selection, clipboard (Ctrl+A/C/X/V), regex search (Ctrl+/) and replace (Ctrl+R), syntax highlighting (C/C++ nesting, pre-parsed, per-line cache). - Search chord:
Ctrl+/opens search. Byte 31 still works. foot and xterm modifyOtherKeys (ESC [27;5;47~) and kitty CSI-u (ESC [47;5u) are the same chord, so that sequence is not typed into the buffer. - Display:
F2line numbers,F3word wrap,F4border toggle (see below), status bar (version/time/position/key-metershow_key_meter), Unicode/Cyrillic. - Incremental rendering: cursor moves repaint only status line, single-line edits repaint only that row (75x less output);
view_decide()+ nesting cache. - Border handling: text in
derwin(stdscr, LINES-2,COLS-2,1,1)(border on) orderwin(stdscr, LINES-1,COLS,0,0)(border off); border only onFULLrepaint. Paste-timeborder_filter_dup()strips| + - │ ─ ┌ ┐ └ ┘ ├ ┤ ┬ ┴ ┼per line and drops pure┌──┐lines — replacestr -d. - Config:
~/.config/led/colorization.conf(colors,reserved_words,paired_keywords,syntax_extensions,show_key_meter,show_border), envLED_NO_BORDER=1/LED_SHOW_BORDER. - C/C++ editing:
file:line:coland+Nopen on the diagnostic,Ctrl+Gjumps there,Ctrl+]matches braces, word motions,Ctrl+Ktoggles//, Enter keeps indent, Shift+Tab outdents. Source files show line numbers. - Tests: 229 tests (buffer, undo, clipboard, autosave, view, search wrap, search chord, indent, braces, save).
./led -ton your machine. - **Open files in with .. in the path. It used to fail.
- Large files: the whole file is still loaded into memory. There is no lazy load or mmap. led stops when the file exceeds
max_file_size_mb, or when the next line would push the nesting cache pastmemory_limit_mb. The buffer stays empty and the status line saysFile too largeorToo many lines. Raise those keys to accept the cost, or split the file first. - Long lines: a line past
max_line_length(default 10000) is cut on load. The status line saysLong line truncated. Cut lines skip highlighting and use basic rendering. - Limits:
max_file_size_mb(1–100, default 10),memory_limit_mb(1–200, default 50), andmax_line_length(80–100000, default 10000) are keys incolorization.conf. A value outside its range keeps the default. - Language support: highlighting and parsing are built for C/C++; other languages may be incomplete. Turn highlighting off in config if a file fights you.
- Error handling: not fully standardized across modules.
- No per-buffer undo persistence across sessions.
- No fuzzing harness yet. Empty-file, size, null-byte, truncation, and memory-ceiling loads are tested.
- Input sanitization: no directory-traversal check beyond
is_filename_safe. - Terminal:
xtermblock-select still copies screen cells — useF4off or filter; no OSC 52 system clipboard. - Unknown languages like Python. Add the .py instead .c,.cpp.h in the colorization.conf file and the file will render.
- Work around, if the data gets corrupted, turning on line numbers with F2 will render correctly
Bugs: size and type (file, head sample), or a gdb ./led backtrace, at https://github.com/refgift/led/issues
C compiler, make (gmake on Unix), libncursesw, glibc regex.
make # builds ./led
make install # installs to /usr/local/bin
make doc # installs led.1
./led file.c
./led +142 file.c # open at a line (compiler output)
./led file.c:142:8 # file:line or file:line:col
./led -t # test mode (stderr, no curses) — also LED_TEST=1 ./led
man led # after make doc
| Keys | Action |
|---|---|
| Arrows, Home/End (×2 top/bottom), PgUp/PgDn | Navigation |
Ctrl+Left / Ctrl+Right, or Esc then b / f |
Previous / next word (_ counts as part of a word) |
Ctrl+] |
Jump to the matching () [] {} (skips strings and comments) |
Ctrl+G |
Go to line, or line:col |
| Printable, Enter, Backspace/Delete, Tab, Shift+Tab | Insert / delete / outdent |
| Enter at end of line | Copy indent; one extra level after { or ( |
Ctrl+K |
Toggle a // comment on this line |
Ctrl+W |
Delete the previous word |
Ctrl+Z / Ctrl+Y |
Undo / Redo |
Ctrl+S / Ctrl+Q |
Save / Quit (Ctrl+Q again if the buffer is modified) |
Ctrl+A / Ctrl+C / Ctrl+X / Ctrl+V |
Select all / Copy / Cut / Paste (paste is border-filtered) |
Ctrl+/ / Ctrl+R |
Search / Replace (regex, wraps, 100-char limit). Ctrl+/ is byte 31 or the terminal's modified-key sequence |
F2 |
Line numbers |
F3 |
Word wrap |
F4 |
Border on/off (subwindow inset vs full-width; pasted │ stripped) |
~/.config/led/colorization.conf — key=value, # comments, created on first run.
Colors (BLACK,RED,GREEN,YELLOW,BLUE,MAGENTA,CYAN,WHITE): normal_fg/bg, selection_fg/bg, semicolon_fg/bg, meta_level1..4_fg/bg, reserved_words_fg/bg.
Display/Border: show_border=0 (default off, 1 shows box). Toggled by F4.
Other: syntax_extensions=.c,.h,.C,.H,.cpp,.cc,.cxx,.hpp,.hh,.hxx, reserved_words=... (C and C++ keywords), paired_keywords=if-then,begin-end,(,), tab_width=8, spaces_for_tab=0, show_key_meter=1, show_line_numbers=0.
Limits: max_file_size_mb=10 (1–100), memory_limit_mb=50 (1–200), max_line_length=10000 (80–100000). A file over the size or memory ceiling is not opened. A longer line is cut and the status line says Long line truncated. A null byte is refused with Binary file.
Source files (those extensions) show line numbers unless show_line_numbers is set in the config. Ctrl+S replaces the file by rename and keeps its permission bits. Search wraps to the top and says so.
Example:
normal_fg=WHITE
normal_bg=BLACK
selection_fg=CYAN
selection_bg=BLACK
show_key_meter=1
show_border=0
syntax_extensions=.c,.h,.cpp