Skip to content

Commit 1f6d877

Browse files
Merge pull request #16 from sebastiansturm/master
Partially address issue #14
2 parents f6e3211 + 32f8f26 commit 1f6d877

File tree

1 file changed

+82
-49
lines changed

1 file changed

+82
-49
lines changed

lsp-ivy.el

Lines changed: 82 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@
4747
:group 'lsp-ivy
4848
:type 'boolean)
4949

50+
(defcustom lsp-ivy-show-symbol-filename
51+
t
52+
"Whether to show the project-relative path to a symbol's point of definition."
53+
:group 'lsp-ivy
54+
:type 'boolean)
55+
5056
(defcustom lsp-ivy-filter-symbol-kind
5157
nil
5258
"A list of LSP SymbolKind's to filter out."
@@ -112,62 +118,89 @@
112118
(cons string face)
113119
(cons string face)))
114120

115-
116-
(defun lsp-ivy--format-symbol-match (symbol-information-match)
117-
"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))
120-
(type (elt lsp-ivy-symbol-kind-to-face kind))
121-
(typestr (if lsp-ivy-show-symbol-kind
122-
(propertize (format "[%s] " (car type)) 'face (cdr type))
123-
"")))
121+
(eval-when-compile
122+
(lsp-interface
123+
(lsp-ivy:FormattedSymbolInformation
124+
(:kind :name :location :textualRepresentation)
125+
(:containerName :deprecated))))
126+
127+
(lsp-defun lsp-ivy--workspace-symbol-action
128+
((&SymbolInformation
129+
:location (&Location :uri :range (&Range :start (&Position :line :character)))))
130+
"Jump to selected candidate."
131+
(find-file (lsp--uri-to-path uri))
132+
(goto-char (point-min))
133+
(forward-line line)
134+
(forward-char character))
135+
136+
(lsp-defun lsp-ivy--format-symbol-match
137+
((&SymbolInformation :name :kind :container-name? :location (&Location :uri))
138+
project-root)
139+
"Convert the match returned by `lsp-mode` into a candidate string."
140+
(let* ((type (elt lsp-ivy-symbol-kind-to-face kind))
141+
(typestr (if lsp-ivy-show-symbol-kind
142+
(propertize (format "[%s] " (car type)) 'face (cdr type))
143+
""))
144+
(pathstr (if lsp-ivy-show-symbol-filename
145+
(propertize (format " · %s" (file-relative-name (lsp--uri-to-path uri) project-root))
146+
'face font-lock-comment-face) "")))
124147
(concat typestr (if (or (null container-name?) (string-empty-p container-name?))
125148
(format "%s" name)
126-
(format "%s.%s" container-name? name)))))
127-
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))
149+
(format "%s.%s" container-name? name)) pathstr)))
150+
151+
(lsp-defun lsp-ivy--transform-candidate ((symbol-information &as &SymbolInformation :kind)
152+
filter-regexps? workspace-root)
153+
"Map candidate to nil if it should be excluded based on `lsp-ivy-filter-symbol-kind' or
154+
FILTER-REGEXPS?, otherwise convert it to an `lsp-ivy:FormattedSymbolInformation' object."
155+
(unless (member kind lsp-ivy-filter-symbol-kind)
156+
(let ((textual-representation
157+
(lsp-ivy--format-symbol-match symbol-information workspace-root)))
158+
(when (--all? (string-match-p it textual-representation) filter-regexps?)
159+
(lsp-put symbol-information :textualRepresentation textual-representation)
160+
symbol-information))))
144161

145162
(defun lsp-ivy--workspace-symbol (workspaces prompt initial-input)
146163
"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))
164+
(let* ((prev-query nil)
165+
(unfiltered-candidates '())
166+
(filtered-candidates nil)
167+
(workspace-root (lsp-workspace-root))
168+
(update-candidates
169+
(lambda (all-candidates filter-regexps?)
170+
(setq filtered-candidates
171+
(--keep (lsp-ivy--transform-candidate it filter-regexps? workspace-root)
172+
all-candidates))
173+
(ivy-update-candidates filtered-candidates))))
174+
(ivy-read
175+
prompt
176+
(lambda (user-input)
177+
(let* ((parts (split-string user-input))
178+
(query (or (car parts) ""))
179+
(filter-regexps? (mapcar #'regexp-quote (cdr parts))))
180+
(when query
181+
(if (string-equal prev-query query)
182+
(funcall update-candidates unfiltered-candidates filter-regexps?)
183+
(with-lsp-workspaces workspaces
184+
(lsp-request-async
185+
"workspace/symbol"
186+
(lsp-make-workspace-symbol-params :query query)
187+
(lambda (result)
188+
(setq unfiltered-candidates result)
189+
(funcall update-candidates unfiltered-candidates filter-regexps?))
190+
:mode 'detached
191+
:cancel-token :workspace-symbol))))
192+
(setq prev-query query))
193+
(or filtered-candidates 0))
194+
:dynamic-collection t
195+
:require-match t
196+
:initial-input initial-input
197+
:action #'lsp-ivy--workspace-symbol-action
198+
:caller 'lsp-ivy-workspace-symbol)))
168199

169200
(ivy-configure 'lsp-ivy-workspace-symbol
170-
:display-transformer-fn #'lsp-ivy--format-symbol-match)
201+
:display-transformer-fn
202+
(-lambda ((&lsp-ivy:FormattedSymbolInformation :textual-representation))
203+
textual-representation))
171204

172205
;;;###autoload
173206
(defun lsp-ivy-workspace-symbol (arg)

0 commit comments

Comments
 (0)