forked from mirrors/org-mode
org-element: Parse affiliated keywords according to granularity
* lisp/org-element.el (org-element--current-element): Parse affiliated keywords according to granularity. * lisp/ox.el (org-export-get-caption): Refactor code. * testing/lisp/test-org-element.el (test-org-element/affiliated-keywords-parser): Add tests. Reported-by: ihor <ihor@antonovs.family> <http://lists.gnu.org/r/emacs-orgmode/2019-06/msg00023.html>
This commit is contained in:
parent
f4083eefd8
commit
bba9116cb8
|
@ -3899,7 +3899,8 @@ element it has to parse."
|
|||
((org-at-heading-p)
|
||||
(org-element-inlinetask-parser limit raw-secondary-p))
|
||||
;; From there, elements can have affiliated keywords.
|
||||
(t (let ((affiliated (org-element--collect-affiliated-keywords limit)))
|
||||
(t (let ((affiliated (org-element--collect-affiliated-keywords
|
||||
limit (memq granularity '(nil object)))))
|
||||
(cond
|
||||
;; Jumping over affiliated keywords put point off-limits.
|
||||
;; Parse them as regular keywords.
|
||||
|
@ -3985,7 +3986,7 @@ element it has to parse."
|
|||
;; that element, and, in the meantime, collect information they give
|
||||
;; into appropriate properties. Hence the following function.
|
||||
|
||||
(defun org-element--collect-affiliated-keywords (limit)
|
||||
(defun org-element--collect-affiliated-keywords (limit parse)
|
||||
"Collect affiliated keywords from point down to LIMIT.
|
||||
|
||||
Return a list whose CAR is the position at the first of them and
|
||||
|
@ -3994,13 +3995,16 @@ beginning of the first line after them.
|
|||
|
||||
As a special case, if element doesn't start at the beginning of
|
||||
the line (e.g., a paragraph starting an item), CAR is current
|
||||
position of point and CDR is nil."
|
||||
position of point and CDR is nil.
|
||||
|
||||
When PARSE is non-nil, values from keywords belonging to
|
||||
`org-element-parsed-keywords' are parsed as secondary strings."
|
||||
(if (not (bolp)) (list (point))
|
||||
(let ((case-fold-search t)
|
||||
(origin (point))
|
||||
;; RESTRICT is the list of objects allowed in parsed
|
||||
;; keywords value.
|
||||
(restrict (org-element-restriction 'keyword))
|
||||
;; keywords value. If PARSE is nil, no object is allowed.
|
||||
(restrict (and parse (org-element-restriction 'keyword)))
|
||||
output)
|
||||
(while (and (< (point) limit) (looking-at org-element--affiliated-re))
|
||||
(let* ((raw-kwd (upcase (match-string 1)))
|
||||
|
@ -4009,35 +4013,35 @@ position of point and CDR is nil."
|
|||
(kwd (or (cdr (assoc raw-kwd
|
||||
org-element-keyword-translation-alist))
|
||||
raw-kwd))
|
||||
;; PARSED? is non-nil when keyword should have its
|
||||
;; value parsed.
|
||||
(parsed? (member kwd org-element-parsed-keywords))
|
||||
;; Find main value for any keyword.
|
||||
(value
|
||||
(save-match-data
|
||||
(org-trim
|
||||
(buffer-substring-no-properties
|
||||
(match-end 0) (line-end-position)))))
|
||||
;; PARSEDP is non-nil when keyword should have its
|
||||
;; value parsed.
|
||||
(parsedp (member kwd org-element-parsed-keywords))
|
||||
;; If KWD is a dual keyword, find its secondary
|
||||
;; value. Maybe parse it.
|
||||
(dualp (member kwd org-element-dual-keywords))
|
||||
(let ((beg (match-end 0))
|
||||
(end (save-excursion
|
||||
(end-of-line)
|
||||
(skip-chars-backward " \t")
|
||||
(point))))
|
||||
(if parsed?
|
||||
(org-element--parse-objects beg end nil restrict)
|
||||
(org-trim (buffer-substring-no-properties beg end)))))
|
||||
;; If KWD is a dual keyword, find its secondary value.
|
||||
;; Maybe parse it.
|
||||
(dual? (member kwd org-element-dual-keywords))
|
||||
(dual-value
|
||||
(and dualp
|
||||
(and dual?
|
||||
(let ((sec (match-string-no-properties 2)))
|
||||
(if (or (not sec) (not parsedp)) sec
|
||||
(cond
|
||||
((and sec parsed?)
|
||||
(save-match-data
|
||||
(org-element--parse-objects
|
||||
(match-beginning 2) (match-end 2) nil restrict))))))
|
||||
(match-beginning 2) (match-end 2) nil restrict)))
|
||||
(sec sec)))))
|
||||
;; Attribute a property name to KWD.
|
||||
(kwd-sym (and kwd (intern (concat ":" (downcase kwd))))))
|
||||
;; Now set final shape for VALUE.
|
||||
(when parsedp
|
||||
(setq value
|
||||
(org-element--parse-objects
|
||||
(match-end 0)
|
||||
(progn (end-of-line) (skip-chars-backward " \t") (point))
|
||||
nil restrict)))
|
||||
(when dualp
|
||||
(when dual?
|
||||
(setq value (and (or value dual-value) (cons value dual-value))))
|
||||
(when (or (member kwd org-element-multiple-keywords)
|
||||
;; Attributes can always appear on multiple lines.
|
||||
|
|
22
lisp/ox.el
22
lisp/ox.el
|
@ -3716,18 +3716,24 @@ will become the empty string."
|
|||
(cdr (nreverse (cons (funcall prepare-value s) result))))))))
|
||||
(if property (plist-get attributes property) attributes)))
|
||||
|
||||
(defun org-export-get-caption (element &optional shortp)
|
||||
(defun org-export-get-caption (element &optional short)
|
||||
"Return caption from ELEMENT as a secondary string.
|
||||
|
||||
When optional argument SHORTP is non-nil, return short caption,
|
||||
as a secondary string, instead.
|
||||
When optional argument SHORT is non-nil, return short caption, as
|
||||
a secondary string, instead.
|
||||
|
||||
Caption lines are separated by a white space."
|
||||
(let ((full-caption (org-element-property :caption element)) caption)
|
||||
(dolist (line full-caption (cdr caption))
|
||||
(let ((cap (funcall (if shortp 'cdr 'car) line)))
|
||||
(when cap
|
||||
(setq caption (nconc (list " ") (copy-sequence cap) caption)))))))
|
||||
(let ((full-caption (org-element-property :caption element))
|
||||
(get (if short #'cdr #'car))
|
||||
caption)
|
||||
(dolist (line full-caption)
|
||||
(pcase (funcall get line)
|
||||
(`nil nil)
|
||||
(c
|
||||
(setq caption
|
||||
(nconc (list " ")
|
||||
(copy-sequence c) caption)))))
|
||||
(cdr caption)))
|
||||
|
||||
|
||||
;;;; For Derived Back-ends
|
||||
|
|
|
@ -376,12 +376,26 @@ Some other text
|
|||
(org-test-with-temp-text
|
||||
"#+ATTR_ASCII: line1\n#+ATTR_ASCII: line2\nParagraph"
|
||||
(org-element-at-point)))))
|
||||
;; Parse "parsed" keywords.
|
||||
;; Parse "parsed" keywords, unless granularity prevents it.
|
||||
(should
|
||||
(equal
|
||||
'(("caption"))
|
||||
(org-test-with-temp-text "#+CAPTION: caption\nParagraph"
|
||||
(car (org-element-property :caption (org-element-at-point))))))
|
||||
(should
|
||||
(org-test-with-temp-text "#+CAPTION: *caption*\nParagraph"
|
||||
(org-element-map (org-element-map (org-element-parse-buffer)
|
||||
'paragraph
|
||||
(lambda (e) (org-element-property :caption e)) nil t)
|
||||
'bold
|
||||
#'org-element-type nil t)))
|
||||
(should-not
|
||||
(org-test-with-temp-text "#+CAPTION: *caption*\nParagraph"
|
||||
(org-element-map (org-element-map (org-element-parse-buffer 'element)
|
||||
'paragraph
|
||||
(lambda (e) (org-element-property :caption e)) nil t)
|
||||
'bold
|
||||
#'org-element-type nil t)))
|
||||
;; Parse dual keywords.
|
||||
(should
|
||||
(equal
|
||||
|
|
Loading…
Reference in New Issue