branch: externals/cape
commit 01cee20ded0f5790186f3e88b0414491de8640de
Author: Daniel Mendler <m...@daniel-mendler.de>
Commit: Daniel Mendler <m...@daniel-mendler.de>

    Add cape-wrap-super and cape-capf-super for consistency
---
 CHANGELOG.org |   2 +
 README.org    |  23 ++++-----
 cape.el       | 150 ++++++++++++++++++++++++++++++----------------------------
 3 files changed, 91 insertions(+), 84 deletions(-)

diff --git a/CHANGELOG.org b/CHANGELOG.org
index 8eb108dab6..fae614508a 100644
--- a/CHANGELOG.org
+++ b/CHANGELOG.org
@@ -5,6 +5,8 @@
 * Development
 
 - Add =cape-wrap-debug= and =cape-capf-debug= to add debug messages to a Capf.
+- Add =cape-wrap-super= and =cape-capf-super= for better consistency with the 
other
+  Capf combinators.
 
 * Version 0.17 (2023-08-14)
 
diff --git a/README.org b/README.org
index 5a0b2836d4..a8d0695f93 100644
--- a/README.org
+++ b/README.org
@@ -65,7 +65,7 @@ Furthermore the =cape-*= functions are Capfs which you can 
add to the
 since each of the Capfs adds a small runtime cost. Note that the Capfs which
 occur earlier in the list take precedence, such that the first Capf returning a
 result will win and the later Capfs may not get a chance to run. In order to
-merge Capfs you can try the experimental function =cape-super-capf=.
+merge Capfs you can try the experimental function =cape-capf-super=.
 
 One must distinguish the buffer-local and the global value of the
 =completion-at-point-functions= variable. The buffer-local value of the list 
takes
@@ -175,7 +175,7 @@ It is possible to merge multiple Company backends and use 
them as a single Capf
 using the ~company--multi-backend-adapter~ function from Company. The adapter
 transforms multiple Company backends into a single Company backend, which can
 then be used as a Capf via ~cape-company-to-capf~. Capfs can be merged directly
