so

Use a function, Luke

Volume 3, Issue 31; 05 Nov 2019

Sometimes I’m reminded how nice Emacs lisp is, mosty because it’s lisp.

I’ve been playing with org-brain. I wanted notes to use in the experiment, so I converted some data that I’d been storing elsewhere into Org mode. Some of those notes are about places, with geospatial coordinates like this: 37.506805,-122.24738.

I wanted to make those into OpenStreetMap links. I spent a few minutes trying to work out whether it would be easier to do this in Emacs by writing some elisp or just doing it with a script. (Well, there’s no question it’d be easier for me with a script, but I like to keep my hand in elisp programming.)

Org Mode has a handy syntax for links. This markup:

Check out [[https://nwalsh.com/][my homepage]].

Is rendered in my emacs buffer as:

Check out my homepage.

And a quick C-c C-l on that link will open it up in a browser.

What’s even better is that I can configure shortcuts. For example, I can configure it so that [[bug:12345]] renders as “bug:12345” and links to bug 12345 without me having to type the whole URI. Here’s a configuration that makes [[dd:docbook]] a shortcut for https://duckduckgo.com/?q=docbook:

("dd" . "https://duckduckgo.com/?q=")

The OpenStreetMap syntax I want to generate is:

https://www.openstreetmap.org/?mlat={LAT}&mlon={LNG}&zoom={ZOOM}

which isn’t just the coordinates stuck on the end or injected in the middle. It’s going to be necessary to parse the coordinates to generate the link.

That’s when it struck me, in lisp, code and data are delightfully intertwingly. In many cases, where you can put a string can also put a function. And this is one of those places! This configuration:

("geo" . geo-to-openstreetmap)

And this function:

(defun geo-to-openstreetmap (coords &optional zoom)
  "Parse COORDS into an OpenStreetMap link. The format of COORDS
is lat,long[/znum]. If ZOOM is specified, it overrides znum."
  (let* ((geo (split-string coords "/" t "[\s]+"))
         (latlong (split-string (car geo) ",[\s\t]*" t "[\s]+")))
    (concat "https://www.openstreetmap.org/?mlat="
            (car latlong)
            "&mlon="
            (car (cdr latlong))
            "&zoom="
            (if zoom
                zoom
              (if (cdr geo)
                  (car (cdr geo))
                "17")))))

Does the trick. Now [[geo:37.506805,-122.24738][OpenStreetMap]] is a link: OpenStreetMap.

Please provide your name and email address. Your email address will not be displayed and I won’t spam you, I promise. Your name and a link to your web address, if you provide one, will be displayed.

Your name:

Your email:

Homepage:

Do you comprehend the words on this page? (Please demonstrate that you aren't a mindless, screen-scraping robot.)

What is four times two?  (e.g. six plus two is 8)

Enter your comment in the box below. You may style your comment with the CommonMark flavor of Markdown.

All comments are moderated. I don’t promise to preserve all of your formatting and I reserve the right to remove comments for any reason.