Skip to content


Add caching of files per project root #7

wants to merge 1 commit into from

3 participants


On my machine with a large rails project, it can take a couple of seconds to pull up the list of files. With this caching support, it's now instantaneous. The cache can be cleared by calling find-file-in-project with a prefix argument.

I'd like to use this file cache for a grep-in-project. You might consider bumping the version.



Is there a reason this never got merged?


Sorry for the silence on this. I didn't merge this because I don't want to have to think about clearing the cache. I would take a patch that caches optionally as long as it's turned off by default.


Since Emacs 24.4 just added support for a filesystem notification API, it might be possible to register a watch to update the cache, which would be another way to solve the problem. But I don't want to add features that require users to trigger an update.


Defaulting to having the feature off sounds pretty reasonable. The only trouble with using the filesystem notification API is that it would require users to have emacs 24.4 which is probably unrealistic for the moment.

Can I look in to this and submit another pull request?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Feb 2, 2012
  1. Add caching of files per project root

    Andrew Hobson committed
Showing with 29 additions and 21 deletions.
  1. +29 −21 find-file-in-project.el
50 find-file-in-project.el
@@ -86,6 +86,9 @@ This overrides variable `ffip-project-root' when set.")
(defvar ffip-limit 512
"Limit results to this many files.")
+;; cache the files per project root
+(defvar ffip-project-file-cache (make-hash-table :test 'equal))
(defun ffip-project-root ()
"Return the root of the project."
(let ((project-root (or ffip-project-root
@@ -109,38 +112,43 @@ This overrides variable `ffip-project-root' when set.")
(mapconcat (lambda (pat) (format "-name \"%s\"" pat))
ffip-patterns " -or "))
-(defun ffip-project-files ()
+(defun ffip-project-files (&optional arg)
"Return an alist of all filenames in the project and their path.
Files with duplicate filenames are suffixed with the name of the
directory they are found in so that they are unique."
- (let ((file-alist nil))
- (mapcar (lambda (file)
- (let ((file-cons (cons (file-name-nondirectory file)
- (expand-file-name file))))
- (when (assoc (car file-cons) file-alist)
- (ffip-uniqueify (assoc (car file-cons) file-alist))
- (ffip-uniqueify file-cons))
- (add-to-list 'file-alist file-cons)
- file-cons))
- (split-string (shell-command-to-string
- (format "find %s -type f \\( %s \\) %s | head -n %s"
- (or ffip-project-root
- (ffip-project-root)
- (error "No project root found"))
- (ffip-join-patterns)
- ffip-find-options
- ffip-limit))))))
+ (let* ((current-project-root (or ffip-project-root
+ (ffip-project-root)
+ (error "No project root found")))
+ (file-alist (if arg
+ nil
+ (gethash current-project-root ffip-project-file-cache))))
+ (or file-alist
+ (puthash current-project-root
+ (mapcar (lambda (file)
+ (let ((file-cons (cons (file-name-nondirectory file)
+ (expand-file-name file))))
+ (when (assoc (car file-cons) file-alist)
+ (ffip-uniqueify (assoc (car file-cons) file-alist))
+ (ffip-uniqueify file-cons))
+ (add-to-list 'file-alist file-cons)
+ file-cons))
+ (split-string (shell-command-to-string
+ (format "find %s -type f \\( %s \\) %s | head -n %s"
+ current-project-root
+ (ffip-join-patterns)
+ ffip-find-options
+ ffip-limit)))) ffip-project-file-cache))))
-(defun find-file-in-project ()
+(defun find-file-in-project (&optional arg)
"Prompt with a completing list of all files in the project to find one.
The project's scope is defined as the first directory containing
an `.emacs-project' file. You can override this by locally
setting the variable `ffip-project-root'."
- (interactive)
- (let* ((project-files (ffip-project-files))
+ (interactive "P")
+ (let* ((project-files (ffip-project-files arg))
(files (mapcar 'car project-files))
(file (if (and (boundp 'ido-mode) ido-mode)
(ido-completing-read "Find file in project: " files)
Something went wrong with that request. Please try again.