Here's a lightly tested walkthrough of how you could get started with
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)
(lambda (&rest _)
(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.
(lambda (&rest _)
(when (and my/org-last-refile-marker
(let ((buf (marker-buffer my/org-last-refile-marker)))
(when (buffer-live-p buf)
(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,
accepts a prefix argument that makes it do something other than refile.
Also it might not work when called via
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
But hopefully above gives you something to build off of.