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: Sun, 03 Apr 2022 10:32:12 +0200 Message-ID: <87o81i5zzn.fsf@gmail.com> References: <87sftyweb2.fsf@gmail.com> <87o84jcx5x.fsf@gmail.com> <8635lvif0r.fsf@mail.linkov.net> <87mtidip1w.fsf@gmail.com> <86zglrl4gq.fsf@mail.linkov.net> <87ee32yk7v.fsf@gmail.com> <861qz1zqfb.fsf@mail.linkov.net> <875yod1wyb.fsf@gmail.com> <86mtho5y56.fsf@mail.linkov.net> <87sfrgz979.fsf@gmail.com> <861qz0475w.fsf@mail.linkov.net> <87sfrd2cbb.fsf@gmail.com> <86fsnc4fvm.fsf@mail.linkov.net> <878rsz6um2.fsf@gmail.com> <86ils2mmbe.fsf@mail.linkov.net> <87v8w2qsee.fsf@gmail.com> <86y20vu9c6.fsf@mail.linkov.net> <875ynt41g9.fsf@gmail.com> <86pmm1azkd.fsf@mail.linkov.net> <87a6d43c6n.fsf@gmail.com> <86r16fz6bw.fsf@mail.linkov.net> 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="23710"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (gnu/linux) Cc: 53126@debbugs.gnu.org To: Juri Linkov Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Sun Apr 03 10:33:20 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 1navfk-0005yE-BD for geb-bug-gnu-emacs@m.gmane-mx.org; Sun, 03 Apr 2022 10:33:20 +0200 Original-Received: from localhost ([::1]:58616 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1navfj-0005W7-32 for geb-bug-gnu-emacs@m.gmane-mx.org; Sun, 03 Apr 2022 04:33:19 -0400 Original-Received: from eggs.gnu.org ([209.51.188.92]:58678) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1navfT-0005Vi-G5 for bug-gnu-emacs@gnu.org; Sun, 03 Apr 2022 04:33:03 -0400 Original-Received: from debbugs.gnu.org ([209.51.188.43]:53648) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1navfS-0007fX-4t for bug-gnu-emacs@gnu.org; Sun, 03 Apr 2022 04:33:03 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1navfS-00018R-24 for bug-gnu-emacs@gnu.org; Sun, 03 Apr 2022 04:33:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Augusto Stoffel Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sun, 03 Apr 2022 08:33:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 53126 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch Original-Received: via spool by 53126-submit@debbugs.gnu.org id=B53126.16489747444296 (code B ref 53126); Sun, 03 Apr 2022 08:33:02 +0000 Original-Received: (at 53126) by debbugs.gnu.org; 3 Apr 2022 08:32:24 +0000 Original-Received: from localhost ([127.0.0.1]:47540 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1navep-00017D-B5 for submit@debbugs.gnu.org; Sun, 03 Apr 2022 04:32:23 -0400 Original-Received: from mail-ej1-f47.google.com ([209.85.218.47]:38878) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1navem-000170-VN for 53126@debbugs.gnu.org; Sun, 03 Apr 2022 04:32:21 -0400 Original-Received: by mail-ej1-f47.google.com with SMTP id r13so14117625ejd.5 for <53126@debbugs.gnu.org>; Sun, 03 Apr 2022 01:32:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:references:date:in-reply-to:message-id :user-agent:mime-version; bh=8X/vCn0D8Z2qVTOdEgPygKb+soSA0PF0WGiHXG528Uk=; b=GkhroTHXUklvWOba311InENILT5W7z/GkpD2bSz+I8hfZdHV3kK0eP0U0VBmmkUSrj SisZKBi/6yIiBG7Mi1hcipVsmnQ+om5VBYchUUW7+DO3YWPSl4B3kwaRNvqfJ01NQEr1 6nyKqHpuNfVBBVdITKJ2DOxN80m9f/YPADLwKK/8o3bez52N0vsU2arAKHxDAKkQl3+0 tR5LAyxFWWPpbTK3J0d4QAlm1UjdewOBZWlfKqtDYHxJS8bBqdu+cutua8Eii/l6FCrv 3SZ9kiY7jov6bTJX7ng3ALwROPEn5b4bWZm+/q+zF5LfzQaiGdvjdBBIeStmjx8wmnmS kXqw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:references:date:in-reply-to :message-id:user-agent:mime-version; bh=8X/vCn0D8Z2qVTOdEgPygKb+soSA0PF0WGiHXG528Uk=; b=q9KpYUD43i7d+VuT0cYTVWpQt6iZgXRlJAj9fWbqrcVRWcTkv9zB2oTMlM1yfWRD6C DUa9tBi53cVk4MmOoiRfCRiSB/x2/h4lOot4Kw1/G4TPrlKXesLFeyTb9gTouOQ/Benp FKpntHdGuMls00jRyhMd0Av0ybiBZB/mZqHrTQwaurSmeWYair8W1//pwpbGJq5A200u scMURZIIiU0LUEnVsiMzVTu+mEaZV0QzDYQOXs9MltOd9lWV/5Ho5khT1ie6btKZTrXE iq79F/nR1DtPmTZSMOUOQrQ702ziBs8ziLzNX3xOPPiQ4+8HoStTo+bdZv9W42as0o7D bk8w== X-Gm-Message-State: AOAM530AM7qfkkLbHKpuL/jkU5ZFFUJVOovnfo2P4UQ0XpzqAoGpf027 m/3dive6S5Gzp0BQvaZV/taaHovXqQo= X-Google-Smtp-Source: ABdhPJyYjAGx9YE8ESK7YvjSqY0hd/MMxRUeJ4+M5E1YUydc3xvf65l1wd1B27u6V1Wnk/oQAUYP0w== X-Received: by 2002:a17:907:3f29:b0:6df:7eac:7fa4 with SMTP id hq41-20020a1709073f2900b006df7eac7fa4mr6421577ejc.391.1648974734580; Sun, 03 Apr 2022 01:32:14 -0700 (PDT) Original-Received: from ars3 ([2a02:8109:8ac0:56d0::7039]) by smtp.gmail.com with ESMTPSA id t1-20020a170906178100b006e7edb2c0bdsm315332eje.15.2022.04.03.01.32.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 03 Apr 2022 01:32:13 -0700 (PDT) In-Reply-To: <86r16fz6bw.fsf@mail.linkov.net> (Juri Linkov's message of "Sat, 02 Apr 2022 21:23:10 +0300") 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:229319 Archived-At: --=-=-= Content-Type: text/plain I've attached a sketch of a macro to help activating the minibuffer lazy highlight. It doesn't make query-replace-read-args exactly short, but if you like this, I can prepare the patch. Note that I haven't tested this code at all. It's for impressionistic purposes only. --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-Display-lazy-highlight-and-match-count-in-query-repl.patch >From 92394967d27bb2750a88a19951182d1465b57040 Mon Sep 17 00:00:00 2001 From: Augusto Stoffel Date: Thu, 17 Mar 2022 20:17:26 +0100 Subject: [PATCH] Display lazy highlight and match count in query-replace * lisp/isearch.el (isearch-query-replace): Don't clean up lazy highlight if applicable. * lisp/replace.el (query-replace-read-args, query-replace-read-to): Add lazy highlighting and count. (replace--region-filter): New function, extracted from 'perform-replace'. (perform-replace): Use 'replace--region-filter'. --- lisp/isearch.el | 65 +++++++++++++++++++++++++++++++++++++++++++------ lisp/replace.el | 49 +++++++++++++++++++++++-------------- 2 files changed, 88 insertions(+), 26 deletions(-) diff --git a/lisp/isearch.el b/lisp/isearch.el index 956b115ce4..b28a7b88a8 100644 --- a/lisp/isearch.el +++ b/lisp/isearch.el @@ -2352,7 +2352,9 @@ isearch-query-replace (isearch-recursive-edit nil) (isearch-string-propertized (isearch-string-propertize isearch-string))) - (isearch-done nil t) + (let ((lazy-highlight-cleanup (and lazy-highlight-cleanup + (not query-replace-lazy-highlight)))) + (isearch-done nil t)) (isearch-clean-overlays) (if (and isearch-other-end (if backward @@ -2368,13 +2370,16 @@ isearch-query-replace (symbol-value query-replace-from-history-variable))) (perform-replace isearch-string-propertized - (query-replace-read-to - isearch-string-propertized - (concat "Query replace" - (isearch--describe-regexp-mode (or delimited isearch-regexp-function) t) - (if backward " backward" "") - (if (use-region-p) " in region" "")) - isearch-regexp) + (condition-case error + (query-replace-read-to + isearch-string-propertized + (concat "Query replace" + (isearch--describe-regexp-mode (or delimited isearch-regexp-function) t) + (if backward " backward" "") + (if (use-region-p) " in region" "")) + isearch-regexp) + (t (lazy-highlight-cleanup lazy-highlight-cleanup) + (signal (car error) (cdr error)))) t isearch-regexp (or delimited isearch-regexp-function) nil nil (if (use-region-p) (region-beginning)) (if (use-region-p) (region-end)) @@ -4413,6 +4418,50 @@ minibuffer-lazy-highlight-setup (make-overlay (point-min) (point-min) (current-buffer) t))) (minibuffer-lazy-highlight--after-change nil nil nil)) +(cl-defmacro with-minibuffer-lazy-highlight (lazy-highlight &rest body &keys (regexp 'unset) (regexp-function 'unset) (case-fold 'unset) (cleanup 'unset) (region 'unset) (transform 'unset)) + (while (keywordp (car body) (setq body (cddr body)))) + `(let ((isearch-lazy-highlight ,lazy-highlight) + ,@(unless (eq 'unset ,case-fold) `(isearch-case-fold-search ,case-fold)) + ,@(unless (eq 'unset ,regexp) `(isearch-regexp ,regexp)) + ,@(unless (eq 'unset ,regexp-function) `(isearch-regexp-function ,regexp-function)) + ,@(unless (eq 'unset ,cleanup) `(lazy-highlight-cleanup ,cleanup)) + ,@(unless (eq 'unset ,transform )`(minibuffer-lazy-highlight-transform ,transform))) + (when isearch-lazy-highlight + (add-hook 'minibuffer-setup-hook #'minibuffer-lazy-highlight-setup) + (when ,region + (letrec ((region-filter (isearch-region-filter + (funcall region-extract-function ,region))) + (cleanup (lambda () + (remove-function isearch-filter-predicate region-filter) + (remove-hook 'minibuffer-exit-hook cleanup)))) + (add-function :after-while isearch-filter-predicate region-filter) + (add-hook 'minibuffer-exit-hook cleanup)))) + (condition-case error + (progn ,@body) + (t (lazy-highlight-cleanup) + (signal (car error) (cdr error)))))) + +(defun isearch-region-filter (bounds) + "Return a function that decides if a region is inside BOUNDS. +BOUNDS is a list of cons cells of the form (START . END). The +returned function takes as argument two buffer positions, START +and END." + (let ((region-bounds + (mapcar (lambda (position) + (cons (copy-marker (car position)) + (copy-marker (cdr position)))) + bounds))) + (lambda (start end) + (delq nil (mapcar + (lambda (bounds) + (and + (>= start (car bounds)) + (<= start (cdr bounds)) + (>= end (car bounds)) + (<= end (cdr bounds)))) + region-bounds))))) + + (defun isearch-resume (string regexp word forward message case-fold) "Resume an incremental search. diff --git a/lisp/replace.el b/lisp/replace.el index e6f565d802..bed4a2824d 100644 --- a/lisp/replace.el +++ b/lisp/replace.el @@ -352,8 +352,15 @@ query-replace-read-to (query-replace-compile-replacement (save-excursion (let* ((history-add-new-input nil) + (count (if (and query-replace-lazy-highlight + minibuffer-lazy-count-format + isearch-lazy-count + isearch-lazy-count-total) + (format minibuffer-lazy-count-format + isearch-lazy-count-total) + "")) (to (read-from-minibuffer - (format "%s %s with: " prompt (query-replace-descr from)) + (format "%s%s %s with: " count prompt (query-replace-descr from)) nil nil nil query-replace-to-history-variable from t))) (add-to-history query-replace-to-history-variable to nil t) @@ -365,7 +372,26 @@ query-replace-read-args (unless noerror (barf-if-buffer-read-only)) (save-mark-and-excursion - (let* ((from (query-replace-read-from prompt regexp-flag)) + (let* ((from (with-minibuffer-lazy-highlight + query-replace-lazy-highlight + :case-fold case-fold-search + :regexp regexp-flag + :regexp-function (or replace-regexp-function + (and current-prefix-arg + (not (eq current-prefix-arg '-))) + (and replace-char-fold + (not regexp-flag) + #'char-fold-to-regexp))) + :cleanup nil + :transform (minibuffer-lazy-highlight-transform + (lambda (string) + (let* ((split (query-replace--split-string string)) + (from-string (if (consp split) (car split) split))) + (when (and case-fold-search search-upper-case) + (setq isearch-case-fold-search + (isearch-no-upper-case-p from-string regexp-flag))) + from-string))) + (query-replace-read-from prompt regexp-flag)) (to (if (consp from) (prog1 (cdr from) (setq from (car from))) (query-replace-read-to from prompt regexp-flag)))) (list from to @@ -2862,22 +2888,9 @@ perform-replace ;; Unless a single contiguous chunk is selected, operate on multiple chunks. (when region-noncontiguous-p - (let ((region-bounds - (mapcar (lambda (position) - (cons (copy-marker (car position)) - (copy-marker (cdr position)))) - (funcall region-extract-function 'bounds)))) - (setq region-filter - (lambda (start end) - (delq nil (mapcar - (lambda (bounds) - (and - (>= start (car bounds)) - (<= start (cdr bounds)) - (>= end (car bounds)) - (<= end (cdr bounds)))) - region-bounds)))) - (add-function :after-while isearch-filter-predicate region-filter))) + (setq region-filter (isearch-region-filter + (funcall region-extract-function 'bounds))) + (add-function :after-while isearch-filter-predicate region-filter)) ;; If region is active, in Transient Mark mode, operate on region. (if backward -- 2.35.1 --=-=-= Content-Type: text/plain Below a response to your last message. On Sat, 2 Apr 2022 at 21:23, Juri Linkov wrote: >> - The value of case-fold-search can change on the fly > > Please clarify when it can be changed on the fly. I refer to the following lines of my patch, which are necessary. (when (and case-fold-search search-upper-case) (setq isearch-case-fold-search (isearch-no-upper-case-p from-string regexp-flag))) (Incidentally, I like better the ripgrep smart case, where an uppercase character only matches itself, and lowercase characters match both upper and lower case.) >> I'm referring to the anzu feature whereby the replacement text is shown >> next to each match, like this: >> >> This will not be totally trivial to implement, right? And it will add >> some extra stuff to query-replace-read-args that is very much >> query-replace specific. > > I very much doubt in usefulness of such a feature. I thought it could > simply highlight the replacement text to show the places in the buffer > that already contain such replacement text. The anzu thing is only really meaningful if you are doing some complex replacements with \, and whatnot. But in that case, I guess it could help a lot? --=-=-=--