emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/org e268e47971: lisp/org.el: Add org-property-separator


From: ELPA Syncer
Subject: [elpa] externals/org e268e47971: lisp/org.el: Add org-property-separators option
Date: Fri, 20 May 2022 04:58:00 -0400 (EDT)

branch: externals/org
commit e268e479718e04f590324a29036f081a3f80f208
Author: Tyler Grinn <tylergrinn@gmail.com>
Commit: Ihor Radchenko <yantar92@gmail.com>

    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 5828165340..35af94f928 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 dc0b215165..d7da8efc46 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
@@ -12358,7 +12386,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)
@@ -12467,7 +12497,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
@@ -12475,8 +12506,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)
@@ -12487,15 +12518,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)
@@ -12516,7 +12547,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 473933a6b4..5f13e89a48 100644
--- a/testing/lisp/test-org.el
+++ b/testing/lisp/test-org.el
@@ -6014,7 +6014,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."



reply via email to

[Prev in Thread] Current Thread [Next in Thread]