-
Notifications
You must be signed in to change notification settings - Fork 25
/
Copy pathselectrum-prescient.el
175 lines (148 loc) · 6.58 KB
/
selectrum-prescient.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
;;; selectrum-prescient.el --- prescient.el + Selectrum -*- lexical-binding: t -*-
;; Copyright (C) 2019-2022 Radian LLC and contributors
;; Author: Radian LLC <[email protected]>
;; Homepage: https://github.com/raxod502/prescient.el
;; Keywords: extensions
;; Created: 8 Dec 2019
;; Package-Requires: ((emacs "25.1") (prescient "6.1.0") (selectrum "3.1"))
;; SPDX-License-Identifier: MIT
;; Version: 6.3.1
;;; Commentary:
;; selectrum-prescient.el provides an interface for using prescient.el
;; to sort and filter candidates in Selectrum menus. To enable its
;; functionality, turn on `selectrum-prescient-mode' in your init-file
;; or interactively.
;; For more information, see https://github.com/raxod502/prescient.el.
;;; Code:
;;;; Libraries
(require 'prescient)
(require 'selectrum)
(require 'subr-x)
;;;; Customization
(defgroup selectrum-prescient nil
"Prescient adapter for Selectrum."
:group 'convenience
:prefix "selectrum-prescient"
:link '(url-link "https://github.com/raxod502/prescient.el"))
(defcustom selectrum-prescient-enable-filtering t
"Whether to enable filtering by `selectrum-prescient'.
If nil, then `selectrum-prescient-mode' does not change the
filtering behavior of Selectrum from the default. See Selectrum
documentation for how to configure filtering yourself. Changing
this variable will not take effect until
`selectrum-prescient-mode' has been reloaded."
:group 'selectrum-prescient
:type 'boolean)
(defcustom selectrum-prescient-enable-sorting t
"Whether to enable sorting by `selectrum-prescient'.
If nil, then `selectrum-prescient-mode' does not change the
sorting behavior of Selectrum from the default. See Selectrum
documentation for how to configure sorting yourself. Changing
this variable will not take effect until
`selectrum-prescient-mode' has been reloaded."
:group 'selectrum-prescient
:type 'boolean)
;;;; Toggling commands
(defun selectrum-prescient--toggle-refresh ()
"Refresh the Selectrum UI.
This function is added to `prescient--toggle-refresh-functions' by
`selectrum-prescient-mode.'"
(when selectrum-is-active
(selectrum-exhibit)))
;;;; Minor mode
(defun selectrum-prescient--preprocess (candidates)
"Sort CANDIDATES, unless `selectrum-should-sort' is nil."
(when selectrum-should-sort
(setq candidates (prescient-sort candidates)))
candidates)
(defun selectrum-prescient--refine (input candidates)
"According to INPUT, filter CANDIDATES.
Additionally, if `selectrum-should-sort',
`selectrum-prescient-enable-sorting', and the option
`prescient-sort-full-matches-first' are all non-nil, sort full
matches first."
(let ((filtered-comps (prescient-filter input candidates))
;; TODO?: For some reason, these text properties are lost in
;; Selectrum, but not in Vertico and Icomplete Vertical, when
;; running `M-x'. This is probably due to how Selectrum
;; handles function tables?
;;
;; Due to the above, we recalculate the values here.
(regexps (prescient-filter-regexps input))
(ignore-case (prescient-ignore-case-p input)))
(if (and selectrum-should-sort
selectrum-prescient-enable-sorting
prescient-sort-full-matches-first)
(prescient-sort-full-matches-first
filtered-comps regexps ignore-case)
filtered-comps)))
(defvar selectrum-prescient--old-preprocess-function nil
"Previous value of `selectrum-preprocess-candidates-function'.")
(defvar selectrum-prescient--old-refine-function nil
"Previous value of `selectrum-refine-candidates-function'.")
(defun selectrum-prescient--remember (candidate &rest _)
"Remember CANDIDATE in prescient.el.
For use on `selectrum-candidate-selected-hook'."
(prescient-remember candidate))
(defvar selectrum-prescient--old-highlight-function nil
"Previous value of `selectrum-highlight-candidates-function'.")
;;;###autoload
(define-minor-mode selectrum-prescient-mode
"Minor mode to use prescient.el in Selectrum menus."
:global t
:group 'prescient
(if selectrum-prescient-mode
(progn
;; Prevent messing up variables if we explicitly enable the
;; mode when it's already on.
(selectrum-prescient-mode -1)
(setq selectrum-prescient-mode t)
(when selectrum-prescient-enable-filtering
(setq selectrum-prescient--old-refine-function
selectrum-refine-candidates-function)
(setq selectrum-prescient--old-highlight-function
selectrum-highlight-candidates-function)
(setq selectrum-refine-candidates-function
#'selectrum-prescient--refine)
(setq selectrum-highlight-candidates-function
#'prescient--highlight-candidates)
(define-key selectrum-minibuffer-map
(kbd "M-s") prescient-toggle-map)
(add-hook 'prescient--toggle-refresh-functions
#'selectrum-prescient--toggle-refresh))
(when selectrum-prescient-enable-sorting
(setq selectrum-prescient--old-preprocess-function
selectrum-preprocess-candidates-function)
(setq selectrum-preprocess-candidates-function
#'selectrum-prescient--preprocess)
(add-hook 'selectrum-candidate-selected-hook
#'selectrum-prescient--remember)
(add-hook 'selectrum-candidate-inserted-hook
#'selectrum-prescient--remember)))
(when (eq selectrum-refine-candidates-function
#'selectrum-prescient--refine)
(setq selectrum-refine-candidates-function
selectrum-prescient--old-refine-function))
(when (eq selectrum-highlight-candidates-function
#'prescient--highlight-candidates)
(setq selectrum-highlight-candidates-function
selectrum-prescient--old-highlight-function))
(when (equal (lookup-key selectrum-minibuffer-map (kbd "M-s"))
prescient-toggle-map)
(define-key selectrum-minibuffer-map (kbd "M-s") nil))
(remove-hook 'prescient--toggle-refresh-functions
#'selectrum-prescient--toggle-refresh)
(remove-hook 'selectrum-candidate-selected-hook
#'selectrum-prescient--remember)
(remove-hook 'selectrum-candidate-inserted-hook
#'selectrum-prescient--remember)
(when (eq selectrum-preprocess-candidates-function
#'selectrum-prescient--preprocess)
(setq selectrum-preprocess-candidates-function
selectrum-prescient--old-preprocess-function))))
;;;; Closing remarks
(provide 'selectrum-prescient)
;;; selectrum-prescient.el ends here
;; Local Variables:
;; outline-regexp: ";;;;* "
;; End: