From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Juri Linkov Newsgroups: gmane.emacs.bugs Subject: bug#29360: 26.0; Add full-buffer choice for `isearch-lazy-highlight' Date: Thu, 25 Oct 2018 02:11:25 +0300 Organization: LINKOV.NET Message-ID: <87sh0vaqjm.fsf@mail.linkov.net> References: <7ec3c778-ee77-48c9-ba10-f21202cac955@default> <87shd8lli4.fsf@mail.linkov.net> <36f5e57c-2eb3-45eb-ae43-3f8fdf7586dd@default> <60f1b355-7455-4bb9-ae3d-294e1494a9d9@default> <87va5yhpaq.fsf@mail.linkov.net> <875zxwjlke.fsf@mail.linkov.net> <87woqbglvb.fsf@mail.linkov.net> <76121a16-e057-4aa7-9a5a-1f09cc221d7c@default> <87efcguxnm.fsf@mail.linkov.net> <3818ac4c-6564-4439-9fb5-c84791f43f7a@default> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: blaine.gmane.org 1540424653 31038 195.159.176.226 (24 Oct 2018 23:44:13 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Wed, 24 Oct 2018 23:44:13 +0000 (UTC) User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.0.50 (x86_64-pc-linux-gnu) Cc: 29360@debbugs.gnu.org To: Drew Adams Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Thu Oct 25 01:44:09 2018 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1gFSoq-0007wQ-7p for geb-bug-gnu-emacs@m.gmane.org; Thu, 25 Oct 2018 01:44:08 +0200 Original-Received: from localhost ([::1]:51125 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gFSqw-0004q7-Aw for geb-bug-gnu-emacs@m.gmane.org; Wed, 24 Oct 2018 19:46:18 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:43950) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gFSqj-0004pC-NZ for bug-gnu-emacs@gnu.org; Wed, 24 Oct 2018 19:46:07 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gFSqg-0001sC-GT for bug-gnu-emacs@gnu.org; Wed, 24 Oct 2018 19:46:05 -0400 Original-Received: from debbugs.gnu.org ([208.118.235.43]:36769) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1gFSqg-0001s3-9N for bug-gnu-emacs@gnu.org; Wed, 24 Oct 2018 19:46:02 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1gFSqg-0001ao-6R for bug-gnu-emacs@gnu.org; Wed, 24 Oct 2018 19:46:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Juri Linkov Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Wed, 24 Oct 2018 23:46:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 29360 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: Original-Received: via spool by 29360-submit@debbugs.gnu.org id=B29360.15404247586101 (code B ref 29360); Wed, 24 Oct 2018 23:46:02 +0000 Original-Received: (at 29360) by debbugs.gnu.org; 24 Oct 2018 23:45:58 +0000 Original-Received: from localhost ([127.0.0.1]:41025 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1gFSqb-0001aL-OI for submit@debbugs.gnu.org; Wed, 24 Oct 2018 19:45:58 -0400 Original-Received: from bonobo.maple.relay.mailchannels.net ([23.83.214.22]:12445) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1gFSqZ-0001aB-1m for 29360@debbugs.gnu.org; Wed, 24 Oct 2018 19:45:56 -0400 X-Sender-Id: dreamhost|x-authsender|jurta@jurta.org Original-Received: from relay.mailchannels.net (localhost [127.0.0.1]) by relay.mailchannels.net (Postfix) with ESMTP id A47875E3610; Wed, 24 Oct 2018 23:45:53 +0000 (UTC) Original-Received: from pdx1-sub0-mail-a38.g.dreamhost.com (unknown [100.96.16.121]) (Authenticated sender: dreamhost) by relay.mailchannels.net (Postfix) with ESMTPA id 5C12B5E364A; Wed, 24 Oct 2018 23:45:53 +0000 (UTC) X-Sender-Id: dreamhost|x-authsender|jurta@jurta.org Original-Received: from pdx1-sub0-mail-a38.g.dreamhost.com (pop.dreamhost.com [64.90.62.162]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384) by 0.0.0.0:2500 (trex/5.16.2); Wed, 24 Oct 2018 23:45:53 +0000 X-MC-Relay: Neutral X-MailChannels-SenderId: dreamhost|x-authsender|jurta@jurta.org X-MailChannels-Auth-Id: dreamhost X-Chemical-Shrill: 3ed1fa8e2252e03b_1540424753469_3199655950 X-MC-Loop-Signature: 1540424753469:801957953 X-MC-Ingress-Time: 1540424753468 Original-Received: from pdx1-sub0-mail-a38.g.dreamhost.com (localhost [127.0.0.1]) by pdx1-sub0-mail-a38.g.dreamhost.com (Postfix) with ESMTP id 16BBC803C0; Wed, 24 Oct 2018 16:45:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=linkov.net; h=from:to:cc :subject:references:date:in-reply-to:message-id:mime-version :content-type; s=linkov.net; bh=32d7mPpEzj4F7Mk9MEL+qRMVyYc=; b= epZxPoefHVdabjmOToPEZtv+sZ6VwqD2Xb096g81V+aoZhf9p0YB8/rXGD8R2mkL naAX/9Et1VH0bnoprADVPs0EXtW5Hk7ovHE7zltVc78rInQhDi947+S3q0pvnvj1 M6tlWDg+hgL4HeyQtpk+AFKyGNuPLdHlT+1/A3kC9Kc= Original-Received: from mail.jurta.org (m91-129-105-154.cust.tele2.ee [91.129.105.154]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) (Authenticated sender: jurta@jurta.org) by pdx1-sub0-mail-a38.g.dreamhost.com (Postfix) with ESMTPSA id BCE4C803B9; Wed, 24 Oct 2018 16:45:50 -0700 (PDT) X-DH-BACKEND: pdx1-sub0-mail-a38 In-Reply-To: <3818ac4c-6564-4439-9fb5-c84791f43f7a@default> (Drew Adams's message of "Tue, 23 Oct 2018 15:51:14 -0700 (PDT)") X-VR-OUT-STATUS: OK X-VR-OUT-SCORE: -100 X-VR-OUT-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedtkedrgeekgddviecutefuodetggdotefrodftvfcurfhrohhfihhlvgemucggtfgfnhhsuhgsshgtrhhisggvpdfftffgtefojffquffvnecuuegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenucfjughrpefhvffuohhfffgjkfgfgggtsehmtderredtredtnecuhfhrohhmpefluhhrihcunfhinhhkohhvuceojhhurhhisehlihhnkhhovhdrnhgvtheqnecukfhppeeluddruddvledruddthedrudehgeenucfrrghrrghmpehmohguvgepshhmthhppdhhvghlohepmhgrihhlrdhjuhhrthgrrdhorhhgpdhinhgvthepledurdduvdelrddutdehrdduheegpdhrvghtuhhrnhdqphgrthhhpefluhhrihcunfhinhhkohhvuceojhhurhhisehlihhnkhhovhdrnhgvtheqpdhmrghilhhfrhhomhepjhhurhhisehlihhnkhhovhdrnhgvthdpnhhrtghpthhtohepughrvgifrdgruggrmhhssehorhgrtghlvgdrtghomhenucevlhhushhtvghrufhiiigvpedt X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 208.118.235.43 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.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.org gmane.emacs.bugs:151579 Archived-At: --=-=-= Content-Type: text/plain > Absolutely. Like with any similar interaction in > Emacs the delay before starting should be a user > option. Users are different, and user machines etc. > are different. You are right, with a small delay lazy-highlighting is responsive. In the attached patch I also added a separate variable that you asked for programmatic use, changed text to "currently visible on the screen" and mentioned lazy-highlight-cleanup. The patch is extensively tested for various scenarios: --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=isearch-lazy-highlight-buffer.2.patch diff --git a/lisp/isearch.el b/lisp/isearch.el index 1e785a44c5..dae85208cb 100644 --- a/lisp/isearch.el +++ b/lisp/isearch.el @@ -304,9 +304,9 @@ isearch-fail (defcustom isearch-lazy-highlight t "Controls the lazy-highlighting during incremental search. -When non-nil, all text in the buffer matching the current search -string is highlighted lazily (see `lazy-highlight-initial-delay' -and `lazy-highlight-interval'). +When non-nil, all text currently visible on the screen +matching the current search string is highlighted lazily +(see `lazy-highlight-initial-delay' and `lazy-highlight-interval'). When multiple windows display the current buffer, the highlighting is displayed only on the selected window, unless @@ -316,6 +316,17 @@ isearch-lazy-highlight :group 'lazy-highlight :group 'isearch) +(defcustom isearch-lazy-highlight-buffer nil + "Controls the lazy-highlighting of the full buffer. +When non-nil, all text in the buffer matching the current search +string is highlighted lazily (see `lazy-highlight-initial-delay', +`lazy-highlight-interval' and `lazy-highlight-buffer-max-at-a-time'). +This is useful when `lazy-highlight-cleanup' is customized to nil +and doesn't remove full-buffer highlighting after a search." + :type 'boolean + :group 'lazy-highlight + :group 'isearch) + ;;; Lazy highlight customization. (defgroup lazy-highlight nil @@ -351,6 +362,15 @@ lazy-highlight-max-at-a-time (integer :tag "Some")) :group 'lazy-highlight) +(defcustom lazy-highlight-buffer-max-at-a-time 20 + "Maximum matches to highlight at a time (for `isearch-lazy-highlight-buffer'). +Larger values may reduce Isearch's responsiveness to user input; +smaller values make matches highlight slowly. +A value of nil means highlight all matches shown in the buffer." + :type '(choice (const :tag "All" nil) + (integer :tag "Some")) + :group 'lazy-highlight) + (defface lazy-highlight '((((class color) (min-colors 88) (background light)) (:background "paleturquoise")) @@ -3178,6 +3198,7 @@ isearch-lazy-highlight-window (defvar isearch-lazy-highlight-window-group nil) (defvar isearch-lazy-highlight-window-start nil) (defvar isearch-lazy-highlight-window-end nil) +(defvar isearch-lazy-highlight-buffer-p nil) (defvar isearch-lazy-highlight-case-fold-search nil) (defvar isearch-lazy-highlight-regexp nil) (defvar isearch-lazy-highlight-lax-whitespace nil) @@ -3226,10 +3247,12 @@ isearch-lazy-highlight-new-loop isearch-lax-whitespace)) (not (eq isearch-lazy-highlight-regexp-lax-whitespace isearch-regexp-lax-whitespace)) - (not (= (window-group-start) - isearch-lazy-highlight-window-start)) - (not (= (window-group-end) ; Window may have been split/joined. - isearch-lazy-highlight-window-end)) + (not (or isearch-lazy-highlight-buffer-p + (= (window-group-start) + isearch-lazy-highlight-window-start))) + (not (or isearch-lazy-highlight-buffer-p + (= (window-group-end) ; Window may have been split/joined. + isearch-lazy-highlight-window-end))) (not (eq isearch-forward isearch-lazy-highlight-forward)) ;; In case we are recovering from an error. @@ -3247,6 +3270,7 @@ isearch-lazy-highlight-new-loop isearch-lazy-highlight-window-group (selected-window-group) isearch-lazy-highlight-window-start (window-group-start) isearch-lazy-highlight-window-end (window-group-end) + isearch-lazy-highlight-buffer-p isearch-lazy-highlight-buffer ;; Start lazy-highlighting at the beginning of the found ;; match (`isearch-other-end'). If no match, use point. ;; One of the next two variables (depending on search direction) @@ -3264,12 +3288,22 @@ isearch-lazy-highlight-new-loop isearch-lazy-highlight-regexp-lax-whitespace isearch-regexp-lax-whitespace isearch-lazy-highlight-regexp-function isearch-regexp-function isearch-lazy-highlight-forward isearch-forward) + ;; Extend start/end to match whole string at point + (if isearch-lazy-highlight-forward + (setq isearch-lazy-highlight-start + (min (+ isearch-lazy-highlight-start + (1- (length isearch-lazy-highlight-last-string))) + (point-max))) + (setq isearch-lazy-highlight-end + (max (- isearch-lazy-highlight-end + (1- (length isearch-lazy-highlight-last-string))) + (point-min)))) (unless (equal isearch-string "") (setq isearch-lazy-highlight-timer (run-with-idle-timer lazy-highlight-initial-delay nil 'isearch-lazy-highlight-start))))) -(defun isearch-lazy-highlight-search () +(defun isearch-lazy-highlight-search (string bound) "Search ahead for the next or previous match, for lazy highlighting. Attempt to do the search exactly the way the pending Isearch would." (condition-case nil @@ -3283,24 +3317,10 @@ isearch-lazy-highlight-search (isearch-forward isearch-lazy-highlight-forward) (search-invisible nil) ; don't match invisible text (retry t) - (success nil) - (bound (if isearch-lazy-highlight-forward - (min (or isearch-lazy-highlight-end-limit (point-max)) - (if isearch-lazy-highlight-wrapped - (+ isearch-lazy-highlight-start - ;; Extend bound to match whole string at point - (1- (length isearch-lazy-highlight-last-string))) - (window-group-end))) - (max (or isearch-lazy-highlight-start-limit (point-min)) - (if isearch-lazy-highlight-wrapped - (- isearch-lazy-highlight-end - ;; Extend bound to match whole string at point - (1- (length isearch-lazy-highlight-last-string))) - (window-group-start)))))) + (success nil)) ;; Use a loop like in `isearch-search'. (while retry - (setq success (isearch-search-string - isearch-lazy-highlight-last-string bound t)) + (setq success (isearch-search-string string bound t)) ;; Clear RETRY unless the search predicate says ;; to skip this search hit. (if (or (not success) @@ -3312,6 +3332,20 @@ isearch-lazy-highlight-search success) (error nil))) +(defvar isearch-lazy-highlight-match-function #'isearch-lazy-highlight-match + "Function that highlights the found match. +The function accepts two arguments: the beginning and the end of the match.") + +(defun isearch-lazy-highlight-match (mb me) + (let ((ov (make-overlay mb me))) + (push ov isearch-lazy-highlight-overlays) + ;; 1000 is higher than ediff's 100+, + ;; but lower than isearch main overlay's 1001 + (overlay-put ov 'priority 1000) + (overlay-put ov 'face 'lazy-highlight) + (unless (eq isearch-lazy-highlight 'all-windows) + (overlay-put ov 'window (selected-window))))) + (defun isearch-lazy-highlight-start () "Start a new lazy-highlight updating loop." (lazy-highlight-cleanup t) ;remove old overlays @@ -3321,19 +3355,32 @@ isearch-lazy-highlight-update "Update highlighting of other matches for current search." (let ((max lazy-highlight-max-at-a-time) (looping t) - nomore) + nomore window-start window-end) (with-local-quit (save-selected-window (if (and (window-live-p isearch-lazy-highlight-window) (not (memq (selected-window) isearch-lazy-highlight-window-group))) (select-window isearch-lazy-highlight-window)) + (setq window-start (window-group-start)) + (setq window-end (window-group-end)) (save-excursion (save-match-data (goto-char (if isearch-lazy-highlight-forward isearch-lazy-highlight-end isearch-lazy-highlight-start)) (while looping - (let ((found (isearch-lazy-highlight-search))) + (let* ((bound (if isearch-lazy-highlight-forward + (min (or isearch-lazy-highlight-end-limit (point-max)) + (if isearch-lazy-highlight-wrapped + isearch-lazy-highlight-start + window-end)) + (max (or isearch-lazy-highlight-start-limit (point-min)) + (if isearch-lazy-highlight-wrapped + isearch-lazy-highlight-end + window-start)))) + (found (isearch-lazy-highlight-search + isearch-lazy-highlight-last-string + bound))) (when max (setq max (1- max)) (if (<= max 0) @@ -3345,24 +3392,16 @@ isearch-lazy-highlight-update (if isearch-lazy-highlight-forward (if (= mb (if isearch-lazy-highlight-wrapped isearch-lazy-highlight-start - (window-group-end))) + window-end)) (setq found nil) (forward-char 1)) (if (= mb (if isearch-lazy-highlight-wrapped isearch-lazy-highlight-end - (window-group-start))) + window-start)) (setq found nil) (forward-char -1))) - ;; non-zero-length match - (let ((ov (make-overlay mb me))) - (push ov isearch-lazy-highlight-overlays) - ;; 1000 is higher than ediff's 100+, - ;; but lower than isearch main overlay's 1001 - (overlay-put ov 'priority 1000) - (overlay-put ov 'face 'lazy-highlight) - (unless (eq isearch-lazy-highlight 'all-windows) - (overlay-put ov 'window (selected-window))))) + (funcall isearch-lazy-highlight-match-function mb me)) ;; Remember the current position of point for ;; the next call of `isearch-lazy-highlight-update' ;; when `lazy-highlight-max-at-a-time' is too small. @@ -3378,17 +3417,83 @@ isearch-lazy-highlight-update (setq isearch-lazy-highlight-wrapped t) (if isearch-lazy-highlight-forward (progn - (setq isearch-lazy-highlight-end (window-group-start)) + (setq isearch-lazy-highlight-end window-start) (goto-char (max (or isearch-lazy-highlight-start-limit (point-min)) - (window-group-start)))) - (setq isearch-lazy-highlight-start (window-group-end)) + window-start))) + (setq isearch-lazy-highlight-start window-end) (goto-char (min (or isearch-lazy-highlight-end-limit (point-max)) - (window-group-end)))))))) - (unless nomore + window-end))))))) + (if nomore + (when isearch-lazy-highlight-buffer-p + (if isearch-lazy-highlight-forward + (setq isearch-lazy-highlight-end (point-min)) + (setq isearch-lazy-highlight-start (point-max))) + (run-at-time lazy-highlight-interval nil + 'isearch-lazy-highlight-buffer-update)) (setq isearch-lazy-highlight-timer (run-at-time lazy-highlight-interval nil 'isearch-lazy-highlight-update))))))))) +(defun isearch-lazy-highlight-buffer-update () + "Update highlighting of other matches in the whole buffer." + (let ((max lazy-highlight-buffer-max-at-a-time) + (looping t) + nomore window-start window-end) + (with-local-quit + (save-selected-window + (if (and (window-live-p isearch-lazy-highlight-window) + (not (memq (selected-window) isearch-lazy-highlight-window-group))) + (select-window isearch-lazy-highlight-window)) + (setq window-start (window-group-start)) + (setq window-end (window-group-end)) + (save-excursion + (save-match-data + (goto-char (if isearch-lazy-highlight-forward + isearch-lazy-highlight-end + isearch-lazy-highlight-start)) + (while looping + (let* ((bound (if isearch-lazy-highlight-forward + (or isearch-lazy-highlight-end-limit (point-max)) + (or isearch-lazy-highlight-start-limit (point-min)))) + (found (isearch-lazy-highlight-search + isearch-lazy-highlight-last-string + bound))) + (when max + (setq max (1- max)) + (if (<= max 0) + (setq looping nil))) + (if found + (let ((mb (match-beginning 0)) + (me (match-end 0))) + (if (= mb me) ;zero-length match + (if isearch-lazy-highlight-forward + (if (= mb (point-max)) + (setq found nil) + (forward-char 1)) + (if (= mb (point-min)) + (setq found nil) + (forward-char -1))) + ;; Already highlighted by isearch-lazy-highlight-update + (unless (or (and (>= mb window-start) (<= me window-end)) + (not isearch-lazy-highlight-buffer-p)) + ;; non-zero-length match + (funcall isearch-lazy-highlight-match-function mb me))) + ;; Remember the current position of point for + ;; the next call of `isearch-lazy-highlight-update' + ;; when `lazy-highlight-buffer-max-at-a-time' is too small. + (if isearch-lazy-highlight-forward + (setq isearch-lazy-highlight-end (point)) + (setq isearch-lazy-highlight-start (point))))) + + ;; not found or zero-length match at the search bound + (if (not found) + (setq looping nil + nomore t)))) + (unless nomore + (setq isearch-lazy-highlight-timer + (run-at-time lazy-highlight-interval nil + 'isearch-lazy-highlight-buffer-update))))))))) + (defun isearch-resume (string regexp word forward message case-fold) "Resume an incremental search. STRING is the string or regexp searched for. --=-=-=--