5

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.

147pm
  • 2,907
  • 1
  • 18
  • 39
  • can't replicate.... more config detalis? – manandearth Apr 29 '19 at 16:05
  • https://github.com/stembasespace/sbs.emacs.d – 147pm Apr 29 '19 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. – Aquaactress Apr 29 '19 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 '19 at 19:17
  • I can run `check-parens` and get the problem. Go into `C-c '` problem disappears. – 147pm Apr 29 '19 at 20:06
  • I can reproduce it but I have no idea why it happens. – NickD Apr 29 '19 at 22:01

4 Answers4

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)
Antlers
  • 3
  • 3
John Kitchin
  • 11,555
  • 1
  • 19
  • 41
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.

noob
  • 61
  • 4
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.

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

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)
overideal
  • 81
  • 2