The daemon's buffer draws errors, warnings and notes in compilation's faces and the program's own output in a face of its own

This commit is contained in:
Joseph Ferano 2026-09-25 15:14:23 +07:00
parent e2aa0196cf
commit 8dc90416d4
3 changed files with 58 additions and 9 deletions

View File

@ -2079,12 +2079,6 @@ per-phase; making it per-form would need a resync point inside a body.
CLOSED: [2026-09-25]
A file with no =main= starts on a stub =main= that returns and parks; =load-file= (=C-c C-k=, already its key — the inspector stays on =C-c C-i=) keeps what compiles and lists the rest. Rules out =flan dev= with no file at all, and =--two-process= on a file with no =main=.
** NEXT The daemon buffer is navigable but not coloured
Decided 2026-09-25: errors, warnings and notes take compilation-mode's faces, and the program's own output takes a face of its own so it reads apart from the compiler's.
=*flan*= is all plain text. =compilation-minor-mode= is on (=emacs/flan.el:822=)
so =next-error= works, but a minor mode installs no font-lock. Open: whether the
program's output should look different from the compiler's.
** DONE compilation-mode steps over the notes
CLOSED: [2026-09-25]
The daemon buffer and the diagnostics buffer set =compilation-skip-threshold= to

View File

@ -412,6 +412,25 @@ nil keeps everything."
(let ((inhibit-read-only t))
(delete-region (point-min) (line-beginning-position)))))))
(defface flan-output-face '((t :inherit font-lock-string-face))
"Face for the running program's own output in the daemon's buffer.
It sets that output apart from what the compiler and the daemon say, whose
errors, warnings and notes take `compilation-mode''s faces."
:group 'flan)
(defun flan--daemon-buffer-setup ()
"Make the current buffer the daemon's log: navigable and coloured.
The daemon writes a diagnostic as `file:line:col: message', the shape
`compilation-minor-mode' already reads, so it only has to be switched on.
The minor mode adds its font-lock rules but turns nothing on, and a process
buffer is in `fundamental-mode', which global font-lock skips; so font-lock
is switched on here, first, or the rules would never be drawn."
(font-lock-mode 1)
;; A log, not source: a quote the program printed opens no string.
(setq-local font-lock-keywords-only t)
(compilation-minor-mode 1)
(flan--navigable-notes))
(defun flan--append-output (text)
"Append TEXT, the running program's own output, where it can be read.
Two places. The daemon's log always gets it, so output lands somewhere
@ -423,7 +442,13 @@ open, above its prompt, which is where whoever is typing there is looking."
(inhibit-read-only t))
(save-excursion
(goto-char (point-max))
(insert text))
;; Marked as it is inserted, because nothing in the text says whose
;; it is. A line the program prints in the diagnostic shape is
;; still read as one by `compilation-minor-mode', and takes its
;; face. `face' for a buffer with font-lock off, `font-lock-face'
;; so fontification does not strip it.
(insert (propertize text 'face 'flan-output-face
'font-lock-face 'flan-output-face)))
(flan--trim-lines)
;; Follow the tail only for someone who was already at it; a reader
;; scrolled back is reading something.
@ -893,8 +918,7 @@ It builds the program first, which for a cold project is most of this."
;; program runs, and `compilation-mode' would claim it as the output of
;; one finished command — killing the process on a `recompile', among
;; other things it has no business doing to a live session.
(compilation-minor-mode 1)
(flan--navigable-notes))
(flan--daemon-buffer-setup))
(make-process
:name "flan-daemon" :buffer buf
:command args

View File

@ -533,6 +533,37 @@ already rely on it — so nothing here is a stand-in for the real thing."
;; The session is not poisoned by that: a good form still lands.
(flan--eval "(defn step [] i64 (set ticks (+ ticks 100)) ticks)" "form")
;; The daemon's buffer is coloured: the compiler's errors, warnings and
;; notes take compilation's faces and the program's own output takes
;; `flan-output-face'. Checked on `font-lock-face', which is what
;; fontification writes; batch Emacs cannot turn `font-lock-mode' on, so
;; nothing here aliases it to `face'.
(let ((flan-daemon-buffer " *flan-colour-test*"))
(with-current-buffer (get-buffer-create flan-daemon-buffer)
(insert "flan dev: built x.flan in 3ms\n"
"/tmp/a.flan:2:8: expected i32, found string\n"
"/tmp/a.flan:3:1: warning: w\n"
"/tmp/a.flan:4:1: note: n\n")
(flan--daemon-buffer-setup)
(flan--append-output "said hi\n")
(font-lock-ensure)
(let ((face-on (lambda (text)
(goto-char (point-min))
(search-forward text)
(get-text-property (match-beginning 0) 'font-lock-face))))
(test-flan--check
"the daemon's buffer draws an error, a warning and a note in compilation's faces"
(and (memq 'compilation-error (ensure-list (funcall face-on "a.flan:2")))
(memq 'compilation-warning (ensure-list (funcall face-on "a.flan:3")))
(memq 'compilation-info (ensure-list (funcall face-on "a.flan:4")))))
(test-flan--check
"the program's output takes its own face"
(eq (funcall face-on "said") 'flan-output-face))
(test-flan--check
"the daemon's own line is left plain"
(null (funcall face-on "flan dev:")))))
(kill-buffer flan-daemon-buffer))
;; The program's own output arrives on replies and lands in the daemon's
;; buffer — no REPL is open yet, and the log is the fallback that makes a
;; println never depend on one.