¶Completions are everywhere
- M-x
- describe-variable / describe-function
- find-file
- switch-to-buffer
- company-mode
It saves time to make the list of recommendations more tailored to your usage!
¶Enter prescient.el
Prescient is a sorting and filtering extension for Ivy, company-mode
, and Selectrum. It provides:
- Sorting candidates based on how frequently you select them
- Configurable filtering rules to quickly find what you’re looking for
¶Ivy
Since we’ve been using Ivy in the configuration for this channel, let’s try Prescient with it.
First, try M-x
without Prescient turned on, then install ivy-prescient
(make sure to load it after Counsel!)
(use-package ivy-prescient :after counsel :config (ivy-prescient-mode 1))
Now run M-x
again and take a look at the results. Select a command, then run M-x
again, see that it is suggested first!
Prescient is remembering the selections you’ve made for M-x
(or counsel-M-x
in this case) and it sorts them first based on some configurable rules:
prescient-history-length
: How many chosen candidates will be rememberedprescient-frequency-decay
: A multiplier applied to each frequent candidate each selection (default:0.997
)prescient-frequency-threshold
: Threshold used for “forgetting” a command that isn’t used frequently anymore (default:0.5
)
NOTE: These variables apply to all usages of Prescient, not just for Ivy!
¶Trying Prescient with other Ivy commands
counsel-find-file
counsel-describe-variable
counsel-switch-buffer
- Doesn’t work!
¶Excluding certain Ivy commands from sorting
- Commands to exclude:
ivy-prescient-sort-commands
By default it contains ivy-switch-buffer
which counsel-switch-buffer
uses internally.
¶Disabling length-based sorting
You might have noticed M-x
is now sorting all commands by shortest-first. If this is distracting to you, it can be disabled!
(setq prescient-sort-length-enable nil)
¶Changing the filtering method
Set prescient-filter-method
:
;; This is the default value! (setq prescient-filter-method '(literal regexp fuzzy))
literal:
the subquery must be a substring of the candidate. Supports char folding.initialism:
the subquery must match a substring of the initials of the candidate.prefix:
words (substrings of only word characters) match the beginning of words found in the candidate, in order, separated by the same non-word characters that separate words in the query. This is similar to the completion style partial or what you get from Ivy by defaultanchored:
words are separated by capital letters or symbols, with capital letters being the start of a new word. This is similar to prefix, but allows for less typing.fuzzy
: the characters of the subquery must match some subset of those of the candidate, in the correct order but not necessarily contiguous.regexp:
the subquery is interpreted directly as a regular expression. (Try^p\w+d
)
¶Going back to Ivy’s filtering
If you are too used to Ivy’s filtering styles, you can use those while still keeping Prescient’s sorting:
(setq ivy-prescient-enable-filtering nil)
NOTE: Make sure you toggle ivy-prescient-mode
after setting this for it to take effect!
¶Getting the old highlighting back
ivy-prescient
changes how results are highlighted when you start typing. To emulate the old highlighting you can use ivy-prescient-retain-classic-highlighting
:
(setq ivy-prescient-retain-classic-highlighting t)
¶Company Mode
Prescient also has an extension for Company to provide candidate sorting based on frequency:
(use-package company-prescient :after company :config (company-prescient-mode 1))
NOTE: Prescient filtering is not applied to company-mode! It would require a custom completion backend.
¶Remembering history between sessions
Remembering your history is great, but it’s even better when it is remembered each time you start Emacs:
;; Remember candidate frequencies across sessions (prescient-persist-mode 1)
¶With all that said…
ivy-prescient
needs a new maintainer: https://github.com/raxod502/prescient.el/issues/65
If you like using Prescient with Ivy, consider helping out!
¶Selectrum
We will talk about Selectrum in another video; we’ll hook it up to Prescient then!