From mboxrd@z Thu Jan 1 00:00:00 1970 From: Nicolas Goaziou Subject: [RFC] Do not declare drawers to use them Date: Sun, 20 Oct 2013 15:38:48 +0200 Message-ID: <87txgc3vvb.fsf@gmail.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Return-path: Received: from eggs.gnu.org ([2001:4830:134:3::10]:48299) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VXtDL-0006ex-Gx for emacs-orgmode@gnu.org; Sun, 20 Oct 2013 09:38:45 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1VXtDF-0002z1-Ig for emacs-orgmode@gnu.org; Sun, 20 Oct 2013 09:38:39 -0400 Received: from mail-wi0-x231.google.com ([2a00:1450:400c:c05::231]:54701) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VXtDE-0002yu-W6 for emacs-orgmode@gnu.org; Sun, 20 Oct 2013 09:38:33 -0400 Received: by mail-wi0-f177.google.com with SMTP id h11so2855222wiv.16 for ; Sun, 20 Oct 2013 06:38:32 -0700 (PDT) Received: from selenimh ([91.224.148.150]) by mx.google.com with ESMTPSA id d11sm45894906wic.4.2013.10.20.06.38.30 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 20 Oct 2013 06:38:31 -0700 (PDT) List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Sender: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org To: Org Mode List --=-=-= Content-Type: text/plain Hello, At the moment, in order to use a drawer, one has to declare its name through `org-drawers' variable or DRAWERS keyword first. I'd like to simplify a bit the process and let the user create drawers on the fly instead. A valid name includes any word constituent, hyphen and underscore characters. Case isn't significant. It also cleans the internals (i.e. some dynamically scoped variables are removed) and makes syntax more portable. But we lose completion for drawer names. This patch is backward compatible, as long as previously user-defined drawers didn't include forbidden characters within their names. WDYT? Regards, -- Nicolas Goaziou --=-=-= Content-Type: text/x-diff Content-Disposition: attachment; filename=0001-Remove-need-to-declare-drawers-before-using-them.patch >From 8a2dad690caec96e6daf86097ff0cb062ac348f8 Mon Sep 17 00:00:00 2001 From: Nicolas Goaziou Date: Sun, 20 Oct 2013 14:40:09 +0200 Subject: [PATCH] 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. --- lisp/org-agenda.el | 15 ++--- lisp/org-clock.el | 6 +- lisp/org-element.el | 5 +- lisp/org-feed.el | 5 +- lisp/org-list.el | 25 ++----- lisp/org-mobile.el | 4 +- lisp/org-pcomplete.el | 19 ------ lisp/org.el | 141 ++++++++++++++------------------------- testing/lisp/test-org-element.el | 57 ++++++---------- testing/lisp/test-org.el | 22 +++--- testing/lisp/test-ox.el | 28 ++++---- 11 files changed, 109 insertions(+), 218 deletions(-) diff --git a/lisp/org-agenda.el b/lisp/org-agenda.el index 0bfba27..fe4c2d4 100644 --- a/lisp/org-agenda.el +++ b/lisp/org-agenda.el @@ -3642,7 +3642,6 @@ generating a new one." (or org-agenda-multi (org-agenda-fit-window-to-buffer)) (throw 'exit "Sticky Agenda buffer, use `r' to refresh")) (setq org-todo-keywords-for-agenda nil) - (setq org-drawers-for-agenda nil) (unless org-agenda-persistent-filter (setq org-agenda-tag-filter nil org-agenda-category-filter nil @@ -3682,7 +3681,6 @@ generating a new one." (org-uniquify org-todo-keywords-for-agenda)) (setq 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-this-buffer-name org-agenda-buffer-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)) (message "Remote: SUBTREE")) ((= 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")) ((> more 4) (show-subtree) diff --git a/lisp/org-clock.el b/lisp/org-clock.el index 3195dc1..1cdbdc1 100644 --- a/lisp/org-clock.el +++ b/lisp/org-clock.el @@ -1589,7 +1589,7 @@ to, overriding the existing value of `org-clock-out-switch-to-state'." (while (and (< (point) end) (search-forward clock-drawer end t)) (goto-char (match-beginning 0)) - (org-remove-empty-drawer-at clock-drawer (point)) + (org-remove-empty-drawer-at (point)) (forward-line 1)))))) (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) (force-mode-line-update) (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))) (goto-char org-clock-marker) (if (org-looking-back (concat "^[ \t]*" org-clock-string ".*")) (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") (sit-for 2))) (move-marker org-clock-marker nil) diff --git a/lisp/org-element.el b/lisp/org-element.el index ed1f515..af5f13c 100644 --- a/lisp/org-element.el +++ b/lisp/org-element.el @@ -1146,9 +1146,6 @@ CONTENTS is the contents of the element." (let ((case-fold-search t) (top-ind limit) (item-re (org-item-re)) - (drawers-re (concat ":\\(" - (mapconcat 'regexp-quote org-drawers "\\|") - "\\):[ \t]*$")) (inlinetask-re (and (featurep 'org-inlinetask) "^\\*+ ")) items struct) (save-excursion @@ -1221,7 +1218,7 @@ CONTENTS is the contents of the element." (format "^[ \t]*#\\+END%s[ \t]*$" (org-match-string-no-properties 1)) limit t))) - ((and (looking-at drawers-re) + ((and (looking-at org-drawer-regexp) (re-search-forward "^[ \t]*:END:[ \t]*$" limit t)))) (forward-line)))))))) diff --git a/lisp/org-feed.el b/lisp/org-feed.el index 05ead8f..5a54f70 100644 --- a/lisp/org-feed.el +++ b/lisp/org-feed.el @@ -215,10 +215,7 @@ Here are the keyword-value pair allows in `org-feed-alist'. (defcustom org-feed-drawer "FEEDSTATUS" "The name of the drawer for feed status information. 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 :type '(string :tag "Drawer Name")) diff --git a/lisp/org-list.el b/lisp/org-list.el index 4a3d471..3cb9b32 100644 --- a/lisp/org-list.el +++ b/lisp/org-list.el @@ -88,7 +88,6 @@ (defvar org-closed-string) (defvar org-deadline-string) (defvar org-description-max-indent) -(defvar org-drawers) (defvar org-odd-levels-only) (defvar org-scheduled-string) (defvar org-ts-regexp) @@ -430,9 +429,6 @@ group 4: description tag") (let* ((case-fold-search t) (context (org-list-context)) (lim-up (car context)) - (drawers-re (concat "^[ \t]*:\\(" - (mapconcat 'regexp-quote org-drawers "\\|") - "\\):[ \t]*$")) (inlinetask-re (and (featurep 'org-inlinetask) (org-inlinetask-outline-regexp))) (item-re (org-item-re)) @@ -476,7 +472,7 @@ group 4: description tag") ((and (looking-at "^[ \t]*#\\+end_") (re-search-backward "^[ \t]*#\\+begin_" lim-up t))) ((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)) ((and inlinetask-re (looking-at inlinetask-re)) (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)))) ;; Is point inside a drawer? (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 (and (not (looking-at beg-re)) (not (looking-at end-re)) @@ -635,9 +627,6 @@ Assume point is at an item." (lim-down (nth 1 context)) (text-min-ind 10000) (item-re (org-item-re)) - (drawers-re (concat "^[ \t]*:\\(" - (mapconcat 'regexp-quote org-drawers "\\|") - "\\):[ \t]*$")) (inlinetask-re (and (featurep 'org-inlinetask) (org-inlinetask-outline-regexp))) (beg-cell (cons (point) (org-get-indentation))) @@ -700,7 +689,7 @@ Assume point is at an item." ((and (looking-at "^[ \t]*#\\+end_") (re-search-backward "^[ \t]*#\\+begin_" lim-up t))) ((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)) ((and inlinetask-re (looking-at inlinetask-re)) (org-inlinetask-goto-beginning) @@ -766,7 +755,7 @@ Assume point is at an item." (cond ((and (looking-at "^[ \t]*#\\+begin_") (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)))) (forward-line 1)))))) (setq struct (append itm-lst (cdr (nreverse itm-lst-2))) @@ -2326,9 +2315,6 @@ in subtree, ignoring drawers." block-item lim-up lim-down - (drawer-re (concat "^[ \t]*:\\(" - (mapconcat 'regexp-quote org-drawers "\\|") - "\\):[ \t]*$")) (keyword-re (concat "^[ \t]*\\<\\(" org-scheduled-string "\\|" org-deadline-string "\\|" org-closed-string @@ -2350,7 +2336,8 @@ in subtree, ignoring drawers." ;; time-stamps (scheduled, etc.). (let ((limit (save-excursion (outline-next-heading) (point)))) (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) (forward-line 1) (re-search-forward "^[ \t]*:END:" limit nil))) diff --git a/lisp/org-mobile.el b/lisp/org-mobile.el index a43896b..54b6e03 100644 --- a/lisp/org-mobile.el +++ b/lisp/org-mobile.el @@ -425,7 +425,7 @@ agenda view showing the flagged items." (def-tags (default-value 'org-tag-alist)) (target-file (expand-file-name org-mobile-index-file 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)) (setq def-todo (list (cons 'sequence def-todo)))) (org-agenda-prepare-buffers (mapcar 'car files-alist)) @@ -433,7 +433,6 @@ agenda view showing the flagged items." (setq todo-kwds (org-delete-all done-kwds (org-uniquify org-todo-keywords-for-agenda))) - (setq drawers (org-uniquify org-drawers-for-agenda)) (setq tags (mapcar 'car (org-global-tags-completion-table (mapcar 'car files-alist)))) (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 (append def-tags tags nil)) (insert "#+TAGS: " (mapconcat 'identity tags " ") "\n") - (insert "#+DRAWERS: " (mapconcat 'identity drawers " ") "\n") (insert "#+ALLPRIORITIES: " org-mobile-allpriorities "\n") (when (file-exists-p (expand-file-name org-mobile-directory "agendas.org")) diff --git a/lisp/org-pcomplete.el b/lisp/org-pcomplete.el index 77f68f4..1eee779 100644 --- a/lisp/org-pcomplete.el +++ b/lisp/org-pcomplete.el @@ -363,25 +363,6 @@ This needs more work, to handle headings with lots of spaces in them." lst)) (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 () "Complete the arguments of a begin_src block. Complete a language in the first field, the header arguments and switches." diff --git a/lisp/org.el b/lisp/org.el index 8c4b5e7..e9807f8 100644 --- a/lisp/org.el +++ b/lisp/org.el @@ -883,6 +883,10 @@ An entry can be toggled between QUOTE and normal with :group 'org-keywords :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 "<[0-9]\\{4\\}-[0-9][0-9]-[0-9][0-9] [^>\n]*?\\([.+]?\\+[0-9]+[hdwmy]\\(/[0-9]+[hdwmy]\\)?\\)" "Regular expression for specifying repeated events. @@ -1071,23 +1075,6 @@ than its value." (const :tag "No limit" nil) (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 "Non-nil means entering Org-mode will fold all blocks. This can also be set in on a per-file basis with @@ -2345,7 +2332,6 @@ taken from the (otherwise obsolete) variable `org-todo-interpretation'." (make-variable-buffer-local 'org-todo-keywords-1) (defvar org-todo-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-tag-alist-for-agenda nil "Alist of all tags from all agenda files.") @@ -4595,9 +4581,6 @@ Otherwise, these types are allowed: ;;; 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 "Matches any of the TODO state keywords.") (make-variable-buffer-local 'org-todo-regexp) @@ -4976,8 +4959,6 @@ Support for group tags is controlled by the option (setq props (org-update-property-plist (match-string 1 value) (match-string 2 value) props)))) - ((equal key "DRAWERS") - (setq drawers (delete-dups (append org-drawers (org-split-string value splitre))))) ((equal key "CONSTANTS") (org-table-set-constants)) ((equal key "STARTUP") @@ -5033,7 +5014,6 @@ Support for group tags is controlled by the option (org-set-local 'org-lowest-priority (nth 1 prio)) (org-set-local 'org-default-priority (nth 2 prio))) (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 links (setq org-link-abbrev-alist-local (nreverse links))) ;; Process the TODO keywords @@ -5093,10 +5073,6 @@ Support for group tags is controlled by the option (length org-scheduled-string) (length org-clock-string) (length org-closed-string))) - org-drawer-regexp - (concat "^[ \t]*:\\(" - (mapconcat 'regexp-quote org-drawers "\\|") - "\\):[ \t]*$") org-not-done-keywords (org-delete-all org-done-keywords (copy-sequence org-todo-keywords-1)) org-todo-regexp @@ -6623,11 +6599,10 @@ in special contexts. ((eq arg t) (org-cycle-internal-global)) ;; 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)))) ;; Show-subtree, ARG levels up from here. @@ -7057,8 +7032,10 @@ open and agenda-wise Org files." "Return the end position of the current entry." (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) (not (memq state '(overview folded contents)))) (save-excursion @@ -7070,7 +7047,8 @@ open and agenda-wise Org files." (org-end-of-subtree t))))) (goto-char beg) (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) "Re-hide inline task when switching to 'contents visibility state." @@ -8521,8 +8499,7 @@ and still retain the repeater to cover future instances of the task." (kill-whole-line)) (goto-char (point-min)) (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)) (when doshift (while (re-search-forward org-ts-regexp-both nil t) @@ -12452,7 +12429,7 @@ See variable `org-track-ordered-property-with-tag'." (org-back-to-heading) (if (org-entry-get nil "ORDERED") (progn - (org-delete-property "ORDERED" "PROPERTIES") + (org-delete-property "ORDERED") (and tag (org-toggle-tag tag 'off)) (message "Subtasks can be completed in arbitrary order")) (org-entry-put nil "ORDERED" "t") @@ -13369,9 +13346,7 @@ EXTRA is additional text that will be inserted into the notes buffer." (push note lines)) (when (or current-prefix-arg org-note-abort) (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)) (when lines (with-current-buffer (marker-buffer org-log-note-marker) @@ -13416,17 +13391,20 @@ EXTRA is additional text that will be inserted into the notes buffer." (move-marker org-log-note-return-to nil) (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." (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) (defun org-sparse-tree (&optional arg type) @@ -14952,7 +14930,6 @@ a *different* entry, you cannot use these techniques." org-todo-keywords-for-agenda org-done-keywords-for-agenda org-todo-keyword-alist-for-agenda - org-drawers-for-agenda org-tag-alist-for-agenda todo-only) @@ -15334,13 +15311,10 @@ If yes, return this value. If not, return the current value of the variable." (read prop) (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))) (if (and range (goto-char (car range)) @@ -15349,9 +15323,7 @@ an empty drawer to delete." (cdr range) t)) (progn (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) nil))))) @@ -15630,23 +15602,14 @@ instead. Point is left between drawer's boundaries." (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 ;; With C-u, fall back on `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. ((not (org-region-active-p)) (progn @@ -15782,17 +15745,15 @@ in the current file." (unless (equal (org-entry-get 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 (let* ((completion-ignore-case t) (prop (org-icompleting-read "Property: " (org-entry-properties nil 'standard)))) (list prop))) (message "Property %s %s" property - (if (org-entry-delete nil property delete-empty-drawer) + (if (org-entry-delete nil property) "deleted" "was not present in the entry"))) @@ -18079,8 +18040,6 @@ When a buffer is unmodified, it is just killed. When modified, it is saved (append org-done-keywords-for-agenda org-done-keywords)) (setq org-todo-keyword-alist-for-agenda (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 (org-uniquify (append org-tag-alist-for-agenda @@ -21677,15 +21636,13 @@ block from point." nil))) (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) "Call `multi-occur' with buffers for all agenda files." diff --git a/testing/lisp/test-org-element.el b/testing/lisp/test-org-element.el index d30b6bc..f9bcc6e 100644 --- a/testing/lisp/test-org-element.el +++ b/testing/lisp/test-org-element.el @@ -415,21 +415,18 @@ Some other text "Test `drawer' parser." ;; Standard test. (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. (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. (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 @@ -1418,16 +1415,10 @@ e^{i\\pi}+1=0 (org-element-map (org-element-parse-buffer) 'paragraph 'identity))) ;; Include incomplete-drawers. (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. (should (org-test-with-temp-text "#+BEGIN_CENTER\nParagraph" @@ -1520,22 +1511,19 @@ Outside list" "Test `property-drawer' parser." ;; Standard test. (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. (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. (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 @@ -1988,8 +1976,7 @@ Outside list" (ert-deftest test-org-element/drawer-interpreter () "Test drawer interpreter." (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"))) (ert-deftest test-org-element/dynamic-block-interpreter () diff --git a/testing/lisp/test-org.el b/testing/lisp/test-org.el index 32fa69e..10f6c98 100644 --- a/testing/lisp/test-org.el +++ b/testing/lisp/test-org.el @@ -392,20 +392,18 @@ (looking-at "- $"))) ;; In a drawer and paragraph insert an empty line, in this case above. (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. (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 "- $")))) diff --git a/testing/lisp/test-ox.el b/testing/lisp/test-ox.el index 5a066a5..1aba00d 100644 --- a/testing/lisp/test-ox.el +++ b/testing/lisp/test-ox.el @@ -414,28 +414,24 @@ Paragraph" ;; Drawers. (should (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 (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 (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 (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. (should (equal "Footnote?" -- 1.8.4.1 --=-=-=--