Assume point is at the beginning of the block."
(let ((case-fold-search t))
(if (not (save-excursion
- (re-search-forward "^[ \t]*#\\+END_CENTER" limit t)))
+ (re-search-forward "^[ \t]*#\\+END_CENTER[ \t]*$" limit t)))
;; Incomplete block: parse it as a paragraph.
(org-element-paragraph-parser limit)
(let ((block-end-line (match-beginning 0)))
(forward-line)
(point)))
(end (save-excursion (skip-chars-forward " \r\t\n" limit)
- (if (eobp) (point) (point-at-bol)))))
+ (skip-chars-backward " \t")
+ (if (bolp) (point) (line-end-position)))))
(list 'center-block
(nconc
(list :begin begin
Assume point is at beginning of drawer."
(let ((case-fold-search t))
- (if (not (save-excursion (re-search-forward "^[ \t]*:END:" limit t)))
+ (if (not (save-excursion (re-search-forward "^[ \t]*:END:[ \t]*$" limit t)))
;; Incomplete drawer: parse it as a paragraph.
(org-element-paragraph-parser limit)
(let ((drawer-end-line (match-beginning 0)))
(forward-line)
(point)))
(end (progn (skip-chars-forward " \r\t\n" limit)
- (if (eobp) (point) (point-at-bol)))))
+ (skip-chars-backward " \t")
+ (if (bolp) (point) (line-end-position)))))
(list 'drawer
(nconc
(list :begin begin
Assume point is at beginning of dynamic block."
(let ((case-fold-search t))
- (if (not (save-excursion (re-search-forward org-dblock-end-re limit t)))
+ (if (not (save-excursion
+ (re-search-forward "^[ \t]*#\\+END:?[ \t]*$" limit t)))
;; Incomplete block: parse it as a paragraph.
(org-element-paragraph-parser limit)
(let ((block-end-line (match-beginning 0)))
(forward-line)
(point)))
(end (progn (skip-chars-forward " \r\t\n" limit)
- (if (eobp) (point) (point-at-bol)))))
+ (skip-chars-backward " \t")
+ (if (bolp) (point) (line-end-position)))))
(list 'dynamic-block
(nconc
(list :begin begin
(contents-end (and contents-begin ending))
(end (progn (goto-char ending)
(skip-chars-forward " \r\t\n" limit)
- (if (eobp) (point) (point-at-bol)))))
+ (skip-chars-backward " \t")
+ (if (bolp) (point) (line-end-position)))))
(list 'footnote-definition
(nconc
(list :label label
(forward-line)
(point)))
(end (progn (skip-chars-forward " \r\t\n" limit)
- (if (eobp) (point) (point-at-bol))))
+ (skip-chars-backward " \t")
+ (if (bolp) (point) (line-end-position))))
(inlinetask
(list 'inlinetask
(nconc
(unless (bolp) (forward-line))
(point)))
(end (progn (skip-chars-forward " \r\t\n" limit)
- (if (eobp) (point) (point-at-bol)))))
+ (skip-chars-backward " \t")
+ (if (bolp) (point) (line-end-position)))))
;; Return value.
(list 'plain-list
(nconc
Assume point is at the beginning of the block."
(let ((case-fold-search t))
(if (not (save-excursion
- (re-search-forward "^[ \t]*#\\+END_QUOTE" limit t)))
+ (re-search-forward "^[ \t]*#\\+END_QUOTE[ \t]*$" limit t)))
;; Incomplete block: parse it as a paragraph.
(org-element-paragraph-parser limit)
(let ((block-end-line (match-beginning 0)))
(forward-line)
(point)))
(end (progn (skip-chars-forward " \r\t\n" limit)
- (if (eobp) (point) (point-at-bol)))))
+ (skip-chars-backward " \t")
+ (if (bolp) (point) (line-end-position)))))
(list 'quote-block
(nconc
(list :begin begin
(type (progn (looking-at "[ \t]*#\\+BEGIN_\\(S-+\\)")
(upcase (match-string-no-properties 1)))))
(if (not (save-excursion
- (re-search-forward (concat "^[ \t]*#\\+END_" type) limit t)))
+ (re-search-forward
+ (format "^[ \t]*#\\+END_%s[ \t]*$" type) limit t)))
;; Incomplete block: parse it as a paragraph.
(org-element-paragraph-parser limit)
(let ((block-end-line (match-beginning 0)))
(pos-before-blank (progn (goto-char block-end-line)
(forward-line)
(point)))
- (end (progn (org-skip-whitespace)
- (if (eobp) (point) (point-at-bol)))))
+ (end (progn (skip-chars-forward " \r\t\n" limit)
+ (skip-chars-backward " \t")
+ (if (bolp) (point) (line-end-position)))))
(list 'special-block
(nconc
(list :type type
(begin (point-at-bol))
(pos-before-blank (progn (forward-line) (point)))
(end (progn (skip-chars-forward " \r\t\n" limit)
- (if (eobp) (point) (point-at-bol)))))
+ (skip-chars-backward " \t")
+ (if (bolp) (point) (line-end-position)))))
(list 'babel-call
(list :begin begin
:end end
(status (if time 'closed 'running))
(post-blank (let ((before-blank (progn (forward-line) (point))))
(skip-chars-forward " \r\t\n" limit)
- (unless (eobp) (beginning-of-line))
+ (skip-chars-backward " \t")
+ (unless (bolp) (end-of-line))
(count-lines before-blank (point))))
(end (point)))
(list 'clock
(point)))
(end (progn (goto-char com-end)
(skip-chars-forward " \r\t\n" limit)
- (if (eobp) (point) (point-at-bol)))))
+ (skip-chars-backward " \t")
+ (if (bolp) (point) (line-end-position)))))
(list 'comment
(nconc
(list :begin begin
Assume point is at comment block beginning."
(let ((case-fold-search t))
(if (not (save-excursion
- (re-search-forward "^[ \t]*#\\+END_COMMENT" limit t)))
+ (re-search-forward "^[ \t]*#\\+END_COMMENT[ \t]*$" limit t)))
;; Incomplete block: parse it as a paragraph.
(org-element-paragraph-parser limit)
(let ((contents-end (match-beginning 0)))
(forward-line)
(point)))
(end (progn (skip-chars-forward " \r\t\n" limit)
- (if (eobp) (point) (point-at-bol))))
+ (skip-chars-backward " \t")
+ (if (bolp) (point) (line-end-position))))
(value (buffer-substring-no-properties
contents-begin contents-end)))
(list 'comment-block
`:switches', `:value' and `:post-blank' keywords."
(let ((case-fold-search t))
(if (not (save-excursion
- (re-search-forward "^[ \t]*#\\+END_EXAMPLE" limit t)))
+ (re-search-forward "^[ \t]*#\\+END_EXAMPLE[ \t]*$" limit t)))
;; Incomplete block: parse it as a paragraph.
(org-element-paragraph-parser limit)
(let ((contents-end (match-beginning 0)))
(begin (car keywords))
(contents-begin (progn (forward-line) (point)))
(hidden (org-invisible-p2))
- (value (buffer-substring-no-properties contents-begin contents-end))
+ (value (org-unescape-code-in-string
+ (buffer-substring-no-properties
+ contents-begin contents-end)))
(pos-before-blank (progn (goto-char contents-end)
(forward-line)
(point)))
(end (progn (skip-chars-forward " \r\t\n" limit)
- (if (eobp) (point) (point-at-bol)))))
+ (skip-chars-backward " \t")
+ (if (bolp) (point) (line-end-position)))))
(list 'example-block
(nconc
(list :begin begin
(let ((switches (org-element-property :switches example-block)))
(concat "#+BEGIN_EXAMPLE" (and switches (concat " " switches)) "\n"
(org-remove-indentation
- (org-element-property :value example-block))
+ (org-escape-code-in-string
+ (org-element-property :value example-block)))
"#+END_EXAMPLE")))
(type (progn (looking-at "[ \t]*#\\+BEGIN_\\(\\S-+\\)")
(upcase (org-match-string-no-properties 1)))))
(if (not (save-excursion
- (re-search-forward (concat "^[ \t]*#\\+END_" type) limit t)))
+ (re-search-forward
+ (format "^[ \t]*#\\+END_%s[ \t]*$" type) limit t)))
;; Incomplete block: parse it as a paragraph.
(org-element-paragraph-parser limit)
(let ((contents-end (match-beginning 0)))
(forward-line)
(point)))
(end (progn (skip-chars-forward " \r\t\n" limit)
- (if (eobp) (point) (point-at-bol))))
+ (skip-chars-backward " \t")
+ (if (bolp) (point) (line-end-position))))
(value (buffer-substring-no-properties contents-begin
contents-end)))
(list 'export-block
(forward-line))
(point)))
(end (progn (skip-chars-forward " \r\t\n" limit)
- (if (eobp) (point) (point-at-bol)))))
+ (skip-chars-backward " \t")
+ (if (bolp) (point) (line-end-position)))))
(list 'fixed-width
(nconc
(list :begin begin
(begin (car keywords))
(post-hr (progn (forward-line) (point)))
(end (progn (skip-chars-forward " \r\t\n" limit)
- (if (eobp) (point) (point-at-bol)))))
+ (skip-chars-backward " \t")
+ (if (bolp) (point) (line-end-position)))))
(list 'horizontal-rule
(nconc
(list :begin begin
(match-end 0) (point-at-eol))))
(pos-before-blank (progn (forward-line) (point)))
(end (progn (skip-chars-forward " \r\t\n" limit)
- (if (eobp) (point) (point-at-bol)))))
+ (skip-chars-backward " \t")
+ (if (bolp) (point) (line-end-position)))))
(list 'keyword
(list :key key
:value value
(env (progn (looking-at "^[ \t]*\\\\begin{\\([A-Za-z0-9]+\\*?\\)}")
(regexp-quote (match-string 1))))
(code-end
- (progn (re-search-forward (format "^[ \t]*\\\\end{%s}" env) limit t)
+ (progn (re-search-forward
+ (format "^[ \t]*\\\\end{%s}[ \t]*$" env) limit t)
(forward-line)
(point)))
(value (buffer-substring-no-properties code-begin code-end))
(end (progn (skip-chars-forward " \r\t\n" limit)
- (if (eobp) (point) (point-at-bol)))))
+ (skip-chars-backward " \t")
+ (if (bolp) (point) (line-end-position)))))
(list 'latex-environment
(nconc
(list :begin begin
Assume point is at the beginning of the paragraph."
(save-excursion
- (let* (;; INNER-PAR-P is non-nil when paragraph is at the
+ (let* ((contents-begin (point))
+ ;; INNER-PAR-P is non-nil when paragraph is at the
;; beginning of an item or a footnote reference. In that
;; case, we mustn't look for affiliated keywords since they
;; belong to the container.
(inner-par-p (not (bolp)))
- (contents-begin (point))
(keywords (unless inner-par-p
(org-element--collect-affiliated-keywords)))
(begin (if inner-par-p contents-begin (car keywords)))
(before-blank
(let ((case-fold-search t))
(end-of-line)
- (re-search-forward org-element-paragraph-separate limit 'm)
- (while (and (/= (point) limit)
- (cond
- ;; Skip non-existent or incomplete drawer.
- ((save-excursion
- (beginning-of-line)
- (and (looking-at "[ \t]*:\\S-")
- (or (not (looking-at org-drawer-regexp))
- (not (save-excursion
- (re-search-forward
- "^[ \t]*:END:" limit t)))))))
- ;; Stop at comments.
- ((save-excursion
- (beginning-of-line)
- (not (looking-at "[ \t]*#\\S-"))) nil)
- ;; Skip incomplete dynamic blocks.
- ((save-excursion
- (beginning-of-line)
- (looking-at "[ \t]*#\\+BEGIN: "))
- (not (save-excursion
- (re-search-forward
- "^[ \t]*\\+END:" limit t))))
- ;; Skip incomplete blocks.
- ((save-excursion
- (beginning-of-line)
- (looking-at "[ \t]*#\\+BEGIN_\\(\\S-+\\)"))
- (not (save-excursion
- (re-search-forward
- (concat "^[ \t]*#\\+END_"
- (match-string 1))
- limit t))))
- ;; Skip incomplete latex environments.
- ((save-excursion
- (beginning-of-line)
- (looking-at "^[ \t]*\\\\begin{\\([A-Za-z0-9]+\\*?\\)}"))
- (not (save-excursion
- (re-search-forward
- (format "^[ \t]*\\\\end{%s}"
- (match-string 1))
- limit t))))
- ;; Skip ill-formed keywords.
- ((not (save-excursion
- (beginning-of-line)
- (looking-at "[ \t]*#\\+\\S-+:"))))))
- (re-search-forward org-element-paragraph-separate limit 'm))
- (if (eobp) (point) (goto-char (line-beginning-position)))))
+ (if (not (re-search-forward
+ org-element-paragraph-separate limit 'm))
+ limit
+ ;; A matching `org-element-paragraph-separate' is not
+ ;; necessarily the end of the paragraph. In
+ ;; particular, lines starting with # or : as a first
+ ;; non-space character are ambiguous. We have check
+ ;; if they are valid Org syntax (i.e. not an
+ ;; incomplete keyword).
+ (beginning-of-line)
+ (while (not
+ (or
+ ;; There's no ambiguity for other symbols or
+ ;; empty lines: stop here.
+ (looking-at "[ \t]*\\(?:[^:#]\\|$\\)")
+ ;; Stop at valid fixed-width areas.
+ (looking-at "[ \t]*:\\(?: \\|$\\)")
+ ;; Stop at drawers.
+ (and (looking-at org-drawer-regexp)
+ (save-excursion
+ (re-search-forward
+ "^[ \t]*:END:[ \t]*$" limit t)))
+ ;; Stop at valid comments.
+ (looking-at "[ \t]*#\\(?: \\|$\\)")
+ ;; Stop at valid dynamic blocks.
+ (and (looking-at org-dblock-start-re)
+ (save-excursion
+ (re-search-forward
+ "^[ \t]*#\\+END:?[ \t]*$" limit t)))
+ ;; Stop at valid blocks.
+ (and (looking-at
+ "[ \t]*#\\+BEGIN_\\(\\S-+\\)")
+ (save-excursion
+ (re-search-forward
+ (format "^[ \t]*#\\+END_%s[ \t]*$"
+ (match-string 1))
+ limit t)))
+ ;; Stop at valid latex environments.
+ (and (looking-at
+ "^[ \t]*\\\\begin{\\([A-Za-z0-9]+\\*?\\)}[ \t]*$")
+ (save-excursion
+ (re-search-forward
+ (format "^[ \t]*\\\\end{%s}[ \t]*$"
+ (match-string 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
+ (goto-char (line-beginning-position)))))
(contents-end (progn (skip-chars-backward " \r\t\n" contents-begin)
(forward-line)
(point)))
(end (progn (skip-chars-forward " \r\t\n" limit)
- (if (eobp) (point) (point-at-bol)))))
+ (skip-chars-backward " \t")
+ (if (bolp) (point) (line-end-position)))))
(list 'paragraph
(nconc
(list :begin begin
(begin (point))
(post-blank (let ((before-blank (progn (forward-line) (point))))
(skip-chars-forward " \r\t\n" limit)
- (unless (eobp) (beginning-of-line))
+ (skip-chars-backward " \t")
+ (unless (bolp) (end-of-line))
(count-lines before-blank (point))))
(end (point))
closed deadline scheduled)
(hidden (org-invisible-p2))
(properties
(let (val)
- (while (not (looking-at "^[ \t]*:END:"))
+ (while (not (looking-at "^[ \t]*:END:[ \t]*$"))
(when (looking-at "[ \t]*:\\([A-Za-z][-_A-Za-z0-9]*\\):")
(push (cons (org-match-string-no-properties 1)
(org-trim
(point-at-bol)))
(pos-before-blank (progn (forward-line) (point)))
(end (progn (skip-chars-forward " \r\t\n" limit)
- (if (eobp) (point) (point-at-bol)))))
+ (skip-chars-backward " \t")
+ (if (bolp) (point) (line-end-position)))))
(list 'property-drawer
(list :begin begin
:end end
Assume point is at the beginning of the block."
(let ((case-fold-search t))
- (if (not (save-excursion (re-search-forward "^[ \t]*#\\+END_SRC" limit t)))
+ (if (not (save-excursion (re-search-forward "^[ \t]*#\\+END_SRC[ \t]*$"
+ limit t)))
;; Incomplete block: parse it as a paragraph.
(org-element-paragraph-parser limit)
(let ((contents-end (match-beginning 0)))
;; Get visibility status.
(hidden (progn (forward-line) (org-invisible-p2)))
;; Retrieve code.
- (value (buffer-substring-no-properties (point) contents-end))
+ (value (org-unescape-code-in-string
+ (buffer-substring-no-properties (point) contents-end)))
(pos-before-blank (progn (goto-char contents-end)
(forward-line)
(point)))
;; Get position after ending blank lines.
(end (progn (skip-chars-forward " \r\t\n" limit)
- (if (eobp) (point) (point-at-bol)))))
+ (skip-chars-backward " \t")
+ (if (bolp) (point) (line-end-position)))))
(list 'src-block
(nconc
(list :language language
(params (org-element-property :parameters src-block))
(value (let ((val (org-element-property :value src-block)))
(cond
-
(org-src-preserve-indentation val)
((zerop org-edit-src-content-indentation)
(org-remove-indentation val))
(concat (and lang (concat " " lang))
(and switches (concat " " switches))
(and params (concat " " params))))
- value
+ (org-escape-code-in-string value)
"#+END_SRC")))
(type (if (org-at-table.el-p) 'table.el 'org))
(keywords (org-element--collect-affiliated-keywords))
(begin (car keywords))
- (table-end (goto-char (marker-position (org-table-end t))))
+ (table-end
+ (if (re-search-forward org-table-any-border-regexp limit 'm)
+ (goto-char (match-beginning 0))
+ (point)))
(tblfm (let (acc)
(while (looking-at "[ \t]*#\\+TBLFM: +\\(.*\\)[ \t]*$")
(push (org-match-string-no-properties 1) acc)
acc))
(pos-before-blank (point))
(end (progn (skip-chars-forward " \r\t\n" limit)
- (if (eobp) (point) (point-at-bol)))))
+ (skip-chars-backward " \t")
+ (if (bolp) (point) (line-end-position)))))
(list 'table
(nconc
(list :begin begin
Assume point is at beginning of the block."
(let ((case-fold-search t))
(if (not (save-excursion
- (re-search-forward "^[ \t]*#\\+END_VERSE" limit t)))
+ (re-search-forward "^[ \t]*#\\+END_VERSE[ \t]*$" limit t)))
;; Incomplete block: parse it as a paragraph.
(org-element-paragraph-parser limit)
(let ((contents-end (match-beginning 0)))
(forward-line)
(point)))
(end (progn (skip-chars-forward " \r\t\n" limit)
- (if (eobp) (point) (point-at-bol)))))
+ (skip-chars-backward " \t")
+ (if (bolp) (point) (line-end-position)))))
(list 'verse-block
(nconc
(list :begin begin
Return value is a cons cell whose CAR is `entity' or
`latex-fragment' and CDR is beginning position."
(save-excursion
+ (unless (bolp) (backward-char))
(let ((matchers
(remove "begin" (plist-get org-format-latex-options :matchers)))
;; ENTITY-RE matches both LaTeX commands and Org entities.
Return value is a cons cell whose CAR is either `subscript' or
`superscript' and CDR is beginning position."
(save-excursion
+ (unless (bolp) (backward-char))
(when (re-search-forward org-match-substring-regexp limit t)
(cons (if (string= (match-string 2) "_") 'subscript 'superscript)
(match-beginning 2)))))
type, as a symbol.
OBJECTS is the previous candidates alist."
+ ;; Filter out any object found but not belonging to RESTRICTION.
+ (setq objects
+ (org-remove-if-not
+ (lambda (obj)
+ (let ((type (car obj)))
+ (memq (or (cdr (assq type org-element-object-successor-alist))
+ type)
+ restriction)))
+ objects))
(let (next-candidates types-to-search)
;; If no previous result, search every object type in RESTRICTION.
;; Otherwise, keep potential candidates (old objects located after
(progn (beginning-of-line)
(skip-chars-forward "* ")
(setq end (point-at-eol))))
- (and (memq type '(paragraph table-cell verse-block))
+ (and (memq type '(paragraph table-row verse-block))
(let ((cbeg (org-element-property
:contents-begin element))
(cend (org-element-property
candidates)))
;; If ORIGIN is before next object in element, there's
;; no point in looking further.
- (if (> (cdr closest-cand) origin) (throw 'exit element)
+ (if (> (cdr closest-cand) origin) (throw 'exit parent)
(let* ((object
(progn (goto-char (cdr closest-cand))
(funcall (intern (format "org-element-%s-parser"
(car closest-cand))))))
(cbeg (org-element-property :contents-begin object))
- (cend (org-element-property :contents-end object)))
+ (cend (org-element-property :contents-end object))
+ (obj-end (org-element-property :end object)))
(cond
;; ORIGIN is after OBJECT, so skip it.
- ((< (org-element-property :end object) origin)
- (goto-char (org-element-property :end object)))
- ;; ORIGIN is within a non-recursive object or at an
- ;; object boundaries: Return that object.
+ ((<= obj-end origin)
+ (if (/= obj-end end) (goto-char obj-end)
+ (throw 'exit
+ (org-element-put-property
+ object :parent parent))))
+ ;; ORIGIN is within a non-recursive object or at
+ ;; an object boundaries: Return that object.
((or (not cbeg) (> cbeg origin) (< cend origin))
(throw 'exit
(org-element-put-property object :parent parent)))
- ;; Otherwise, move within current object and restrict
- ;; search to the end of its contents.
+ ;; Otherwise, move within current object and
+ ;; restrict search to the end of its contents.
(t (goto-char cbeg)
(org-element-put-property object :parent parent)
- (setq parent object end cend)))))))
+ (setq parent object
+ restriction (org-element-restriction object)
+ end cend)))))))
parent))))))
(defsubst org-element-nested-p (elem-A elem-B)
(cdr overlays)))
(goto-char (org-element-property :end elem-B)))))
-
(provide 'org-element)
+
+;; Local variables:
+;; generated-autoload-file: "org-loaddefs.el"
+;; End:
+
;;; org-element.el ends here