The manual and the record follow the buffer story

MANUAL.md: *flan* and *flan-repl* throughout, the REPL's output and
error-summary behaviour, the two clears on C-c C-o / C-c M-o, the
diagnostics buffer as the one list with the memory section below the
errors, and the settings table without flan-output-buffer. BUILT.md's
three mentions of *flan-output* updated to the routing that exists.
FIX.org records the decision, dated.
This commit is contained in:
Joseph Ferano 2026-09-20 21:07:40 +07:00
parent e83a50b5c3
commit 9fae298816
3 changed files with 73 additions and 18 deletions

35
FIX.org
View File

@ -3558,3 +3558,38 @@ them exactly as it skips the shadowing guard; nothing in that test changed.
and ~@sanitize~ sweeps were not run here — the new corpus row is registered
for the x86 survey through the existing ~programs/*.flan~ glob and will be
compared on the next sweep.
* The Emacs buffer story, consolidated, 2026-09-20
The decision: two streams, one tool list, and the rest untouched.
- Two streams. ~*flan*~ (renamed from ~*flan-dev*~) is the daemon's log —
compilation-minor-mode, jump-to-error, and now a mirror of the program's
println output, so output lands somewhere before any REPL interaction has
happened. ~*flan-repl*~ is the working stream: eval results, the program's
output inserted above the prompt (output first, then the value), and a
one-line summary when a compile fails — "1 error — see ~*flan-diagnostics*~".
- One tool list. ~*flan-diagnostics*~ holds everything the compiler reports:
the errors as today, popped up (shown, not selected) when one lands, and
below them the memory-allocation sites ~flan-check-memory~ asks the
~(:op "memory")~ op for — one section, replaced whole on every ask, each
line in its kind's faint face (memory/gc, memory/native). The buffer got a
major mode: read-only, ~n~/~p~/~RET~ throughout both sections.
- ~*flan-output*~ is removed entirely, its ~C-c C-o~ with it. The key now
clears the REPL's last send; ~C-c M-o~ clears the transcript whole
(CIDER's pair), both bound in flan-mode and flan-repl-mode.
- Inspector and break/conditions buffers unchanged.
No daemon changes: the program's output already rides every reply's
~:output~, so both destinations are editor-side routing in
~flan--append-output~. A REPL rejection is distinguished from a connection
failure (~:client~ on the synthetic reply); only the compiler's messages
reach the diagnostics list.
** What was run
~dune test --root .~ green, test_emacs and test_cider included; the three
changed .el files byte-compile clean with warnings as errors. New checks in
test-flan.el: output reaches the daemon buffer with no REPL open, output
lands above the value at the REPL and is mirrored, the rejection summary and
its full message in the diagnostics list, both clears, and the two-section
layout (errors above, memory below, replace-whole, clear takes both).

View File

@ -1540,7 +1540,7 @@ request and `read` reads a reply.
| `C-c C-k` | the whole buffer, as **one** module |
| `C-x C-e` | the expression before point, evaluated *in the running program* |
| `C-c C-z` / `C-c C-q` | connect (finds `.flan-dev.sock` upward) / disconnect |
| `C-c C-o` | the running program's own output, in `*flan-output*` |
| `C-c C-o` | clear what the REPL's last send produced (`C-c M-o`: the whole transcript) |
| `C-c C-r` | a prompt on the running program (`*flan-repl*`) |
| `C-c C-b` | what a **stopped** program is offering, and which to take |
| `C-c C-d` | what the running program currently defines |
@ -1617,7 +1617,7 @@ same call the command loop makes — and checks the hook is installed in that bu
is Emacs' contract and a test claiming to check it would be checking nothing.
**The program's stdout is a pipe into the daemon**, and whatever it printed since the last reply rides along with the
next one into `*flan-output*`. Having it arrive *with* a reply rather than by a separate request is the point: the
next one into `*flan*` — and into `*flan-repl*` when a prompt is open. Having it arrive *with* a reply rather than by a separate request is the point: the
output an evaluation itself caused is the output anyone wants to see. Draining that pipe is a liveness requirement and
not a nicety — a pipe nobody reads fills at 64K and the next write blocks the program forever — so it is read from the
accept loop's `select`, not only when an editor asks, and the buffer is capped so a program printing every frame cannot
@ -1731,8 +1731,8 @@ because the file says which package it belongs to; a prompt has no file and noth
paren inside a string does not count.
- **A value and the program's output are different things and arrive by different routes.** The value is the result of
the request and appears at the prompt; anything the program printed while evaluating it rides along on the same reply
and goes to `*flan-output*`. Showing them in one place would be convenient and wrong, so there is a test for the
separation.
and is inserted above the value — output first, then the value, the way a terminal REPL reads — with `*flan*` mirroring
the output. There is a test for the ordering.
That test is what caught a real bug: the renderer's unit case emitted `()` without evaluating the expression, so
`(println "x")` — the most ordinary thing anyone types at a prompt — answered `()` while nothing happened. A `()`

View File

@ -54,7 +54,7 @@ You also need the `flan` binary on your `PATH`. If it is somewhere else, set
Two settings worth knowing about before you need them. `flan-start-timeout`
(60s) bounds the wait for a daemon to come up, and `flan-reply-timeout`
(30s) bounds one request once it has. The second is the one a long first
compile can exhaust: the message says so and names `*flan-dev*`, where the
compile can exhaust: the message says so and names `*flan*`, where the
daemon's own build log is, so you can see whether it is still working before
you raise it.
@ -132,7 +132,7 @@ socket reaches `flan dev` from Emacs:
(setq flan-daemon-args '("--debug")) ; breakpoints, through flan-dape
```
The first line of `*flan-dev*` is the command that actually ran, so you can
The first line of `*flan*` is the command that actually ran, so you can
always check what a session was started with.
There is no prefix argument for this and that is deliberate: `C-u M-x flan`
@ -292,9 +292,17 @@ One thing to know: it is **program-scoped**, not buffer-scoped. Names are the
running program's names. In sand you write `sim/settle`, not `settle`, because
that is what the program calls it.
**`C-c C-o`** shows `*flan-output*` — whatever the program itself has printed.
That is separate from the REPL, because the program's stdout belongs to the
program.
**Output lands here too.** Whatever the program printed while evaluating your
form rides along on the reply and is inserted above the prompt — output
first, then the value, the way a terminal REPL reads. When a compile fails
the prompt gets one line, `1 error — see *flan-diagnostics*`, and the message
itself is in that buffer, which pops up. The daemon's buffer `*flan*` mirrors
all program output, so a println is never lost when no prompt is open.
**Two clears.** `C-c C-o` removes what the last send produced — output, value
or error line — and leaves the transcript. `C-c M-o` erases the transcript
whole and leaves a fresh prompt. Both work from a `.flan` buffer as well as
from the prompt, and neither touches the input history.
**History.** `<up>` and `<down>` walk it while you are on the line you are
typing, filtered by whatever you have typed so far — `(sim` then `<up>` reaches
@ -597,6 +605,12 @@ They last until you edit the buffer — they are a reading of the source, not
feedback about an evaluation, so moving point through them leaves them alone.
Asking again while they are up takes them down.
**The full list goes to `*flan-diagnostics*`** as its own section, below
whatever errors are logged there — every site, the ones in files you have
open and the ones elsewhere, one `file:line:col: message` line each in the
kind's face. `n`, `p` and `RET` navigate it like the errors above it. Asking
again replaces the section; the errors above it stay.
#### The same thing from the command line, and flycheck
`flan check FILE --warn-memory` prints the same list in the standard
@ -992,16 +1006,22 @@ the thing rather than when you dismiss it.
**And it is kept.** Every compiler message the editor is handed is also appended
to `*flan-diagnostics*`, one entry per message with the time it arrived above
it: `M-x flan-show-diagnostics`. The overlay is feedback about one command and
it, and the buffer pops up when one lands — shown, not selected, so your
typing stays where it was. The overlay is feedback about one command and
is gone at the next keystroke; this is the copy you can still quote an hour
later, without going through `*Messages*` for it. Nothing clears it — not
connecting, not a successful evaluation, not quitting the program — until you
say `M-x flan-clear-diagnostics`. Each entry's message line is left in the shape
the compiler wrote it, `file:line:col: message`, so `RET` and `M-g M-n` on one
go to the code and a line yanked out of the buffer reads the same as one pasted
from a terminal.
the compiler wrote it, `file:line:col: message`, so `RET`, `n` and `p` on one
go to or between the code lines it names, and a line yanked out of the buffer
reads the same as one pasted from a terminal. `M-x flan-show-diagnostics`
brings it back by hand.
**A build that failed is in `*flan-dev*`**, and it jumps too: the buffer is in
**It is the one list for everything the compiler reports.** The errors are
the log above; the allocation sites `M-x flan-check-memory` asks for are one
section below them, replaced whole on every ask, navigable the same way.
**A build that failed is in `*flan*`**, and it jumps too: the buffer is in
`compilation-minor-mode`, so `M-g M-n`, `M-g M-p` and `RET` on a diagnostic take
you to the line it names. That is the buffer to read when `M-x flan` reports a
daemon that exited before it was ready — a `main` that does not compile means no
@ -1035,7 +1055,8 @@ Use `C-c C-g` if you need frames.
| `C-u C-x C-e` | ...and stop at it instead of showing its value |
| `C-c C-z` | connect (finds `.flan-dev.sock` upward) |
| `C-c C-q` | disconnect |
| `C-c C-o` | the running program's own output |
| `C-c C-o` | clear what the REPL's last send produced |
| `C-c M-o` | clear the REPL transcript whole |
| `C-c C-r` | a prompt on the running program |
| `C-c C-b` | a stopped program: condition, restarts, stack |
| `C-c C-M-b` | the same restarts, as a one-key prompt |
@ -1074,10 +1095,9 @@ in the buffer).
| `flan-echo-result` | `t` | report an accepted evaluation in the echo area |
| `flan-inline-result` | `t` | also show an expression's value at the end of its line |
| `flan-names-shown` | `4` | how many names to list before summarising |
| `flan-output-buffer` | `"*flan-output*"` | where the program's output goes |
| `flan-poll-interval` | `1.0` | seconds between checks for whether it stopped |
| `flan-daemon-buffer` | `"*flan-dev*"` | the daemon's own log |
| `flan-diagnostics-buffer` | `"*flan-diagnostics*"` | every compiler message, kept |
| `flan-daemon-buffer` | `"*flan*"` | the daemon's own log; mirrors program output |
| `flan-diagnostics-buffer` | `"*flan-diagnostics*"` | everything the compiler reports, kept |
| `flan-start-timeout` | `60` | seconds to wait for a program to come up |
| `flan-lower-buffer` | `"*flan-lowering*"` | where `C-c C-l` writes |
| `flan-lower-program` | `"flan"` | the compiler `C-c C-l` shells out to |