emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
* [RFC] Document level property drawer
@ 2019-09-29 10:27 Gustav Wikström
  2019-09-29 19:13 ` Marco Wahl
                   ` (3 more replies)
  0 siblings, 4 replies; 23+ messages in thread
From: Gustav Wikström @ 2019-09-29 10:27 UTC (permalink / raw)
  To: emacs-orgmode; +Cc: Nicolas Goaziou

[-- Attachment #1: Type: text/plain, Size: 1584 bytes --]

Hi,

This patch introduces a document level property drawer. 

This has been discussed previously in a larger context:
- https://lists.gnu.org/archive/html/emacs-orgmode/2019-06/msg00000.html
- https://lists.gnu.org/archive/html/emacs-orgmode/2019-08/msg00339.html 
- https://lists.gnu.org/archive/html/emacs-orgmode/2019-09/msg00010.html

The patch is a somewhat modified version of what was included in the third 
link above.

The following will be true for document level property drawers:
1) In the same way that one can have a property drawer for a heading, one
   can have a property drawer for a whole document.
2) All existing commands that can work with property drawers will
   (shall) work also on property drawers before the first heading.
3) Properties defined in a property drawer will have precedence over
   properties defined as a property keyword, if the same property is
   defined using both conventions.
4) The position for the document level property drawer is:
   - At the first line in a file that is not a comment or a keyword.

     I.e. the following will work:
     #+begin_src org
       # -*- mode: org -*-
       ,#+TITLE: Test
       :PROPERTIES:
       :CATEGORY: Test
       :END:

       Preamble 

       ,* Some heading
       Some content
     #+end_src

     but not this:
     #+begin_src org
       Some comment and/or empty line

       :PROPERTIES:
       :CATEGORY: Test
       :END:

       ,* Some heading
       Some content
     #+end_src

What do you say?

Regards
Gustav Wikström

[-- Attachment #2: 0001-Org-document-property-drawers.patch --]
[-- Type: application/octet-stream, Size: 45416 bytes --]

From 91dad61268b0c2a6efe9c9fa5cee868434d33b76 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gustav=20Wikstr=C3=B6m?= <gustav@whil.se>
Date: Sun, 26 May 2019 22:13:09 +0200
Subject: [PATCH] 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.
---
 contrib/lisp/ox-taskjuggler.el            |   2 +-
 doc/org-manual.org                        |  27 +-
 etc/ORG-NEWS                              |  10 +-
 lisp/org-attach.el                        |   2 +-
 lisp/org-capture.el                       |   4 +-
 lisp/org-compat.el                        |   6 +
 lisp/org-element.el                       |   5 +-
 lisp/org.el                               | 268 ++++++++++++-------
 testing/examples/property-inheritance.org |   6 +-
 testing/lisp/test-org-element.el          |  21 ++
 testing/lisp/test-org.el                  | 305 +++++++++++++++++++++-
 11 files changed, 539 insertions(+), 117 deletions(-)

diff --git a/contrib/lisp/ox-taskjuggler.el b/contrib/lisp/ox-taskjuggler.el
index 16a6a3a74..bc90b93a4 100644
--- a/contrib/lisp/ox-taskjuggler.el
+++ b/contrib/lisp/ox-taskjuggler.el
@@ -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
diff --git a/doc/org-manual.org b/doc/org-manual.org
index f2f059e77..8358620ca 100644
--- a/doc/org-manual.org
+++ b/doc/org-manual.org
@@ -4951,7 +4951,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
@@ -5015,8 +5015,13 @@ 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 and keywords
+above.
+
+Properties can also be defined using lines like:
 
 #+cindex: @samp{_ALL} suffix, in properties
 #+cindex: @samp{PROPERTY}, keyword
@@ -5081,7 +5086,9 @@ 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 or
+  keywords.
 
 - {{{kbd(C-c C-c)}}} (~org-property-action~) ::
 
@@ -5304,11 +5311,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:
 
@@ -5319,6 +5321,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
diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index 9fff4ad16..716818720 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -130,6 +130,14 @@ Export ignore done tasks with a deadline when
 Likewise, scheduled done tasks are also ignored when
 ~org-icalendar-use-scheduled~ contains the same symbol.
 
+*** 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.
+
 *** Add split-window-right option for src block edit window placement
 Given the increasing popularity of wide screen monitors, splitting
 horizontally may make more sense than splitting vertically.  An
@@ -2165,7 +2173,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".
 
diff --git a/lisp/org-attach.el b/lisp/org-attach.el
index 2138a2807..b2f948c2e 100644
--- a/lisp/org-attach.el
+++ b/lisp/org-attach.el
@@ -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
diff --git a/lisp/org-capture.el b/lisp/org-capture.el
index 4f97e17ea..67343e02a 100644
--- a/lisp/org-capture.el
+++ b/lisp/org-capture.el
@@ -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)))
diff --git a/lisp/org-compat.el b/lisp/org-compat.el
index 4446a169d..c167ba908 100644
--- a/lisp/org-compat.el
+++ b/lisp/org-compat.el
@@ -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")
 
diff --git a/lisp/org-element.el b/lisp/org-element.el
index 56b3cc413..110ff5624 100644
--- a/lisp/org-element.el
+++ b/lisp/org-element.el
@@ -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
diff --git a/lisp/org.el b/lisp/org.el
index cb83bef3b..cbc476644 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -350,6 +350,9 @@ FULL is given."
 
 \f
 ;;; Syntax Constants
+;;;; Keyword
+(defconst org-keyword-regexp "^[ \t]*#\\+\\(\\S-+?\\):[ \t]*\\(.*\\)$"
+  "Regular expression for keyword-lines")
 
 ;;;; Block
 
@@ -3182,8 +3185,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
@@ -3191,10 +3199,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."
@@ -3203,11 +3215,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
 
@@ -4340,8 +4359,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)))
@@ -4349,9 +4368,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)))
@@ -8269,13 +8288,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?))
@@ -8283,21 +8303,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."
@@ -8313,9 +8341,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
@@ -8327,15 +8355,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)))))))))
 
