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] 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=. 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 ** DONE compilation-mode steps over the notes
CLOSED: [2026-09-25] CLOSED: [2026-09-25]
The daemon buffer and the diagnostics buffer set =compilation-skip-threshold= to 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)) (let ((inhibit-read-only t))
(delete-region (point-min) (line-beginning-position))))))) (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) (defun flan--append-output (text)
"Append TEXT, the running program's own output, where it can be read. "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 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)) (inhibit-read-only t))
(save-excursion (save-excursion
(goto-char (point-max)) (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) (flan--trim-lines)
;; Follow the tail only for someone who was already at it; a reader ;; Follow the tail only for someone who was already at it; a reader
;; scrolled back is reading something. ;; 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 ;; program runs, and `compilation-mode' would claim it as the output of
;; one finished command — killing the process on a `recompile', among ;; one finished command — killing the process on a `recompile', among
;; other things it has no business doing to a live session. ;; other things it has no business doing to a live session.
(compilation-minor-mode 1) (flan--daemon-buffer-setup))
(flan--navigable-notes))
(make-process (make-process
:name "flan-daemon" :buffer buf :name "flan-daemon" :buffer buf
:command args :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. ;; The session is not poisoned by that: a good form still lands.
(flan--eval "(defn step [] i64 (set ticks (+ ticks 100)) ticks)" "form") (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 ;; 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 ;; buffer — no REPL is open yet, and the log is the fallback that makes a
;; println never depend on one. ;; println never depend on one.