// HACKER NEWS — CYBERSECURITY
e is a customizable self-aware Emacs-like editor written in Chez Scheme
A tiny console text editor written in
Chez Scheme. It is Emacs-like in
spirit—buffers, windows, a kill ring, incremental search, and a Scheme
top level—but it is not an Emacs clone. It borrows the ideas that stay
small and stops there.
Or vendored inside a project, so anyone who clones the project gets a
working editor with it:
Every installation is self-contained: the loader uses strictly the
lib/ next to the script itself, compiled objects stay local in eo/,
and sources recompile automatically when they (or anything they import)
change. Project-specific modules dropped into a vendored checkout's
lib/ stay local to that project.
The terminal size is detected via ioctl and tracked across resizes;
if that is unavailable, set LINES and COLUMNS. On FreeBSD, whose
Chez port renames the scheme-script interpreter, change the shebang
to #!/usr/bin/env -S chez-scheme --script or run
chez-scheme --script e (details in the loader's header comment).
Each window has its own status line, point, and scroll position; the
same buffer can be shown in several windows at once. Buffers have per-buffer
history and marks; windows have independent point, scrolling, wrapping, and
status. A right-side scrollbar is shown by default; C-x l toggles a
buffer-owned line-number gutter. See
Buffers for switching, *buffers*, file integrity, target
windows, mouse behavior, scrollbars, wrapping, splits, and the public API.
All keyboard commands can be rebound in config.e. User bindings override
built-in and module defaults, and C-h k describes a key, its source, and
its contextual meanings:
See Key binding configuration for key syntax,
context maps, available actions, precedence, unbinding, and module defaults.
C-s starts an incremental search: type to extend the needle, C-s
again jumps to the next match (wrapping around), Backspace shortens the
needle, RET/ESC accepts silently, C-g cancels and returns point
to where the search began. In a new, empty search, C-s recalls and
searches for the previous needle. Point rides just past the current
match, so a mark set before searching leaves the found text inside the
region.
The needle's matches in the current window are highlighted while
searching. Matching folds case the smart way, as in Emacs: it
ignores case only while the needle is all lowercase, and one typed
capital makes it exact (the prompt then reads I-search (exact):).
M-c toggles the current search either way, and (search-fold-case #f) in config.e makes every search exact. Everything else—including
M-% query replace—always matches exactly.
Indentation is the one thing enforced—spacing within a line is the
author's (tables, alignment, and hand layout communicate structure),
and lines are never joined or split. The Scheme rules are
Emacs-like: body forms (define, lambda, the let family, when,
...) indent their bodies two columns past the opener, a lone closer
sits under its opener, and an application's continuation lines have
two stops: two past the opener, or aligned under the first
argument when it shares the opener's line. The author picks:
TAB indents the current line, cycling through its stops -- the
nearest stop to the right, wrapping around -- and puts point on the
indentation (a blank line pads out to it); modes opt in when they
register an indenter, and scheme-mode does. indent-region! and
indent-buffer! indent line by line from the top as one undo step,
each line settling on the stop nearest its current indentation: on a
stop it stays, before the first it takes the first, past the last the
last. format-region! and format-buffer! additionally widen tabs
outside strings to spaces ((scheme-tab-width 2); #f keeps tabs),
trim trailing whitespace, drop trailing blank lines so the file ends
with exactly one newline, and apply the bracket conventions -- [ ]
for the bindings of the let family, do, parameterize, and
with-syntax, and for the clauses of cond, case, case-lambda,
guard, syntax-rules, and syntax-case; ( ) everywhere else --
the scheme