Archive for July, 2007

Yesterday I posted a command that executes emacs commands by giving an abbreviation. Today I’ve built a complete global minor mode around it. Here’s the file’s description:

This file includes the command `exec-abbrev-cmd’ which lets you execute a
command by giving it in an abbreviated form, where the abbreviation takes
the first character of each word in the command name. For example “g” is an
abbreviation for the command `gnus’, “eb” is an abbreviation for
`emms-browser’ and “omm” is an abbreviation for `outline-minor-mode’. Of
course it is possible, that an abbreviation matches several commands,
e.g. “g” matches not only `gnus’ but `grep’, `gdb’ and some more. In such
cases you will be queried, which command to use.

To have this functionality quickly accessible you might want to bind it to
some key. That’s what I use:

(add-to-list 'load-path "~/elisp") ;; Where is exec-abbrev-cmd.el?
(require 'exec-abbrev-cmd)         ;; Load it.
(global-set-key (kbd "C-x x") 'exec-abbrev-cmd)

Now you’ll say, “Wow, what a nice feature!”, but it’s even getting better.
Let’s say you often invoke `customize-face’ with `C-x x cf RET’ and then
choosing from the completion list between `copy-file’ and `customize-face’.
Always `copy-file’ is selected first, because it’s lexicographically before
`customize-face’. As a solution to this problem there’s
`exec-abbrev-cmd-mode’, a global minor mode that does bookkeeping how often
you invoke a command with `exec-abbrev-cmd’, so that the list of commands
you have to choose from is sorted by the frequency of command invokation.
After a while in most cases `C-x x <abbrev> RET RET’ will do what you want.

If you want to enable this feature put this in your ~/.emacs:

(exec-abbrev-cmd-mode 1)

Have fun!

You can get exec-abbrev-cmd.el from my elisp darcs repository.

UPDATE: I moved all my projects to Git repositories. Have a look at my homepage for more infos on exec-abbrev-cmd.el.

Advertisements

Today I looked at my ~/.emacs file and I saw that I defined a lot of aliases for commands I frequently use. Most of the time the aliases are words that are built by taking each first char of a word in the command, e.g. nsn for newsticker-show-news, eb for emms-browser or omm for outline-minor-mode. But what should I do when I want to create an alias for ediff-buffers since eb is already used?

My solution was to write a function that calls a command by its abbreviation.

(defun th-execute-abbreviated-command (prefixarg)
  "Queries for a command abbreviation like "mbm" and calculates
a list of all commands of the form "m[^-]*-b[^-]*-m[^-]*$". If
this list has only one item, this command will be called
interactively. If there a more choices, the user will be queried
which one to call.

The PREFIXARG is passed on to the invoked command."
  (interactive "P")
  (let* ((abbrev (read-from-minibuffer "Command Abbrev: "))
         (regexp (let ((char-list (append abbrev nil)) ;; string => list of chars
                       (str "^"))
                   (dolist (c char-list)
                     (setq str (concat str (list c) "[^-]*-")))
                   (concat (substring str 0 (1- (length str))) "$")))
         (commands (remove-if-not (lambda (string) (string-match regexp string))
                                  (let (c)
                                    (mapatoms (lambda (a)
                                                (if (commandp a)
                                                    (push (symbol-name a) c))))
                                    c))))
    (cond ((> (length commands) 1)
           (call-interactively (intern
                                (if ido-mode
                                    (ido-completing-read "Command: " commands)
                                  (completing-read "Command: " commands)))
                               t))
          ((= (length commands) 1)
           (call-interactively (intern (car commands)) t))
          (t (message "No such command.")))))

To make it quickly accessible I’ve bound it to C-x x.

(global-set-key (kbd "C-x x") 'th-execute-abbreviated-command)

UPDATE:
Alex Schröder pointed me to the builtin partial-completion-mode which allows nearly the same. It requires that you type the separator (- or _), too, so you need a few keystrokes more when you know the commands name. On the other hand it completes not only function names, but also files, e.g. f_b.c will expand to foo_bar.c.

UPDATE2:
The version above uses ido-completing-read when ido-mode is enabled.