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, 09 Apr 2022 13:06:25 +0200 Message-ID: <877d7yqzwu.fsf@gmail.com> References: <87sftyweb2.fsf@gmail.com> <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> <87o81i5zzn.fsf@gmail.com> <86v8vo6c2k.fsf@mail.linkov.net> <87bkxfeb8j.fsf@gmail.com> <86wng3laj3.fsf@mail.linkov.net> <87r168g056.fsf@gmail.com> <86fsmohwe6.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="29717"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.1.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 Sat Apr 09 13:07:17 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 1nd8w1-0007WZ-BH for geb-bug-gnu-emacs@m.gmane-mx.org; Sat, 09 Apr 2022 13:07:17 +0200 Original-Received: from localhost ([::1]:58082 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nd8vz-0002kZ-Cs for geb-bug-gnu-emacs@m.gmane-mx.org; Sat, 09 Apr 2022 07:07:15 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:39292) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nd8vn-0002ha-Fz for bug-gnu-emacs@gnu.org; Sat, 09 Apr 2022 07:07:03 -0400 Original-Received: from debbugs.gnu.org ([209.51.188.43]:42924) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1nd8vn-0003kI-7j for bug-gnu-emacs@gnu.org; Sat, 09 Apr 2022 07:07:03 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1nd8vl-00012O-WD for bug-gnu-emacs@gnu.org; Sat, 09 Apr 2022 07:07: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: Sat, 09 Apr 2022 11:07:01 +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.16495023973953 (code B ref 53126); Sat, 09 Apr 2022 11:07:01 +0000 Original-Received: (at 53126) by debbugs.gnu.org; 9 Apr 2022 11:06:37 +0000 Original-Received: from localhost ([127.0.0.1]:36821 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nd8vM-00011g-Bb for submit@debbugs.gnu.org; Sat, 09 Apr 2022 07:06:37 -0400 Original-Received: from mail-ed1-f49.google.com ([209.85.208.49]:40520) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nd8vJ-00011T-K4 for 53126@debbugs.gnu.org; Sat, 09 Apr 2022 07:06:34 -0400 Original-Received: by mail-ed1-f49.google.com with SMTP id q26so12671623edc.7 for <53126@debbugs.gnu.org>; Sat, 09 Apr 2022 04:06:33 -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=uPutWSFQ3aPBEZfdU2zxt92lXpXb6DN7T0Uk+gEnlbw=; b=b0T4sZaCyo9djbkh8gW2KSpRKsTStu+vJLmQy9A7R785flLPMb/je1eu6TLq7OHVxv lGKl/T5IfqI4WNxSgv5E4XvK1veFZDh8E9novJ5Rezj7vUfWbCnrLRBVsDz7vJ79rTWe bU9htZVJkFL3z78pV0ehhtsTWQTkeW9AkiA/D57tIFgmwkA17lEG03weuStGZDumj6VI vm4Gbw5816tlW/oD/4cEDKmuZKH+LWqvB5Ts/+gLvTFhduGSkW+iK5XLuII6LSBecO/D RfJk0ws9yXiKczLwvz9pOh5EOM5Wxrr5RQ7F9k4EGFsn3rJKwGhKexJ9cVzwQyKvTHX/ TeUg== 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=uPutWSFQ3aPBEZfdU2zxt92lXpXb6DN7T0Uk+gEnlbw=; b=rmL7iYf+VxOlR+QTc54BpBFNCzicZkfDp6yDQOZ8M5kRssHpcW1r7YZVbZW2gGERMQ eDCB8PBIISR+uYn4zzQ9UjYAysAtiG7Et1O84jE34az1ve2+9YJ9gX2Ue3w0Uq7IDcJk W9+PNKelezsI1QM+dOkHx/JzJq7CtHnrCYym4Hh/pIB9FtEMbGQ7q2CcoJZe8jebZVYx xYe93ZJdNx714fm36+ZmgrEmyVej3rnF1ljxOISGimmFw/RgP2K3p/EhMxXDZfQjBuUB QCK1ahB7fXirqHBQC3FQl8aO38z6mSwSkOjiPPJuzZ73bAy6OEenp088dA5O18xBAyfr RDDA== X-Gm-Message-State: AOAM533F8c8c6D0K02aK3J2p/re3IWzEqI17NpQQ5f6NyK72FqD5DlzX ssfbCkIHtm1iWhF3P3r51+0o9pGF00Y= X-Google-Smtp-Source: ABdhPJweGRSE2kKIktQsN3TC9BZMZUTTkrLqERvZL2zrZ0eQDGwgFBrG1okycis8kb+SAW86oXQwBg== X-Received: by 2002:aa7:c948:0:b0:413:2bed:e82e with SMTP id h8-20020aa7c948000000b004132bede82emr23684520edt.394.1649502387335; Sat, 09 Apr 2022 04:06:27 -0700 (PDT) Original-Received: from ars3 ([2a02:8109:8ac0:56d0::7039]) by smtp.gmail.com with ESMTPSA id p9-20020a50c949000000b0041d180b8beesm2292625edh.48.2022.04.09.04.06.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 09 Apr 2022 04:06:26 -0700 (PDT) In-Reply-To: <86fsmohwe6.fsf@mail.linkov.net> (Juri Linkov's message of "Fri, 08 Apr 2022 10:32:41 +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:229611 Archived-At: --=-=-= Content-Type: text/plain On Fri, 8 Apr 2022 at 10:32, Juri Linkov wrote: >>> Looks good. >> >> Okay, I've refactored my code like this. I actually like it better that >> way. (As a downside, the stuff that was already merged to isearch.el is >> completely changed.) > > Thanks, now it looks much better! Please find attached the patches. --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-Rewrite-the-minibuffer-lazy-highlight-feature.patch >From 5ed0e5a850992c62189c0dc74ef98b892522d4df Mon Sep 17 00:00:00 2001 From: Augusto Stoffel Date: Sat, 9 Apr 2022 12:38:14 +0200 Subject: [PATCH 1/2] Rewrite the minibuffer lazy highlight feature The new API was discussed in bug#53126. It's more robust and easier to use in complex cases like that of 'query-replace'. * etc/NEWS: Amend the feature announcement * lisp/isearch.el (isearch-edit-string): Use new API. (minibuffer-lazy-highlight-transform, minibuffer-lazy-highlight--overlay, minibuffer-lazy-highlight--count, minibuffer-lazy-highlight--after-change, minibuffer-lazy-highlight--exit) Remove helper functions, which are now kept together with the lazy highlight configuration variables within a closure. (minibuffer-lazy-highlight-setup): This function now takes the lazy highlighting configuration variables as argument, and returns a closure that is intended to run as part of the minibuffer setup. --- etc/NEWS | 5 +- lisp/isearch.el | 148 ++++++++++++++++++++++++++++-------------------- 2 files changed, 88 insertions(+), 65 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index 2fac893cc5..2cddfcc8db 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1593,9 +1593,8 @@ the clipboard, and insert it into the buffer. --- ** New function 'minibuffer-lazy-highlight-setup'. -This function is intended to be added to 'minibuffer-setup-hook'. -It sets up the minibuffer for lazy highlighting of matches -in the original window. +This function allows to set up the minibuffer so that lazy +highlighting of its content is applied in the original window. +++ ** New text property 'inhibit-isearch'. diff --git a/lisp/isearch.el b/lisp/isearch.el index 956b115ce4..168d71ada3 100644 --- a/lisp/isearch.el +++ b/lisp/isearch.el @@ -1812,20 +1812,20 @@ isearch-edit-string (minibuffer-history-symbol) ;; Search string might have meta information on text properties. (minibuffer-allow-text-properties t)) - (when isearch-lazy-highlight - (add-hook 'minibuffer-setup-hook #'minibuffer-lazy-highlight-setup)) (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 + (minibuffer-lazy-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 ""))))) @@ -4361,57 +4361,81 @@ minibuffer-lazy-count-format :group 'lazy-count :version "29.1") -(defvar minibuffer-lazy-highlight-transform #'identity - "Function to transform minibuffer text into a `isearch-string' for highlighting.") - -(defvar minibuffer-lazy-highlight--overlay nil - "Overlay for minibuffer prompt updates.") - -(defun minibuffer-lazy-highlight--count () - "Display total match count in the minibuffer prompt." - (when minibuffer-lazy-highlight--overlay - (overlay-put minibuffer-lazy-highlight--overlay - 'before-string - (and isearch-lazy-count-total - (not isearch-error) - (format minibuffer-lazy-count-format - isearch-lazy-count-total))))) - -(defun minibuffer-lazy-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 minibuffer-lazy-highlight-transform string)) - (isearch-lazy-highlight-new-loop))))) - -(defun minibuffer-lazy-highlight--exit () - "Unwind changes from `minibuffer-lazy-highlight-setup'." - (remove-hook 'after-change-functions - #'minibuffer-lazy-highlight--after-change) - (remove-hook 'lazy-count-update-hook #'minibuffer-lazy-highlight--count) - (remove-hook 'minibuffer-exit-hook #'minibuffer-lazy-highlight--exit) - (setq minibuffer-lazy-highlight--overlay nil) - (when lazy-highlight-cleanup - (lazy-highlight-cleanup))) - -(defun minibuffer-lazy-highlight-setup () +(cl-defun minibuffer-lazy-highlight-setup + (&key (highlight isearch-lazy-highlight) + (cleanup lazy-highlight-cleanup) + (transform #'identity) + (filter nil) + (regexp isearch-regexp) + (regexp-function isearch-regexp-function) + (case-fold isearch-case-fold-search) + (lax-whitespace (if regexp + isearch-regexp-lax-whitespace + isearch-lax-whitespace))) "Set up minibuffer for lazy highlight of matches in the original window. -This function is intended to be added to `minibuffer-setup-hook'. -Note that several other isearch variables influence the lazy -highlighting, including `isearch-regexp', -`isearch-lazy-highlight' and `isearch-lazy-count'." - (remove-hook 'minibuffer-setup-hook #'minibuffer-lazy-highlight-setup) - (add-hook 'after-change-functions - #'minibuffer-lazy-highlight--after-change) - (add-hook 'lazy-count-update-hook #'minibuffer-lazy-highlight--count) - (add-hook 'minibuffer-exit-hook #'minibuffer-lazy-highlight--exit) - (setq minibuffer-lazy-highlight--overlay - (and minibuffer-lazy-count-format - (make-overlay (point-min) (point-min) (current-buffer) t))) - (minibuffer-lazy-highlight--after-change nil nil nil)) +This function return a closure intended to be added to +`minibuffer-setup-hook'. It accepts the following keyword +arguments, all of which have a default based on the current +isearch settings. + +HIGHLIGHT: Whether to perform lazy highlight. +CLEANUP: Whether to clean up the lazy highlight when the minibuffer +exits. +TRANSFORM: A function taking one argument, the minibuffer contents, +and returning the `isearch-string' to use for lazy highlighting. +FILTER: A function to add to `isearch-filter-predicate'. +REGEXP: The value of `isearch-regexp' to use for lazy highlighting. +REGEXP-FUNCTION: The value of `isearch-regexp-function' to use for +lazy highlighting. +CASE-FOLD: The value of `isearch-case-fold' to use for lazy +highlighting. +LAX-WHITESPACE: The value of `isearch-lax-whitespace' and +`isearch-regexp-lax-whitespace' to use for lazy highlighting." + (if (not highlight) + #'ignore + (let ((unwind (make-symbol "minibuffer-lazy-highlight--unwind")) + (after-change (make-symbol "minibuffer-lazy-highlight--after-change")) + (display-count (make-symbol "minibuffer-lazy-highlight--display-count")) + overlay) + (fset unwind + (lambda () + (remove-function isearch-filter-predicate filter) + (remove-hook 'lazy-count-update-hook display-count) + (when overlay (delete-overlay overlay)) + (remove-hook 'after-change-functions after-change) + (remove-hook 'minibuffer-exit-hook unwind) + (let ((lazy-highlight-cleanup cleanup)) + (lazy-highlight-cleanup)))) + (fset after-change + (lambda (_beg _end _len) + (let ((inhibit-redisplay t) ;; Avoid cursor flickering + (string (minibuffer-contents))) + (with-minibuffer-selected-window + (let* ((isearch-forward t) + (isearch-regexp regexp) + (isearch-regexp-function regexp-function) + (isearch-case-fold-search case-fold) + (isearch-lax-whitespace lax-whitespace) + (isearch-regexp-lax-whitespace lax-whitespace) + (isearch-string (funcall transform string))) + (isearch-lazy-highlight-new-loop)))))) + (fset display-count + (lambda () + (overlay-put overlay 'before-string + (and isearch-lazy-count-total + (not isearch-error) + (format minibuffer-lazy-count-format + isearch-lazy-count-total))))) + (lambda () + (add-hook 'minibuffer-exit-hook unwind) + (add-hook 'after-change-functions after-change) + (when minibuffer-lazy-count-format + (setq overlay (make-overlay (point-min) (point-min) (current-buffer) t)) + (add-hook 'lazy-count-update-hook display-count)) + (when filter + (add-function :after-while isearch-filter-predicate filter)) + (funcall after-change nil nil nil))))) (defun isearch-resume (string regexp word forward message case-fold) -- 2.35.1 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0002-Add-lazy-highlight-when-reading-query-replace-argume.patch >From 432fcd0172a538713d85e3d4a64c2586ae1a9a5b Mon Sep 17 00:00:00 2001 From: Augusto Stoffel Date: Sat, 9 Apr 2022 12:47:28 +0200 Subject: [PATCH 2/2] Add lazy highlight when reading 'query-replace' arguments * lisp/replace.el (query-replace-read-args): Use 'minibuffer-lazy-highlight-setup' to highlight the text to be replaced in the original buffer (and a match count, if applicable). (replace--region-filter): New function for code that used to be inlined in perform-replace but is useful elsewhere. (perform-replace): Use 'replace--region-filter'. --- lisp/replace.el | 65 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 47 insertions(+), 18 deletions(-) diff --git a/lisp/replace.el b/lisp/replace.el index e6f565d802..00d30d1e38 100644 --- a/lisp/replace.el +++ b/lisp/replace.el @@ -365,11 +365,33 @@ 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* ((delimited-flag (and current-prefix-arg + (not (eq current-prefix-arg '-)))) + (from (minibuffer-with-setup-hook + (minibuffer-lazy-highlight-setup + :case-fold case-fold-search + :filter (when (use-region-p) + (replace--region-filter + (funcall region-extract-function 'bounds))) + :highlight query-replace-lazy-highlight + :regexp regexp-flag + :regexp-function (or replace-regexp-function + delimited-flag + (and replace-char-fold + (not regexp-flag) + #'char-fold-to-regexp)) + :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 - (or (and current-prefix-arg (not (eq current-prefix-arg '-))) + (or delimited-flag (and (plist-member (text-properties-at 0 from) 'isearch-regexp-function) (get-text-property 0 'isearch-regexp-function from))) (and current-prefix-arg (eq current-prefix-arg '-)))))) @@ -2778,6 +2800,26 @@ replace--push-stack ,search-str ,next-replace) ,stack)) +(defun replace--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 perform-replace (from-string replacements query-flag regexp-flag delimited-flag &optional repeat-count map start end backward region-noncontiguous-p) @@ -2862,22 +2904,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 (replace--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 > In `isearch-edit-string' you replaced: > (add-hook 'minibuffer-setup-hook #'minibuffer-lazy-highlight-setup) > with > (minibuffer-with-setup-hook (minibuffer-lazy-highlight-setup) > but the docstring of `minibuffer-lazy-highlight-setup' in your patch is: > > This function return a closure intended to be added to > `minibuffer-setup-hook'. > > Maybe either a typo that needs to mention `minibuffer-with-setup-hook', > or `minibuffer-setup-hook' needs to evaluate such closure with something like > > (add-hook 'minibuffer-setup-hook (funcall 'minibuffer-lazy-highlight-setup)) > > But since this is more ugly, then using `minibuffer-with-setup-hook' is fine. > Well, as a matter of fact the closure is meant to run in the 'minibuffer-setup-hook'. This is not to say it's a good idea to use 'add-hook' to do add it there. One should always use 'minibuffer-with-setup-hook' for that kind of stuff, I guess. Feel free to copy edit the docstring, but in light of the above I didn't change it for now. >>> Shouldn't both cases clean up highlight from the buffer? >>> Then I see no need to distinguish each case. Or if really needed, >>> you can try to bind the cleanup to command-error-function. >> >> My previous patch had only one case: if the user quits, we clean up the >> highlighting. >> >> I can only see one simpler alternative, which is to always >> unconditionally clean up the highlight. This is not as nice, but if >> keeping the code as simple as possible is important here, then I guess >> this is the way forward. So that's what the current patch does. >> >> I suspect people will see this as a bug, but maybe discussing this issue >> by itself later will be easier. > > Yep, let's do this later when people will ask for it. All right, I've removed all the "clever business" related to delayed clean up of the lazy highlight for now. >>> 4 lines look nice, unlike 20 lines in one of your patches ;-) >> >> When you add all the bells and whistles, 4 lines just won't do it. > > Now the parameters of minibuffer-lazy-highlight-setup look nice, > so line count doesn't matter when code keeps simplicity. So, my sample code from the previous message defined a function for this snippet which already repeats 3 times (or replace-regexp-function delimited-flag (and replace-char-fold (not regexp-flag) #'char-fold-to-regexp)) I've removed that function for now. We can reintroduce the function if you deem it helpful. --=-=-=--