I often need to keep track of conversations that happen in Slack, so I wrote a small elisp package that retrieves all message info (channel, timestamps, message(s)) for a given Slack permalink.

Then I convert the data to org-element using org-element-interpret-data.

Now, I need to find a way to either override org-insert-link so whenever I want to insert a link and it happens to match a pattern, it would not insert link as is, but extracts Slack data using my method and inserts that instead.

What's the best way of doing something like this?


Usually advising functions can be used to change the behavior of a function. But for this interactive function it would get complicated when looking at the source.

Fortunately org-mode (version 9.1+) has a built-in method to add custom link types which is the preferred way in this case:

(org-link-set-parameters TYPE &rest PARAMETERS)

An example that should come close to what you have in mind:

(defun my-org-link-insert-slack-data (&optional arg)
  "Get the slack link and insert the data."
  (let ((slack-link (read-string "slack link: ")))
    ;; Use your function here to insert the slack data.
    (insert slack-link)))

(org-link-set-parameters "slack" :complete #'my-org-link-insert-slack-data)

Evaluate the example code and then run M-x org-insert-link. The custom link type slack can be selected:

new org link type for slack

Then it prompts you for the slack link and inserts the text entered at point.

Usually the completing function has to return a string. But as long as I have understood your question correctly you don't really want to insert a link. Therefore the function just inserts the text itself. Org will show an user error in the minibuffer (wrong type argument: stringp, nil) but it still works.

It would probably be better to just use a function for this and not rely on org-insert-link at all.

  • Your edit to highlight that the completing read should return a string makes sense. But it can prompt for a description too? In which case would it then return the entire link? Or I guess org-insert-link should do that based on some flag. Can you elaborate on that please?
    – RichieHH
    Feb 13 '20 at 10:14
  • If the function returns a string (just replace (insert slack-link) with "text" to test) you will be prompted to enter a description and then a link is inserted as follows: [[text][description]]. The prompt for the description is inside the org-insert-link function: (read-string "Description: " initial-input). The function with (insert slack-link) will not prompt for a description as org-insert-link aborts beforehand because an error is signaled.
    – Hubisan
    Feb 13 '20 at 11:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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