Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Acronyms #73

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
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
5 changes: 5 additions & 0 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ next/previous match. `Enter` executes the selected command.
`smex-major-mode-commands` runs Smex, limited to commands that
are relevant to the active major mode. Try it with Dired or Magit.

### Acronyms
Set `smex-acronyms` to use acronyms instead of the whole command names.

E.g.: `ff` instead of `find-file` or `ffow` instead of `find-file-other-window`

### Command help
`C-h f`, while Smex is active, runs `describe-function` on the
currently selected command.
Expand Down
69 changes: 68 additions & 1 deletion smex.el
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@
:group 'convenience
:link '(emacs-library-link :tag "Lisp File" "smex.el"))

(defcustom smex-acronyms nil
"If non-nil, you can use acronyms instead of the whole command names.
E.g.: 'ff' instead of 'find-file', or 'ffow' instead of
'find-file-other-window."
:type 'boolean
: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 @@ -73,6 +80,7 @@ Set this to nil to disable fuzzy matching."
(defvar smex-history)
(defvar smex-command-count 0)
(defvar smex-custom-action nil)
(defvar smex-activep nil) ;; t when we are into smex-completing-read()

;; Check if Smex is supported
(when (equal (cons 1 1)
Expand Down Expand Up @@ -134,7 +142,8 @@ Set this to nil to disable fuzzy matching."
(ido-enable-prefix nil)
(ido-enable-flex-matching smex-flex-matching)
(ido-max-prospects 10)
(minibuffer-completion-table choices))
(minibuffer-completion-table choices)
(smex-activep t))
(ido-completing-read (smex-prompt-with-prefix-arg) choices nil nil
initial-input 'extended-command-history (car choices))))

Expand Down Expand Up @@ -479,5 +488,63 @@ sorted by frequency of use."
(insert "\n "))))
(insert "\n)\n")))

(defadvice ido-set-matches-1 (around ido-smex-acronym-matches activate)
"Filters ITEMS by setting acronynms first."
(if (and smex-acronyms smex-activep (> (length ido-text) 1))

;; We use a hash table for the matches, <type> => <list of items>, where
;; <type> can be one of (e.g. `ido-text' is "ff"):
;; - a-s: for acronym strict matching (i.e. "^f[^-]*-f[^-]*$");
;; - a-r: for acronym relaxed matching (i.e. "^f[^-]*-f[^-]*");
;; - prefix: the text start with (i.e. "^ff.*");
;; - substring: the text contains (i.e. ".*ff.*");
;; - flex: flexible matching (i.e. ".*f.*f.*");
(let ((regex (concat "^" (mapconcat
(lambda (c) (regexp-quote (char-to-string c)))
ido-text "[^-]*-")))
(flex-regex (mapconcat
(lambda (c) (regexp-quote (char-to-string c)))
ido-text ".*"))
(matches (make-hash-table :test 'eq)))

;; Filtering
(dolist (item items)
(let ((key))
(cond
;; strict match
((string-match (concat regex "[^-]*$") item)
(setq key 'a-s))

;; acronym matching
((string-match regex item)
(setq key 'a-r))

;; prefix matching
((string-match (concat "^" ido-text) item)
(setq key 'prefix))

;; substring matching
((and (not ido-enable-prefix) (string-match ido-text item))
(setq key 'substring))

;; flexible matching
((and ido-enable-flex-matching (string-match flex-regex item))
(setq key 'flex)))

(when key
;; We have a winner! Update its list.
(let ((list (gethash key matches ())))
(puthash key (push item list) matches)))))

;; Finally, we can order and return the results
(setq ad-return-value (append (gethash 'a-s matches)
(gethash 'a-r matches)
(gethash 'prefix matches)
(gethash 'substring matches)
(gethash 'flex matches))))

;; ...else, run the original ido-set-matches-1
ad-do-it))

(provide 'smex)
;;; smex.el ends here