Ping! Gentlemen, any update about my suggestion below or how we should proceed?
Arash Esbati <[email protected]> writes: > Ciao Gabriele, > > Gabriele Nicolardi via bug-auctex via Bug reporting list for AUCTeX > <[email protected]> writes: > >> A regex without lookbehind cannot reliably encode "preceded by an even >> number of backslashes" through alternation alone. > > Yes, we have to try harder if we want to fix issue. > >> The robust fix is to capture the whole backslash run with a single, >> non-alternating quantifier, and check its parity in Lisp: >> >> In texmathp-compile: >> >> texmathp-toggle-regexp >> (concat "\\(\\\\*\\)" >> (regexp-opt togglers t)) >> >> In texmathp, the toggle-scanning loop needs a matching change (group 1 >> no longer means "real toggle", it now holds the backslash run, so >> parity must be checked before deciding to toggle): >> >> (while (re-search-forward texmathp-toggle-regexp pos t) >> (when (zerop (mod (length (match-string-no-properties 1)) 2)) >> (if (setq math-on (not math-on)) >> (setq sw-match (cons (match-string-no-properties 2) >> (match-beginning 2))) >> (setq sw-match nil)))) > > I only had a brief look at this, but within AUCTeX, we have the function > `TeX-escaped-p' which we can use for this. My proposal is this (look > for the ;; Next line changed: and ;; (unless ...) added:): > > (defun texmathp-compile () > "Compile the value of `texmathp-tex-commands' into the internal lists. > Call this when you have changed the value of that variable without using > customize (customize calls it when setting the variable)." > (interactive) > ;; Extract lists and regexp. > (setq texmathp-macros nil texmathp-environments nil) > (setq texmathp-memory > (cons texmathp-tex-commands texmathp-tex-commands-default)) > (setq texmathp-tex-commands1 (append texmathp-tex-commands > texmathp-tex-commands-default)) > (let ((list (reverse texmathp-tex-commands1)) > entry type switches togglers) > (while (setq entry (car list)) > (setq type (nth 1 entry) > list (cdr list)) > (cond ((memq type '(env-on env-off)) (push (car entry) > texmathp-environments)) > ((memq type '(arg-on arg-off)) (push (car entry) texmathp-macros)) > ((memq type '(sw-on sw-off)) (push (car entry) switches)) > ((memq type '(sw-toggle)) (push (car entry) togglers)))) > (setq texmathp-onoff-regexp > (concat "\\(?:[^\\]\\|\\`\\)" > (regexp-opt switches t)) > texmathp-toggle-regexp > ;; Next line changed: > ;; (concat "\\([^\\$]\\|\\`\\)" > (concat "\\(\\`\\|\\)" > (regexp-opt togglers t))))) > > (defun texmathp () > "Determine if point is inside (La)TeX math mode. > Returns t or nil. Additional info is placed into `texmathp-why'. > The functions assumes that you have (almost) syntactically correct (La)TeX in > the buffer. > See the variable `texmathp-tex-commands' about which commands are checked." > (interactive) > (let* ((pos (point)) math-on sw-match > (bound (save-excursion > (if (re-search-backward > (if (memq major-mode '(doctex-mode docTeX-mode)) > "[\n\r]%*[ \t]*[\n\r]" > "[\n\r][ \t]*[\n\r]") > nil 1 texmathp-search-n-paragraphs) > (match-beginning 0) > (point-min)))) > (mac-match (texmathp-match-macro bound)) > (env-match (texmathp-match-environment > (if (and mac-match (> (cdr mac-match) bound)) > (cdr mac-match) > bound))) > (match (cons nil bound))) > > ;; Select the nearer match > (and env-match (setq match env-match)) > ;; Use `>=' instead of `>' in case called inside \ensuremath{..} > ;; beginning just at (point-min). > (and mac-match (>= (cdr mac-match) (cdr match)) (setq match mac-match)) > (setq math-on (memq (nth 1 (assoc (car match) texmathp-tex-commands1)) > '(env-on arg-on))) > > ;; Check for switches > (and (not math-on) > (setq sw-match (texmathp-match-switch bound)) > ;; Use `>=' instead of `>' by similar reason as above. (bug#41559) > (>= (cdr sw-match) (cdr match)) > (eq (nth 1 (assoc (car sw-match) texmathp-tex-commands1)) 'sw-on) > (setq match sw-match math-on t)) > > ;; Check for togglers > (if (not math-on) > (save-excursion > (goto-char (cdr match)) > (while (re-search-forward texmathp-toggle-regexp pos t) > ;; (unless ...) added: > (unless (TeX-escaped-p (1- (point))) > (if (setq math-on (not math-on)) > (setq sw-match (cons (match-string-no-properties 2) > (match-beginning 2))) > (setq sw-match nil)))) > (and math-on sw-match (setq match sw-match)))) > > ;; Store info, show as message when interactive, and return > (setq texmathp-why match) > ;; Check also if the match is inside a verbatim construct and > ;; return immediately nil. This relies on the function > ;; `LaTeX-verbatim-p'. We add a check here in case this library > ;; is used stand-alone without latex.el provided by AUCTeX > ;; (bug#61410) and the `major-mode' doesn't derive from `TeX-mode' > ;; (bug#69681): > (if (and (derived-mode-p 'TeX-mode) > (fboundp 'LaTeX-verbatim-p) > (LaTeX-verbatim-p (cdr match))) > (progn > (setq texmathp-why `(nil . ,(cdr match))) > (when (called-interactively-p 'any) > (message "math-mode is off: Math command in verbatim construct at > buffer position %d" > (cdr match))) > nil) > (and (called-interactively-p 'any) > (message "math-mode is %s: %s begins at buffer position %d" > (if math-on "on" "off") > (or (car match) "new paragraph") > (cdr match))) > (and math-on t)))) > >> I tested it against backslash runs from N=0 up to N=101 (even and >> odd), the original tabular/TikZ case, your \\\$ counterexample, $$ >> display math combined with backslash runs, and multi-cell tabular rows >> -- all correct. I also confirmed the compiled regexp still lets >> regexp-opt factor "$" and "$$" exactly as before >> ("\\(\\\\*\\)\\($\\$?\\)"), so display math is unaffected. > > Can you please run your tests with the suggestion above? > >> For full transparency, as with my initial report: I used an AI >> assistant (Claude) throughout this follow-up as well -- to analyze why >> the paired-backslash regex fails structurally, to design this >> alternative, and to build and run a test harness (an actual Emacs >> instance, byte-compiling texmathp.el and exercising the real texmathp >> function against dozens of cases, including the ones above) rather >> than reasoning about the regex in the abstract. I independently >> reviewed the test cases and the reasoning, and I'm satisfied the fix >> and the testing are sound, but of course I'd still welcome your >> review, especially given your closer familiarity with texmathp's >> history and edge cases. > > Thanks for the disclaimer above. Note that currently, the GNU project > doesn't accept any code generated with LLMs until further notice. So we > can't install your suggestion above. So we either find another solution > (which I've proposed) or your change has to wait (if we agree on it). > TBH, I'm not happy with ("\\(\\\\*\\)\\($\\$?\\)"). > > Best, Arash _______________________________________________ bug-auctex mailing list [email protected] https://lists.gnu.org/mailman/listinfo/bug-auctex
