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 ()