Every so often, as I am performing some repetitive or tedious task in my job as a web developer, it dawns on me that I am not taking advantage of technology the way I should. Case in point: a recent project required me to format a large list of URLs and email addresses as HTML hyperlinks. For each one, I had to perform the following keyboard gymnastics in Emacs:

  1. move point to the beginning of the URL
  2. set the mark
  3. move the point to the end of the URL
  4. kill the selection
  5. type <a href=" possibly followed by some scheme like mailto:
  6. yank the saved text from the kill ring
  7. type ">
  8. type the appropriate display text for the link
  9. type </a>

Looks like a prime candidate for a keyboard macro, yes? That is what I thought at first. But a generic macro cannot differentiate between hyperlinks needing an http: scheme and those needing mailto:, or which ones should have a title attribute.

Emacs Lisp to the rescue. Here is what I added to my .emacs configuration to aid the process:

(defun hyperlink-url-at-point ()
  (interactive)
  (require 'thingatpt)
  (let ((url (or (thing-at-point 'url)
                 (error "No URL at point")))
        (text (read-from-minibuffer "Text: "))
        (title (read-from-minibuffer "Title: "))
        (bounds (bounds-of-thing-at-point 'url)))
    (if (equal "" text)
        (setq text (buffer-substring-no-properties
                    (car bounds) (cdr bounds))))
    (if (not (equal "" title))
        (setq title (concat " title="" title """)))
    (delete-region (car bounds) (cdr bounds))
    (insert (format "<a href="%s"%s>%s</a>" url title text))))

(global-set-key "C-cu" 'hyperlink-url-at-point)

The resulting keyboard work is greatly reduced:

  1. move point to anywhere along the URL
  2. type ctrl-c u
  3. type optional display text for the hyperlink at the prompt, press enter (defaults to the URL itself)
  4. type optional title attribute text at the prompt, press enter

Here is the best part: thanks to the wonderful thing-at-point library which recognizes all kinds of URLs (among other “things”), hyperlink-url-at-point will automagically insert the proper scheme in the link’s href attribute for a given URL. That means that email addresses will be linked correctly with a mailto: scheme, and that URLs lacking the leading http:// will have it inserted.