;;; Introduction ;; ;; In my Org notes I often refer to terms like JIRA tickets or some ;; queries to an (internal) search engine. Doing it natively with Org ;; mode is a bit involved: ;; ;; 1. org-insert-link ;; 2. Type link, e.g. "JIRA:MYPRJ-1234" ;; 3. Type the visible description again: "MYPRJ-1234". ;; ;; The repetition is a bit cumbersome and a template to insert the ;; link would be more convenient. And sometimes I already typed the ;; ticket number and I want to turn it into a link quickly. ;; ;; The code below adds a element which can be used in Tempel templates ;; to insert [[org:links][links]]. It works with and without active ;; region. If no region is active, a term is prompted in the ;; minibuffer. ;; ;; The following template: ;; ;; (jira (ol "JIRA")) ;; ;; results in [[JIRA:ticket][ticket]] where ticket is prompted or ;; taken from the region. ;; ;; This relies on having link types configured in your ;; `org-link-abbrev-alist', the link type accepts one parameter ;; matching a link type. ;; ;;; Requirements / why na(t)ive templates don't work ;; ;; The template has to meet the following requirements: ;; ;; - type the search term / ID only once ;; - or, use the region instead, if active ;; - no visible prefixes (link abbrevations) ;; ;; We need to store the region before the templating kicks ;; in, because the region can be used only once in a template. For ;; example, this doesn't work: ;; ;; (jira "[[JIRA:" r "][" r "]]") ;; ;; (and it's a region-only template, so another template would be ;; needed for a prompt). ;; ;; Also, a prompting variant doesn't work due to a bug in Org mode ;; which makes the element cache trip: ;; ;; (jira "[[JIRA:" (p "Ticket: " ticket) "][" (s ticket) "]]") ;; ;; Unfortunately, this not-so-elegant code is needed to meet the ;; requirements. (defun my/tempel-org-link (elt) "Tempel field to insert an org link." (when (eq (car-safe elt) 'ol) (let ((link-type (cadr elt))) (if (and (boundp 'my/region) my/region) ;; consume region with r and use the stored region ;; afterwards, as r can be used only once `(l "[[" ,link-type ":" r "][" ,my/region "]]") ;; NOINSERT is used for the prompt because the org-mode ;; element cache doesn't handle simultaneous edits well. So ;; prompt in minibuffer and insert the result twice. `(l "[[" ,link-type ":" (p "Term: " term t) term "][" term "]]"))))) (defun my/store-region (f &rest args) "Store the region in the my/region variable." (setq my/region (when (use-region-p) (buffer-substring (region-beginning) (region-end)))) (apply f args) (setq my/region nil)) (add-to-list 'tempel-user-elements #'my/tempel-org-link) (advice-add #'tempel-insert :around #'my/store-region)