Skip to content

Commit

Permalink
Show keybindings in smex results.
Browse files Browse the repository at this point in the history
Getting keybindings is relatively slow (a few seconds), so we only
update keybindings when Emacs is idle. We repurpose `smex-auto-update`
for this, as it's currently unused.
  • Loading branch information
Wilfred committed Nov 25, 2015
1 parent 8c40191 commit 70dee6f
Showing 1 changed file with 48 additions and 8 deletions.
56 changes: 48 additions & 8 deletions smex.el
Original file line number Diff line number Diff line change
Expand Up @@ -128,15 +128,45 @@ 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* ((keybindings (where-is-internal command))
(first-binding (car keybindings)))
(when first-binding
(key-description first-binding))))

(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 +213,15 @@ 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
(format "%s (%s)" command-name keybinding)
command-name)))
command-items))

(defun smex-restore-history ()
"Rearranges `smex-cache' according to `smex-history'"
Expand Down Expand Up @@ -223,11 +261,12 @@ 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 (smex-detect-new-commands)
(smex-update-command-keybindings)
(smex-update)))))

;;;###autoload
(defun smex-initialize ()
Expand All @@ -237,6 +276,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

0 comments on commit 70dee6f

Please sign in to comment.