Improve handling of org attach id to path functions

* doc/org-manual.org (Attachment options)
* etc/ORG-NEWS (Org-Attach has been refactored and extended)
(New ID method based on timestamp)
* lisp/org-attach.el (org-attach-id-uuid-folder-format)
(org-attach-id-ts-folder-format)
(org-attach-id-to-path-function-list, org-attach-dir)
(org-attach-dir-from-id): Better handling of id to path
functionality. At the same time adding an id-to-path function
for timestamp-based ID that easily can be promoted to the
primary function by customization of the user.
This commit is contained in:
Gustav Wikström 2019-10-20 02:49:48 +02:00
parent aa8500505f
commit 42b8db0d34
3 changed files with 59 additions and 23 deletions

View File

@ -8004,15 +8004,15 @@ mentioning.
When attaching files to a heading it will be assigned a tag When attaching files to a heading it will be assigned a tag
according to what is set here. according to what is set here.
- ~org-attach-id-to-path-function~ :: - ~org-attach-id-to-path-function-list~ ::
#+vindex: org-attach-id-to-path-function #+vindex: org-attach-id-to-path-function-list
When =ID= is used for attachments, the ID is parsed into a part of a When =ID= is used for attachments, the ID is parsed into a part of a
directory-path. See ~org-attach-id-folder-format~ for the default directory-path. See ~org-attach-id-uuid-folder-format~ for the
function. Define a new one and add it to default function. Define a new one and add it as first element in
~org-attach-id-to-path-function~ if you want the folder structure ~org-attach-id-to-path-function-list~ if you want the folder
any other way. Note that modifying this makes org-attach dependent structure in any other way. All functions in this list will be
on your function also for opening attachments, not only setting tried when resolving existing ID's into paths, to maintain backward
them! compatability with existing folders in your system.
- ~org-attach-expert~ :: - ~org-attach-expert~ ::
#+vindex: org-attach-expert #+vindex: org-attach-expert

View File

@ -178,8 +178,9 @@ precedence and will be used.
One can now also choose to build attachment-directory-paths in a One can now also choose to build attachment-directory-paths in a
customized way. This is an advanced topic, but in some case it makes customized way. This is an advanced topic, but in some case it makes
sense to parse an ID in a different way than the default one. Create sense to parse an ID in a different way than the default one. Create
your own function and use it is ~org-attach-id-to-path-function~ if your own function and add it to the beginning of
you want to customize the ID-based folder structure. ~org-attach-id-to-path-function~list~ if you want to customize the ID
based folder structure.
If you've used ATTACH_DIR properties to manage attachments, use the If you've used ATTACH_DIR properties to manage attachments, use the
following code to rename that property to DIR which supports the same following code to rename that property to DIR which supports the same
@ -411,6 +412,11 @@ the attachment dispatcher.
If one chooses, it is now possible to create ID's based on timestamp If one chooses, it is now possible to create ID's based on timestamp
(ISO8601) instead of UUID by changing org-id-method to ts. (ISO8601) instead of UUID by changing org-id-method to ts.
For an improved folder structure when using timestamp as ID, make sure
to promote ~org-attach-id-ts-folder-format~ to the first element of
~org-attach-id-to-path-function-list~ in your configuration at the
same time.
*** New customization: ~org-id-locations-relative~ *** New customization: ~org-id-locations-relative~
New customization to make the persisting of org-id-locations between New customization to make the persisting of org-id-locations between
sessions to store links to files as relative instead of absolute. The sessions to store links to files as relative instead of absolute. The

View File

