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
