branch: externals/cape
commit d5a17477033b2cd624b26daa74ac312579c23865
Author: Daniel Mendler <[email protected]>
Commit: Daniel Mendler <[email protected]>
Add cape-capf-trigger
---
CHANGELOG.org | 3 +++
README.org | 23 ++++++++++++++++-------
cape.el | 30 +++++++++++++++++++++++++++++-
3 files changed, 48 insertions(+), 8 deletions(-)
diff --git a/CHANGELOG.org b/CHANGELOG.org
index 830e3d83a3..bae707d283 100644
--- a/CHANGELOG.org
+++ b/CHANGELOG.org
@@ -7,6 +7,9 @@
- Mark ~cape-capf-purify~ and ~cape-wrap-purify~ as obsolete.
- ~cape-capf-sort~: Make ~SORT~ function argument optional. If the ~SORT~
argument is
nil or not given, the completion UI sorting will take over.
+- ~cape-capf-trigger~, ~cape-wrap-trigger~: New Capf transformer for trigger
+ characters. The Capf will only complete if the trigger character occurs
before
+ point.
* Version 2.2 (2025-10-13)
diff --git a/README.org b/README.org
index 3652e3041c..d02571a72c 100644
--- a/README.org
+++ b/README.org
@@ -259,24 +259,33 @@ the Capf transformers with =defalias= to a function
symbol.
- ~cape-capf-silent~, ~cape-wrap-silent~: Silence Capf messages and errors.
- ~cape-capf-sort~, ~cape-wrap-sort~: Add sort function to a Capf.
- ~cape-capf-super~, ~cape-wrap-super~: Merge multiple Capfs into a Super-Capf.
+- ~cape-capf-trigger~, ~cape-wrap-trigger~: Create a Capf with a trigger
character or string.
In the following we show a few example configurations, which have come up on
the
[[https://github.com/minad/cape/issues][Cape]] or
[[https://github.com/minad/corfu/issues][Corfu issue tracker]] or the
[[https://github.com/minad/corfu/wiki][Corfu wiki.]] I use some of these tweaks
in my
personal configuration.
#+begin_src emacs-lisp
-;; Example 1: Configure a Capf with a specific auto completion prefix length
+;; Example 1: Configure a merged Capf with a trigger prefix
+(setq-local completion-at-point-functions
+ (list (cape-capf-trigger
+ (cape-capf-super #'cape-abbrev
+ #'cape-dabbrev
+ #'tempel-complete)
+ ?/)))
+
+;; Example 2: Configure a Capf with a specific auto completion prefix length
(setq-local completion-at-point-functions
(list (cape-capf-prefix-length #'cape-dabbrev 2)))
-;; Example 2: Create a Capf with debugging messages
+;; Example 3: Create a Capf with debugging messages
(setq-local completion-at-point-functions (list (cape-capf-debug #'cape-dict)))
-;; Example 3: Named Capf
+;; Example 4: Named Capf
(defalias 'cape-dabbrev-min-2 (cape-capf-prefix-length #'cape-dabbrev 2))
(setq-local completion-at-point-functions (list #'cape-dabbrev-min-2))
-;; Example 4: Define a defensive Dabbrev Capf, which accepts all inputs. If
you
+;; Example 5: Define a defensive Dabbrev Capf, which accepts all inputs. If
you
;; use Corfu and `corfu-auto=t', the first candidate won't be auto selected if
;; `corfu-preselect=valid', such that it cannot be accidentally committed when
;; pressing RET.
@@ -284,19 +293,19 @@ personal configuration.
(cape-wrap-accept-all #'cape-dabbrev))
(add-hook 'completion-at-point-functions #'my-cape-dabbrev-accept-all)
-;; Example 5: Define interactive Capf which can be bound to a key. Here we
wrap
+;; Example 6: Define interactive Capf which can be bound to a key. Here we
wrap
;; the `elisp-completion-at-point' such that we can complete Elisp code
;; explicitly in arbitrary buffers.
(keymap-global-set "C-c p e" (cape-capf-interactive
#'elisp-completion-at-point))
-;; Example 6: Ignore :keywords in Elisp completion.
+;; Example 7: Ignore :keywords in Elisp completion.
(defun ignore-elisp-keywords (sym)
(not (keywordp sym)))
(setq-local completion-at-point-functions
(list (cape-capf-predicate #'elisp-completion-at-point
#'ignore-elisp-keywords)))
-;; Example 7: Catch errors with `cape-wrap-silent'.
+;; Example 8: Catch errors with `cape-wrap-silent'.
(advice-add 'dabbrev-capf :around #'cape-wrap-silent)
(advice-add 'pcomplete-completions-at-point :around #'cape-wrap-silent) ;; Was
necessary on Emacs 28
#+end_src
diff --git a/cape.el b/cape.el
index 3c7e502912..49dc0f4433 100644
--- a/cape.el
+++ b/cape.el
@@ -1216,6 +1216,33 @@ This function can be used as an advice around an
existing Capf."
(`(,beg ,end ,table . ,plist)
`(,beg ,end ,(cape--accept-all-table table) . ,plist))))
+;;;###autoload
+(defun cape-wrap-trigger (capf trigger)
+ "Ensure that TRIGGER string or character occurs before point and then call
CAPF.
+Example:
+ (setq completion-at-point-functions
+ (list (cape-capf-trigger \\='cape-abbrev ?/)))"
+ (setq trigger (if (stringp trigger) trigger (char-to-string trigger)))
+ (when-let ((tbeg (save-excursion (search-backward trigger (pos-bol)
'noerror)))
+ (tend (+ tbeg (length trigger)))
+ ((save-excursion (not (re-search-backward "\\s-" tbeg
'noerror)))))
+ (pcase (funcall capf)
+ (`(,beg ,end ,table . ,plist)
+ (when (<= tbeg beg tend)
+ (if (markerp beg)
+ (move-marker beg tend)
+ (setq beg tend))
+ (setq tbeg (copy-marker tbeg)
+ tend (copy-marker tend))
+ `( ,beg ,end ,table
+ :company-prefix-length t
+ :exit-function
+ ,(lambda (str status)
+ (delete-region tbeg tend)
+ (when-let ((exit (plist-get plist :exit-function)))
+ (funcall exit str status)))
+ . ,plist))))))
+
;;;###autoload (autoload 'cape-capf-purify "cape")
;;;###autoload
(defun cape-wrap-purify (capf)
@@ -1242,7 +1269,7 @@ This function can be used as an advice around an existing
Capf."
#'cape-wrap-passthrough #'cape-wrap-predicate
#'cape-wrap-prefix-length #'cape-wrap-properties
'cape-wrap-purify #'cape-wrap-silent
- #'cape-wrap-sort #'cape-wrap-super))
+ #'cape-wrap-sort #'cape-wrap-super #'cape-wrap-trigger))
(let ((name (string-remove-prefix "cape-wrap-" (symbol-name wrapper))))
(defalias (intern (format "cape-capf-%s" name))
(lambda (capf &rest args) (lambda () (apply wrapper capf args)))
@@ -1266,6 +1293,7 @@ See `%s' for documentation." name wrapper wrapper))))
;;;###autoload (autoload 'cape-capf-properties "cape")
;;;###autoload (autoload 'cape-capf-silent "cape")
;;;###autoload (autoload 'cape-capf-super "cape")
+;;;###autoload (autoload 'cape-capf-trigger "cape")
(defvar-keymap cape-prefix-map
:doc "Keymap used as completion entry point.