From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Augusto Stoffel Newsgroups: gmane.emacs.bugs Subject: bug#53126: 29.0.50; [PATCH] Lazy highlight/count when reading query-replace string, etc. Date: Sat, 08 Jan 2022 14:24:33 +0100 Message-ID: <87sftyweb2.fsf@gmail.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="10474"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (gnu/linux) To: 53126@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Sat Jan 08 14:26:03 2022 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1n6BjP-0002aJ-1N for geb-bug-gnu-emacs@m.gmane-mx.org; Sat, 08 Jan 2022 14:26:03 +0100 Original-Received: from localhost ([::1]:44976 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1n6BjN-00088y-Uf for geb-bug-gnu-emacs@m.gmane-mx.org; Sat, 08 Jan 2022 08:26:01 -0500 Original-Received: from eggs.gnu.org ([209.51.188.92]:58056) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1n6BiQ-00086O-Ph for bug-gnu-emacs@gnu.org; Sat, 08 Jan 2022 08:25:02 -0500 Original-Received: from debbugs.gnu.org ([209.51.188.43]:53684) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1n6BiQ-0002tl-Ak for bug-gnu-emacs@gnu.org; Sat, 08 Jan 2022 08:25:02 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1n6BiQ-0004zH-34 for bug-gnu-emacs@gnu.org; Sat, 08 Jan 2022 08:25:02 -0500 X-Loop: help-debbugs@gnu.org Resent-From: Augusto Stoffel Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sat, 08 Jan 2022 13:25:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 53126 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch X-Debbugs-Original-To: bug-gnu-emacs@gnu.org Original-Received: via spool by submit@debbugs.gnu.org id=B.164164828519136 (code B ref -1); Sat, 08 Jan 2022 13:25:01 +0000 Original-Received: (at submit) by debbugs.gnu.org; 8 Jan 2022 13:24:45 +0000 Original-Received: from localhost ([127.0.0.1]:46587 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1n6Bi8-0004yY-Dz for submit@debbugs.gnu.org; Sat, 08 Jan 2022 08:24:45 -0500 Original-Received: from lists.gnu.org ([209.51.188.17]:46044) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1n6Bi4-0004yN-Ov for submit@debbugs.gnu.org; Sat, 08 Jan 2022 08:24:43 -0500 Original-Received: from eggs.gnu.org ([209.51.188.92]:58020) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1n6Bi4-0007js-K3 for bug-gnu-emacs@gnu.org; Sat, 08 Jan 2022 08:24:40 -0500 Original-Received: from [2a00:1450:4864:20::334] (port=51722 helo=mail-wm1-x334.google.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1n6Bi2-0002sV-Ah for bug-gnu-emacs@gnu.org; Sat, 08 Jan 2022 08:24:40 -0500 Original-Received: by mail-wm1-x334.google.com with SMTP id e5so5728044wmq.1 for ; Sat, 08 Jan 2022 05:24:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:subject:date:message-id:user-agent:mime-version; bh=SgV5AddMxwLgFwrCpf68eS9aqAcUfGRMfInRKJRQ35g=; b=XFKlAWhHxo1vg4rIA6TQ3+gA6EOvf99uTYo06EY4vu2Aoi+IWqtktYZtCdxhA2ZNae AWq3N5iG6HxjkErhVuZFF+FXX5Wbv3gUy79tql1Fry7oNOOl7XgGg07f69+Mf2Jieuja HkE2m0Fa0uX7B1wBelWMD+O3Y/5fsXrgnzbx2rHHnuGRzZE3r9MF67gLN3bcwJyHeY9w z9HB8Ab1WFkkusIXAP4rtdnwedT5ZZnvtjZ1+/w133B6i0EndohqsCntDe3ReyJ1yj0h 1hGXDMJTJUwqlnIR2XBAIbAARdgX08tPV4y+ohb8soMf9WJYA5OLxgIeZ5F9Vlc5nwqQ Tagg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:user-agent :mime-version; bh=SgV5AddMxwLgFwrCpf68eS9aqAcUfGRMfInRKJRQ35g=; b=xkNaid8TjdjCLOJlPOLR2ZjUl7bXXqdh/YOnSicxQFCorC9Ho19qOtdFm/71Mj84ZJ scbv4EZ7ABM1+y7yhUN0AWBPFNDyBFABR30ebu5sNJgWQgLTwLDQATeOPXclk0zvsyob 94PQNAvisthd68Z/h8XjdFusd1/z9Cig4mZvf3nn+o4nsPRl6W9JEyQfMzGistrEdoQH liB4YJPTgQgx2BpWsVUYb4bcuP4hL90z9/dv60CUG2bEMgRmQ/7349sPTiYt5FH7xQDS m4bWmyO0LREJ/vHcXU9wFCwFoTI/vOGjo1P12QVmIDbPSQIB27MO2xRu8JCH+/O85E8T bHcw== X-Gm-Message-State: AOAM533A7HjEfRRM1V9N1sjIC/JiYt+xOsUx3JI7GK/uxdgPmpor7XRf b1WLY3IFwjja0gZojc2P9ducA0JGRS8= X-Google-Smtp-Source: ABdhPJyRswlDYINO1Gc7brHFbkCAi6yJHCIAh0kJa5Pvl3ypSVLGG5bEEeALM7c9a5xjJIdR/OmCSg== X-Received: by 2002:a1c:740c:: with SMTP id p12mr14642787wmc.140.1641648275461; Sat, 08 Jan 2022 05:24:35 -0800 (PST) Original-Received: from ars3 ([2a02:8109:8ac0:56d0::b4b9]) by smtp.gmail.com with ESMTPSA id r19sm730999wmh.42.2022.01.08.05.24.34 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Jan 2022 05:24:34 -0800 (PST) X-Host-Lookup-Failed: Reverse DNS lookup failed for 2a00:1450:4864:20::334 (failed) Received-SPF: pass client-ip=2a00:1450:4864:20::334; envelope-from=arstoffel@gmail.com; helo=mail-wm1-x334.google.com X-Spam_score_int: -12 X-Spam_score: -1.3 X-Spam_bar: - X-Spam_report: (-1.3 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, RDNS_NONE=0.793, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.io gmane.emacs.bugs:223818 Archived-At: --=-=-= Content-Type: text/plain The anzu package was mentioned recently in the mailing list. Emacs now includes the lazy-count feature, which is the main purpose of anzu, but it's still missing one nice feature from that package, namely the highlighting and count of matches as one types a regexp or string to replace in `query-replace{-regexp}'. See the below patch for a (probably not yet mature) stab at this. I've also added lazy highlighting to the `isearch-edit-string' command. I didn't introduce any new customization variables. Lazy highlighting in both `query-replace{-regexp}' and `isearch-edit-string' is controlled by `isearch-lazy-highlight' (therefore is on by default) and lazy count next to the minibuffer prompt is controlled by `isearch-lazy-count' (therefore off by default). I believe the problems pointed out in a previous iteration of this in https://lists.gnu.org/archive/html/emacs-devel/2021-05/msg01196.html are now solved. --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-Allow-reading-from-minibuffer-with-lazy-highlight-an.patch >From 11e52a1bf1adb2a15dda3097d6c6016034ae4487 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/comint.el | 2 ++ lisp/isearch.el | 91 +++++++++++++++++++++++++++++++++++++++---------- lisp/simple.el | 1 + 3 files changed, 76 insertions(+), 18 deletions(-) diff --git a/lisp/comint.el b/lisp/comint.el index fdea3e33bb..c1695bbbdf 100644 --- a/lisp/comint.el +++ b/lisp/comint.el @@ -1515,6 +1515,7 @@ comint-history-isearch-setup #'comint-history-isearch-wrap) (setq-local isearch-push-state-function #'comint-history-isearch-push-state) + (setq-local isearch-lazy-count-display-function nil) (add-hook 'isearch-mode-end-hook 'comint-history-isearch-end nil t))) (defun comint-history-isearch-end () @@ -1526,6 +1527,7 @@ comint-history-isearch-end (setq isearch-message-function nil) (setq isearch-wrap-function nil) (setq isearch-push-state-function nil) + (setq-local isearch-lazy-count-display-function #'isearch-message) (remove-hook 'isearch-mode-end-hook 'comint-history-isearch-end t) (unless isearch-suspended (custom-reevaluate-setting 'comint-history-isearch))) diff --git a/lisp/isearch.el b/lisp/isearch.el index 7593a0ec98..ccb06d534e 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 #'isearch-message + "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 (and isearch-lazy-count isearch-lazy-count-display-function) (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,8 @@ 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 "") + (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 +4101,13 @@ 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 (and isearch-lazy-count isearch-lazy-count-display-function) ;; 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)))) + (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 +4308,65 @@ isearch-lazy-highlight-buffer-update (setq looping nil nomore t)))) (if nomore - (when (and isearch-lazy-count isearch-mode (null isearch-message-function)) + (when (and isearch-lazy-count isearch-lazy-count-display-function) (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)) + (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. diff --git a/lisp/simple.el b/lisp/simple.el index 070d2764fe..ecf07b912d 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -2787,6 +2787,7 @@ minibuffer-history-isearch-setup #'minibuffer-history-isearch-wrap) (setq-local isearch-push-state-function #'minibuffer-history-isearch-push-state) + (setq-local isearch-lazy-count-display-function nil) (add-hook 'isearch-mode-end-hook 'minibuffer-history-isearch-end nil t)) (defun minibuffer-history-isearch-end () -- 2.33.1 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0002-Lazy-highlight-when-reading-query-replace-text.patch >From 6d9ec412addfc450f63487de0d90a1076cab47a0 Mon Sep 17 00:00:00 2001 From: Augusto Stoffel Date: Sat, 8 Jan 2022 13:15:40 +0100 Subject: [PATCH 2/2] Lazy highlight when reading query-replace text * lisp/replace.el (query-replace-read-from): Add lazy highlighting. --- lisp/replace.el | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lisp/replace.el b/lisp/replace.el index 60e507c642..241a97a3a2 100644 --- a/lisp/replace.el +++ b/lisp/replace.el @@ -244,6 +244,17 @@ query-replace-read-from (query-replace-descr (cdar query-replace-defaults))))) (t (format-prompt prompt nil)))) + ;; Set up lazy highlighting while reading FROM regexp + (isearch-lazy-highlight query-replace-highlight) + (isearch-regexp regexp-flag) + (isearch-regexp-function nil) + (isearch-case-fold-search case-fold-search) ;; TODO: the case-folding rule here is complicated... + (isearch-read-with-highlight-transform + (lambda (string) + (let ((from (query-replace--split-string string))) + (if (consp from) (car from) from)))) + (isearch-lazy-count-display-function + #'isearch-read-with-highlight-count) (from ;; The save-excursion here is in case the user marks and copies ;; a region in order to specify the minibuffer input. @@ -251,6 +262,7 @@ query-replace-read-from (save-excursion (minibuffer-with-setup-hook (lambda () + (isearch-read-with-highlight-setup) (setq-local text-property-default-nonsticky (append '((separator . t) (face . t)) text-property-default-nonsticky))) -- 2.33.1 --=-=-=--