[Not a complete answer (but too long for a comment), just a sketch of a possible implementation - untested and possibly wrong. The main assumption is that I can advise a function and change its argument list by adding an extra optional argument: I think that's possible but I'm not sure.]
If I had to do it, I would advise org-find-olp
to take an extra optional boolean argument, create-if-necessary
. If the arg is true, the new function would use its first argument (which is a list consisting of the file path and the list of headings) to check if the file exists and, if not, create it; also it would check that the heading hierarchy exists within that file and, if not, create it or add any missing components; then it would call the existing org-find-olp
without the extra argument with the assurance that the pieces it needs exist already.
The problem is that the call sites of org-find-olp
would have to change to pass the new argument when needed.
There are three places in Org mode that org-find-olp
is called, although there may be more in packages that are added through ELPA/MELPA (I don't have any such, but my package list is rather Spartan). Two of the three places are the file+olp
and file+olp+datetree
targets in org-capture
; the third is in org-mobile
. You'd have to change (at least) the file+olp
target to call org-find-olp
with extra args. Instead of:
;; line 1032 or thereabouts in org-capture.el
...
(`(file+olp ,path . ,outline-path)
(let ((m (org-find-olp (cons (org-capture-expand-file path)
outline-path))))
(set-buffer (marker-buffer m))
...
you'd write:
...
(`(file+olp ,path . ,outline-path)
(let ((m (org-find-olp (cons (org-capture-expand-file path)
outline-path) nil t)))
(set-buffer (marker-buffer m))
...
You'd leave the org-mobile
call (as well as any other calls from other modules) unmodified, unless you investigate them and you want them to have the same behavior as the capture calls.
The advice would be something like this (Caution: pseudocode ahead):
(defun org-find-olp-create (orig-func path &optional this-buffer create-if-necessary)
(when create-if-necessary
(let ((filepath (car path))
(headings (cdr path))
(when <filepath does not exist>
<create it>)
<check headings in filepath and create/add missing>))
;; call the original function without the last argument
(apply orig-func (list path this-buffer)))
(advice-add 'org-find-olp :around #'org-find-olp-create)
Note that if you remove the advice, you will also have to revert the changes in org-capture
(and any other changes you might have made in call sites from other modules). The fact that this method requires changes to code other than just advising the function is its major disadvantage. Maybe somebody might be able to suggest a better method that does not require such changes, but I can't help but think that it would require more complicated tricks to accomplish that.
Note also that the actual work that org-find-olp-create
would have to do to create the file and the headings if necessary, would need to be implemented. The pseudocode above is just placeholders for the actual implementation.
To reiterate what I said in my comment: some things are not worth automating. This is one of them.
cl-letf
on error.