From 0c4d449b9dc5855464851518eb1081e0315045a5 Mon Sep 17 00:00:00 2001 From: Emanuele Tomasi Date: Sun, 22 Jun 2014 01:30:41 +0200 Subject: [PATCH 01/10] Using acronyms instead of the whole command names. When the custom variable `smex-acronyms` is non-nil, the user can use acronyms instead of the whole command names. E.g.: 'ff' instead of 'find-file' or, 'ffow' instead of 'find-file-other-window' # Please enter the commit message for your changes. Lines starting --- smex.el | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/smex.el b/smex.el index f1888d7..390926f 100644 --- a/smex.el +++ b/smex.el @@ -35,6 +35,13 @@ :group 'convenience :link '(emacs-library-link :tag "Lisp File" "smex.el")) +(defcustom smex-acronyms t + "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." @@ -454,5 +461,33 @@ sorted by frequency of use." (set-buffer-modified-p nil) (goto-char (point-min)))) +;;; Filters ido-matches setting acronynm matches in front of the results +(defadvice ido-set-matches-1 (after ido-smex-acronym-matches activate) + (if (and smex-acronyms (> (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)))) + (provide 'smex) ;;; smex.el ends here From cb88db7e6bd49784f5042b66bdeab0654c5d972a Mon Sep 17 00:00:00 2001 From: Emanuele Tomasi Date: Sun, 22 Jun 2014 17:22:20 +0200 Subject: [PATCH 02/10] [acronyms] We don't need to reverse ad-return-value --- smex.el | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/smex.el b/smex.el index 390926f..1466ac5 100644 --- a/smex.el +++ b/smex.el @@ -486,8 +486,7 @@ sorted by frequency of use." (append acronym-matches ad-return-value)) - (delete-dups ad-return-value) - (reverse ad-return-value)))) + (delete-dups ad-return-value)))) (provide 'smex) ;;; smex.el ends here From 227aef89bb3d27072ac0d18d4cc3959956009ad3 Mon Sep 17 00:00:00 2001 From: Emanuele Tomasi Date: Sun, 22 Jun 2014 22:18:16 +0200 Subject: [PATCH 03/10] [acronyms] Removed filter ad-return-value. Is another thing. --- smex.el | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/smex.el b/smex.el index 1466ac5..1fa6d76 100644 --- a/smex.el +++ b/smex.el @@ -461,12 +461,12 @@ sorted by frequency of use." (set-buffer-modified-p nil) (goto-char (point-min)))) -;;; Filters ido-matches setting acronynm matches in front of the results (defadvice ido-set-matches-1 (after ido-smex-acronym-matches activate) + "Filters ido-matches by setting acronynms in front of the ad-return-value." (if (and smex-acronyms (> (length ido-text) 1)) (let ((regex (concat "^" (mapconcat 'char-to-string ido-text "[^-]*-"))) - (acronym-matches (list)) - (remove-regexes '("-menu-"))) + (acronym-matches (list))) + ;; Creating the list of the results to be set as first (dolist (item items) (if (string-match (concat regex "[^-]*$") item) ;; strict match @@ -474,13 +474,6 @@ sorted by frequency of use." (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 From 83541e92a77aaa726a094adf09db3877d4d0975e Mon Sep 17 00:00:00 2001 From: Emanuele Tomasi aka targzeta Date: Tue, 29 Aug 2017 15:54:24 +0200 Subject: [PATCH 04/10] Filtering command names based upon regexes. --- smex.el | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/smex.el b/smex.el index a1987d1..d41fcdd 100644 --- a/smex.el +++ b/smex.el @@ -48,6 +48,16 @@ Turn it off for minor speed improvements on older systems." :type 'boolean :group 'smex) +(defcustom smex-filter-alist nil + "List used by `Smex' to hide command names. Every command name that matches +one of these regexes will be hide." + :type '(repeat regexp) + :initialize 'custom-initialize-default + :set (lambda (symbol value) + (set-default symbol value) + (smex-update))) + :group 'smex + (defcustom smex-save-file (locate-user-emacs-file "smex-items" ".smex-items") "File in which the smex state is saved between Emacs sessions. Variables stored are: `smex-data', `smex-history'. @@ -187,7 +197,12 @@ Set this to nil to disable fuzzy matching." (setq smex-cache (sort smex-cache 'smex-sorting-rules)) (smex-restore-history) - (setq smex-ido-cache (smex-convert-for-ido smex-cache))) + (setq smex-ido-cache (smex-filter-commands + (smex-convert-for-ido smex-cache)))) + +(defun smex-filter-commands (commands) + (dolist (filter smex-filter-alist commands) + (cl-delete-if (lambda (item) (string-match filter item)) commands))) (defun smex-convert-for-ido (command-items) (mapcar (lambda (command-item) (symbol-name (car command-item))) command-items)) From 085c4176b2a997a2bfcec7a5b6cfbf348fcc6ef8 Mon Sep 17 00:00:00 2001 From: Emanuele Tomasi Date: Mon, 20 Nov 2017 23:53:00 +0100 Subject: [PATCH 05/10] [bugfix] typo --- smex.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/smex.el b/smex.el index d41fcdd..34293f4 100644 --- a/smex.el +++ b/smex.el @@ -55,8 +55,8 @@ one of these regexes will be hide." :initialize 'custom-initialize-default :set (lambda (symbol value) (set-default symbol value) - (smex-update))) - :group 'smex + (smex-update)) + :group 'smex) (defcustom smex-save-file (locate-user-emacs-file "smex-items" ".smex-items") "File in which the smex state is saved between Emacs sessions. From 7f248b5118efb24e4a290216370d8bedcfb1ce00 Mon Sep 17 00:00:00 2001 From: Emanuele Tomasi aka targzeta Date: Tue, 21 Nov 2017 12:30:52 +0100 Subject: [PATCH 06/10] [bugfix] Error setting smex-filter-alist: (void-variable smex-cache) This error appears when we set smex-filter-alist before (smex-initialize) --- smex.el | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/smex.el b/smex.el index 34293f4..658aa2f 100644 --- a/smex.el +++ b/smex.el @@ -54,8 +54,9 @@ one of these regexes will be hide." :type '(repeat regexp) :initialize 'custom-initialize-default :set (lambda (symbol value) - (set-default symbol value) - (smex-update)) + (when (fboundp 'smex-cache) + (set-default symbol value) + (smex-update))) :group 'smex) (defcustom smex-save-file (locate-user-emacs-file "smex-items" ".smex-items") From c0457df309d054f496b371fe6702f2f079aac2f1 Mon Sep 17 00:00:00 2001 From: Emanuele Tomasi aka targzeta Date: Tue, 21 Nov 2017 12:46:00 +0100 Subject: [PATCH 07/10] Running ido-set-matches-1 advice only with smex. --- smex.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/smex.el b/smex.el index 658aa2f..1fde8ee 100644 --- a/smex.el +++ b/smex.el @@ -504,7 +504,7 @@ sorted by frequency of use." (defadvice ido-set-matches-1 (after ido-smex-acronym-matches activate) "Filters ido-matches by setting acronynms in front of the ad-return-value." - (if (and smex-acronyms (> (length ido-text) 1)) + (if (and smex-acronyms (smex-already-running) (> (length ido-text) 1)) (let ((regex (concat "^" (mapconcat 'char-to-string ido-text "[^-]*-"))) (acronym-matches (list))) From ea36f833c166a54d982cc26fb8fd0c482a1424af Mon Sep 17 00:00:00 2001 From: Emanuele Tomasi aka targzeta Date: Tue, 21 Nov 2017 12:47:08 +0100 Subject: [PATCH 08/10] Setting the exact matches in front of the list. --- smex.el | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/smex.el b/smex.el index 1fde8ee..b36eb19 100644 --- a/smex.el +++ b/smex.el @@ -510,10 +510,12 @@ sorted by frequency of use." ;; Creating the list of the results to be set as first (dolist (item items) - (if (string-match (concat regex "[^-]*$") item) ;; strict match + (if (string-match ido-text item) ;; exact match (add-to-list 'acronym-matches item) - (if (string-match regex item) ;; appending relaxed match - (add-to-list 'acronym-matches item t)))) + (if (string-match (concat regex "[^-]*$") item) ;; strict match + (add-to-list 'acronym-matches item) + (if (string-match regex item) ;; relaxed match + (add-to-list 'acronym-matches item t))))) ;; Creating resulting list (setq ad-return-value From a6e4eeca329a2e4ac0b47582a032c6abfc78228d Mon Sep 17 00:00:00 2001 From: Emanuele Tomasi aka targzeta Date: Tue, 21 Nov 2017 12:48:11 +0100 Subject: [PATCH 09/10] delete-dups while building the result. --- smex.el | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/smex.el b/smex.el index b36eb19..167edd1 100644 --- a/smex.el +++ b/smex.el @@ -519,9 +519,7 @@ sorted by frequency of use." ;; Creating resulting list (setq ad-return-value - (append acronym-matches - ad-return-value)) + (delete-dups (append acronym-matches ad-return-value)))))) - (delete-dups ad-return-value)))) (provide 'smex) ;;; smex.el ends here From 6f4d167d82e338c8985c51e154df8d60113e1779 Mon Sep 17 00:00:00 2001 From: Emanuele Tomasi aka targzeta Date: Wed, 22 Nov 2017 18:41:35 +0100 Subject: [PATCH 10/10] Improved and clearer algorithm --- smex.el | 51 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/smex.el b/smex.el index 167edd1..3ca4e8c 100644 --- a/smex.el +++ b/smex.el @@ -503,23 +503,48 @@ sorted by frequency of use." (insert "\n)\n"))) (defadvice ido-set-matches-1 (after ido-smex-acronym-matches activate) - "Filters ido-matches by setting acronynms in front of the ad-return-value." + "Filters ITEMS by setting acronynms first." (if (and smex-acronyms (smex-already-running) (> (length ido-text) 1)) + + ;; We use a hash table for the matches, => , where + ;; can be one of (e.g. `ido-text' is "ff"): + ;; - strict: strict acronym match (i.e. "^f[^-]*-f[^-]*$"); + ;; - relaxed: for relaxed match (i.e. "^f[^-]*-f[^-]*"); + ;; - start: the text start with (i.e. "^ff.*"); + ;; - contains: the text contains (i.e. ".*ff.*"); (let ((regex (concat "^" (mapconcat 'char-to-string ido-text "[^-]*-"))) - (acronym-matches (list))) + (matches (make-hash-table :test 'eq))) - ;; Creating the list of the results to be set as first + ;; Filtering (dolist (item items) - (if (string-match ido-text item) ;; exact match - (add-to-list 'acronym-matches item) - (if (string-match (concat regex "[^-]*$") item) ;; strict match - (add-to-list 'acronym-matches item) - (if (string-match regex item) ;; relaxed match - (add-to-list 'acronym-matches item t))))) - - ;; Creating resulting list - (setq ad-return-value - (delete-dups (append acronym-matches ad-return-value)))))) + (let ((key)) + (cond + ;; strict match + ((string-match (concat regex "[^-]*$") item) + (setq key 'strict)) + + ;; relaxed match + ((string-match regex item) + (setq key 'relaxed)) + + ;; text that start with ido-text + ((string-match (concat "^" ido-text) item) + (setq key 'start)) + + ;; text that contains ido-text + ((string-match ido-text item) + (setq key 'contains))) + + (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 'strict matches) + (gethash 'relaxed matches) + (gethash 'start matches) + (gethash 'contains matches)))))) (provide 'smex) ;;; smex.el ends here