One way to accomplish what you want is to wrap org-contacts
with a special org-contacts-mode
as demonstrated in the following.
This new major mode defines the keys l and c as you specified it in its local keymap.
You may paste the code into your .emacs
file after (require 'org-contacts)
or a suitable autoload
.
You can just call org-contacts
instead of your proposed new function. Put point at the entry you want to insert into the original buffer and press l or c.
(require 'org-contacts)
(define-derived-mode org-contacts-mode org-agenda-mode "org-contacts"
"Like `org-agenda-mode' with the following alternative key-bindings:
l: insert a link to the selected contact at point in the original buffer
c: insert a copy of the subtree corresponding to the contact at point in the original buffer
Both commands burry the contacts buffer afterwards.
")
(defadvice org-contacts (around contacts-mode activate)
"Wrap `org-contacts' with `org-contacts-mode' where special keybindings are in effect.
See `org-contacts-mode' for further details."
(let* ((org-contacts-buffer (get-buffer-create "*org-contacts*"))
(original-buffer (current-buffer))
(org-agenda-buffer-name (buffer-name org-contacts-buffer)))
(switch-to-buffer org-contacts-buffer)
ad-do-it
(org-contacts-mode)
(setq-local org-contacts-original-buffer original-buffer)))
(defun org-contacts-return (content)
"Insert CONTENT into original buffer and switch there."
(declare (special org-contacts-original-buffer))
(unless (and
(boundp 'org-contacts-original-buffer)
org-contacts-original-buffer)
(error "Cannot determine the original buffer.
Note, you should not manually activate `org-contacts-mode'."))
(let ((original-buffer org-contacts-original-buffer))
(bury-buffer)
(switch-to-buffer original-buffer)
(insert content)))
(defun org-subtree-string (&optional marker)
"Return subtree at location MARKER.
MARKER should be nil or a marker pointing to a live org-buffer.
If MARKER is nil it corresponds to the current point in the current buffer."
(let ((buf (or (and (markerp marker) (marker-buffer marker)) (current-buffer)))
(pt (or (and (markerp marker) (marker-position marker)) (point)))
b e)
(with-current-buffer buf
(unless (derived-mode-p 'org-mode)
(error "This is not an org-mode buffer."))
(save-excursion
(goto-char pt)
(org-back-to-heading t)
(setq b (point))
(org-end-of-subtree t)
(setq e (point)))
(buffer-substring b e))))
(setq org-contacts-mode-map (let ((map (make-sparse-keymap)))
(define-key map [?l]
(lambda () (interactive)
(let* ((marker (org-get-at-bol 'org-hd-marker))
(buf (marker-buffer marker))
(filename (expand-file-name (buffer-file-name buf))))
(org-contacts-return
(concat "[[file:" filename "::"
(nth 4 (org-with-point-at marker
(org-heading-components)))
"]]")))))
(define-key map [?c]
(lambda () (interactive)
(let* ((marker (org-get-at-bol 'org-hd-marker)))
(org-contacts-return
(org-subtree-string marker)))))
map))
Usage-Example:
Assume you have already defined some contact with name Nobody
and you want to insert a copy of the contact in file test.org
at the current point position.
With point at the place where you want to insert the copy of the contact call M-x org-contacts
. Maybe, you have already a key-sequence for that. You get the prompt for the contact name from org-contacts
as shown in the following figure.

Input the contact name ("Nobody" in our example). You get an org-contacts buffer with all matches of "Nobody". In our example there is just one match. Place point on the match of your like.

For copying the corresponding contact into the target buffer press c (see following figure).

If you press l instead of c you get a link to the contact as shown in the following figure below the copied contact. (Note, that I have replaced some sensitive data by three dots. Actually, you get the absolute path to the contact file.)
