emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
* Allowing :PROPERTIES: drawer to appear at the end of entries
@ 2023-04-25 22:53 John Wiegley
  2023-04-26  6:50 ` Ihor Radchenko
  0 siblings, 1 reply; 5+ messages in thread
From: John Wiegley @ 2023-04-25 22:53 UTC (permalink / raw)
  To: emacs-orgmode

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

I have about 21,000 headlines throughout my Org files, most of those tasks.
Nearly all of them have PROPERTIES drawers, and since those drawers appear at
the end of the entries, I've grown quite used to that arrangement. Anyway, it
didn't take much effort to adapt Org 9.x to allow for such positioning. This
patch is what I've been using, and it permits me to have the drawer either at
the beginning or the end.

What I haven't tested/modified yet is the code that drops items from the
cache, since that seems to also search for the properties re, yet I'm not sure
under what conditions that code is run...


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: properties-at-end.patch --]
[-- Type: text/x-patch, Size: 5432 bytes --]

--- a/lisp/org-element.el
+++ b/lisp/org-element.el
@@ -1018,6 +1018,20 @@ CONTENTS is the contents of the footnote-definition."
 
 ;;;; Headline
 
+(defcustom org-allow-properties-at-end t
+  "Allow the PROPERTIES drawer to appear at the end of an entry.
+Normally, for reasons of efficiency, the PROPERTIES drawer is
+expected to appear only at the beginning of an entry, after any
+scheduling lines. This avoids having to scan through a large
+entry in order to find its properties.
+
+When this option is non-nil, the PROPERIES drawer may also appear
+at the end of an entry. Note that this may adversely affect the
+speed of many operations, such as building the agenda."
+  :group 'org-todo
+  :type 'boolean
+  :package-version '(Org . "9.6.2"))
+
 (defun org-element--get-node-properties (&optional at-point-p?)
   "Return node properties for headline or property drawer at point.
 Upcase property names.  It avoids confusion between properties
@@ -1030,7 +1044,13 @@ parse properties for property drawer at point."
     (unless at-point-p?
       (forward-line)
       (when (looking-at-p org-element-planning-line-re) (forward-line)))
-    (when (looking-at org-property-drawer-re)
+    (when (if org-allow-properties-at-end
+              (and (re-search-forward org-property-drawer-re
+                                      (save-excursion
+                                        (outline-next-heading)
+                                        (point)) t)
+                   (goto-char (match-beginning 0)))
+            (looking-at org-property-drawer-re))
       (forward-line)
       (let ((end (match-end 0)) properties)
 	(while (< (line-end-position) end)
@@ -1158,8 +1178,14 @@ Assume point is at beginning of the headline."
                                             0)
                                           (point)))))
            (robust-end (and robust-begin
-                            (when (> (- contents-end 2) robust-begin)
-                              (- contents-end 2)))))
+                            (if (> (- contents-end 2) robust-begin)
+                                (min
+                                 (- contents-end 2)
+                                 (if (and org-allow-properties-at-end
+                                          (re-search-forward org-property-drawer-re
+                                                             contents-end t))
+                                     (- (match-beginning 0) 2)
+                                   (point-max)))))))
       (unless robust-end (setq robust-begin nil))
       (let ((headline
 	     (list 'headline
@@ -4246,13 +4272,14 @@ element it has to parse."
 	          (looking-at org-element-planning-line-re))
 	     (org-element-planning-parser limit))
             ;; Property drawer.
-            ((and (pcase mode
+            ((and (or org-allow-properties-at-end
+                      (pcase mode
 	                (`planning (eq ?* (char-after (line-beginning-position 0))))
 	                ((or `property-drawer `top-comment)
 		         (save-excursion
 		           (beginning-of-line 0)
 		           (not (looking-at "[[:blank:]]*$"))))
-	            (_ nil))
+	                (_ nil)))
 	          (looking-at org-property-drawer-re))
 	     (org-element-property-drawer-parser limit))
             ;; When not at bol, point is at the beginning of an item or
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -12342,19 +12342,29 @@ 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
-   (let ((beg (cond (beg (goto-char beg))
+   (let* ((beg (cond (beg (goto-char beg))
 		     ((or (not (featurep 'org-inlinetask))
 			  (org-inlinetask-in-task-p))
 		      (org-back-to-heading-or-point-min t) (point))
 		     (t (org-with-limited-levels
 			 (org-back-to-heading-or-point-min t))
-		       (point)))))
+		        (point))))
+          (end (save-excursion
+                 (outline-next-heading)
+                 (point))))
      ;; Move point to its position according to its positional rules.
      (cond ((org-before-first-heading-p)
 	    (while (and (org-at-comment-p) (bolp)) (forward-line)))
 	   (t (forward-line)
 	      (when (looking-at-p org-planning-line-re) (forward-line))))
-     (cond ((looking-at org-property-drawer-re)
+     (cond ((and (< (point) end)
+                 (if org-allow-properties-at-end
+                     (and (re-search-forward org-property-drawer-re
+                                             (save-excursion
+                                               (outline-next-heading)
+                                               (point)) t)
+                          (goto-char (match-beginning 0)))
+                   (looking-at org-property-drawer-re)))
             (forward-line)
             (cons (point) (progn (goto-char (match-end 0))
 			         (line-beginning-position))))
@@ -20600,7 +20610,8 @@ properties, clocking lines and logbook drawers."
   ;; Skip planning information.
   (when (looking-at-p org-planning-line-re) (forward-line))
   ;; Skip property drawer.
-  (when (looking-at org-property-drawer-re)
+  (when (and (not org-allow-properties-at-end)
+             (looking-at org-property-drawer-re))
     (goto-char (match-end 0))
     (forward-line))
   ;; When FULL is not nil, skip more.

[-- Attachment #3: Type: text/plain, Size: 150 bytes --]


--
John Wiegley                  GPG fingerprint = 4710 CF98 AF9B 327B B80F
http://newartisans.com                          60E1 46C4 BD1A 7AC1 4BA2

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

end of thread, other threads:[~2023-04-26  8:54 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-04-25 22:53 Allowing :PROPERTIES: drawer to appear at the end of entries John Wiegley
2023-04-26  6:50 ` Ihor Radchenko
2023-04-26  8:25   ` John Wiegley
2023-04-26  8:44     ` John Wiegley
2023-04-26  8:56     ` Ihor Radchenko

Code repositories for project(s) associated with this public 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).