@@ -12921,30 +12954,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 (bolp) (or (org-at-keyword-p) (org-at-comment-p))) (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.
@@ -13029,7 +13077,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)))
@@ -13238,13 +13286,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))))
@@ -13393,12 +13441,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))))
@@ -13430,8 +13478,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")
@@ -13567,19 +13615,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 (bolp) (or (org-at-keyword-p) (org-at-comment-p))) (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))))))
@@ -20484,6 +20539,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
@@ -20517,6 +20581,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
@@ -20564,6 +20634,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)
@@ -20664,28 +20745,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
diff --git a/testing/examples/property-inheritance.org b/testing/examples/property-inheritance.org
index 6979de595..9c0b7e662 100644
--- a/testing/examples/property-inheritance.org
+++ b/testing/examples/property-inheritance.org
@@ -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)
diff --git a/testing/lisp/test-org-element.el b/testing/lisp/test-org-element.el
index f2ab38031..1408e6be5 100644
--- a/testing/lisp/test-org-element.el
+++ b/testing/lisp/test-org-element.el
@@ -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#+Key: V\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
diff --git a/testing/lisp/test-org.el b/testing/lisp/test-org.el
index 215d8fdb0..1b3fb48bb 100644
--- a/testing/lisp/test-org.el
+++ b/testing/lisp/test-org.el
@@ -386,10 +386,116 @@
 \f
 ;;; 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 '(23 . 23)
+	  (org-test-with-temp-text "#+Key: v\n:PROPERTIES:\n:END:\n"
+	    (org-get-property-block))))
+  ;; Comments and keywords are allowed before a document property block.
+  (should
+   (equal '(27 . 36)
+	  (org-test-with-temp-text "# C\n#+key: v\n:PROPERTIES:\n:KEY: V:\n:END:\n"
+	    (org-get-property-block))))
+  (should
+   (equal '(36 . 45)
+	  (org-test-with-temp-text "#+Key: v\n# C\n#+Key: v\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#+TITLE: T\n:PROPERTIES:\n:END:\n"
+	  (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 +2284,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 +2313,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 +2397,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))))))
 
 
 \f
@@ -4941,6 +5047,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 +5188,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 +5231,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 +5251,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 +5286,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 +5617,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 +5674,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)))))
+
 \f
 ;;; Refile
 
-- 
2.17.1


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC] Document level property drawer
  2019-09-29 10:27 [RFC] Document level property drawer Gustav Wikström
@ 2019-09-29 19:13 ` Marco Wahl
  2019-09-30 16:01 ` Adam Porter
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 23+ messages in thread
From: Marco Wahl @ 2019-09-29 19:13 UTC (permalink / raw)
  To: emacs-orgmode

Hi,

> This patch introduces a document level property drawer. 

[...]

> What do you say?

I'll install the patch and have a look how it feels in my little
personal Org universe.


Thanks,
-- 
Marco

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC] Document level property drawer
  2019-09-29 10:27 [RFC] Document level property drawer Gustav Wikström
  2019-09-29 19:13 ` Marco Wahl
@ 2019-09-30 16:01 ` Adam Porter
  2019-09-30 20:46   ` Marco Wahl
  2019-10-15 17:49 ` Gustav Wikström
  2020-01-20  3:27 ` [Question] adding document global properties drawer stardiviner
  3 siblings, 1 reply; 23+ messages in thread
From: Adam Porter @ 2019-09-30 16:01 UTC (permalink / raw)
  To: emacs-orgmode

Gustav Wikström <gustav@whil.se> writes:

> Hi,
>
> This patch introduces a document level property drawer. 
>
> This has been discussed previously in a larger context:
> - https://lists.gnu.org/archive/html/emacs-orgmode/2019-06/msg00000.html
> - https://lists.gnu.org/archive/html/emacs-orgmode/2019-08/msg00339.html 
> - https://lists.gnu.org/archive/html/emacs-orgmode/2019-09/msg00010.html
>
> The patch is a somewhat modified version of what was included in the third 
> link above.

How does it differ from what was previously proposed?

> The following will be true for document level property drawers:
> 1) In the same way that one can have a property drawer for a heading, one
>    can have a property drawer for a whole document.
> 2) All existing commands that can work with property drawers will
>    (shall) work also on property drawers before the first heading.

What exactly does "will (shall)" mean?

> 3) Properties defined in a property drawer will have precedence over
>    properties defined as a property keyword, if the same property is
>    defined using both conventions.

That protocol seems unnatural and confusing to me:

- If precedence were to be defined by something other than file-order,
  it seems to me that those defined with #+ keywords should have
  precedence, because they are more visible, while those in drawers are
  hidden.
- However, it seems to me that the simplest, most natural protocol would
  be for later declarations to override earlier ones.

> 4) The position for the document level property drawer is:
>    - At the first line in a file that is not a comment or a keyword.
>
>      I.e. the following will work:
>
>      #+begin_src org
>        # -*- mode: org -*-
>        ,#+TITLE: Test
>        :PROPERTIES:
>        :CATEGORY: Test
>        :END:
>
>        Preamble 
>
>        ,* Some heading
>        Some content
>      #+end_src
>
>
>      but not this:
>
>      #+begin_src org
>        Some comment and/or empty line
>
>        :PROPERTIES:
>        :CATEGORY: Test
>        :END:
>
>        ,* Some heading
>        Some content
>      #+end_src

That feels unintuitive to me.  Document-level property keywords may
appear anywhere in a file, so it seems inconsistent for document-level
property drawers to be limited in this way, as if there were an implied
headline at the top of the file.  If it were so, I would expect to see
many mailing list posts by users asking why the properties defined in
their document-level property drawers aren't working.  Given that there
is no enforcement in Org's UI to keep such drawers in certain places, I
think the implementation should be tolerant of users' preferences and
mistakes (cf. Postel's Law).

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC] Document level property drawer
  2019-09-30 16:01 ` Adam Porter
