Last edit
Summary: Automatic bookmark creation (Bookmark+). Use cached file names during buffer-name completion (Icicles).
Added:
> == Automatically Create Bookmarks for Cached Files ==
> [[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 [[BookmarkPlus#AutofileBookmarks|Autofile Bookmarks]].
> == Use During Buffer-Name Completion in Icicles ==
> 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]].
The FileNameCache is a really nice piece of functionality in Emacs. It provides functionality to quickly find often-needed files without using bookmarks. From the Commentary:
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.
See also:
‘locate’: find files without knowing their locationsAdding 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>'‘load-path’ or ‘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-read-cache-from-file "~/.file_cache")
‘file-cache-clear-cache’ is not autoloaded, so for this to work you have to put (require ‘filecache) in your .emacs – GregBognar?
‘file-cache-save-cache-to-file’:‘with-temp-file’ instead of creating a buffer and inserting a string.‘prin1’ instead of printing to a string.‘file-cache-read-cache-from-file’:‘find-file-noselect’ instead of ‘insert-file-contents’.‘read’ on the buffer contents, instead of ‘read-from-string’ – no need to create a string with the buffer contents.‘icicle-candidate-set-save’ and ‘icicle-retrieve-candidates-from-set’ in library icicles-mcmd.el. – DrewAdams Thanks Drew! Very good hints. Much smaller and neater! Me like Lisp! – MaDa
There is a problem with the above version of ‘file-cache-read-cache-from-file’ since ‘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 ‘read’ing):
(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)))
I bind ‘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))))))))
– JohanClaesson?
(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