Quicksilver for Emacs: anything.el
Wednesday, July 11, 2007
In my post Mac OS X for Emacs Users, I mentioned that I use (and really like) Quicksilver:
Quicksilver application launcher: The standard place to put applications that you frequently use is the Dock. However, a lot of people (myself included) dislike the dock. There are alternatives though and my personal favorite is Quicksilver, an application launcher that allows you to quickly launch (and manipulate) anything using just the keyboard. However, as with many powerful utilities, it is really hard to describe what makes Quicksilver so neat. Fortunately, there are a number of good reviews, online videos, and tutorials that do a good job of illustrating how using Quicksilver really changes the way that you interact with your Mac. Since switching to Quicksilver, I just hide my Dock and launch everything from the keyboard. Incidentally, I also use Spotlight for local searches (I only index key directories with Quicksilver and use Spotlight for broader searches. Although Spotlight may look similar to Quicksivler initially, Quicksilver is much more powerful. But, Spotlight is much quicker at just searching for things, so I use them both. I bind Quicksilver to Cmd-SPC and Spotlight to Cmd-Shift-SPC). In addition to using Quicksilver, there are a number of other things that you can do if you want more of a "full screen" view in your apps; however, I've found that just the change to Quicksilver has been enough to radically change how I work on my Mac. Definitely recommended!Until recently, with Emacs, I haven't used any analogous equivalent to Quicksilver. There are many different ways to quickly access specific objects in Emacs; however, they all tend to be "modal" in nature (e.g. - dired mode for files/directories, iswitchb for buffers, recentf for recently opened files, etc). Then I discovered a new emacs utility: anything.el. It's a bit hard to describe (as is Quicksilver), but it really speeds up accessing things in Emacs. It doesn't matter whether the thing you want to access is in a buffer, a file that you've recently accessed, a file in the current directory, a command you've recently evaluated, or whatever - you can quickly and easily "do things" with that object.
The key to anything.el is the list of sources that anything.el looks at. By default, there are a certain number of sources defined, along with actions that go with those sources:
;; This is only an example. Customize it to your own taste!
(defvar anything-sources `(((name . "Buffers")
(candidates . anything-buffer-list)
(action . (("Switch to Buffer" . switch-to-buffer)
("Kill Buffer" . kill-buffer))))
((name . "File Name History")
(candidates . file-name-history)
(action . find-file)
(type . file))
((name . "Files from Current Directory")
(init-func . (lambda ()
(setq anything-default-directory
default-directory)))
(candidates . (lambda ()
(directory-files
anything-default-directory)))
(action . find-file)
(type . file))
((name . "Manual Pages")
(candidates . ,(progn
(require 'woman)
(woman-file-name "")
(sort (mapcar 'car
woman-topic-all-completions)
'string-lessp)))
(action . woman)
(requires-pattern . 2))
((name . "Complex Command History")
(candidates . (lambda ()
(mapcar 'prin1-to-string
command-history)))
(action . (lambda (c)
(eval (read c))))
(delayed))))
Documentation on the format of this sources list is in
the anything.el code. However, even without reading it, you'll notice in the above list that anything.el currently looks for matches in
the following categories:- Currently open buffers
- File names that have been recently opened
- File names that are in the current directory
- Man pages
- The command history
find-file command. However, if we wanted to add
additional actions (for example, to also provide an action to delete
files), we could easily add that action:((name . "Files from Current Directory")
(init-func . (lambda ()
(setq anything-default-directory
default-directory)))
(candidates . (lambda ()
(directory-files
anything-default-directory)))
(action . (("Open" . find-file)
("Delete" . delete-file)))
(type . file))
If I evoke anything.el and start typing ".em" in my home
directory, anything.el will display ".emacs" as one of the possible
choices since it is a file in my current directory. By the same
token, if I had been in another directory, it would still have
displayed ".emacs" as a possible match since I have recently accessed
my .emacs file and it will show up in the "File Name History" category of
matches. If I currently have my .emacs file open in a buffer, it
would also have been selected as a match in the "Buffers"
category. Since the default action for "Buffers" items is "Switch to
Buffer", I could have just pressed RET on the ".emacs" entry under
"Buffers" and I would have switched to that buffer. If, on the other
hand, I wanted to close that buffer, I could have pressed TAB. This
would have displayed the list of available commands (which for
"Buffers" is either "Switch to Buffer" or "Kill Buffer". I can then
select the appropriate action. All this takes a whole lot longer to
explain than it does to do. The end result is very quick access to
recently used "things" with the ability to perform a number of
actions on those items.Other individuals are already contributing new categories and actions. So far, the ones that I've come across are: Recently, iswitchb support has been integrated into anything.el so that it is now possible to automatically change over to anything.el if your iswitchb search doesn't return a match. Since a lot of people use iswitchb, I imagine this will be a very popular way to access anything.el (I know I've found it useful already!).
At the moment, anything.el is still in active development and the best place to follow development is to read the ongoing thread on gnu.emacs.sources and the history of changes on Emacs Wiki.