@ 2019-09-30 20:46   ` Marco Wahl
  2019-10-01 12:38     ` Sebastian Miele
  2019-10-01 13:55     ` Adam Porter
  0 siblings, 2 replies; 23+ messages in thread
From: Marco Wahl @ 2019-09-30 20:46 UTC (permalink / raw)
  To: emacs-orgmode

Adam Porter <adam@alphapapa.net> writes:

> Gustav Wikström <gustav@whil.se> writes:
>
>> 3) Properties defined in a property drawer will have precedence over
>>    properties defined as a property keyword, if the same property is
>>    defined using both conventions.
>
> That protocol seems unnatural and confusing to me:
>
> - If precedence were to be defined by something other than file-order,
>   it seems to me that those defined with #+ keywords should have
>   precedence, because they are more visible, while those in drawers are
>   hidden.
> - However, it seems to me that the simplest, most natural protocol would
>   be for later declarations to override earlier ones.

I think it would be quite natural to use the tree structure of Org.  A
property setting in a subtree overrides the setting in a parent (which
could be the document(= the whole file.))

>> 4) The position for the document level property drawer is:
>>    - At the first line in a file that is not a comment or a keyword.
>>
>>      I.e. the following will work:
>>
>>      #+begin_src org
>>        # -*- mode: org -*-
>>        ,#+TITLE: Test
>>        :PROPERTIES:
>>        :CATEGORY: Test
>>        :END:
>>
>>        Preamble
>>
>>        ,* Some heading
>>        Some content
>>      #+end_src

[...]

> That feels unintuitive to me.  Document-level property keywords may
> appear anywhere in a file, so it seems inconsistent for document-level
> property drawers to be limited in this way, as if there were an implied
> headline at the top of the file.  If it were so, I would expect to see
> many mailing list posts by users asking why the properties defined in
> their document-level property drawers aren't working.  Given that there
> is no enforcement in Org's UI to keep such drawers in certain places, I
> think the implementation should be tolerant of users' preferences and
> mistakes (cf. Postel's Law).

TBH allowing document-level properties anywhere in an Org file looks
rather messy to me.  When a user is interested in all the document-level
properties she needs to scan the whole file.  Also the spread out
document-level properties introduce a distinction between a whole Org
file and an Org subtree.

I think the distinction between Org file and Org subtree should be kept
to a minimum.  Wouldn't it be nice if Org files can be considered as Org
subtrees?  In this sense a property drawer for the document is a step in
the right direction.


Ciao,
--
Marco

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC] Document level property drawer
  2019-09-30 20:46   ` Marco Wahl
@ 2019-10-01 12:38     ` Sebastian Miele
  2020-01-13 21:52       ` Marco Wahl
  2019-10-01 13:55     ` Adam Porter
  1 sibling, 1 reply; 23+ messages in thread
From: Sebastian Miele @ 2019-10-01 12:38 UTC (permalink / raw)
  To: emacs-orgmode

Marco Wahl <marcowahlsoft@gmail.com> writes:

> [..]
>
> I think the distinction between Org file and Org subtree should be kept
> to a minimum.  Wouldn't it be nice if Org files can be considered as Org
> subtrees?

Yes, this would be very nice.

I have a related question or proposal.

Up until now, I basically do not use property drawers except absolutely
necessary, because properties are invisible by default. Properties "need
to be inserted into a [..] drawer", and "in order to look inside the
drawer, you need to move point to the drawer line and press ‘<TAB>’
there."

A place that comes to mind where I really would like to use properties
is the header-args property in order to specify parameters related to
tangling for all src blocks in certain subtrees.

But for such properties to satisfactorily work for me, they would have
to be visible by default. E.g. I would want the header-args to be
immediately visible just like they are when they are written after
#+BEGIN_SRC or #+HEADER. Otherwise I would find myself constantly
wondering whether this or that property drawer contains something
essential and every TAB on a collapsed headline would have be followed
by an accompanying move to the property drawer and a TAB there.

On the other hand, there are properties that are very good candidates
for remaining hidden by default, like ID.

I would like to be able to make a clear distinction between properties
that are visible by default and properties that are not. Maybe it would
be possible to allow some #+.. syntax following headings for subtree
properties that are visible by default. A requirement could be made that
such property specifications always have to be followed by a property
drawer, even if that is empty. Then everything #+.. that is before the
property drawer would belong to the heading/subtree, and everything #+..
that follows the drawer would be treated as it is until now.

Please tell me if I missed something and Org is already capable of
something like that. If not, are there others who would like
visible-by-default property specifications for headings/subtrees in
addition to invisible-by-default property specifications in drawers,
too?

Finally, I would like to state an opinion: If there is
visible-by-default (by #+..) and invisible-by-default (by drawers)
syntax for headings/subtrees, including level 0, it may be viable to
require them to be disjoint for each heading/subtree. Most probably it
would be good practice, anyway. And the precedence question raised
previously in this thread would be eliminated.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC] Document level property drawer
  2019-09-30 20:46   ` Marco Wahl
  2019-10-01 12:38     ` Sebastian Miele
@ 2019-10-01 13:55     ` Adam Porter
  2019-10-02 10:29       ` Marco Wahl
  1 sibling, 1 reply; 23+ messages in thread
From: Adam Porter @ 2019-10-01 13:55 UTC (permalink / raw)
  To: emacs-orgmode

Marco Wahl <marcowahlsoft@gmail.com> writes:

> Adam Porter <adam@alphapapa.net> writes:
>
>> Gustav Wikström <gustav@whil.se> writes:
>>
>>> 3) Properties defined in a property drawer will have precedence over
>>>    properties defined as a property keyword, if the same property is
>>>    defined using both conventions.
>>
>> That protocol seems unnatural and confusing to me:
>>
>> - If precedence were to be defined by something other than file-order,
>>   it seems to me that those defined with #+ keywords should have
>>   precedence, because they are more visible, while those in drawers are
>>   hidden.
>> - However, it seems to me that the simplest, most natural protocol would
>>   be for later declarations to override earlier ones.
>
> I think it would be quite natural to use the tree structure of Org.  A
> property setting in a subtree overrides the setting in a parent (which
> could be the document(= the whole file.))

Hi Marco,

I think you misunderstood his point #3 and my objection to it.  :)

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC] Document level property drawer
  2019-10-01 13:55     ` Adam Porter
@ 2019-10-02 10:29       ` Marco Wahl
  2019-10-03 18:06         ` Adam Porter
  0 siblings, 1 reply; 23+ messages in thread
From: Marco Wahl @ 2019-10-02 10:29 UTC (permalink / raw)
  To: emacs-orgmode

Adam Porter <adam@alphapapa.net> writes:

