diff --git a/CHANGELOG.md b/CHANGELOG.md index 923de14..e207d47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -82,6 +82,11 @@ The format is based on [Keep a Changelog]. `selectrum-secondary-highlight` are now a part of `selectrum-prescient.el` rather than Selectrum proper ([#94]) +* The user option `prescient-sort-full-matches-first` was added. If + non-nil, candidates that are fully matched are sorted before + partially matched candidates, though all candidates still follow the + order of recency, frequency, and length. See [#95]. + [#66]: https://github.com/raxod502/prescient.el/pull/66 [#67]: https://github.com/raxod502/prescient.el/pull/67 [#70]: https://github.com/raxod502/prescient.el/pull/70 @@ -89,6 +94,7 @@ The format is based on [Keep a Changelog]. [#76]: https://github.com/raxod502/prescient.el/pull/76 [#77]: https://github.com/raxod502/prescient.el/pull/77 [#94]: https://github.com/raxod502/prescient.el/pull/94 +[#95]: https://github.com/raxod502/prescient.el/pull/95 ## 5.0 (release 2020-07-16) ### Breaking changes diff --git a/README.md b/README.md index 03c70d0..8790e48 100644 --- a/README.md +++ b/README.md @@ -97,6 +97,10 @@ different one by customizing `prescient-filter-method`. to define your own custom filter methods, and use them by adding the appropriate symbol to `prescient-filter-method`. +* `prescient-sort-full-matches-first`: Whether `prescient.el` sorts + candidates that are fully matched before candidates that are + partially matched. + ### Company-specific * `company-prescient-sort-length-enable`: By default, the standard diff --git a/prescient.el b/prescient.el index ef8c7af..8d79c02 100644 --- a/prescient.el +++ b/prescient.el @@ -184,6 +184,15 @@ after the cache data is updated by `prescient-remember' when `prescient-persist-mode' is activated." :type 'boolean) +(defcustom prescient-sort-full-matches-first nil + "Whether to sort fully matched candidates before others. + +Prescient can sort by recency, frequency, and candidate length. +With this option, fully matched candidates will be sorted before +partially matched candidates, but candidates in each group will +still be sorted like normal." + :type 'boolean) + ;;;; Caches (defvar prescient--history (make-hash-table :test 'equal) @@ -525,18 +534,27 @@ must match each subquery, either using substring or initialism matching. Discard any that do not, and return the resulting list. Do not modify CANDIDATES; always make a new copy of the list." (let ((regexps (prescient-filter-regexps query)) - (results nil)) + (results nil) + (prioritized-results nil)) (save-match-data ;; Use named block in case somebody loads `cl' accidentally - ;; which causes `dolist' to turn into `cl-dolist' which creates - ;; a nil block implicitly. + ;; which causes `dolist' to turn into `cl-dolist' which + ;; creates a nil block implicitly. (dolist (candidate candidates) (cl-block done - (dolist (regexp regexps) - (unless (string-match regexp candidate) - (cl-return-from done))) - (push candidate results))) - (nreverse results)))) + (let ((fully-matched nil)) + (dolist (regexp regexps) + (unless (string-match regexp candidate) + (cl-return-from done)) + (when (and + prescient-sort-full-matches-first + (equal (length candidate) + (length (match-string 0 candidate)))) + (setq fully-matched t))) + (if fully-matched + (push candidate prioritized-results) + (push candidate results))))) + (nconc (nreverse prioritized-results) (nreverse results))))) (defmacro prescient--sort-compare () "Hack used to cause the byte-compiler to produce faster code.