Function: projectile-index-project-async

projectile-index-project-async is an autoloaded, interactive and byte-compiled function defined in projectile.el.

Signature

(projectile-index-project-async &optional PROJECT-ROOT)

Documentation

Index PROJECT-ROOT in the background and populate the files cache.

This warms projectile-projects-cache without blocking Emacs, so a later projectile-find-file (or any command that lists project files) finds the cache already populated instead of indexing synchronously.

Only the external-command indexing methods (alien and hybrid) can be warmed this way; under native indexing this is a no-op with a message, since the Elisp directory walk cannot run off the main thread. Warming also requires caching to be enabled.

When PROJECT-ROOT is omitted the current project is used. Returns the indexing process, or nil when nothing was started.

Key Bindings

Source Code

;; Defined in ~/.emacs.d/elpa/projectile-20260820.1509/projectile.el
;;;###autoload
(defun projectile-index-project-async (&optional project-root)
  "Index PROJECT-ROOT in the background and populate the files cache.

This warms `projectile-projects-cache' without blocking Emacs, so a
later `projectile-find-file' (or any command that lists project files)
finds the cache already populated instead of indexing synchronously.

Only the external-command indexing methods (`alien' and `hybrid') can be
warmed this way; under `native' indexing this is a no-op with a message,
since the Elisp directory walk cannot run off the main thread.  Warming
also requires caching to be enabled.

When PROJECT-ROOT is omitted the current project is used.  Returns the
indexing process, or nil when nothing was started."
  (interactive)
  (let ((root (or project-root (projectile-acquire-root))))
    (cond
     ((eq projectile-indexing-method 'native)
      (projectile--message-always
       "Async indexing needs the `alien'/`hybrid' method; `native' cannot be warmed")
      nil)
     ((not projectile-enable-caching)
      (projectile--message-always
       "Async indexing has no effect while caching is disabled")
      nil)
     ((let ((proc (gethash root projectile--async-index-processes)))
        (and proc (process-live-p proc)))
      (projectile--message-always "Already indexing %s" root)
      nil)
     (t
      (projectile--message-always "Indexing %s in the background..." root)
      ;; The callback needs to know which process it belongs to so it can
      ;; tell whether it is still the active index for ROOT when it
      ;; finishes (a re-trigger or `projectile-invalidate-cache' replaces
      ;; or clears the registry entry).  But the process object is the
      ;; return value of the very call the callback is passed to, so we
      ;; thread it through a mutable cell that is filled in below, before
      ;; the (asynchronous) sentinel can ever run.
      (let* ((proc-cell (list nil))
             (proc
              (projectile-dir-files-alien-async
               root
               (lambda (files err)
                 ;; Ignore a stale result whose registry entry was
                 ;; replaced (re-trigger) or removed (invalidation) while
                 ;; we were running, so it can't resurrect a cache that
                 ;; has since moved on.
                 (when (eq (gethash root projectile--async-index-processes)
                           (car proc-cell))
                   (remhash root projectile--async-index-processes)
                   (if err
                       (projectile--message-always
                        "Background indexing of %s failed: %s" root err)
                     (projectile-cache-project root files)
                     (projectile--message-always "Finished indexing %s (%d files)"
                                                 root (length files))))))))
        (setcar proc-cell proc)
        (when (processp proc)
          (puthash root proc projectile--async-index-processes))
        proc)))))