From c1a612abfb89dc2fea3dab4c900916a362a6caf2 Mon Sep 17 00:00:00 2001 From: Joseph Ferano Date: Sat, 12 Sep 2026 03:56:41 +0700 Subject: [PATCH] The rejection goes away when you do anything else An overlay that lasted until the next accepted evaluation was a durable annotation on the source, which is not what it is: it is feedback about the action that just failed, and the moment you move, type or evaluate it is describing a program state nobody is in any more. pre-command-hook rather than post-command-hook, which fires at the end of the failing command and would take the overlay down before redisplay ever drew it. Buffer-local and installed only while an overlay exists, so a session of twenty buffers does not end up running this on every keystroke in all of them. --- emacs/flan-dev.el | 46 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/emacs/flan-dev.el b/emacs/flan-dev.el index e1aba46..dd2bba7 100644 --- a/emacs/flan-dev.el +++ b/emacs/flan-dev.el @@ -731,9 +731,27 @@ Compared with `file-equal-p', so a symlinked or relative path still matches." ;; An error is shown where it is rather than only in the echo area, because the ;; echo area is gone the moment you type and the location is the useful half of -;; the message. It is cleared when the next evaluation of that buffer is -;; accepted: an overlay left behind after a fix is a lie about the program, and -;; a stale one is worse than none. +;; the message. +;; +;; It is feedback about the evaluation that just failed and not an annotation +;; on the source, so it lasts exactly as long as that: the next command in that +;; buffer takes it away, whatever the command was — a keystroke, a motion, +;; another evaluation. An overlay that survived until some later evaluation +;; was accepted outlived the thing it was about, and a stale one is worse than +;; none. +;; +;; `pre-command-hook' and not `post-command-hook': the hook has to run before +;; the *next* command, because `post-command-hook' fires at the end of the +;; failing command itself and would take the overlay down before redisplay had +;; ever drawn it. +;; +;; The hook is buffer-local and lives exactly as long as an overlay does — +;; added where one is drawn, removed where they are cleared. Globally it would +;; be a hook every buffer in the session runs on every keystroke for the sake +;; of a feature most of them will never use; buffer-locally it is also the +;; behaviour asked for, since the overlay belongs to the buffer the failed +;; evaluation came from and a command somewhere else is not "doing something +;; else in that buffer". (defface flan-dev-error-face '((t :inherit error :underline (:style wave))) @@ -749,7 +767,19 @@ Compared with `file-equal-p', so a symlinked or relative path still matches." "Remove Flan error overlays from BUFFER, or from the current buffer." (interactive) (with-current-buffer (or buffer (current-buffer)) - (remove-overlays (point-min) (point-max) 'flan-dev-error t))) + (remove-overlays (point-min) (point-max) 'flan-dev-error t) + ;; With nothing left to clear there is nothing for the hook to do, and a + ;; hook that stays installed after the last overlay is gone is the half of + ;; this that quietly accumulates. + (remove-hook 'pre-command-hook #'flan-dev--clear-errors-on-command t))) + +(defun flan-dev--clear-errors-on-command () + "Take this buffer's error overlays down, as a `pre-command-hook'. +Any command at all, because the overlay is about the evaluation that failed +and not about the text: moving, typing and evaluating are all something +else, and an overlay that survived a fix would be pointing at code that is +no longer wrong." + (flan-dev-clear-errors)) (defun flan-dev--show-error (loc msg) "Mark MSG at LOC, if LOC names a file some buffer is visiting. @@ -771,6 +801,10 @@ Returns non-nil when it put an overlay somewhere." (overlay-put ov 'after-string (propertize (concat " " msg) 'face 'flan-dev-error-message-face)) + ;; Local to this buffer, and installed only now that there is + ;; something for it to remove. + (add-hook 'pre-command-hook + #'flan-dev--clear-errors-on-command nil t) ;; Point goes there too, but only in the buffer being looked at: ;; moving point in a buffer nobody is showing is a surprise the ;; next time it is visited. @@ -1079,6 +1113,10 @@ of the tenth name tells you neither how many there were nor which." (note (plist-get reply :note)) (value (plist-get reply :value))) ;; Accepted, so whatever the last rejection marked is no longer true. + ;; Redundant now that any command clears it — the command that ran this + ;; evaluation already did — and kept because it is the claim being + ;; made, not the mechanism: an accepted evaluation is never left with a + ;; rejection drawn over it. (flan-dev-clear-errors) ;; ...and a name that was just installed should complete, and have a ;; signature, from this moment rather than from the next connect.