mirror of
https://github.com/fluffos/fluffos
synced 2026-08-12 18:26:06 -04:00
* Char-mode input: deliver real keystrokes (BS/DEL, whole UTF-8, raw ESC); fix NAWS lost at logon Five input-path fixes that make raw-keystroke (get_char) applications viable, found by building the LPC TUI library on top of them: - comm.cc: char mode delivered "" for Backspace/Delete (the byte was zeroed before delivery, making BS/DEL/NUL indistinguishable). The literal byte is now delivered; line-mode in-buffer editing unchanged. - comm.cc: char mode delivered one *byte* per callback, splitting a multi-byte UTF-8 character into 2-4 invalid one-byte strings. Extraction is now UTF-8 aware: a complete sequence arrives as one callback carrying one valid character; malformed bytes still go byte-at-a-time (no stalls). - comm.cc: the "no ansi" + "strip before process input" ESC->space rewrite (both default on) also applied to char mode, so arrow keys arrived as literal "[A". The rewrite is an anti-ANSI-injection protection for line-mode commands; char mode now always passes ESC through. - net/telnet.cc: each received chunk was u8_sanitize()d independently, so a UTF-8 character split across TCP segments became U+FFFD in any input mode. An incomplete trailing sequence (new u8_incomplete_tail(), GTest-covered) is now carried over in interactive_t and prepended to the next chunk. - net/telnet.cc + comm.cc: fast clients answer the initial DO NAWS while ip->ob is still the master object, so the window_size apply fired on the wrong object and the size was lost until the next resize. The last report is cached and replayed on the user object at logon. docs/efun/interactive/get_char.md documents the delivery contract. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RpXv4yGCWpkzbkifyZy9EE * Add /std/tui: an LPC TUI library (readline + ncurses for the prompt line and full-screen apps) A terminal-UI toolkit in pure LPC, strictly layered (design + rationale in testsuite/std/tui/DESIGN.md; user docs in docs/concepts/general/tui.md): - ansi.lpc: escape builders plus the width toolkit the driver lacks (visible_width/wslice/wpad are ANSI-blind and wide-char aware). - keys.lpc: keystroke decoder state machine: the get_char byte stream -> key events (CSI/SS3 with xterm modifiers, Alt prefixes, bracketed paste as one event, SGR mouse, UTF-8, lone-ESC via caller-driven flush()). - readline.lpc: the line editor: emacs keymap (motion/kill/yank/ transpose), Up/Down history, C-r/C-s incremental search, Tab completion, masked mode, horizontal scrolling with wide-char aware viewport; repaints only its own line so it works at any scroll position. - screen.lpc: virtual cell grid + minimal-diff frame renderer with copy-on-write rows (frame cost tracks touched rows, not W x H); wide chars own two cells, boxes/fills/attrs as SGR param strings. - widget.lpc + w/ (label, list, textfield) + app.lpc: widget protocol, focus cycling, event routing; textfield embeds a readline engine. - terminal.lpc: the one impure module, inherited by the user object: get_char re-arm loop (I_NOECHO across re-arms), NAWS/TTYPE caching via the window_size/terminal_type applies, lone-ESC walltime timeout, guaranteed teardown. tui_readline() is a drop-in input_to() replacement; tui_open() runs full-screen apps on the alt screen. Everything below terminal.lpc is a pure state machine: 194 checks in single/tests/std/tui/ cover the decoder, editor sessions, history search, screen diffing and widgets headlessly. `tuidemo` / `tuidemo app` (command/tuidemo.lpc) demo both modes over any telnet client; the whole stack was verified end-to-end over a live connection including split-packet UTF-8, modifier keys, paste, resize and alternate-screen teardown. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RpXv4yGCWpkzbkifyZy9EE * /std/tui v2: pterm/blessed-inspired widgets, inline printers and prompts, showcases Reviewed the pterm (Go) and blessed widget catalogs and ported what earns its keep in a MUD; DESIGN.md is renamed to README.md and documents the full set (including what was deliberately not ported). New layers: - print.lpc — pterm-style printers that compose with plain write(): p_table (boxed, width-aware, header rule), p_tree, p_bars, p_spark, p_panel, p_bullets, p_header, p_progress, p_info/success/warn/error, and p_bigtext via the existing /std/bitmap_font. - menu.lpc + terminal glue — inline interactive prompts in the normal output flow: tui_select(), tui_multiselect() (Space toggles, list windows by height, collapses to a "? prompt: answer" line) and tui_confirm() (y/n with a default). New widgets (/std/tui/w/): table (columns + header + selection), tree (collapsible, arrows fold), checklist, radiolist, button, progress, spinner (app-driven tick()), and log (bottom-anchored scrollback pane). Showcases (command/tuidemo.lpc): `tuidemo select` (prompt chain), `tuidemo print` (all printers), `tuidemo dashboard` (animated spinner, progress bars, sparkline, live table and log on a call_out tick), and `tuidemo form` (textfield, radio group, checkboxes, buttons). Coverage: three new test files (print exact-output, menu sessions, widgets2) bring /std/tui to 8 files in the suite; the live-connection e2e run now drives all six showcases end-to-end (52 checks), including the select->multiselect->confirm chain, unattended dashboard animation, and full form entry. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RpXv4yGCWpkzbkifyZy9EE * /std/tui: charts — braille canvas, line charts, vertical bars, heatmap Fills the chart gap left by v2 (only the horizontal p_bars existed): - canvas.lpc: a braille dot canvas (each cell is a 2x4 dot grid from the U+2800 block — the blessed-contrib/drawille technique), giving sub-cell resolution: c_set/c_unset/c_get, Bresenham c_line, and c_plot (scale a value series across the canvas), with per-cell colour. Renders as a string, per-row strings, or per-cell ({ ch, attr }) pairs for blitting into a screen. - print.lpc: p_chart (multi-series braille line chart with y-axis gutter and coloured legend), p_vbars (vertical bar chart with eighth-block partial tops and optional value row), p_heatmap (2D matrix as 256-colour cells, cool-to-hot ramp, optional axis labels). - w/chart.lpc: the live line-chart widget — add_series()/add_point() rolling history sized to the widget, auto or fixed y-range; replaces the dashboard's sparkline label with a real animating graph. - `tuidemo charts` showcase; chart docs in README.md and the docs page (heatmap removed from the not-ported list). Tests: single/tests/std/tui/charts.lpc pins the braille bit math with exact glyphs, line drawing, plot endpoints, exact p_vbars output, chart/heatmap structure, and the widget's rolling window. The live e2e run verifies `tuidemo charts` output and braille frames streaming from the dashboard chart. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RpXv4yGCWpkzbkifyZy9EE * docs: move the TUI page from Concepts to STDLIB /std/tui is a mudlib library like base64/break_string/json, so its page belongs under docs/stdlib/ with the rest of the /std modules, not under Concepts. Registered in stdlib/index.md; README file-layout pointer updated. (Concepts' sidebar is autogenerated, so the old entry disappears with the file.) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RpXv4yGCWpkzbkifyZy9EE --------- Co-authored-by: Claude <noreply@anthropic.com>
2.2 KiB
2.2 KiB
| title |
|---|
| interactive / get_char |
get_char
NAME
get_char - causes next character of input to be sent to a specified
function
SYNOPSIS
varargs int get_char( string | function fun, int flag, ... );
DESCRIPTION
Enable next character of user input to be sent to the function 'fun' as
an argument. The input character will not be parsed by the driver.
Note that get_char is non-blocking which means that the object calling
get_char does not pause waiting for input. Instead the object contin‐
ues to execute any statements following the get_char. The specified
function 'fun' will not be called until the user input has been col‐
lected.
If "get_char()" is called more than once in the same execution, only
the first call has any effect.
If optional argument 'flag' is non-zero, the char given by the player
will not be echoed, and is not seen if snooped (this is useful for col‐
lecting passwords).
The function 'fun' will be called with the user input as its first
argument (a string). Any additional arguments supplied to get_char will
be passed on to 'fun' as arguments following the user input.
DELIVERY
Exactly one keystroke is delivered per callback:
- A printable character arrives as itself. A multi-byte UTF-8 charac‐
ter is delivered whole, as one valid one-character string (it is
never split into fragment bytes).
- Control bytes arrive verbatim, including Backspace (0x08) and Delete
(0x7f) -- char mode performs no line editing.
- Escape sequences (arrow keys, function keys) arrive byte-by-byte:
ESC, '[', 'A' are three separate callbacks. Reassembling them is
the mudlib's job; see /std/tui/keys.lpc in the testsuite mudlib for
a full decoder, and the TUI library built on top of it.
Char mode is one-shot: after each callback the driver reverts to line
mode unless the callback re-arms get_char() before returning. Pass‐
ing the no-echo flag on every re-arm keeps client echo off across the
whole exchange.
SEE ALSO
call_other(3), call_out(3), input_to(3)