>From 471c37844f0baba925bd948e13005d2227d43f65 Mon Sep 17 00:00:00 2001 From: Augusto Stoffel Date: Sat, 8 Jan 2022 11:08:46 +0100 Subject: [PATCH 1/2] Allow reading from minibuffer with lazy highlight and match count * lisp/isearch.el (isearch-lazy-count-display-function): New variable allowing to display the lazy count in special ways. (isearch-edit-string): Add lazy highlight and count of matching text. (isearch-lazy-highlight-new-loop, isearch-lazy-highlight-buffer-update): Use `isearch-lazy-count-display-function' instead of hardcoded call to `isearch-message'. (isearch-read-with-highlight--overlay, isearch-read-with-highlight--after-change, isearch-read-with-highlight--exit, isearch-read-with-highlight-setup, isearch-read-with-highlight-count): Variable and functions implementing the lazy highlight functionality while reading from minibuffer. * lisp/simple.el (minibuffer-history-isearch-setup): Set `isearch-lazy-count-display-function' appropriately. * lisp/comint.el (comint-history-isearch-setup, comint-history-isearch-end): Set `isearch-lazy-count-display-function' appropriately. --- lisp/isearch.el | 100 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 82 insertions(+), 18 deletions(-) diff --git a/lisp/isearch.el b/lisp/isearch.el index 7593a0ec98..c10f365ee5 100644 --- a/lisp/isearch.el +++ b/lisp/isearch.el @@ -465,6 +465,9 @@ lazy-count-suffix-format :group 'lazy-count :version "27.1") +(defvar isearch-lazy-count-display-function nil + "Function called when new lazy count results are available.") + ;; Define isearch help map. @@ -1808,19 +1811,21 @@ isearch-edit-string ;; for some incompatibility with gmhist. (minibuffer-history-symbol) ;; Search string might have meta information on text properties. - (minibuffer-allow-text-properties t)) + (minibuffer-allow-text-properties t) + (isearch-lazy-count-display-function #'isearch-read-with-highlight-count)) (setq isearch-new-string - (read-from-minibuffer - (isearch-message-prefix nil isearch-nonincremental) - (cons isearch-string (1+ (or (isearch-fail-pos) - (length isearch-string)))) - minibuffer-local-isearch-map nil - (if isearch-regexp - (cons 'regexp-search-ring - (1+ (or regexp-search-ring-yank-pointer -1))) - (cons 'search-ring - (1+ (or search-ring-yank-pointer -1)))) - nil t) + (minibuffer-with-setup-hook #'isearch-read-with-highlight-setup + (read-from-minibuffer + (isearch-message-prefix nil isearch-nonincremental) + (cons isearch-string (1+ (or (isearch-fail-pos) + (length isearch-string)))) + minibuffer-local-isearch-map nil + (if isearch-regexp + (cons 'regexp-search-ring + (1+ (or regexp-search-ring-yank-pointer -1))) + (cons 'search-ring + (1+ (or search-ring-yank-pointer -1)))) + nil t)) isearch-new-message (mapconcat 'isearch-text-char-description isearch-new-string ""))))) @@ -4023,7 +4028,7 @@ isearch-lazy-highlight-new-loop isearch-lazy-highlight-window-end)))))) ;; something important did indeed change (lazy-highlight-cleanup t (not (equal isearch-string ""))) ;stop old timer - (when (and isearch-lazy-count isearch-mode (null isearch-message-function)) + (when isearch-lazy-count (when (or (equal isearch-string "") ;; Check if this place was reached by a condition above ;; other than changed window boundaries (that shouldn't @@ -4042,7 +4047,11 @@ isearch-lazy-highlight-new-loop (setq isearch-lazy-count-current nil isearch-lazy-count-total nil) ;; Delay updating the message if possible, to avoid flicker - (when (string-equal isearch-string "") (isearch-message)))) + (when (string-equal isearch-string "") + (when (and isearch-mode (null isearch-message-function)) + (isearch-message)) + (when isearch-lazy-count-display-function + (funcall isearch-lazy-count-display-function))))) (setq isearch-lazy-highlight-window-start-changed nil) (setq isearch-lazy-highlight-window-end-changed nil) (setq isearch-lazy-highlight-error isearch-error) @@ -4095,13 +4104,16 @@ isearch-lazy-highlight-new-loop 'isearch-lazy-highlight-start)))) ;; Update the current match number only in isearch-mode and ;; unless isearch-mode is used specially with isearch-message-function - (when (and isearch-lazy-count isearch-mode (null isearch-message-function)) + (when isearch-lazy-count ;; Update isearch-lazy-count-current only when it was already set ;; at the end of isearch-lazy-highlight-buffer-update (when isearch-lazy-count-current (setq isearch-lazy-count-current (gethash (point) isearch-lazy-count-hash 0)) - (isearch-message)))) + (when (and isearch-mode (null isearch-message-function)) + (isearch-message)) + (when isearch-lazy-count-display-function + (funcall isearch-lazy-count-display-function))))) (defun isearch-lazy-highlight-search (string bound) "Search ahead for the next or previous match, for lazy highlighting. @@ -4302,16 +4314,68 @@ isearch-lazy-highlight-buffer-update (setq looping nil nomore t)))) (if nomore - (when (and isearch-lazy-count isearch-mode (null isearch-message-function)) + (when isearch-lazy-count (unless isearch-lazy-count-total (setq isearch-lazy-count-total 0)) (setq isearch-lazy-count-current (gethash opoint isearch-lazy-count-hash 0)) - (isearch-message)) + (when (and isearch-mode (null isearch-message-function)) + (isearch-message)) + (when isearch-lazy-count-display-function + (funcall isearch-lazy-count-display-function))) (setq isearch-lazy-highlight-timer (run-at-time lazy-highlight-interval nil 'isearch-lazy-highlight-buffer-update))))))))) +;; Reading from minibuffer with lazy highlight and match count + +(defvar isearch-read-with-highlight--overlay nil + "Overlay for minibuffer prompt updates.") + +(defvar isearch-read-with-highlight-transform #'identity + "Function to transform minibuffer text into a `isearch-string' for highlighting.") + +(defun isearch-read-with-highlight--after-change (_beg _end _len) + "Update lazy highlight state in minibuffer selected window." + (when isearch-lazy-highlight + (let ((inhibit-redisplay t) ;; Avoid cursor flickering + (string (minibuffer-contents))) + (with-minibuffer-selected-window + (setq isearch-string (funcall isearch-read-with-highlight-transform string)) + (isearch-lazy-highlight-new-loop))))) + +(defun isearch-read-with-highlight--exit () + "Unwind changes from `isearch-read-with-highlight-setup'." + (remove-hook 'after-change-functions + #'isearch-read-with-highlight--after-change) + (remove-hook 'minibuffer-exit-hook #'isearch-read-with-highlight--exit) + (setq isearch-read-with-highlight--overlay nil) + (lazy-highlight-cleanup)) + +(defun isearch-read-with-highlight-setup () + "Set up minibuffer for lazy highlight of matches in the original window. + +This is intended to be called via `minibuffer-with-setup-hook'. +Note that several other isearch variables influence the lazy +highlighting, including `isearch-regexp' and +`isearch-lazy-count-display-function'." + (add-hook 'after-change-functions + #'isearch-read-with-highlight--after-change) + (add-hook 'minibuffer-exit-hook #'isearch-read-with-highlight--exit) + (setq isearch-read-with-highlight--overlay + (make-overlay (point-min) (point-min) (current-buffer) t t)) + (isearch-read-with-highlight--after-change nil nil nil)) + +(defun isearch-read-with-highlight-count () + "Display total match count in the minibuffer prompt." + (when isearch-read-with-highlight--overlay + (overlay-put isearch-read-with-highlight--overlay + 'before-string + (and isearch-lazy-count-total + (not isearch-error) + (format "%s " isearch-lazy-count-total))))) + + (defun isearch-resume (string regexp word forward message case-fold) "Resume an incremental search. STRING is the string or regexp searched for. -- 2.34.1