7

So I'm trying to make an "autolinks mode" to emulate the functionality of notetaking software like Tomboy Notes or notes.vim, which automatically linkifies any text that happens to be the title of a note. But I'm totally new to Emacs and to Elisp. This is what I have so far (it's like the first elisp I've ever written, be gentle):

;; Set directory of files to search for *.org files 
(setq autolinks-mode-dir "~/Dropbox/Org/")

;; Get all .org files in this directory. 
(setq autolinks-mode-files (directory-files autolinks-mode-dir t "[.]org\\'"))

;; Convert it to a list of just the filenames, without paths.
(setq autolinks-mode-files-bare
      (mapcar 'file-name-nondirectory autolinks-mode-files))

;; Strip extensions
(setq autolinks-mode-topics
      (mapcar 'file-name-sans-extension autolinks-mode-files-bare))

So far, so good. Now I I have a list of topics, and a list of corresponding files. For example, the topic "James" corresponds to an org file at "/path/to/notes/James.org". Now I want to manually update org's list of links for a particular buffer with this list of topics, so that, when I turn on this mode, it highlights any instance of the word "James" in an org buffer and makes it a link to /path/to/notes/James.org. Same with a multi-word org file, like "Henry James", which would point to /path/to/notes/Henry James.org. Note that I'm not trying to replace all instances of James with [[James]] or <James> or something, just trying to get those text snippets to behave as links.

I've been browsing through org.el, and I saw this variable:

(defvar org-link-re-with-space nil
  "Matches a link with spaces, optional angular brackets around it.")

Which in my system has all kinds of stuff in it, probably due to org-ref and other things:

org-link-re-with-space is a variable defined in ‘org.el’.
Its value is
"<?\\(A\\(?:cp?\\|utocite[*s]?\\)\\|Cite\\(?:a\\(?:l[pt]\\|uthor\\*?\\)\\|[pst]\\)?\\|Gls\\(?:pl\\)?\\|Notecite\\|P\\(?:arencites?\\|notecite\\)\\|Smartcites?\\|Textcites?\\|a\\(?:c\\(?:p\\|r\\(?:full\\|long\\|short\\)\\)?\\|ddbibresource\\|uto\\(?:cite[*s]?\\|ref\\)\\)\\|b\\(?:bdb\\|ib\\(?:entry\\|liography\\(?:style\\)?\\|tex\\)\\)\\|cite\\(?:a\\(?:l\\(?:[pt]\\*\\|[pt]\\)\\|uthor\\*?\\)\\|date\\*?\\|num\\|p\\*\\|t\\(?:\\*\\|ext\\|itle\\*?\\)\\|url\\|year\\*?\\|[*pst]\\)?\\|do\\(?:cview\\|i\\)\\|e\\(?:l\\(?:feed\\|isp\\)\\|qref\\)\\|f\\(?:ile\\(?:\\+\\(?:\\(?:emac\\|sy\\)s\\)\\)?\\|notecite\\|oot\\(?:cite\\(?:s\\|texts?\\)?\\|fullcite\\)\\|tp\\|ullcite\\)\\|g\\(?:ls\\(?:desc\\|link\\|\\(?:p\\|symbo\\)l\\)?\\|nus\\)\\|h\\(?:elp\\|ttps?\\)\\|i\\(?:n\\(?:dex\\|fo\\)\\|pynb\\|rc\\)\\|l\\(?:abel\\|ist-of-\\(?:\\(?:figur\\|tabl\\)es\\)\\)\\|m\\(?:ailto\\|\\(?:essag\\|h\\|u4\\)e\\)\\|n\\(?:ameref\\|ews\\|o\\(?:bibliography\\|\\(?:te\\)?cite\\)\\)\\|orgit\\(?:-\\(?:log\\|rev\\)\\)?\\|p\\(?:a\\(?:geref\\|rencite[*s]?\\)\\|notecite\\|rint\\(?:bibliography\\|index\\)\\)\\|r\\(?:ef\\|mail\\)\\|s\\(?:hell\\|martcites?\\|upercites?\\)\\|textcites?\\|w3m\\):\\([^]    

So it seems Org has the functionality to be able to highlight plain text as a link. I just don't know the best way to do it. I think I can append my list of link words to org-link-re-with-space, maybe? But then how do I set their targets? Any help would be much appreciated.

3
  • You probably cannot use org-links for this. It sounds like you want to use font-lock to get the behavior you want. You might find some inspiration here kitchingroup.cheme.cmu.edu/blog/2015/06/22/…. In particular the use of button-lock-set-button to make some patterns clickable. May 22, 2017 at 0:16
  • I am not sure I understand completely what you are trying to do, but why not just replace all occurences of James with [[file:/path/to/notes/James.org][James]] in the buffer. Then it will appear as a link if the buffer is in org-mode major mode. Jun 21, 2017 at 21:03
  • 1
    The idea is not to make new links, but to automatically emulate links for any filename. That way, I can delete James.org, change its name, and not have to worry about updating the link. Hard linking is silly compared to autolinking.
    – Jonathan
    Jun 21, 2017 at 23:52

2 Answers 2

2

I believe this is essentially what you want:

;; Set directory of files to search for *.org files
(setq autolinks-mode-dir "/Users/jkitchin/vc/journal/2018/08/07/")

;; Get all .org files in this directory.
(setq autolinks-mode-files (directory-files autolinks-mode-dir t "[.]org\\'"))

;; Convert it to a list of just the filenames, without paths.
(setq autolinks-mode-files-bare
      (mapcar 'file-name-nondirectory autolinks-mode-files))

;; Strip extensions
(setq autolinks-mode-topics
      (mapcar 'file-name-sans-extension autolinks-mode-files-bare))

(button-lock-set-button
 (regexp-opt autolinks-mode-topics)
 (lambda (event)
   (interactive "e")
   (let ((click-pos (posn-point (event-end event))))
     (save-mark-and-excursion
      (save-match-data
    ;; This is clunky, but with grouping the properties may not extend to
    ;; the whole regexp, e.g. if you set properties on a subgroup.
    (goto-char (previous-single-property-change click-pos
                            'button-lock))
    ;; now make sure we see it again to get the match-data
    (while (not (looking-at (regexp-opt autolinks-mode-topics)))
      (backward-char))
    (find-file (expand-file-name
            (concat (match-string 0) ".org")
            autolinks-mode-dir))))))
 :face (list 'org-link))

You could embed that in a function, and then call it in an org-mode-hook and turn on button-lock-mode. That should make your topics look like links, and when you click on them it will open the file. One possible hiccup is the order that the topics are searched. You want to make sure "Henry James" is searched before James, which may take some sorting by length or something.

0

This answer is just a suggestion.

Note that I'm not trying to replace all instances of James with [[James]] or or something, just trying to get those text snippets to behave as links.

Why not? If you do this automatically, you get links and following the method bellow you could just have "normal" face for words links and an other face for links you create manually.

How to change faces of org-mode links depending on the link type?

Your Answer

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

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