From 15b2138719b34083967001c3903e7560d5e0947c Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Thu, 30 Jun 2022 13:20:33 -0400 Subject: (syntax-wholeline-max): New var Try and reduce the pain caused by font-lock and syntax-propertize's wholeline-based operation in buffers made up of a few very long lines (bug#45898). * lisp/emacs-lisp/syntax.el (syntax-wholeline-max): New var. (syntax--lbp): New function. (syntax-propertize-wholelines): Use it. * lisp/jit-lock.el (jit-lock--antiblink-post-command): Use `syntax--lbp`. * lisp/font-lock.el (font-lock-extend-region-wholelines): Rewrite, using `syntax-propertize-wholelines`. --- lisp/emacs-lisp/syntax.el | 46 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 6 deletions(-) (limited to 'lisp/emacs-lisp/syntax.el') 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 @@ When the last position scanned holds the first character of a 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." -- cgit v1.2.3