Posts

  • Meet Utterson, my Jekyll blogging helper

    Back in 2019 I wrote about dealing with Jekyll post URLs, where I shared a tiny command that spared me from having to remember the exact file name of every article I wanted to link to. That command has been in my config ever since, and over the years it quietly grew a few siblings. Recently I finally gathered them all in one place and turned them into a small package - utterson.

    The common Jekyll tasks

    I guess anyone who blogs with Jekyll knows the drill. Jekyll is great and I have no intention of switching, but a few of its conventions generate a steady trickle of manual work:

    • posts live in _posts and their file names have to start with the publication date, as in 2026-08-26-some-post.md
    • every article needs a bit of YAML front matter at the top - a layout, a title, a date, some tags
    • linking to another post means using a Liquid tag that wants that date-prefixed file name, which nobody remembers
    • images and other assets need URLs relative to the site root, not to the article you happen to be editing

    None of this is hard. All of it is annoying, and all of it is exactly the sort of mechanical work an editor should be doing on your behalf. So over the years I wrote a command for each chore, dropped it in my init.el and moved on with my life.

    Why I finally cleaned this up

    The tipping point was the last command I added - promoting a draft to a post.

    I write most articles in _drafts, where jekyll serve --drafts shows them but a deploy doesn’t. Publishing one used to mean renaming the file by hand to add today’s date, then editing the date in the front matter to match, then convincing git that this was a rename rather than a delete plus a brand new file. Three chances to get something wrong, and I certainly got it wrong more than once.

    Once that was automated I took a look at what had accumulated in my config and realized it wasn’t a bag of snippets anymore - it was a workflow. And since every person blogging with Jekyll from Emacs deals with exactly the same chores, there was no good reason to keep it to myself. So I spent an evening extracting the lot, wrote some tests, and gave it a name.1

    There are other Jekyll packages for Emacs, of course. Both hyde and easy-jekyll aim to be something like an IDE for your site, with dashboards, deployment and preview buffers. That’s a perfectly reasonable thing to want, it’s just never been what I wanted. My site lives in git, I deploy it with a push, and I’ve already got Magit and a browser. All I ever wanted was for the bookkeeping to stop being my problem.

    So utterson is deliberately small. It knows that a Jekyll site is a folder of Markdown files with YAML front matter, and that’s about the extent of its ambitions. Renames go through vc, so git records them as renames and the history of an article follows it around. Nothing in there ever deploys anything.

    Taking it for a spin

    The package is not on MELPA (yet?), so for the time being it’s package-vc territory:

    (use-package utterson
      :vc (:url "https://github.com/bbatsov/utterson" :rev :newest)
      :custom
      ;; where to look for sites, when you invoke a command outside one
      (utterson-search-path '("~/projects/"))
      :config
      ;; the commands live in a keymap that you bind wherever you please
      (keymap-set utterson-mode-map "C-c j" 'utterson-command-map)
      (global-utterson-mode +1))
    

    global-utterson-mode enables the minor mode in the buffers of any folder that has a _config.yml in it, so the commands are around while you’re working on a site and nowhere else.

    C-c j p starts a post. It asks for a title, offers a file name slug derived from it (which you’re free to shorten right there, and I usually do), then asks for tags, completing against every tag the site already uses. That last bit is how you avoid ending up with both Emacs and emacs in your tag cloud. Finally it writes the front matter, saves the file and leaves the cursor exactly where you’re about to start writing:

    ---
    layout: post
    title: Meet Utterson, my Jekyll blogging helper
    date: 2026-08-26 15:01 +0300
    tags:
    - Jekyll
    - Blogs
    - Packages
    ---
    

    That block, as it happens, is the one this very article started with. Here’s the whole thing in action:

    Creating a new post with utterson: the title prompt, the slug derived from it, tag completion, and the finished front matter

    C-c j d does the same in _drafts and C-c j t moves an article between the two, dating it on the way in and staging the rename with git. C-c j r is for the article you wrote a couple of weeks ago and never got around to publishing - it sets the date to now and renames the file to match. Both of them take a prefix argument if you’d rather type a date than accept the current time, which is how you schedule something for next Monday morning.

    Publishing a draft looks like this - notice that the file name, the date in the front matter and git’s idea of what happened all stay in sync:

    Publishing a draft with utterson: the file is renamed with today's date, the front matter date is updated, and git records a rename

    The linking commands are the descendants of that 2019 snippet, all grown up. C-c j u inserts a post_url tag, completing over your posts newest first and showing you each post’s title next to its file name, and C-c j l inserts the entire Markdown link, already titled after the post it points to:

    Inserting a link to another post: the completion list shows every post newest first, with its title next to the file name

    C-c j i inserts an image, C-c j I copies a file into your images folder first (perfect for a screenshot that’s still sitting on your desktop under a name like Screenshot 2026-08-26 at 15.01.12.png), and C-c j a links to anything else under assets. And C-c j s runs jekyll serve in a buffer, because sooner or later you do want to look at the thing.

    Note: There’s a menu as well, in case you’d rather click your way around while the keybindings are still settling in.

    Epilogue

    It’s early days for the package, even though most of the code behind it has been in daily use for years. If you blog with Jekyll from Emacs, I’d love to hear which of your own little chores it doesn’t cover yet - that’s the fastest way for it to get better.

    And if you don’t blog with Jekyll - what does your setup look like? I’ve got the feeling that quite a few of you are writing your posts in org-mode and I’m always curious about the workflows people come up with.

    That’s all I have for you today! Keep hacking!

    1. Gabriel John Utterson is Doctor Jekyll’s loyal friend and lawyer - the man who keeps his affairs in order. Naming things is hard, but every now and then you get lucky. 

  • Flycheck 38: Might & Magic

    Not all those who wander are lost.

    – J.R.R. Tolkien

    Today I’m happy to announce Flycheck 38 - easily the biggest and most ambitious Flycheck release since I took over the stewardship of the project. It’s the release where Flycheck grows a proper story for language servers, gets the kind of inline diagnostics you’d expect from a modern editor, and learns to apply fixes - all without giving up the checker model that made it popular in the first place.

    The version number, I’ll admit, doesn’t do this one justice - it’s just the next integer after 37, and nothing about “38” whispers “special”. But that’s how it goes with version numbers: some releases are more special than others, and you’d rarely guess which from the number alone.

    Read More
  • CIDER and Projectile Meet Embark

    Embark is one of those packages that quietly rewires how you use Emacs. Think of it as a context-aware right-click: you invoke embark-act (I keep it on C-.) on whatever’s at point - a file name, a symbol, a URL - and Embark offers a menu of things you can do with it. The neat part is that it’s completely extensible, so you can teach it about new kinds of targets. Lately two of my projects, CIDER and Projectile, have grown Embark integrations, in slightly different ways, and both are worth a look.

    Let’s start with CIDER, and teach Embark about Clojure symbols, so embark-act on one offers a bunch of CIDER commands:

    CIDER actions in Embark

    So d shows the documentation, . jumps to the definition, r finds references, i inspects the value, c opens ClojureDocs and a runs apropos - the usual CIDER commands, a keystroke away from wherever your cursor happens to be.

    Here’s the setup. It’s a handful of little wrappers around the CIDER commands, a keymap that binds them, a target finder that spots a Clojure symbol at point, and the bit of wiring that ties it all together:

    (defun my-cider-embark-doc (sym)
      (interactive "sClojure symbol: ")
      (cider-doc-lookup sym))
    
    (defun my-cider-embark-find-def (sym)
      (interactive "sClojure symbol: ")
      (cider-find-var nil sym))
    
    (defun my-cider-embark-fn-refs (sym)
      (interactive "sClojure symbol: ")
      (cider-xref-fn-refs nil sym))
    
    (defun my-cider-embark-inspect (sym)
      (interactive "sClojure symbol: ")
      (cider-inspect-expr sym (cider-current-ns)))
    
    (defun my-cider-embark-clojuredocs (sym)
      (interactive "sClojure symbol: ")
      (cider-clojuredocs-lookup sym))
    
    (defun my-cider-embark-apropos (sym)
      (interactive "sClojure symbol: ")
      (cider-apropos sym))
    
    (defvar my-cider-embark-symbol-map
      (let ((map (make-sparse-keymap)))
        (define-key map "d" #'my-cider-embark-doc)
        (define-key map "." #'my-cider-embark-find-def)
        (define-key map "r" #'my-cider-embark-fn-refs)
        (define-key map "i" #'my-cider-embark-inspect)
        (define-key map "c" #'my-cider-embark-clojuredocs)
        (define-key map "a" #'my-cider-embark-apropos)
        map))
    
    (defun my-cider-embark-target ()
      (when (derived-mode-p 'clojure-mode 'clojurescript-mode 'clojurec-mode
                            'clojure-ts-mode 'cider-repl-mode)
        (when-let* ((bounds (bounds-of-thing-at-point 'symbol))
                    (sym (cider-symbol-at-point)))
          (unless (string-empty-p sym)
            `(cider-clojure-symbol ,sym . ,bounds)))))
    
    (with-eval-after-load 'embark
      (add-to-list 'embark-target-finders #'my-cider-embark-target)
      (add-to-list 'embark-keymap-alist '(cider-clojure-symbol my-cider-embark-symbol-map))
      (add-to-list 'embark-keymap-alist '(cider my-cider-embark-symbol-map)))
    

    That last cider line is my favorite bit. CIDER’s symbol prompts (things like cider-doc and cider-find-var) can read through completing-read and tag their candidates with the cider completion category, so pointing that category at the same keymap means embark-act works on the candidates too. You start typing a symbol to read its docs, spot it in the candidate list, decide you’d rather jump to its definition - C-. . and you’re there, no retyping. Symbols in your code and candidates in the minibuffer end up sharing one set of actions.

    Projectile took the opposite tack and ships its Embark integration out of the box - there’s nothing to configure, it wires itself up as soon as Embark is loaded. Two things happen. Acting on a project candidate (say, in projectile-switch-project) gives you project-specific actions - switch to it, open its VC interface, drop into dired, or remove it from the known-projects list - instead of the generic file actions you’d otherwise get:

    Embark actions on a Projectile project

    And when you act on a project file candidate, Projectile makes sure the path resolves against the project root, so Embark’s file actions land on the right file no matter what your default-directory happens to be.

    You might wonder why Projectile ships this while CIDER leaves it to you. It comes down to what each integration is. Projectile’s is mostly about making the completion categories it already exposes behave correctly under Embark, plus a small and fairly obvious set of project actions - there isn’t much to bikeshed there. CIDER’s symbol actions are a bigger, more personal grab-bag: which commands you want on that menu, and which keys you put them on, is very much a matter of taste. A recipe you copy and tailor felt like the better fit. Same idea, two problems that wanted different answers.

    That’s all I have for you today. Keep hacking!

    P.S. If you’re not using Embark yet, the actions above are just the start - once you start thinking of embark-act as “do something with the thing at point”, it’s hard to stop.

  • Dedicate Windows with toggle-window-dedicated

    You’ve carefully arranged your windows just the way you want them - source code on the left, tests on the right, maybe a shell at the bottom. Then you run some command that calls display-buffer, and suddenly one of your carefully placed windows gets hijacked to show a *Help* buffer or a compilation log. We’ve all been there.

    The display-buffer machinery is one of Emacs’s most powerful features, but also one of its most frustrating. Emacs 30 adds a simple, practical tool to help tame it: toggle-window-dedicated.

    Read More
  • Right-aligned Mode Line Elements

    Emacs users have long wanted the ability to push certain mode line elements to the right edge of the window. Think of it like having a left-aligned and right-aligned section in your mode line - buffer name on the left, maybe the time or some status info on the right.

    Before Emacs 30, achieving this required various hacks involving padding calculations and propertized strings. It was doable, but fragile and ugly.

    Emacs 30 makes it trivial with mode-line-format-right-align.

    Read More

Subscribe via RSS | View Older Posts