From b8a5769b2d4faa02bdd19cd93a6510969486da72 Mon Sep 17 00:00:00 2001 From: Daniel Mendler Date: Thu, 29 Jun 2023 20:22:19 +0200 Subject: Remove cape-dabbrev-min-length, introduce cape-capf-expansion-length --- CHANGELOG.org | 1 + README.org | 1 + cape.el | 65 +++++++++++++++++++++++++++++++++++------------------------ 3 files changed, 41 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.org b/CHANGELOG.org index c911a17..4323fc9 100644 --- a/CHANGELOG.org +++ b/CHANGELOG.org @@ -7,6 +7,7 @@ - =cape-dabbrev=: Respect =dabbrev-abbrev-char-regexp= and =dabbrev-abbrev-skip-leading-regexp=. - =cape-file=: Quote file names in comint/eshell buffers. +- Replace =cape-dabbrev-min-length= with =cape-capf-expansion-length=. * Version 0.15 (2023-04-17) diff --git a/README.org b/README.org index 35a76d7..b14fce1 100644 --- a/README.org +++ b/README.org @@ -235,6 +235,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-expansion-length~, ~cape-capf-expansion-length~: Enforce a minimal length of the expansion. - ~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 8cb83c8..00367b5 100644 --- a/cape.el +++ b/cape.el @@ -90,13 +90,6 @@ See `dabbrev-case-fold-search' for details." (const :tag "use `case-fold-search'" case-fold-search) (other :tag "on" t))) -(defcustom cape-dabbrev-min-length 4 - "Minimum length of dabbrev expansions. -This setting ensures that words which are too short -are not offered as completion candidates, such that -auto completion does not pop up too aggressively." - :type 'natnum) - (defcustom cape-dabbrev-check-other-buffers t "Buffers to check for dabbrev. @@ -136,6 +129,17 @@ The buffers are scanned for completion candidates by `cape-line'." ;;;; Helpers +(defsubst cape--predicate-argument (arg) + "Normalize predicate ARG." + ;; First argument is key, second is value for hash tables. + ;; The first argument can be a cons cell for alists. Then + ;; the candidate itself is either a string or a symbol. We + ;; normalize the calling convention here such that PREDICATE + ;; always receives a string. + (setq arg (car arg) + arg (if (consp arg) (car arg) arg)) + (if (symbolp arg) (symbol-name arg) arg)) + (defun cape--case-fold-p (fold) "Return non-nil if case folding is enabled for FOLD." (if (eq fold 'case-fold-search) case-fold-search fold)) @@ -447,11 +451,10 @@ If INTERACTIVE is nil the function acts like a Capf." (let ((dabbrev-check-other-buffers (not (null cape-dabbrev-check-other-buffers))) (dabbrev-check-all-buffers (eq cape-dabbrev-check-other-buffers t))) (dabbrev--reset-global-variables)) - (cl-loop with min-len = (+ cape-dabbrev-min-length (length input)) - with ic = (cape--case-fold-p dabbrev-case-fold-search) - for w in (dabbrev--find-all-expansions input ic) - if (>= (length w) min-len) collect - (cape--case-replace (and ic dabbrev-case-replace) input w)))) + (cape--case-replace-list + dabbrev-case-fold-search input + (dabbrev--find-all-expansions + input (cape--case-fold-p dabbrev-case-fold-search))))) (defun cape--dabbrev-bounds () "Return bounds of abbreviation." @@ -486,7 +489,7 @@ See the user options `cape-dabbrev-min-length' and `cape-dabbrev-check-other-buffers'." (interactive (list t)) (if interactive - (cape-interactive '((cape-dabbrev-min-length 0)) #'cape-dabbrev) + (cape-interactive #'cape-dabbrev) (when-let ((bounds (cape--dabbrev-bounds))) `(,(car bounds) ,(cdr bounds) ,(cape--table-with-properties @@ -894,23 +897,15 @@ This function can be used as an advice around an existing Capf." ;;;###autoload (defun cape-wrap-predicate (capf predicate) "Call CAPF and add an additional candidate PREDICATE. -The PREDICATE is passed the candidate symbol or string." +The PREDICATE is passed the candidate string." (pcase (funcall capf) (`(,beg ,end ,table . ,plist) `(,beg ,end ,table :predicate - ,(if-let (pred (plist-get plist :predicate)) - ;; First argument is key, second is value for hash tables. - ;; The first argument can be a cons cell for alists. Then - ;; the candidate itself is either a string or a symbol. We - ;; normalize the calling convention here such that PREDICATE - ;; always receives a string or a symbol. - (lambda (&rest args) - (when (apply pred args) - (setq args (car args)) - (funcall predicate (if (consp args) (car args) args)))) - (lambda (key &optional _val) - (funcall predicate (if (consp key) (car key) key)))) + ,(let ((pred (plist-get plist :predicate))) + (lambda (&rest args) + (and (or (not pred) (apply pred args)) + (funcall predicate (cape--predicate-argument args))))) ,@plist)))) ;;;###autoload @@ -950,6 +945,22 @@ If the prefix is long enough, enforce auto completion." ,@plist))))) ;;;###autoload +(defun cape-wrap-expansion-length (capf length) + "Call CAPF and ensure that the expansions are long enough. +This is useful for auto completion, only candidates which are +LENGTH characters longer than the prefix are considered." + (pcase (funcall capf) + (`(,beg ,end ,table . ,plist) + `(,beg ,end ,table + :predicate + ,(let ((pred (plist-get plist :predicate)) + (min (+ length (- end beg)))) + (lambda (&rest args) + (and (or (not pred) (apply pred args)) + (>= (length (cape--predicate-argument args)) min)))) + ,@plist)))) + +;;;###autoload (defun cape-wrap-inside-comment (capf) "Call CAPF only if inside comment. This function can be used as an advice around an existing Capf." @@ -1018,6 +1029,8 @@ This function can be used as an advice around an existing Capf." (cape--capf-wrapper properties) ;;;###autoload (autoload 'cape-capf-purify "cape") (cape--capf-wrapper purify) +;;;###autoload (autoload 'cape-capf-expansion-length "cape") +(cape--capf-wrapper expansion-length) ;;;###autoload (autoload 'cape-capf-silent "cape") (cape--capf-wrapper silent) -- cgit v1.0