Smex

Intro

SmexScreenshotImage

Smex is a M-x enhancement for Emacs. Built on top of IDO, it provides a convenient interface to your recently and most frequently used commands. And to all the other commands, too.

Extras: Limit commands to those relevant to the active major mode. Show frequently used commands that have no key bindings.

Download

Via package.el, el-get or http://github.com/nonsequitur/smex/blob/master/smex.el?raw=true

Documentation

http://github.com/nonsequitur/smex/

Customization/Hacks

Delayed Initiation

I install smex with the following code to make emacs startup a little faster. This delays initializing smex until it’s needed. IMO, smex should load without this hack. Just have smex call ‘smex-initialize’ when it’s needed instead of having the user do it. --LeWang

(global-set-key [(meta x)] (lambda ()
                             (interactive)
                             (or (boundp 'smex-cache)
                                 (smex-initialize))
                             (global-set-key [(meta x)] 'smex)
                             (smex)))

(global-set-key [(shift meta x)] (lambda ()
                                   (interactive)
                                   (or (boundp 'smex-cache)
                                       (smex-initialize))
                                   (global-set-key [(shift meta x)] 'smex-major-mode-commands)
                                   (smex-major-mode-commands)))

You can also use:

;;; Smex
(autoload 'smex "smex"
  "Smex is a M-x enhancement for Emacs, it provides a convenient interface to
your recently and most frequently used commands.")

(global-set-key (kbd "M-x") 'smex)

Hyphen on Space

How to modify smex so that typing a space will insert a hyphen ‘-’ like in normal M-x?

      (defadvice smex (around space-inserts-hyphen activate compile)
        (let ((ido-cannot-complete-command 
               `(lambda ()
                  (interactive)
                  (if (string= " " (this-command-keys))
                      (insert ?-)
                    (funcall ,ido-cannot-complete-command)))))
          ad-do-it))

If there is only one match it will be completed instead of inserting a hyphen (which may well be a desirable thing). To avoid that, fset ido-complete-space to that lambda form above, then fset it back after ad-do-it (flet doesn’t work for interactive functions).

See also ido-complete-space-or-hyphen.

Update less often

I don’t like to have smex update every time I run (auto-update is usually good enough, and is noticeably faster). But it’s annoying when I manually load a file and the new commands are not in smex. So I add a smex-update to after-load-functions.

    (defun smex-update-after-load (unused)
      (when (boundp 'smex-cache)
        (smex-update)))
    (add-hook 'after-load-functions 'smex-update-after-load)

See also Update smex after function calls that are likely to define new commands

Using acronyms

You can see mnemonical commands (within completion) before the others with this code snippet:

;;; Filters ido-matches setting acronynm matches in front of the results
(defadvice ido-set-matches-1 (after ido-smex-acronym-matches activate)
  (if (and (fboundp 'smex-already-running) (smex-already-running)
           (> (length ido-text) 1))
      (let ((regex (concat "^" (mapconcat 'char-to-string ido-text "[^-]*-")))
            (acronym-matches (list))
            (remove-regexes '("-menu-")))
        ;; Creating the list of the results to be set as first
        (dolist (item items)
          (if (string-match (concat regex "[^-]*$") item) ;; strict match
              (add-to-list 'acronym-matches item)
            (if (string-match regex item) ;; appending relaxed match
                (add-to-list 'acronym-matches item t))))

        ;; Filtering ad-return-value
        (dolist (to_remove remove-regexes)
          (setq ad-return-value
                (delete-if (lambda (item)
                             (string-match to_remove item))
                           ad-return-value)))

        ;; Creating resulting list
        (setq ad-return-value
              (append acronym-matches
                      ad-return-value))

        (delete-dups ad-return-value)
        (reverse ad-return-value))))

e.g. without this code the completion of ‘ffow’ shows:

{ ediff-show-registry | Buffer-menu-1-window | Buffer-menu-2-window ...

with:

{ find-file-other-window | find-function-other-window | ediff-show-registry ...

targzeta