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)))))