> Marco Wahl <marcowahlsoft@gmail.com> writes:
>
>> Adam Porter <adam@alphapapa.net> writes:
>>
>>> Gustav Wikström <gustav@whil.se> writes:
>>>
>>>> 3) Properties defined in a property drawer will have precedence over
>>>>    properties defined as a property keyword, if the same property is
>>>>    defined using both conventions.
>>>
>>> That protocol seems unnatural and confusing to me:
>>>
>>> - If precedence were to be defined by something other than file-order,
>>>   it seems to me that those defined with #+ keywords should have
>>>   precedence, because they are more visible, while those in drawers are
>>>   hidden.
>>> - However, it seems to me that the simplest, most natural protocol would
>>>   be for later declarations to override earlier ones.
>>
>> I think it would be quite natural to use the tree structure of Org.  A
>> property setting in a subtree overrides the setting in a parent (which
>> could be the document(= the whole file.))
>
> Hi Marco,
>
> I think you misunderstood his point #3 and my objection to it.  :)

Hi Adam,

that's possible but I don't think so.  But I'm willing to learn if
I didn't get it. :)

Possibly a concrete example can help.  Let's take Org property CATEGORY
for illustration.

First to Gustav's statement 3):

Let the file be this:

--8<---------------cut here---------------start------------->8---
#+title: file
:PROPERTIES:
:CATEGORY: cat-doc-prop-drawer
:END:

* foo
SCHEDULED: <2019-10-02 Wed>

#+CATEGORY:  cat-doc-prop-keyword-1

** bar

:somedrawer:
#+CATEGORY:  cat-doc-prop-keyword-2
:END:
--8<---------------cut here---------------end--------------->8---

With Gustav's proposition the CATEGORY of task foo is
cat-doc-prop-drawer.

Next to your statements:

You say the visibility is better for the #+-property keywords.  I say
they can occur _anywhere_ in the file and even in some drawers.  See
above "#+CATEGORY:  cat-doc-prop-keyword-2".

Further you say 

>>> - However, it seems to me that the simplest, most natural protocol would
>>>   be for later declarations to override earlier ones.

This means that cat-doc-prop-keyword-2 from the example defines the
CATEGORY property which at least I find not so natural.  And I already
stated what I find natural.


Best regards,  Marco

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC] Document level property drawer
  2019-10-02 10:29       ` Marco Wahl
@ 2019-10-03 18:06         ` Adam Porter
  2019-10-04 11:05           ` Marco Wahl
  0 siblings, 1 reply; 23+ messages in thread
From: Adam Porter @ 2019-10-03 18:06 UTC (permalink / raw)
  To: emacs-orgmode

Marco Wahl <marcowahlsoft@gmail.com> writes:

> You say the visibility is better for the #+-property keywords.  I say
> they can occur _anywhere_ in the file and even in some drawers.  See
> above "#+CATEGORY:  cat-doc-prop-keyword-2".
>
> Further you say 
>
>>>> - However, it seems to me that the simplest, most natural protocol would
>>>>   be for later declarations to override earlier ones.
>
> This means that cat-doc-prop-keyword-2 from the example defines the
> CATEGORY property which at least I find not so natural.  And I already
> stated what I find natural.

Hi Marco,

Org may allow #+KEYWORD: lines to appear anywhere in a file, including
in arbitrary drawers, but that's up to the user.  If the user chooses to
hide them in drawers, it's his responsibility.

AFAICT that's not a common or generally recommended thing to do.  Most
Org files have such lines at the top of the file, and some under a
heading at the bottom of the file with other settings.  Such lines don't
need to be in drawers, and this proposal wouldn't change that.

So I think it would be confusing if settings in a drawer at the top of
the file were to absolutely override settings outside of drawers (which
would mean that hidden settings could override plainly visible ones).
The most natural protocol would be like written language: later
declarations override earlier ones.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC] Document level property drawer
  2019-10-03 18:06         ` Adam Porter
@ 2019-10-04 11:05           ` Marco Wahl
  2019-10-06  1:05             ` Adam Porter
  0 siblings, 1 reply; 23+ messages in thread
From: Marco Wahl @ 2019-10-04 11:05 UTC (permalink / raw)
  To: emacs-orgmode

Adam Porter <adam@alphapapa.net> writes:

> Marco Wahl <marcowahlsoft@gmail.com> writes:

>> You say the visibility is better for the #+-property keywords.  I say
>> they can occur _anywhere_ in the file and even in some drawers.  See
>> above "#+CATEGORY:  cat-doc-prop-keyword-2".
>>
>> Further you say 
>>
>>>>> - However, it seems to me that the simplest, most natural protocol would
>>>>>   be for later declarations to override earlier ones.
>>
>> This means that cat-doc-prop-keyword-2 from the example defines the
>> CATEGORY property which at least I find not so natural.  And I already
>> stated what I find natural.

> Org may allow #+KEYWORD: lines to appear anywhere in a file, including
> in arbitrary drawers, but that's up to the user.  If the user chooses to
> hide them in drawers, it's his responsibility.
>
> AFAICT that's not a common or generally recommended thing to do.  Most
> Org files have such lines at the top of the file, and some under a
> heading at the bottom of the file with other settings.  Such lines don't
> need to be in drawers, and this proposal wouldn't change that.
>
> So I think it would be confusing if settings in a drawer at the top of
> the file were to absolutely override settings outside of drawers (which
> would mean that hidden settings could override plainly visible ones).
> The most natural protocol would be like written language: later
> declarations override earlier ones.

Hi Adam,

Just I got the idea that for a good part this discussion is about
personal preferences.  For me for example it's not a big deal if a
property is placed within a drawer or not.  I don't care much about the
"visibility" of a property setting.  Of course I respect other views
about this.

What I really find irritating is that "Org ... allows #+KEYWORD: lines
to appear anywhere in a file" (This sentence is from you) with the
meaning that the settings apply to the whole file.  I think this
interpretation of #+KEYWORD: lines is unnecessary and confusing.

BTW I find it completely natural that--let's for simplicity assume an
Org file without any drawers--#+KEYWORD: settings that appear later in
a file replace earlier settings.


