summaryrefslogtreecommitdiff
path: root/lisp/org-element.el
diff options
context:
space:
mode:
authorNicholas D Steeves <nsteeves@gmail.com>2017-07-03 20:44:19 -0400
committerNicholas D Steeves <nsteeves@gmail.com>2017-07-03 20:57:31 -0400
commit3458b4fdfffc1b4f542405325ffa8b6eed0eb1df (patch)
tree0c9ed6fcddc796bdb92d3fc5fd266fac3b583eda /lisp/org-element.el
parent969f455bc143bb93c745b82db358392b123661e0 (diff)
New upstream version 9.0.9+dfsg
Diffstat (limited to 'lisp/org-element.el')
-rw-r--r--lisp/org-element.el278
1 files changed, 120 insertions, 158 deletions
diff --git a/lisp/org-element.el b/lisp/org-element.el
index b86244e..41b4a3a 100644
--- a/lisp/org-element.el
+++ b/lisp/org-element.el
@@ -1,6 +1,6 @@
;;; org-element.el --- Parser for Org Syntax -*- lexical-binding: t; -*-
-;; Copyright (C) 2012-2016 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2017 Free Software Foundation, Inc.
;; Author: Nicolas Goaziou <n.goaziou at gmail dot com>
;; Keywords: outlines, hypermedia, calendar, wp
@@ -22,79 +22,21 @@
;;; Commentary:
;;
-;; Org syntax can be divided into three categories: "Greater
-;; elements", "Elements" and "Objects".
+;; See <http://orgmode.org/worg/dev/org-syntax.html> for details about
+;; Org syntax.
;;
-;; Elements are related to the structure of the document. Indeed, all
-;; elements are a cover for the document: each position within belongs
-;; to at least one element.
-;;
-;; An element always starts and ends at the beginning of a line. With
-;; a few exceptions (`clock', `headline', `inlinetask', `item',
-;; `planning', `property-drawer', `node-property', `section' and
-;; `table-row' types), it can also accept a fixed set of keywords as
-;; attributes. Those are called "affiliated keywords" to distinguish
-;; them from other keywords, which are full-fledged elements. Almost
-;; all affiliated keywords are referenced in
-;; `org-element-affiliated-keywords'; the others are export attributes
-;; and start with "ATTR_" prefix.
-;;
-;; Element containing other elements (and only elements) are called
-;; greater elements. Concerned types are: `center-block', `drawer',
-;; `dynamic-block', `footnote-definition', `headline', `inlinetask',
-;; `item', `plain-list', `property-drawer', `quote-block', `section'
-;; and `special-block'.
-;;
-;; Other element types are: `babel-call', `clock', `comment',
-;; `comment-block', `diary-sexp', `example-block', `export-block',
-;; `fixed-width', `horizontal-rule', `keyword', `latex-environment',
-;; `node-property', `paragraph', `planning', `src-block', `table',
-;; `table-row' and `verse-block'. Among them, `paragraph' and
-;; `verse-block' types can contain Org objects and plain text.
-;;
-;; Objects are related to document's contents. Some of them are
-;; recursive. Associated types are of the following: `bold', `code',
-;; `entity', `export-snippet', `footnote-reference',
-;; `inline-babel-call', `inline-src-block', `italic',
-;; `latex-fragment', `line-break', `link', `macro', `radio-target',
-;; `statistics-cookie', `strike-through', `subscript', `superscript',
-;; `table-cell', `target', `timestamp', `underline' and `verbatim'.
-;;
-;; Some elements also have special properties whose value can hold
-;; objects themselves (e.g. an item tag or a headline name). Such
-;; values are called "secondary strings". Any object belongs to
-;; either an element or a secondary string.
-;;
-;; Notwithstanding affiliated keywords, each greater element, element
-;; and object has a fixed set of properties attached to it. Among
-;; them, four are shared by all types: `:begin' and `:end', which
-;; refer to the beginning and ending buffer positions of the
-;; considered element or object, `:post-blank', which holds the number
-;; of blank lines, or white spaces, at its end and `:parent' which
-;; refers to the element or object containing it. Greater elements,
-;; elements and objects containing objects will also have
-;; `:contents-begin' and `:contents-end' properties to delimit
-;; contents. Eventually, All elements have a `:post-affiliated'
-;; property referring to the buffer position after all affiliated
-;; keywords, if any, or to their beginning position otherwise.
-;;
-;; At the lowest level, a `:parent' property is also attached to any
-;; string, as a text property.
-;;
-;; Lisp-wise, an element or an object can be represented as a list.
+;; Lisp-wise, a syntax object can be represented as a list.
;; It follows the pattern (TYPE PROPERTIES CONTENTS), where:
-;; TYPE is a symbol describing the Org element or object.
+;; TYPE is a symbol describing the object.
;; PROPERTIES is the property list attached to it. See docstring of
-;; appropriate parsing function to get an exhaustive
-;; list.
-;; CONTENTS is a list of elements, objects or raw strings contained
-;; in the current element or object, when applicable.
+;; appropriate parsing function to get an exhaustive list.
+;; CONTENTS is a list of syntax objects or raw strings contained
+;; in the current object, when applicable.
;;
-;; An Org buffer is a nested list of such elements and objects, whose
-;; type is `org-data' and properties is nil.
+;; For the whole document, TYPE is `org-data' and PROPERTIES is nil.
;;
-;; The first part of this file defines Org syntax, while the second
-;; one provide accessors and setters functions.
+;; The first part of this file defines constants for the Org syntax,
+;; while the second one provide accessors and setters functions.
;;
;; The next part implements a parser and an interpreter for each
;; element and object type in Org syntax.
@@ -450,7 +392,7 @@ past the brackets."
;; There is `org-element-put-property', `org-element-set-contents'.
;; These low-level functions are useful to build a parse tree.
;;
-;; `org-element-adopt-element', `org-element-set-element',
+;; `org-element-adopt-elements', `org-element-set-element',
;; `org-element-extract-element' and `org-element-insert-before' are
;; high-level functions useful to modify a parse tree.
;;
@@ -593,16 +535,15 @@ Parse tree is modified by side effect."
(specialp (and (not property)
(eq siblings parent)
(eq (car parent) location))))
- ;; Install ELEMENT at the appropriate POSITION within SIBLINGS.
+ ;; Install ELEMENT at the appropriate LOCATION within SIBLINGS.
(cond (specialp)
((or (null siblings) (eq (car siblings) location))
(push element siblings))
((null location) (nconc siblings (list element)))
- (t (let ((previous (cadr (memq location (reverse siblings)))))
- (if (not previous)
- (error "No location found to insert element")
- (let ((next (memq previous siblings)))
- (setcdr next (cons element (cdr next))))))))
+ (t
+ (let ((index (cl-position location siblings)))
+ (unless index (error "No location found to insert element"))
+ (push element (cdr (nthcdr (1- index) siblings))))))
;; Store SIBLINGS at appropriate place in parse tree.
(cond
(specialp (setcdr parent (copy-sequence parent)) (setcar parent element))
@@ -850,7 +791,7 @@ CONTENTS is the contents of the element."
(format "#+BEGIN: %s%s\n%s#+END:"
(org-element-property :block-name dynamic-block)
(let ((args (org-element-property :arguments dynamic-block)))
- (and args (concat " " args)))
+ (if args (concat " " args) ""))
contents))
@@ -880,14 +821,14 @@ Assume point is at the beginning of the footnote definition."
(match-string-no-properties 1)))
(begin (car affiliated))
(post-affiliated (point))
- (ending
+ (end
(save-excursion
(end-of-line)
(cond
((not
(re-search-forward org-element--footnote-separator limit t))
limit)
- ((eq (char-after (match-beginning 0)) ?\[)
+ ((eq ?\[ (char-after (match-beginning 0)))
;; At a new footnote definition, make sure we end
;; before any affiliated keyword above.
(forward-line -1)
@@ -895,26 +836,27 @@ Assume point is at the beginning of the footnote definition."
(looking-at-p org-element--affiliated-re))
(forward-line -1))
(line-beginning-position 2))
- (t (match-beginning 0)))))
+ ((eq ?* (char-after (match-beginning 0))) (match-beginning 0))
+ (t (skip-chars-forward " \r\t\n" limit)
+ (if (= limit (point)) limit (line-beginning-position))))))
(contents-begin
- (progn
- (search-forward "]")
- (skip-chars-forward " \r\t\n" ending)
- (cond ((= (point) ending) nil)
- ((= (line-beginning-position) post-affiliated) (point))
- (t (line-beginning-position)))))
- (contents-end (and contents-begin ending))
- (end (progn (goto-char ending)
- (skip-chars-forward " \r\t\n" limit)
- (if (eobp) (point) (line-beginning-position)))))
+ (progn (search-forward "]")
+ (skip-chars-forward " \r\t\n" end)
+ (cond ((= (point) end) nil)
+ ((= (line-beginning-position) post-affiliated) (point))
+ (t (line-beginning-position)))))
+ (contents-end
+ (progn (goto-char end)
+ (skip-chars-backward " \r\t\n")
+ (line-beginning-position 2))))
(list 'footnote-definition
(nconc
(list :label label
:begin begin
:end end
:contents-begin contents-begin
- :contents-end contents-end
- :post-blank (count-lines ending end)
+ :contents-end (and contents-begin contents-end)
+ :post-blank (count-lines contents-end end)
:post-affiliated post-affiliated)
(cdr affiliated))))))
@@ -1696,30 +1638,37 @@ containing `:call', `:inside-header', `:arguments',
(save-excursion
(let* ((begin (car affiliated))
(post-affiliated (point))
- (value (progn (search-forward ":" nil t)
+ (before-blank (line-beginning-position 2))
+ (value (progn (search-forward ":" before-blank t)
+ (skip-chars-forward " \t")
(org-trim
(buffer-substring-no-properties
(point) (line-end-position)))))
- (pos-before-blank (progn (forward-line) (point)))
- (end (progn (skip-chars-forward " \r\t\n" limit)
- (if (eobp) (point) (line-beginning-position))))
- (valid-value
- (string-match
- "\\([^()\n]+?\\)\\(?:\\[\\(.*?\\)\\]\\)?(\\(.*\\))[ \t]*\\(.*\\)"
- value)))
+ (call
+ (or (org-string-nw-p
+ (buffer-substring-no-properties
+ (point) (progn (skip-chars-forward "^[]()" before-blank)
+ (point))))))
+ (inside-header (org-element--parse-paired-brackets ?\[))
+ (arguments (org-string-nw-p
+ (org-element--parse-paired-brackets ?\()))
+ (end-header
+ (org-string-nw-p
+ (org-trim
+ (buffer-substring-no-properties (point) (line-end-position)))))
+ (end (progn (forward-line)
+ (skip-chars-forward " \r\t\n" limit)
+ (if (eobp) (point) (line-beginning-position)))))
(list 'babel-call
(nconc
- (list :call (and valid-value (match-string 1 value))
- :inside-header (and valid-value
- (org-string-nw-p (match-string 2 value)))
- :arguments (and valid-value
- (org-string-nw-p (match-string 3 value)))
- :end-header (and valid-value
- (org-string-nw-p (match-string 4 value)))
+ (list :call call
+ :inside-header inside-header
+ :arguments arguments
+ :end-header end-header
:begin begin
:end end
:value value
- :post-blank (count-lines pos-before-blank end)
+ :post-blank (count-lines before-blank end)
:post-affiliated post-affiliated)
(cdr affiliated))))))
@@ -3041,7 +2990,8 @@ Assume point is at the beginning of the LaTeX fragment."
(search-forward "$" nil t 2)
(not (memq (char-before (match-beginning 0))
'(?\s ?\t ?\n ?, ?.)))
- (looking-at "\\(\\s.\\|\\s-\\|\\s(\\|\\s)\\|\\s\"\\|$\\)")
+ (looking-at-p
+ "\\(\\s.\\|\\s-\\|\\s(\\|\\s)\\|\\s\"\\|'\\|$\\)")
(point)))
(pcase (char-after (1+ (point)))
(?\( (search-forward "\\)" nil t))
@@ -3196,7 +3146,7 @@ Assume point is at the beginning of the link."
(when (string-match "::\\(.*\\)\\'" path)
(setq search-option (match-string 1 path))
(setq path (replace-match "" nil nil path)))
- (setq path (replace-regexp-in-string "\\`///+" "/" path)))
+ (setq path (replace-regexp-in-string "\\`///*\\(.:\\)?/" "\\1/" path)))
;; Translate link, if `org-link-translation-function' is set.
(let ((trans (and (functionp org-link-translation-function)
(funcall org-link-translation-function type path))))
@@ -4031,7 +3981,7 @@ Optional argument GRANULARITY determines the depth of the
recursion. It can be set to the following symbols:
`headline' Only parse headlines.
-`greater-element' Don't recurse into greater elements excepted
+`greater-element' Don't recurse into greater elements except
headlines and sections. Thus, elements
parsed are the top-level ones.
`element' Parse everything but objects and plain text.
@@ -4040,7 +3990,7 @@ recursion. It can be set to the following symbols:
When VISIBLE-ONLY is non-nil, don't parse contents of hidden
elements.
-An element or an objects is represented as a list with the
+An element or object is represented as a list with the
pattern (TYPE PROPERTIES CONTENTS), where :
TYPE is a symbol describing the element or object. See
@@ -4367,6 +4317,10 @@ to an appropriate container (e.g., a paragraph)."
(if (memq 'table-cell restriction) (org-element-table-cell-parser)
(let* ((start (point))
(limit
+ ;; Object regexp sometimes needs to have a peek at
+ ;; a character ahead. Therefore, when there is a hard
+ ;; limit, make it one more than the true beginning of the
+ ;; radio target.
(save-excursion
(cond ((not org-target-link-regexp) nil)
((not (memq 'link restriction)) nil)
@@ -4382,8 +4336,8 @@ to an appropriate container (e.g., a paragraph)."
((and (= start (1+ (line-beginning-position)))
(= start (match-end 1)))
(and (re-search-forward org-target-link-regexp nil t)
- (match-beginning 1)))
- (t (match-beginning 1)))))
+ (1+ (match-beginning 1))))
+ (t (1+ (match-beginning 1))))))
found)
(save-excursion
(while (and (not found)
@@ -4457,7 +4411,8 @@ to an appropriate container (e.g., a paragraph)."
(org-element-link-parser)))))))
(or (eobp) (forward-char))))
(cond (found)
- (limit (org-element-link-parser)) ;radio link
+ (limit (forward-char -1)
+ (org-element-link-parser)) ;radio link
(t nil))))))
(defun org-element--parse-objects (beg end acc restriction &optional parent)
@@ -4677,47 +4632,51 @@ indentation removed from its contents."
;; the beginnings of the contents or right after a line
;; break.
(lambda (blob first-flag min-ind)
- (catch 'zero
- (dolist (datum (org-element-contents blob) min-ind)
- (when first-flag
- (setq first-flag nil)
- (cond
- ;; Objects cannot start with spaces: in this
- ;; case, indentation is 0.
- ((not (stringp datum)) (throw 'zero 0))
- ((not (string-match
- "\\`\\([ \t]+\\)\\([^ \t\n]\\|\n\\|\\'\\)" datum))
- (throw 'zero 0))
- ((equal (match-string 2 datum) "\n")
- (put-text-property
- (match-beginning 1) (match-end 1) 'org-ind 'empty datum))
- (t
- (let ((i (string-width (match-string 1 datum))))
- (put-text-property
- (match-beginning 1) (match-end 1) 'org-ind i datum)
- (setq min-ind (min i min-ind))))))
+ (dolist (datum (org-element-contents blob) min-ind)
+ (when first-flag
+ (setq first-flag nil)
(cond
- ((stringp datum)
- (let ((s 0))
- (while (string-match
- "\n\\([ \t]+\\)\\([^ \t\n]\\|\n\\|\\'\\)" datum s)
- (setq s (match-end 1))
- (if (equal (match-string 2 datum) "\n")
- (put-text-property
- (match-beginning 1) (match-end 1)
- 'org-ind 'empty
- datum)
- (let ((i (string-width (match-string 1 datum))))
- (put-text-property
- (match-beginning 1) (match-end 1) 'org-ind i datum)
- (setq min-ind (min i min-ind)))))))
- ((eq (org-element-type datum) 'line-break)
- (setq first-flag t))
- ((memq (org-element-type datum) org-element-recursive-objects)
- (setq min-ind
- (funcall find-min-ind datum first-flag min-ind))))))))
- (min-ind (funcall find-min-ind
- element (not ignore-first) most-positive-fixnum)))
+ ;; Objects cannot start with spaces: in this
+ ;; case, indentation is 0.
+ ((not (stringp datum)) (throw :zero 0))
+ ((not (string-match
+ "\\`\\([ \t]+\\)\\([^ \t\n]\\|\n\\|\\'\\)" datum))
+ (throw :zero 0))
+ ((equal (match-string 2 datum) "\n")
+ (put-text-property
+ (match-beginning 1) (match-end 1) 'org-ind 'empty datum))
+ (t
+ (let ((i (string-width (match-string 1 datum))))
+ (put-text-property
+ (match-beginning 1) (match-end 1) 'org-ind i datum)
+ (setq min-ind (min i min-ind))))))
+ (cond
+ ((stringp datum)
+ (let ((s 0))
+ (while (string-match
+ "\n\\([ \t]*\\)\\([^ \t\n]\\|\n\\|\\'\\)" datum s)
+ (setq s (match-end 1))
+ (cond
+ ((equal (match-string 1 datum) "")
+ (unless (member (match-string 2 datum) '("" "\n"))
+ (throw :zero 0)))
+ ((equal (match-string 2 datum) "\n")
+ (put-text-property (match-beginning 1) (match-end 1)
+ 'org-ind 'empty datum))
+ (t
+ (let ((i (string-width (match-string 1 datum))))
+ (put-text-property (match-beginning 1) (match-end 1)
+ 'org-ind i datum)
+ (setq min-ind (min i min-ind))))))))
+ ((eq (org-element-type datum) 'line-break)
+ (setq first-flag t))
+ ((memq (org-element-type datum) org-element-recursive-objects)
+ (setq min-ind
+ (funcall find-min-ind datum first-flag min-ind)))))))
+ (min-ind
+ (catch :zero
+ (funcall find-min-ind
+ element (not ignore-first) most-positive-fixnum))))
(if (or (zerop min-ind) (= min-ind most-positive-fixnum)) element
;; Build ELEMENT back, replacing each string with the same
;; string minus common indentation.
@@ -4800,9 +4759,12 @@ indentation removed from its contents."
;; `org-element--cache-objects'.
-(defvar org-element-use-cache t
- "Non nil when Org parser should cache its results.
-This is mostly for debugging purpose.")
+(defvar org-element-use-cache nil
+ "Non-nil when Org parser should cache its results.
+
+WARNING: for the time being, using cache sometimes triggers
+freezes. Therefore, it is disabled by default. Activate it if
+you want to help debugging the issue.")
(defvar org-element-cache-sync-idle-time 0.6
"Length, in seconds, of idle time before syncing cache.")