-with ~cape-super-capf~.
+with ~cape-capf-super~.
 
 #+begin_src emacs-lisp
 (require 'company)
@@ -191,34 +191,34 @@ with ~cape-super-capf~.
 
 /Throw multiple Capfs under the Cape and get a Super-Capf!/
 
-Cape supports merging multiple Capfs using the function ~cape-super-capf~. This
+Cape supports merging multiple Capfs using the function ~cape-capf-super~. This
 feature is *EXPERIMENTAL* and should only be used carefully in special 
scenarios.
 Due to some technical details, only a subset of Capfs can be merged. Merge 
Capfs
 one by one and make sure that you get the desired outcome on each step.
 
-Note that ~cape-super-capf~ is not needed if you want to use multiple Capfs 
which
+Note that ~cape-capf-super~ is not needed if you want to use multiple Capfs 
which
 are tried one after the other, for example you can use ~cape-file~ together 
with
 programming mode Capfs by adding ~cape-file~ to the 
~completion-at-point-functions~
 list. File completion will then be available in comments and string literals,
-but not in normal code. ~cape-super-capf~ is only necessary if you want to 
combine
+but not in normal code. ~cape-capf-super~ is only necessary if you want to 
combine
 multiple Capfs, such that the candidates from multiple sources appear 
/together/
 in the completion list at the same time.
 
 Capf merging works only for completion functions which are sufficiently
 well-behaved and completion functions which do not define completion 
boundaries.
-~cape-super-capf~ has the same restrictions as ~completion-table-merge~ and
-~completion-table-in-turn~. As a simple rule of thumb, ~cape-super-capf~ works 
only
+~cape-capf-super~ has the same restrictions as ~completion-table-merge~ and
+~completion-table-in-turn~. As a simple rule of thumb, ~cape-capf-super~ works 
only
 for static completion functions like ~cape-dabbrev~, ~cape-keyword~, 
~cape-dict~,
 etc., but not for multi-step completions like ~cape-file~.
 
 #+begin_src emacs-lisp
 ;; Merge the dabbrev, dict and keyword capfs, display candidates together.
 (setq-local completion-at-point-functions
-            (list (cape-super-capf #'cape-dabbrev #'cape-dict #'cape-keyword)))
+            (list (cape-capf-super #'cape-dabbrev #'cape-dict #'cape-keyword)))
 
 ;; Alternative: Define named Capf instead of using the anonymous Capf directly
-(defalias 'cape-dabbrev-dict-keyword
-  (cape-super-capf #'cape-dabbrev #'cape-dict #'cape-keyword))
+(defun cape-dabbrev-dict-keyword ()
+  (cape-wrap-super #'cape-dabbrev #'cape-dict #'cape-keyword))
 (setq-local completion-at-point-functions (list #'cape-dabbrev-dict-keyword))
 #+end_src
 
@@ -230,7 +230,7 @@ allows you to merge multiple Company backends.
 /The Capf-Buster ensures that you always get a fresh set of candidates!/
 
 If a Capf caches the candidates for too long we can use a cache busting
-Capf-transformer. For example the Capf merging function ~cape-super-capf~ 
creates
+Capf-transformer. For example the Capf merging function ~cape-capf-super~ 
creates
 a Capf, which caches the candidates for the whole lifetime of the Capf.
 Therefore you may want to combine a merged Capf with a cache buster under some
 circumstances. It is noteworthy that the ~company-capf~ backend from Company
@@ -261,6 +261,7 @@ the Capf transformers with =defalias= to a function symbol.
 - ~cape-wrap-properties~, ~cape-capf-properties~: Add completion properties to 
a Capf.
 - ~cape-wrap-predicate~, ~cape-capf-predicate~: Add candidate predicate to a 
Capf.
 - ~cape-wrap-prefix-length~, ~cape-capf-prefix-length~: Enforce a minimal 
prefix length.
+- ~cape-wrap-super~, ~cape-capf-super~: Merge multiple Capfs into a Super-Capf.
 - ~cape-wrap-inside-comment~, ~cape-capf-inside-comment~: Ensure that Capf 
triggers only inside comment.
 - ~cape-wrap-inside-string~, ~cape-capf-inside-string~: Ensure that Capf 
triggers only inside a string literal.
 
diff --git a/cape.el b/cape.el
index 94fd91ec55..0d706f5644 100644
--- a/cape.el
+++ b/cape.el
@@ -717,79 +717,6 @@ If INTERACTIVE is nil the function acts like a Capf."
 
 ;;;; Capf combinators
 
-;;;###autoload
-(defun cape-super-capf (&rest capfs)
-  "Merge CAPFS and return new Capf which includes all candidates.
-The function `cape-super-capf' is experimental."
-  (lambda ()
-    (when-let (results (delq nil (mapcar #'funcall capfs)))
-      (pcase-let* ((`((,beg ,end . ,_)) results)
-                   (cand-ht (make-hash-table :test #'equal))
-                   (tables nil)
-                   (prefix-len nil))
-        (cl-loop for (beg2 end2 . rest) in results do
-                 (when (and (= beg beg2) (= end end2))
-                   (push rest tables)
-                   (let ((plen (plist-get (cdr rest) :company-prefix-length)))
-                     (cond
-                      ((eq plen t)
-                       (setq prefix-len t))
-                      ((and (not prefix-len) (integerp plen))
-                       (setq prefix-len plen))
-                      ((and (integerp prefix-len) (integerp plen))
-                       (setq prefix-len (max prefix-len plen)))))))
-        (setq tables (nreverse tables))
-        `(,beg ,end
-          ,(lambda (str pred action)
-             (pcase action
-               (`(boundaries . ,_) nil)
-               ('metadata
-                '(metadata (category . cape-super)
-                           (display-sort-function . identity)
-                           (cycle-sort-function . identity)))
-               ('t ;; all-completions
-                (let ((ht (make-hash-table :test #'equal))
-                      (candidates nil))
-                  (cl-loop for (table . plist) in tables do
-                           (let* ((pr (if-let (pr (plist-get plist :predicate))
-                                          (if pred
-                                              (lambda (x) (and (funcall pr x) 
(funcall pred x)))
-                                            pr)
-                                        pred))
-                                  (md (completion-metadata "" table pr))
-                                  (sort (or (completion-metadata-get md 
'display-sort-function)
-                                            #'identity))
-                                  (cands (funcall sort (all-completions str 
table pr))))
-                             (cl-loop for cell on cands
-                                      for cand = (car cell) do
-                                      (if (eq (gethash cand ht t) t)
-                                          (puthash cand plist ht)
-                                        (setcar cell nil)))
-                             (setq candidates (nconc candidates cands))))
-                  (setq cand-ht ht)
-                  (delq nil candidates)))
-               (_ ;; try-completion and test-completion
-                (completion--some
-                 (pcase-lambda (`(,table . ,plist))
-                   (complete-with-action
-                    action table str
-                    (if-let (pr (plist-get plist :predicate))
-                        (if pred
-                            (lambda (x) (and (funcall pr x) (funcall pred x)))
-                          pr)
-                      pred)))
-                 tables))))
-          :exclusive no
-          :company-prefix-length ,prefix-len
-          ,@(mapcan
-             (lambda (prop)
-               (list prop (lambda (cand &rest args)
-                            (when-let (fun (plist-get (gethash cand cand-ht) 
prop))
-                              (apply fun cand args)))))
-             '(:company-docsig :company-location :company-kind
-               :company-doc-buffer :company-deprecated
-               :annotation-function :exit-function)))))))
-
 (defun cape--company-call (&rest app)
   "Apply APP and handle future return values."
   ;; Backends are non-interruptible. Disable interrupts!
@@ -906,6 +833,81 @@ changed.  The function `cape-company-to-capf' is 
experimental."
     (interactive (list t))
     (if interactive (cape-interactive capf) (funcall capf))))
 
+;;;###autoload
+(defalias 'cape-super-capf #'cape-capf-super)
+
+;;;###autoload
+(defun cape-wrap-super (&rest capfs)
+  "Call CAPFS and return merged completion result.
+The functions `cape-wrap-super' and `cape-capf-super' are experimental."
+  (when-let ((results (delq nil (mapcar #'funcall capfs))))
+    (pcase-let* ((`((,beg ,end . ,_)) results)
+                 (cand-ht (make-hash-table :test #'equal))
+                 (tables nil)
+                 (prefix-len nil))
+      (cl-loop for (beg2 end2 . rest) in results do
+               (when (and (= beg beg2) (= end end2))
+                 (push rest tables)
+                 (let ((plen (plist-get (cdr rest) :company-prefix-length)))
+                   (cond
+                    ((eq plen t)
+                     (setq prefix-len t))
+                    ((and (not prefix-len) (integerp plen))
+                     (setq prefix-len plen))
+                    ((and (integerp prefix-len) (integerp plen))
+                     (setq prefix-len (max prefix-len plen)))))))
+      (setq tables (nreverse tables))
+      `(,beg ,end
+        ,(lambda (str pred action)
+           (pcase action
+             (`(boundaries . ,_) nil)
+             ('metadata
+              '(metadata (category . cape-super)
+                         (display-sort-function . identity)
+                         (cycle-sort-function . identity)))
+             ('t ;; all-completions
+              (let ((ht (make-hash-table :test #'equal))
+                    (candidates nil))
+                (cl-loop for (table . plist) in tables do
+                         (let* ((pr (if-let (pr (plist-get plist :predicate))
+                                        (if pred
+                                            (lambda (x) (and (funcall pr x) 
(funcall pred x)))
+                                          pr)
+                                      pred))
+                                (md (completion-metadata "" table pr))
+                                (sort (or (completion-metadata-get md 
'display-sort-function)
+                                          #'identity))
+                                (cands (funcall sort (all-completions str 
table pr))))
+                           (cl-loop for cell on cands
+                                    for cand = (car cell) do
+                                    (if (eq (gethash cand ht t) t)
+                                        (puthash cand plist ht)
+                                      (setcar cell nil)))
+                           (push cands candidates)))
+                (setq cand-ht ht)
+                (delq nil (apply #'nconc (nreverse candidates)))))
+             (_ ;; try-completion and test-completion
+              (completion--some
+               (pcase-lambda (`(,table . ,plist))
+                 (complete-with-action
+                  action table str
+                  (if-let (pr (plist-get plist :predicate))
+                      (if pred
+                          (lambda (x) (and (funcall pr x) (funcall pred x)))
+                        pr)
+                    pred)))
+               tables))))
+        :exclusive no
+        :company-prefix-length ,prefix-len
+        ,@(mapcan
+           (lambda (prop)
+             (list prop (lambda (cand &rest args)
+                          (when-let (fun (plist-get (gethash cand cand-ht) 
prop))
+                            (apply fun cand args)))))
+           '(:company-docsig :company-location :company-kind
+             :company-doc-buffer :company-deprecated
+             :annotation-function :exit-function))))))
+
 ;;;###autoload
 (defun cape-wrap-debug (capf &optional name)
   "Call CAPF and return a completion table which prints trace messages.
@@ -1116,6 +1118,8 @@ This function can be used as an advice around an existing 
Capf."
 (cape--capf-wrapper inside-comment)
 ;;;###autoload (autoload 'cape-capf-inside-string "cape")
 (cape--capf-wrapper inside-string)
+;;;###autoload (autoload 'cape-capf-super "cape")
+(cape--capf-wrapper super)
 ;;;###autoload (autoload 'cape-capf-noninterruptible "cape")
 (cape--capf-wrapper noninterruptible)
 ;;;###autoload (autoload 'cape-capf-nonexclusive "cape")

Reply via email to