Ihor Radchenko <[email protected]> writes:

> This looks promising. And fixes a long-standing bug.
> Could you please share the analysis why the tests failed in the original 
> version?

There were two main cases I saw (although I haven't thoroughly investigated
every failure):

1. Inline source code: The original patch broke
   org-element--parse-paired-brackets because that function relies on
   syntax tables to find the pair of surrounding curly braces.
2. Source blocks: The original patch broke some regular expression (I
   think?) that matches the beginning of source blocks, causing it to
   include the first word of the source-code in the language name. E.g.,
   in one test:

   #+BEGIN_SRC eshell
   echo 2
   #+END_SRC

   Parsed the language as "eshell\necho"

> What about inline src blocks?

I restricted the previous version to JUST blocks because I figured it'd
be safer (I assume org-mode skips over all the lines between begin/end
when fontifying).

I've dug into this a bit more now and, I can fix the tests by binding
parse-sexp-lookup-properties to nil inside
org-element--parse-paired-brackets (patch attached). However, I'm not
sure there aren't other cases lurking untested.

One option here is to replace calls to with-syntax-table with an
org-with-syntax-table that binds parse-sexp-lookup-properties to nil but
that may be overkill.

> Maybe we should limit this when calling the fontification, not inside?

This seems to work, yes. Really, it appears that skipping the initial
initial newline line is sufficient (patch attached).

>From 9dac39c420581bf31a79046879e3db7da3c8ac8b Mon Sep 17 00:00:00 2001
From: Steven Allen <[email protected]>
Date: Fri, 7 Nov 2025 11:31:39 -0800
Subject: [PATCH] Apply the mode's syntax table when fontifying natively

This makes it easier to work with source blocks without editing them in
a new buffer: s-expression and symbol navigation/selection work as
expected, < is not treated as a parentheses within source blocks unless
appropriate for the source block's mode, etc.

* lisp/org-src.el (org-src-font-lock-fontify-block): Apply the
syntax-table from the source-code's mode to the text (both blocks and inline).
(org-src--edit-element): Remove any pre-existing syntax table properties.
* lisp/org.el (org-mode): Obey the syntax table text property in
commands.  This ensures that, e.g., "C-h f" correctly suggests the
symbol at point and doesn't, e.g., include any quotes, etc.
(org-unfontify-region): Cleanup the syntax-table property.
(org-fontify-meta-lines-and-blocks-1): Start fontifying on the first
line of the source-code, not the final newline before the source-code.
* lisp/org-element.el (org-element--parse-paired-brackets): Ignore the
syntax table property when trying to find paired brackets, we only want
to use our own custom syntax table here.
---
 lisp/org-element.el | 1 +
 lisp/org-src.el     | 9 +++++++--
 lisp/org.el         | 8 ++++++--
 3 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/lisp/org-element.el b/lisp/org-element.el
index 0b51b4524..85590e838 100644
--- a/lisp/org-element.el
+++ b/lisp/org-element.el
@@ -508,6 +508,7 @@ defun org-element--parse-paired-brackets
 			  (?\[ org-element--pair-square-table)
 			  (?\( org-element--pair-round-table)
 			  (_ nil)))
+          (parse-sexp-lookup-properties nil)
 	  (pos (point)))
       (when syntax-table
 	(with-syntax-table syntax-table
diff --git a/lisp/org-src.el b/lisp/org-src.el
index 971d6e938..e6a895cd7 100644
--- a/lisp/org-src.el
+++ b/lisp/org-src.el
@@ -609,7 +609,10 @@ defun org-src--edit-element
 	;; Insert contents.
 	(insert contents)
 	(remove-text-properties (point-min) (point-max)
-				'(display nil invisible nil intangible nil))
+				'( display nil
+                                   invisible nil
+                                   intangible nil
+                                   syntax-table nil ))
 	(let ((lf (eq type 'latex-fragment)))
           (unless preserve-ind (org-do-remove-indentation (and lf block-ind) lf)))
 	(set-buffer-modified-p nil)
@@ -669,7 +672,8 @@ defun org-src-font-lock-fontify-block
   "Fontify code block between START and END using LANG's syntax.
 This function is called by Emacs's automatic fontification, as long
 as `org-src-fontify-natively' is non-nil."
-  (let ((modified (buffer-modified-p)) native-tab-width)
+  (let ((modified (buffer-modified-p))
+        native-tab-width)
     (remove-text-properties start end '(face nil))
     (when-let* ((lang-mode (org-src-get-lang-mode-if-bound lang)))
       (condition-case nil
@@ -737,6 +741,7 @@ defun org-src-font-lock-fontify-block
                                'org-src-invisible new-prop
 		               org-buffer)))))))
 	          (setq pos next)))
+              (put-text-property start end 'syntax-table (syntax-table) org-buffer)
               (set-buffer-modified-p nil)))
         (error
          (message "Native code fontification error in %S at pos%d\n Error: %S"
diff --git a/lisp/org.el b/lisp/org.el
index ed012d2e6..7a6b02c46 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -5178,6 +5178,9 @@ define-derived-mode org-mode
   (org-setup-filling)
   ;; Comments.
   (org-setup-comments-handling)
+  ;; Obey the syntax-table text property when navigating text (used in
+  ;; source blocks).
+  (setq-local parse-sexp-lookup-properties t)
   ;; Beginning/end of defun
   (setq-local beginning-of-defun-function 'org-backward-element)
   (setq-local end-of-defun-function
@@ -5676,7 +5679,7 @@ defun org-fontify-meta-lines-and-blocks-1
                    ;; for user convenience.
                    (member block-type '("src" "export" "example")))
 	      (save-match-data
-                (org-src-font-lock-fontify-block (or lang "") block-start block-end))
+                (org-src-font-lock-fontify-block (or lang "") bol-after-beginline block-end))
 	      (add-text-properties bol-after-beginline block-end '(src-block t)))
 	     (quoting
 	      (add-text-properties
@@ -6338,7 +6341,8 @@ defun org-unfontify-region
     (remove-text-properties beg end
 			    '(mouse-face t keymap t org-linked-text t
 					 invisible t intangible t
-					 org-emphasis t))
+					 org-emphasis t
+                                         syntax-table t))
     (org-fold-core-update-optimisation beg end)
     (org-remove-font-lock-display-properties beg end)))
 
-- 
2.51.2

Reply via email to