Best regards,
-- 
Marco

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC] Document level property drawer
  2019-10-04 11:05           ` Marco Wahl
@ 2019-10-06  1:05             ` Adam Porter
  2019-10-06  5:10               ` Matt Price
  0 siblings, 1 reply; 23+ messages in thread
From: Adam Porter @ 2019-10-06  1:05 UTC (permalink / raw)
  To: emacs-orgmode

Marco Wahl <marcowahlsoft@gmail.com> writes:

> Just I got the idea that for a good part this discussion is about
> personal preferences.

Personal preferences are relevant to this issue in that Org is flexible
and allows users to configure it accordingly.  But that is not the only
consideration at stake.  Consistency, compatibility, and longevity are
even more important.

> What I really find irritating is that "Org ... allows #+KEYWORD: lines
> to appear anywhere in a file" (This sentence is from you) with the
> meaning that the settings apply to the whole file.  I think this
> interpretation of #+KEYWORD: lines is unnecessary and confusing.

Regardless, that is the way Org works, and how it has for many years.
We can't break that.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC] Document level property drawer
  2019-10-06  1:05             ` Adam Porter
@ 2019-10-06  5:10               ` Matt Price
  0 siblings, 0 replies; 23+ messages in thread
From: Matt Price @ 2019-10-06  5:10 UTC (permalink / raw)
  To: Adam Porter; +Cc: Org Mode

[-- Attachment #1: Type: text/plain, Size: 1918 bytes --]

On Sat., Oct. 5, 2019, 6:10 p.m. Adam Porter, <adam@alphapapa.net> wrote:

> Marco Wahl <marcowahlsoft@gmail.com> writes:
>
> > Just I got the idea that for a good part this discussion is about
> > personal preferences.
>
> Personal preferences are relevant to this issue in that Org is flexible
> and allows users to configure it accordingly.  But that is not the only
> consideration at stake.  Consistency, compatibility, and longevity are
> even more important.
>
> > What I really find irritating is that "Org ... allows #+KEYWORD: lines
> > to appear anywhere in a file" (This sentence is from you) with the
> > meaning that the settings apply to the whole file.  I think this
> > interpretation of #+KEYWORD: lines is unnecessary and confusing.
>
> Regardless, that is the way Org works, and how it has for many years.
> We can't break that.
>

I'd like to just  quickly chime in in support of Adam's caution on this
issue. I can absolutely see advantages to document level properties, I have
written many code fragments that rely on the use of keywords and expect org
filensyntax to be consistent with what actually exists. I use these code
fragments to hold together a somewhat fragile workflow that allows me to
use org in a work environment that is not especially receptive to simple
text documents. I have invested a lot of time in making those systems run
and sometimes even I don't entirely remember what I did to make them
possible.

It would really, really suck to have those systems break. It would take me
a lot of time to track down the causes and change what I needed to. VMs
that currently pull in Emacs andnorg and my code would stop working. Old
versions of my files would no longer render properly. My efforts to make my
courses and other writings effectively reproducible by others would be
significantly set back. Etc. I think these are the kinds of difficulties
Adam means to describe.

>
>

[-- Attachment #2: Type: text/html, Size: 2643 bytes --]

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC] Document level property drawer
  2019-09-29 10:27 [RFC] Document level property drawer Gustav Wikström
  2019-09-29 19:13 ` Marco Wahl
  2019-09-30 16:01 ` Adam Porter
@ 2019-10-15 17:49 ` Gustav Wikström
  2019-10-16  0:48   ` Adam Porter
  2019-10-16  9:48   ` Marco Wahl
  2020-01-20  3:27 ` [Question] adding document global properties drawer stardiviner
  3 siblings, 2 replies; 23+ messages in thread
From: Gustav Wikström @ 2019-10-15 17:49 UTC (permalink / raw)
  To: emacs-orgmode, Marco Wahl; +Cc: Nicolas Goaziou

Hi again,

I'd like to take the next step with this patch. I'm hesitant to do it without wider support though, since only a few people have commented.

@Marco Wahl; As I understand you've applied the patch and tried it out. Have you found any issues yet? What do you think of the patch after having used it for a while?

Any other thoughts/comments/objections/praises?

Regards
Gustav

> -----Original Message-----
> From: Gustav Wikström
> Sent: den 29 september 2019 12:27
> To: emacs-orgmode@gnu.org
> Cc: Nicolas Goaziou <mail@nicolasgoaziou.fr>
> Subject: [RFC] Document level property drawer
> 
> Hi,
> 
> This patch introduces a document level property drawer.
> 
> This has been discussed previously in a larger context:
> - https://lists.gnu.org/archive/html/emacs-orgmode/2019-06/msg00000.html
> - https://lists.gnu.org/archive/html/emacs-orgmode/2019-08/msg00339.html
> - https://lists.gnu.org/archive/html/emacs-orgmode/2019-09/msg00010.html
> 
> The patch is a somewhat modified version of what was included in the third
> link above.
> 
> The following will be true for document level property drawers:
> 1) In the same way that one can have a property drawer for a heading, one
>    can have a property drawer for a whole document.
> 2) All existing commands that can work with property drawers will
>    (shall) work also on property drawers before the first heading.
> 3) Properties defined in a property drawer will have precedence over
>    properties defined as a property keyword, if the same property is
>    defined using both conventions.
> 4) The position for the document level property drawer is:
>    - At the first line in a file that is not a comment or a keyword.
> 
>      I.e. the following will work:
>      #+begin_src org
>        # -*- mode: org -*-
>        ,#+TITLE: Test
>        :PROPERTIES:
>        :CATEGORY: Test
>        :END:
> 
>        Preamble
> 
>        ,* Some heading
>        Some content
>      #+end_src
> 
>      but not this:
>      #+begin_src org
>        Some comment and/or empty line
> 
>        :PROPERTIES:
>        :CATEGORY: Test
>        :END:
> 
>        ,* Some heading
>        Some content
>      #+end_src
> 
> What do you say?
> 
> Regards
> Gustav Wikström

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC] Document level property drawer
  2019-10-15 17:49 ` Gustav Wikström
@ 2019-10-16  0:48   ` Adam Porter
  2019-10-16  9:48   ` Marco Wahl
  1 sibling, 0 replies; 23+ messages in thread
From: Adam Porter @ 2019-10-16  0:48 UTC (permalink / raw)
  To: emacs-orgmode

Gustav Wikström <gustav@whil.se> writes:

> Hi again,
>
> I'd like to take the next step with this patch. I'm hesitant to do it
> without wider support though, since only a few people have commented.
>
> @Marco Wahl; As I understand you've applied the patch and tried it
> out. Have you found any issues yet? What do you think of the patch
> after having used it for a while?
>
> Any other thoughts/comments/objections/praises?

