Here's a lightly tested walkthrough of how you could get started with
this.
The first thing we need is a way to capture where the
heading-to-be-refiled is. Org might store this information itself,
but we don't need to worry about that. Let's create a variable that
stores a marker to the location (see (info "(elisp)Markers")
) and
then use advice ((info "(elisp)Advising Functions")
) to instruct
org-refile
to set the variable to that marker before refiling.
(defvar my/org-last-refile-marker nil)
(advice-add 'org-refile
:before
(lambda (&rest _)
(save-excursion
(org-back-to-heading)
(setq my/org-last-refile-marker (point-marker))))
'((name . "my/org-set-refile-marker")))
Next we need to store a link after the heading has been refiled. Org
provides a hook, org-after-refile-insert-hook
, that we can use.
(defvar my/org-last-refile-link nil)
(defun my/org-set-last-refile-link ()
(setq my/org-last-refile-link (org-store-link nil)))
(add-hook 'org-after-refile-insert-hook #'my/org-set-last-refile-link)
Now the link text for that heading will be stored in the variable
my/org-last-refile-link
. The remaining piece is to go back to the
original location and insert the link. Again, we can advise
org-refile
, this time to do something after instead of before.
(advice-add 'org-refile
:after
(lambda (&rest _)
(when (and my/org-last-refile-marker
my/org-last-refile-link)
(let ((buf (marker-buffer my/org-last-refile-marker)))
(when (buffer-live-p buf)
(with-current-buffer buf
(save-excursion
(goto-char my/org-last-refile-marker)
(insert (concat my/org-last-refile-link "\n"))))))
(setq my/org-last-refile-marker nil)
(setq my/org-last-refile-link nil)))
'((name . "my/org-insert-refile-marker")))
That's got at least a few rough edges. For example, org-refile
accepts a prefix argument that makes it do something other than refile.
Also it might not work when called via org-agenda-refile
. Another
thing to consider is whether you want this behavior for every
org-refile
call. If not, it might make sense to make a custom
command that wraps org-refile
instead of using the :before
advice
above.
But hopefully above gives you something to build off of.