88
99; ; SPDX-License-Identifier: GPL-3.0-or-later
1010
11+ (require 'seq )
1112(require 'racket-complete )
1213(require 'racket-describe )
1314(require 'racket-company-doc )
1415
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)))
1877
1978(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 )))))
2286
2387(defun racket-xp-complete-at-point ()
2488 " 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'.")
51115(defun racket--xp-capf-bindings (beg end )
52116 (list beg
53117 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)))
58123
59124(defun racket--xp-capf-require-transformers (beg end )
60125 " Note: Currently this returns too many candidates -- all
@@ -70,23 +135,15 @@ that are require transformers."
70135(defun racket--xp-capf-absolute-module-paths (beg end )
71136 (list beg
72137 end
73- ( racket--completion-table racket-- xp-module-completions)
138+ racket--xp-module-completions
74139 :exclusive 'no ))
75140
76141(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 )))
90147
91148(defun racket--xp-make-company-location-proc ()
92149 (when (racket--cmd-open-p)
0 commit comments