branch: elpa/dirvish
commit ecb7c42e20ce18f80d702eafb2e6add5b1e4d023
Author: Alex Lu <hellosimon1...@hotmail.com>
Commit: Alex Lu <hellosimon1...@hotmail.com>

    perf(narrow): lazy completion
---
 dirvish-widgets.el           | 16 +++++++------
 dirvish.el                   |  8 +++----
 extensions/dirvish-narrow.el | 54 +++++++++++++++++++++++---------------------
 extensions/dirvish-peek.el   |  2 +-
 4 files changed, 42 insertions(+), 38 deletions(-)

diff --git a/dirvish-widgets.el b/dirvish-widgets.el
index 1348984fbd..8f34562ecb 100644
--- a/dirvish-widgets.el
+++ b/dirvish-widgets.el
@@ -427,13 +427,15 @@ GROUP-TITLES is a list of group titles."
 
 (dirvish-define-mode-line index
   "Current file's index and total files count."
-  (let ((cur-pos (format "%3d " (- (line-number-at-pos (point)) 1)))
-        (fin-pos (format "/%3d " (- (line-number-at-pos (point-max)) 2))))
-    (if (dirvish--selected-p)
-        (put-text-property 0 (length fin-pos) 'face 'bold fin-pos)
-      (put-text-property 0 (length cur-pos) 'face 'dirvish-inactive cur-pos)
-      (put-text-property 0 (length fin-pos) 'face 'dirvish-inactive fin-pos))
-    (format "%s%s" cur-pos fin-pos)))
+  (let* ((ct (dirvish-prop :count)) (cpos (- (line-number-at-pos (point)) 1))
+         (fpos (- (line-number-at-pos (point-max)) 2))
+         (cur (if ct "" (format "%3d " cpos)))
+         (end (if ct (format " found %s matches " ct) (format "/%3d " fpos))))
+    (if (or (dirvish--selected-p) ct)
+        (put-text-property 0 (length end) 'face 'bold end)
+      (put-text-property 0 (length cur) 'face 'dirvish-inactive cur)
+      (put-text-property 0 (length end) 'face 'dirvish-inactive end))
+    (format "%s%s" cur end)))
 
 (dirvish-define-mode-line free-space
   "Amount of free space on `default-directory''s file system."
diff --git a/dirvish.el b/dirvish.el
index 3779499eb9..02381104b7 100644
--- a/dirvish.el
+++ b/dirvish.el
@@ -335,13 +335,13 @@ Set the PROP with BODY if given."
                     (push (cons ,prop val) dirvish--props)))
         `val)))
 
-(defun dirvish-run-with-delay (action fun &optional debounce throttle record)
+(defun dirvish--run-with-delay (action &optional record fun debounce throttle)
   "Run function FUN accroding to ACTION with delay.
 DEBOUNCE defaults to `dirvish-input-debounce'.
 THROTTLE defaults to `dirvish-input-throttle'.
 RECORD defaults to `dirvish--delay-timer'."
   (declare (indent defun))
