You can start the file-cache by either using
‘C-TAB’ when entering a file name in the minibuffer (
‘C-x C-f C-TAB C-g’ works), or loading library filecache (
‘M-x load-library’ or (require ‘filecache)). More information on this feature is available in node File Name Cache of the EmacsManual: File Name Cache.
‘locate’: find files without knowing their locations
Adding files to the file name cache is easy:
`M-x file-cache-add-directory <RET> DIRECTORY <RET>'
`M-x file-cache-add-directory-using-find <RET> DIRECTORY <RET>'
`M-x file-cache-add-directory-using-locate <RET> DIRECTORY <RET>'
‘locate’to find them all.
`M-x file-cache-add-directory-list <RET> VARIABLE <RET>'
‘exec-path’, whose value is a list of directory names.
To test this out, add all files in Emacs’ lisp directory to the cache. Evaluate the following:
(file-cache-add-directory "c:/pgm/emacs/lisp/") ;;; Name of your own Emacs-lisp dir, of course
Next, to use it, execute
‘find-file’ as usual:
Find file: ~/elisp/
And, at the prompt, type a few letters of the file name you want to open:
Find file: ~/elisp/sim
Next press C-TAB (the default key binding), which will expand to something like this:
Find file: c:/pgm/emacs/lisp/simple.el
The suggested way to add files automatically:
(eval-after-load "filecache" '(progn (message "Loading file cache...") (file-cache-add-directory-using-find "~/projects") (file-cache-add-directory-list load-path) (file-cache-add-directory "~/") (file-cache-add-file-list (list "~/foo/bar" "~/baz/bar")) ))
For file lists that seldom change, I use this:
(defun file-cache-save-cache-to-file (file) "Save contents of `file-cache-alist' to FILE. For later retrieval using `file-cache-read-cache-from-file'" (interactive "FFile: ") (with-temp-file (expand-file-name file) (prin1 file-cache-alist (current-buffer)))) (defun file-cache-read-cache-from-file (file) "Clear `file-cache-alist' and read cache from FILE. The file cache can be saved to a file using `file-cache-save-cache-to-file'." (interactive "fFile: ") (file-cache-clear-cache) (let ((buf (find-file-noselect file))) (setq file-cache-alist (read buf)) (kill-buffer buf)))
In my .emacs, I have this:
‘file-cache-clear-cache’ is not autoloaded, so for this to work you have to put (require ‘filecache) in your .emacs – GregBognar?
‘with-temp-file’instead of creating a buffer and inserting a string.
‘prin1’instead of printing to a string.
‘read’on the buffer contents, instead of
‘read-from-string’– no need to create a string with the buffer contents.
Thanks Drew! Very good hints. Much smaller and neater! Me like Lisp! – MaDa
There is a problem with the above version of
‘read’ is dependant on the point. If one has opened the file cache file and navigated around in it,
‘read’ing the cache will fail because when opening the file cache file, the point will not be at the beginning of buffer any more. Here is a version that seems to work fine (it makes sure the point is at the beginning of the buffer before
(defun file-cache-read-cache-from-file (file) "Clear `file-cache-alist' and read cache from FILE. The file cache can be saved to a file using `file-cache-save-cache-to-file'." (interactive "fFile: ") (file-cache-clear-cache) (save-excursion (set-buffer (find-file-noselect file)) (beginning-of-buffer) (setq file-cache-alist (read (current-buffer)))))
Bookmark+ user option
‘bmkp-autofile-filecache’ lets you automatically create autofile bookmarks whenever you add a file name to the file-name cache. You can optionally create the bookmark instead of, or in addition to, caching the file name. See Autofile Bookmarks.
In Icicles, when you complete buffer names, you can use
‘C-x F’ to include matching cached file names as completion candidates. This does everything that
‘iswitchb-fc’ does (see next), and more. See Icicles - Buffer-Name Input.
I think iswitchb-fc is awesome!! – Anonymous
(defun iswitchb-fc-read-buffer (prompt &optional default existing) (save-window-excursion (buffer-name (iswitchb)))) (defadvice read-buffer (around iswitchb-fc-read-buffer) (setq ad-return-value (iswitchb-fc-read-buffer prompt)))
Filecache rules but I did not like the way it completes the file names. Iswitchb-fc above is a really cool enhancement to filecache but I did not like that it was integrated with
‘C-x b’ (I guess I want to know what files I actually have open). Hence this little hack:
(defun file-cache-iswitchb-file () "Using iswitchb, interactively open file from file cache'. First select a file, matched using iswitchb against the contents in `file-cache-alist'. If the file exist in more than one directory, select directory. Lastly the file is opened." (interactive) (let* ((file (file-cache-iswitchb-read "File: " (mapcar (lambda (x) (car x)) file-cache-alist))) (record (assoc file file-cache-alist))) (find-file (concat (if (= (length record) 2) (car (cdr record)) (file-cache-iswitchb-read (format "Find %s in dir: " file) (cdr record))) file)))) (defun file-cache-iswitchb-read (prompt choices) (let ((iswitchb-make-buflist-hook (lambda () (setq iswitchb-temp-buflist choices)))) (iswitchb-read-buffer prompt)))
‘C-c f’ to it:
(global-set-key "\C-cf" 'file-cache-iswitchb-file)
Happy happy, joy joy! – MaDa
Oh man, this is the best enhancement I’ve seen in years – Alex
I prefer ido-mode before iswitchb-mode, so here is take two but using ido:
(defun file-cache-ido-find-file (file) "Using ido, interactively open file from file cache'. First select a file, matched using ido-switch-buffer against the contents in `file-cache-alist'. If the file exist in more than one directory, select directory. Lastly the file is opened." (interactive (list (file-cache-ido-read "File: " (mapcar (lambda (x) (car x)) file-cache-alist)))) (let* ((record (assoc file file-cache-alist))) (find-file (expand-file-name file (if (= (length record) 2) (car (cdr record)) (file-cache-ido-read (format "Find %s in dir: " file) (cdr record))))))) (defun file-cache-ido-read (prompt choices) (let ((ido-make-buffer-list-hook (lambda () (setq ido-temp-list choices)))) (ido-read-buffer prompt)))
Copied the previous command and added
‘C-f’ to fallback to the current directory. Typically you hit
‘C-f’ when you realize the file was not found in the file name cache.
(defun jcl-file-cache-ido-find-file () "Open a file from the file cache. First select a file from `file-cache-alist'. If the file exist in more than one directory one is asked to select which to open. If you find out that the desired file is not present in the file cache then you may want to fallback to normal ido find file with C-f. Bind this command to C-x C-f to get: C-x C-f -> Open file in filecache. C-x C-f C-f -> Open file with normal ido. C-x C-f C-f C-f -> Open file with vanilla find-file. " (interactive) (let* (jcl-ido-text (file (let ((ido-setup-hook (cons (lambda () (define-key ido-completion-map [(control ?f)] (lambda (arg) (interactive "P") (if jcl-ido-text (ido-magic-forward-char arg) (setq jcl-ido-text ido-text ido-text 'fallback-from-cache ido-exit 'done) (exit-minibuffer))))) ido-setup-hook))) (ido-completing-read "Cached File: " (mapcar 'car file-cache-alist))))) (if (eq file 'fallback-from-cache) (progn (setq minibuffer-history (delete 'fallback-from-cache minibuffer-history)) (ido-file-internal ido-default-file-method nil nil "Ido Find File: " nil jcl-ido-text)) (let ((record (assoc file file-cache-alist))) (find-file (expand-file-name file (if (= (length record) 2) (cadr record) (ido-completing-read (format "Find %s in dir: " file) (cdr record) nil t))))))))
(defun file-cache-add-this-file () (and buffer-file-name (file-exists-p buffer-file-name) (file-cache-add-file buffer-file-name))) (add-hook 'kill-buffer-hook 'file-cache-add-this-file)
I have used this for more than a year. – rubikitch