From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.ciao.gmane.io!not-for-mail From: Ikumi Keita Newsgroups: gmane.emacs.devel Subject: Giving "text quotes" syntax in font-lock-syntax-table only Date: Wed, 20 May 2020 15:53:58 +0900 Message-ID: <50114.1589957638@localhost> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="ciao.gmane.io:159.69.161.202"; logging-data="105540"; mail-complaints-to="usenet@ciao.gmane.io" To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Wed May 20 08:55:31 2020 Return-path: Envelope-to: ged-emacs-devel@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 1jbIdW-000RLp-Fd for ged-emacs-devel@m.gmane-mx.org; Wed, 20 May 2020 08:55:30 +0200 Original-Received: from localhost ([::1]:51150 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jbIdV-0006it-Hz for ged-emacs-devel@m.gmane-mx.org; Wed, 20 May 2020 02:55:29 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:58290) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jbIcB-0005CT-0A for emacs-devel@gnu.org; Wed, 20 May 2020 02:54:07 -0400 Original-Received: from smtp1a.inetd.co.jp ([210.129.88.11]:39684) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jbIc8-0001uu-Hg for emacs-devel@gnu.org; Wed, 20 May 2020 02:54:06 -0400 Original-Received: from localhost (125-14-252-253.rev.home.ne.jp [125.14.252.253]) by smtp1a.inetd.co.jp (Postfix) with ESMTPA id 1695E62 for ; Wed, 20 May 2020 15:54:00 +0900 (JST) X-Mailer: MH-E 8.6+git; nmh 1.7.1; GNU Emacs 26.3 Received-SPF: pass client-ip=210.129.88.11; envelope-from=ikumi@ikumi.que.jp; helo=smtp1a.inetd.co.jp X-detected-operating-system: by eggs.gnu.org: First seen = 2020/05/20 02:54:00 X-ACL-Warn: Detected OS = Linux 3.1-3.10 X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_PASS=-0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.io gmane.emacs.devel:251016 Archived-At: --=-=-= Content-Type: text/plain Dear Emacs developers, I was recommended to post to emacs-devel by Tassilo, AUCTeX maintainer. I'd like to ask about SYNTAX-ALIST entry of `font-lock-defaults'. It enables to redefine syntax table entries temporarily during font lock, but is it allowed to assign "text quotes" syntax to a particular char (dollar sign)? Background: In AUCTeX's TeX and LaTeX modes, $ normally has "paired delimiter ('$')" syntax. But during font lock (by font-latex.el) we give it "string quote ('"')" syntax via the SYNTAX-ALIST in order to apply the right faces for math (treated as strings here) through syntactic fontification. However, we recently discovered that leads to the tricky bug#33139 where under some special circumstances the syntax recognition is confused and after a certain position of buffer math and non-math is fontified in inverted way. We think that the problem comes from running `syntax-ppss'. We demonstrate by the attached toy example how font-latex.el implements the syntactic fontification of math expression "$...$" and that `syntax-ppss' actually interferes badly with that method. Here, the example file hw.txt is taken and adopted from the report of bug#33139 mentioned above. Open it by emacs -Q -geometry 140x35 -l bug-repro.el hw.txt and type C-v three times. You will see that the paragraph beginning with "Let $B$ be the subset ..." has inverted fontification. (In case you didn't, do xterm -geometry 80x25 and in that terminal emacs -Q -nw -l bug-repro.el hw.txt and type C-v eight times. The part beginning with "N$ and $c^{\mathcal M}..." will be showed in inverted style.) If the line adding `syntax-ppss' to `pre-command-hook' is deleted from bug-repro.el, the above problem doesn't appear. We think that the reason is that `syntax-ppss' is called with different syntax-tables and that leads to some faulty cache entry: (a) In font lock `font-lock-fontify-syntactically-region' calls `syntax-ppss' within (with-syntax-table (or syntax-ppss-table (syntax-table)) ... ). Here, (syntax-table) returns the `font-lock-syntax-table' which gives "string quote" syntax to "$" according to SYNTAX-ALIST. (b) On the other hand, `pre-command-hook' calls `syntax-ppss' with `bug-repro-mode-syntax-table', which gives "paired delimiter" syntax to "$". Thus the two `syntax-ppss' can return different results conflicting to each other which are cached deep in the guts of syntax.el. Of course, the repro is contrieved but it seems something similar happens to many users during normal LaTeX editing work. I suspect that the bug#40930 and examples listed in its report are the same as the one discussed now. I guess that user-enabled minor modes (or packages) use syntax-aware functions extensibly in those examples, typically in `pre-command-hook', and produce syntax ppss caches which conflict with font-latex.el. If we give $ string-quote syntax also in the mode's syntax-table, the bug cannot be reproduced anymore. But that's not something we want to do in actual AUCTeX, as it has other unwanted effects. Obviously, inline math is not really a string. It is certain that the key is the syntax ppss cache, which I could confirm by the following try in the above example: ---------------------------------------------------------------------- --- bug-repro.el~ 2020-05-19 13:17:23.000000000 +0900 +++ bug-repro.el 2020-05-19 21:41:12.232250000 +0900 @@ -18,4 +18,17 @@ (setq font-lock-defaults '(nil nil nil ((?$ . "\"")) (font-lock-syntactic-face-function - . bug-repro-syntactic-face-function)))) + . bug-repro-syntactic-face-function) + (font-lock-fontify-region-function + . bug-repro-fontify-region)))) + +(defvar bug-repro-syntax-ppss-cache (list nil nil -1)) +(make-variable-buffer-local 'bug-repro-syntax-ppss-cache) + +(defun bug-repro-fontify-region (beg end loudly) + (let ((syntax-ppss-wide (pop bug-repro-syntax-ppss-cache)) + (syntax-ppss-narrow (pop bug-repro-syntax-ppss-cache)) + (syntax-propertize--done (pop bug-repro-syntax-ppss-cache))) + (font-lock-default-fontify-region beg end loudly) + (setq bug-repro-syntax-ppss-cache + (list syntax-ppss-wide syntax-ppss-narrow syntax-propertize--done)))) ---------------------------------------------------------------------- This change attempts to use separate cache for syntax ppss during font lock, and it really eliminates the wrong fontification for the above example. However, it is unsatisfactory by at least two reasons: 1. When a similar attempt is adopted in AUCTeX (font-latex.el), editing the LaTeX document is fragile. font-latex.el uses syntax-based fontification to fontify the argument of the \verb macro also, but it stops giving the right face when I insert "\verb|xyz|" with the above change. (But typing "$" just after it immediately makes "|xyz|" fontified.) I suppose the reason of this trouble is that the new cache isn't flushed properly. Whereas sytax.el uses `syntax-ppss-flush-cache' to update cache as the editing in the buffer proceeds, it doesn't touch the new cache hided in `*-syntax-ppss-cache' in the above patch. 2. It depends heavily on the implementation of caching of syntax.el. The above patch assumes that syntax ppss cache is managed by three variables `syntax-ppss-wide', `syntax-ppss-narrow' and `syntax-propertize--done'. But I don't know whether this assumption continues to hold in future nor it is appropriate for even current syntax.el. If the caching mechanism of syntax.el is not uniform across emacs versions, the maintenance cost of such codes would be much expensive. And even if syntax.el is stable enough, it is still not good to use such dependent code, especially to use internal variable with "--" in its name. So I'd like to ask that: (1) It doesn't work reliably to give "string quotes" syntax to $ in SYNTAX-ALIST. Is this an emacs bug or an intented restriction? (2) If not a bug, is it reasonable to ask to extend the font lock framework to allow syntactic fontification of $...$ form? E.g. [A] Implement some kind of "separate cache" in syntax-ppss and make it available from font lock. [B] Extend syntax parse state to include information about "the position is in-math state or not" and make `font-lock-fontify-syntactically-region' responsive to the in-math state in addition to in-comment and in-string states. This way, it would no longer be necessary to redefine syntax of $ in SYNTAX-ALIST and we can naturally implement syntactic fontification of $...$ via `font-lock-syntactic-face-function'. This approach would be beneficial for standard tex-mode.el, and potentially other program modes as well, if realized. (3) Or is there some smart way to achieve syntactic fontification of $...$ in the current font lock scheme? I'm not on emacs-devel list, so please keep me in CC when replying. Best regards, Ikumi Keita --=-=-= Content-Type: application/x-gzip Content-Disposition: attachment; filename=font-latex-bug-repro.tar.gz Content-Transfer-Encoding: base64 Content-Description: test kit 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 --=-=-=--