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
_postsand their file names have to start with the publication date, as in2026-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.eland 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, wherejekyll serve --draftsshows them but a deploy doesn’t. Publishing one used to mean renaming the file by hand to add today’s date, then editing thedatein 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
uttersonis 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 throughvc, 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-vcterritory:(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-modeenables the minor mode in the buffers of any folder that has a_config.ymlin it, so the commands are around while you’re working on a site and nowhere else.C-c j pstarts 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 bothEmacsandemacsin 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:

C-c j ddoes the same in_draftsandC-c j tmoves an article between the two, dating it on the way in and staging the rename with git.C-c j ris 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
datein the front matter and git’s idea of what happened all stay in sync:
The linking commands are the descendants of that 2019 snippet, all grown up.
C-c j uinserts apost_urltag, completing over your posts newest first and showing you each post’s title next to its file name, andC-c j linserts the entire Markdown link, already titled after the post it points to:
C-c j iinserts an image,C-c j Icopies a file into your images folder first (perfect for a screenshot that’s still sitting on your desktop under a name likeScreenshot 2026-08-26 at 15.01.12.png), andC-c j alinks to anything else underassets. AndC-c j srunsjekyll servein 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-modeand I’m always curious about the workflows people come up with.That’s all I have for you today! Keep hacking!
-
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. ↩
- posts live in
-
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 onC-.) 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-acton one offers a bunch of CIDER commands:
So
dshows the documentation,.jumps to the definition,rfinds references,iinspects the value,copens ClojureDocs andaruns 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
ciderline is my favorite bit. CIDER’s symbol prompts (things likecider-docandcider-find-var) can read throughcompleting-readand tag their candidates with thecidercompletion category, so pointing that category at the same keymap meansembark-actworks 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 intodired, or remove it from the known-projects list - instead of the generic file actions you’d otherwise get:
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-directoryhappens 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-actas “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
Read Moredisplay-buffermachinery 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. -
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
Read Moremode-line-format-right-align.
Subscribe via RSS | View Older Posts