6

Here's some emacs-lisp code in a babel block:

#+begin_src emacs-lisp
(defun factor (number)
  (labels
      ((*factor (divisor number)
        (if (> (* divisor divisor) number)
            (list number)
          (if (= (mod number divisor) 0)
              (cons divisor (*factor divisor (/ number divisor)))
            (*factor (+ divisor 1) number)))))
    (*factor 2 number)))
#+end_src

So in the org buffer I get a parentheses matching problem, i.e., that very last ) at the bottom is flagged as one too many. It flashes red and check-parens flags it as well. Trouble is, this is not an error, i.e., the same code in scratch is perfectly paren-matched, likewise when I bring it up in the Org Source C-c ' window. BTW, this code compiles and runs giving good output. Any ideas what org-mode is doing here? I've got (show-paren-mode 1). When I turn it off, obviously, no problem because no highlighting matching parens.

6
  • can't replicate.... more config detalis? Apr 29, 2019 at 16:05
  • github.com/stembasespace/sbs.emacs.d
    – 147pm
    Apr 29, 2019 at 16:13
  • I don't think this block is the problem. It's evidence of some other syntax problem in your org file. I'd suggest identifying what section of your org file provokes this error. Do this by removing parts of your org file until this matching problem does not occur and adding back what you removed one by one until the error returns. Apr 29, 2019 at 16:29
  • I've got this problem in a totally naked file, i.e., just the code block, no headers, saved with an .org suffix. I'm on Emacs 26.2 and Org mode version 9.2.3 (9.2.3-11-g42abf5-elpaplus @ /.../.emacs.d/elpa/org-plus-contrib-20190429/)
    – 147pm
    Apr 29, 2019 at 19:17
  • I can run check-parens and get the problem. Go into C-c ' problem disappears.
    – 147pm
    Apr 29, 2019 at 20:06

4 Answers 4

4

Here is a potential solution:

(defun org-mode-<>-syntax-fix (start end)
  (when (eq major-mode 'org-mode)
    (save-excursion
      (goto-char start)
      (while (re-search-forward "<\\|>" end t)
    (when (get-text-property (point) 'src-block)
      ;; This is a < or > in an org-src block
      (put-text-property (point) (1- (point))
                 'syntax-table (string-to-syntax "_")))))))

(add-hook 'org-mode-hook
      (lambda ()
        (setq syntax-propertize-function 'org-mode-<>-syntax-fix)
        (syntax-propertize (point-max))))

This basically just changes the syntax table for <> inside src blocks I think. It seems to solve the problem.


The code above depends on source blocks already propertized with src-block.

The src-block property is put on source blocks by org-fontify-meta-lines-and-blocks during keyword fontification through font-lock. But, syntax fontification comes before keyword fontification. So maybe the following function is better. For easier copy-paste the full code is given. The main change is the search for source blocks by re-search-backward.

We set syntax-propertize-function as a buffer-local variable to avoid unforeseen consequences outside of our org-mode buffers, such as in cc-mode's check for syntax-table functionality, which otherwise fails and prevents HTML exports of org-mode buffers.

(defun org-mode-<>-syntax-fix (start end)
  "Change syntax of characters ?< and ?> to symbol within source code blocks."
  (let ((case-fold-search t))
    (when (eq major-mode 'org-mode)
      (save-excursion
        (goto-char start)
        (while (re-search-forward "<\\|>" end t)
          (when (save-excursion
                  (and
                   (re-search-backward "[[:space:]]*#\\+\\(begin\\|end\\)_src\\_>" nil t)
                   (string-equal (downcase (match-string 1)) "begin")))
            ;; This is a < or > in an org-src block
            (put-text-property (point) (1- (point))
                               'syntax-table (string-to-syntax "_"))))))))

(defun org-setup-<>-syntax-fix ()
  "Setup for characters ?< and ?> in source code blocks.
Add this function to `org-mode-hook'."
  (make-local-variable 'syntax-propertize-function)
  (setq syntax-propertize-function 'org-mode-<>-syntax-fix)
  (syntax-propertize (point-max)))

(add-hook 'org-mode-hook #'org-setup-<>-syntax-fix)
3
  • 2
    Dear John, your solution is very nice! I just added a small bugfix. I hope you do not mind. I did not write a new solution since the main idea is yours.
    – Tobias
    Oct 4, 2019 at 16:36
  • 1
    No problem, thanks for the improvement! Oct 5, 2019 at 13:23
  • This code works. However, the code slows down loading a large org-mode file. For example, when I opens this file with the fix, it takes a few seconds.
    – dhnam
    Mar 5 at 13:17
3

The reason for the mismatch is the code contains an angled bracket (">") which is treated as a matching paren.

I don't know the solution for how to specify that orgmode emacs-elisp should ignore angled brackets when matching parens (but I would like to know a solution).

Note: I posted this as an "answer" because I don't have enough reputation points to post it as a comment in the OP.

2

Since I never use <> as brackets in org mode documents, I have these two lines in my org mode hook function:

(modify-syntax-entry ?< ".")
(modify-syntax-entry ?> ".")

No need to play around with properties etc. Of course, if you use XML or HTML, you may wish to avoid this.

1
  • Add this to org-mode hook didn't solve it for me. I still get paren mismatch because of < and >.
    – Sahas
    Mar 23, 2020 at 11:35
2

A small variation of eric's answer that works for me:

(defun org-syntax-table-modify ()
  "Modify `org-mode-syntax-table' for the current org buffer."
  (modify-syntax-entry ?< "." org-mode-syntax-table)
  (modify-syntax-entry ?> "." org-mode-syntax-table))

(add-hook 'org-mode-hook #'org-syntax-table-modify)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.