From 18b12dac615085e4c55029568b65c30b17ec5189 Mon Sep 17 00:00:00 2001 From: stardiviner Date: Fri, 30 Oct 2020 15:11:53 +0800 Subject: [PATCH] org-contacts.el: Add new link type "contact:" * contrib/lisp/org-contacts.el (org-contacts-link-store): Store a link of org-contacts in Org file. * contrib/lisp/org-contacts.el (org-contacts-link-open): Open contact: link in Org file. * contrib/lisp/org-contacts.el (org-contacts-link-complete): Insert a contact: link with completion of contacts. * contrib/lisp/org-contacts.el (org-contacts-link-face): Set different face for contact: link. --- contrib/lisp/org-contacts.el | 66 ++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/contrib/lisp/org-contacts.el b/contrib/lisp/org-contacts.el index 4b3693a0e..851802916 100644 --- a/contrib/lisp/org-contacts.el +++ b/contrib/lisp/org-contacts.el @@ -1146,6 +1146,72 @@ (defun org-contacts-split-property (string &optional separators omit-nulls) (setq proplist (cons bufferstring proplist)))) (cdr (reverse proplist)))) +;;; Add an Org link type `contact:' for easy jump to or searching org-contacts headline. +;;; link spec: [[contact:query][desc]] +(org-link-set-parameters "contact" + :follow 'org-contacts-link-open + :complete 'org-contacts-link-complete + :store 'org-contacts-link-store + :face 'org-contacts-link-face) + +(defun org-contacts-link-store () + "Store the contact in `org-contacts-files' with a link." + (when (eq major-mode 'org-mode) + ;; (member (buffer-file-name) (mapcar 'expand-file-name org-contacts-files)) + (let ((headline-str (substring-no-properties (org-get-heading t t t t)))) + (org-store-link-props + :type "contact" + :link headline-str + :description headline-str)))) + +(defun org-contacts--all-contacts () + "Return an alist (name . (file . position)) of all contacts in `org-contacts-files'." + (car (mapcar + (lambda (file) + (unless (buffer-live-p (get-buffer (file-name-nondirectory file))) + (find-file file)) + (with-current-buffer (get-buffer (file-name-nondirectory file)) + (org-map-entries + (lambda () + (let ((name (substring-no-properties (org-get-heading t t t t))) + (file (buffer-file-name)) + (position (point))) + `(:name ,name :file ,file :position ,position)))))) + org-contacts-files))) + +(defun org-contacts-link-open (path) + "Open contacts: link type with jumping or searching." + (let ((query path)) + (cond + ((string-match "/.*/" query) + (let* ((f (car org-contacts-files)) + (buf (get-buffer (file-name-nondirectory f)))) + (unless (buffer-live-p buf) (find-file f)) + (with-current-buffer buf + (string-match "/\\(.*\\)/" query) + (occur (match-string 1 query))))) + (t + (let* ((f (car org-contacts-files)) + (buf (get-buffer (file-name-nondirectory f)))) + (unless (buffer-live-p buf) (find-file f)) + (with-current-buffer buf + (goto-char (marker-position (org-find-exact-headline-in-buffer query))))))))) + +(defun org-contacts-link-complete (&optional arg) + "Create a org-contacts link using completion." + (let ((name (completing-read "Contact Name: " + (mapcar + (lambda (plist) (plist-get plist :name)) + (org-contacts--all-contacts))))) + (concat "contact:" name))) + +(defun org-contacts-link-face (path) + "Different face color for different org-contacts link query." + (cond + ((string-match "/.*/" path) + '(:background "sky blue" :overline t :slant 'italic)) + (t '(:background "green yellow" :underline t)))) + (provide 'org-contacts) ;;; org-contacts.el ends here -- 2.28.0