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
| Key | Action | Works in |
|---|---|---|
| ← (Left arrow) | Move cursor left one character | All text fields |
| → (Right arrow) | Move cursor right one character | All text fields |
| ↑ (Up arrow) | Move cursor up one line / move selection up | Text areas, tables, lists |
| ↓ (Down arrow) | Move cursor down one line / move selection down | Text areas, tables, lists |
| Home | Jump to beginning of line / first item | All fields, tables, lists |
| End | Jump to end of line / last item | All fields, tables, lists |
| Page Up | Scroll up one page / first item | Text areas, tables, lists |
| Page Down | Scroll down one page / last item | Text areas, tables, lists |
| Ctrl+A | Jump to beginning of line (emacs move-beginning-of-line) | All text fields |
| Ctrl+E | Jump to end of line (emacs move-end-of-line) | All text fields |
| Ctrl+F | Move cursor right one character (emacs forward-char) | All text fields |
| Ctrl+B | Move cursor left one character (emacs backward-char) | All text fields |
| Ctrl+P | Move up one line or one item (emacs previous-line) | All text fields, tables, lists |
| Ctrl+N | Move down one line or one item (emacs next-line) | All text fields, tables, lists |
| Ctrl+V | Page down (emacs scroll-up-command) | Text areas, tables, lists |
Editing
| Key | Action | Works in |
|---|---|---|
| Backspace | Delete character before cursor; at line start, joins with previous line | All text fields |
| Delete | Delete character after cursor; at line end, joins with next line | All text fields |
| Ctrl+D | Delete character after cursor (emacs delete-char); same as Delete key | All text fields |
| Ctrl+K | Kill from cursor to end of line (emacs kill-line); at line end, joins with next line | All text fields |
| Enter | Insert new line | Text areas |
| Tab | Accept ghost text completion if present | All text fields |
Completion and navigation
| Key | Action | Works in |
|---|---|---|
| Tab | Accept ghost text suggestion (inline completion) | All text fields with a completion provider |
| Space | Dismiss ghost text without accepting, insert a literal space | All text fields |
| Esc | Dismiss ghost text without accepting | All text fields |
| Q | Close current screen, go back one level | All screens |
| Esc | Close current screen, go back one level (same as Q) | All screens |
Session control
| Key | Action | Works in |
|---|---|---|
| Ctrl+C | Detach immediately — preserve session, disconnect, re-attach later | All 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-saveordelete-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.