Please do not merge your patch without the approval of the Org
maintainers.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC] Document level property drawer
  2019-10-15 17:49 ` Gustav Wikström
  2019-10-16  0:48   ` Adam Porter
@ 2019-10-16  9:48   ` Marco Wahl
  1 sibling, 0 replies; 23+ messages in thread
From: Marco Wahl @ 2019-10-16  9:48 UTC (permalink / raw)
  To: emacs-orgmode

Gustav Wikström <gustav@whil.se> writes:

> I'd like to take the next step with this patch. I'm hesitant to do it
> without wider support though, since only a few people have commented.
>
> @Marco Wahl; As I understand you've applied the patch and tried it
> out. Have you found any issues yet? What do you think of the patch
> after having used it for a while?

Indeed I applied your patch and have it applied still.  Please note that
I did nothing fancy and in particular I did not try to break the patch.

The patch works good for me.

Noteworthy observations AFAICT:

1. I could not translate my personal "#+TODO: . N ~ | x c g >" into a
respective :TODO: property.

2. With org-ids turned on and point before the first heading, function
org-store-link creates an org-id property at the document level.

Regarding number 1. I think a list of document-level properties which
don't behave the same when used in the document property drawer would be
nice.  Ideally this list is empty AFAICT.  Maybe I overlook something.
Is this an issue?

I think observation 2. is just a little surprise but turns out to be
natural when the document level property drawer is enabled.


Still +1 for the inclusion of the patch and HTH,
-- 
Marco

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC] Document level property drawer
  2019-10-01 12:38     ` Sebastian Miele
@ 2020-01-13 21:52       ` Marco Wahl
  2020-01-15  8:18         ` Sebastian Miele
  0 siblings, 1 reply; 23+ messages in thread
From: Marco Wahl @ 2020-01-13 21:52 UTC (permalink / raw)
  To: Sebastian Miele; +Cc: emacs-orgmode

Sebastian Miele <sebastian.miele@gmail.com> writes:

> But for such properties to satisfactorily work for me, they would have
> to be visible by default. E.g. I would want the header-args to be
> immediately visible just like they are when they are written after
> #+BEGIN_SRC or #+HEADER. Otherwise I would find myself constantly
> wondering whether this or that property drawer contains something
> essential and every TAB on a collapsed headline would have be followed
> by an accompanying move to the property drawer and a TAB there.
>
> On the other hand, there are properties that are very good candidates
> for remaining hidden by default, like ID.
>
> I would like to be able to make a clear distinction between properties
> that are visible by default and properties that are not. Maybe it would
> be possible to allow some #+.. syntax following headings for subtree
> properties that are visible by default. A requirement could be made that
> such property specifications always have to be followed by a property
> drawer, even if that is empty. Then everything #+.. that is before the
> property drawer would belong to the heading/subtree, and everything #+..
> that follows the drawer would be treated as it is until now.
>
> Please tell me if I missed something and Org is already capable of
> something like that. If not, are there others who would like
> visible-by-default property specifications for headings/subtrees in
> addition to invisible-by-default property specifications in drawers,
> too?

I don't think Org is capable of this out of the box right now.  Further
I don't feel the need for a visible-by-default property, but that's just
me.

> Finally, I would like to state an opinion: If there is
> visible-by-default (by #+..) and invisible-by-default (by drawers)
> syntax for headings/subtrees, including level 0, it may be viable to
> require them to be disjoint for each heading/subtree. Most probably it
> would be good practice, anyway. And the precedence question raised
> previously in this thread would be eliminated.

I may not feel the need for the visible/invisible-by-default properties
but actually I like the idea of #+ properties parallel to the property
drawers as visible by default properties.  But since the #+ properties
may appear anywhere in the Org file and affect the whole file it would
be difficult or even impossible to give them reliable meaning for
subtrees AFAICS.


My 2ct,
-- 
Marco

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC] Document level property drawer
  2020-01-13 21:52       ` Marco Wahl
@ 2020-01-15  8:18         ` Sebastian Miele
  2020-02-01 19:59           ` Marco Wahl
  0 siblings, 1 reply; 23+ messages in thread
From: Sebastian Miele @ 2020-01-15  8:18 UTC (permalink / raw)
  To: Marco Wahl; +Cc: emacs-orgmode

Marco Wahl <marcowahlsoft@gmail.com> writes:

> Sebastian Miele <sebastian.miele@gmail.com> writes:
>
>> But for such properties to satisfactorily work for me, they would have
>> to be visible by default. E.g. I would want the header-args to be
>> immediately visible just like they are when they are written after
>> #+BEGIN_SRC or #+HEADER. Otherwise I would find myself constantly
>> wondering whether this or that property drawer contains something
>> essential and every TAB on a collapsed headline would have be followed
>> by an accompanying move to the property drawer and a TAB there.
>>
>> On the other hand, there are properties that are very good candidates
>> for remaining hidden by default, like ID.
>>
>> I would like to be able to make a clear distinction between properties
>> that are visible by default and properties that are not. Maybe it would
>> be possible to allow some #+.. syntax following headings for subtree
>> properties that are visible by default. A requirement could be made that
>> such property specifications always have to be followed by a property
>> drawer, even if that is empty. Then everything #+.. that is before the
>> property drawer would belong to the heading/subtree, and everything #+..
>> that follows the drawer would be treated as it is until now.
>>
>> Please tell me if I missed something and Org is already capable of
>> something like that. If not, are there others who would like
>> visible-by-default property specifications for headings/subtrees in
>> addition to invisible-by-default property specifications in drawers,
>> too?
>
> I don't think Org is capable of this out of the box right now.  Further
> I don't feel the need for a visible-by-default property, but that's just
> me.

After a few more months of living without that feature I must say that I
basically live perfectly well without that, too. I just do not define
source block header args in property drawers. It gets a bit verbose at
times. But not to the degree of being painful.

>> Finally, I would like to state an opinion: If there is
>> visible-by-default (by #+..) and invisible-by-default (by drawers)
>> syntax for headings/subtrees, including level 0, it may be viable to
>> require them to be disjoint for each heading/subtree. Most probably it
>> would be good practice, anyway. And the precedence question raised
>> previously in this thread would be eliminated.
>
> I may not feel the need for the visible/invisible-by-default properties
> but actually I like the idea of #+ properties parallel to the property
> drawers as visible by default properties.  But since the #+ properties
> may appear anywhere in the Org file and affect the whole file it would
> be difficult or even impossible to give them reliable meaning for
> subtrees AFAICS.

In the meantime I had a look into worg/dev/org-syntax.org. From the
document: "Property drawers are a special type of drawer containing
properties attached to a headline. They are located right after a
headline and its planning information."

So, currently, #+ properties may not appear between a heading and a
property drawer. At least not without turning the property drawer into a
non-special drawer. So, in principle, it would be possible to change the
syntax of Org to allow #+ properties between headings and (possibly
empty) property drawers in order to denote visible-by-default
properties attached to a heading.

Moreover, this change probably would introduce very little to no
backwards incompatibility. With the change it would not be possible to
turn property drawers into non-special drawers by putting a #+ property
before them. Now it is possible to sort of uncomment property drawers by
putting #+ properties before them. This "feature" probably is hardly
used, if at all.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Question] adding document global properties drawer
  2019-09-29 10:27 [RFC] Document level property drawer Gustav Wikström
                   ` (2 preceding siblings ...)
  2019-10-15 17:49 ` Gustav Wikström
@ 2020-01-20  3:27 ` stardiviner
  2020-01-21 16:40   ` Nicolas Goaziou
  3 siblings, 1 reply; 23+ messages in thread
From: stardiviner @ 2020-01-20  3:27 UTC (permalink / raw)
  To: emacs-orgmode; +Cc: Nicolas Goaziou


In an *empty* Org file buffer, I press =[C-c C-x p]= to add properties drawer. It
works fine. But when the Org buffer has nodes already like this:

#+begin_src org
|

,* node 1

context
#+end_src

The "|" means the cursor point.

Then I press =[C-c C-x p]= again try to add document global properties drawer, It
insert nothing. No modification on buffer at all. Is this a bug?

-- 
[ stardiviner ]
       I try to make every word tell the meaning what I want to express.

       Blog: https://stardiviner.github.io/
       IRC(freenode): stardiviner, Matrix: stardiviner
       GPG: F09F650D7D674819892591401B5DF1C95AE89AC3
      

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Question] adding document global properties drawer
  2020-01-20  3:27 ` [Question] adding document global properties drawer stardiviner
