8
8
9
9
; ; SPDX-License-Identifier: GPL-3.0-or-later
10
10
11
+ (require 'seq )
11
12
(require 'racket-complete )
12
13
(require 'racket-describe )
13
14
(require 'racket-company-doc )
14
15
15
- (defvar-local racket--xp-binding-completions nil
16
- " Completion candidates that are bindings.
17
- Set by `racket-xp-mode' . Used by `racket-xp-complete-at-point' ." )
16
+ (defvar-local racket--xp-completion-table-all nil
17
+ " A completion table of all bindings; for use by a CAPF.
18
+
19
+ Includes both imports and lexical bindings. Better for use by
20
+ `completion-at-point' in an edit buffer, because in general more
21
+ completion candidates offer more opportunities to minimize
22
+ typing.
23
+
24
+ The table includes category and affixation-function metadata; the
25
+ latter shows the module from which an identifier was imported,
26
+ when not a lexical binding." )
27
+
28
+ (defvar-local racket--xp-completion-table-imports nil
29
+ " A completion table of import bindings; for use in minibuffer.
30
+
31
+ Includes only imports, not lexical bindings. Definitely better
32
+ for use by commands that look up documentation. Sometimes better
33
+ for use by `completing-read' in the minibuffer, because that
34
+ returns strings stripped of all text properties -- unless a
35
+ command is able to find a suitable matching string in the buffer
36
+ and use its text properties.
37
+
38
+ The table includes category and affixation-funciton metadata." )
39
+
40
+ (defun racket--set-xp-binding-completions (mods+syms )
41
+ ; ; The back end gives us data optimized for space when serializing:
42
+ ; ;
43
+ ; ; ((modA symA0 symA1 ...)
44
+ ; ; (modB symB0 symB1 ...) ...)
45
+ ; ;
46
+ ; ; Reshape that to a list of strings, each propertized with is mod,
47
+ ; ; for use as completion table.
48
+ (let ((all nil )
49
+ (imports nil )
50
+ (metadata `((category . , racket--identifier-category )
51
+ (affixation-function . ,#'racket--xp-binding-completion-affixator ))))
52
+ (dolist (mod+syms mods+syms)
53
+ (pcase-let ((`(, mod . , syms ) mod+syms))
54
+ (dolist (sym syms)
55
+ (push (propertize sym 'racket-module mod) all)
56
+ (when mod
57
+ (push (propertize sym 'racket-module mod) imports)))))
58
+ (setq racket--xp-completion-table-all
59
+ (racket--completion-table all metadata))
60
+ (setq racket--xp-completion-table-imports
61
+ (racket--completion-table imports metadata))))
62
+
63
+ (defun racket--xp-binding-completion-affixator (strs )
64
+ " Value for :affixation-function."
65
+ (let ((max-len (seq-reduce (lambda (max-len str )
66
+ (max max-len (1+ (length str))))
67
+ strs
68
+ 15 )))
69
+ (seq-map (lambda (str )
70
+ (let* ((leading-space (make-string (- max-len (length str)) 32 ))
71
+ (mod (get-text-property 0 'racket-module str))
72
+ (suffix (or mod " " ))
73
+ (suffix (propertize suffix 'face 'completions-annotations ))
74
+ (suffix (concat leading-space suffix)))
75
+ (list str " " suffix)))
76
+ strs)))
18
77
19
78
(defvar-local racket--xp-module-completions nil
20
- " Completion candidates that are available collection module paths.
21
- Set by `racket-xp-mode' . Used by `racket-xp-complete-at-point' ." )
79
+ " A completion table for available collection module paths.
80
+ Do not `setq' directly; instead call `racket--xp-set-module-completions' ." )
81
+
82
+ (defun racket--set-xp-module-completions (completions )
83
+ (setq-local racket--xp-module-completions
84
+ (racket--completion-table completions
85
+ `((category . , racket--module-category )))))
22
86
23
87
(defun racket-xp-complete-at-point ()
24
88
" A value for the variable `completion-at-point-functions' .
@@ -51,10 +115,11 @@ Set by `racket-xp-mode'. Used by `racket-xp-complete-at-point'.")
51
115
(defun racket--xp-capf-bindings (beg end )
52
116
(list beg
53
117
end
54
- (racket--completion-table racket--xp-binding-completions)
55
- :exclusive 'no
56
- :company-location (racket--xp-make-company-location-proc)
57
- :company-doc-buffer (racket--xp-make-company-doc-buffer-proc)))
118
+ racket--xp-completion-table-all
119
+ :affixation-function #'racket--xp-binding-completion-affixator
120
+ :exclusive 'no
121
+ :company-location (racket--xp-make-company-location-proc)
122
+ :company-doc-buffer (racket--xp-make-company-doc-buffer-proc)))
58
123
59
124
(defun racket--xp-capf-require-transformers (beg end )
60
125
" Note: Currently this returns too many candidates -- all
@@ -70,23 +135,15 @@ that are require transformers."
70
135
(defun racket--xp-capf-absolute-module-paths (beg end )
71
136
(list beg
72
137
end
73
- ( racket--completion-table racket-- xp-module-completions)
138
+ racket--xp-module-completions
74
139
:exclusive 'no ))
75
140
76
141
(defun racket--xp-capf-relative-module-paths ()
77
- (pcase (thing-at-point 'filename t )
78
- ((and (pred stringp) str)
79
- (pcase-let ((`(, beg . , end ) (bounds-of-thing-at-point 'filename )))
80
- (pcase (completion-file-name-table str #'file-exists-p t )
81
- ((and (pred listp ) table)
82
- (let* ((dir (file-name-directory str))
83
- (table (mapcar (lambda (v ) (concat dir v)) ; #466
84
- table)))
85
- (list beg
86
- end
87
- (racket--completion-table table
88
- '((category . file)))
89
- :exclusive 'no ))))))))
142
+ (when-let (bounds (bounds-of-thing-at-point 'filename ))
143
+ (list (car bounds)
144
+ (cdr bounds)
145
+ #'completion-file-name-table
146
+ :exclusive 'no )))
90
147
91
148
(defun racket--xp-make-company-location-proc ()
92
149
(when (racket--cmd-open-p)
0 commit comments