Browse Source

Remove need to declare drawers before using them

* lisp/org-agenda.el (org-agenda-prepare): Remove reference to
  `org-drawers-for-agenda'.
(org-agenda-show-1): Remove reference to `org-drawers'.
* lisp/org-clock.el (org-clock-remove-empty-clock-drawer,
  org-clock-cancel): Apply signature change to
  `org-remove-empty-drawer-at'.
* lisp/org-element.el (org-element--list-struct): Use
  `org-drawer-regexp' instead of `org-drawers'.
* lisp/org-feed.el (org-feed-drawer): Update docstring according to
  change.
* lisp/org-list.el (org-in-item-p, org-list-context): Use
  `org-drawer-regexp' instead of `org-drawers'.
* lisp/org-mobile.el (org-mobile-create-index-file): Remove reference
  to `org-drawers-for-agenda'.
* lisp/org-pcomplete.el (pcomplete/org-mode/drawer): Remove function.
* lisp/org.el (org-drawer-regexp): Make variable global.
(org-drawers): Remove variable.
(org-set-regexps-and-options): Ignore DRAWER keyword.
(org-cycle): Use `org-drawer-regexp' instead of `org-drawers'.
(org-cycle-hide-drawers): Add an optional argument to ignore some
drawers.
(org-remove-empty-drawer-at): Remove second argument.  Rewrite
function.
(org-clone-subtree-with-time-shift): Apply signature change to
`org-remove-empty-drawer-at'.
(org-toggle-ordered-property): Apply `org-delete-property' signature
change.
(org-map-entries): Remove reference to `org-drawers-for-agenda'.
(org-entry-delete): Remove optional argument.  Small refactoring.
(org-insert-drawer): Remove reference to `org-drawers'.
(org-delete-property): Apply `org-entry-delete' signature change.
(org-in-drawer-p): Rewrite function.
* testing/lisp/test-org-element.el: Update tests.
* testing/lisp/test-org.el: Update tests.
* testing/lisp/test-ox.el: Update tests.
Nicolas Goaziou 12 years ago
parent
commit
6202ec7b3b

+ 4 - 11
lisp/org-agenda.el

@@ -3642,7 +3642,6 @@ generating a new one."
 	(or org-agenda-multi (org-agenda-fit-window-to-buffer))
 	(or org-agenda-multi (org-agenda-fit-window-to-buffer))
 	(throw 'exit "Sticky Agenda buffer, use `r' to refresh"))
 	(throw 'exit "Sticky Agenda buffer, use `r' to refresh"))
     (setq org-todo-keywords-for-agenda nil)
     (setq org-todo-keywords-for-agenda nil)
-    (setq org-drawers-for-agenda nil)
     (unless org-agenda-persistent-filter
     (unless org-agenda-persistent-filter
       (setq org-agenda-tag-filter nil
       (setq org-agenda-tag-filter nil
 	    org-agenda-category-filter nil
 	    org-agenda-category-filter nil
@@ -3682,7 +3681,6 @@ generating a new one."
 	    (org-uniquify org-todo-keywords-for-agenda))
 	    (org-uniquify org-todo-keywords-for-agenda))
       (setq org-done-keywords-for-agenda
       (setq org-done-keywords-for-agenda
 	    (org-uniquify org-done-keywords-for-agenda))
 	    (org-uniquify org-done-keywords-for-agenda))
-      (setq org-drawers-for-agenda (org-uniquify org-drawers-for-agenda))
       (setq org-agenda-last-prefix-arg current-prefix-arg)
       (setq org-agenda-last-prefix-arg current-prefix-arg)
       (setq org-agenda-this-buffer-name org-agenda-buffer-name)
       (setq org-agenda-this-buffer-name org-agenda-buffer-name)
       (and name (not org-agenda-name)
       (and name (not org-agenda-name)
@@ -8627,15 +8625,10 @@ if it was hidden in the outline."
 	(run-hook-with-args 'org-cycle-hook 'subtree))
 	(run-hook-with-args 'org-cycle-hook 'subtree))
       (message "Remote: SUBTREE"))
       (message "Remote: SUBTREE"))
      ((= more 4)
      ((= more 4)
-      (let* ((org-drawers (delete "LOGBOOK" (copy-sequence org-drawers)))
-	     (org-drawer-regexp
-	      (concat "^[ \t]*:\\("
-		      (mapconcat 'regexp-quote org-drawers "\\|")
-		      "\\):[ \t]*$")))
-	(show-subtree)
-	(save-excursion
-	  (org-back-to-heading)
-	  (org-cycle-hide-drawers 'subtree)))
+      (show-subtree)
+      (save-excursion
+	(org-back-to-heading)
+	(org-cycle-hide-drawers 'subtree '("LOGBOOK")))
       (message "Remote: SUBTREE AND LOGBOOK"))
       (message "Remote: SUBTREE AND LOGBOOK"))
      ((> more 4)
      ((> more 4)
       (show-subtree)
       (show-subtree)

+ 3 - 3
lisp/org-clock.el

@@ -1589,7 +1589,7 @@ to, overriding the existing value of `org-clock-out-switch-to-state'."
 	(while (and (< (point) end)
 	(while (and (< (point) end)
 		    (search-forward clock-drawer end t))
 		    (search-forward clock-drawer end t))
 	  (goto-char (match-beginning 0))
 	  (goto-char (match-beginning 0))
-	  (org-remove-empty-drawer-at clock-drawer (point))
+	  (org-remove-empty-drawer-at (point))
 	  (forward-line 1))))))
 	  (forward-line 1))))))
 
 
 (defun org-clock-timestamps-up (&optional n)
 (defun org-clock-timestamps-up (&optional n)
@@ -1653,12 +1653,12 @@ Optional argument N tells to change by that many units."
     (setq frame-title-format org-frame-title-format-backup)
     (setq frame-title-format org-frame-title-format-backup)
     (force-mode-line-update)
     (force-mode-line-update)
     (error "No active clock"))
     (error "No active clock"))
-  (save-excursion ; Do not replace this with `with-current-buffer'.
+  (save-excursion    ; Do not replace this with `with-current-buffer'.
     (org-no-warnings (set-buffer (org-clocking-buffer)))
     (org-no-warnings (set-buffer (org-clocking-buffer)))
     (goto-char org-clock-marker)
     (goto-char org-clock-marker)
     (if (org-looking-back (concat "^[ \t]*" org-clock-string ".*"))
     (if (org-looking-back (concat "^[ \t]*" org-clock-string ".*"))
 	(progn (delete-region (1- (point-at-bol)) (point-at-eol))
 	(progn (delete-region (1- (point-at-bol)) (point-at-eol))
-	       (org-remove-empty-drawer-at "LOGBOOK" (point)))
+	       (org-remove-empty-drawer-at (point)))
       (message "Clock gone, cancel the timer anyway")
       (message "Clock gone, cancel the timer anyway")
       (sit-for 2)))
       (sit-for 2)))
   (move-marker org-clock-marker nil)
   (move-marker org-clock-marker nil)

+ 1 - 4
lisp/org-element.el

@@ -1146,9 +1146,6 @@ CONTENTS is the contents of the element."
   (let ((case-fold-search t)
   (let ((case-fold-search t)
 	(top-ind limit)
 	(top-ind limit)
 	(item-re (org-item-re))
 	(item-re (org-item-re))
-	(drawers-re (concat ":\\("
-			    (mapconcat 'regexp-quote org-drawers "\\|")
-			    "\\):[ \t]*$"))
 	(inlinetask-re (and (featurep 'org-inlinetask) "^\\*+ "))
 	(inlinetask-re (and (featurep 'org-inlinetask) "^\\*+ "))
 	items struct)
 	items struct)
     (save-excursion
     (save-excursion
@@ -1221,7 +1218,7 @@ CONTENTS is the contents of the element."
 		    (format "^[ \t]*#\\+END%s[ \t]*$"
 		    (format "^[ \t]*#\\+END%s[ \t]*$"
 			    (org-match-string-no-properties 1))
 			    (org-match-string-no-properties 1))
 		    limit t)))
 		    limit t)))
-	     ((and (looking-at drawers-re)
+	     ((and (looking-at org-drawer-regexp)
 		   (re-search-forward "^[ \t]*:END:[ \t]*$" limit t))))
 		   (re-search-forward "^[ \t]*:END:[ \t]*$" limit t))))
 	    (forward-line))))))))
 	    (forward-line))))))))
 
 

+ 1 - 4
lisp/org-feed.el

@@ -215,10 +215,7 @@ Here are the keyword-value pair allows in `org-feed-alist'.
 (defcustom org-feed-drawer "FEEDSTATUS"
 (defcustom org-feed-drawer "FEEDSTATUS"
   "The name of the drawer for feed status information.
   "The name of the drawer for feed status information.
 Each feed may also specify its own drawer name using the `:drawer'
 Each feed may also specify its own drawer name using the `:drawer'
-parameter in `org-feed-alist'.
-Note that in order to make these drawers behave like drawers, they must
-be added to the variable `org-drawers' or configured with a #+DRAWERS
-line."
+parameter in `org-feed-alist'."
   :group 'org-feed
   :group 'org-feed
   :type '(string :tag "Drawer Name"))
   :type '(string :tag "Drawer Name"))
 
 

+ 6 - 19
lisp/org-list.el

@@ -88,7 +88,6 @@
 (defvar org-closed-string)
 (defvar org-closed-string)
 (defvar org-deadline-string)
 (defvar org-deadline-string)
 (defvar org-description-max-indent)
 (defvar org-description-max-indent)
-(defvar org-drawers)
 (defvar org-odd-levels-only)
 (defvar org-odd-levels-only)
 (defvar org-scheduled-string)
 (defvar org-scheduled-string)
 (defvar org-ts-regexp)
 (defvar org-ts-regexp)
@@ -430,9 +429,6 @@ group 4: description tag")
     (let* ((case-fold-search t)
     (let* ((case-fold-search t)
 	   (context (org-list-context))
 	   (context (org-list-context))
 	   (lim-up (car context))
 	   (lim-up (car context))
-	   (drawers-re (concat "^[ \t]*:\\("
-			       (mapconcat 'regexp-quote org-drawers "\\|")
-			       "\\):[ \t]*$"))
 	   (inlinetask-re (and (featurep 'org-inlinetask)
 	   (inlinetask-re (and (featurep 'org-inlinetask)
 			       (org-inlinetask-outline-regexp)))
 			       (org-inlinetask-outline-regexp)))
 	   (item-re (org-item-re))
 	   (item-re (org-item-re))
@@ -476,7 +472,7 @@ group 4: description tag")
 	       ((and (looking-at "^[ \t]*#\\+end_")
 	       ((and (looking-at "^[ \t]*#\\+end_")
 		     (re-search-backward "^[ \t]*#\\+begin_" lim-up t)))
 		     (re-search-backward "^[ \t]*#\\+begin_" lim-up t)))
 	       ((and (looking-at "^[ \t]*:END:")
 	       ((and (looking-at "^[ \t]*:END:")
-		     (re-search-backward drawers-re lim-up t))
+		     (re-search-backward org-drawer-regexp lim-up t))
 		(beginning-of-line))
 		(beginning-of-line))
 	       ((and inlinetask-re (looking-at inlinetask-re))
 	       ((and inlinetask-re (looking-at inlinetask-re))
 		(org-inlinetask-goto-beginning)
 		(org-inlinetask-goto-beginning)
@@ -547,11 +543,7 @@ Contexts `block' and `invalid' refer to `org-list-forbidden-blocks'."
 	     (lim-down (or (save-excursion (outline-next-heading)) (point-max))))
 	     (lim-down (or (save-excursion (outline-next-heading)) (point-max))))
 	 ;; Is point inside a drawer?
 	 ;; Is point inside a drawer?
 	 (let ((end-re "^[ \t]*:END:")
 	 (let ((end-re "^[ \t]*:END:")
-	       ;; Can't use org-drawers-regexp as this function might
-	       ;; be called in buffers not in Org mode.
-	       (beg-re (concat "^[ \t]*:\\("
-			       (mapconcat 'regexp-quote org-drawers "\\|")
-			       "\\):[ \t]*$")))
+	       (beg-re org-drawer-regexp))
 	   (when (save-excursion
 	   (when (save-excursion
 		   (and (not (looking-at beg-re))
 		   (and (not (looking-at beg-re))
 			(not (looking-at end-re))
 			(not (looking-at end-re))
@@ -635,9 +627,6 @@ Assume point is at an item."
 	   (lim-down (nth 1 context))
 	   (lim-down (nth 1 context))
 	   (text-min-ind 10000)
 	   (text-min-ind 10000)
 	   (item-re (org-item-re))
 	   (item-re (org-item-re))
-	   (drawers-re (concat "^[ \t]*:\\("
-			       (mapconcat 'regexp-quote org-drawers "\\|")
-			       "\\):[ \t]*$"))
 	   (inlinetask-re (and (featurep 'org-inlinetask)
 	   (inlinetask-re (and (featurep 'org-inlinetask)
 			       (org-inlinetask-outline-regexp)))
 			       (org-inlinetask-outline-regexp)))
 	   (beg-cell (cons (point) (org-get-indentation)))
 	   (beg-cell (cons (point) (org-get-indentation)))
@@ -700,7 +689,7 @@ Assume point is at an item."
 	       ((and (looking-at "^[ \t]*#\\+end_")
 	       ((and (looking-at "^[ \t]*#\\+end_")
 		     (re-search-backward "^[ \t]*#\\+begin_" lim-up t)))
 		     (re-search-backward "^[ \t]*#\\+begin_" lim-up t)))
 	       ((and (looking-at "^[ \t]*:END:")
 	       ((and (looking-at "^[ \t]*:END:")
-		     (re-search-backward drawers-re lim-up t))
+		     (re-search-backward org-drawer-regexp lim-up t))
 		(beginning-of-line))
 		(beginning-of-line))
 	       ((and inlinetask-re (looking-at inlinetask-re))
 	       ((and inlinetask-re (looking-at inlinetask-re))
 		(org-inlinetask-goto-beginning)
 		(org-inlinetask-goto-beginning)
@@ -766,7 +755,7 @@ Assume point is at an item."
 	      (cond
 	      (cond
 	       ((and (looking-at "^[ \t]*#\\+begin_")
 	       ((and (looking-at "^[ \t]*#\\+begin_")
 		     (re-search-forward "^[ \t]*#\\+end_" lim-down t)))
 		     (re-search-forward "^[ \t]*#\\+end_" lim-down t)))
-	       ((and (looking-at drawers-re)
+	       ((and (looking-at org-drawer-regexp)
 		     (re-search-forward "^[ \t]*:END:" lim-down t))))
 		     (re-search-forward "^[ \t]*:END:" lim-down t))))
 	      (forward-line 1))))))
 	      (forward-line 1))))))
       (setq struct (append itm-lst (cdr (nreverse itm-lst-2)))
       (setq struct (append itm-lst (cdr (nreverse itm-lst-2)))
@@ -2326,9 +2315,6 @@ in subtree, ignoring drawers."
 	   block-item
 	   block-item
 	   lim-up
 	   lim-up
 	   lim-down
 	   lim-down
-	   (drawer-re (concat "^[ \t]*:\\("
-			      (mapconcat 'regexp-quote org-drawers "\\|")
-			      "\\):[ \t]*$"))
 	   (keyword-re (concat "^[ \t]*\\<\\(" org-scheduled-string
 	   (keyword-re (concat "^[ \t]*\\<\\(" org-scheduled-string
 			       "\\|" org-deadline-string
 			       "\\|" org-deadline-string
 			       "\\|" org-closed-string
 			       "\\|" org-closed-string
@@ -2350,7 +2336,8 @@ in subtree, ignoring drawers."
 	      ;; time-stamps (scheduled, etc.).
 	      ;; time-stamps (scheduled, etc.).
 	      (let ((limit (save-excursion (outline-next-heading) (point))))
 	      (let ((limit (save-excursion (outline-next-heading) (point))))
 		(forward-line 1)
 		(forward-line 1)
-		(while (or (looking-at drawer-re) (looking-at keyword-re))
+		(while (or (looking-at org-drawer-regexp)
+			   (looking-at keyword-re))
 		  (if (looking-at keyword-re)
 		  (if (looking-at keyword-re)
 		      (forward-line 1)
 		      (forward-line 1)
 		    (re-search-forward "^[ \t]*:END:" limit nil)))
 		    (re-search-forward "^[ \t]*:END:" limit nil)))

+ 1 - 3
lisp/org-mobile.el

@@ -425,7 +425,7 @@ agenda view showing the flagged items."
 	(def-tags (default-value 'org-tag-alist))
 	(def-tags (default-value 'org-tag-alist))
 	(target-file (expand-file-name org-mobile-index-file
 	(target-file (expand-file-name org-mobile-index-file
 				       org-mobile-directory))
 				       org-mobile-directory))
-	file link-name todo-kwds done-kwds tags drawers entry kwds dwds twds)
+	file link-name todo-kwds done-kwds tags entry kwds dwds twds)
     (when (stringp (car def-todo))
     (when (stringp (car def-todo))
       (setq def-todo (list (cons 'sequence def-todo))))
       (setq def-todo (list (cons 'sequence def-todo))))
     (org-agenda-prepare-buffers (mapcar 'car files-alist))
     (org-agenda-prepare-buffers (mapcar 'car files-alist))
@@ -433,7 +433,6 @@ agenda view showing the flagged items."
     (setq todo-kwds (org-delete-all
     (setq todo-kwds (org-delete-all
 		     done-kwds
 		     done-kwds
 		     (org-uniquify org-todo-keywords-for-agenda)))
 		     (org-uniquify org-todo-keywords-for-agenda)))
-    (setq drawers (org-uniquify org-drawers-for-agenda))
     (setq tags (mapcar 'car (org-global-tags-completion-table
     (setq tags (mapcar 'car (org-global-tags-completion-table
 			     (mapcar 'car files-alist))))
 			     (mapcar 'car files-alist))))
     (with-temp-file
     (with-temp-file
@@ -468,7 +467,6 @@ agenda view showing the flagged items."
       (setq tags (sort tags (lambda (a b) (string< (downcase a) (downcase b)))))
       (setq tags (sort tags (lambda (a b) (string< (downcase a) (downcase b)))))
       (setq tags (append def-tags tags nil))
       (setq tags (append def-tags tags nil))
       (insert "#+TAGS: " (mapconcat 'identity tags " ") "\n")
       (insert "#+TAGS: " (mapconcat 'identity tags " ") "\n")
-      (insert "#+DRAWERS: " (mapconcat 'identity drawers " ") "\n")
       (insert "#+ALLPRIORITIES: " org-mobile-allpriorities "\n")
       (insert "#+ALLPRIORITIES: " org-mobile-allpriorities "\n")
       (when (file-exists-p (expand-file-name
       (when (file-exists-p (expand-file-name
 			    org-mobile-directory "agendas.org"))
 			    org-mobile-directory "agendas.org"))

+ 0 - 19
lisp/org-pcomplete.el

@@ -363,25 +363,6 @@ This needs more work, to handle headings with lots of spaces in them."
 	     lst))
 	     lst))
    (substring pcomplete-stub 1)))
    (substring pcomplete-stub 1)))
 
 
-(defvar org-drawers)
-
-(defun pcomplete/org-mode/drawer ()
-  "Complete a drawer name."
-  (let ((spc (save-excursion
-	       (move-beginning-of-line 1)
-	       (looking-at "^\\([ \t]*\\):")
-	       (match-string 1)))
-	(cpllist (mapcar (lambda (x) (concat x ": ")) org-drawers)))
-    (pcomplete-here cpllist
-		    (substring pcomplete-stub 1)
-		    (unless (or (not (delq
-				      nil
-				      (mapcar (lambda(x)
-						(string-match (substring pcomplete-stub 1) x))
-					      cpllist)))
-				(looking-at "[ \t]*\n.*:END:"))
-		      (save-excursion (insert "\n" spc ":END:"))))))
-
 (defun pcomplete/org-mode/block-option/src ()
 (defun pcomplete/org-mode/block-option/src ()
   "Complete the arguments of a begin_src block.
   "Complete the arguments of a begin_src block.
 Complete a language in the first field, the header arguments and switches."
 Complete a language in the first field, the header arguments and switches."

+ 49 - 92
lisp/org.el

@@ -884,6 +884,10 @@ An entry can be toggled between QUOTE and normal with
   :group 'org-keywords
   :group 'org-keywords
   :type 'string)
   :type 'string)
 
 
+(defconst org-drawer-regexp "^[ \t]*:\\(\\(?:\\w\\|[-_]\\)+\\):[ \t]*$"
+  "Matches first line of a hidden block.
+Group 1 contains drawer's name.")
+
 (defconst org-repeat-re
 (defconst org-repeat-re
   "<[0-9]\\{4\\}-[0-9][0-9]-[0-9][0-9] [^>\n]*?\\([.+]?\\+[0-9]+[hdwmy]\\(/[0-9]+[hdwmy]\\)?\\)"
   "<[0-9]\\{4\\}-[0-9][0-9]-[0-9][0-9] [^>\n]*?\\([.+]?\\+[0-9]+[hdwmy]\\(/[0-9]+[hdwmy]\\)?\\)"
   "Regular expression for specifying repeated events.
   "Regular expression for specifying repeated events.
@@ -1072,23 +1076,6 @@ than its value."
 	  (const :tag "No limit" nil)
 	  (const :tag "No limit" nil)
 	  (integer :tag "Maximum level")))
 	  (integer :tag "Maximum level")))
 
 
-(defcustom org-drawers '("PROPERTIES" "CLOCK" "LOGBOOK" "RESULTS")
-  "Names of drawers.  Drawers are not opened by cycling on the headline above.
-Drawers only open with a TAB on the drawer line itself.  A drawer looks like
-this:
-   :DRAWERNAME:
-   .....
-   :END:
-The drawer \"PROPERTIES\" is special for capturing properties through
-the property API.
-
-Drawers can be defined on the per-file basis with a line like:
-
-#+DRAWERS: HIDDEN STATE PROPERTIES"
-  :group 'org-structure
-  :group 'org-cycle
-  :type '(repeat (string :tag "Drawer Name")))
-
 (defcustom org-hide-block-startup nil
 (defcustom org-hide-block-startup nil
   "Non-nil means entering Org-mode will fold all blocks.
   "Non-nil means entering Org-mode will fold all blocks.
 This can also be set in on a per-file basis with
 This can also be set in on a per-file basis with
@@ -2346,7 +2333,6 @@ taken from the (otherwise obsolete) variable `org-todo-interpretation'."
 (make-variable-buffer-local 'org-todo-keywords-1)
 (make-variable-buffer-local 'org-todo-keywords-1)
 (defvar org-todo-keywords-for-agenda nil)
 (defvar org-todo-keywords-for-agenda nil)
 (defvar org-done-keywords-for-agenda nil)
 (defvar org-done-keywords-for-agenda nil)
-(defvar org-drawers-for-agenda nil)
 (defvar org-todo-keyword-alist-for-agenda nil)
 (defvar org-todo-keyword-alist-for-agenda nil)
 (defvar org-tag-alist-for-agenda nil
 (defvar org-tag-alist-for-agenda nil
   "Alist of all tags from all agenda files.")
   "Alist of all tags from all agenda files.")
@@ -4596,9 +4582,6 @@ Otherwise, these types are allowed:
 
 
 ;;; Variables for pre-computed regular expressions, all buffer local
 ;;; Variables for pre-computed regular expressions, all buffer local
 
 
-(defvar org-drawer-regexp "^[ \t]*:PROPERTIES:[ \t]*$"
-  "Matches first line of a hidden block.")
-(make-variable-buffer-local 'org-drawer-regexp)
 (defvar org-todo-regexp nil
 (defvar org-todo-regexp nil
   "Matches any of the TODO state keywords.")
   "Matches any of the TODO state keywords.")
 (make-variable-buffer-local 'org-todo-regexp)
 (make-variable-buffer-local 'org-todo-regexp)
@@ -4977,8 +4960,6 @@ Support for group tags is controlled by the option
 		(setq props (org-update-property-plist (match-string 1 value)
 		(setq props (org-update-property-plist (match-string 1 value)
 						       (match-string 2 value)
 						       (match-string 2 value)
 						       props))))
 						       props))))
-	     ((equal key "DRAWERS")
-	      (setq drawers (delete-dups (append org-drawers (org-split-string value splitre)))))
 	     ((equal key "CONSTANTS")
 	     ((equal key "CONSTANTS")
 	      (org-table-set-constants))
 	      (org-table-set-constants))
 	     ((equal key "STARTUP")
 	     ((equal key "STARTUP")
@@ -5034,7 +5015,6 @@ Support for group tags is controlled by the option
 	(org-set-local 'org-lowest-priority  (nth 1 prio))
 	(org-set-local 'org-lowest-priority  (nth 1 prio))
 	(org-set-local 'org-default-priority (nth 2 prio)))
 	(org-set-local 'org-default-priority (nth 2 prio)))
       (and props (org-set-local 'org-file-properties (nreverse props)))
       (and props (org-set-local 'org-file-properties (nreverse props)))
-      (and drawers (org-set-local 'org-drawers drawers))
       (and arch (org-set-local 'org-archive-location arch))
       (and arch (org-set-local 'org-archive-location arch))
       (and links (setq org-link-abbrev-alist-local (nreverse links)))
       (and links (setq org-link-abbrev-alist-local (nreverse links)))
       ;; Process the TODO keywords
       ;; Process the TODO keywords
@@ -5094,10 +5074,6 @@ Support for group tags is controlled by the option
 					    (length org-scheduled-string)
 					    (length org-scheduled-string)
 					    (length org-clock-string)
 					    (length org-clock-string)
 					    (length org-closed-string)))
 					    (length org-closed-string)))
-	    org-drawer-regexp
-	    (concat "^[ \t]*:\\("
-		    (mapconcat 'regexp-quote org-drawers "\\|")
-		    "\\):[ \t]*$")
 	    org-not-done-keywords
 	    org-not-done-keywords
 	    (org-delete-all org-done-keywords (copy-sequence org-todo-keywords-1))
 	    (org-delete-all org-done-keywords (copy-sequence org-todo-keywords-1))
 	    org-todo-regexp
 	    org-todo-regexp
@@ -6624,11 +6600,10 @@ in special contexts.
        ((eq arg t) (org-cycle-internal-global))
        ((eq arg t) (org-cycle-internal-global))
 
 
        ;; Drawers: delegate to `org-flag-drawer'.
        ;; Drawers: delegate to `org-flag-drawer'.
-       ((and org-drawers org-drawer-regexp
-	     (save-excursion
-	       (beginning-of-line 1)
-	       (looking-at org-drawer-regexp)))
-	(org-flag-drawer ; toggle block visibility
+       ((save-excursion
+	  (beginning-of-line 1)
+	  (looking-at org-drawer-regexp))
+	(org-flag-drawer		; toggle block visibility
 	 (not (get-char-property (match-end 0) 'invisible))))
 	 (not (get-char-property (match-end 0) 'invisible))))
 
 
        ;; Show-subtree, ARG levels up from here.
        ;; Show-subtree, ARG levels up from here.
@@ -7058,8 +7033,10 @@ open and agenda-wise Org files."
   "Return the end position of the current entry."
   "Return the end position of the current entry."
   (save-excursion (outline-next-heading) (point)))
   (save-excursion (outline-next-heading) (point)))
 
 
-(defun org-cycle-hide-drawers (state)
-  "Re-hide all drawers after a visibility state change."
+(defun org-cycle-hide-drawers (state &optional exceptions)
+  "Re-hide all drawers after a visibility state change.
+When non-nil, optional argument EXCEPTIONS is a list of strings
+specifying which drawers should not be hidden."
   (when (and (derived-mode-p 'org-mode)
   (when (and (derived-mode-p 'org-mode)
 	     (not (memq state '(overview folded contents))))
 	     (not (memq state '(overview folded contents))))
     (save-excursion
     (save-excursion
@@ -7071,7 +7048,8 @@ open and agenda-wise Org files."
 		      (org-end-of-subtree t)))))
 		      (org-end-of-subtree t)))))
 	(goto-char beg)
 	(goto-char beg)
 	(while (re-search-forward org-drawer-regexp end t)
 	(while (re-search-forward org-drawer-regexp end t)
-	  (org-flag-drawer t))))))
+	  (unless (member-ignore-case (match-string 1) exceptions)
+	    (org-flag-drawer t)))))))
 
 
 (defun org-cycle-hide-inline-tasks (state)
 (defun org-cycle-hide-inline-tasks (state)
   "Re-hide inline task when switching to 'contents visibility state."
   "Re-hide inline task when switching to 'contents visibility state."
@@ -8523,8 +8501,7 @@ and still retain the repeater to cover future instances of the task."
 		(kill-whole-line))
 		(kill-whole-line))
 	      (goto-char (point-min))
 	      (goto-char (point-min))
 	      (while (re-search-forward drawer-re nil t)
 	      (while (re-search-forward drawer-re nil t)
-		(mapc (lambda (d)
-			(org-remove-empty-drawer-at d (point))) org-drawers)))
+		(org-remove-empty-drawer-at (point))))
 	    (goto-char (point-min))
 	    (goto-char (point-min))
 	    (when doshift
 	    (when doshift
 	      (while (re-search-forward org-ts-regexp-both nil t)
 	      (while (re-search-forward org-ts-regexp-both nil t)
@@ -12454,7 +12431,7 @@ See variable `org-track-ordered-property-with-tag'."
       (org-back-to-heading)
       (org-back-to-heading)
       (if (org-entry-get nil "ORDERED")
       (if (org-entry-get nil "ORDERED")
 	  (progn
 	  (progn
-	    (org-delete-property "ORDERED" "PROPERTIES")
+	    (org-delete-property "ORDERED")
 	    (and tag (org-toggle-tag tag 'off))
 	    (and tag (org-toggle-tag tag 'off))
 	    (message "Subtasks can be completed in arbitrary order"))
 	    (message "Subtasks can be completed in arbitrary order"))
 	(org-entry-put nil "ORDERED" "t")
 	(org-entry-put nil "ORDERED" "t")
@@ -13371,9 +13348,7 @@ EXTRA is additional text that will be inserted into the notes buffer."
       (push note lines))
       (push note lines))
     (when (or current-prefix-arg org-note-abort)
     (when (or current-prefix-arg org-note-abort)
       (when org-log-into-drawer
       (when org-log-into-drawer
-	(org-remove-empty-drawer-at
-	 (if (stringp org-log-into-drawer) org-log-into-drawer "LOGBOOK")
-	 org-log-note-marker))
+	(org-remove-empty-drawer-at org-log-note-marker))
       (setq lines nil))
       (setq lines nil))
     (when lines
     (when lines
       (with-current-buffer (marker-buffer org-log-note-marker)
       (with-current-buffer (marker-buffer org-log-note-marker)
@@ -13418,17 +13393,20 @@ EXTRA is additional text that will be inserted into the notes buffer."
     (move-marker org-log-note-return-to nil)
     (move-marker org-log-note-return-to nil)
     (and org-log-post-message (message "%s" org-log-post-message))))
     (and org-log-post-message (message "%s" org-log-post-message))))
 
 
-(defun org-remove-empty-drawer-at (drawer pos)
-  "Remove an empty drawer DRAWER at position POS.
+(defun org-remove-empty-drawer-at (pos)
+  "Remove an empty drawer at position POS.
 POS may also be a marker."
 POS may also be a marker."
   (with-current-buffer (if (markerp pos) (marker-buffer pos) (current-buffer))
   (with-current-buffer (if (markerp pos) (marker-buffer pos) (current-buffer))
-    (save-excursion
-      (save-restriction
-	(widen)
-	(goto-char pos)
-	(if (org-in-regexp
-	     (concat "^[ \t]*:" drawer ":[ \t]*\n[ \t]*:END:[ \t]*\n?") 2)
-	    (replace-match ""))))))
+    (org-with-wide-buffer
+     (goto-char pos)
+     (let ((drawer (org-element-at-point)))
+       (when (and (memq (org-element-type drawer) '(drawer property-drawer))
+		  (not (org-element-property :contents-begin drawer)))
+	 (delete-region (org-element-property :begin drawer)
+			(progn (goto-char (org-element-property :end drawer))
+			       (skip-chars-backward " \r\t\n")
+			       (forward-line)
+			       (point))))))))
 
 
 (defvar org-ts-type nil)
 (defvar org-ts-type nil)
 (defun org-sparse-tree (&optional arg type)
 (defun org-sparse-tree (&optional arg type)
@@ -14954,7 +14932,6 @@ a *different* entry, you cannot use these techniques."
 	   org-todo-keywords-for-agenda
 	   org-todo-keywords-for-agenda
 	   org-done-keywords-for-agenda
 	   org-done-keywords-for-agenda
 	   org-todo-keyword-alist-for-agenda
 	   org-todo-keyword-alist-for-agenda
-	   org-drawers-for-agenda
 	   org-tag-alist-for-agenda
 	   org-tag-alist-for-agenda
 	   todo-only)
 	   todo-only)
 
 
@@ -15336,13 +15313,10 @@ If yes, return this value.  If not, return the current value of the variable."
 	(read prop)
 	(read prop)
       (symbol-value var))))
       (symbol-value var))))
 
 
-(defun org-entry-delete (pom property &optional delete-empty-drawer)
-  "Delete the property PROPERTY from entry at point-or-marker POM.
-When optional argument DELETE-EMPTY-DRAWER is a string, it defines
-an empty drawer to delete."
-  (org-with-point-at pom
-    (if (member property org-special-properties)
-	nil ; cannot delete these properties.
+(defun org-entry-delete (pom property)
+  "Delete the property PROPERTY from entry at point-or-marker POM."
+  (unless (member property org-special-properties)
+    (org-with-point-at pom
       (let ((range (org-get-property-block)))
       (let ((range (org-get-property-block)))
 	(if (and range
 	(if (and range
 		 (goto-char (car range))
 		 (goto-char (car range))
@@ -15351,9 +15325,7 @@ an empty drawer to delete."
 		  (cdr range) t))
 		  (cdr range) t))
 	    (progn
 	    (progn
 	      (delete-region (match-beginning 0) (1+ (point-at-eol)))
 	      (delete-region (match-beginning 0) (1+ (point-at-eol)))
-	      (and delete-empty-drawer
-		   (org-remove-empty-drawer-at
-		    delete-empty-drawer (car range)))
+	      (org-remove-empty-drawer-at (car range))
 	      t)
 	      t)
 	  nil)))))
 	  nil)))))
 
 
@@ -15632,23 +15604,14 @@ instead.
 
 
 Point is left between drawer's boundaries."
 Point is left between drawer's boundaries."
   (interactive "P")
   (interactive "P")
-  (let* ((logbook (if (stringp org-log-into-drawer) org-log-into-drawer
-		    "LOGBOOK"))
-	 ;; SYSTEM-DRAWERS is a list of drawer names that are used
-	 ;; internally by Org.  They are meant to be inserted
-	 ;; automatically.
-	 (system-drawers `("CLOCK" ,logbook "PROPERTIES"))
-	 ;; Remove system drawers from list.  Note: For some reason,
-	 ;; `org-completing-read' ignores the predicate while
-	 ;; `completing-read' handles it fine.
-	 (drawer (if arg "PROPERTIES"
-		   (or drawer
-		       (completing-read
-			"Drawer: " org-drawers
-			(lambda (d) (not (member d system-drawers))))))))
+  (let* ((drawer (if arg "PROPERTIES"
+		   (or drawer (read-from-minibuffer "Drawer: ")))))
     (cond
     (cond
      ;; With C-u, fall back on `org-insert-property-drawer'
      ;; With C-u, fall back on `org-insert-property-drawer'
      (arg (org-insert-property-drawer))
      (arg (org-insert-property-drawer))
+     ;;
+     ((not (org-string-match-p org-drawer-regexp (format ":%s:" drawer)))
+      (user-error "Invalid drawer name"))
      ;; With an active region, insert a drawer at point.
      ;; With an active region, insert a drawer at point.
      ((not (org-region-active-p))
      ((not (org-region-active-p))
       (progn
       (progn
@@ -15784,17 +15747,15 @@ in the current file."
     (unless (equal (org-entry-get nil property) value)
     (unless (equal (org-entry-get nil property) value)
       (org-entry-put nil property value))))
       (org-entry-put nil property value))))
 
 
-(defun org-delete-property (property &optional delete-empty-drawer)
-  "In the current entry, delete PROPERTY.
-When optional argument DELETE-EMPTY-DRAWER is a string, it defines
-an empty drawer to delete."
+(defun org-delete-property (property)
+  "In the current entry, delete PROPERTY."
   (interactive
   (interactive
    (let* ((completion-ignore-case t)
    (let* ((completion-ignore-case t)
 	  (prop (org-icompleting-read "Property: "
 	  (prop (org-icompleting-read "Property: "
 				      (org-entry-properties nil 'standard))))
 				      (org-entry-properties nil 'standard))))
      (list prop)))
      (list prop)))
   (message "Property %s %s" property
   (message "Property %s %s" property
-	   (if (org-entry-delete nil property delete-empty-drawer)
+	   (if (org-entry-delete nil property)
 	       "deleted"
 	       "deleted"
 	     "was not present in the entry")))
 	     "was not present in the entry")))
 
 
@@ -18081,8 +18042,6 @@ When a buffer is unmodified, it is just killed.  When modified, it is saved
 		  (append org-done-keywords-for-agenda org-done-keywords))
 		  (append org-done-keywords-for-agenda org-done-keywords))
 	    (setq org-todo-keyword-alist-for-agenda
 	    (setq org-todo-keyword-alist-for-agenda
 		  (append org-todo-keyword-alist-for-agenda org-todo-key-alist))
 		  (append org-todo-keyword-alist-for-agenda org-todo-key-alist))
-	    (setq org-drawers-for-agenda
-		  (append org-drawers-for-agenda org-drawers))
 	    (setq org-tag-alist-for-agenda
 	    (setq org-tag-alist-for-agenda
 		  (org-uniquify
 		  (org-uniquify
 		   (append org-tag-alist-for-agenda
 		   (append org-tag-alist-for-agenda
@@ -21679,15 +21638,13 @@ block from point."
       nil)))
       nil)))
 
 
 (defun org-in-drawer-p ()
 (defun org-in-drawer-p ()
-  "Is point within a drawer?"
-  (save-match-data
-    (let ((case-fold-search t)
-	  (lim-up (save-excursion (outline-previous-heading)))
-	  (lim-down (save-excursion (outline-next-heading))))
-      (org-between-regexps-p
-       (concat "^[ \t]*:" (regexp-opt org-drawers) ":")
-       "^[ \t]*:end:.*$"
-       lim-up lim-down))))
+  "Non-nil if point is within a drawer.
+If point is within a drawer, return it, as parsed data."
+  (let ((element (save-match-data (org-element-at-point))))
+    (while (and element (not (memq (org-element-type element)
+				   '(drawer property-drawer))))
+      (setq element (org-element-property :parent element)))
+    element))
 
 
 (defun org-occur-in-agenda-files (regexp &optional nlines)
 (defun org-occur-in-agenda-files (regexp &optional nlines)
   "Call `multi-occur' with buffers for all agenda files."
   "Call `multi-occur' with buffers for all agenda files."

+ 22 - 35
testing/lisp/test-org-element.el

@@ -415,21 +415,18 @@ Some other text
   "Test `drawer' parser."
   "Test `drawer' parser."
   ;; Standard test.
   ;; Standard test.
   (should
   (should
-   (let ((org-drawers '("TEST")))
-     (org-test-with-temp-text ":TEST:\nText\n:END:"
-       (org-element-map (org-element-parse-buffer) 'drawer 'identity))))
+   (org-test-with-temp-text ":TEST:\nText\n:END:"
+     (org-element-map (org-element-parse-buffer) 'drawer 'identity)))
   ;; Do not mix regular drawers and property drawers.
   ;; Do not mix regular drawers and property drawers.
   (should-not
   (should-not
-   (let ((org-drawers '("PROPERTIES")))
-     (org-test-with-temp-text ":PROPERTIES:\n:prop: value\n:END:"
-       (org-element-map
-	(org-element-parse-buffer) 'drawer 'identity nil t))))
+   (org-test-with-temp-text ":PROPERTIES:\n:prop: value\n:END:"
+     (org-element-map
+	 (org-element-parse-buffer) 'drawer 'identity nil t)))
   ;; Ignore incomplete drawer.
   ;; Ignore incomplete drawer.
   (should-not
   (should-not
-   (let ((org-drawers '("TEST")))
-     (org-test-with-temp-text ":TEST:"
-       (org-element-map
-	(org-element-parse-buffer) 'drawer 'identity nil t)))))
+   (org-test-with-temp-text ":TEST:"
+     (org-element-map
+	 (org-element-parse-buffer) 'drawer 'identity nil t))))
 
 
 
 
 ;;;; Dynamic Block
 ;;;; Dynamic Block
@@ -1403,16 +1400,10 @@ e^{i\\pi}+1=0
      (org-element-map (org-element-parse-buffer) 'paragraph 'identity)))
      (org-element-map (org-element-parse-buffer) 'paragraph 'identity)))
   ;; Include incomplete-drawers.
   ;; Include incomplete-drawers.
   (should
   (should
-   (let ((org-drawers '("TEST")))
-     (org-test-with-temp-text ":TEST:\nParagraph"
-       (let ((elem (org-element-at-point)))
-	 (and (eq (org-element-type elem) 'paragraph)
-	      (= (point-max) (org-element-property :end elem)))))))
-  ;; Include non-existent drawers.
-  (should
-   (let ((org-drawers '("TEST")))
-     (org-test-with-temp-text ":NONAME:"
-       (org-element-map (org-element-parse-buffer) 'paragraph 'identity))))
+   (org-test-with-temp-text ":TEST:\nParagraph"
+     (let ((elem (org-element-at-point)))
+       (and (eq (org-element-type elem) 'paragraph)
+	    (= (point-max) (org-element-property :end elem))))))
   ;; Include incomplete blocks.
   ;; Include incomplete blocks.
   (should
   (should
    (org-test-with-temp-text "#+BEGIN_CENTER\nParagraph"
    (org-test-with-temp-text "#+BEGIN_CENTER\nParagraph"
@@ -1505,22 +1496,19 @@ Outside list"
   "Test `property-drawer' parser."
   "Test `property-drawer' parser."
   ;; Standard test.
   ;; Standard test.
   (should
   (should
-   (let ((org-drawers '("PROPERTIES")))
-     (org-test-with-temp-text ":PROPERTIES:\n:prop: value\n:END:"
-       (org-element-map
-	(org-element-parse-buffer) 'property-drawer 'identity nil t))))
+   (org-test-with-temp-text ":PROPERTIES:\n:prop: value\n:END:"
+     (org-element-map
+	 (org-element-parse-buffer) 'property-drawer 'identity nil t)))
   ;; Do not mix property drawers and regular drawers.
   ;; Do not mix property drawers and regular drawers.
   (should-not
   (should-not
-   (let ((org-drawers '("TEST")))
-     (org-test-with-temp-text ":TEST:\n:prop: value\n:END:"
-       (org-element-map
-	(org-element-parse-buffer) 'property-drawer 'identity nil t))))
+   (org-test-with-temp-text ":TEST:\n:prop: value\n:END:"
+     (org-element-map
+	 (org-element-parse-buffer) 'property-drawer 'identity nil t)))
   ;; Ignore incomplete drawer.
   ;; Ignore incomplete drawer.
   (should-not
   (should-not
-   (let ((org-drawers '("PROPERTIES")))
-     (org-test-with-temp-text ":PROPERTIES:\n:prop: value"
-       (org-element-map
-	(org-element-parse-buffer) 'property-drawer 'identity nil t)))))
+   (org-test-with-temp-text ":PROPERTIES:\n:prop: value"
+     (org-element-map
+	 (org-element-parse-buffer) 'property-drawer 'identity nil t))))
 
 
 
 
 ;;;; Quote Block
 ;;;; Quote Block
@@ -1965,8 +1953,7 @@ Outside list"
 (ert-deftest test-org-element/drawer-interpreter ()
 (ert-deftest test-org-element/drawer-interpreter ()
   "Test drawer interpreter."
   "Test drawer interpreter."
   (should
   (should
-   (equal (let ((org-drawers '("TEST")))
-	    (org-test-parse-and-interpret ":TEST:\nTest\n:END:"))
+   (equal (org-test-parse-and-interpret ":TEST:\nTest\n:END:")
 	  ":TEST:\nTest\n:END:\n")))
 	  ":TEST:\nTest\n:END:\n")))
 
 
 (ert-deftest test-org-element/dynamic-block-interpreter ()
 (ert-deftest test-org-element/dynamic-block-interpreter ()

+ 10 - 12
testing/lisp/test-org.el

@@ -392,20 +392,18 @@
      (looking-at "- $")))
      (looking-at "- $")))
   ;; In a drawer and paragraph insert an empty line, in this case above.
   ;; In a drawer and paragraph insert an empty line, in this case above.
   (should
   (should
-   (let ((org-drawers '("MYDRAWER")))
-     (org-test-with-temp-text ":MYDRAWER:\na\n:END:"
-       (forward-line)
-       (org-meta-return)
-       (forward-line -1)
-       (looking-at "$"))))
+   (org-test-with-temp-text ":MYDRAWER:\na\n:END:"
+     (forward-line)
+     (org-meta-return)
+     (forward-line -1)
+     (looking-at "$")))
   ;; In a drawer and item insert an item, in this case above.
   ;; In a drawer and item insert an item, in this case above.
   (should
   (should
-   (let ((org-drawers '("MYDRAWER")))
-     (org-test-with-temp-text ":MYDRAWER:\n- a\n:END:"
-       (forward-line)
-       (org-meta-return)
-       (beginning-of-line)
-       (looking-at "- $")))))
+   (org-test-with-temp-text ":MYDRAWER:\n- a\n:END:"
+     (forward-line)
+     (org-meta-return)
+     (beginning-of-line)
+     (looking-at "- $"))))
 
 
 (ert-deftest test-org/insert-todo-heading-respect-content ()
 (ert-deftest test-org/insert-todo-heading-respect-content ()
   "Test `org-insert-todo-heading-respect-content' specifications."
   "Test `org-insert-todo-heading-respect-content' specifications."

+ 12 - 16
testing/lisp/test-ox.el

@@ -414,28 +414,24 @@ Paragraph"
   ;; Drawers.
   ;; Drawers.
   (should
   (should
    (equal ""
    (equal ""
-	  (let ((org-drawers '("TEST")))
-	    (org-test-with-temp-text ":TEST:\ncontents\n:END:"
-	      (org-export-as (org-test-default-backend)
-			     nil nil nil '(:with-drawers nil))))))
+	  (org-test-with-temp-text ":TEST:\ncontents\n:END:"
+	    (org-export-as (org-test-default-backend)
+			   nil nil nil '(:with-drawers nil)))))
   (should
   (should
    (equal ":TEST:\ncontents\n:END:\n"
    (equal ":TEST:\ncontents\n:END:\n"
-	  (let ((org-drawers '("TEST")))
-	    (org-test-with-temp-text ":TEST:\ncontents\n:END:"
-	      (org-export-as (org-test-default-backend)
-			     nil nil nil '(:with-drawers t))))))
+	  (org-test-with-temp-text ":TEST:\ncontents\n:END:"
+	    (org-export-as (org-test-default-backend)
+			   nil nil nil '(:with-drawers t)))))
   (should
   (should
    (equal ":FOO:\nkeep\n:END:\n"
    (equal ":FOO:\nkeep\n:END:\n"
-	  (let ((org-drawers '("FOO" "BAR")))
-	    (org-test-with-temp-text ":FOO:\nkeep\n:END:\n:BAR:\nremove\n:END:"
-	      (org-export-as (org-test-default-backend)
-			     nil nil nil '(:with-drawers ("FOO")))))))
+	  (org-test-with-temp-text ":FOO:\nkeep\n:END:\n:BAR:\nremove\n:END:"
+	    (org-export-as (org-test-default-backend)
+			   nil nil nil '(:with-drawers ("FOO"))))))
   (should
   (should
    (equal ":FOO:\nkeep\n:END:\n"
    (equal ":FOO:\nkeep\n:END:\n"
-	  (let ((org-drawers '("FOO" "BAR")))
-	    (org-test-with-temp-text ":FOO:\nkeep\n:END:\n:BAR:\nremove\n:END:"
-	      (org-export-as (org-test-default-backend)
-			     nil nil nil '(:with-drawers (not "BAR")))))))
+	  (org-test-with-temp-text ":FOO:\nkeep\n:END:\n:BAR:\nremove\n:END:"
+	    (org-export-as (org-test-default-backend)
+			   nil nil nil '(:with-drawers (not "BAR"))))))
   ;; Footnotes.
   ;; Footnotes.
   (should
   (should
    (equal "Footnote?"
    (equal "Footnote?"