@ 2020-01-21 16:40   ` Nicolas Goaziou
  2020-01-22 16:28     ` stardiviner
  0 siblings, 1 reply; 23+ messages in thread
From: Nicolas Goaziou @ 2020-01-21 16:40 UTC (permalink / raw)
  To: stardiviner; +Cc: emacs-orgmode

Hello,

stardiviner <numbchild@gmail.com> writes:

> In an *empty* Org file buffer, I press =[C-c C-x p]= to add properties drawer. It
> works fine. But when the Org buffer has nodes already like this:
>
> #+begin_src org
> |
>
> ,* node 1
>
> context
> #+end_src
>
> The "|" means the cursor point.
>
> Then I press =[C-c C-x p]= again try to add document global properties drawer, It
> insert nothing. No modification on buffer at all. Is this a bug?

FWIW, I could not reproduce it.

Regards,

-- 
Nicolas Goaziou

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Question] adding document global properties drawer
  2020-01-21 16:40   ` Nicolas Goaziou
@ 2020-01-22 16:28     ` stardiviner
  2020-01-24 23:14       ` Nicolas Goaziou
  0 siblings, 1 reply; 23+ messages in thread
From: stardiviner @ 2020-01-22 16:28 UTC (permalink / raw)
  To: Nicolas Goaziou; +Cc: emacs-orgmode


Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:

> Hello,
>
> stardiviner <numbchild@gmail.com> writes:
>
>> In an *empty* Org file buffer, I press =[C-c C-x p]= to add properties drawer. It
>> works fine. But when the Org buffer has nodes already like this:
>>
>> #+begin_src org
>> |
>>
>> ,* node 1
>>
>> context
>> #+end_src
>>
>> The "|" means the cursor point.
>>
>> Then I press =[C-c C-x p]= again try to add document global properties drawer, It
>> insert nothing. No modification on buffer at all. Is this a bug?
>
> FWIW, I could not reproduce it.
>
> Regards,

You're right, with EMC is fine.

I found I can add property with name input name like "kk", "hello" etc, but
can't add property "CATEGORY". Is there some limitation on document level
property?

-- 
[ stardiviner ]
       I try to make every word tell the meaning what I want to express.

       Blog: https://stardiviner.github.io/
       IRC(freenode): stardiviner, Matrix: stardiviner
       GPG: F09F650D7D674819892591401B5DF1C95AE89AC3
      

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Question] adding document global properties drawer
  2020-01-22 16:28     ` stardiviner
@ 2020-01-24 23:14       ` Nicolas Goaziou
  2020-02-23  7:31         ` [SOLVED] " stardiviner
  0 siblings, 1 reply; 23+ messages in thread
From: Nicolas Goaziou @ 2020-01-24 23:14 UTC (permalink / raw)
  To: stardiviner; +Cc: emacs-orgmode

Hello,

stardiviner <numbchild@gmail.com> writes:

> I found I can add property with name input name like "kk", "hello" etc, but
> can't add property "CATEGORY". Is there some limitation on document level
> property?

I still cannot reproduce it.

Regards,

-- 
Nicolas Goaziou

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC] Document level property drawer
  2020-01-15  8:18         ` Sebastian Miele
@ 2020-02-01 19:59           ` Marco Wahl
  0 siblings, 0 replies; 23+ messages in thread
From: Marco Wahl @ 2020-02-01 19:59 UTC (permalink / raw)
  To: emacs-orgmode


>> Sebastian Miele <sebastian.miele@gmail.com> writes:

>>> I would like to be able to make a clear distinction between properties
>>> that are visible by default and properties that are not. Maybe it would
>>> be possible to allow some #+.. syntax following headings for subtree
>>> properties that are visible by default. A requirement could be made that
>>> such property specifications always have to be followed by a property
>>> drawer, even if that is empty. Then everything #+.. that is before the
>>> property drawer would belong to the heading/subtree, and everything #+..
>>> that follows the drawer would be treated as it is until now.
>>>
>>> Please tell me if I missed something and Org is already capable of
>>> something like that. If not, are there others who would like
>>> visible-by-default property specifications for headings/subtrees in
>>> addition to invisible-by-default property specifications in drawers,
>>> too?
>>
>> I don't think Org is capable of this out of the box right now.  Further
>> I don't feel the need for a visible-by-default property, but that's just
>> me.
>
> After a few more months of living without that feature I must say that I
> basically live perfectly well without that, too. I just do not define
> source block header args in property drawers. It gets a bit verbose at
> times. But not to the degree of being painful.

