From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Stefan Monnier via "Bug reports for GNU Emacs, the Swiss army knife of text editors" Newsgroups: gmane.emacs.bugs Subject: bug#45898: 27.1; wedged in redisplay again Date: Wed, 29 Jun 2022 17:07:45 -0400 Message-ID: References: <46b65e3f-cf3d-a3f2-9a9a-100e58274ff6@jovi.net> <83mtem2dc9.fsf@gnu.org> <87y1y63qmq.fsf@gnus.org> <83h74t3k5u.fsf@gnu.org> <87tu8sx569.fsf@gnus.org> <83v8t6us8t.fsf@gnu.org> <87zgiinptk.fsf@gnus.org> <83mteiufih.fsf@gnu.org> <877d5kojbo.fsf@gnus.org> <83zgigu3e0.fsf@gnu.org> <500e4b9c69f2a90e7cf05b956178d71b@webmail.orcon.net.nz> <835yl3tnv3.fsf@gnu.org> <83iloyo0x7.fsf@gnu.org> <83mte5jukr.fsf@gnu.org> <837d57gbed.fsf@gnu.org> <83o7yicx3p.fsf@gnu.org> <83pmir5lwc.fsf@gnu.org> Reply-To: Stefan Monnier Mime-Version: 1.0 Content-Type: text/plain Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="22301"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (gnu/linux) Cc: gerd.moellmann@gmail.com, psainty@orcon.net.nz, larsi@gnus.org, Emacs-hacker2018@jovi.net, 45898@debbugs.gnu.org To: Eli Zaretskii Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Wed Jun 29 23:08:12 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 1o6eux-0005ce-08 for geb-bug-gnu-emacs@m.gmane-mx.org; Wed, 29 Jun 2022 23:08:11 +0200 Original-Received: from localhost ([::1]:58638 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1o6euv-0006yI-KP for geb-bug-gnu-emacs@m.gmane-mx.org; Wed, 29 Jun 2022 17:08:09 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:57380) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1o6euo-0006xv-AV for bug-gnu-emacs@gnu.org; Wed, 29 Jun 2022 17:08:02 -0400 Original-Received: from debbugs.gnu.org ([209.51.188.43]:38222) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1o6euo-0003aL-1R for bug-gnu-emacs@gnu.org; Wed, 29 Jun 2022 17:08:02 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1o6eun-0005fT-Og for bug-gnu-emacs@gnu.org; Wed, 29 Jun 2022 17:08:01 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Stefan Monnier Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Wed, 29 Jun 2022 21:08:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 45898 X-GNU-PR-Package: emacs Original-Received: via spool by 45898-submit@debbugs.gnu.org id=B45898.165653688021780 (code B ref 45898); Wed, 29 Jun 2022 21:08:01 +0000 Original-Received: (at 45898) by debbugs.gnu.org; 29 Jun 2022 21:08:00 +0000 Original-Received: from localhost ([127.0.0.1]:60352 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1o6eul-0005fE-Th for submit@debbugs.gnu.org; Wed, 29 Jun 2022 17:08:00 -0400 Original-Received: from mailscanner.iro.umontreal.ca ([132.204.25.50]:48088) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1o6eui-0005et-38 for 45898@debbugs.gnu.org; Wed, 29 Jun 2022 17:07:58 -0400 Original-Received: from pmg3.iro.umontreal.ca (localhost [127.0.0.1]) by pmg3.iro.umontreal.ca (Proxmox) with ESMTP id 54892441318; Wed, 29 Jun 2022 17:07:50 -0400 (EDT) Original-Received: from mail01.iro.umontreal.ca (unknown [172.31.2.1]) by pmg3.iro.umontreal.ca (Proxmox) with ESMTP id 55E7D4416B1; Wed, 29 Jun 2022 17:07:47 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=iro.umontreal.ca; s=mail; t=1656536867; bh=PXojWVq8F32lFvGSm6l0dylPWAnblA1KAAjuazpoT34=; h=From:To:Cc:Subject:References:Date:In-Reply-To:From; b=bUihG1jgn1ir2+5jLn1NhyqbGa0zjEfPW0WLxNBhJ8N163whLvAiGIUyGuSDJ9a+C rH5tJacT031Qg18lOtprvNhSREt+/+B3LUVKZa8IPoOm2OAUCxRE0qxK0fg/VjmdCU Of6mzLpz19HVff/JU5Om4D9DEn9WkzR93R/DEEp9LFAY6OkNKZpqS++6IwxxTpMM5D oDEICcm7h+j8DXQIN3rfMavh/OjRHXqzcXKN7VMq6EU8x6mgTHRI4tw23icV77U65B WHGWJ45gX1AhMoa+LkUACuQsYL7nG9M0s/FoWvm+wpk7JEegncgOmI8SbAa76VG+m8 GxLnquxBrPxjw== Original-Received: from lechazo (lechon.iro.umontreal.ca [132.204.27.242]) by mail01.iro.umontreal.ca (Postfix) with ESMTPSA id 0F071120180; Wed, 29 Jun 2022 17:07:47 -0400 (EDT) In-Reply-To: <83pmir5lwc.fsf@gnu.org> (Eli Zaretskii's message of "Wed, 29 Jun 2022 22:07:15 +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:235672 Archived-At: >> How 'bout the patch below? > Thanks. Doesn't work: the looping around font-lock-extend-region-functions ends up calling `font-lock-extend-region-wholelines` repeatedly as long as the bounds a grown and so the bounds keep growing until we're back at square one. The patch below addresses this problem by truncating in a more careful way, so `font-lock-extend-region-wholelines` is idempotent (i.e. repeated calls don't keep growing the bounds). It's also careful to use that same "chunking" in syntax.el and in the antiblink code of jit-lock. Tracing `syntax-ppss` and `syntax-propertize-wholelines` suggests that this patch is sufficient to keep most of the work "local" rather than applying to the whole line/file all the time. >> It doesn't seem to make much difference on the `medium_line.json` >> example from Phil, tho :-( > In what case does it make much difference? None that I can see :-( > And how did you test whether it makes a difference? I just did src/emacs -Q ~/tmp/medium_line.json and then tried to move around in the buffer, search with Isearch, and insert a few chars. I don't notice any difference with or without the patch :-( Stefan diff --git a/lisp/emacs-lisp/syntax.el b/lisp/emacs-lisp/syntax.el index 36b0c56e953..e1be3015838 100644 --- a/lisp/emacs-lisp/syntax.el +++ b/lisp/emacs-lisp/syntax.el @@ -124,15 +124,49 @@ syntax-propertize-extend-region-functions otherwise nil. That construct can be a two character comment delimiter or an Escaped or Char-quoted character.")) -(defun syntax-propertize-wholelines (start end) - "Extend the region delimited by START and END to whole lines. +(defvar syntax-wholeline-max 10000 + "Maximum line length for syntax operations. +If lines are longer than that, syntax operations will treat them as chunks +of this size. Misfontification may then occur. +This is a tradeoff between correctly applying the syntax rules, +and avoiding major slowdown on pathologically long lines.") + +(defun syntax--lbp (&optional arg) + "Like `line-beginning-position' but obeying `syntax-wholeline-max'." + (let ((pos (point)) + (res (line-beginning-position arg))) + (cond + ((< (abs (- pos res)) syntax-wholeline-max) res) + ;; For lines that are too long, round to the nearest multiple of + ;; `syntax-wholeline-max'. We use rounding rather than just + ;; (min res (+ pos syntax-wholeline-max)) so that repeated calls + ;; to `syntax-propertize-wholelines' don't keep growing the bounds, + ;; i.e. it really behaves like additional line-breaks. + ((< res pos) + (let ((max syntax-wholeline-max)) + (max (point-min) (* max (truncate pos max))))) + (t + (let ((max syntax-wholeline-max)) + (min (point-max) (* max (ceiling pos max)))))))) + +(defun syntax-propertize-wholelines (beg end) + "Extend the region delimited by BEG and END to whole lines. This function is useful for `syntax-propertize-extend-region-functions'; see Info node `(elisp) Syntax Properties'." - (goto-char start) - (cons (line-beginning-position) - (progn (goto-char end) - (if (bolp) (point) (line-beginning-position 2))))) + ;; This let-binding was taken from + ;; `font-lock-extend-region-wholelines' where it was used to avoid + ;; inf-looping (Bug#21615) but for some reason it was not applied + ;; here in syntax.el and was used only for the "beg" side. + (let ((inhibit-field-text-motion t)) + (let ((new-beg (progn (goto-char beg) + (if (bolp) beg + (syntax--lbp)))) + (new-end (progn (goto-char end) + (if (bolp) end + (syntax--lbp 2))))) + (unless (and (eql beg new-beg) (eql end new-end)) + (cons new-beg new-end))))) (defun syntax-propertize-multiline (beg end) "Let `syntax-propertize' pay attention to the syntax-multiline property." diff --git a/lisp/font-lock.el b/lisp/font-lock.el index df0a26f4d0f..7eeaf2f547f 100644 --- a/lisp/font-lock.el +++ b/lisp/font-lock.el @@ -1260,18 +1260,11 @@ font-lock-extend-region-multiline (defun font-lock-extend-region-wholelines () "Move fontification boundaries to beginning of lines." - (let ((changed nil)) - (goto-char font-lock-beg) - (unless (bolp) - (setq changed t font-lock-beg - (let ((inhibit-field-text-motion t)) - (line-beginning-position)))) - (goto-char font-lock-end) - (unless (bolp) - (unless (eq font-lock-end - (setq font-lock-end (line-beginning-position 2))) - (setq changed t))) - changed)) + (let ((new (syntax-propertize-wholelines font-lock-beg font-lock-end))) + (when new + (setq font-lock-beg (car new)) + (setq font-lock-end (cdr new)) + t))) (defun font-lock-default-fontify-region (beg end loudly) "Fontify the text between BEG and END. @@ -1565,7 +1558,7 @@ font-lock-apply-syntactic-highlight (or (nth 3 highlight) (error "No match %d in highlight %S" match highlight)) (when (and (consp value) (not (numberp (car value)))) - (setq value (eval value))) + (setq value (eval value t))) (when (stringp value) (setq value (string-to-syntax value))) ;; Flush the syntax-cache. I believe this is not necessary for ;; font-lock's use of syntax-ppss, but I'm not 100% sure and it can @@ -1589,7 +1582,7 @@ font-lock-fontify-syntactic-anchored-keywords LIMIT can be modified by the value of its PRE-MATCH-FORM." (let ((matcher (nth 0 keywords)) (lowdarks (nthcdr 3 keywords)) highlights ;; Evaluate PRE-MATCH-FORM. - (pre-match-value (eval (nth 1 keywords)))) + (pre-match-value (eval (nth 1 keywords) t))) ;; Set LIMIT to value of PRE-MATCH-FORM or the end of line. (if (and (numberp pre-match-value) (> pre-match-value (point))) (setq limit pre-match-value) @@ -1605,7 +1598,7 @@ font-lock-fontify-syntactic-anchored-keywords (font-lock-apply-syntactic-highlight (car highlights)) (setq highlights (cdr highlights))))) ;; Evaluate POST-MATCH-FORM. - (eval (nth 2 keywords)))) + (eval (nth 2 keywords) t))) (defun font-lock-fontify-syntactic-keywords-region (start end) "Fontify according to `font-lock-syntactic-keywords' between START and END. @@ -1718,7 +1711,7 @@ font-lock-apply-highlight ;; No match but we might not signal an error. (or (nth 3 highlight) (error "No match %d in highlight %S" match highlight)) - (let ((val (eval (nth 1 highlight)))) + (let ((val (eval (nth 1 highlight) t))) (when (eq (car-safe val) 'face) (add-text-properties start end (cddr val)) (setq val (cadr val))) @@ -1753,7 +1746,7 @@ font-lock-fontify-anchored-keywords (let ((matcher (nth 0 keywords)) (lowdarks (nthcdr 3 keywords)) highlights (lead-start (match-beginning 0)) ;; Evaluate PRE-MATCH-FORM. - (pre-match-value (eval (nth 1 keywords)))) + (pre-match-value (eval (nth 1 keywords) t))) ;; Set LIMIT to value of PRE-MATCH-FORM or the end of line. (if (not (and (numberp pre-match-value) (> pre-match-value (point)))) (setq limit (line-end-position)) @@ -1778,7 +1771,7 @@ font-lock-fontify-anchored-keywords (font-lock-apply-highlight (car highlights)) (setq highlights (cdr highlights))))) ;; Evaluate POST-MATCH-FORM. - (eval (nth 2 keywords)))) + (eval (nth 2 keywords) t))) (defun font-lock-fontify-keywords-region (start end &optional loudly) "Fontify according to `font-lock-keywords' between START and END. @@ -1884,7 +1877,7 @@ font-lock-compile-keyword (cond ((or (functionp keyword) (nlistp keyword)) ; MATCHER (list keyword '(0 font-lock-keyword-face))) ((eq (car keyword) 'eval) ; (eval . FORM) - (font-lock-compile-keyword (eval (cdr keyword)))) + (font-lock-compile-keyword (eval (cdr keyword) t))) ((eq (car-safe (cdr keyword)) 'quote) ; (MATCHER . 'FORM) ;; If FORM is a FACENAME then quote it. Otherwise ignore the quote. (if (symbolp (nth 2 keyword)) @@ -1905,7 +1898,7 @@ font-lock-eval-keywords keywords (font-lock-eval-keywords (if (fboundp keywords) (funcall keywords) - (eval keywords))))) + (eval keywords t))))) (defun font-lock-value-in-major-mode (values) "If VALUES is a list, use `major-mode' as a key and return the `assq' value. diff --git a/lisp/jit-lock.el b/lisp/jit-lock.el index 17969d57620..a3ada443702 100644 --- a/lisp/jit-lock.el +++ b/lisp/jit-lock.el @@ -242,20 +242,20 @@ jit-lock-mode (when (and jit-lock-stealth-time (null jit-lock-stealth-timer)) (setq jit-lock-stealth-timer (run-with-idle-timer jit-lock-stealth-time t - 'jit-lock-stealth-fontify))) + #'jit-lock-stealth-fontify))) ;; Create, but do not activate, the idle timer for repeated ;; stealth fontification. (when (and jit-lock-stealth-time (null jit-lock-stealth-repeat-timer)) (setq jit-lock-stealth-repeat-timer (timer-create)) (timer-set-function jit-lock-stealth-repeat-timer - 'jit-lock-stealth-fontify '(t))) + #'jit-lock-stealth-fontify '(t))) ;; Init deferred fontification timer. (when (and jit-lock-defer-time (null jit-lock-defer-timer)) (setq jit-lock-defer-timer (run-with-idle-timer jit-lock-defer-time t - 'jit-lock-deferred-fontify))) + #'jit-lock-deferred-fontify))) ;; Initialize contextual fontification if requested. (when (eq jit-lock-contextually t) @@ -265,13 +265,13 @@ jit-lock-mode (lambda () (unless jit-lock--antiblink-grace-timer (jit-lock-context-fontify)))))) - (add-hook 'post-command-hook 'jit-lock--antiblink-post-command nil t) + (add-hook 'post-command-hook #'jit-lock--antiblink-post-command nil t) (setq jit-lock-context-unfontify-pos (or jit-lock-context-unfontify-pos (point-max)))) ;; Setup our hooks. - (add-hook 'after-change-functions 'jit-lock-after-change nil t) - (add-hook 'fontification-functions 'jit-lock-function nil t)) + (add-hook 'after-change-functions #'jit-lock-after-change nil t) + (add-hook 'fontification-functions #'jit-lock-function nil t)) ;; Turn Just-in-time Lock mode off. (t @@ -294,8 +294,9 @@ jit-lock-mode (setq jit-lock-defer-timer nil))) ;; Remove hooks. - (remove-hook 'after-change-functions 'jit-lock-after-change t) - (remove-hook 'fontification-functions 'jit-lock-function)))) + (remove-hook 'post-command-hook #'jit-lock--antiblink-post-command t) + (remove-hook 'after-change-functions #'jit-lock-after-change t) + (remove-hook 'fontification-functions #'jit-lock-function)))) (define-minor-mode jit-lock-debug-mode "Minor mode to help debug code run from jit-lock. @@ -707,8 +708,8 @@ jit-lock-after-change (min jit-lock-context-unfontify-pos jit-lock-start)))))) (defun jit-lock--antiblink-post-command () - (let* ((new-l-b-p (copy-marker (line-beginning-position))) - (l-b-p-2 (line-beginning-position 2)) + (let* ((new-l-b-p (copy-marker (syntax--lbp))) + (l-b-p-2 (syntax--lbp 2)) (same-line (and jit-lock-antiblink-grace (not (= new-l-b-p l-b-p-2))