diff options
| author | Daniel Mendler <mail@daniel-mendler.de> | 2025-11-07 18:22:30 +0100 |
|---|---|---|
| committer | Daniel Mendler <mail@daniel-mendler.de> | 2025-11-07 18:23:44 +0100 |
| commit | d5a17477033b2cd624b26daa74ac312579c23865 (patch) | |
| tree | 8bb77df280b5014bf041545889796428becbcbf4 | |
| parent | f5c7c76f10155204bad13c2dfa51bc48b7b20e1b (diff) | |
Add cape-capf-trigger
| -rw-r--r-- | CHANGELOG.org | 3 | ||||
| -rw-r--r-- | README.org | 23 | ||||
| -rw-r--r-- | cape.el | 30 |
3 files changed, 48 insertions, 8 deletions
diff --git a/CHANGELOG.org b/CHANGELOG.org index 830e3d8..bae707d 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) @@ -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 @@ -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. |
