Lite Emacs in Your BBS: The Key Bindings That Make Phosphor's Text Fields Work

August 31, 2026

If you’re the kind of person who reaches for Ctrl+A to jump to the beginning of a line, or Ctrl+K to delete everything from the cursor to the end, Phosphor’s text fields already speak your language. Every text input in the BBS — username, password, chat message, board post, search query — uses the same set of emacs-inspired key bindings, alongside the arrow keys and Home/End you’d expect.

This is a reference post. Bookmark it.

The key binding table

These bindings work everywhere you type text in Phosphor: single-line fields (username, password, search), multi-line editors (board posts, mail, the Phosphor script editor), and even inside selection widgets like tables and lists.

Cursor movement

KeyActionWorks in
(Left arrow)Move cursor left one characterAll text fields
(Right arrow)Move cursor right one characterAll text fields
(Up arrow)Move cursor up one line / move selection upText areas, tables, lists
(Down arrow)Move cursor down one line / move selection downText areas, tables, lists
HomeJump to beginning of line / first itemAll fields, tables, lists
EndJump to end of line / last itemAll fields, tables, lists
Page UpScroll up one page / first itemText areas, tables, lists
Page DownScroll down one page / last itemText areas, tables, lists
Ctrl+AJump to beginning of line (emacs move-beginning-of-line)All text fields
Ctrl+EJump to end of line (emacs move-end-of-line)All text fields
Ctrl+FMove cursor right one character (emacs forward-char)All text fields
Ctrl+BMove cursor left one character (emacs backward-char)All text fields
Ctrl+PMove up one line or one item (emacs previous-line)All text fields, tables, lists
Ctrl+NMove down one line or one item (emacs next-line)All text fields, tables, lists
Ctrl+VPage down (emacs scroll-up-command)Text areas, tables, lists

Editing

KeyActionWorks in
BackspaceDelete character before cursor; at line start, joins with previous lineAll text fields
DeleteDelete character after cursor; at line end, joins with next lineAll text fields
Ctrl+DDelete character after cursor (emacs delete-char); same as Delete keyAll text fields
Ctrl+KKill from cursor to end of line (emacs kill-line); at line end, joins with next lineAll text fields
EnterInsert new lineText areas
TabAccept ghost text completion if presentAll text fields

Completion and navigation

KeyActionWorks in
TabAccept ghost text suggestion (inline completion)All text fields with a completion provider
SpaceDismiss ghost text without accepting, insert a literal spaceAll text fields
EscDismiss ghost text without acceptingAll text fields
QClose current screen, go back one levelAll screens
EscClose current screen, go back one level (same as Q)All screens

Session control

KeyActionWorks in
Ctrl+CDetach immediately — preserve session, disconnect, re-attach laterAll screens, all contexts

Why emacs bindings in a BBS

Two reasons: muscle memory and terminal constraints.

The muscle memory argument is straightforward. A lot of people who use a BBS in 2026 also use a terminal daily. Bash has emacs-mode key bindings by default. So do many readline applications. If you instinctively hit Ctrl+A to go to the start of a line in your shell, that same instinct works in Phosphor. No mental mode switch required.

The terminal constraint argument is more practical. Not every terminal emulator sends the same key codes for Home, End, Page Up, and Page Down. Some send escape sequences. Some send different escape sequences depending on the terminal mode. Some SSH clients remap them. But every terminal, on every protocol (SSH, telnet, web, console), sends Ctrl+A through Ctrl+Z reliably. The control character range is the one part of the keyboard that’s truly portable across every terminal emulator ever made.

So we map the emacs navigation bindings that make sense — A/E for line start/end, F/B for forward/back, P/N for previous/next, K for kill-line, D for delete-char — and pair them with the standard arrow keys, Home/End, and Page Up/Down as first-class alternatives. Either way works. Use what’s comfortable.

The bindings that aren’t here

A few emacs bindings are intentionally omitted because they conflict with other functions or don’t make sense in a BBS context:

  • Ctrl+H: In emacs, this is help. In most terminals, it’s synonymous with Backspace. We let the terminal handle it as Backspace — which is what users expect.
  • Ctrl+U: In emacs, this is universal-argument (prefix for numeric arguments). We don’t support numeric prefix arguments in text fields, so Ctrl+U is unclaimed and passes through to the screen-level key handler.
  • Ctrl+W: In emacs, kill-ring-save or delete-word-backward. In a BBS, we might want this for a future “close this dialog” shortcut. Unclaimed for now.
  • Ctrl+Y: In emacs, yank (paste from kill ring). We don’t have a kill ring, so this is unclaimed. Future use: paste from clipboard in terminals that support bracketed paste.
  • Ctrl+L: In emacs, recenter. In many terminal apps, this refreshes/redraws the screen. Unclaimed — could be useful for a future force-refresh.
  • Ctrl+X: In emacs, the prefix for the entire Ctrl+X command map. We don’t support prefix keymaps, so this is unclaimed.

Ctrl+C is the big one — it’s SIGINT in a shell, copy in a GUI, and “cancel” in many apps. In Phosphor, it’s the universal detach key (covered in the session persistence key binding post). We made this choice because in a BBS there’s no foreground process to interrupt — the “cancel what I’m doing” instinct maps directly to “detach and keep my work.”

Ghost text and Tab completion

Every text field in Phosphor can have a completion provider attached — username autocomplete, board name suggestions, command completions. When a provider is set, ghost text appears as a dim suffix ahead of the cursor:

Write a message: Hello w|orld__
                         ↑ ghost text suggestion

Press Tab to accept the suggestion. Press Space to dismiss it and type a literal space. Press Esc to dismiss it without inserting anything. The completion provider is per-field — usernames in the “to” field, board names in the board selector, Phosphor keywords in the script editor.

Spellcheck highlights

In fields with spellcheck enabled (board posts, mail, the script editor), misspelled words appear with a yellow underline. This uses the same per-character styling system that powers ghost text — no popups, no inline suggestions you didn’t ask for, just a visual flag. The spellcheck post covers the implementation.

The reference card

Print it, screenshot it, tattoo it on your forearm:

╔══════════════════════════════════════════════════════════╗
║           PHOSPHOR BBS — KEY BINDINGS                    ║
╠══════════════════════════════════════════════════════════╣
║  CURSOR           EDITING            NAVIGATION          ║
║  Ctrl+A  Start    Ctrl+D  Del-fwd    Ctrl+P  Up          ║
║  Ctrl+E  End      Ctrl+K  Kill-line  Ctrl+N  Down        ║
║  Ctrl+F  Right    Backspace Del-back  Ctrl+V  Page-dn    ║
║  Ctrl+B  Left     Delete   Del-fwd    Home    Start      ║
║  ←→  Left/Right   Enter   New line    End     End        ║
║  ↑↓  Up/Down      Tab    Accept       PgUp  Page-up     ║
║  ═════════════════════════════════════  PgDn  Page-dn     ║
║  SESSION           SCREEN                              ║
║  Ctrl+C  Detach     Q / Esc  Go back                    ║
╚══════════════════════════════════════════════════════════╝

Every one of these works over SSH, telnet, and the web terminal — no special client required.

Your community. Your terminal. Your rules.

Follow #dtp (#digitalthirdplace #socialterminal) for what ships next.