Function: consult--async-dynamic

consult--async-dynamic is a byte-compiled function defined in consult.el.

Signature

(consult--async-dynamic FUN &optional RESTART)

Documentation

Dynamic computation of candidates.

FUN computes the candidates. It takes either a single input argument or an input argument and a callback function, if computed candidates should be updated incrementally. The callback function must not be called after FUN has returned. RESTART is the time after which an interrupted computation should be restarted and defaults to consult-async-input-debounce.

Source Code

;; Defined in ~/.emacs.d/elpa/consult-20260805.1130/consult.el
(defun consult--async-dynamic (fun &optional restart)
  "Dynamic computation of candidates.
FUN computes the candidates.  It takes either a single input argument or
an input argument and a callback function, if computed candidates should
be updated incrementally.  The callback function must not be called
after FUN has returned.
RESTART is the time after which an interrupted computation should be
restarted and defaults to `consult-async-input-debounce'."
  (setq restart (or restart consult-async-input-debounce))
  (when (equal (func-arity fun) '(1 . 1))
    (let ((orig fun))
      (setq fun (lambda (input callback)
                  (funcall callback (funcall orig input))))))
  (lambda (sink)
    (let ((timer (timer-create)) (current nil) (compute nil))
      (setq compute
            (lambda (input)
              (cancel-timer timer)
              (funcall sink [indicator running])
              (redisplay)
              (let* ((state 'init)
                     (killed
                      (while-no-input
                        (funcall
                         fun input
                         (lambda (response)
                           (when (eq state 'done)
                             (error "consult--async-dynamic: Callback called too late"))
                           (let (throw-on-input)
                             (when (eq state 'init)
                               (funcall sink 'flush)
                               (setq state 'running))
                             (when response
                               (funcall sink response)
                               ;; Accept process input such that timers
                               ;; trigger and refresh the completion UI.
                               (accept-process-output)))))
                        (setq current input
                              state 'done)
                        nil)))
                (funcall sink `[indicator ,(if killed 'killed 'finished)])
                (funcall sink 'refresh)
                ;; If the computation was killed, restart it after a while.
                ;; This happens when the point is moved.  Then the input does
                ;; not change and the computation is not restarted otherwise.
                (when (and killed (not (memq timer timer-list)))
                  (timer-set-function timer compute (list input))
                  (timer-set-time timer (timer-relative-time nil restart))
                  (timer-activate timer)))))
      (lambda (action)
        (prog1 (funcall sink action)
          (pcase action
            ((or 'cancel 'destroy) (cancel-timer timer))
            ((pred stringp)
             (if (not (equal action current))
                 (funcall compute action)
               (cancel-timer timer)
               (funcall sink [indicator finished])))))))))