Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 57 additions & 8 deletions smex.el
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@
:group 'convenience
:link '(emacs-library-link :tag "Lisp File" "smex.el"))

(defface smex-keybinding-face
'((t (:foreground "orange" :weight bold)))
"Burndown warning 2" :group 'smex)

(defcustom smex-auto-update t
"If non-nil, `Smex' checks for new commands each time it is run.
Turn it off for minor speed improvements on older systems."
Expand Down Expand Up @@ -128,15 +132,44 @@ Set this to nil to disable fuzzy matching."
(setq commands (mapcar #'symbol-name commands))
(smex-read-and-run commands)))

(defun smex-extract-command-name (pretty-name)
"Given a string \"foo (C-c f)\", return \"foo\"."
(car (split-string pretty-name " ")))

(defvar smex-command-keybindings
(make-hash-table)
"A keybinding (a string) for each command symbol.")

(defun smex-update-command-keybindings ()
"Ensure `smex-command-keybindings' contains the latest keybindings.
This can take ~5 seconds, so we only run when Emacs
is idle."
(interactive)
(clrhash smex-command-keybindings)
(mapc (lambda (symbol-with-index)
(let* ((symbol (car symbol-with-index))
(keybinding (smex-find-keybinding symbol)))
(if keybinding
(puthash symbol keybinding smex-command-keybindings))))
smex-cache))

(defun smex-find-keybinding (command)
"Find the first keybinding for COMMAND, if one exists.
Uses the currently active keymap."
(let ((keybinding (where-is-internal command nil t t)))
(when keybinding
(key-description keybinding))))

(defun smex-completing-read (choices initial-input)
(let ((ido-completion-map ido-completion-map)
(ido-setup-hook (cons 'smex-prepare-ido-bindings ido-setup-hook))
(ido-enable-prefix nil)
(ido-enable-flex-matching smex-flex-matching)
(ido-max-prospects 10)
(minibuffer-completion-table choices))
(ido-completing-read (smex-prompt-with-prefix-arg) choices nil nil
initial-input 'extended-command-history (car choices))))
(smex-extract-command-name
(ido-completing-read (smex-prompt-with-prefix-arg) choices nil nil
initial-input 'extended-command-history (car choices)))))

(defun smex-prompt-with-prefix-arg ()
(if (not current-prefix-arg)
Expand Down Expand Up @@ -183,7 +216,19 @@ Set this to nil to disable fuzzy matching."
(setq smex-ido-cache (smex-convert-for-ido smex-cache)))

(defun smex-convert-for-ido (command-items)
(mapcar (lambda (command-item) (symbol-name (car command-item))) command-items))
(mapcar (lambda (command-item)
(let* ((command (car command-item))
(command-name (symbol-name command))
(keybinding
(gethash command smex-command-keybindings)))
(if keybinding
(concat
(format "%s" command-name)
(propertize
(format " (%s)" keybinding)
'face 'smex-keybinding-face))
command-name)))
command-items))

(defun smex-restore-history ()
"Rearranges `smex-cache' according to `smex-history'"
Expand Down Expand Up @@ -223,11 +268,14 @@ Set this to nil to disable fuzzy matching."
(unless (= i smex-command-count)
(setq smex-command-count i))))

(defun smex-auto-update (&optional idle-time)
"Update Smex when Emacs has been idle for IDLE-TIME."
(unless idle-time (setq idle-time 60))
(run-with-idle-timer idle-time t
'(lambda () (if (smex-detect-new-commands) (smex-update)))))
(defun smex-background-update ()
"Update Smex when Emacs has been idle for 20 seconds."
(run-with-idle-timer 20 t
'(lambda ()
(when (or (= 0 (hash-table-count smex-command-keybindings))
(smex-detect-new-commands))
(smex-update-command-keybindings)
(smex-update)))))

;;;###autoload
(defun smex-initialize ()
Expand All @@ -237,6 +285,7 @@ Set this to nil to disable fuzzy matching."
(smex-detect-new-commands)
(smex-rebuild-cache)
(add-hook 'kill-emacs-hook 'smex-save-to-file)
(smex-background-update)
(setq smex-initialized-p t))

(defun smex-initialize-ido ()
Expand Down