emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/consult b0ed250 3/4: Introduce consult--buffer-query


From: ELPA Syncer
Subject: [elpa] externals/consult b0ed250 3/4: Introduce consult--buffer-query
Date: Sun, 25 Jul 2021 15:57:07 -0400 (EDT)

branch: externals/consult
commit b0ed250a1dbe011c3f4bef56d4273236ea8d265b
Author: Daniel Mendler <mail@daniel-mendler.de>
Commit: Daniel Mendler <mail@daniel-mendler.de>

    Introduce consult--buffer-query
---
 consult-compile.el |  12 +++--
 consult-imenu.el   |  17 +++----
 consult.el         | 135 +++++++++++++++++++++++++++++++++++------------------
 3 files changed, 102 insertions(+), 62 deletions(-)

diff --git a/consult-compile.el b/consult-compile.el
index 91f9dd9..e83634a 100644
--- a/consult-compile.el
+++ b/consult-compile.el
@@ -84,11 +84,13 @@
 
 (defun consult-compile--compilation-buffers (file)
   "Return a list of compilation buffers relevant to FILE."
-  (seq-filter (lambda (buffer)
-                (with-current-buffer buffer
-                  (and (compilation-buffer-internal-p)
-                       (file-in-directory-p file default-directory))))
-              (buffer-list)))
+  (consult--buffer-query
+   :sort 'alpha :as
+   (lambda (buffer)
+     (with-current-buffer buffer
+       (and (compilation-buffer-internal-p)
+            (file-in-directory-p file default-directory)
+            buffer)))))
 
 ;;;###autoload
 (defun consult-compile-error ()
diff --git a/consult-imenu.el b/consult-imenu.el
index 7b6f343..6b552b5 100644
--- a/consult-imenu.el
+++ b/consult-imenu.el
@@ -143,16 +143,6 @@ TYPES is the mode-specific types configuration."
   "Return all imenu items from each BUFFERS."
   (seq-mapcat (lambda (buf) (with-current-buffer buf (consult-imenu--items))) 
buffers))
 
