From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp12.migadu.com ([2001:41d0:8:6d80::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms9.migadu.com with LMTPS id HhIDHhhaSGRHWAAASxT56A (envelope-from ) for ; Wed, 26 Apr 2023 00:54:16 +0200 Received: from aspmx1.migadu.com ([2001:41d0:8:6d80::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp12.migadu.com with LMTPS id +LwKHRhaSGTHDwEAauVa8A (envelope-from ) for ; Wed, 26 Apr 2023 00:54:16 +0200 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id 0BAD33822F for ; Wed, 26 Apr 2023 00:54:16 +0200 (CEST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1prRXA-0005iC-Pk; Tue, 25 Apr 2023 18:53:16 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1prRX8-0005i0-SD for emacs-orgmode@gnu.org; Tue, 25 Apr 2023 18:53:15 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1prRX8-000526-5M for emacs-orgmode@gnu.org; Tue, 25 Apr 2023 18:53:14 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:Date:Subject:To:From:in-reply-to: references; bh=ddMjfCI8L4/KxZIT6ceEJeI+y7bQGcLcbXX6nWhTbOE=; b=dUBGptjinZ0lns 5lH0b0PATvfjJJkQpQ/sWWeywRVSFRIX7TlO12b95IGH5ncxvVa2oBoxcNJUgW1cEYSsiyWznYHJ2 5pSkiUZF6G1E/rf5V/FdzdZHnzzKJNORt2FolqNS0CQQHPNv0Nn+C3z8h4L86SWTiuAYqhyeSADcu VhVVgB4XjZ075nSAcJVweJIVdgoNXpBf216VFl25DH22cHQkz/ztLpfenChlYex9Sy5RCuRZLe1m8 7j31AhJVuV6zJo8CbGth4u1kI0p4zQo6MNFvGdff43cp5msnZPE8ifquu/8n8bmVOyDMwMrVHKJZD QXCMeT++r+JVCN/zhJCw==; Received: from auth2-smtp.messagingengine.com ([66.111.4.228]) by fencepost.gnu.org with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1prRX7-0005mN-EQ for emacs-orgmode@gnu.org; Tue, 25 Apr 2023 18:53:13 -0400 Received: from compute2.internal (compute2.nyi.internal [10.202.2.46]) by mailauth.nyi.internal (Postfix) with ESMTP id E7D9527C005B for ; Tue, 25 Apr 2023 18:53:11 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute2.internal (MEProxy); Tue, 25 Apr 2023 18:53:11 -0400 X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvhedrfedufedgudehucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkfgggtgesmhdtreertd ertdenucfhrhhomhepfdflohhhnhcuhghivghglhgvhidfuceojhhohhhnfiesghhnuhdr ohhrgheqnecuggftrfgrthhtvghrnhepleelvddufeefleejtefgffdtgefffedttdegud fhhfeihefggeehieekgfetvedunecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghm pehmrghilhhfrhhomhepjhhohhhnfidomhgvshhmthhprghuthhhphgvrhhsohhnrghlih hthidqieekjeektdelgeegqddujeejheefkeduiedqjhhohhhnfieppehgnhhurdhorhhg sehnvgifrghrthhishgrnhhsrdgtohhm X-ME-Proxy: Feedback-ID: ib64945b7:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA for ; Tue, 25 Apr 2023 18:53:11 -0400 (EDT) From: "John Wiegley" To: emacs-orgmode@gnu.org Subject: Allowing :PROPERTIES: drawer to appear at the end of entries Date: Tue, 25 Apr 2023 15:53:08 -0700 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.2 (darwin) Mail-Followup-To: emacs-orgmode@gnu.org MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-BeenThere: emacs-orgmode@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-orgmode-bounces+larch=yhetil.org@gnu.org Sender: emacs-orgmode-bounces+larch=yhetil.org@gnu.org X-Migadu-Country: US X-Migadu-Flow: FLOW_IN ARC-Seal: i=1; s=key1; d=yhetil.org; t=1682463256; a=rsa-sha256; cv=none; b=m5fyxax4m41DSIDCmZQdGSYLIPuTqyyLlBfIp6j1JWPKCfcFihU24FYODipih1UgLIIyPX kcTFgDCi6uJZPD6puOAngQfp9dV1wXTGLU6mQPLsC33qmjDfl0lwi8/LdoyT97k0+VKDTp S6esEYpWlwqoVt+unQWJKwJAZ1yTg8uOx4XH7xFlD3xRd6pOWbl/qwhBsYHwQlqJ3zPMP1 dymlkX0113LK4ejZ9yh8lRTpwDIphko3ZCvX5BixDWargvQMbnmFjPC9RcSbJ5BbC0+CTY Y52MEZOqzQyafif1TQrAonFx5mNcbCbSMLLZzA+vyeokAj260+Jn2Q/usQenjQ== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=pass header.d=gnu.org header.s=fencepost-gnu-org header.b=dUBGptji; dmarc=pass (policy=none) header.from=gnu.org; spf=pass (aspmx1.migadu.com: domain of "emacs-orgmode-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="emacs-orgmode-bounces+larch=yhetil.org@gnu.org" ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1682463256; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type:list-id:list-help:list-unsubscribe: list-subscribe:list-post:dkim-signature; bh=ddMjfCI8L4/KxZIT6ceEJeI+y7bQGcLcbXX6nWhTbOE=; b=iWuYl/TN2VnstEzVFMt1JXnhnyYllJDlPseEYK8rbje9U/JAT64GuWPwMZYixs026LcL+Z xmOvV5WnPsWNBjjCwLyWobeBVUGDXzi3f/WWKdiEysQ1xdKx8bcgYv/Ccm+/0WNHfwk/+T wAGVt+ZzWTp89l9AetFR8HviBOtoCHl0gMbvAEDn58rWujcFtpkd4/ofgOoyFLGwhPW1X+ RbEBnOb/nz1Ga+pFh8aUyOQOHbHRCc2Thijc9lHgK7lqwByGmxxQbrkF/aAffsikW5mLJM A4wtIgmNIXjSIB0AvPxq6ijhfr11xkxESoPBjKtvsTO9t+A0wRxRkvCF0/KxmQ== X-Migadu-Spam-Score: -9.41 X-Spam-Score: -9.41 X-Migadu-Queue-Id: 0BAD33822F X-Migadu-Scanner: scn0.migadu.com Authentication-Results: aspmx1.migadu.com; dkim=pass header.d=gnu.org header.s=fencepost-gnu-org header.b=dUBGptji; dmarc=pass (policy=none) header.from=gnu.org; spf=pass (aspmx1.migadu.com: domain of "emacs-orgmode-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="emacs-orgmode-bounces+larch=yhetil.org@gnu.org" X-TUID: mbTEKxOcHl4c --=-=-= Content-Type: text/plain 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... --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=properties-at-end.patch --- 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. --=-=-= Content-Type: text/plain -- John Wiegley GPG fingerprint = 4710 CF98 AF9B 327B B80F http://newartisans.com 60E1 46C4 BD1A 7AC1 4BA2 --=-=-=--