Org document property-drawers
Add functionality to define property-blocks on document level, in addition to at headline level. * doc/org-manual.org: * etc/ORG-NEWS: Document new functionality. * lisp/org.el (org-keyword-regexp): Define constant instead of hardcoding. (org-file-properties): Renamed, see next line. (org-keyword-properties): Renamed from above. Due to the fact that properties can be defined for the whole document using property drawers this local variable needs a rename to make its name less ambigous. (org-refresh-properties, org-refresh-property, org-entry-properties) (org-refresh-category-properties, org-get-property-block) (org-entry-get-with-inheritance, org-entry-put) (org-insert-property-drawer, org-end-of-subtree): Made to work before first headline. (org-at-property-block-p): New function to validate if point is at the start of a property block. (org-property-global-value): Renamed, see next line. (org-property-global-or-keyword-value): Renamed from above to match its functionality better. (org-back-to-heading-or-point-min): New function to make a document work as a level 0 node in the outline. (org-at-keyword-p): Predicate function to answer to if we're currently at a keyword line or not. (org-up-heading-or-point-min): New function to make a document work as a level 0 node in the outline. * lisp/org-element.el (org-element--current-element): Can now detect property-blocks before first headline according to it's positional rules. * lisp/org-attach.el (org-attach): Make it possible to call the attachment dispatcher also before the first headline, since document property drawers make attachments possible for the whole document now. * lisp/org-capture.el: Modified only due to rename of function in org.el. * lisp/org-compat.el (org-file-properties) (org-property-global-value): Renamed functions declared obsolete. * testing/lisp/test-org.el (org/insert-property-drawer) (org/set-property, org/delete-property, org/delete-property-globally): Additions of tests to check if they work before first headline. (org/at-property-p, org/at-property-block-p, org/get-property-block) (org/entry-get, org/refresh-properties): New tests * testing/examples/property-inheritance.org: Switch from property-keywords to a property-drawer in the testfile. Functionality should be the same, but now using a document drawer instead of property-keywords. Reason for switching is that I'd like us to slowly depricate property-keywords. * testing/lisp/test-org-element.el: * contrib/lisp/ox-taskjuggler.el: A comment is modified only due to rename of function in org.el.
This commit is contained in:
parent
aa8500505f
commit
1bdff9f73d
|
@ -137,7 +137,7 @@
|
|||
;; :END:
|
||||
;;
|
||||
;;;; * TODO
|
||||
;; - Look at org-file-properties, org-global-properties and
|
||||
;; - Look at org-keyword-properties, org-global-properties and
|
||||
;; org-global-properties-fixed
|
||||
;; - What about property inheritance and org-property-inherit-p?
|
||||
;; - Use TYPE_TODO as an way to assign resources
|
||||
|
|
|
@ -4957,7 +4957,7 @@ with many examples, see [[*Matching tags and properties]].
|
|||
|
||||
A property is a key-value pair associated with an entry. Properties
|
||||
can be set so they are associated with a single entry, with every
|
||||
entry in a tree, or with every entry in an Org file.
|
||||
entry in a tree, or with the whole buffer.
|
||||
|
||||
There are two main applications for properties in Org mode. First,
|
||||
properties are like tags, but with a value. Imagine maintaining
|
||||
|
@ -5021,8 +5021,12 @@ disks in a box like this:
|
|||
:END:
|
||||
#+end_example
|
||||
|
||||
If you want to set properties that can be inherited by any entry in
|
||||
a file, use a line like:
|
||||
Properties can be inserted on buffer level. That means they apply
|
||||
before the first headline and can be inherited by all entries in a
|
||||
file. Property blocks defined before first headline needs to be
|
||||
located at the top of the buffer, allowing only comments above.
|
||||
|
||||
Properties can also be defined using lines like:
|
||||
|
||||
#+cindex: @samp{_ALL} suffix, in properties
|
||||
#+cindex: @samp{PROPERTY}, keyword
|
||||
|
@ -5087,7 +5091,8 @@ The following commands help to work with properties:
|
|||
#+findex: org-insert-drawer
|
||||
Insert a property drawer into the current entry. The drawer is
|
||||
inserted early in the entry, but after the lines with planning
|
||||
information like deadlines.
|
||||
information like deadlines. If before first headline the drawer is
|
||||
inserted at the top of the drawer after any potential comments.
|
||||
|
||||
- {{{kbd(C-c C-c)}}} (~org-property-action~) ::
|
||||
|
||||
|
@ -5310,11 +5315,6 @@ done by defining a column format line.
|
|||
:DESCRIPTION: Where defined, where valid?
|
||||
:END:
|
||||
|
||||
To define a column format for an entire file, use a line like:
|
||||
|
||||
#+cindex: @samp{COLUMNS}, keyword
|
||||
: #+COLUMNS: %25ITEM %TAGS %PRIORITY %TODO
|
||||
|
||||
To specify a format that only applies to a specific tree, add
|
||||
a =COLUMNS= property to the top node of that tree, for example:
|
||||
|
||||
|
@ -5325,6 +5325,13 @@ a =COLUMNS= property to the top node of that tree, for example:
|
|||
:END:
|
||||
#+end_example
|
||||
|
||||
A =COLUMNS= property within a property drawer before first headline
|
||||
will apply to the entire file. As an addition to property drawers,
|
||||
keywords can also be defined for an entire file using a line like:
|
||||
|
||||
#+cindex: @samp{COLUMNS}, keyword
|
||||
: #+COLUMNS: %25ITEM %TAGS %PRIORITY %TODO
|
||||
|
||||
If a =COLUMNS= property is present in an entry, it defines columns for
|
||||
the entry itself, and for the entire subtree below it. Since the
|
||||
column definition is part of the hierarchical structure of the
|
||||
|
|
12
etc/ORG-NEWS
12
etc/ORG-NEWS
|
@ -10,6 +10,16 @@ See the end of the file for license conditions.
|
|||
|
||||
Please send Org bug reports to mailto:emacs-orgmode@gnu.org.
|
||||
|
||||
* Version Next
|
||||
** New features
|
||||
*** Property drawers before first headline, outline level 0
|
||||
Property drawers will now work before first headline and Org mode is
|
||||
moving more towards making things before the first headline behave
|
||||
just as if it was at outline level 0. Inheritance for properties will
|
||||
work also for this level. In other words; defining things in a
|
||||
property drawer before the first headline will make them "inheritable"
|
||||
for all headlines.
|
||||
|
||||
* Version 9.3
|
||||
|
||||
** Incompatible changes
|
||||
|
@ -2171,7 +2181,7 @@ without changing the headline.
|
|||
|
||||
*** Hierarchies of tags
|
||||
|
||||
The functionality of nesting tags in hierarchies is added to org-mode.
|
||||
The functionality of nesting tags in hierarchies is added to Org mode.
|
||||
This is the generalization of what was previously called "Tag groups"
|
||||
in the manual. That term is now changed to "Tag hierarchy".
|
||||
|
||||
|
|
|
@ -244,7 +244,7 @@ Shows a list of commands and prompts for another key to execute a command."
|
|||
(when marker
|
||||
(set-buffer (marker-buffer marker))
|
||||
(goto-char marker))
|
||||
(org-back-to-heading t)
|
||||
(org-back-to-heading-or-point-min t)
|
||||
(save-excursion
|
||||
(save-window-excursion
|
||||
(unless org-attach-expert
|
||||
|
|
|
@ -1736,11 +1736,11 @@ The template may still contain \"%?\" for cursor positioning."
|
|||
(_ (error "Invalid `org-capture--clipboards' value: %S"
|
||||
org-capture--clipboards)))))
|
||||
("p"
|
||||
;; We remove file properties inherited from
|
||||
;; We remove keyword properties inherited from
|
||||
;; target buffer so `org-read-property-value' has
|
||||
;; a chance to find allowed values in sub-trees
|
||||
;; from the target buffer.
|
||||
(setq-local org-file-properties nil)
|
||||
(setq-local org-keyword-properties nil)
|
||||
(let* ((origin (set-marker (make-marker)
|
||||
(org-capture-get :pos)
|
||||
(org-capture-get :buffer)))
|
||||
|
|
|
@ -556,6 +556,12 @@ use of this function is for the stuck project list."
|
|||
(define-obsolete-function-alias 'org-make-link-regexps
|
||||
'org-link-make-regexps "Org 9.3")
|
||||
|
||||
(define-obsolete-function-alias 'org-file-properties
|
||||
'org-keyword-properties "Org 9.3")
|
||||
|
||||
(define-obsolete-function-alias 'org-property-global-value
|
||||
'org-property-global-or-keyword-value "Org 9.3")
|
||||
|
||||
(define-obsolete-variable-alias 'org-angle-link-re
|
||||
'org-link-angle-re "Org 9.3")
|
||||
|
||||
|
|
|
@ -3910,7 +3910,10 @@ element it has to parse."
|
|||
;; LaTeX Environment.
|
||||
((looking-at org-element--latex-begin-environment)
|
||||
(org-element-latex-environment-parser limit affiliated))
|
||||
;; Drawer and Property Drawer.
|
||||
;; Property drawer (before first headline, else it's catched above).
|
||||
((org-at-property-block-p)
|
||||
(org-element-property-drawer-parser limit))
|
||||
;; Drawer.
|
||||
((looking-at org-drawer-regexp)
|
||||
(org-element-drawer-parser limit affiliated))
|
||||
;; Fixed Width
|
||||
|
|
268
lisp/org.el
268
lisp/org.el
|
@ -348,6 +348,9 @@ FULL is given."
|
|||
|
||||
|
||||
;;; Syntax Constants
|
||||
;;;; Keyword
|
||||
(defconst org-keyword-regexp "^[ \t]*#\\+\\(\\S-+?\\):[ \t]*\\(.*\\)$"
|
||||
"Regular expression for keyword-lines")
|
||||
|
||||
;;;; Block
|
||||
|
||||
|
@ -3180,8 +3183,13 @@ This list will be combined with the constant `org-global-properties-fixed'.
|
|||
The entries in this list are cons cells where the car is a property
|
||||
name and cdr is a string with the value.
|
||||
|
||||
You can set buffer-local values for the same purpose in the variable
|
||||
`org-file-properties' this by adding lines like
|
||||
Buffer local properties are added either by a document property drawer
|
||||
|
||||
:PROPERTIES:
|
||||
:NAME: VALUE
|
||||
:END:
|
||||
|
||||
or by adding lines like
|
||||
|
||||
#+PROPERTY: NAME VALUE"
|
||||
:group 'org-properties
|
||||
|
@ -3189,10 +3197,14 @@ You can set buffer-local values for the same purpose in the variable
|
|||
(cons (string :tag "Property")
|
||||
(string :tag "Value"))))
|
||||
|
||||
(defvar-local org-file-properties nil
|
||||
(defvar-local org-keyword-properties nil
|
||||
"List of property/value pairs that can be inherited by any entry.
|
||||
Valid for the current buffer.
|
||||
This variable is populated from #+PROPERTY lines.")
|
||||
Valid for the current buffer. This variable is populated from
|
||||
#+PROPERTY lines.
|
||||
|
||||
Note that properties are defined also in property drawers.
|
||||
Properties defined there will take precedence over properties
|
||||
defined as keywords.")
|
||||
|
||||
(defgroup org-agenda nil
|
||||
"Options concerning agenda views in Org mode."
|
||||
|
@ -3201,11 +3213,18 @@ This variable is populated from #+PROPERTY lines.")
|
|||
|
||||
(defvar-local org-category nil
|
||||
"Variable used by Org files to set a category for agenda display.
|
||||
Such files should use a file variable to set it, for example
|
||||
There are multiple ways to set the category. One way is to set
|
||||
it in the document property drawer. For example:
|
||||
|
||||
:PROPERTIES:
|
||||
:CATEGORY: ELisp
|
||||
:END:
|
||||
|
||||
Other ways to define it is as an emacs file variable, for example
|
||||
|
||||
# -*- mode: org; org-category: \"ELisp\"
|
||||
|
||||
or contain a special line
|
||||
or for the file to contain a special line:
|
||||
|
||||
#+CATEGORY: ELisp
|
||||
|
||||
|
@ -4338,8 +4357,8 @@ related expressions."
|
|||
(setq org-tag-groups-alist
|
||||
(org-tag-alist-to-groups org-current-tag-alist))
|
||||
(unless tags-only
|
||||
;; File properties.
|
||||
(setq-local org-file-properties (cdr (assq 'property alist)))
|
||||
;; Properties.
|
||||
(setq-local org-keyword-properties (cdr (assq 'property alist)))
|
||||
;; Archive location.
|
||||
(let ((archive (cdr (assq 'archive alist))))
|
||||
(when archive (setq-local org-archive-location archive)))
|
||||
|
@ -4347,9 +4366,9 @@ related expressions."
|
|||
(let ((cat (org-string-nw-p (cdr (assq 'category alist)))))
|
||||
(when cat
|
||||
(setq-local org-category (intern cat))
|
||||
(setq-local org-file-properties
|
||||
(setq-local org-keyword-properties
|
||||
(org--update-property-plist
|
||||
"CATEGORY" cat org-file-properties))))
|
||||
"CATEGORY" cat org-keyword-properties))))
|
||||
;; Columns.
|
||||
(let ((column (cdr (assq 'columns alist))))
|
||||
(when column (setq-local org-columns-default-format column)))
|
||||
|
@ -8267,13 +8286,14 @@ the value of the drawer property."
|
|||
(inhibit-read-only t)
|
||||
(inherit? (org-property-inherit-p dprop))
|
||||
(property-re (org-re-property (concat (regexp-quote dprop) "\\+?") t))
|
||||
(global (and inherit? (org--property-global-value dprop nil))))
|
||||
(global-or-keyword (and inherit?
|
||||
(org--property-global-or-keyword-value dprop nil))))
|
||||
(with-silent-modifications
|
||||
(org-with-point-at 1
|
||||
;; Set global values (e.g., values defined through
|
||||
;; "#+PROPERTY:" keywords) to the whole buffer.
|
||||
(when global (put-text-property (point-min) (point-max) tprop global))
|
||||
;; Set local values.
|
||||
;; Set global and keyword based values to the whole buffer.
|
||||
(when global-or-keyword
|
||||
(put-text-property (point-min) (point-max) tprop global-or-keyword))
|
||||
;; Set values based on property-drawers throughout the document.
|
||||
(while (re-search-forward property-re nil t)
|
||||
(when (org-at-property-p)
|
||||
(org-refresh-property tprop (org-entry-get (point) dprop) inherit?))
|
||||
|
@ -8281,21 +8301,29 @@ the value of the drawer property."
|
|||
|
||||
(defun org-refresh-property (tprop p &optional inherit)
|
||||
"Refresh the buffer text property TPROP from the drawer property P.
|
||||
The refresh happens only for the current headline, or the whole
|
||||
sub-tree if optional argument INHERIT is non-nil."
|
||||
(unless (org-before-first-heading-p)
|
||||
(save-excursion
|
||||
(org-back-to-heading t)
|
||||
(let ((start (point))
|
||||
(end (save-excursion
|
||||
(if inherit (org-end-of-subtree t t)
|
||||
(or (outline-next-heading) (point-max))))))
|
||||
(if (symbolp tprop)
|
||||
;; TPROP is a text property symbol.
|
||||
(put-text-property start end tprop p)
|
||||
;; TPROP is an alist with (property . function) elements.
|
||||
(pcase-dolist (`(,prop . ,f) tprop)
|
||||
(put-text-property start end prop (funcall f p))))))))
|
||||
The refresh happens only for the current entry, or the whole
|
||||
sub-tree if optional argument INHERIT is non-nil.
|
||||
|
||||
If point is before first headline, the function applies to the
|
||||
part before the first headline. In that particular case, when
|
||||
optional argument INHERIT is non-nil, it refreshes properties for
|
||||
the whole buffer."
|
||||
(save-excursion
|
||||
(org-back-to-heading-or-point-min t)
|
||||
(let ((start (point))
|
||||
(end (save-excursion
|
||||
(cond ((and inherit (org-before-first-heading-p))
|
||||
(point-max))
|
||||
(inherit
|
||||
(org-end-of-subtree t t))
|
||||
((outline-next-heading))
|
||||
((point-max))))))
|
||||
(if (symbolp tprop)
|
||||
;; TPROP is a text property symbol.
|
||||
(put-text-property start end tprop p)
|
||||
;; TPROP is an alist with (property . function) elements.
|
||||
(pcase-dolist (`(,prop . ,f) tprop)
|
||||
(put-text-property start end prop (funcall f p)))))))
|
||||
|
||||
(defun org-refresh-category-properties ()
|
||||
"Refresh category text properties in the buffer."
|
||||
|
@ -8311,9 +8339,9 @@ sub-tree if optional argument INHERIT is non-nil."
|
|||
(t org-category))))
|
||||
(with-silent-modifications
|
||||
(org-with-wide-buffer
|
||||
;; Set buffer-wide category. Search last #+CATEGORY keyword.
|
||||
;; This is the default category for the buffer. If none is
|
||||
;; found, fall-back to `org-category' or buffer file name.
|
||||
;; Set buffer-wide property from keyword. Search last #+CATEGORY
|
||||
;; keyword. If none is found, fall-back to `org-category' or
|
||||
;; buffer file name, or set it by the document property drawer.
|
||||
(put-text-property
|
||||
(point-min) (point-max)
|
||||
'org-category
|
||||
|
@ -8325,15 +8353,20 @@ sub-tree if optional argument INHERIT is non-nil."
|
|||
(throw 'buffer-category
|
||||
(org-element-property :value element)))))
|
||||
default-category))
|
||||
;; Set sub-tree specific categories.
|
||||
;; Set categories from the document property drawer or
|
||||
;; property drawers in the outline. If category is found in
|
||||
;; the property drawer for the whole buffer that value
|
||||
;; overrides the keyword-based value set above.
|
||||
(goto-char (point-min))
|
||||
(let ((regexp (org-re-property "CATEGORY")))
|
||||
(while (re-search-forward regexp nil t)
|
||||
(let ((value (match-string-no-properties 3)))
|
||||
(when (org-at-property-p)
|
||||
(put-text-property
|
||||
(save-excursion (org-back-to-heading t) (point))
|
||||
(save-excursion (org-end-of-subtree t t) (point))
|
||||
(save-excursion (org-back-to-heading-or-point-min t))
|
||||
(save-excursion (if (org-before-first-heading-p)
|
||||
(point-max)
|
||||
(org-end-of-subtree t t)))
|
||||
'org-category
|
||||
value)))))))))
|
||||
|
||||
|
@ -12919,30 +12952,45 @@ Modifications are made by side-effect. Return new alist."
|
|||
|
||||
(defun org-get-property-block (&optional beg force)
|
||||
"Return the (beg . end) range of the body of the property drawer.
|
||||
BEG is the beginning of the current subtree, or of the part
|
||||
before the first headline. If it is not given, it will be found.
|
||||
If the drawer does not exist, create it if FORCE is non-nil, or
|
||||
return nil."
|
||||
BEG is the beginning of the current subtree or the beginning of
|
||||
the document if before the first headline. If it is not given,
|
||||
it will be found. If the drawer does not exist, create it if
|
||||
FORCE is non-nil, or return nil."
|
||||
(org-with-wide-buffer
|
||||
(when beg (goto-char beg))
|
||||
(unless (org-before-first-heading-p)
|
||||
(let ((beg (cond (beg)
|
||||
(let ((beg (cond (beg (goto-char beg))
|
||||
((or (not (featurep 'org-inlinetask))
|
||||
(org-inlinetask-in-task-p))
|
||||
(org-back-to-heading t))
|
||||
(t (org-with-limited-levels (org-back-to-heading t))))))
|
||||
(forward-line)
|
||||
(when (looking-at-p org-planning-line-re) (forward-line))
|
||||
(cond ((looking-at org-property-drawer-re)
|
||||
(forward-line)
|
||||
(cons (point) (progn (goto-char (match-end 0))
|
||||
(line-beginning-position))))
|
||||
(force
|
||||
(goto-char beg)
|
||||
(org-insert-property-drawer)
|
||||
(let ((pos (save-excursion (search-forward ":END:")
|
||||
(line-beginning-position))))
|
||||
(cons pos pos))))))))
|
||||
(org-back-to-heading-or-point-min t) (point))
|
||||
(t (org-with-limited-levels
|
||||
(org-back-to-heading-or-point-min t))
|
||||
(point)))))
|
||||
;; Move point to its position according to its positional rules.
|
||||
(cond ((org-before-first-heading-p)
|
||||
(while (and (org-at-comment-p) (bolp)) (forward-line)))
|
||||
(t (forward-line)
|
||||
(when (looking-at-p org-planning-line-re) (forward-line))))
|
||||
(cond ((looking-at org-property-drawer-re)
|
||||
(forward-line)
|
||||
(cons (point) (progn (goto-char (match-end 0))
|
||||
(line-beginning-position))))
|
||||
(force
|
||||
(goto-char beg)
|
||||
(org-insert-property-drawer)
|
||||
(let ((pos (save-excursion (re-search-forward org-property-drawer-re)
|
||||
(line-beginning-position))))
|
||||
(cons pos pos)))))))
|
||||
|
||||
(defun org-at-property-block-p ()
|
||||
"Return t when point is at the first line of a property drawer.
|
||||
The property drawer is validated according to its positional
|
||||
rules using `org-get-property-block'."
|
||||
(save-excursion
|
||||
(beginning-of-line)
|
||||
(and (looking-at org-property-start-re)
|
||||
(forward-line)
|
||||
(let ((property-drawer (org-get-property-block)))
|
||||
(and property-drawer
|
||||
(= (point) (car property-drawer)))))))
|
||||
|
||||
(defun org-at-property-p ()
|
||||
"Non-nil when point is inside a property drawer.
|
||||
|
@ -13027,7 +13075,7 @@ Return value is an alist. Keys are properties, as upcased
|
|||
strings."
|
||||
(org-with-point-at pom
|
||||
(when (and (derived-mode-p 'org-mode)
|
||||
(ignore-errors (org-back-to-heading t)))
|
||||
(org-back-to-heading-or-point-min t))
|
||||
(catch 'exit
|
||||
(let* ((beg (point))
|
||||
(specific (and (stringp which) (upcase which)))
|
||||
|
@ -13236,13 +13284,13 @@ unless LITERAL-NIL is non-nil."
|
|||
;; Return final values.
|
||||
(and (not (equal value '(nil))) (nreverse value))))))
|
||||
|
||||
(defun org--property-global-value (property literal-nil)
|
||||
"Return value for PROPERTY in current buffer.
|
||||
(defun org--property-global-or-keyword-value (property literal-nil)
|
||||
"Return value for PROPERTY as defined by global properties or by keyword.
|
||||
Return value is a string. Return nil if property is not set
|
||||
globally. Also return nil when PROPERTY is set to \"nil\",
|
||||
unless LITERAL-NIL is non-nil."
|
||||
globally or by keyword. Also return nil when PROPERTY is set to
|
||||
\"nil\", unless LITERAL-NIL is non-nil."
|
||||
(let ((global
|
||||
(cdr (or (assoc-string property org-file-properties t)
|
||||
(cdr (or (assoc-string property org-keyword-properties t)
|
||||
(assoc-string property org-global-properties t)
|
||||
(assoc-string property org-global-properties-fixed t)))))
|
||||
(if literal-nil global (org-not-nil global))))
|
||||
|
@ -13391,12 +13439,12 @@ However, if LITERAL-NIL is set, return the string value \"nil\" instead."
|
|||
value)))
|
||||
(cond
|
||||
((car v)
|
||||
(org-back-to-heading t)
|
||||
(org-back-to-heading-or-point-min t)
|
||||
(move-marker org-entry-property-inherited-from (point))
|
||||
(throw 'exit nil))
|
||||
((org-up-heading-safe))
|
||||
((org-up-heading-or-point-min))
|
||||
(t
|
||||
(let ((global (org--property-global-value property literal-nil)))
|
||||
(let ((global (org--property-global-or-keyword-value property literal-nil)))
|
||||
(cond ((not global))
|
||||
(value (setq value (concat global " " value)))
|
||||
(t (setq value global))))
|
||||
|
@ -13428,8 +13476,8 @@ decreases scheduled or deadline date by one day."
|
|||
(user-error "Invalid property name: \"%s\"" property)))
|
||||
(org-with-point-at pom
|
||||
(if (or (not (featurep 'org-inlinetask)) (org-inlinetask-in-task-p))
|
||||
(org-back-to-heading t)
|
||||
(org-with-limited-levels (org-back-to-heading t)))
|
||||
(org-back-to-heading-or-point-min t)
|
||||
(org-with-limited-levels (org-back-to-heading-or-point-min t)))
|
||||
(let ((beg (point)))
|
||||
(cond
|
||||
((equal property "TODO")
|
||||
|
@ -13565,19 +13613,26 @@ COLUMN formats in the current buffer."
|
|||
Do nothing if the drawer already exists. The newly created
|
||||
drawer is immediately hidden."
|
||||
(org-with-wide-buffer
|
||||
;; Set point to the position where the drawer should be inserted.
|
||||
(if (or (not (featurep 'org-inlinetask)) (org-inlinetask-in-task-p))
|
||||
(org-back-to-heading t)
|
||||
(org-with-limited-levels (org-back-to-heading t)))
|
||||
(forward-line)
|
||||
(when (looking-at-p org-planning-line-re) (forward-line))
|
||||
(org-back-to-heading-or-point-min t)
|
||||
(org-with-limited-levels (org-back-to-heading-or-point-min t)))
|
||||
(if (org-before-first-heading-p)
|
||||
(while (and (org-at-comment-p) (bolp)) (forward-line))
|
||||
(progn
|
||||
(forward-line)
|
||||
(when (looking-at-p org-planning-line-re) (forward-line))))
|
||||
(unless (looking-at-p org-property-drawer-re)
|
||||
;; Make sure we start editing a line from current entry, not from
|
||||
;; next one. It prevents extending text properties or overlays
|
||||
;; belonging to the latter.
|
||||
(when (bolp) (backward-char))
|
||||
(let ((begin (1+ (point)))
|
||||
(when (and (bolp) (> (point) (point-min))) (backward-char))
|
||||
(let ((begin (if (= (point) (point-min))
|
||||
(point)
|
||||
(1+ (point))))
|
||||
(inhibit-read-only t))
|
||||
(insert "\n:PROPERTIES:\n:END:")
|
||||
(unless (= begin (point-min)) (insert "\n"))
|
||||
(insert ":PROPERTIES:\n:END:")
|
||||
(org-flag-drawer t nil (line-end-position 0) (point))
|
||||
(when (eobp) (insert "\n"))
|
||||
(org-indent-region begin (point))))))
|
||||
|
@ -20482,6 +20537,15 @@ interactive command with similar behavior."
|
|||
(error (error "Before first headline at position %d in buffer %s"
|
||||
(point) (current-buffer)))))
|
||||
|
||||
(defun org-back-to-heading-or-point-min (&optional invisible-ok)
|
||||
"Go back to heading or first point in buffer.
|
||||
If point is before first heading go to first point in buffer
|
||||
instead of back to heading."
|
||||
(condition-case nil
|
||||
(outline-back-to-heading invisible-ok)
|
||||
(error
|
||||
(goto-char (point-min)))))
|
||||
|
||||
(defun org-before-first-heading-p ()
|
||||
"Before first heading?"
|
||||
(org-with-limited-levels
|
||||
|
@ -20515,6 +20579,12 @@ unless optional argument NO-INHERITANCE is non-nil."
|
|||
(beginning-of-line)
|
||||
(looking-at "^[ \t]*# "))))
|
||||
|
||||
(defun org-at-keyword-p nil
|
||||
"Return t if cursor is at a keyword-line."
|
||||
(save-excursion
|
||||
(move-beginning-of-line 1)
|
||||
(looking-at org-keyword-regexp)))
|
||||
|
||||
(defun org-at-drawer-p nil
|
||||
"Return t if cursor is at a drawer keyword."
|
||||
(save-excursion
|
||||
|
@ -20562,6 +20632,17 @@ make a significant difference in outlines with very many siblings."
|
|||
(re-search-backward (format "^\\*\\{1,%d\\} " level-up) nil t)
|
||||
(funcall outline-level)))))
|
||||
|
||||
(defun org-up-heading-or-point-min ()
|
||||
"Move to the heading line of which the present is a subheading, or point-min.
|
||||
This version is needed to make point-min behave like a virtual
|
||||
heading of level 0 for property-inheritance. It will return the
|
||||
level of the headline found (down to 0) or nil if already at a
|
||||
point before the first headline or at point-min."
|
||||
(when (ignore-errors (org-back-to-heading t))
|
||||
(if (< 1 (funcall outline-level))
|
||||
(org-up-heading-safe)
|
||||
(unless (= (point) (point-min)) (goto-char (point-min))))))
|
||||
|
||||
(defun org-first-sibling-p ()
|
||||
"Is this heading the first child of its parents?"
|
||||
(interactive)
|
||||
|
@ -20662,28 +20743,31 @@ If there is no such heading, return nil."
|
|||
(defun org-end-of-subtree (&optional invisible-ok to-heading)
|
||||
"Goto to the end of a subtree."
|
||||
;; This contains an exact copy of the original function, but it uses
|
||||
;; `org-back-to-heading', to make it work also in invisible
|
||||
;; trees. And is uses an invisible-ok argument.
|
||||
;; `org-back-to-heading-or-point-min', to make it work also in invisible
|
||||
;; trees and before first headline. And is uses an invisible-ok argument.
|
||||
;; Under Emacs this is not needed, but the old outline.el needs this fix.
|
||||
;; Furthermore, when used inside Org, finding the end of a large subtree
|
||||
;; with many children and grandchildren etc, this can be much faster
|
||||
;; than the outline version.
|
||||
(org-back-to-heading invisible-ok)
|
||||
(org-back-to-heading-or-point-min invisible-ok)
|
||||
(let ((first t)
|
||||
(level (funcall outline-level)))
|
||||
(if (and (derived-mode-p 'org-mode) (< level 1000))
|
||||
;; A true heading (not a plain list item), in Org
|
||||
;; This means we can easily find the end by looking
|
||||
;; only for the right number of stars. Using a regexp to do
|
||||
;; this is so much faster than using a Lisp loop.
|
||||
(let ((re (concat "^\\*\\{1," (int-to-string level) "\\} ")))
|
||||
(forward-char 1)
|
||||
(and (re-search-forward re nil 'move) (beginning-of-line 1)))
|
||||
;; something else, do it the slow way
|
||||
(while (and (not (eobp))
|
||||
(or first (> (funcall outline-level) level)))
|
||||
(setq first nil)
|
||||
(outline-next-heading)))
|
||||
(cond ((= level 0)
|
||||
(goto-char (point-max)))
|
||||
((and (derived-mode-p 'org-mode) (< level 1000))
|
||||
;; A true heading (not a plain list item), in Org
|
||||
;; This means we can easily find the end by looking
|
||||
;; only for the right number of stars. Using a regexp to do
|
||||
;; this is so much faster than using a Lisp loop.
|
||||
(let ((re (concat "^\\*\\{1," (int-to-string level) "\\} ")))
|
||||
(forward-char 1)
|
||||
(and (re-search-forward re nil 'move) (beginning-of-line 1))))
|
||||
(t
|
||||
;; something else, do it the slow way
|
||||
(while (and (not (eobp))
|
||||
(or first (> (funcall outline-level) level)))
|
||||
(setq first nil)
|
||||
(outline-next-heading))))
|
||||
(unless to-heading
|
||||
(when (memq (preceding-char) '(?\n ?\^M))
|
||||
;; Go to end of line before heading
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#+property: header-args :var foo=1
|
||||
#+property: header-args+ :var bar=2
|
||||
:PROPERTIES:
|
||||
:header-args: :var foo=1
|
||||
:header-args+: :var bar=2
|
||||
:END:
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(+ foo bar)
|
||||
|
|
|
@ -1925,6 +1925,15 @@ e^{i\\pi}+1=0
|
|||
(let ((element (org-element-at-point)))
|
||||
(list (org-element-property :key element)
|
||||
(org-element-property :value element))))))
|
||||
;; The insides of property blocks on document level are parsed the
|
||||
;; same way as headline property blocks. I.e. the concept of
|
||||
;; `node-property' apply also for properties in those blocks.
|
||||
(should
|
||||
(equal '("abc" "value")
|
||||
(org-test-with-temp-text ":PROPERTIES:\n<point>:abc: value\n:END:"
|
||||
(let ((element (org-element-at-point)))
|
||||
(list (org-element-property :key element)
|
||||
(org-element-property :value element))))))
|
||||
;; Value should be trimmed.
|
||||
(should
|
||||
(equal "value"
|
||||
|
@ -2111,6 +2120,18 @@ Outside list"
|
|||
(org-test-with-temp-text
|
||||
"* H\nDEADLINE: <2014-03-04 tue.>\n<point>:PROPERTIES:\n:prop: value\n:END:"
|
||||
(org-element-type (org-element-at-point)))))
|
||||
(should
|
||||
(eq 'property-drawer
|
||||
(org-test-with-temp-text "<point>:PROPERTIES:\n:prop: value\n:END:"
|
||||
(org-element-type (org-element-at-point)))))
|
||||
(should
|
||||
(eq 'property-drawer
|
||||
(org-test-with-temp-text "# C\n# C\n<point>:PROPERTIES:\n:prop: value\n:END:"
|
||||
(org-element-type (org-element-at-point)))))
|
||||
(should-not
|
||||
(eq 'property-drawer
|
||||
(org-test-with-temp-text "\n<point>:PROPERTIES:\n:prop: value\n:END:"
|
||||
(org-element-type (org-element-at-point)))))
|
||||
;; Allow properties without value and no property at all.
|
||||
(should
|
||||
(eq 'property-drawer
|
||||
|
|
|
@ -386,10 +386,112 @@
|
|||
|
||||
;;; Drawers
|
||||
|
||||
(ert-deftest test-org/at-property-p ()
|
||||
"Test `org-at-property-p' specifications."
|
||||
(should
|
||||
(equal 't
|
||||
(org-test-with-temp-text "* H\n:PROPERTIES:\n<point>:PROP: t\n:END:\n"
|
||||
(org-at-property-p))))
|
||||
(should
|
||||
(equal 't
|
||||
(org-test-with-temp-text ":PROPERTIES:\n<point>:PROP: t\n:END:\n"
|
||||
(org-at-property-p)))))
|
||||
|
||||
(ert-deftest test-org/at-property-block-p ()
|
||||
"Test `org-at-property-block-p' specifications."
|
||||
(should
|
||||
(equal 't
|
||||
(org-test-with-temp-text "* H\n<point>:PROPERTIES:\n:PROP: t\n:END:\n"
|
||||
(org-at-property-block-p))))
|
||||
(should
|
||||
(equal 't
|
||||
(org-test-with-temp-text ":PROPERTIES:\n:PROP: t\n:END:\n"
|
||||
(org-at-property-block-p))))
|
||||
;; The function only returns t if point is at the first line of a
|
||||
;; property block.
|
||||
(should-not
|
||||
(equal 't
|
||||
(org-test-with-temp-text ":PROPERTIES:\n<point>:PROP: t\n:END:\n"
|
||||
(org-at-property-block-p)))))
|
||||
|
||||
(ert-deftest test-org/get-property-block ()
|
||||
"Test `org-get-property-block' specifications."
|
||||
(should
|
||||
(equal '(14 . 14)
|
||||
(org-test-with-temp-text ":PROPERTIES:\n:END:\n* H\n"
|
||||
(org-get-property-block))))
|
||||
(should
|
||||
(equal '(14 . 14)
|
||||
(org-test-with-temp-text ":PROPERTIES:\n:END:\n"
|
||||
(org-get-property-block))))
|
||||
;; Comments above a document property block is ok.
|
||||
(should
|
||||
(equal '(18 . 18)
|
||||
(org-test-with-temp-text "# C\n:PROPERTIES:\n:END:\n"
|
||||
(org-get-property-block))))
|
||||
;; Keywords above a document property block is ok.
|
||||
(should
|
||||
(equal '(22 . 22)
|
||||
(org-test-with-temp-text "# C\n# C\n:PROPERTIES:\n:END:\n"
|
||||
(org-get-property-block))))
|
||||
;; Comments and keywords are allowed before a document property block.
|
||||
(should
|
||||
(equal '(18 . 27)
|
||||
(org-test-with-temp-text "# C\n:PROPERTIES:\n:KEY: V:\n:END:\n"
|
||||
(org-get-property-block))))
|
||||
;; A document property block will not be valid if there are lines
|
||||
;; with whitespace above it
|
||||
(should-not
|
||||
(org-test-with-temp-text "\n:PROPERTIES:\n:END:\n"
|
||||
(org-get-property-block)))
|
||||
(should
|
||||
(equal '(18 . 18)
|
||||
(org-test-with-temp-text "* H\n:PROPERTIES:\n:END:\n<point>"
|
||||
(org-get-property-block))))
|
||||
(should
|
||||
(equal "* H\n:PROPERTIES:\n:END:\n"
|
||||
(org-test-with-temp-text "* H"
|
||||
(let ((org-adapt-indentation nil))
|
||||
(org-get-property-block nil 'force))
|
||||
(buffer-string))))
|
||||
(should
|
||||
(equal ":PROPERTIES:\n:END:\n"
|
||||
(org-test-with-temp-text ""
|
||||
(org-get-property-block nil 'force)
|
||||
(buffer-string))))
|
||||
(should
|
||||
(equal "* H1\n :PROPERTIES:\n :END:\n* H2"
|
||||
(org-test-with-temp-text "* H1\n* H2"
|
||||
(let ((org-adapt-indentation t))
|
||||
(org-get-property-block nil 'force))
|
||||
(buffer-string)))))
|
||||
|
||||
(ert-deftest test-org/insert-property-drawer ()
|
||||
"Test `org-insert-property-drawer' specifications."
|
||||
;; Error before first headline.
|
||||
(should-error (org-test-with-temp-text "" (org-insert-property-drawer)))
|
||||
;; Insert drawer in empty buffer
|
||||
(should
|
||||
(equal ":PROPERTIES:\n:END:\n"
|
||||
(org-test-with-temp-text ""
|
||||
(let ((org-adapt-indentation nil)) (org-insert-property-drawer))
|
||||
(buffer-string))))
|
||||
;; Insert drawer in document header with existing comment and
|
||||
;; keyword.
|
||||
(should
|
||||
(equal "# C\n:PROPERTIES:\n:END:\n#+TITLE: T"
|
||||
(org-test-with-temp-text "# C\n#+TITLE: T"
|
||||
(let ((org-adapt-indentation nil)) (org-insert-property-drawer))
|
||||
(buffer-string))))
|
||||
(should
|
||||
(equal ":PROPERTIES:\n:END:"
|
||||
(org-test-with-temp-text ":PROPERTIES:\n:END:"
|
||||
(let ((org-adapt-indentation nil)) (org-insert-property-drawer))
|
||||
(buffer-string))))
|
||||
;; Insert drawer in document header with one existing heading in buffer.
|
||||
(should
|
||||
(equal ":PROPERTIES:\n:END:\n* T\n"
|
||||
(org-test-with-temp-text "<point>\n* T\n"
|
||||
(let ((org-adapt-indentation nil)) (org-insert-property-drawer))
|
||||
(buffer-string))))
|
||||
;; Insert drawer right after headline if there is no planning line,
|
||||
;; or after it otherwise.
|
||||
(should
|
||||
|
@ -2178,19 +2280,19 @@ SCHEDULED: <2014-03-04 tue.>"
|
|||
(equal "foo=1"
|
||||
(org-test-with-temp-text "#+PROPERTY: var foo=1"
|
||||
(org-mode-restart)
|
||||
(cdr (assoc "var" org-file-properties)))))
|
||||
(cdr (assoc "var" org-keyword-properties)))))
|
||||
(should
|
||||
(equal
|
||||
"foo=1 bar=2"
|
||||
(org-test-with-temp-text "#+PROPERTY: var foo=1\n#+PROPERTY: var+ bar=2"
|
||||
(org-mode-restart)
|
||||
(cdr (assoc "var" org-file-properties)))))
|
||||
(cdr (assoc "var" org-keyword-properties)))))
|
||||
(should
|
||||
(equal
|
||||
"foo=1 bar=2"
|
||||
(org-test-with-temp-text "#+PROPERTY: var foo=1\n#+PROPERTY: VAR+ bar=2"
|
||||
(org-mode-restart)
|
||||
(cdr (assoc "var" org-file-properties)))))
|
||||
(cdr (assoc "var" org-keyword-properties)))))
|
||||
;; ARCHIVE keyword.
|
||||
(should
|
||||
(equal "%s_done::"
|
||||
|
@ -2207,7 +2309,7 @@ SCHEDULED: <2014-03-04 tue.>"
|
|||
(equal "test"
|
||||
(org-test-with-temp-text "#+CATEGORY: test"
|
||||
(org-mode-restart)
|
||||
(cdr (assoc "CATEGORY" org-file-properties)))))
|
||||
(cdr (assoc "CATEGORY" org-keyword-properties)))))
|
||||
;; COLUMNS keyword.
|
||||
(should
|
||||
(equal "%25ITEM %TAGS %PRIORITY %TODO"
|
||||
|
@ -2291,7 +2393,7 @@ SCHEDULED: <2014-03-04 tue.>"
|
|||
(org-test-with-temp-text
|
||||
(format "#+SETUPFILE: \"%s/examples/setupfile.org\"" org-test-dir)
|
||||
(org-mode-restart)
|
||||
(cdr (assoc "a" org-file-properties))))))
|
||||
(cdr (assoc "a" org-keyword-properties))))))
|
||||
|
||||
|
||||
|
||||
|
@ -4941,6 +5043,66 @@ Paragraph<point>"
|
|||
(org-test-with-temp-text "* H\n:PROPERTIES:\n:A: 1\n:A+: 2\n:END:"
|
||||
(org-property-values "A")))))
|
||||
|
||||
(ert-deftest test-org/set-property ()
|
||||
"Test `org-set-property' specifications."
|
||||
(should
|
||||
(equal
|
||||
":PROPERTIES:\n:TEST: t\n:END:\n"
|
||||
(org-test-with-temp-text ""
|
||||
(let ((org-property-format "%s %s"))
|
||||
(org-set-property "TEST" "t"))
|
||||
(buffer-string))))
|
||||
(should
|
||||
(equal
|
||||
"* H\n:PROPERTIES:\n:TEST: t\n:END:\n"
|
||||
(org-test-with-temp-text "* H"
|
||||
(let ((org-adapt-indentation nil)
|
||||
(org-property-format "%s %s"))
|
||||
(org-set-property "TEST" "t"))
|
||||
(buffer-string)))))
|
||||
|
||||
(ert-deftest test-org/delete-property ()
|
||||
"Test `org-delete-property' specifications."
|
||||
(should
|
||||
(equal
|
||||
""
|
||||
(org-test-with-temp-text ":PROPERTIES:\n:TEST: t\n:END:\n"
|
||||
(org-delete-property "TEST")
|
||||
(buffer-string))))
|
||||
(should
|
||||
(equal
|
||||
":PROPERTIES:\n:TEST1: t\n:END:\n"
|
||||
(org-test-with-temp-text ":PROPERTIES:\n:TEST1: t\n:TEST2: t\n:END:\n"
|
||||
(org-delete-property "TEST2")
|
||||
(buffer-string))))
|
||||
(should
|
||||
(equal
|
||||
"* H\n"
|
||||
(org-test-with-temp-text "* H\n:PROPERTIES:\n:TEST: t\n:END:\n"
|
||||
(org-delete-property "TEST")
|
||||
(buffer-string))))
|
||||
(should
|
||||
(equal
|
||||
"* H\n:PROPERTIES:\n:TEST1: t\n:END:\n"
|
||||
(org-test-with-temp-text "* H\n:PROPERTIES:\n:TEST1: t\n:TEST2: t\n:END:\n"
|
||||
(org-delete-property "TEST2")
|
||||
(buffer-string)))))
|
||||
|
||||
(ert-deftest test-org/delete-property-globally ()
|
||||
"Test `org-delete-property-global' specifications."
|
||||
(should
|
||||
(equal
|
||||
""
|
||||
(org-test-with-temp-text ":PROPERTIES:\n:TEST: t\n:END:\n"
|
||||
(org-delete-property-globally "TEST")
|
||||
(buffer-string))))
|
||||
(should
|
||||
(equal
|
||||
"* H\n"
|
||||
(org-test-with-temp-text ":PROPERTIES:\n:TEST: t\n:END:\n* H\n:PROPERTIES:\n:TEST: nil\n:END:"
|
||||
(org-delete-property-globally "TEST")
|
||||
(buffer-string)))))
|
||||
|
||||
(ert-deftest test-org/find-property ()
|
||||
"Test `org-find-property' specifications."
|
||||
;; Regular test.
|
||||
|
@ -5022,6 +5184,10 @@ Paragraph<point>"
|
|||
(ert-deftest test-org/entry-get ()
|
||||
"Test `org-entry-get' specifications."
|
||||
;; Regular test.
|
||||
(should
|
||||
(equal "1"
|
||||
(org-test-with-temp-text ":PROPERTIES:\n:A: 1\n:END:"
|
||||
(org-entry-get (point) "A"))))
|
||||
(should
|
||||
(equal "1"
|
||||
(org-test-with-temp-text "* H\n:PROPERTIES:\n:A: 1\n:END:"
|
||||
|
@ -5061,6 +5227,11 @@ Paragraph<point>"
|
|||
(org-entry-get (point) "B" nil t)))
|
||||
;; Handle inheritance, when allowed. Include extended values and
|
||||
;; possibly global values.
|
||||
(should
|
||||
(equal
|
||||
"1"
|
||||
(org-test-with-temp-text ":PROPERTIES:\n:A: 1\n:END:\n* H"
|
||||
(org-entry-get (point-max) "A" t))))
|
||||
(should
|
||||
(equal
|
||||
"1"
|
||||
|
@ -5076,12 +5247,30 @@ Paragraph<point>"
|
|||
(org-test-with-temp-text "* H\n:PROPERTIES:\n:A: 1\n:END:\n** H2"
|
||||
(let ((org-use-property-inheritance nil))
|
||||
(org-entry-get (point-max) "A" 'selective))))
|
||||
(should
|
||||
(equal
|
||||
"1 2"
|
||||
(org-test-with-temp-text
|
||||
":PROPERTIES:\n:A: 1\n:END:\n* H\n:PROPERTIES:\n:A+: 2\n:END:"
|
||||
(org-entry-get (point-max) "A" t))))
|
||||
(should
|
||||
(equal
|
||||
"1 2"
|
||||
(org-test-with-temp-text
|
||||
"* H\n:PROPERTIES:\n:A: 1\n:END:\n** H2\n:PROPERTIES:\n:A+: 2\n:END:"
|
||||
(org-entry-get (point-max) "A" t))))
|
||||
(should
|
||||
(equal
|
||||
"1 2"
|
||||
(org-test-with-temp-text
|
||||
":PROPERTIES:\n:A: 1\n:END:\n* H1\n* H2\n:PROPERTIES:\n:A+: 2\n:END:"
|
||||
(org-entry-get (point-max) "A" t))))
|
||||
(should
|
||||
(equal
|
||||
"1 2"
|
||||
(org-test-with-temp-text
|
||||
"* H1\n:PROPERTIES:\n:A: 1\n:END:\n* H2.1\n* H2.2\n:PROPERTIES:\n:A+: 2\n:END:"
|
||||
(org-entry-get (point-max) "A" t))))
|
||||
(should
|
||||
(equal "1"
|
||||
(org-test-with-temp-text
|
||||
|
@ -5093,6 +5282,14 @@ Paragraph<point>"
|
|||
(org-test-with-temp-text
|
||||
"#+PROPERTY: A 0\n* H\n:PROPERTIES:\n:A+: 1\n:END:"
|
||||
(org-mode-restart)
|
||||
(org-entry-get (point-max) "A" t))))
|
||||
;; document level property-drawer has precedance over
|
||||
;; global-property by PROPERTY-keyword.
|
||||
(should
|
||||
(equal "0 2"
|
||||
(org-test-with-temp-text
|
||||
":PROPERTIES:\n:A: 0\n:END:\n#+PROPERTY: A 1\n* H\n:PROPERTIES:\n:A+: 2\n:END:"
|
||||
(org-mode-restart)
|
||||
(org-entry-get (point-max) "A" t)))))
|
||||
|
||||
(ert-deftest test-org/entry-properties ()
|
||||
|
@ -5416,8 +5613,44 @@ Paragraph<point>"
|
|||
(let ((org-use-property-inheritance t))
|
||||
(org-refresh-properties "A" 'org-test))
|
||||
(get-text-property (point) 'org-test))))
|
||||
;; When a document level property-drawer is used, those properties
|
||||
;; should work exactly like headline-properties as if at a
|
||||
;; headline-level 0.
|
||||
(should
|
||||
(equal "1"
|
||||
(org-test-with-temp-text
|
||||
":PROPERTIES:\n:A: 1\n:END:\n"
|
||||
(org-mode-restart)
|
||||
(let ((org-use-property-inheritance t))
|
||||
(org-refresh-properties "A" 'org-test))
|
||||
(get-text-property (point) 'org-test))))
|
||||
(should-not
|
||||
(equal "1"
|
||||
(org-test-with-temp-text
|
||||
":PROPERTIES:\n:A: 1\n:END:\n<point>* H1"
|
||||
(org-mode-restart)
|
||||
(let ((org-use-property-inheritance nil))
|
||||
(org-refresh-properties "A" 'org-test))
|
||||
(get-text-property (point) 'org-test))))
|
||||
(should
|
||||
(equal "1"
|
||||
(org-test-with-temp-text
|
||||
":PROPERTIES:\n:A: 1\n:END:\n<point>* H1"
|
||||
(org-mode-restart)
|
||||
(let ((org-use-property-inheritance t))
|
||||
(org-refresh-properties "A" 'org-test))
|
||||
(get-text-property (point) 'org-test))))
|
||||
(should
|
||||
(equal "2"
|
||||
(org-test-with-temp-text
|
||||
":PROPERTIES:\n:A: 1\n:END:\n<point>* H1\n:PROPERTIES:\n:A: 2\n:END:"
|
||||
(org-mode-restart)
|
||||
(let ((org-use-property-inheritance t))
|
||||
(org-refresh-properties "A" 'org-test))
|
||||
(get-text-property (point) 'org-test))))
|
||||
;; When property is inherited, use global value across the whole
|
||||
;; buffer. However local values have precedence.
|
||||
;; buffer. However local values have precedence, as well as the
|
||||
;; document level property-drawer.
|
||||
(should-not
|
||||
(equal "1"
|
||||
(org-test-with-temp-text "#+PROPERTY: A 1\n<point>* H1"
|
||||
|
@ -5437,10 +5670,62 @@ Paragraph<point>"
|
|||
(org-test-with-temp-text
|
||||
"#+PROPERTY: A 1\n<point>* H\n:PROPERTIES:\n:A: 2\n:END:"
|
||||
(org-mode-restart)
|
||||
(let ((org-use-property-inheritance t))
|
||||
(org-refresh-properties "A" 'org-test))
|
||||
(get-text-property (point) 'org-test))))
|
||||
;; When both keyword-property and document-level property-block is
|
||||
;; defined, the property-block has precedance.
|
||||
(should
|
||||
(equal "1"
|
||||
(org-test-with-temp-text
|
||||
":PROPERTIES:\n:A: 1\n:END:\n#+PROPERTY: A 2\n<point>* H1"
|
||||
(org-mode-restart)
|
||||
(let ((org-use-property-inheritance t))
|
||||
(org-refresh-properties "A" 'org-test))
|
||||
(get-text-property (point) 'org-test)))))
|
||||
|
||||
(ert-deftest test-org/refresh-category-properties ()
|
||||
"Test `org-refresh-category-properties' specifications"
|
||||
(should
|
||||
(equal "cat1"
|
||||
(org-test-with-temp-text
|
||||
":PROPERTIES:\n:CATEGORY: cat1\n:END:"
|
||||
(org-refresh-category-properties)
|
||||
(get-text-property (point) 'org-category))))
|
||||
(should
|
||||
(equal "cat1"
|
||||
(org-test-with-temp-text
|
||||
"* H\n:PROPERTIES:\n:CATEGORY: cat1\n:END:"
|
||||
(org-refresh-category-properties)
|
||||
(get-text-property (point) 'org-category))))
|
||||
;; Even though property-inheritance is deactivated, category
|
||||
;; property should be inherited. As described in
|
||||
;; `org-use-property-inheritance'.
|
||||
(should
|
||||
(equal "cat1"
|
||||
(org-test-with-temp-text
|
||||
":PROPERTIES:\n:CATEGORY: cat1\n:END:\n<point>* H"
|
||||
(org-mode-restart)
|
||||
(let ((org-use-property-inheritance nil))
|
||||
(org-refresh-category-properties))
|
||||
(get-text-property (point) 'org-category))))
|
||||
(should
|
||||
(equal "cat1"
|
||||
(org-test-with-temp-text
|
||||
":PROPERTIES:\n:CATEGORY: cat1\n:END:\n<point>* H"
|
||||
(org-mode-restart)
|
||||
(let ((org-use-property-inheritance t))
|
||||
(org-refresh-category-properties))
|
||||
(get-text-property (point) 'org-category))))
|
||||
(should
|
||||
(equal "cat2"
|
||||
(org-test-with-temp-text
|
||||
":PROPERTIES:\n:CATEGORY: cat1\n:END:\n<point>* H\n:PROPERTIES:\n:CATEGORY: cat2\n:END:\n"
|
||||
(org-mode-restart)
|
||||
(let ((org-use-property-inheritance t))
|
||||
(org-refresh-category-properties))
|
||||
(get-text-property (point) 'org-category)))))
|
||||
|
||||
|
||||
;;; Refile
|
||||
|
||||
|
|
Loading…
Reference in New Issue