Keep the indicator, eldoc and the cache to buffers that asked for them

Three things the first cut got wrong by being global when it had no business
being.

The modeline entry was added to `mode-line-misc-info' at load. It returns nil
outside a Flan buffer, so it was invisible — but it was still evaluated on
every redisplay of every buffer in the session, for someone who loads the
client and then spends the afternoon in dired. It is installed buffer-locally
by `flan-dev-setup' now, which already runs in exactly the buffers that want
it. The `derived-mode-p' guard stays: cheap, and it keeps the function honest
wherever it is called from.

`flan-dev-setup' switched eldoc on. Contributing a documentation source is
this file's business; whether eldoc runs at all is the user's, and turning it
on overrules someone who has `global-eldoc-mode' off deliberately. It is on by
default, so nearly everyone gets the same behaviour either way.

And a reconnect forgot the name cache without asking for it again. An empty
cache is honest but silent — eldoc goes quiet, M-. falls through to whatever
else is registered, and nothing says why — until the next install happens to
refill it. It refreshes straight after reconnecting, which is safe from there
because the connection is live by that point and the request does not come
back round through the same function.
This commit is contained in:
Joseph Ferano 2026-09-11 17:58:34 +07:00
parent 7118d6106d
commit 6f3ec2bb91
2 changed files with 32 additions and 3 deletions

View File

@ -179,6 +179,12 @@ that quietly did nothing, which is why it is on."
;; A restarted daemon is a rebuilt program: everything known
;; about its names was about the last one.
(flan-dev--forget-defs)
;; And asked again straight away. An empty cache is honest
;; but silent: eldoc would go quiet and M-. would fall through
;; to some other backend until the next install happened to
;; refill it. Safe to call from here — the connection is live
;; by now, so it does not come back through this function.
(ignore-errors (flan-dev-refresh-defs))
(message "flan dev: reconnected to %s"
(abbreviate-file-name flan-dev--socket)))
(error
@ -254,8 +260,11 @@ mistake, so it is distinguished from never having connected."
(_ (propertize " flan:off" 'face 'shadow
'help-echo "Not connected (C-c C-z)")))))
;; Appended rather than prepended: this is the least urgent thing in the line.
(add-to-list 'mode-line-misc-info '(:eval (flan-dev-mode-line)) t)
;; Installed buffer-locally by `flan-dev-setup', not globally. A global entry
;; would evaluate on every redisplay of every buffer in the session — dired,
;; eshell, everything — to return nil, for someone who may never open a .flan
;; file at all. The `derived-mode-p' guard above stays anyway: cheap, and it
;; keeps the function honest wherever it is called from.
;;;###autoload
(defun flan-show-output ()
@ -533,8 +542,15 @@ Installed from here rather than from `flan-mode', which must keep working for
someone editing Flan with no program running and this file never loaded."
(add-hook 'completion-at-point-functions #'flan-dev-completion-at-point nil t)
(add-hook 'xref-backend-functions #'flan-dev-xref-backend nil t)
;; Registered, not switched on. Contributing a source is this file's
;; business; whether eldoc runs at all is the user's, and turning it on for
;; someone who has `global-eldoc-mode' off is overruling a decision they made
;; on purpose. It is on by default, so this is what almost everyone gets.
(add-hook 'eldoc-documentation-functions #'flan-dev-eldoc-function nil t)
(eldoc-mode 1))
(unless (member '(:eval (flan-dev-mode-line)) mode-line-misc-info)
;; Appended rather than prepended: the least urgent thing in the line.
(setq-local mode-line-misc-info
(append mode-line-misc-info '((:eval (flan-dev-mode-line)))))))
(add-hook 'flan-mode-hook #'flan-dev-setup)

View File

@ -54,6 +54,14 @@ is written instead — the real `message' call the real command makes."
(string-match-p "live" (flan-dev-mode-line))))
(test-flan--check "and says nothing in a buffer that is not Flan's"
(with-temp-buffer (null (flan-dev-mode-line))))
;; Buffer-locally, so that someone who loads this and never opens a .flan
;; file is not evaluating it on every redisplay of every buffer they have.
(test-flan--check "the indicator is in this buffer's modeline"
(member '(:eval (flan-dev-mode-line)) mode-line-misc-info))
(test-flan--check "and not in everyone else's"
(with-temp-buffer
(not (member '(:eval (flan-dev-mode-line))
mode-line-misc-info))))
;; A daemon restarted while Emacs was not looking is the ordinary case. The
;; socket outlives this connection, so dropping the process and asking again
@ -67,6 +75,11 @@ is written instead — the real `message' call the real command makes."
(test-flan--check "the next request reconnects on its own"
(and (process-live-p flan-dev--connection)
(member "step" (plist-get r :fns)))))
;; ...and knows the program's names again. An empty cache after a reconnect
;; is honest but silent: eldoc goes quiet and M-. falls through to another
;; backend, with nothing said about why.
(test-flan--check "and knows the program's names again"
(assoc "step" flan-dev--defs))
;; But a socket nobody is listening on is refused by name, rather than
;; retried forever or reported as some other failure.