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

Reply via email to