Function: eca-chat--doctor-format
eca-chat--doctor-format is a natively compiled function defined in
eca-chat.el.
Signature
(eca-chat--doctor-format SRC-BUF)
Documentation
Return a markdown diagnostic string describing chat buffer SRC-BUF.
Captures major-mode derivation, RET binding, shadowing minor modes,
ECA chat state, prompt overlays, and rule-based hints.
Source Code
;; Defined in /nix/store/jklqzw6pzz6j4jrbv8wy0iwgi7jlrbld-emacs-packages-deps/share/emacs/site-lisp/elpa/eca-20260928.1827/eca-chat.el
(defun eca-chat--doctor-format (src-buf)
"Return a markdown diagnostic string describing chat buffer SRC-BUF.
Captures `major-mode' derivation, RET binding, shadowing minor modes,
ECA chat state, prompt overlays, and rule-based hints."
(let* ((mm (buffer-local-value 'major-mode src-buf))
(in-chat-p (with-current-buffer src-buf
(derived-mode-p 'eca-chat-mode)))
(parent-mode (and (boundp 'eca-chat-parent-mode)
eca-chat-parent-mode))
(def-dir (buffer-local-value 'default-directory src-buf))
(ret-cmd (with-current-buffer src-buf
(key-binding (kbd "RET"))))
(return-cmd (with-current-buffer src-buf
(key-binding (kbd "<return>"))))
(cm-cmd (with-current-buffer src-buf
(key-binding (kbd "C-m"))))
(input-method (buffer-local-value 'current-input-method src-buf))
(e-indent (and (boundp 'electric-indent-mode)
(buffer-local-value 'electric-indent-mode src-buf)))
(e-pair (and (boundp 'electric-pair-mode)
(buffer-local-value 'electric-pair-mode src-buf)))
(e-quote (and (boundp 'electric-quote-mode)
(buffer-local-value 'electric-quote-mode src-buf)))
(evil-on (and (boundp 'evil-mode) (symbol-value 'evil-mode)))
(evil-state-val (and (boundp 'evil-state)
(buffer-local-value 'evil-state src-buf)))
(viper-on (and (boundp 'viper-mode) (symbol-value 'viper-mode)))
(god-on (and (boundp 'god-local-mode)
(buffer-local-value 'god-local-mode src-buf)))
(sp-on (and (boundp 'smartparens-mode)
(buffer-local-value 'smartparens-mode src-buf)))
(paredit-on (and (boundp 'paredit-mode)
(buffer-local-value 'paredit-mode src-buf)))
(corfu-on (and (boundp 'corfu-mode)
(buffer-local-value 'corfu-mode src-buf)))
(company-on (and (boundp 'company-mode)
(buffer-local-value 'company-mode src-buf)))
(chat-id (buffer-local-value 'eca-chat--id src-buf))
(closed (buffer-local-value 'eca-chat--closed src-buf))
(loading (buffer-local-value 'eca-chat--chat-loading src-buf))
(pending (buffer-local-value 'eca-chat--pending-questions src-buf))
(session (with-current-buffer src-buf
(ignore-errors (eca-session))))
(prompt-area (with-current-buffer src-buf
(ignore-errors (eca-chat--prompt-area-ov))))
(prompt-field (with-current-buffer src-buf
(ignore-errors (eca-chat--prompt-field-ov))))
(prompt-content (with-current-buffer src-buf
(ignore-errors (eca-chat--prompt-content))))
(pt (with-current-buffer src-buf (point)))
(self (eca-chat--doctor-self-check src-buf))
(hints nil))
;; --- compute hints ---
(unless in-chat-p
(push (format "Inspected buffer's `major-mode' is `%s' and is not \
derived from `eca-chat-mode'. `eca-chat-mode' likely failed to activate." mm)
hints))
(when (and in-chat-p
(not (eq ret-cmd 'eca-chat--key-pressed-return)))
(push (format "RET is bound to `%s', not \
`eca-chat--key-pressed-return'. Another keymap is intercepting RET — see \
\"Likely shadowing\" below." ret-cmd)
hints))
(when (and in-chat-p (null session))
(push "(eca-session) returned nil from inside the chat buffer — \
the buffer is not registered to any ECA workspace." hints))
(when (and in-chat-p (null prompt-area))
(push "The `eca-chat-prompt-area' overlay is missing — chat buffer is \
in an inconsistent state. Try `M-x eca-chat-reset'." hints))
(when (and in-chat-p evil-on (eq evil-state-val 'insert))
(push "evil-mode is in insert state. `evil-insert-state-map' (an \
emulation map) beats major-mode maps. If RET above is `evil-ret' / \
`newline', that is the cause." hints))
(when (and in-chat-p pending)
(push "An unanswered question is pending \
(`eca-chat--pending-questions' non-nil). RET without freeform input is \
intentionally a no-op until you answer the question." hints))
(when (and in-chat-p closed)
(push "This chat is marked closed (`eca-chat--closed' non-nil); \
sending will raise a user-error." hints))
(when (and in-chat-p (not (plist-get self :mode-map-ret-ok)))
(push (format "`eca-chat-mode-map' RET is `%s', expected \
`eca-chat--key-pressed-return'. Some code has clobbered the mode-map \
after `eca-chat' was loaded; check your user config."
(plist-get self :mode-map-ret))
hints))
(when (and in-chat-p (eq (plist-get self :cond-ok) nil))
(push "`eca-chat--key-pressed-return' references the markdown-link \
clause before the expandable clause. Loaded code predates commit \
`dac33d8'; pull master, restart Emacs, and `M-x byte-recompile-directory' \
if the warning persists." hints))
(when (and in-chat-p (plist-get self :has-label)
(not (plist-get self :label-ret-ok)))
(push "The first expandable block label has no RET binding in its \
`keymap' text-property. Either the loaded `eca-chat-expandable.el' \
predates commit `dac33d8' or this block was rendered before the fix was \
reloaded; start a new chat or wait for a fresh tool call to be rendered."
hints))
(when (and in-chat-p (plist-get self :stale-elc-p))
(push (format "`%s' is newer than the loaded `%s'. Recompile \
(`M-x byte-recompile-directory') or delete the stale `.elc' and restart \
Emacs." (plist-get self :source-file) (plist-get self :loaded-file))
hints))
;; --- render report into temp buffer and return as string ---
(with-temp-buffer
(insert "### Inspected chat buffer\n\n")
(insert (format "- buffer: %s\n" (buffer-name src-buf)))
(insert (format "- major-mode: %s\n" mm))
(insert (format "- derived from `eca-chat-mode': %s\n"
(if in-chat-p "yes" "NO")))
(insert (format "- `eca-chat-parent-mode': %s\n" parent-mode))
(insert (format "- default-directory: %s\n\n" def-dir))
(insert "### Key bindings in chat buffer\n\n")
(insert (format "- RET → %s\n" (or ret-cmd "<unbound>")))
(insert (format "- <return> → %s\n" (or return-cmd "<unbound>")))
(insert (format "- C-m → %s\n\n" (or cm-cmd "<unbound>")))
(insert "### Likely shadowing / input translation\n\n")
(insert (format "- current-input-method: %s\n" (or input-method "nil")))
(insert (format "- electric-indent-mode: %s\n" e-indent))
(insert (format "- electric-pair-mode: %s\n" e-pair))
(insert (format "- electric-quote-mode: %s\n" e-quote))
(insert (format "- evil-mode: %s (state=%s)\n"
evil-on evil-state-val))
(insert (format "- viper-mode: %s\n" viper-on))
(insert (format "- god-local-mode: %s\n" god-on))
(insert (format "- smartparens-mode: %s\n" sp-on))
(insert (format "- paredit-mode: %s\n" paredit-on))
(insert (format "- corfu-mode: %s\n" corfu-on))
(insert (format "- company-mode: %s\n\n" company-on))
(insert "### ECA chat state\n\n")
(insert (format "- eca-chat--id: %s\n" chat-id))
(insert (format "- eca-chat--closed: %s\n" closed))
(insert (format "- eca-chat--chat-loading: %s\n" loading))
(insert (format "- eca-chat--pending-questions: %d\n"
(length pending)))
(insert "- (eca-session): ")
(if session
(insert (format "found (id=%s, roots=%S)\n\n"
(eca--session-id session)
(eca--session-workspace-folders session)))
(insert "NIL — buffer is not registered to a workspace\n\n"))
(insert "### Self-check\n\n")
(insert (format "- `eca-chat-mode-map' RET → %s %s\n"
(or (plist-get self :mode-map-ret) "<unbound>")
(if (plist-get self :mode-map-ret-ok) "✓" "✗")))
(insert (format
"- `eca-chat--key-pressed-return': expandable before \
markdown-link %s\n"
(let ((status (plist-get self :cond-ok)))
(cond ((eq status t) "✓")
((null status) "✗")
(t "? (could not introspect)")))))
(if (plist-get self :has-label)
(insert (format "- nearest expandable label RET → %s %s\n"
(let ((b (plist-get self :label-ret)))
(cond ((null b) "<unbound>")
((functionp b) "<toggle lambda>")
(t (format "%s" b))))
(if (plist-get self :label-ret-ok) "✓" "✗")))
(insert "- nearest expandable label RET: n.a. \
(no blocks rendered yet)\n"))
(insert (format "- loaded from: %s\n"
(or (plist-get self :loaded-file) "<unknown>")))
(when (plist-get self :stale-elc-p)
(insert (format " ⚠ source `%s' is newer than the loaded `.elc'\n"
(plist-get self :source-file))))
(insert "\n")
(insert "### Prompt overlays\n\n")
(insert (format "- prompt-area overlay: %s\n"
(if prompt-area
(format "%d..%d"
(overlay-start prompt-area)
(overlay-end prompt-area))
"MISSING")))
(insert (format "- prompt-field overlay: %s\n"
(if prompt-field
(format "%d..%d"
(overlay-start prompt-field)
(overlay-end prompt-field))
"MISSING")))
(insert (format "- point: %d\n" pt))
(insert (format "- (eca-chat--prompt-content): %S\n\n" prompt-content))
(insert "### Hints\n\n")
(if hints
(dolist (h (nreverse hints))
(insert "- " h "\n"))
(insert "- No obvious issue detected by the static checks.\n"))
(buffer-string))))