~edwargix/emacs.d

854b0a61bfe0e70e5220b246298ee070486cb979 — David Florness 2 months ago a3715f1
llm: pop company for agent-shell @/ completion

agent-shell installs a post-self-insert-hook trigger that calls the built-in
completion-at-point, which opens the *Completions* buffer.  With
global-company-mode on, that pre-empts company: the trigger runs on
post-self-insert-hook *before* company's post-command-hook trigger, and a bare
'/' has an empty prefix (below company-minimum-prefix-length), so company never
fires for slash commands. (corfu works out of the box here because it hooks
completion-in-region-function; company doesn't.)

Fix: on agent-shell-completion-mode-hook -- which runs after the mode installs
its trigger -- swap agent-shell's trigger for one that calls
company-manual-begin on @ or / at a word boundary. company-manual-begin ignores
company-minimum-prefix-length, so the command list pops even with nothing typed
after the '/'.

The swap is guarded on the private agent-shell--trigger-completion-at-point
still being on the hook, so if agent-shell renames or drops it, this no-ops and
falls back to upstream completion instead of double-triggering.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 files changed, 30 insertions(+), 0 deletions(-)

M lisp/llm.el
M lisp/llm.el => lisp/llm.el +30 -0
@@ 1,7 1,37 @@
(defun my-agent-shell-company-trigger ()
  "Pop up company for agent-shell @ and / completions at a word boundary.
`company-manual-begin' ignores `company-minimum-prefix-length', so the
command list appears even with no characters typed after the `/'."
  (when (and (memq (char-before) '(?@ ?/))
             (or (= (point) (1+ (line-beginning-position)))
                 (memq (char-before (1- (point))) '(?\s ?\t ?\n))))
    (company-manual-begin)))

(defun my-agent-shell-use-company-completion ()
  "Route agent-shell @/ completion through company.
agent-shell's own trigger calls `completion-at-point', which opens the
default *Completions* buffer from `post-self-insert-hook' before company's
`post-command-hook' trigger runs, so company never fires on a bare `/'.
Swap it for a trigger that invokes company directly.  Runs from
`agent-shell-completion-mode-hook', after that mode installs its trigger.

Guarded on the (private) `agent-shell--trigger-completion-at-point' still
being installed on the hook: if agent-shell renames or drops it, this
no-ops and leaves upstream's completion untouched rather than
double-triggering."
  (when (and agent-shell-completion-mode
             (memq #'agent-shell--trigger-completion-at-point
                   post-self-insert-hook))
    (remove-hook 'post-self-insert-hook
                 #'agent-shell--trigger-completion-at-point t)
    (add-hook 'post-self-insert-hook
              #'my-agent-shell-company-trigger nil t)))

(use-package agent-shell
  :custom
  (agent-shell-prefer-viewport-interaction t)
  (agent-shell-session-restore-verbosity 'full)
  :hook (agent-shell-completion-mode . my-agent-shell-use-company-completion)
  :config
  (setq acp-logging-enabled t))