@ -152,19 +152,33 @@ When set to `query', ask the user instead."
(const :tag "Always delete attachments" t) (const :tag "Always delete attachments" t)
(const :tag "Query the user" query))) (const :tag "Query the user" query)))
(defun org-attach-id-folder-format (id) (defun org-attach-id-uuid-folder-format (id)
"Translate an ID into a folder-path. "Translate an UUID ID into a folder-path.
Default format for how Org translates ID properties to a path for Default format for how Org translates ID properties to a path for
attachments." attachments. Useful if ID is generated with UUID."
(format "%s/%s" (format "%s/%s"
(substring id 0 2) (substring id 0 2)
(substring id 2))) (substring id 2)))
(defcustom org-attach-id-to-path-function #'org-attach-id-folder-format (defun org-attach-id-ts-folder-format (id)
"Function parsing the ID parameter into a folder-path." "Translate an ID based on a timestamp to a folder-path.
Useful way of translation if ID is generated based on ISO8601
timestamp. Splits the attachment folder hierarchy into
year-month, the rest."
(format "%s/%s"
(substring id 0 6)
(substring id 6)))
(defcustom org-attach-id-to-path-function-list '(org-attach-id-uuid-folder-format
org-attach-id-ts-folder-format)
"List of functions parsing an ID string into a folder-path.
The first function in this list defines the preferred function
which will be used when creating new attachment folders. All
functions of this list will be tried when looking for existing
attachment folders based on ID."
:group 'org-attach :group 'org-attach
:package-version '(Org . "9.3") :package-version '(Org . "9.3")
:type 'function) :type '(repeat (function :tag "Function with ID as input")))
(defvar org-attach-after-change-hook nil (defvar org-attach-after-change-hook nil
"Hook to be called when files have been added or removed to the attachment folder.") "Hook to be called when files have been added or removed to the attachment folder.")
@ -301,7 +315,7 @@ is run. If NO-FS-CHECK is non-nil, the function returns the path
to the attachment even if it has not yet been initialized in the to the attachment even if it has not yet been initialized in the
filesystem. filesystem.
If no attachment directory exist, return nil." If no attachment directory can be derived, return nil."
(let (attach-dir id) (let (attach-dir id)
(cond (cond
(create-if-not-exists-p (create-if-not-exists-p
@ -314,7 +328,7 @@ If no attachment directory exist, return nil."
(org-attach-check-absolute-path attach-dir)) (org-attach-check-absolute-path attach-dir))
((setq id (org-entry-get nil "ID" org-attach-use-inheritance)) ((setq id (org-entry-get nil "ID" org-attach-use-inheritance))
(org-attach-check-absolute-path nil) (org-attach-check-absolute-path nil)
(setq attach-dir (org-attach-dir-from-id id)))) (setq attach-dir (org-attach-dir-from-id id 'try-all))))
(if no-fs-check (if no-fs-check
attach-dir attach-dir
(when (and attach-dir (file-directory-p attach-dir)) (when (and attach-dir (file-directory-p attach-dir))
@ -346,11 +360,27 @@ If the attachment by some reason cannot be created an error will be raised."
(make-directory attach-dir t)) (make-directory attach-dir t))
attach-dir)) attach-dir))
(defun org-attach-dir-from-id (id) (defun org-attach-dir-from-id (id &optional try-all)
"Returns a file name based on `org-attach-id-dir' and ID." "Returns a folder path based on `org-attach-id-dir' and ID.
(expand-file-name If TRY-ALL is non-nil, try all id-to-path functions in
(funcall org-attach-id-to-path-function id) `org-attach-id-to-path-function-list' and return the first path
(expand-file-name org-attach-id-dir))) that exist in the filesystem, or the first one if none exist.
Otherwise only use the first function in that list."
(let ((attach-dir-preferred (expand-file-name
(funcall (car org-attach-id-to-path-function-list) id)
(expand-file-name org-attach-id-dir))))
(if try-all
(let ((attach-dir attach-dir-preferred)
(fun-list (cdr org-attach-id-to-path-function-list)))
(while (and fun-list (not (file-directory-p attach-dir)))
(setq attach-dir (expand-file-name
(funcall (car fun-list) id)
(expand-file-name org-attach-id-dir)))
(setq fun-list (cdr fun-list)))
(if (file-directory-p attach-dir)
attach-dir
attach-dir-preferred))
attach-dir-preferred)))
(defun org-attach-check-absolute-path (dir) (defun org-attach-check-absolute-path (dir)
"Check if we have enough information to root the attachment directory. "Check if we have enough information to root the attachment directory.