Customizing Pasted Strings in Emacs
(A version of this post was posted earlier, but disappeared. Sorry for any inconvenience.)
The Problem
At my day job, we use the Jira ticketing system, so it’s very useful to link to tickets in Org-mode files, to the point where I’ve defined a shortcut, [[jira:ABC-12345]], and an org capture template for tickets. But sometimes, I’ll copy a link from an email message or something, and C-y to paste it in Emacs, and then I get an ugly
https://jira.example.com/ticket/ABC-12345
That got me to wondering if I could rewrite the text before pasting it, and turn that URL into
The Transform Function
We’re going to need a function to do the transformation, so let’s get that out of the way. Here’s a function that takes a string to be yanked from the kill buffer, and returns the string that we actually want. The only thing to note is that I used cond instead of if because I’ll probably want to expand it later, as I find new patterns I want to transform.
(defun my-org-convert-links (str) "Given a string to yank, try to convert it to org format." ;; Use `cond' rather than `if' to make it easier to add other ;; patterns. (cond ;; Example Jira URL. Extract the ticket number. ((string-match "^https://jira.example.com/ticket/\\([A-Z]+-[0-9]+\\)$" str) (let ((ticket (substring str (match-beginning 1) (match-end 1)))) (format "[[jira:%s][%s]]" ticket ticket) )) ;; Insert other transformations here. Whatever's useful for you. ;; Nothing special. Just return the string. (t str)) )
Hooking into yank
In an ordinary buffer, the Emacs function for pasting is yank, as you can confirm with M-x describe-key C-y, or whatever you’ve bound it to. And if you look up its documentation, you’ll see that it can be customized using yank-transform-functions. This is a list of functions that are called with the string to be yanked. We’ve already written a transform function above, so all we need to do is add it to yank-transform-functions:
(add-to-list 'yank-transform-functions
#'my-org-convert-links)
In this case, the syntax [[jira:ABC-123456][ABC-123456]] doesn’t make sense outside of Org-Mode buffers, so let’s make it specific to org-mode buffers: we’ll make yank-transform-functions buffer-local, and only add our function to it in Org-Mode buffers:
(add-hook 'org-mode-hook
(lambda nil
(make-variable-buffer-local 'yank-transform-functions)
(add-to-list 'yank-transform-functions
#'my-org-convert-links)
))
Now, the more astute among you will have noticed that in Org-Mode, C-y is bound to org-yank, which performs other org-specific magic before pasting. Thankfully, it winds up calling the built-in yank, so the customization above still works.
And that’s about it! I can now have Jira links look pretty when I paste them into my Org-Mode notes, and a structure where I can easily add more transformations if and when I want them.
I’ll note that yanking is different from drag-and-drop, and is handled differently from Emacs. I want to set up something similar for that, but that’ll be a story for a different day.