branch: externals/org
commit 759da9046a4fc0d65d9aba3185fc04991cd1a81c
Author: Steven Allen <[email protected]>
Commit: Ihor Radchenko <[email protected]>
Apply the mode's syntax table(s) when fontifying code 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): Preserve the
fontified source-code's syntax-table text-property where set. Otherwise
apply the syntax-table from the source-code's buffer to the text (both
blocks and inline).
(org-src--edit-element): Cleanup any syntax-table properties before
editing.
* 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.
---
lisp/org-src.el | 12 +++++++++--
lisp/org.el | 6 +++++-
testing/lisp/test-org-src.el | 49 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 64 insertions(+), 3 deletions(-)
diff --git a/lisp/org-src.el b/lisp/org-src.el
index d36a69f851..763f93eed5 100644
--- a/lisp/org-src.el
+++ b/lisp/org-src.el
@@ -608,7 +608,10 @@ Leave point in edit buffer."
;; 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)
@@ -695,7 +698,7 @@ as `org-src-fontify-natively' is non-nil."
;; space and the remapping between 'font-lock-face and 'face
;; text properties may thus not be set. See commit
;; 453d634bc.
- (dolist (prop (append '(font-lock-face face)
font-lock-extra-managed-props))
+ (dolist (prop (append '(font-lock-face face syntax-table)
font-lock-extra-managed-props))
(let ((new-prop (get-text-property pos prop)))
(when new-prop
(if (not (eq prop 'invisible))
@@ -736,6 +739,11 @@ as `org-src-fontify-natively' is non-nil."
'org-src-invisible new-prop
org-buffer)))))))
(setq pos next)))
+ (let ((new-table (syntax-table)))
+ (alter-text-property
+ start end 'syntax-table
+ (lambda (old-table) (or old-table new-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 967cd223f8..707405ff29 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -5155,6 +5155,9 @@ The following commands are available:
(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
@@ -6312,7 +6315,8 @@ If TAG is a number, get the corresponding match group."
(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)))
diff --git a/testing/lisp/test-org-src.el b/testing/lisp/test-org-src.el
index ebf8d85695..ec7c0601ad 100644
--- a/testing/lisp/test-org-src.el
+++ b/testing/lisp/test-org-src.el
@@ -569,6 +569,55 @@ This is a tab:\t.
(should (equal "#" (org-unescape-code-in-string "#")))
(should (equal "," (org-unescape-code-in-string ","))))
+;;; Syntax Table Preservation
+
+(ert-deftest test-org-src/preserve-syntax-table ()
+ "Make sure we preserve the code's syntax-table where appropriate."
+ ;; Source blocks
+ (org-test-with-temp-text
+ "
+#+begin_src nxml
+<root><point>></root>
+#+end_src
+"
+ (should (looking-at-p "></root>"))
+ ;; nXML mode applies a different syntax-table to lone ">"
+ ;; characters, make sure we preserve that.
+ (should (equal (get-text-property (point) 'syntax-table)
+ (string-to-syntax ".")))
+ ;; Everywhere else should use the mode's syntax table.
+ (dolist (pos (list (1+ (point)) (1- (point)) (pos-bol) (pos-eol)))
+ (should (equal (get-text-property pos 'syntax-table)
+ nxml-mode-syntax-table)))
+ ;; But not outside the source code.
+ (dolist (pos (list (1- (pos-bol)) (1+ (pos-eol))))
+ (should-not (get-text-property pos 'syntax-table))))
+ ;; Inline source.
+ (org-test-with-temp-text
+ "src_nxml{<root><point>></root>}"
+ (should (looking-at-p "></root>"))
+ (should (equal (get-text-property (point) 'syntax-table)
+ (string-to-syntax ".")))
+ ;; Everywhere else should use the mode's syntax table.
+ (dolist (pos (list (1+ (point)) (1- (point))))
+ (should (equal (get-text-property pos 'syntax-table)
+ nxml-mode-syntax-table)))
+ ;; We should correctly parse this as an inline source block.
+ (let ((e (org-element-context)))
+ (should (eq (org-element-type e) 'inline-src-block)))
+ ;; And we should only add the syntax table to the code itself.
+ (save-excursion
+ (should (search-forward "}"))
+ (goto-char (match-beginning 0))
+ (should (eq (char-after) ?}))
+ (should-not (get-text-property (point) 'syntax-table))
+ (should (equal (get-text-property (1- (point)) 'syntax-table)
+ nxml-mode-syntax-table)))
+ (save-excursion
+ (search-backward "{")
+ (should-not (get-text-property (point) 'syntax-table))
+ (should (equal (get-text-property (1+ (point)) 'syntax-table)
+ nxml-mode-syntax-table)))))
(provide 'test-org-src)
;;; test-org-src.el ends here