-(defun consult-imenu--project-buffers ()
-  "Return project buffers with the same `major-mode' as the current buffer."
-  (if-let (root (consult--project-root))
-      (seq-filter (lambda (buf)
-                    (when-let (dir (buffer-local-value 'default-directory buf))
-                      (and (eq (buffer-local-value 'major-mode buf) major-mode)
-                           (string-prefix-p root (expand-file-name dir)))))
-                  (buffer-list))
-    (list (current-buffer))))
-
 (defun consult-imenu--jump (item)
   "Jump to imenu ITEM via `consult--jump'.
 
@@ -223,7 +213,12 @@ In order to determine the buffers belonging to the same 
project, the
 same major mode as the current buffer are used. See also
 `consult-imenu' for more details."
   (interactive)
-  (consult-imenu--select (consult-imenu--all-items 
(consult-imenu--project-buffers))))
+  (consult-imenu--select
+   (consult-imenu--all-items
+    (or (consult--buffer-query :project t
+                               :mode major-mode
+                               :sort 'alpha)
+        (list (current-buffer))))))
 
 (define-obsolete-function-alias
   'consult-project-imenu
diff --git a/consult.el b/consult.el
index 5204796..364fc37 100644
--- a/consult.el
+++ b/consult.el
@@ -452,9 +452,6 @@ should not be considered as stable as the public API.")
 (defvar consult--buffer-display #'switch-to-buffer
   "Buffer display function.")
 
-(defvar consult--cache nil
-  "Cached data populated by `consult--define-cache'.")
-
 (defvar consult--completion-candidate-hook
   (list #'consult--default-completion-mb-candidate
         #'consult--default-completion-list-candidate)
@@ -545,6 +542,23 @@ ARGS is a list of commands or sources followed by the list 
of keyword-value pair
 
 ;;;; Helper functions and macros
 
+(defmacro consult--keep! (list form)
+  "Evaluate FORM for every element of LIST and keep the non-nil results."
+  (declare (indent 1))
+  (let ((head (make-symbol "head"))
+        (prev (make-symbol "prev"))
+        (result (make-symbol "result")))
+    `(let* ((,head (cons nil ,list))
+            (,prev ,head))
+       (while (cdr ,prev)
+         (if-let (,result (let ((it (cadr ,prev))) ,form))
+             (progn
+               (pop ,prev)
+               (setcar ,prev ,result))
+           (setcdr ,prev (cddr ,prev))))
+       (setq ,list (cdr ,head))
+       nil)))
+
 ;; Upstream bug#46326, Consult issue 
https://github.com/minad/consult/issues/193
 (defmacro consult--minibuffer-with-setup-hook (fun &rest body)
   "Variant of `minibuffer-with-setup-hook' using a symbol and `fset'.
@@ -567,17 +581,6 @@ FUN is the hook function and BODY opens the minibuffer."
              ,@body)
          (remove-hook 'minibuffer-setup-hook ,hook)))))
 
-(defmacro consult--define-cache (name &rest body)
-  "Define cached value with NAME and BODY."
-  (declare (indent 1))
-  `(defun ,name ()
-     (or (alist-get ',name consult--cache)
-         (progn
-           ;; XXX Emacs bug#35546, fixed in Emacs 27.1
-           ;; (setf (alist-get key list) val) should return val
-           (setf (alist-get ',name consult--cache) ,(macroexp-progn body))
-           (alist-get ',name consult--cache)))))
-
 (defun consult--completion-filter (pattern cands category _highlight)
   "Filter CANDS with PATTERN.
 
@@ -1992,8 +1995,7 @@ Optional source fields:
 * Other source fields can be added specifically to the use case."
   (let* ((sources (consult--multi-enabled-sources sources))
          (candidates (consult--with-increased-gc
-                      (let ((consult--cache))
-                        (consult--multi-candidates sources))))
+                      (consult--multi-candidates sources)))
          (align (propertize
                  " " 'display
                  `(space :align-to (+ left ,(cadr candidates)))))
@@ -3515,20 +3517,66 @@ The command supports previewing the currently selected 
theme."
 
 ;;;;; Command: consult-buffer
 
-(consult--define-cache consult--cached-all-buffers
-  (let ((buffers (delq (current-buffer) (buffer-list)))
-        (visible-p (lambda (x) (get-buffer-window x 'visible))))
-    (nconc (seq-remove visible-p buffers)
-           (seq-filter visible-p buffers)
-           (list (current-buffer)))))
-
-(consult--define-cache consult--cached-buffers
-  (let ((filter (consult--regexp-filter consult-buffer-filter)))
-    (seq-remove (lambda (x) (string-match-p filter (buffer-name x)))
-                (consult--cached-all-buffers))))
-
-(consult--define-cache consult--cached-buffer-file-hash
-  (consult--string-hash (delq nil (mapcar #'buffer-file-name 
(consult--cached-buffers)))))
+(defun consult--buffer-sort-alpha (buffers)
+  "Sort BUFFERS alphabetically."
+  (sort buffers
+        (lambda (x y)
+          (string< (buffer-name x)
+                   (buffer-name y)))))
+
+(defun consult--buffer-sort-visibility (buffers)
+  "Sort BUFFERS by visibility."
+  (let ((hidden)
+        (current (current-buffer)))
+    (consult--keep! buffers
+      (unless (eq it current)
+        (if (get-buffer-window it 'visible)
+            it
+          (push it hidden)
+          nil)))
+    (nconc (nreverse hidden) buffers (list (current-buffer)))))
+
+(cl-defun consult--buffer-query (&key sort (filter t) project mode as)
+  "Buffer query function.
+PROJECT can be set to t to consider only project-specific buffers.
+SORT can be visibility, alpha or nil.
+FILTER can be t, hidden or nil.
+MODE can be a mode or a list of modes to restrict the returned buffers.
+AS is a conversion function."
+  ;; This function is quite messy but optimized to avoid unnecessary
+  ;; allocations. It is the backbone of most `consult-buffer' source. The
+  ;; function supports filtering by various criteria which are used throughout
+  ;; Consult.
+  (when-let (root (or (not project) (consult--project-root)))
+    (let ((buffers (buffer-list)))
+      (when sort
+        (setq buffers (funcall (intern (format "consult--buffer-sort-%s" 
sort)) buffers)))
+      (when (or filter mode project as)
+        (let ((mode (if (listp mode) mode (list mode)))
+              (re (consult--regexp-filter consult-buffer-filter)))
+          (consult--keep! buffers
+            (and
+             (or (not mode)
+                 (apply #'provided-mode-derived-p
+                        (buffer-local-value 'major-mode it) mode))
+             (pcase-exhaustive filter
+               ('nil t)
+               ('hidden (string-match-p re (buffer-name it)))
+               ('t (not (string-match-p re (buffer-name it)))))
+             (pcase-exhaustive project
+               ('nil t)
+               ('t
+                (when-let (dir (buffer-local-value 'default-directory it))
+                  (string-prefix-p root
+                                   (if (and (/= 0 (length dir)) (eq (aref dir 
0) ?/))
+                                       dir
+                                     (expand-file-name dir))))))
+             (if as (funcall as it) it)))))
+      buffers)))
+
+(defun consult--buffer-file-hash ()
+  "Return hash table of all buffer file names."
+  (consult--string-hash (consult--buffer-query :as #'buffer-file-name)))
 
 (defun consult--buffer-preview ()
   "Buffer preview function."
@@ -3571,13 +3619,9 @@ If NORECORD is non-nil, do not record the buffer switch 
in the buffer list."
     :enabled  ,(lambda () consult-project-root-function)
     :items
     ,(lambda ()
-       (when-let (root (consult--project-root))
-         (mapcar #'buffer-name
-                 (seq-filter
-                  (lambda (x)
-                    (when-let (dir (buffer-local-value 'default-directory x))
-                      (string-prefix-p root (expand-file-name dir))))
-                  (consult--cached-buffers))))))
+       (consult--buffer-query :sort 'visibility
+                              :project t
+                              :as #'buffer-name)))
   "Project buffer candidate source for `consult-buffer'.")
 
 (defvar consult--source-project-file
@@ -3589,13 +3633,13 @@ If NORECORD is non-nil, do not record the buffer switch 
in the buffer list."
     :history  file-name-history
     :state    ,#'consult--file-state
     :enabled  ,(lambda () (and consult-project-root-function
-                                recentf-mode))
+                               recentf-mode))
     :items
     ,(lambda ()
       (when-let (root (consult--project-root))
         (let ((len (length root))
               (inv-root (propertize root 'invisible t))
-              (ht (consult--cached-buffer-file-hash)))
+              (ht (consult--buffer-file-hash)))
           (mapcar (lambda (x)
                     (concat inv-root (substring x len)))
                   (seq-filter (lambda (x)
@@ -3613,10 +3657,9 @@ If NORECORD is non-nil, do not record the buffer switch 
in the buffer list."
     :history  buffer-name-history
     :action   ,#'consult--buffer-action
     :items
-    ,(lambda ()
-       (let ((filter (consult--regexp-filter consult-buffer-filter)))
-         (seq-filter (lambda (x) (string-match-p filter x))
-                     (mapcar #'buffer-name (consult--cached-all-buffers))))))
+    ,(lambda () (consult--buffer-query :sort 'visibility
+                                       :filter 'hidden
+                                       :as #'buffer-name)))
   "Hidden buffer candidate source for `consult-buffer'.")
 
 (defvar consult--source-buffer
@@ -3628,8 +3671,8 @@ If NORECORD is non-nil, do not record the buffer switch 
in the buffer list."
     :state    ,#'consult--buffer-state
     :default  t
     :items
-    ,(lambda ()
-       (mapcar #'buffer-name (consult--cached-buffers))))
+    ,(lambda () (consult--buffer-query :sort 'visibility
+                                       :as #'buffer-name)))
   "Buffer candidate source for `consult-buffer'.")
 
 (defvar consult--source-file
@@ -3642,7 +3685,7 @@ If NORECORD is non-nil, do not record the buffer switch 
in the buffer list."
     :enabled  ,(lambda () recentf-mode)
     :items
     ,(lambda ()
-       (let ((ht (consult--cached-buffer-file-hash)))
+       (let ((ht (consult--buffer-file-hash)))
          (mapcar #'abbreviate-file-name
                  (seq-remove (lambda (x) (gethash x ht)) recentf-list)))))
   "Recent file candidate source for `consult-buffer'.")



reply via email to

[Prev in Thread] Current Thread [Next in Thread]