-  (setq record (or record dirvish--delay-timer)
+  (setq record (or record dirvish--delay-timer) fun (or fun #'ignore)
         debounce (or debounce dirvish-input-debounce)
         throttle (or throttle dirvish-input-throttle))
   (pcase action
@@ -357,7 +357,7 @@ RECORD defaults to `dirvish--delay-timer'."
          nil (max debounce (- (+ (nth 1 record) throttle) (float-time)))))
        (setf (nth 2 record) action)
        (timer-activate (car record))))
-    ('reset (setf (nth 2 record) nil))))
+    ('reset (setf (nth 2 record) ""))))
 
 (defmacro dirvish-save-dedication (&rest body)
   "Run BODY after undedicating window, restore dedication afterwards."
@@ -1288,7 +1288,7 @@ Dirvish sets `revert-buffer-function' to this function."
     (when-let* ((idx (save-excursion (dired-get-filename nil t))))
       (dirvish-prop :index (setq idx (file-local-name idx)))
       (when (dv-curr-layout dv)
-        (dirvish-run-with-delay idx
+        (dirvish--run-with-delay idx nil
           (lambda (action)
             ;; don't grab focus when peeking or preview window is selected
             (force-mode-line-update t)
diff --git a/extensions/dirvish-narrow.el b/extensions/dirvish-narrow.el
index cf22997df9..1bd50af655 100644
--- a/extensions/dirvish-narrow.el
+++ b/extensions/dirvish-narrow.el
@@ -57,6 +57,11 @@
   "Face for matches of components numbered 3 mod 4."
   :group 'dirvish)
 
+(defun dirvish-narrow--compile-regex (string)
+  "Compile `completion-regexp-list' from STRING."
+  (if (fboundp 'orderless-compile) (cdr (orderless-compile string))
+    (split-string string)))
+
 (defun dirvish-narrow--highlight (regexps ignore-case string)
   "Destructively propertize STRING to highlight a match of each of the REGEXPS.
 The search is case insensitive if IGNORE-CASE is non-nil."
@@ -100,36 +105,32 @@ The search is case insensitive if IGNORE-CASE is non-nil."
 
 (defun dirvish-narrow-update-h ()
   "Update the Dirvish buffer based on the input of the minibuffer."
-  (dirvish-run-with-delay (minibuffer-contents-no-properties)
+  (dirvish--run-with-delay
+    (minibuffer-contents-no-properties) dirvish-narrow--delay-timer
     (lambda (action)
       (with-current-buffer (window-buffer (minibuffer-selected-window))
         (save-excursion
-          (cl-loop with regs = (if (fboundp 'orderless-compile)
-                                   (cdr (orderless-compile action))
-                                 (split-string action))
-                   for idx from 0
-                   for (dir . pos) in dired-subdir-alist
-                   do (dirvish-narrow--filter-subdir dir pos regs idx)))))
-    nil nil dirvish-narrow--delay-timer))
-
-(defun dirvish-narrow--filter-subdir (dir pos regexs idx)
-  "Filter the subdir DIR in POS with REGEXS.
-IDX the index of DIR in `dired-subdir-alist'."
+          (cl-loop with regs = (dirvish-narrow--compile-regex action)
+                   for (dir . pos) in dired-subdir-alist and idx from 0
+                   do (dirvish-narrow--subdir dir pos regs idx)))))))
+
+(defun dirvish-narrow--subdir (dir pos regexs idx &optional all)
+  "Narrow subdir DIR at index IDX in POS with REGEXS."
   (delete-region
    (progn (goto-char pos) (forward-line (dirvish--subdir-offset)) (point))
    (- (dired-subdir-max) (if (eq idx 0) 0 1)))
   (cl-loop with completion-regexp-list = regexs
            with completion-ignore-case =
-           (cl-loop for regexp in (ensure-list regexs)
-                    always (isearch-no-upper-case-p regexp t))
+           (cl-loop for re in (ensure-list regexs)
+                    always (isearch-no-upper-case-p re t))
            with files = (gethash (md5 dir) dirvish--dir-data)
            and fr-h = (+ (frame-height) 5) and count = 0
-           for f in (all-completions "" files)
+           with pred = (if all #'always (lambda (&rest _) (<= (cl-incf count) 
fr-h)))
+           for f in (all-completions "" files pred)
            for l = (concat (gethash f files)) ; use copy, not reference
-           for hl = (if (> (cl-incf count) fr-h) l ; lazy highlighting
-                      (dirvish-narrow--highlight
-                       regexs completion-ignore-case l))
-           do (insert hl)))
+           do (insert (if all l (dirvish-narrow--highlight ; lazy highlighting
+                                 regexs completion-ignore-case l)))
+           finally do (dirvish-prop :count count)))
 
 ;;;###autoload
 (defun dirvish-narrow ()
@@ -139,9 +140,7 @@ IDX the index of DIR in `dired-subdir-alist'."
     (user-error "Current buffer has unfinished jobs"))
   (require 'orderless nil t)
   (dirvish-narrow--build-indices)
-  (let ((dv (dirvish-prop :dv))
-        (restore (dirvish-prop :index))
-        (bstr (buffer-string))
+  (let ((dv (dirvish-prop :dv)) (restore (dirvish-prop :index))
         input buffer-read-only)
     (font-lock-mode -1) (buffer-disable-undo)
     (minibuffer-with-setup-hook
@@ -150,11 +149,14 @@ IDX the index of DIR in `dired-subdir-alist'."
           (add-hook 'post-command-hook #'dirvish-narrow-update-h nil t))
       (unwind-protect
           (setq input (read-from-minibuffer "Focus on files: "))
-        (when (= (length input) 0)
-          (erase-buffer) (insert bstr)
-          (unless (cdr dired-subdir-alist) (dirvish--hide-dired-header)))
+        (save-excursion
+          (cl-loop with re = (dirvish-narrow--compile-regex (or input ""))
+                   for (d . p) in dired-subdir-alist and i from 0
+                   do (dirvish-narrow--subdir d p re i (or input ""))))
+        (dirvish-prop :count nil)
         (when restore (dired-goto-file restore))
-        (dirvish-run-with-delay 'reset #'ignore)
+        (dirvish--run-with-delay 'reset)
+        (dirvish--run-with-delay 'reset dirvish-narrow--delay-timer)
         (font-lock-mode 1) (buffer-enable-undo)))))
 
 (provide 'dirvish-narrow)
diff --git a/extensions/dirvish-peek.el b/extensions/dirvish-peek.el
index 617b5cde6a..638533e62b 100644
--- a/extensions/dirvish-peek.el
+++ b/extensions/dirvish-peek.el
@@ -153,7 +153,7 @@ one of categories in `dirvish-peek-categories'."
          (error (setq cand (format "LIB_EXCEPTION:::%s:::%s" cand
                                    (error-message-string err)))))))
     (dirvish-prop :index cand)
-    (dirvish-run-with-delay cand
+    (dirvish--run-with-delay cand nil
       (lambda (action) (dirvish--preview-update dv action)) (cdr peek-key))))
 
 (defun dirvish-peek-exit-h ()

Reply via email to