Sounds good to me.

>>> Finally, I would like to state an opinion: If there is
>>> visible-by-default (by #+..) and invisible-by-default (by drawers)
>>> syntax for headings/subtrees, including level 0, it may be viable to
>>> require them to be disjoint for each heading/subtree. Most probably it
>>> would be good practice, anyway. And the precedence question raised
>>> previously in this thread would be eliminated.
>>
>> I may not feel the need for the visible/invisible-by-default properties
>> but actually I like the idea of #+ properties parallel to the property
>> drawers as visible by default properties.  But since the #+ properties
>> may appear anywhere in the Org file and affect the whole file it would
>> be difficult or even impossible to give them reliable meaning for
>> subtrees AFAICS.
>
> In the meantime I had a look into worg/dev/org-syntax.org. From the
> document: "Property drawers are a special type of drawer containing
> properties attached to a headline. They are located right after a
> headline and its planning information."

Thanks for the quote.

> So, currently, #+ properties may not appear between a heading and a
> property drawer. At least not without turning the property drawer into a
> non-special drawer. So, in principle, it would be possible to change the
> syntax of Org to allow #+ properties between headings and (possibly
> empty) property drawers in order to denote visible-by-default
> properties attached to a heading.

Sounds true AFAICS.

> Moreover, this change probably would introduce very little to no
> backwards incompatibility. With the change it would not be possible to
> turn property drawers into non-special drawers by putting a #+ property
> before them. Now it is possible to sort of uncomment property drawers by
> putting #+ properties before them. This "feature" probably is hardly
> used, if at all.

I also think this is very corner case-y.

All in all I think your idea is good.  But the masses did not scream for
that change so I think your idea is something for a wishlist to wait for
further discussion.


Best regards,
-- 
Marco

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [SOLVED] Re: [Question] adding document global properties drawer
  2020-01-24 23:14       ` Nicolas Goaziou
@ 2020-02-23  7:31         ` stardiviner
  2020-02-23 13:14           ` Bastien
  0 siblings, 1 reply; 23+ messages in thread
From: stardiviner @ 2020-02-23  7:31 UTC (permalink / raw)
  To: Nicolas Goaziou; +Cc: emacs-orgmode

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256


This problem has gone, I don't know what config caused this problem. I recently
modify some config of Org Mode. Anyway, it's good news.

Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:

> Hello,
>
> stardiviner <numbchild@gmail.com> writes:
>
>> I found I can add property with name input name like "kk", "hello" etc, but
>> can't add property "CATEGORY". Is there some limitation on document level
>> property?
>
> I still cannot reproduce it.
>
> Regards,


- -- 
[ stardiviner ]
       I try to make every word tell the meaning what I want to express.

       Blog: https://stardiviner.github.io/
       IRC(freenode): stardiviner, Matrix: stardiviner
       GPG: F09F650D7D674819892591401B5DF1C95AE89AC3
      
-----BEGIN PGP SIGNATURE-----

iQFIBAEBCAAyFiEE8J9lDX1nSBmJJZFAG13xyVromsMFAl5SKkYUHG51bWJjaGls
ZEBnbWFpbC5jb20ACgkQG13xyVromsPFXgf9EoRG/qXJBblOrNwRdv2dfzgA8rDd
HTGsxcPVbssguPXlL6uMoCkHsdveGnZN8VDR6GENtNUwm5aSmzMdNNnFV3xSIQ3M
glF+xAicdOKeWvJ+pkpvmUudqkq9+e+mj3Hz/8DNBox4qpUHUDkdjP0EewTLD6NN
3bPx426zy83bd26b2ebier8oo5RcU+ky1kfwTOCiXyiO5JBkOBOSJU8iFWG1fn4A
oqNjev0r7RUwOoxkC7e8/+kFH0MnhDWQe+SmN6+vUhcbosGjF6QFqTNwL4mBeHg5
WJSnA8QFoUh2+2e81JyAX15n05x7KLxCf3tLa8hLjPXmwBBKx6DwCKmLaA==
=yF9e
-----END PGP SIGNATURE-----

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [SOLVED] Re: [Question] adding document global properties drawer
  2020-02-23  7:31         ` [SOLVED] " stardiviner
@ 2020-02-23 13:14           ` Bastien
  0 siblings, 0 replies; 23+ messages in thread
From: Bastien @ 2020-02-23 13:14 UTC (permalink / raw)
  To: stardiviner; +Cc: emacs-orgmode, Nicolas Goaziou

stardiviner <numbchild@gmail.com> writes:

> This problem has gone, I don't know what config caused this problem. I recently
> modify some config of Org Mode. Anyway, it's good news.

Thanks for confirming!

-- 
 Bastien

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2020-02-23 13:14 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-09-29 10:27 [RFC] Document level property drawer Gustav Wikström
2019-09-29 19:13 ` Marco Wahl
2019-09-30 16:01 ` Adam Porter
2019-09-30 20:46   ` Marco Wahl
2019-10-01 12:38     ` Sebastian Miele
2020-01-13 21:52       ` Marco Wahl
2020-01-15  8:18         ` Sebastian Miele
2020-02-01 19:59           ` Marco Wahl
2019-10-01 13:55     ` Adam Porter
2019-10-02 10:29       ` Marco Wahl
2019-10-03 18:06         ` Adam Porter
2019-10-04 11:05           ` Marco Wahl
2019-10-06  1:05             ` Adam Porter
2019-10-06  5:10               ` Matt Price
2019-10-15 17:49 ` Gustav Wikström
2019-10-16  0:48   ` Adam Porter
2019-10-16  9:48   ` Marco Wahl
2020-01-20  3:27 ` [Question] adding document global properties drawer stardiviner
2020-01-21 16:40   ` Nicolas Goaziou
2020-01-22 16:28     ` stardiviner
2020-01-24 23:14       ` Nicolas Goaziou
2020-02-23  7:31         ` [SOLVED] " stardiviner
2020-02-23 13:14           ` Bastien

Code repositories for project(s) associated with this inbox:

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).