summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Goaziou <mail@nicolasgoaziou.fr>2014-06-18 21:28:19 (GMT)
committer Nicolas Goaziou <mail@nicolasgoaziou.fr>2014-06-18 21:28:19 (GMT)
commitab145f0df553e0bb77795c946ff158d8c069f6e4 (patch)
treea20d17167174b6e0787eb482d1ef9c8b52449c44
parentb1dcd0fb0bec6b523c900bc1304fbe834c21697d (diff)
downloadorg-mode-ab145f0df553e0bb77795c946ff158d8c069f6e4.zip
org-mode-ab145f0df553e0bb77795c946ff158d8c069f6e4.tar.gz
org-element: Properly parse headline properties
* lisp/org-element.el (org-element-headline-parser, org-element-inlinetask-parser): First find appropriate property drawer in order to read properties. * testing/lisp/test-org-element.el (test-org-element/headline-properties): Add tests. Thanks to S├ębastien Vauban for reporting it. http://permalink.gmane.org/gmane.emacs.orgmode/87701
-rw-r--r--lisp/org-element.el132
-rw-r--r--testing/lisp/test-org-element.el28
2 files changed, 113 insertions, 47 deletions
diff --git a/lisp/org-element.el b/lisp/org-element.el
index 5af513f..f0fc09a 100644
--- a/lisp/org-element.el
+++ b/lisp/org-element.el
@@ -811,24 +811,48 @@ Assume point is at beginning of the headline."
(archivedp (member org-archive-tag tags))
(footnote-section-p (and org-footnote-section
(string= org-footnote-section raw-value)))
- ;; Upcase property names. It avoids confusion between
- ;; properties obtained through property drawer and default
- ;; properties from the parser (e.g. `:end' and :END:)
(standard-props
- (let (plist)
- (mapc
- (lambda (p)
- (setq plist
- (plist-put plist
- (intern (concat ":" (upcase (car p))))
- (cdr p))))
- (org-entry-properties nil 'standard))
- plist))
+ ;; Find property drawer associated to current headline and
+ ;; extract properties.
+ ;;
+ ;; Upcase property names. It avoids confusion between
+ ;; properties obtained through property drawer and default
+ ;; properties from the parser (e.g. `:end' and :END:)
+ (let ((end (save-excursion
+ (org-with-limited-levels (outline-next-heading))
+ (point)))
+ plist)
+ (save-excursion
+ (while (and (null plist)
+ (re-search-forward org-property-start-re end t))
+ (let ((drawer (org-element-at-point)))
+ (when (and (eq (org-element-type drawer) 'property-drawer)
+ ;; Make sure drawer is not associated
+ ;; to an inlinetask.
+ (let ((p drawer))
+ (while (and (setq p (org-element-property
+ :parent p))
+ (not (eq (org-element-type p)
+ 'inlinetask))))
+ (not p)))
+ (let ((end (org-element-property :contents-end drawer)))
+ (when end
+ (forward-line)
+ (while (< (point) end)
+ (looking-at org-property-re)
+ (setq plist
+ (plist-put
+ plist
+ (intern
+ (concat ":" (upcase (match-string 2))))
+ (org-match-string-no-properties 3)))
+ (forward-line)))))))
+ plist)))
(time-props
;; Read time properties on the line below the headline.
(save-excursion
- (when (progn (forward-line)
- (looking-at org-planning-or-clock-line-re))
+ (forward-line)
+ (when (looking-at org-planning-or-clock-line-re)
(let ((end (line-end-position)) plist)
(while (re-search-forward
org-keyword-time-not-clock-regexp end t)
@@ -974,43 +998,59 @@ Assume point is at beginning of the inline task."
(tags (let ((raw-tags (nth 5 components)))
(and raw-tags (org-split-string raw-tags ":"))))
(raw-value (or (nth 4 components) ""))
- ;; Upcase property names. It avoids confusion between
- ;; properties obtained through property drawer and default
- ;; properties from the parser (e.g. `:end' and :END:)
- (standard-props
- (let (plist)
- (mapc
- (lambda (p)
- (setq plist
- (plist-put plist
- (intern (concat ":" (upcase (car p))))
- (cdr p))))
- (org-entry-properties nil 'standard))
- plist))
- (time-props
- ;; Read time properties on the line below the inlinetask
- ;; opening string.
- (save-excursion
- (when (progn (forward-line)
- (looking-at org-planning-or-clock-line-re))
- (let ((end (line-end-position)) plist)
- (while (re-search-forward
- org-keyword-time-not-clock-regexp end t)
- (goto-char (match-end 1))
- (skip-chars-forward " \t")
- (let ((keyword (match-string 1))
- (time (org-element-timestamp-parser)))
- (cond ((equal keyword org-scheduled-string)
- (setq plist (plist-put plist :scheduled time)))
- ((equal keyword org-deadline-string)
- (setq plist (plist-put plist :deadline time)))
- (t (setq plist (plist-put plist :closed time))))))
- plist))))
(task-end (save-excursion
(end-of-line)
(and (re-search-forward org-outline-regexp-bol limit t)
(org-looking-at-p "END[ \t]*$")
(line-beginning-position))))
+ (standard-props
+ ;; Find property drawer associated to current inlinetask
+ ;; and extract properties.
+ ;;
+ ;; Upcase property names. It avoids confusion between
+ ;; properties obtained through property drawer and default
+ ;; properties from the parser (e.g. `:end' and :END:)
+ (when task-end
+ (let (plist)
+ (save-excursion
+ (while (and (null plist)
+ (re-search-forward
+ org-property-start-re task-end t))
+ (let ((d (org-element-at-point)))
+ (when (eq (org-element-type d) 'property-drawer)
+ (let ((end (org-element-property :contents-end d)))
+ (when end
+ (forward-line)
+ (while (< (point) end)
+ (looking-at org-property-re)
+ (setq plist
+ (plist-put
+ plist
+ (intern
+ (concat ":" (upcase (match-string 2))))
+ (org-match-string-no-properties 3)))
+ (forward-line)))))))
+ plist))))
+ (time-props
+ ;; Read time properties on the line below the inlinetask
+ ;; opening string.
+ (when task-end
+ (save-excursion
+ (when (progn (forward-line)
+ (looking-at org-planning-or-clock-line-re))
+ (let ((end (line-end-position)) plist)
+ (while (re-search-forward
+ org-keyword-time-not-clock-regexp end t)
+ (goto-char (match-end 1))
+ (skip-chars-forward " \t")
+ (let ((keyword (match-string 1))
+ (time (org-element-timestamp-parser)))
+ (cond ((equal keyword org-scheduled-string)
+ (setq plist (plist-put plist :scheduled time)))
+ ((equal keyword org-deadline-string)
+ (setq plist (plist-put plist :deadline time)))
+ (t (setq plist (plist-put plist :closed time))))))
+ plist)))))
(contents-begin (progn (forward-line)
(and task-end (< (point) task-end) (point))))
(contents-end (and contents-begin task-end))
diff --git a/testing/lisp/test-org-element.el b/testing/lisp/test-org-element.el
index d3a5428..da45193 100644
--- a/testing/lisp/test-org-element.el
+++ b/testing/lisp/test-org-element.el
@@ -1003,7 +1003,33 @@ Some other text
(org-element-property :FOO (org-element-at-point))))
(should-not
(org-test-with-temp-text "* Headline\n:PROPERTIES:\n:foo: bar\n:END:"
- (org-element-property :foo (org-element-at-point)))))
+ (org-element-property :foo (org-element-at-point))))
+ ;; Do not find property drawer in a verbatim area.
+ (should-not
+ (org-test-with-temp-text
+ "* Headline
+#+BEGIN_EXAMPLE
+:PROPERTIES:
+:foo: bar
+:END:
+#+END_EXAMPLE"
+ (org-element-property :FOO (org-element-at-point))))
+ ;; Do not use properties from a drawer associated to an inlinetask.
+ (when (featurep 'org-inlinetask)
+ (should-not
+ (org-test-with-temp-text
+ "* Headline
+*************** Inlinetask
+:PROPERTIES:
+:foo: bar
+:END:
+*************** END"
+ (org-element-property
+ :FOO (let ((org-inlinetask-min-level 15)) (org-element-at-point))))))
+ ;; Do not find incomplete drawers.
+ (should-not
+ (org-test-with-temp-text "* Headline\n:PROPERTIES:\n:foo: bar"
+ (org-element-property :FOO (org-element-at-point)))))
;;;; Horizontal Rule