112
112
(cons string face)
113
113
(cons string face)))
114
114
115
-
116
- (defun lsp-ivy--format-symbol-match (symbol-information-match )
115
+ (eval-when-compile
116
+ (lsp-interface
117
+ (lsp-ivy:FormattedSymbolInformation
118
+ (:kind :name :location :textualRepresentation )
119
+ (:containerName :deprecated ))))
120
+
121
+ (lsp-defun lsp-ivy--workspace-symbol-action
122
+ ((&SymbolInformation
123
+ :location (&Location :uri :range (&Range :start (&Position :line :character )))))
124
+ " Jump to selected candidate."
125
+ (find-file (lsp--uri-to-path uri))
126
+ (goto-char (point-min ))
127
+ (forward-line line)
128
+ (forward-char character))
129
+
130
+ (defun lsp-ivy--format-symbol-match (symbol-information )
117
131
" Convert the match returned by `lsp-mode` into a candidate string.
118
- SYMBOL-INFORMATION-MATCH is a cons cell whose cdr is the SymbolInformation interface from `lsp-mode`."
119
- (-let* (((&SymbolInformation :name :kind :container-name? ) ( cdr symbol-information-match) )
132
+ SYMBOL-INFORMATION is a SymbolInformation object from `lsp-mode`."
133
+ (-let* (((&SymbolInformation :name :kind :container-name? ) symbol-information)
120
134
(type (elt lsp-ivy-symbol-kind-to-face kind))
121
135
(typestr (if lsp-ivy-show-symbol-kind
122
136
(propertize (format " [%s ] " (car type)) 'face (cdr type))
@@ -125,49 +139,57 @@ SYMBOL-INFORMATION-MATCH is a cons cell whose cdr is the SymbolInformation inter
125
139
(format " %s " name)
126
140
(format " %s .%s " container-name? name)))))
127
141
128
- (defun lsp-ivy--workspace-symbol-action (symbol-information-candidate )
129
- " Jump to selected SYMBOL-INFORMATION-CANDIDATE, a cons cell whose cdr is a a SymbolInformation."
130
- (-let (((&SymbolInformation :location
131
- (&Location :uri
132
- :range
133
- (&Range :start
134
- (&Position :line :character ))))
135
- (cdr symbol-information-candidate)))
136
- (find-file (lsp--uri-to-path uri))
137
- (goto-char (point-min ))
138
- (forward-line line)
139
- (forward-char character)))
140
-
141
- (lsp-defun lsp-ivy--filter-func ((&SymbolInformation :kind ))
142
- " Filter candidate kind from symbol kinds."
143
- (member kind lsp-ivy-filter-symbol-kind))
142
+ (lsp-defun lsp-ivy--transform-candidate ((symbol-information &as &SymbolInformation :kind )
143
+ filter-regexps?)
144
+ " Map candidate to nil if it should be excluded based on `lsp-ivy-filter-symbol-kind' or
145
+ FILTER-REGEXPS?, otherwise convert it to an `lsp-ivy:FormattedSymbolInformation' object."
146
+ (unless (member kind lsp-ivy-filter-symbol-kind)
147
+ (let ((textual-representation (lsp-ivy--format-symbol-match symbol-information)))
148
+ (when (--all? (string-match-p it textual-representation) filter-regexps?)
149
+ (lsp-put symbol-information :textualRepresentation textual-representation)
150
+ symbol-information))))
144
151
145
152
(defun lsp-ivy--workspace-symbol (workspaces prompt initial-input )
146
153
" Search against WORKSPACES with PROMPT and INITIAL-INPUT."
147
- (ivy-read
148
- prompt
149
- (lambda (user-input )
150
- (with-lsp-workspaces workspaces
151
- (lsp-request-async
152
- " workspace/symbol"
153
- (lsp-make-workspace-symbol-params :query user-input)
154
- (lambda (result )
155
- (ivy-update-candidates
156
- (mapcar
157
- (-lambda ((symbol-information &as &SymbolInformation :name ))
158
- (cons name symbol-information))
159
- (-remove #'lsp-ivy--filter-func result))))
160
- :mode 'detached
161
- :cancel-token :workspace-symbol ))
162
- 0 )
163
- :dynamic-collection t
164
- :require-match t
165
- :initial-input initial-input
166
- :action #'lsp-ivy--workspace-symbol-action
167
- :caller 'lsp-ivy-workspace-symbol ))
154
+ (let* ((prev-query nil )
155
+ (unfiltered-candidates '())
156
+ (filtered-candidates nil )
157
+ (update-candidates
158
+ (lambda (all-candidates filter-regexps? )
159
+ (setq filtered-candidates
160
+ (--keep (lsp-ivy--transform-candidate it filter-regexps?)
161
+ all-candidates))
162
+ (ivy-update-candidates filtered-candidates))))
163
+ (ivy-read
164
+ prompt
165
+ (lambda (user-input )
166
+ (let* ((parts (split-string user-input))
167
+ (query (or (car parts) " " ))
168
+ (filter-regexps? (mapcar #'regexp-quote (cdr parts))))
169
+ (when query
170
+ (if (string-equal prev-query query)
171
+ (funcall update-candidates unfiltered-candidates filter-regexps?)
172
+ (with-lsp-workspaces workspaces
173
+ (lsp-request-async
174
+ " workspace/symbol"
175
+ (lsp-make-workspace-symbol-params :query query)
176
+ (lambda (result )
177
+ (setq unfiltered-candidates result)
178
+ (funcall update-candidates unfiltered-candidates filter-regexps?) )
179
+ :mode 'detached
180
+ :cancel-token :workspace-symbol ))))
181
+ (setq prev-query query))
182
+ (or filtered-candidates 0 ))
183
+ :dynamic-collection t
184
+ :require-match t
185
+ :initial-input initial-input
186
+ :action #'lsp-ivy--workspace-symbol-action
187
+ :caller 'lsp-ivy-workspace-symbol )))
168
188
169
189
(ivy-configure 'lsp-ivy-workspace-symbol
170
- :display-transformer-fn #'lsp-ivy--format-symbol-match )
190
+ :display-transformer-fn
191
+ (-lambda ((&lsp-ivy:FormattedSymbolInformation :textual-representation ))
192
+ textual-representation))
171
193
172
194
;;;### autoload
173
195
(defun lsp-ivy-workspace-symbol (arg )
0 commit comments