From 2032acea9b5aaa40bffa06cfced7da51675896ea Mon Sep 17 00:00:00 2001 From: Daniel Mendler Date: Tue, 30 Jan 2024 17:28:12 +0100 Subject: Relax the completion table recomputation condition The completion table will be recomputed when the input prefix changes, even if there is trailing Orderless filter input. Affected are cape--dynamic-table (cape-dict, cape-company-to-capf): and cape-capf-buster. See the discussion at https://github.com/minad/cape/discussions/106 for details. --- CHANGELOG.org | 2 ++ cape.el | 39 +++++++++++++++++++++++---------------- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.org b/CHANGELOG.org index 51ac1db..98c9bf7 100644 --- a/CHANGELOG.org +++ b/CHANGELOG.org @@ -5,6 +5,8 @@ * Development - Add =cape-wrap-inside-code= and =cape-capf-inside-code=. +=- =cape--dynamic-table=, =cape-capf-buster=: Recompute the completion table when the + input prefix changes, even in the presence of trailing Orderless input. * Version 1.2 (2024-01-23) diff --git a/cape.el b/cape.el index d231794..a196c68 100644 --- a/cape.el +++ b/cape.el @@ -158,16 +158,19 @@ The buffers are scanned for completion candidates by `cape-line'." (replace-match str nil nil input)))) str)) -(defun cape--separator-p (str) - "Return non-nil if input STR has a separator character. +(defun cape--input-string (beg end) + "Return input string between BEG and END up to a separator character. Separator characters are used by completion styles like Orderless to split filter words. In Corfu, the separator is configurable via the variable `corfu-separator'." - (string-search (string ;; Support `corfu-separator' and Orderless - (or (and (bound-and-true-p corfu-mode) - (bound-and-true-p corfu-separator)) - ?\s)) - str)) + (save-excursion + (goto-char beg) + (if (search-forward (string (or (and (bound-and-true-p corfu-mode) + (bound-and-true-p corfu-separator)) + ?\s)) + end t) + (buffer-substring-no-properties beg (1- (point))) + (buffer-substring-no-properties beg end)))) (defmacro cape--silent (&rest body) "Silence BODY." @@ -324,10 +327,8 @@ string as first argument to the completion table." ;; `all-completions' must surely be most expensive, so nobody will suspect ;; a thing. (unless (or (eq action 'metadata) (eq (car-safe action) 'boundaries)) - (let ((input (buffer-substring-no-properties beg end))) - (unless (and valid - (or (cape--separator-p input) - (funcall valid input))) + (let ((input (cape--input-string beg end))) + (unless (and valid (funcall valid input)) (let* (;; Reset in case `all-completions' is used inside FUN completion-ignore-case completion-regexp-list ;; Retrieve new state by calling FUN @@ -1005,16 +1006,22 @@ completion table is refreshed on every input change." (end (copy-marker end t)) (input (buffer-substring-no-properties beg end))) (lambda (str pred action) - (let ((new-input (buffer-substring-no-properties beg end))) - (unless (or (not (eq action t)) - (cape--separator-p new-input) - (funcall valid input new-input)) + (let ((new-input (cape--input-string beg end))) + (when (and + ;; Only refresh table for the `all-completions' action. + (eq action t) + ;; Point must be inside the input string. It could lie + ;; outside if the Orderless completion style is used. + (<= beg (point) (+ beg (length new-input))) + ;; Current input is not valid. + (not (funcall valid input new-input))) (pcase ;; Reset in case `all-completions' is used inside CAPF (let (completion-ignore-case completion-regexp-list) (funcall capf)) ((and `(,new-beg ,new-end ,new-table . ,new-plist) - (guard (and (= beg new-beg) (= end new-end)))) + ;; new-end can be before end for Orderless completion. + (guard (and (= new-beg beg) (<= new-end end)))) (let (throw-on-input) ;; No interrupt during state update (setf table new-table input new-input -- cgit v1.0