An Extensive, But Not Comprehensive, Look At Finding Files

The Problem

Finding files can be a tricky business. If you have a number of different directories where your files can be stored, how can you open a particular file as quickly as possible. The standard find-file interface is pretty good if you’re already in the correct directory as it will do tab completion on anything you have already typed in similar to how a decent shell will.

ido improves this interface. If you enter part of a filename that has already been seen, even if it is in a different directory it will be offered to you. I enable flex-matching so that ido will match files containing the characters which have been entered anywhere so long as they are in the correct sequence. e.g. eod will match hello-world.c.

(ido-mode t) (setq ido-enable-flex-matching t) (setq ido-create-new-buffer 'always)

I understand that icicles does even better here, enabling you to filter out matches but as I’m not (yet) using it myself, I can’t say much more about it.

If you need more help in finding your files, what other options are there?

Bookmarks

I hadn’t heard of Bookmarks before I saw a a post on them recently. I use them in conjunction with directory aliases.

From the emacs manual:

Bookmarks are somewhat like registers in that they record positions you can jump to. Unlike registers, they have long names, and they persist automatically from one Emacs session to the next. The prototypical use of bookmarks is to record “where you were reading” in various files.

Filecache

Sacha Chua wrote a post about navigating your source tree using ido and filecache. I’m not sure what additional benefits

filecache offers over vanilla ido as ido finds files in other directories too.

Tags

The traditional way for finding function definitions is with Emacs Tags. Once you have generated the tags file you can go from call site to function definition with M-. (find-tag) .

When I go on holiday I leave a link to the current method I am working on in an orgfile. Then when I come back, I can click on the current work link and press M-. and I’ll be right back where I left off.

[[SomeClass::SomeMethod][Current Work]] * Work Projects *** A Specific Project SomeClass::SomeMethod Some notes about what I was doing...

I set the tags file so I don’t need to find that file.

(setq tags-file-name "/path/to/tags/file" )

( require ' ido ) ( require ' dired ) ( defconst *web-top* "~/websites" ) ( defun web (path) (concat *web-top* path))

dired-dirs is an associating list mapping aliases to directories. I need to use (list ...) to construct it so that (web ...) expands correctly.

( defconst *dired-dirs* (list (cons "mrc-theme" (web "/blog/mrc/wp-content/themes/mrc" )) (cons "mrc-pages" (web "/pages/mrc" )) (cons "webtest" (web "/test" )))) ( defconst *dired-aliases* (mapcar ( lambda (e) (car e)) *dired-dirs*))

dired-open-alias uses ido-completing-read to choose between the aliases I defined earlier.

( defun dired-open-alias ( &optional alias) (interactive) ( unless alias (setq alias (ido-completing-read "Alias: " *dired-aliases* nil t))) ( if (and (stringp alias) (> (length alias) 0 )) ( let ((pair (assoc alias *dired-dirs*))) ( if pair (dired (cdr pair)) ( error "Invalid alias %s" alias))) ( error "Invalid alias %s" alias)))

I really like f2 as a prefix key. The default binding is related to two-column mode, which I never use, and you can use it without pressing shift, ctrl or alt. I have this defined in my-defaults.el (which probably isn’t strictly necessary but at least it names the prefix map).

( defvar f2-prefix-map nil) (setq f2-prefix-map (make-sparse-keymap)) (global-set-key [f2] f2-prefix-map)

<f2> d calls up the list of directory aliases.

(global-set-key (kbd "<f2> d" ) 'dired-open-alias)