Improving my elisp by building an API to my YOURLS shortener

Table of Contents

img

Until recently I was well-served by now-derelict url-shortener which worked well. It’s a cool library – very general, supporting a variety of shortening options. But when it broke, it was annoyingly complex to fix. Plus, I needed the excuse to sharpen my elisp skills a bit. The result is below. I learned a lot of good things (big thanks to the Reddit emacs community), including:

  • Using defcustom to create customs groups for use in emacs’ nice customization tooling
  • Utilizing url-build-query-string to build my… well, you know. And using backtick ` with it to work with my customized variables.
  • Using url-retrieve-synchronously with its returned buffer (a distinctly emacsy way of doing things) instead of attempting url-retrieve with its asynchronous callback function to make time my friend rather than a complication
  • Utilizing with-current-buffer, buffer-string, string-match, and replace-regexp-in-string to trim the full response down to my desired result.

The result is just a couple of short functions that do what I (and perhaps anyone else using a YOURLS instance) need. No logging, no error messages, no trying to allow for other shorteners, no worry about people using other operating systems, no testing suite, no support provisions – just about one screen of code, that’s it. Fun and done.

(defcustom yourls-signature nil "The YOURLS-given signature code"
  :group 'yourls)
(defcustom yourls-url nil "The base URL of yourls-api.php"
  :group 'yourls)

(defun tsa/yourls-get-short (url)
  (let* ((querys (url-build-query-string `(("signature" ,yourls-signature)
                                           ("action" "shorturl")
                                           ("format" "json")
                                           ("url" ,url))))
         (final-url (concat yourls-url "/?" querys))
         (url-request-method "GET")
         (retrieved (url-retrieve-synchronously final-url)))
    (with-current-buffer retrieved
      (let* ((s (buffer-string))
             (shortened (when (string-match "\"shorturl\":\"\\([^\"]*\\)\""
                                            s)
                          (replace-regexp-in-string "\\\\" "" (match-string 1 s)))))
        shortened))))

(defun tsa/yourls-shorten-at-point ()
  "Shorten the URL at point with your YOURLS install"
    (interactive)
    (let ((url-bounds (bounds-of-thing-at-point 'url)))
      (when url-bounds
        (let ((url (tsa/yourls-get-short (thing-at-point 'url))))
          (when url
            (save-restriction
              (narrow-to-region (car url-bounds) (cdr url-bounds))
              (delete-region (point-min) (point-max))
              (insert url)))))))
Tory Anderson avatar
Tory Anderson
Web App Engineer, Digital Humanist, Researcher, Computer Psychologist