* Concatenate properties @ 2022-05-05 22:37 Tyler Grinn 2022-05-05 22:56 ` John Kitchin 0 siblings, 1 reply; 19+ messages in thread From: Tyler Grinn @ 2022-05-05 22:37 UTC (permalink / raw) To: emacs-orgmode I'm exporting sub-trees as pdf files for some classes I'm taking: # -*- org-use-property-inheritance: t; -*- * Class A :PROPERTIES: :EXPORT_FILE_NAME: support/Class A :END: ** Assignment 1 :PROPERTIES: :EXPORT_FILE_NAME+: /assignment-1 :END: Some assignment for Class A ** Assignment 2 :PROPERTIES: :EXPORT_FILE_NAME+: /assignment-2 :END: Some other assignment for Class A * Class B :PROPERTIES :EXPORT_FILE_NAME: support/Class B :END: ** Assignment 1 :PROPERTIES: :EXPORT_FILE_NAME+: /assignment-1 :END: Some assignment for Class B ** Assignment 2 :PROPERTIES: :EXPORT_FILE_NAME+: /assignment-2 :END: Some other assignment for Class B And this works great, except there's always a space between 'support/Class A' and '/assignment-1.pdf'. Is there any way to concatenate the two properties rather than join them with spaces? Best, Tyler ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Concatenate properties 2022-05-05 22:37 Concatenate properties Tyler Grinn @ 2022-05-05 22:56 ` John Kitchin 2022-05-06 15:40 ` Tyler Grinn 0 siblings, 1 reply; 19+ messages in thread From: John Kitchin @ 2022-05-05 22:56 UTC (permalink / raw) To: Tyler Grinn; +Cc: org-mode-email [-- Attachment #1: Type: text/plain, Size: 1523 bytes --] I believe this is hard coded in org-entry-get-with-inheritance. The fastest option would be an override advice with your own function that replaces (and value " ") with (and value ""), and maybe the two other " " with "". John ----------------------------------- Professor John Kitchin (he/him/his) Doherty Hall A207F Department of Chemical Engineering Carnegie Mellon University Pittsburgh, PA 15213 412-268-7803 @johnkitchin http://kitchingroup.cheme.cmu.edu On Thu, May 5, 2022 at 6:38 PM Tyler Grinn <tylergrinn@gmail.com> wrote: > > I'm exporting sub-trees as pdf files for some classes I'm taking: > > # -*- org-use-property-inheritance: t; -*- > > * Class A > :PROPERTIES: > :EXPORT_FILE_NAME: support/Class A > :END: > ** Assignment 1 > :PROPERTIES: > :EXPORT_FILE_NAME+: /assignment-1 > :END: > Some assignment for Class A > ** Assignment 2 > :PROPERTIES: > :EXPORT_FILE_NAME+: /assignment-2 > :END: > Some other assignment for Class A > * Class B > :PROPERTIES > :EXPORT_FILE_NAME: support/Class B > :END: > ** Assignment 1 > :PROPERTIES: > :EXPORT_FILE_NAME+: /assignment-1 > :END: > Some assignment for Class B > ** Assignment 2 > :PROPERTIES: > :EXPORT_FILE_NAME+: /assignment-2 > :END: > Some other assignment for Class B > > And this works great, except there's always a space between > 'support/Class A' and '/assignment-1.pdf'. Is there any way to > concatenate the two properties rather than join them with spaces? > > Best, > > Tyler > > [-- Attachment #2: Type: text/html, Size: 2335 bytes --] ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Concatenate properties 2022-05-05 22:56 ` John Kitchin @ 2022-05-06 15:40 ` Tyler Grinn 2022-05-07 5:33 ` Ihor Radchenko 2022-05-07 13:20 ` John Kitchin 0 siblings, 2 replies; 19+ messages in thread From: Tyler Grinn @ 2022-05-06 15:40 UTC (permalink / raw) To: John Kitchin; +Cc: org-mode-email John Kitchin <jkitchin@andrew.cmu.edu> writes: > I believe this is hard coded in org-entry-get-with-inheritance. The > fastest option would be an override advice with your own function that > replaces (and value " ") with (and value ""), and maybe the two other > " " with "". > > John > > ----------------------------------- > Professor John Kitchin (he/him/his) > Doherty Hall A207F > Department of Chemical Engineering > Carnegie Mellon University > Pittsburgh, PA 15213 > 412-268-7803 > @johnkitchin > http://kitchingroup.cheme.cmu.edu > Thanks for the advice. I've added the caret symbol (:EXPORT_FILE_NAME^: assignment-1) to mean 'concatenate' as opposed to + for 'joining'. If this is something the community would want I will clean it up and send in a patch. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Concatenate properties 2022-05-06 15:40 ` Tyler Grinn @ 2022-05-07 5:33 ` Ihor Radchenko 2022-05-07 11:44 ` John Kitchin 2022-05-07 13:20 ` John Kitchin 1 sibling, 1 reply; 19+ messages in thread From: Ihor Radchenko @ 2022-05-07 5:33 UTC (permalink / raw) To: Tyler Grinn; +Cc: John Kitchin, org-mode-email Tyler Grinn <tylergrinn@gmail.com> writes: > Thanks for the advice. I've added the caret symbol (:EXPORT_FILE_NAME^: > assignment-1) to mean 'concatenate' as opposed to + for 'joining'. If > this is something the community would want I will clean it up and send > in a patch. Hmm. I am not sure if it going to be a straightforward patch. You may need to update org-element parser accordingly. Also, I do not like the idea of extending org syntax with :PROPERTY^:. It may be easier to introduce a variable similar to org-use-property-inheritance where the user can customise how to accumulate parent properties. Best, Ihor ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Concatenate properties 2022-05-07 5:33 ` Ihor Radchenko @ 2022-05-07 11:44 ` John Kitchin 2022-05-07 12:29 ` Tyler Grinn 0 siblings, 1 reply; 19+ messages in thread From: John Kitchin @ 2022-05-07 11:44 UTC (permalink / raw) To: Ihor Radchenko; +Cc: Tyler Grinn, org-mode-email [-- Attachment #1: Type: text/plain, Size: 1307 bytes --] I like the variable idea. I would make it a concatenation string for joining. That way “” would concatenate the way Tyler wants, “ “ would preserve current behavior, and “,” could lead to a comma separated list for example. Other things like “\n” might lead to a column, etc. On Sat, May 7, 2022 at 1:32 AM Ihor Radchenko <yantar92@gmail.com> wrote: > Tyler Grinn <tylergrinn@gmail.com> writes: > > > Thanks for the advice. I've added the caret symbol (:EXPORT_FILE_NAME^: > > assignment-1) to mean 'concatenate' as opposed to + for 'joining'. If > > this is something the community would want I will clean it up and send > > in a patch. > > Hmm. I am not sure if it going to be a straightforward patch. You may > need to update org-element parser accordingly. > > Also, I do not like the idea of extending org syntax with :PROPERTY^:. > It may be easier to introduce a variable similar to > org-use-property-inheritance where the user can customise how to > accumulate parent properties. > > Best, > Ihor > -- John ----------------------------------- Professor John Kitchin (he/him/his) Doherty Hall A207F Department of Chemical Engineering Carnegie Mellon University Pittsburgh, PA 15213 412-268-7803 @johnkitchin http://kitchingroup.cheme.cmu.edu [-- Attachment #2: Type: text/html, Size: 2005 bytes --] ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Concatenate properties 2022-05-07 11:44 ` John Kitchin @ 2022-05-07 12:29 ` Tyler Grinn 2022-05-08 12:21 ` Ihor Radchenko 0 siblings, 1 reply; 19+ messages in thread From: Tyler Grinn @ 2022-05-07 12:29 UTC (permalink / raw) To: John Kitchin; +Cc: Ihor Radchenko, org-mode-email John Kitchin <jkitchin@andrew.cmu.edu> writes: > I like the variable idea. I would make it a concatenation string for > joining. That way “” would concatenate the way Tyler wants, “ “ would > preserve current behavior, and “,” could lead to a comma separated > list for example. Other things like “\n” might lead to a column, etc. I'm not a huge fan of the variable idea because it would make it impossible to include both behaviors in a single file, whereas extending the syntax maintains any existing properties that used '+'. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Concatenate properties 2022-05-07 12:29 ` Tyler Grinn @ 2022-05-08 12:21 ` Ihor Radchenko 2022-05-08 14:14 ` Tyler Grinn 0 siblings, 1 reply; 19+ messages in thread From: Ihor Radchenko @ 2022-05-08 12:21 UTC (permalink / raw) To: Tyler Grinn; +Cc: John Kitchin, org-mode-email Tyler Grinn <tylergrinn@gmail.com> writes: > John Kitchin <jkitchin@andrew.cmu.edu> writes: > >> I like the variable idea. I would make it a concatenation string for >> joining. That way “” would concatenate the way Tyler wants, “ “ would >> preserve current behavior, and “,” could lead to a comma separated >> list for example. Other things like “\n” might lead to a column, etc. > > I'm not a huge fan of the variable idea because it would make it > impossible to include both behaviors in a single file, whereas extending > the syntax maintains any existing properties that used '+'. I think I need to elaborate what I meant by "similar to org-use-property-inheritance". org-use-property-inheritance docstring: >>> When nil, only the properties directly given in the current entry >>> count. When t, every property is inherited. The value may also be a >>> list of properties that should have inheritance, or a regular >>> expression matching properties that should be inherited. Similarly, concatenation of PROPERTY+ can be controlled on per-property basis. Best, Ihor ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Concatenate properties 2022-05-08 12:21 ` Ihor Radchenko @ 2022-05-08 14:14 ` Tyler Grinn 2022-05-08 14:47 ` Ihor Radchenko 0 siblings, 1 reply; 19+ messages in thread From: Tyler Grinn @ 2022-05-08 14:14 UTC (permalink / raw) To: Ihor Radchenko; +Cc: org-mode-email Ihor Radchenko <yantar92@gmail.com> writes: > Tyler Grinn <tylergrinn@gmail.com> writes: > >> John Kitchin <jkitchin@andrew.cmu.edu> writes: >> >>> I like the variable idea. I would make it a concatenation string for >>> joining. That way “” would concatenate the way Tyler wants, “ “ would >>> preserve current behavior, and “,” could lead to a comma separated >>> list for example. Other things like “\n” might lead to a column, etc. >> >> I'm not a huge fan of the variable idea because it would make it >> impossible to include both behaviors in a single file, whereas extending >> the syntax maintains any existing properties that used '+'. > > I think I need to elaborate what I meant by "similar to > org-use-property-inheritance". > > org-use-property-inheritance docstring: > >>>> When nil, only the properties directly given in the current entry >>>> count. When t, every property is inherited. The value may also be a >>>> list of properties that should have inheritance, or a regular >>>> expression matching properties that should be inherited. > > Similarly, concatenation of PROPERTY+ can be controlled on per-property > basis. > > Best, > Ihor Could you provide an example of what the value of that variable would be if, for instance, I wanted PROP_A and PROP_B to be joined with a single space and PROP_C and PROP_D to be concatenated? Or better yet, have the default be to join with a single space for any property and have only PROP_C and PROP_D concatenated? ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Concatenate properties 2022-05-08 14:14 ` Tyler Grinn @ 2022-05-08 14:47 ` Ihor Radchenko 2022-05-09 20:18 ` Tyler Grinn 0 siblings, 1 reply; 19+ messages in thread From: Ihor Radchenko @ 2022-05-08 14:47 UTC (permalink / raw) To: Tyler Grinn; +Cc: org-mode-email Tyler Grinn <tylergrinn@gmail.com> writes: > > Could you provide an example of what the value of that variable would be > if, for instance, I wanted PROP_A and PROP_B to be joined with a single > space and PROP_C and PROP_D to be concatenated? Or better yet, have the > default be to join with a single space for any property and have only > PROP_C and PROP_D concatenated? Say, '(("PROP_[CD]" . "")) or '(("PROP_[AB]" . "/") ("PROP_[CD]" . "") (".+" . "∿")) Best, Ihor ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Concatenate properties 2022-05-08 14:47 ` Ihor Radchenko @ 2022-05-09 20:18 ` Tyler Grinn 2022-05-11 11:51 ` Ihor Radchenko 0 siblings, 1 reply; 19+ messages in thread From: Tyler Grinn @ 2022-05-09 20:18 UTC (permalink / raw) To: Ihor Radchenko; +Cc: org-mode-email Ihor Radchenko <yantar92@gmail.com> writes: > Tyler Grinn <tylergrinn@gmail.com> writes: > >> >> Could you provide an example of what the value of that variable would be >> if, for instance, I wanted PROP_A and PROP_B to be joined with a single >> space and PROP_C and PROP_D to be concatenated? Or better yet, have the >> default be to join with a single space for any property and have only >> PROP_C and PROP_D concatenated? > > Say, > > '(("PROP_[CD]" . "")) > > or > > '(("PROP_[AB]" . "/") ("PROP_[CD]" . "") (".+" . "∿")) > > Best, > Ihor I'm not sure forcing regular expressions for all use cases is ideal. Is there a way to allow the option (I'm calling it org-property-separators) to allow either regular expressions or exact matches, like org-use-property-inheritance does? Other than that I'm mostly ready to send in my first patch. Should I attach it in this thread or start a new one? Best, Tyler ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Concatenate properties 2022-05-09 20:18 ` Tyler Grinn @ 2022-05-11 11:51 ` Ihor Radchenko 2022-05-11 17:47 ` [PATCH] " Tyler Grinn 0 siblings, 1 reply; 19+ messages in thread From: Ihor Radchenko @ 2022-05-11 11:51 UTC (permalink / raw) To: Tyler Grinn; +Cc: org-mode-email Tyler Grinn <tylergrinn@gmail.com> writes: > Ihor Radchenko <yantar92@gmail.com> writes: > >> Tyler Grinn <tylergrinn@gmail.com> writes: >> >>> >>> Could you provide an example of what the value of that variable would be >>> if, for instance, I wanted PROP_A and PROP_B to be joined with a single >>> space and PROP_C and PROP_D to be concatenated? Or better yet, have the >>> default be to join with a single space for any property and have only >>> PROP_C and PROP_D concatenated? >> >> Say, >> >> '(("PROP_[CD]" . "")) >> >> or >> >> '(("PROP_[AB]" . "/") ("PROP_[CD]" . "") (".+" . "∿")) >> >> Best, >> Ihor > > I'm not sure forcing regular expressions for all use cases is ideal. Is > there a way to allow the option (I'm calling it org-property-separators) > to allow either regular expressions or exact matches, like > org-use-property-inheritance does? It's up to you. I merely suggested that the new option should work similarly to org-use-property-inheritance. It will not be the exact match since we also need to provide the separator string. > Other than that I'm mostly ready to send in my first patch. Should I > attach it in this thread or start a new one? Keeping the patch within this thread will be more reasonable for future readers. Just remember to prefix the subject line with [PATCH]. Best, Ihor ^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH] Re: Concatenate properties 2022-05-11 11:51 ` Ihor Radchenko @ 2022-05-11 17:47 ` Tyler Grinn 2022-05-12 9:59 ` Ihor Radchenko 0 siblings, 1 reply; 19+ messages in thread From: Tyler Grinn @ 2022-05-11 17:47 UTC (permalink / raw) To: Ihor Radchenko; +Cc: org-mode-email [-- Attachment #1: Type: text/plain, Size: 1670 bytes --] Ihor Radchenko <yantar92@gmail.com> writes: > Tyler Grinn <tylergrinn@gmail.com> writes: > >> Ihor Radchenko <yantar92@gmail.com> writes: >> >>> Tyler Grinn <tylergrinn@gmail.com> writes: >>> >>>> >>>> Could you provide an example of what the value of that variable would be >>>> if, for instance, I wanted PROP_A and PROP_B to be joined with a single >>>> space and PROP_C and PROP_D to be concatenated? Or better yet, have the >>>> default be to join with a single space for any property and have only >>>> PROP_C and PROP_D concatenated? >>> >>> Say, >>> >>> '(("PROP_[CD]" . "")) >>> >>> or >>> >>> '(("PROP_[AB]" . "/") ("PROP_[CD]" . "") (".+" . "∿")) >>> >>> Best, >>> Ihor >> >> I'm not sure forcing regular expressions for all use cases is ideal. Is >> there a way to allow the option (I'm calling it org-property-separators) >> to allow either regular expressions or exact matches, like >> org-use-property-inheritance does? > > It's up to you. I merely suggested that the new option should work > similarly to org-use-property-inheritance. It will not be the exact > match since we also need to provide the separator string. > >> Other than that I'm mostly ready to send in my first patch. Should I >> attach it in this thread or start a new one? > > Keeping the patch within this thread will be more reasonable for future > readers. Just remember to prefix the subject line with [PATCH]. > > Best, > Ihor OK, what I have now is that if the car of an alist item is a list, exact matching will be done for each list item, but if it is a string, it will be matched as a regular expression. Best, Tyler [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: Add org-property-separators option --] [-- Type: text/x-patch, Size: 8332 bytes --] From c23b45dd5d0bc5a049b916a4b4003c6f55ce4b51 Mon Sep 17 00:00:00 2001 From: Tyler Grinn <tylergrinn@gmail.com> Date: Mon, 9 May 2022 15:52:58 -0400 Subject: [PATCH] lisp/org.el: Add org-property-separators option * lisp/org.el (org-property-separators, org-property-get-separator): Created. (org-entry-get, org-entry-get-with-inheritance): Use new org-property-get-separator function. * testing/lisp/test-org.el (test-org/entry-get): Added tests for combining properties with custom separators org-property-separators is a customization option that allows for properties to be combined using a separator other than the default (a single space). It is an alist with the car of each element being a list of property names or regular expression and the cdr being the separator string, like '((("EXPORT_FILE_NAME") . "/")). --- etc/ORG-NEWS | 21 ++++++++++++++++++++ lisp/org.el | 43 ++++++++++++++++++++++++++++++++-------- testing/lisp/test-org.el | 30 +++++++++++++++++++++++++++- 3 files changed, 85 insertions(+), 9 deletions(-) diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS index 27de6da62..0297a9d49 100644 --- a/etc/ORG-NEWS +++ b/etc/ORG-NEWS @@ -141,6 +141,27 @@ discouraged when working with Org files. ** New features +*** New customization option =org-property-separators= +A new alist variable to control how properties are combined. + +If a property is specified multiple times with a =+=, like +=:EXPORT_FILE_NAME+:=, the old behavior was to always combine them +with a single space. For the new variable, the car of each item in the +alist should be either a list of property names or a regular +expression, while the cdr should be the separator to use when +combining that property. + +The default value for the separator is a single space, if none of the +provided items in the alist match a given property. + +For example, in order to combine =EXPORT_FILE_NAME= properties with a +forward slash =/=, one can use + +#+begin_src emacs-lisp +(setq org-use-property-inheritance '("EXPORT_FILE_NAME") + org-property-separators '((("EXPORT_FILE_NAME") . "/"))) +#+end_src + *** New library =org-persist.el= implements variable persistence across Emacs sessions The library stores variable data in ~org-persist-directory~ (set to XDG diff --git a/lisp/org.el b/lisp/org.el index cab59b87c..a53505752 100644 --- a/lisp/org.el +++ b/lisp/org.el @@ -2850,6 +2850,30 @@ in this variable)." (member-ignore-case property org-use-property-inheritance)) (t (error "Invalid setting of `org-use-property-inheritance'")))) +(defcustom org-property-separators nil + "An alist to control how properties are combined. + +The car of each item should be either a list of property names or +a regular expression, while the cdr should be the separator to +use when combining that property. + +If an alist item cannot be found that matches a given property, a +single space will be used as the separator." + :group 'org-properties + :type '(alist :key-type string :value-type sexp)) + +(defun org-property-get-separator (property) + "Get the separator to use for combining PROPERTY." + (or + (catch 'separator + (dolist (spec org-property-separators) + (if (listp (car spec)) + (if (member property (car spec)) + (throw 'separator (cdr spec))) + (if (string-match-p (car spec) property) + (throw 'separator (cdr spec)))))) + " ")) + (defcustom org-columns-default-format "%25ITEM %TODO %3PRIORITY %TAGS" "The default column format, if no other format has been defined. This variable can be set on the per-file basis by inserting a line @@ -12355,7 +12379,9 @@ value higher up the hierarchy." (org-entry-get-with-inheritance property literal-nil)) (t (let* ((local (org--property-local-values property literal-nil)) - (value (and local (mapconcat #'identity (delq nil local) " ")))) + (value (and local (mapconcat #'identity + (delq nil local) + (org-property-get-separator property))))) (if literal-nil value (org-not-nil value))))))) (defun org-property-or-variable-value (var &optional inherit) @@ -12464,7 +12490,8 @@ However, if LITERAL-NIL is set, return the string value \"nil\" instead." (catch 'exit (let ((element (or element (and (org-element--cache-active-p) - (org-element-at-point nil 'cached))))) + (org-element-at-point nil 'cached)))) + (separator (org-property-get-separator property))) (if element (let ((element (org-element-lineage element '(headline org-data inlinetask) 'with-self))) (while t @@ -12472,8 +12499,8 @@ However, if LITERAL-NIL is set, return the string value \"nil\" instead." (v (if (listp v) v (list v)))) (when v (setq value - (concat (mapconcat #'identity (delq nil v) " ") - (and value " ") + (concat (mapconcat #'identity (delq nil v) separator) + (and value separator) value))) (cond ((car v) @@ -12484,15 +12511,15 @@ However, if LITERAL-NIL is set, return the string value \"nil\" instead." (t (let ((global (org--property-global-or-keyword-value property literal-nil))) (cond ((not global)) - (value (setq value (concat global " " value))) + (value (setq value (concat global separator value))) (t (setq value global)))) (throw 'exit nil)))))) (while t (let ((v (org--property-local-values property literal-nil))) (when v (setq value - (concat (mapconcat #'identity (delq nil v) " ") - (and value " ") + (concat (mapconcat #'identity (delq nil v) separator) + (and value separator) value))) (cond ((car v) @@ -12513,7 +12540,7 @@ However, if LITERAL-NIL is set, return the string value \"nil\" instead." (t (let ((global (org--property-global-or-keyword-value property literal-nil))) (cond ((not global)) - (value (setq value (concat global " " value))) + (value (setq value (concat global separator value))) (t (setq value global)))) (throw 'exit nil)))))))) (if literal-nil value (org-not-nil value))))) diff --git a/testing/lisp/test-org.el b/testing/lisp/test-org.el index 0cee31d4e..c0c13f586 100644 --- a/testing/lisp/test-org.el +++ b/testing/lisp/test-org.el @@ -5997,7 +5997,35 @@ Paragraph<point>" (org-test-with-temp-text ":PROPERTIES:\n:A: 0\n:END:\n#+PROPERTY: A 1\n* H\n:PROPERTIES:\n:A+: 2\n:END:" (org-mode-restart) - (org-entry-get (point-max) "A" t))))) + (org-entry-get (point-max) "A" t)))) + ;; Use alternate separators + (should + (equal "0~2" + (org-test-with-temp-text + ":PROPERTIES:\n:A: 0\n:A+: 2\n:END:" + (let ((org-property-separators '((("A") . "~")))) + (org-entry-get (point) "A"))))) + ;; Default separator is single space + (should + (equal "0 2" + (org-test-with-temp-text + ":PROPERTIES:\n:A: 0\n:B: 1\n:A+: 2\n:B+: 3\n:END:" + (let ((org-property-separators '((("B") . "~")))) + (org-entry-get (point) "A"))))) + ;; Regular expression matching for separator + (should + (equal "0/2" + (org-test-with-temp-text + ":PROPERTIES:\n:A: 0\n:A+: 2\n:END:" + (let ((org-property-separators '((("B") . "~") ("[AC]" . "/")))) + (org-entry-get (point) "A"))))) + ;; Separator works with inheritance + (should + (equal "1~2" + (org-test-with-temp-text + "* H\n:PROPERTIES:\n:A: 1\n:END:\n** H2\n:PROPERTIES:\n:A+: 2\n:END:" + (let ((org-property-separators '((("A") . "~")))) + (org-entry-get (point-max) "A" t)))))) (ert-deftest test-org/entry-properties () "Test `org-entry-properties' specifications." -- 2.35.3 ^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH] Re: Concatenate properties 2022-05-11 17:47 ` [PATCH] " Tyler Grinn @ 2022-05-12 9:59 ` Ihor Radchenko 2022-05-12 23:27 ` Tyler Grinn 0 siblings, 1 reply; 19+ messages in thread From: Ihor Radchenko @ 2022-05-12 9:59 UTC (permalink / raw) To: Tyler Grinn; +Cc: org-mode-email Tyler Grinn <tylergrinn@gmail.com> writes: > OK, what I have now is that if the car of an alist item is a list, exact > matching will be done for each list item, but if it is a string, it will > be matched as a regular expression. Sounds reasonable. Note that your patch is >15LOC long and you need to sign the copyright agreement with FSF in order to contribute. See https://orgmode.org/worg/org-contribute.html#copyright Some comments on the patch: > * lisp/org.el (org-property-separators, org-property-get-separator): > Created. I'd make the function private: org--property-get-separator. It is not intended as an API function. > (org-entry-get, org-entry-get-with-inheritance): Use new > org-property-get-separator function. > org-property-separators is a customization option that allows for Please quote the function name as `org-property-get-separator'. > +If a property is specified multiple times with a =+=, like > +=:EXPORT_FILE_NAME+:=, the old behavior was to always combine them > +with a single space. For the new variable, the car of each item in > the Please, use double space " " to separate sentences. Also, see doc/Documentation_Standards.org > +For example, in order to combine =EXPORT_FILE_NAME= properties with a > +forward slash =/=, one can use > + > +#+begin_src emacs-lisp > +(setq org-use-property-inheritance '("EXPORT_FILE_NAME") > + org-property-separators '((("EXPORT_FILE_NAME") . "/"))) > +#+end_src This example is a bit confusing because it is unclear what you want to achieve and why you also need to set inheritance. > +(defcustom org-property-separators nil > ... > + :group 'org-properties > + :type '(alist :key-type string :value-type sexp)) This defcustom type does not match what you described in the docstring. You need something like :type '(alist :key-type (choice string (repeat string)) :value-type string) Best, Ihor ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH] Re: Concatenate properties 2022-05-12 9:59 ` Ihor Radchenko @ 2022-05-12 23:27 ` Tyler Grinn 2022-05-13 12:21 ` Ihor Radchenko 0 siblings, 1 reply; 19+ messages in thread From: Tyler Grinn @ 2022-05-12 23:27 UTC (permalink / raw) To: Ihor Radchenko; +Cc: org-mode-email [-- Attachment #1: Type: text/plain, Size: 2419 bytes --] Ihor Radchenko <yantar92@gmail.com> writes: > Note that your patch is >15LOC long and you need to sign the copyright > agreement with FSF in order to contribute. See > https://orgmode.org/worg/org-contribute.html#copyright I've already submitted a copyright assignment to the FSF in order to publish on ELPA. Do I need one specific to org-mode? > Some comments on the patch: > >> * lisp/org.el (org-property-separators, org-property-get-separator): >> Created. > > I'd make the function private: org--property-get-separator. It is not > intended as an API function. I agree, that was an oversight. > >> (org-entry-get, org-entry-get-with-inheritance): Use new >> org-property-get-separator function. > >> org-property-separators is a customization option that allows for > > Please quote the function name as `org-property-get-separator'. > No problem. >> +If a property is specified multiple times with a =+=, like >> +=:EXPORT_FILE_NAME+:=, the old behavior was to always combine them >> +with a single space. For the new variable, the car of each item in >> the > > Please, use double space " " to separate sentences. Also, see > doc/Documentation_Standards.org No problem. > >> +For example, in order to combine =EXPORT_FILE_NAME= properties with a >> +forward slash =/=, one can use >> + >> +#+begin_src emacs-lisp >> +(setq org-use-property-inheritance '("EXPORT_FILE_NAME") >> + org-property-separators '((("EXPORT_FILE_NAME") . "/"))) >> +#+end_src > > This example is a bit confusing because it is unclear what you want to > achieve and why you also need to set inheritance. Inheritance is the most likely scenario one would need to use the '+' property syntax, but I do agree it's kinda distracting and not absolutely necessary in order to get the correct behavior. > >> +(defcustom org-property-separators nil >> ... >> + :group 'org-properties >> + :type '(alist :key-type string :value-type sexp)) > > This defcustom type does not match what you described in the docstring. > You need something like :type '(alist :key-type (choice string (repeat string)) :value-type string) > > Best, > Ihor Setting ':value-type string' is confusing, in my opinion, because the default single space looks like: in the customization buffer, which is indistinguishable from no space: . I just found out about the restricted-sexp type, which I think makes the customization buffer more user-friendly. [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: Add org-property-separators option --] [-- Type: text/x-patch, Size: 8763 bytes --] From f474cb25840fdc6b24618b1452cb7fdd32545092 Mon Sep 17 00:00:00 2001 From: Tyler Grinn <tylergrinn@gmail.com> Date: Mon, 9 May 2022 15:52:58 -0400 Subject: [PATCH] lisp/org.el: Add org-property-separators option * lisp/org.el (org-property-separators, org-property-get-separator): Created. (org-entry-get, org-entry-get-with-inheritance): Use new `org-property-get-separator' function. * testing/lisp/test-org.el (test-org/entry-get): Added tests for combining properties with custom separators `org-property-separators' is a customization option that allows for properties to be combined using a separator other than the default (a single space). It is an alist with the car of each element being a list of property names or regular expression and the cdr being the separator string, like '((("EXPORT_FILE_NAME") . "/")). --- etc/ORG-NEWS | 31 ++++++++++++++++++++++++++ lisp/org.el | 47 +++++++++++++++++++++++++++++++++------- testing/lisp/test-org.el | 30 ++++++++++++++++++++++++- 3 files changed, 99 insertions(+), 9 deletions(-) diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS index 27de6da62..9d1d2cdcf 100644 --- a/etc/ORG-NEWS +++ b/etc/ORG-NEWS @@ -141,6 +141,37 @@ discouraged when working with Org files. ** New features +*** New customization option =org-property-separators= +A new alist variable to control how properties are combined. + +If a property is specified multiple times with a =+=, like + +#+begin_src org +:PROPERTIES: +:EXPORT_FILE_NAME: some/path +:EXPORT_FILE_NAME+: to/file +:END: +#+end_src + +the old behavior was to always combine them with a single space +(=some/path to/file=). For the new variable, the car of each item in +the alist should be either a list of property names or a regular +expression, while the cdr should be the separator to use when +combining that property. + +The default value for the separator is a single space, if none of the +provided items in the alist match a given property. + +For example, in order to combine =EXPORT_FILE_NAME= properties with a +forward slash =/=, one can use + +#+begin_src emacs-lisp +(setq org-property-separators '((("EXPORT_FILE_NAME") . "/"))) +#+end_src + +The example above would then produce the property value +=some/path/to/file=. + *** New library =org-persist.el= implements variable persistence across Emacs sessions The library stores variable data in ~org-persist-directory~ (set to XDG diff --git a/lisp/org.el b/lisp/org.el index cab59b87c..643fd6b73 100644 --- a/lisp/org.el +++ b/lisp/org.el @@ -2850,6 +2850,34 @@ in this variable)." (member-ignore-case property org-use-property-inheritance)) (t (error "Invalid setting of `org-use-property-inheritance'")))) +(defcustom org-property-separators nil + "An alist to control how properties are combined. + +The car of each item should be either a list of property names or +a regular expression, while the cdr should be the separator to +use when combining that property. + +If an alist item cannot be found that matches a given property, a +single space will be used as the separator." + :group 'org-properties + :type '(alist :key-type (choice (repeat :tag "Properties" string) + (string :tag "Regular Expression")) + :value-type (restricted-sexp :tag "Separator" + :match-alternatives (stringp) + :value " "))) + +(defun org--property-get-separator (property) + "Get the separator to use for combining PROPERTY." + (or + (catch 'separator + (dolist (spec org-property-separators) + (if (listp (car spec)) + (if (member property (car spec)) + (throw 'separator (cdr spec))) + (if (string-match-p (car spec) property) + (throw 'separator (cdr spec)))))) + " ")) + (defcustom org-columns-default-format "%25ITEM %TODO %3PRIORITY %TAGS" "The default column format, if no other format has been defined. This variable can be set on the per-file basis by inserting a line @@ -12355,7 +12383,9 @@ value higher up the hierarchy." (org-entry-get-with-inheritance property literal-nil)) (t (let* ((local (org--property-local-values property literal-nil)) - (value (and local (mapconcat #'identity (delq nil local) " ")))) + (value (and local (mapconcat #'identity + (delq nil local) + (org--property-get-separator property))))) (if literal-nil value (org-not-nil value))))))) (defun org-property-or-variable-value (var &optional inherit) @@ -12464,7 +12494,8 @@ However, if LITERAL-NIL is set, return the string value \"nil\" instead." (catch 'exit (let ((element (or element (and (org-element--cache-active-p) - (org-element-at-point nil 'cached))))) + (org-element-at-point nil 'cached)))) + (separator (org--property-get-separator property))) (if element (let ((element (org-element-lineage element '(headline org-data inlinetask) 'with-self))) (while t @@ -12472,8 +12503,8 @@ However, if LITERAL-NIL is set, return the string value \"nil\" instead." (v (if (listp v) v (list v)))) (when v (setq value - (concat (mapconcat #'identity (delq nil v) " ") - (and value " ") + (concat (mapconcat #'identity (delq nil v) separator) + (and value separator) value))) (cond ((car v) @@ -12484,15 +12515,15 @@ However, if LITERAL-NIL is set, return the string value \"nil\" instead." (t (let ((global (org--property-global-or-keyword-value property literal-nil))) (cond ((not global)) - (value (setq value (concat global " " value))) + (value (setq value (concat global separator value))) (t (setq value global)))) (throw 'exit nil)))))) (while t (let ((v (org--property-local-values property literal-nil))) (when v (setq value - (concat (mapconcat #'identity (delq nil v) " ") - (and value " ") + (concat (mapconcat #'identity (delq nil v) separator) + (and value separator) value))) (cond ((car v) @@ -12513,7 +12544,7 @@ However, if LITERAL-NIL is set, return the string value \"nil\" instead." (t (let ((global (org--property-global-or-keyword-value property literal-nil))) (cond ((not global)) - (value (setq value (concat global " " value))) + (value (setq value (concat global separator value))) (t (setq value global)))) (throw 'exit nil)))))))) (if literal-nil value (org-not-nil value))))) diff --git a/testing/lisp/test-org.el b/testing/lisp/test-org.el index 0cee31d4e..c0c13f586 100644 --- a/testing/lisp/test-org.el +++ b/testing/lisp/test-org.el @@ -5997,7 +5997,35 @@ Paragraph<point>" (org-test-with-temp-text ":PROPERTIES:\n:A: 0\n:END:\n#+PROPERTY: A 1\n* H\n:PROPERTIES:\n:A+: 2\n:END:" (org-mode-restart) - (org-entry-get (point-max) "A" t))))) + (org-entry-get (point-max) "A" t)))) + ;; Use alternate separators + (should + (equal "0~2" + (org-test-with-temp-text + ":PROPERTIES:\n:A: 0\n:A+: 2\n:END:" + (let ((org-property-separators '((("A") . "~")))) + (org-entry-get (point) "A"))))) + ;; Default separator is single space + (should + (equal "0 2" + (org-test-with-temp-text + ":PROPERTIES:\n:A: 0\n:B: 1\n:A+: 2\n:B+: 3\n:END:" + (let ((org-property-separators '((("B") . "~")))) + (org-entry-get (point) "A"))))) + ;; Regular expression matching for separator + (should + (equal "0/2" + (org-test-with-temp-text + ":PROPERTIES:\n:A: 0\n:A+: 2\n:END:" + (let ((org-property-separators '((("B") . "~") ("[AC]" . "/")))) + (org-entry-get (point) "A"))))) + ;; Separator works with inheritance + (should + (equal "1~2" + (org-test-with-temp-text + "* H\n:PROPERTIES:\n:A: 1\n:END:\n** H2\n:PROPERTIES:\n:A+: 2\n:END:" + (let ((org-property-separators '((("A") . "~")))) + (org-entry-get (point-max) "A" t)))))) (ert-deftest test-org/entry-properties () "Test `org-entry-properties' specifications." -- 2.35.3 ^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH] Re: Concatenate properties 2022-05-12 23:27 ` Tyler Grinn @ 2022-05-13 12:21 ` Ihor Radchenko 2022-05-14 2:11 ` Tyler Grinn 2022-05-20 8:04 ` Ihor Radchenko 0 siblings, 2 replies; 19+ messages in thread From: Ihor Radchenko @ 2022-05-13 12:21 UTC (permalink / raw) To: Tyler Grinn; +Cc: org-mode-email Tyler Grinn <tylergrinn@gmail.com> writes: > Ihor Radchenko <yantar92@gmail.com> writes: > >> Note that your patch is >15LOC long and you need to sign the copyright >> agreement with FSF in order to contribute. See >> https://orgmode.org/worg/org-contribute.html#copyright > > I've already submitted a copyright assignment to the FSF in order to > publish on ELPA. Do I need one specific to org-mode? Nope. The ELPA one is good enough. Basically, Org has the same requirement as Emacs (Org is a part of Emacs). >>> +(defcustom org-property-separators nil >>> ... >>> + :group 'org-properties >>> + :type '(alist :key-type string :value-type sexp)) >> >> This defcustom type does not match what you described in the docstring. >> You need something like :type '(alist :key-type (choice string (repeat string)) :value-type string) > > Setting ':value-type string' is confusing, in my opinion, because the > default single space looks like: in the customization buffer, which is > indistinguishable from no space: . I just found out about the restricted-sexp > type, which I think makes the customization buffer more user-friendly. restricted-sexp is fine. Though you could also do something like (choice (const :tag "Single space" " ") (string :tag "Other string")) > From f474cb25840fdc6b24618b1452cb7fdd32545092 Mon Sep 17 00:00:00 2001 > From: Tyler Grinn <tylergrinn@gmail.com> > Date: Mon, 9 May 2022 15:52:58 -0400 > Subject: [PATCH] lisp/org.el: Add org-property-separators option LGTM! I will leave this for another week to give other people a chance to comment. For reference, this patch might be useful in https://orgmode.org/list/87o821dv7o.fsf@localhost Best, Ihor ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH] Re: Concatenate properties 2022-05-13 12:21 ` Ihor Radchenko @ 2022-05-14 2:11 ` Tyler Grinn 2022-05-20 8:04 ` Ihor Radchenko 1 sibling, 0 replies; 19+ messages in thread From: Tyler Grinn @ 2022-05-14 2:11 UTC (permalink / raw) To: Ihor Radchenko; +Cc: org-mode-email Ihor Radchenko <yantar92@gmail.com> writes: >> From f474cb25840fdc6b24618b1452cb7fdd32545092 Mon Sep 17 00:00:00 2001 >> From: Tyler Grinn <tylergrinn@gmail.com> >> Date: Mon, 9 May 2022 15:52:58 -0400 >> Subject: [PATCH] lisp/org.el: Add org-property-separators option > > LGTM! > > I will leave this for another week to give other people a chance to > comment. > > For reference, this patch might be useful in https://orgmode.org/list/87o821dv7o.fsf@localhost > > Best, > Ihor Great; it's exciting to have my first patch accepted and I look forward to future development. Best, Tyler ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH] Re: Concatenate properties 2022-05-13 12:21 ` Ihor Radchenko 2022-05-14 2:11 ` Tyler Grinn @ 2022-05-20 8:04 ` Ihor Radchenko 1 sibling, 0 replies; 19+ messages in thread From: Ihor Radchenko @ 2022-05-20 8:04 UTC (permalink / raw) To: Tyler Grinn; +Cc: org-mode-email Ihor Radchenko <yantar92@gmail.com> writes: > I will leave this for another week to give other people a chance to > comment. Applied upstream onto main via e268e4797. Best, Ihor ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Concatenate properties 2022-05-06 15:40 ` Tyler Grinn 2022-05-07 5:33 ` Ihor Radchenko @ 2022-05-07 13:20 ` John Kitchin 2022-05-07 14:09 ` Tyler Grinn 1 sibling, 1 reply; 19+ messages in thread From: John Kitchin @ 2022-05-07 13:20 UTC (permalink / raw) To: Tyler Grinn; +Cc: org-mode-email [-- Attachment #1: Type: text/plain, Size: 1161 bytes --] Where did you add that? John ----------------------------------- Professor John Kitchin (he/him/his) Doherty Hall A207F Department of Chemical Engineering Carnegie Mellon University Pittsburgh, PA 15213 412-268-7803 @johnkitchin http://kitchingroup.cheme.cmu.edu On Fri, May 6, 2022 at 11:40 AM Tyler Grinn <tylergrinn@gmail.com> wrote: > John Kitchin <jkitchin@andrew.cmu.edu> writes: > > > I believe this is hard coded in org-entry-get-with-inheritance. The > > fastest option would be an override advice with your own function that > > replaces (and value " ") with (and value ""), and maybe the two other > > " " with "". > > > > John > > > > ----------------------------------- > > Professor John Kitchin (he/him/his) > > Doherty Hall A207F > > Department of Chemical Engineering > > Carnegie Mellon University > > Pittsburgh, PA 15213 > > 412-268-7803 > > @johnkitchin > > http://kitchingroup.cheme.cmu.edu > > > > Thanks for the advice. I've added the caret symbol (:EXPORT_FILE_NAME^: > assignment-1) to mean 'concatenate' as opposed to + for 'joining'. If > this is something the community would want I will clean it up and send > in a patch. > [-- Attachment #2: Type: text/html, Size: 2064 bytes --] ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Concatenate properties 2022-05-07 13:20 ` John Kitchin @ 2022-05-07 14:09 ` Tyler Grinn 0 siblings, 0 replies; 19+ messages in thread From: Tyler Grinn @ 2022-05-07 14:09 UTC (permalink / raw) To: John Kitchin; +Cc: org-mode-email John Kitchin <jkitchin@andrew.cmu.edu> writes: > Where did you add that? > > John > > ----------------------------------- > Professor John Kitchin (he/him/his) > Doherty Hall A207F > Department of Chemical Engineering > Carnegie Mellon University > Pittsburgh, PA 15213 > 412-268-7803 > @johnkitchin > http://kitchingroup.cheme.cmu.edu > > On Fri, May 6, 2022 at 11:40 AM Tyler Grinn <tylergrinn@gmail.com> > wrote: > > Thanks for the advice. I've added the caret symbol > (:EXPORT_FILE_NAME^: > assignment-1) to mean 'concatenate' as opposed to + for 'joining'. > If > this is something the community would want I will clean it up and > send > in a patch. I modified 'org--property-local-values' to return a cons list with the car being the value of the property and the cdr being either 'concat or 'join. ;; Find additional values. (let* ((property-extension (org-re-property (concat (regexp-quote property) "[+^]") t t))) (while (re-search-forward property-extension end t) (push (cons (match-string-no-properties 3) (if (string-match-p "\\^\\'" (match-string-no-properties 2)) 'concat 'join)) value))) I used a single re-search in order to maintain the ordering of properties, ie: :PROP: he :PROP^: llo :PROP+: world produces 'hello world' I then updated both 'org-entry-get' and 'org-entry-get-with-inheritance' to 'cl-reduce' the cons list into the final string value. ^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2022-05-20 8:07 UTC | newest] Thread overview: 19+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2022-05-05 22:37 Concatenate properties Tyler Grinn 2022-05-05 22:56 ` John Kitchin 2022-05-06 15:40 ` Tyler Grinn 2022-05-07 5:33 ` Ihor Radchenko 2022-05-07 11:44 ` John Kitchin 2022-05-07 12:29 ` Tyler Grinn 2022-05-08 12:21 ` Ihor Radchenko 2022-05-08 14:14 ` Tyler Grinn 2022-05-08 14:47 ` Ihor Radchenko 2022-05-09 20:18 ` Tyler Grinn 2022-05-11 11:51 ` Ihor Radchenko 2022-05-11 17:47 ` [PATCH] " Tyler Grinn 2022-05-12 9:59 ` Ihor Radchenko 2022-05-12 23:27 ` Tyler Grinn 2022-05-13 12:21 ` Ihor Radchenko 2022-05-14 2:11 ` Tyler Grinn 2022-05-20 8:04 ` Ihor Radchenko 2022-05-07 13:20 ` John Kitchin 2022-05-07 14:09 ` Tyler Grinn
Code repositories for project(s) associated with this external index https://git.savannah.gnu.org/cgit/emacs.git https://git.savannah.gnu.org/cgit/emacs/org-mode.git This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.