3

A silly question.

I try to link my org-files more closely together. I looked into org-roam and org-brain but i'm not convinced that these packages provide what i have in mind (haven't tested it).

As an example what i mean. When i write following sentence in org-mode:

I go to school every monday.

That as soon as i hit SPC after the word school that school is linked to the file school.org or org-header * School. Of course it would search in a default directory or so.

Is there a package providing such functionality in org-mode?

2 Answers 2

3

You can use Radio Links for this. I use them quite a bit. Here's an excerpt with an example from the org-mode manual.


For example, a target <<<My Target>>> causes each occurrence of ‘my target’ in normal text to become activated as a link.

I found some more answers in another stack exchange answer.

In this one a glossary is included as a list definition, which pairs radio links for acronyms, with the definition being a link, possibly to another file

* List of Acronyms

- <<<ABI>>> :: Application Binary Interface
- <<<API>>> :: Application Programming Interface
- <<<DOR>>> :: Documentation Requirement

  :PROPERTIES:
  :TAGS: requirement
  :END:
  Anything related to documentation it self not the specific content like "documents must be in a diff-able format".
- <<<HTML>>> :: HyperText Markup Language
  Almost everyone knows this nowadays :)
1
  • Thanks for answer. I didn't know them. But the Problem with radio-targets is that they can't refer cross multiple files. Cross-file linking seems not supported because of performance reasons.
    – lordnik22
    Commented May 12, 2020 at 12:54
0

Solved it be adding small customization at various places. I now use a combination of a custom-org-store-link, custom-id-completion and custom company-backend (company-org-bookmark) combined with a custom bookmark+ type:

(defvar company-org-bookmark-available 'unknown)

(defun company-org-bookmark-available ()
  "When bookmarks successfully loaded will return non-nil."
  (when (eq company-org-bookmark-available 'unknown)
(condition-case err
    (progn
      (list-bookmarks)
      (setq company-org-bookmark-available (not (null bookmark-alist))))
  (error
   (message "Company-Org-Bookmark: %s" (error-message-string err))
   (setq company-org-bookmark-available nil))))
  company-org-bookmark-available)

(defun company-org-bookmark--lookup-words (word)
  "Filter bookmark-alist by WORD and return candidates."
  (all-completions word bookmark-alist))

;;;###autoload
(defun company-org-bookmark (command &optional arg &rest _ignored)
  "`company-mode' completion backend using bookmark-alist."
  (interactive (list 'interactive))
  (cl-case command
(interactive (company-begin-backend 'company-org-bookmark))
(prefix (when (company-org-bookmark-available) (company-grab-word)))
(candidates
 (let ((words (company-org-bookmark--lookup-words arg))
       (completion-ignore-case t))
   words))
(post-completion
 (kill-backward-chars (length arg))
 (insert (concat "[[" "id:" (cadr (caddr (bookmark-prop-get arg 'function))) "]" "[" arg "]]")))
(kind 'text)
(sorted t)
(ignore-case 'keep-prefix)))

(defun myfunc-bmkp-make-org-id-bookmark ()
  "Used to create bookmarks to org-header identified by ID-Property."
  (interactive)
  (cond ((derived-mode-p 'org-mode)
     (let* ((hid (org-id-get-create))
        (bn (org-link-display-format (org-get-heading t t t t)))
        (bm-bn (bmkp-get-bookmark bn 'NOERROR)))
       (org-store-link nil t)
       (when (not (null bm-bn))
     (setq bn (concat bn
           " (" (file-name-nondirectory buffer-file-name)
           ":" (number-to-string (line-number-at-pos))
           ")")))
       (if (and bm-bn
        (equal hid (cadr (caddr (bookmark-prop-get bm-bn 'function)))))
       bm-bn
     (bmkp-make-function-bookmark bn (backquote (lambda () (org-id-goto ,hid)))))))))

(define-key global-map (kbd "C-c l") 'myfunc-bmkp-make-org-id-bookmark))
(setq company-backends '(company-org-bookmark)) ; beaware all backend deleted, you probably need to adjust this!

The backend is currently case sensitive. When I want to manually link something. I have following in place:

(defun myfunc-org-id-complete-link (&optional arg)
   "Create an id: link using completion"
  (concat "id:" (org-id-get-with-outline-path-completion '((org-agenda-files . (:maxlevel . 9))))))

(defun myfunc-id-description-function (link desc)
  "Generate description for links"
  (interactive)
  (cond (desc desc)
    ((region-active-p) (progn (buffer-substring (region-beginning) (region-end))))
    ((string-prefix-p "id:" link)
     (save-window-excursion
       (save-excursion
     (org-id-goto (string-remove-prefix "id:" link))
     (org-get-heading t t t t))))
    (t (save-excursion (word-at-point)))))

(setq org-link-make-description-function 'myfunc-id-description-function)
(setq org-link-set-parameters "id" :complete 'myfunc-org-id-complete-link)

When calling org-insert-id with C-C C-l and choose an id:-link it prompts for a target with completion of all headings that exist in org-agenda-files. When a header hasn't already got an ID, it will be created automatically as it is chosen. Beaware, this won't add the header to the bookmarks which would be necessary for the company-backend.

Hope it helps!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.