org-element: Fix parapraph parsing

* lisp/org-element.el (org-element--set-regexps): Refine
  `org-element-paragraph-separate'.
(org-element-paragraph-parser): Fix paragraph parsing when followed by
a dual keyword or an ill-formed latex environment.

* testing/lisp/test-org-element.el (test-org-element/paragraph-parser):
  Add tests.

Reported-by: Jacob Gerlach <jacobgerlach@gmail.com>
<http://permalink.gmane.org/gmane.emacs.orgmode/97256>
This commit is contained in:
Nicolas Goaziou 2015-04-27 22:24:00 +02:00
parent 2965f8fb0c
commit eb77fed33f
2 changed files with 66 additions and 66 deletions

View File

@ -159,16 +159,20 @@ specially in `org-element--object-lex'.")
"$" "\\|" "$" "\\|"
;; Tables (any type). ;; Tables (any type).
"\\(?:|\\|\\+-[-+]\\)" "\\|" "\\(?:|\\|\\+-[-+]\\)" "\\|"
;; Blocks (any type), Babel calls and keywords. This ;; Comments, keyword-like or block-like constructs.
;; is only an indication and need some thorough check. ;; Blocks and keywords with dual values need to be
"#\\(?:[+ ]\\|$\\)" "\\|" ;; double-checked.
;; Drawers (any type) and fixed-width areas. This is "#\\(?: \\|$\\|\\+\\(?:"
;; also only an indication. "BEGIN_\\S-+" "\\|"
":" "\\|" "\\S-+\\(?:\\[.*\\]\\)?:\\(?: \\|$\\)\\)\\)"
"\\|"
;; Drawers (any type) and fixed-width areas. Drawers
;; need to be double-checked.
":\\(?: \\|$\\|[-_[:word:]]+:[ \t]*$\\)" "\\|"
;; Horizontal rules. ;; Horizontal rules.
"-\\{5,\\}[ \t]*$" "\\|" "-\\{5,\\}[ \t]*$" "\\|"
;; LaTeX environments. ;; LaTeX environments.
"\\\\begin{\\([A-Za-z0-9]+\\*?\\)}" "\\|" "\\\\begin{\\([A-Za-z0-9*]+\\)}" "\\|"
;; Clock lines. ;; Clock lines.
(regexp-quote org-clock-string) "\\|" (regexp-quote org-clock-string) "\\|"
;; Lists. ;; Lists.
@ -2233,65 +2237,42 @@ Assume point is at the beginning of the paragraph."
(before-blank (before-blank
(let ((case-fold-search t)) (let ((case-fold-search t))
(end-of-line) (end-of-line)
(if (not (re-search-forward ;; A matching `org-element-paragraph-separate' is not
org-element-paragraph-separate limit 'm)) ;; necessarily the end of the paragraph. In particular,
limit ;; drawers, blocks or LaTeX environments opening lines
;; A matching `org-element-paragraph-separate' is not ;; must be closed. Moreover keywords with a secondary
;; necessarily the end of the paragraph. In ;; value must belong to "dual keywords".
;; particular, lines starting with # or : as a first (while (not
;; non-space character are ambiguous. We have to (cond
;; check if they are valid Org syntax (e.g., not an ((not (and (re-search-forward
;; incomplete keyword). org-element-paragraph-separate limit 'move)
(beginning-of-line) (progn (beginning-of-line) t))))
(while (not ((looking-at org-drawer-regexp)
(or (save-excursion
;; There's no ambiguity for other symbols or (re-search-forward "^[ \t]*:END:[ \t]*$" limit t)))
;; empty lines: stop here. ((looking-at "[ \t]*#\\+BEGIN_\\(\\S-+\\)")
(looking-at "[ \t]*\\(?:[^:#]\\|$\\)") (save-excursion
;; Stop at valid fixed-width areas. (re-search-forward
(looking-at "[ \t]*:\\(?: \\|$\\)") (format "^[ \t]*#\\+END_%s[ \t]*$"
;; Stop at drawers. (regexp-quote (match-string 1)))
(and (looking-at org-drawer-regexp) limit t)))
(save-excursion ((looking-at org-element--latex-begin-environment)
(re-search-forward (save-excursion
"^[ \t]*:END:[ \t]*$" limit t))) (re-search-forward
;; Stop at valid comments. (format org-element--latex-end-environment
(looking-at "[ \t]*#\\(?: \\|$\\)") (regexp-quote (match-string 1)))
;; Stop at valid dynamic blocks. limit t)))
(and (looking-at org-dblock-start-re) ((looking-at "[ \t]*#\\+\\(\\S-+\\)\\[.*\\]:")
(save-excursion (member-ignore-case (match-string 1)
(re-search-forward org-element-dual-keywords))
"^[ \t]*#\\+END:?[ \t]*$" limit t))) ;; Everything else is unambiguous.
;; Stop at valid blocks. (t)))
(and (looking-at "[ \t]*#\\+BEGIN_\\(\\S-+\\)") (end-of-line))
(save-excursion
(re-search-forward
(format "^[ \t]*#\\+END_%s[ \t]*$"
(regexp-quote
(org-match-string-no-properties 1)))
limit t)))
;; Stop at valid latex environments.
(and (looking-at org-element--latex-begin-environment)
(save-excursion
(re-search-forward
(format org-element--latex-end-environment
(regexp-quote
(org-match-string-no-properties 1)))
limit t)))
;; Stop at valid keywords.
(looking-at "[ \t]*#\\+\\S-+:")
;; Skip everything else.
(not
(progn
(end-of-line)
(re-search-forward org-element-paragraph-separate
limit 'm)))))
(beginning-of-line)))
(if (= (point) limit) limit (if (= (point) limit) limit
(goto-char (line-beginning-position))))) (goto-char (line-beginning-position)))))
(contents-end (progn (skip-chars-backward " \r\t\n" contents-begin) (contents-end (save-excursion
(forward-line) (skip-chars-backward " \r\t\n" contents-begin)
(point))) (line-beginning-position 2)))
(end (progn (skip-chars-forward " \r\t\n" limit) (end (progn (skip-chars-forward " \r\t\n" limit)
(if (eobp) (point) (line-beginning-position))))) (if (eobp) (point) (line-beginning-position)))))
(list 'paragraph (list 'paragraph

View File

@ -1744,10 +1744,29 @@ e^{i\\pi}+1=0
(let ((elem (org-element-at-point))) (let ((elem (org-element-at-point)))
(and (eq (org-element-type elem) 'paragraph) (and (eq (org-element-type elem) 'paragraph)
(= (point-max) (org-element-property :end elem)))))) (= (point-max) (org-element-property :end elem))))))
(should
(org-test-with-temp-text "Paragraph\n\begin{equation}"
(let ((elem (org-element-at-point)))
(and (eq (org-element-type elem) 'paragraph)
(= (point-max) (org-element-property :end elem))))))
;; Stop at affiliated keywords.
(should
(org-test-with-temp-text "Paragraph\n#+NAME: test\n| table |"
(let ((elem (org-element-at-point)))
(and (eq (org-element-type elem) 'paragraph)
(not (org-element-property :name elem))
(= (org-element-property :end elem) (line-beginning-position 2))))))
(should
(org-test-with-temp-text
"Paragraph\n#+CAPTION[with short caption]: test\n| table |"
(let ((elem (org-element-at-point)))
(and (eq (org-element-type elem) 'paragraph)
(not (org-element-property :name elem))
(= (org-element-property :end elem) (line-beginning-position 2))))))
;; Do not steal affiliated keywords from container. ;; Do not steal affiliated keywords from container.
(should (should
(org-test-with-temp-text "#+ATTR_LATEX: test\n- item 1" (org-test-with-temp-text "#+ATTR_LATEX: test\n- item<point> 1"
(let ((elem (progn (search-forward "item") (org-element-at-point)))) (let ((elem (org-element-at-point)))
(and (eq (org-element-type elem) 'paragraph) (and (eq (org-element-type elem) 'paragraph)
(not (org-element-property :attr_latex elem)) (not (org-element-property :attr_latex elem))
(/= (org-element-property :begin elem) 1))))) (/= (org-element-property :begin elem) 1)))))