Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
marvel
GitHub Repository: marvel/qnf
Path: blob/master/elisp/slime/contrib/slime-c-p-c.el
990 views
1
(defvar slime-c-p-c-init-undo-stack nil)
2
3
(define-slime-contrib slime-c-p-c
4
"ILISP style Compound Prefix Completion."
5
(:authors "Luke Gorrie <[email protected]>"
6
"Edi Weitz <[email protected]>"
7
"Matthias Koeppe <[email protected]>"
8
"Tobias C. Rittweiler <[email protected]>")
9
(:license "GPL")
10
(:slime-dependencies slime-parse slime-editing-commands slime-autodoc)
11
(:swank-dependencies swank-c-p-c)
12
(:on-load
13
(push
14
`(progn
15
(setq slime-complete-symbol-function ',slime-complete-symbol-function)
16
(remove-hook 'slime-connected-hook 'slime-c-p-c-on-connect)
17
,@(when (featurep 'slime-repl)
18
`((define-key slime-mode-map "\C-c\C-s"
19
',(lookup-key slime-mode-map "\C-c\C-s"))
20
(define-key slime-repl-mode-map "\C-c\C-s"
21
',(lookup-key slime-repl-mode-map "\C-c\C-s")))))
22
slime-c-p-c-init-undo-stack)
23
(setq slime-complete-symbol-function 'slime-complete-symbol*)
24
(define-key slime-mode-map "\C-c\C-s" 'slime-complete-form)
25
(when (featurep 'slime-repl)
26
(define-key slime-repl-mode-map "\C-c\C-s" 'slime-complete-form)))
27
(:on-unload
28
(while slime-c-p-c-init-undo-stack
29
(eval (pop slime-c-p-c-init-undo-stack)))))
30
31
(defcustom slime-c-p-c-unambiguous-prefix-p t
32
"If true, set point after the unambigous prefix.
33
If false, move point to the end of the inserted text."
34
:type 'boolean
35
:group 'slime-ui)
36
37
(defcustom slime-complete-symbol*-fancy nil
38
"Use information from argument lists for DWIM'ish symbol completion."
39
:group 'slime-mode
40
:type 'boolean)
41
42
(defun slime-complete-symbol* ()
43
"Expand abbreviations and complete the symbol at point."
44
;; NB: It is only the name part of the symbol that we actually want
45
;; to complete -- the package prefix, if given, is just context.
46
(or (slime-maybe-complete-as-filename)
47
(slime-expand-abbreviations-and-complete)))
48
49
;; FIXME: factorize
50
(defun slime-expand-abbreviations-and-complete ()
51
(let* ((end (move-marker (make-marker) (slime-symbol-end-pos)))
52
(beg (move-marker (make-marker) (slime-symbol-start-pos)))
53
(prefix (buffer-substring-no-properties beg end))
54
(completion-result (slime-contextual-completions beg end))
55
(completion-set (first completion-result))
56
(completed-prefix (second completion-result)))
57
(if (null completion-set)
58
(progn (slime-minibuffer-respecting-message
59
"Can't find completion for \"%s\"" prefix)
60
(ding)
61
(slime-complete-restore-window-configuration))
62
;; some XEmacs issue makes this distinction necessary
63
(cond ((> (length completed-prefix) (- end beg))
64
(goto-char end)
65
(insert-and-inherit completed-prefix)
66
(delete-region beg end)
67
(goto-char (+ beg (length completed-prefix))))
68
(t nil))
69
(cond ((and (member completed-prefix completion-set)
70
(slime-length= completion-set 1))
71
(slime-minibuffer-respecting-message "Sole completion")
72
(when slime-complete-symbol*-fancy
73
(slime-complete-symbol*-fancy-bit))
74
(slime-complete-restore-window-configuration))
75
;; Incomplete
76
(t
77
(when (member completed-prefix completion-set)
78
(slime-minibuffer-respecting-message
79
"Complete but not unique"))
80
(when slime-c-p-c-unambiguous-prefix-p
81
(let ((unambiguous-completion-length
82
(loop for c in completion-set
83
minimizing (or (mismatch completed-prefix c)
84
(length completed-prefix)))))
85
(goto-char (+ beg unambiguous-completion-length))))
86
(slime-display-or-scroll-completions completion-set
87
completed-prefix))))))
88
89
(defun slime-complete-symbol*-fancy-bit ()
90
"Do fancy tricks after completing a symbol.
91
\(Insert a space or close-paren based on arglist information.)"
92
(let ((arglist (slime-retrieve-arglist (slime-symbol-at-point))))
93
(unless (eq arglist :not-available)
94
(let ((args
95
;; Don't intern these symbols
96
(let ((obarray (make-vector 10 0)))
97
(cdr (read arglist))))
98
(function-call-position-p
99
(save-excursion
100
(backward-sexp)
101
(equal (char-before) ?\())))
102
(when function-call-position-p
103
(if (null args)
104
(insert-and-inherit ")")
105
(insert-and-inherit " ")
106
(when (and (slime-background-activities-enabled-p)
107
(not (minibuffer-window-active-p (minibuffer-window))))
108
(slime-echo-arglist))))))))
109
110
(defun* slime-contextual-completions (beg end)
111
"Return a list of completions of the token from BEG to END in the
112
current buffer."
113
(let ((token (buffer-substring-no-properties beg end)))
114
(cond
115
((and (< beg (point-max))
116
(string= (buffer-substring-no-properties beg (1+ beg)) ":"))
117
;; Contextual keyword completion
118
(let ((completions
119
(slime-completions-for-keyword token
120
(save-excursion
121
(goto-char beg)
122
(slime-parse-form-upto-point)))))
123
(when (first completions)
124
(return-from slime-contextual-completions completions))
125
;; If no matching keyword was found, do regular symbol
126
;; completion.
127
))
128
((and (>= (length token) 2)
129
(string= (subseq token 0 2) "#\\"))
130
;; Character name completion
131
(return-from slime-contextual-completions
132
(slime-completions-for-character token))))
133
;; Regular symbol completion
134
(slime-completions token)))
135
136
(defun slime-completions (prefix)
137
(slime-eval `(swank:completions ,prefix ',(slime-current-package))))
138
139
(defun slime-completions-for-keyword (prefix buffer-form)
140
(slime-eval `(swank:completions-for-keyword ,prefix ',buffer-form)))
141
142
(defun slime-completions-for-character (prefix)
143
(flet ((append-char-syntax (string) (concat "#\\" string)))
144
(let ((result (slime-eval `(swank:completions-for-character
145
,(subseq prefix 2)))))
146
(when (car result)
147
(list (mapcar 'append-char-syntax (car result))
148
(append-char-syntax (cadr result)))))))
149
150
151
;;; Complete form
152
153
(defun slime-complete-form ()
154
"Complete the form at point.
155
This is a superset of the functionality of `slime-insert-arglist'."
156
(interactive)
157
;; Find the (possibly incomplete) form around point.
158
(let ((buffer-form (slime-parse-form-upto-point)))
159
(let ((result (slime-eval `(swank:complete-form ',buffer-form))))
160
(if (eq result :not-available)
161
(error "Could not generate completion for the form `%s'" buffer-form)
162
(progn
163
(just-one-space (if (looking-back "\\s(") 0 1))
164
(save-excursion
165
(insert result)
166
(let ((slime-close-parens-limit 1))
167
(slime-close-all-parens-in-sexp)))
168
(save-excursion
169
(backward-up-list 1)
170
(indent-sexp)))))))
171
172
;;; Tests
173
174
(def-slime-test complete-symbol*
175
(prefix expected-completions)
176
"Find the completions of a symbol-name prefix."
177
'(("cl:compile" (("cl:compile" "cl:compile-file" "cl:compile-file-pathname"
178
"cl:compiled-function" "cl:compiled-function-p"
179
"cl:compiler-macro" "cl:compiler-macro-function")
180
"cl:compile"))
181
("cl:foobar" nil)
182
("swank::compile-file" (("swank::compile-file"
183
"swank::compile-file-for-emacs"
184
"swank::compile-file-if-needed"
185
"swank::compile-file-output"
186
"swank::compile-file-pathname")
187
"swank::compile-file"))
188
("cl:m-v-l" (("cl:multiple-value-list" "cl:multiple-values-limit") "cl:multiple-value"))
189
("common-lisp" (("common-lisp-user:" "common-lisp:") "common-lisp")))
190
(let ((completions (slime-completions prefix)))
191
(slime-test-expect "Completion set" expected-completions completions)))
192
193
(def-slime-test complete-form
194
(buffer-sexpr wished-completion &optional skip-trailing-test-p)
195
""
196
'(("(defmethod arglist-dispatch *HERE*"
197
"(defmethod arglist-dispatch (operator arguments) body...)")
198
("(with-struct *HERE*"
199
"(with-struct (conc-name names...) obj body...)")
200
("(with-struct *HERE*"
201
"(with-struct (conc-name names...) obj body...)")
202
("(with-struct (*HERE*"
203
"(with-struct (conc-name names...)" t)
204
("(with-struct (foo. bar baz *HERE*"
205
"(with-struct (foo. bar baz names...)" t))
206
(slime-check-top-level)
207
(with-temp-buffer
208
(lisp-mode)
209
(setq slime-buffer-package "SWANK")
210
(insert buffer-sexpr)
211
(search-backward "*HERE*")
212
(delete-region (match-beginning 0) (match-end 0))
213
(slime-complete-form)
214
(slime-check-completed-form buffer-sexpr wished-completion)
215
216
;; Now the same but with trailing `)' for paredit users...
217
(unless skip-trailing-test-p
218
(erase-buffer)
219
(insert buffer-sexpr)
220
(search-backward "*HERE*")
221
(delete-region (match-beginning 0) (match-end 0))
222
(insert ")") (backward-char)
223
(slime-complete-form)
224
(slime-check-completed-form (concat buffer-sexpr ")") wished-completion))
225
))
226
227
(defun slime-check-completed-form (buffer-sexpr wished-completion)
228
(slime-test-expect (format "Completed form for `%s' is as expected"
229
buffer-sexpr)
230
wished-completion
231
(buffer-string)
232
'equal))
233
234
(provide 'slime-c-p-c)
235
236
237