branch: externals/consult commit 8bccc73073247cd395a84165515a68468790a6dd Author: Daniel Mendler <m...@daniel-mendler.de> Commit: Daniel Mendler <m...@daniel-mendler.de>
consult--multi: Support the creation of new candidates (Fix #539) consult--read: Change the calling convention of the :lookup function. --- consult.el | 128 ++++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 71 insertions(+), 57 deletions(-) diff --git a/consult.el b/consult.el index 078f945e40..d483025d39 100644 --- a/consult.el +++ b/consult.el @@ -200,12 +200,12 @@ character, the *Completions* buffer and a few log buffers." :type '(repeat regexp)) (defcustom consult-buffer-sources - '(consult--source-buffer + '(consult--source-hidden-buffer + consult--source-buffer consult--source-recent-file consult--source-bookmark consult--source-project-buffer - consult--source-project-recent-file - consult--source-hidden-buffer) + consult--source-project-recent-file) "Sources used by `consult-buffer'. See also `consult-project-buffer-sources'. See `consult--multi' for a description of the source data structure." @@ -958,26 +958,27 @@ selection change to full Emacs markers." (setcar loc (set-marker (make-marker) (cdar loc) (caar loc)))) loc)) -(defun consult--lookup-member (_ candidates cand) - "Lookup CAND in CANDIDATES list, return original element." - (car (member cand candidates))) +(cl-defun consult--lookup-member (&key selected candidates &allow-other-keys) + "Lookup SELECTED in CANDIDATES list, return original element." + (car (member selected candidates))) -(defun consult--lookup-cons (_ candidates cand) - "Lookup CAND in CANDIDATES alist, return cons." - (assoc cand candidates)) +(cl-defun consult--lookup-cons (&key selected candidates &allow-other-keys) + "Lookup SELECTED in CANDIDATES alist, return cons." + (assoc selected candidates)) -(defun consult--lookup-cdr (_ candidates cand) - "Lookup CAND in CANDIDATES alist, return cdr of element." - (cdr (assoc cand candidates))) +(cl-defun consult--lookup-cdr (&key selected candidates &allow-other-keys) + "Lookup SELECTED in CANDIDATES alist, return cdr of element." + (cdr (assoc selected candidates))) -(defun consult--lookup-location (_ candidates cand) - "Lookup CAND in CANDIDATES list of 'consult-location category, return the marker." - (when-let (found (member cand candidates)) +(cl-defun consult--lookup-location (&key selected candidates &allow-other-keys) + "Lookup SELECTED in CANDIDATES list of `consult-location' category. +Return the location marker." + (when-let (found (member selected candidates)) (car (consult--get-location (car found))))) -(defun consult--lookup-candidate (_ candidates cand) - "Lookup CAND in CANDIDATES list and return property 'consult--candidate." - (when-let (found (member cand candidates)) +(cl-defun consult--lookup-candidate (&key selected candidates &allow-other-keys) + "Lookup SELECTED in CANDIDATES list and return property `consult--candidate'." + (when-let (found (member selected candidates)) (get-text-property 0 'consult--candidate (car found)))) (defun consult--forbid-minibuffer () @@ -1393,7 +1394,7 @@ FACE is the cursor face." "Add preview support for FUN. See `consult--with-preview' for the arguments PREVIEW-KEY, STATE, TRANSFORM and CANDIDATE." - (let ((input "") selected timer last-preview) + (let ((input "") narrow selected timer last-preview) (consult--minibuffer-with-setup-hook (if (and state preview-key) (lambda () @@ -1419,7 +1420,7 @@ PREVIEW-KEY, STATE, TRANSFORM and CANDIDATE." (with-selected-window (active-minibuffer-window) (let ((input (minibuffer-contents-no-properties))) (with-selected-window (or (minibuffer-selected-window) (next-window)) - (let ((transformed (funcall transform input cand)) + (let ((transformed (funcall transform narrow input cand)) (new-preview (cons input cand))) (when-let (debounce (consult--preview-key-debounce preview-key transformed)) (when timer @@ -1443,14 +1444,16 @@ PREVIEW-KEY, STATE, TRANSFORM and CANDIDATE." (setq last-preview new-preview))))))))))) (consult--append-local-post-command-hook (lambda () - (setq input (minibuffer-contents-no-properties)) + (setq input (minibuffer-contents-no-properties) + narrow consult--narrow) (funcall consult--preview-function)))) (lambda () (consult--append-local-post-command-hook - (lambda () (setq input (minibuffer-contents-no-properties)))))) + (lambda () (setq input (minibuffer-contents-no-properties) + narrow consult--narrow))))) (unwind-protect (cons (setq selected (when-let (result (funcall fun)) - (funcall transform input result))) + (funcall transform narrow input result))) input) (when state ;; STEP 5: The preview function should perform its final action @@ -2173,8 +2176,13 @@ PREVIEW-KEY are the preview keys." (result (consult--with-preview preview-key state - (lambda (input cand) - (funcall lookup input (funcall async nil) cand)) + (lambda (narrow input cand) + (condition-case nil + (funcall lookup :input input :narrow narrow :candidates (funcall async nil) :selected cand) + (wrong-number-of-arguments + ;; TODO Remove the condition-case after upgrades of :lookup functions + (message "consult--read: The :lookup function protocol changed") + (funcall lookup input (funcall async nil) cand)))) (apply-partially #'run-hook-with-args-until-success 'consult--completion-candidate-hook) (completing-read prompt @@ -2236,7 +2244,7 @@ INHERIT-INPUT-METHOD, if non-nil the minibuffer inherits the input method." (list :prompt "Select: " :preview-key consult-preview-key :sort t - :lookup (lambda (_input _cands x) x))))) + :lookup (lambda (&rest args) (plist-get args :selected)))))) ;;;; Internal API: consult--multi @@ -2295,20 +2303,23 @@ INHERIT-INPUT-METHOD, if non-nil the minibuffer inherits the input method." (consult--ensure-list key))) sources)))) -(defun consult--multi-lookup (sources _ candidates cand) - "Lookup CAND in CANDIDATES given SOURCES." - (unless (string-blank-p cand) - (if-let (found (member cand candidates)) +(cl-defun consult--multi-lookup (sources &key candidates selected narrow &allow-other-keys) + "Lookup SELECTED in CANDIDATES given SOURCES." + (unless (string-blank-p selected) + (if-let (found (member selected candidates)) (cons (cdr (get-text-property 0 'multi-category (car found))) - (consult--multi-source sources cand)) - (let* ((tofu (consult--tofu-p (aref cand (1- (length cand))))) - (source (if tofu - (consult--multi-source sources cand) - ;; TODO Use narrowed source here or fallback to source - ;; with :default=t. Take source 0 only as last resort. - (aref sources 0)))) - `(,(if tofu (substring cand 0 -1) cand) - :new t :action ,(plist-get source :new) ,@source))))) + (consult--multi-source sources selected)) + (let* ((tofu (consult--tofu-p (aref selected (1- (length selected))))) + (src (cond + (tofu (consult--multi-source sources selected)) + (narrow (seq-find (lambda (src) + (let ((n (plist-get src :narrow))) + (eq (or (car-safe n) n -1) narrow))) + sources)) + ((seq-find (lambda (src) (plist-get src :default)) sources)) + ((aref sources 0))))) + `(,(if tofu (substring selected 0 -1) selected) + :new t :action ,(plist-get src :new) ,@src))))) (defun consult--multi-candidates (sources) "Return `consult--multi' candidates from SOURCES." @@ -2451,7 +2462,7 @@ Optional source fields: (apply-partially #'consult--add-history nil add-history)))) (car (consult--with-preview preview-key state - (lambda (inp _) (funcall transform inp)) (lambda () t) + (lambda (_narrow inp _cand) (funcall transform inp)) (lambda () t) (read-from-minibuffer prompt initial nil nil history default inherit-input-method))))) (cl-defun consult--prompt (&rest options &key prompt history add-history initial default @@ -2585,18 +2596,18 @@ These configuration options are supported: (cond ;; Transform absolute file names ((file-name-absolute-p initial) - (lambda (_inp cand) + (lambda (_narrow _inp cand) (substitute-in-file-name cand))) ;; Ensure that ./ prefix is kept for the shell (#356) ((string-match-p "\\`\\.\\.?/" initial) - (lambda (_inp cand) + (lambda (_narrow _inp cand) (setq cand (file-relative-name (substitute-in-file-name cand))) (if (string-match-p "\\`\\.\\.?/" cand) cand (concat "./" cand)))) ;; Simplify relative file names (t - (lambda (_inp cand) + (lambda (_narrow _inp cand) (file-relative-name (substitute-in-file-name cand))))) - (lambda (_inp cand) cand)) + (lambda (_narrow _inp cand) cand)) ;; candidate function (apply-partially #'run-hook-with-args-until-success 'consult--completion-candidate-hook) @@ -2997,20 +3008,20 @@ CURR-LINE is the current line number." (setcdr default-cand nil) (nconc before candidates))))))) -(defun consult--line-match (input candidates cand) +(cl-defun consult--line-match (&rest args &key input selected &allow-other-keys) "Lookup position of match. +ARGS is the argument list. INPUT is the input string entered by the user. -CANDIDATES is the line candidates alist. -CAND is the currently selected candidate." - (when-let (pos (consult--lookup-location input candidates cand)) +SELECTED is the currently selected candidate." + (when-let (pos (apply #'consult--lookup-location args)) (if (or (string-blank-p input) (eq consult-line-point-placement 'line-beginning)) pos (let ((beg 0) - (end (length cand))) + (end (length selected))) ;; Ignore tofu-encoded unique line number suffix - (while (and (> end 0) (consult--tofu-p (aref cand (1- end)))) + (while (and (> end 0) (consult--tofu-p (aref selected (1- end)))) (setq end (1- end))) ;; Find match end position, remove characters from line end until ;; matching fails @@ -3023,7 +3034,7 @@ CAND is the currently selected candidate." ;; candidate, since setting up deferred highlighting is ;; costly. (consult--completion-filter input - (list (substring cand 0 (- end step))) + (list (substring selected 0 (- end step))) 'consult-location 'highlight)) (setq end (- end step))) (setq step (/ step 2)))) @@ -3035,7 +3046,7 @@ CAND is the currently selected candidate." (while (and (< (+ beg step) end) ;; See comment above, call to `consult--completion-filter'. (consult--completion-filter input - (list (substring cand (+ beg step) end)) + (list (substring selected (+ beg step) end)) 'consult-location 'highlight)) (setq beg (+ beg step))) (setq step (/ step 2))) @@ -3921,8 +3932,10 @@ starts a new Isearch session otherwise." cand (alist-get (consult--tofu-get cand) consult--isearch-history-narrow))) :lookup - (lambda (_ candidates str) - (if-let (found (member str candidates)) (substring (car found) 0 -1) str)) + (lambda (&rest args) + (if-let (found (member (plist-get args :selected) (plist-get args :candidates))) + (substring (car found) 0 -1) + (plist-get args :selected))) :state (lambda (action cand) (when (and (eq action 'preview) cand) @@ -4023,9 +4036,10 @@ The command supports previewing the currently selected theme." :require-match t :category 'theme :history 'consult--theme-history - :lookup (lambda (_input _cands x) - (or (when-let (cand (and x (intern-soft x))) - (car (memq cand avail-themes))) + :lookup (lambda (&rest selected) + (setq selected (plist-get selected :selected) + selected (and selected (intern-soft selected))) + (or (and selected (car (memq selected avail-themes))) saved-theme)) :state (lambda (action theme) (pcase action