All posts

61 posts across 9 years

Pinned

vui

vui.el Quickstart

A 15-minute introduction to vui.el - React-style declarative UI components for Emacs. Learn props, state, composition, and the basics of building interactive interfaces without wrestling with buffers.

2025

13 posts
emacs

Implicit Identity Through Call Order

How React-style hooks work without explicit keys—using call order during execution to establish identity. A pattern that's non-obvious but elegant, implemented in Emacs Lisp.

vui

vui.el: Under the Hood

How vui.el works internally — virtual nodes, instances, reconciliation, and the render cycle

vui

vui.el: Optimisation Hooks

Master use-ref, use-callback, and use-memo — the hooks that help you avoid unnecessary work. Learn when mutable references beat state, how stable callbacks prevent wasteful re-renders, and when memoisation pays off.

vui

vui.el: Lifecycle Hooks

Master vui.el's four hooks - on-mount, on-unmount, use-effect, and use-async. Learn cleanup patterns, avoid stale closures with functional updates, and see runnable examples throughout.

vui

vui.el: Context and Composition

Solve prop drilling with context and learn four composition patterns - container/presentational, compound components, render props, and slots - that keep complex UIs maintainable.

vui

vui.el: Building a File Browser

Build a working file browser from scratch in 8 incremental steps. Learn component decomposition, state lifting, callbacks, and the patterns that make UI code maintainable.

emacs

Building Complex UIs in Emacs: Lessons from Three Approaches

Complex Emacs UIs are hard - multiple data sources, cascading updates, cursor management. I tried three approaches to the same interface: imperative rendering, widget.el with zones, and declarative components. Here's what I learned, and why I ended up writing a 2.5k line library.

emacs

The Emacs Widget Library: A Critique and Case Study

A deep dive into Emacs's widget library: what it does well, where it falls apart, and a step-by-step case study of building a table widget with editable cells. Includes working code and hard-won lessons about state management, layout hacks, and cursor position preservation.

nix

Why I ditched Nix after ~4 years

After using Nix, nix-darwin, and home-manager for 4-5 years, I've finally switched back to Homebrew and bash scripts. Here's why the promise of reproducibility didn't hold up on macOS, and how freeing 80GB of disk space was the final push I needed.

emacs-plus

emacs-plus: Emacs Client.app

After fixing PATH injection on macOS 15, I'm dusting off a year-old feature: proper Finder integration for emacsclient. Using AppleScript instead of shell scripts, Emacs Client.app now handles file opening from Finder, drag-and-drop, and auto-starts the daemon. With one cosmetic icon issue that needs your help to solve.

blog

Fresh Coat of Paint: Redesigning d12frosted.io

A complete visual overhaul of this site—migrating from Hakyll to Next.js, adopting a brutalist + jRPG aesthetic, and upgrading to Tailwind CSS v4.1. Sharp corners, bold colors, and way less fighting with build systems.

2022

5 posts
emacs

Vulpea v0.3

Announcing Vulpea v0.3, with major performance improvements for note querying operations. The release introduces a materialised view table that provides a 4.5x speed boost for general queries, plus specialised query functions that can be up to 150x faster in certain scenarios. Whilst write operations take a small hit, the trade-off is worth it for large note collections. I've also added several quality-of-life improvements like better metadata handling and new tag utility functions.

emacs-plus

emacs-plus: PATH injection

Sharing how I improved PATH handling in Emacs+ to solve a common pain point. By injecting the user's PATH into Emacs.app during build, users now get the expected environment variables when launching Emacs from anywhere on macOS. This change also simplifies native-comp configuration and helps avoid common compilation issues. Whilst it's not as dynamic as exec-path-from-shell, it provides a solid out-of-the-box experience for Emacs+ users.

emacs-plus

emacs-plus: stats

Sharing some analytics insights from Emacs Plus and how they'll influence future maintenance. Looking at installation data, Emacs 28 is currently the most popular version, and features like native-comp and xwidgets are heavily used. I'm considering deprecating some rarely-used options whilst making it easier to enable simple build flags. For icons, modern-doom3, nobu417-big-sur, and spacemacs lead in popularity. Any major changes will be well-communicated to avoid disrupting users' workflows.

yabai

Automatic setup of spaces with yabai

Sharing my yabai configuration for automatically setting up workspaces in macOS. I walk through how to create a consistent set of labelled spaces, clean up extras, and automatically move applications to specific workspaces on startup. Whilst tiling window managers aren't for everyone, this setup helps maintain an organised workflow by ensuring applications always land in their designated spaces.

blog

War and World

A personal note explaining that whilst I'll be less available due to the war in Ukraine, projects will continue—though help from the community would be welcome.

2021

8 posts
emacs

Path to org-roam v2

Migrating from org-roam v1 to v2—covering mandatory IDs, improved note structure, enhanced database queries, and the transition from file-based to ID-based linking, with migration scripts and lessons learned.

emacs

Fixing PATH in fish with nix-darwin

Fixing PATH order issues when using Fish shell with nix-darwin—Fish's path_helper reimplementation was moving .nix-profile/bin to the end, preventing nix packages from overriding system binaries. Solution: preserve original PATH and restore order after Fish initialisation.

emacs

Task management with org-roam Vol. 7: Capture

Streamlining task capture in org-roam with dedicated inbox files per machine, processing via org-agenda, and dynamic capture templates that automatically place one-on-one meeting notes in the correct person's file.

emacs

Project management tool for Emacs packages

Comparing build tools for Emacs packages—makem.sh for simplicity, cask for robustness, and eldev for extensibility—with observations on when each tool suits different project needs.

emacs

Towards future-safe emacs.d

Making Emacs configurations maintainable with eldev, straight.el, and structured init/lib/config files—achieving fast startup whilst enabling proper byte compilation, linting with elisp-lint, and testing with buttercup.

emacs

Retries with straight.el

Handling network instability when updating Emacs packages with straight.el by creating a retry wrapper using advice-add to automatically retry failed network operations.

2020

10 posts
emacs

Task management with org-roam Vol. 3: FILETAGS

Managing person-related tasks in org-roam using filetags to automatically tag all tasks (like @FrodoBaggins), maintaining tag inheritance whilst moving to individual notes.

emacs

Task management with org-roam Vol. 2: Categories

Fixing category display in org-roam agenda views by showing meaningful categories based on note titles instead of file IDs, with automatic extraction and formatting for clean, readable results.

emacs

Task management with org-roam Vol. 1: Path to Roam

How to organize tasks and projects in org-roam whilst maintaining compatibility with org-mode's agenda features. Implementing a familiar structure of tasks, projects, and meta-projects across multiple files.

emacs

Org-roam tags

Functions for managing tags in org-roam notes with completion support. Whilst this functionality is now part of org-roam v2, the code demonstrates how to extend org-roam and work with its database.

emacs

Emacs: moving to beginning of line

Custom Emacs functions for smarter line navigation that jump to meaningful content before the actual line start. Includes an enhanced org-mode version that handles headlines, TODO items, and list bullets intelligently—no external packages required.

haskell

Readings Vol. I: precondition encoding

Exploring different approaches to encoding preconditions in Haskell libraries, from simple Maybe types to sophisticated type-level guarantees. Drawing on insights from Alexis King's "Parse, don't validate" and Matt Noonan's "Ghosts of Departed Proofs", learn how to make illegal states unrepresentable.

haskell

Predicate composition

Exploring predicate composition in Haskell through multiple implementation approaches—from simple operators to Semigroup instances and coercion. Learn how to create elegant abstractions without runtime penalties by leveraging GHC's optimisation capabilities, complete with Core dumps and benchmarks.

emacs-plus

emacs-plus: current state

Status update on emacs-plus: improvements to CI/CD with GitHub Workflows, better patch management, and thoughts on simplifying build options whilst maintaining experimental features.

haskell

env-extra v1.0.0.0

Introducing env-extra, a small Haskell library that improves environment variable handling with Text support, flexible return types, and better error handling—reducing boilerplate from System.Environment.

2019

3 posts
emacs

flyspell-correct v0.6

Announcing flyspell-correct 0.6 with a new avy-menu interface, fixed point movements, lexical binding, and various improvements. Special thanks to @clemera and @Ergus for their contributions!

emacs

Emacs: reusing window for helpful buffers

How to make the helpful package reuse windows more sensibly in Emacs by customizing helpful-switch-buffer-function to keep your code visible whilst browsing documentation.

shell

Asking for input in Bash

Learn how to create a reusable 'ask' function in Bash that handles both required and optional user inputs with default values. Discover why bash's indirection and declare features are safer alternatives to eval for variable manipulation.

2018

5 posts
shell

Revisiting Eru

Introducing Eru.sh, my system bootstrapping script that sets up my development environment across different machines. Learn how I use Bash patterns like mapping over files and handling optional themes to make the code more maintainable, plus how to avoid eval whilst still achieving dynamic variable handling.

emacs

Equality of booleans in Emacs

Exploring the quirky world of booleans in Emacs Lisp—or rather, the lack of them! Since everything is either nil (the empty list) or some form of "true", comparing boolean values gets interesting. Learn different approaches using if/when, not, and xor to handle boolean comparisons properly.

shell

High quality GIF from video

Learn how to create high-quality GIFs from video using FFmpeg's custom palette generation. I share my 'gifify' script that automates the process, with options for FPS, scaling, and compression, plus visual examples comparing default vs custom palettes.

emacs

flyspell-correct v0.5

Announcing flyspell-correct 0.5 with rapid mode for fixing multiple words in one run, function renames, improved skipping behaviour, and test coverage.

shell

Random bytes generation with OpenSSL

A quick tip for generating high-entropy random bytes using OpenSSL's rand command. Learn how to use hex or base64 encoding to create valid random strings for passwords, and how to handle the output length when encoding changes the byte count.

2017

5 posts
emacs

Structure templates in Org mode

Discover Org mode's built-in structure templates that make inserting source blocks and other structural elements effortless. Learn how to use C-c C-, for modern template insertion or enable the legacy Easy Template system with <s<TAB> for quick shortcuts.

applescript

AppleScript and the GitHub API

Building a GitHub API client in AppleScript for OmniFocus integration. The script handles authentication and data extraction, though it has some efficiency limitations when fetching multiple values.

fish

Fish: notify me when you finish

A simple Fish shell hack to help you stay focused: get notified when long-running commands complete instead of getting distracted whilst waiting. Learn how to use Fish's CMD_DURATION variable to detect lengthy commands and send notifications when they finish.

git

Git: conditional configurations

Exploring Git's conditional includes feature and comparing it to my git-config-manager tool—whilst the native solution elegantly handles many use cases, there's still room for unique features.

blog

Deep in the black bashic

A humorous reflection on yak shaving: how wanting to write a blog post led me down a rabbit hole of infrastructure improvements—from EC2 to S3, Hakyll to Docker, and everything in between. Sometimes the journey is more interesting than the destination.

2016

6 posts
emacs

Being an org-mode addict

A personal reflection on my love-hate relationship with org-mode. Exploring how this deceptively simple outliner keeps drawing me back in, gradually imposing more complex features upon myself, whilst remaining an essential tool for organising my life.

shell

Errors in shell scripts

Learn how to write robust shell scripts that handle errors gracefully. This practical guide covers exit-on-error mode (set -e), signal traps for cleanup operations, and best practices for preventing corrupted states when commands fail.

emacs

flyspell-correct v0.1

Announcing flyspell-correct v0.1, featuring a complete package restructuring into separate core and interface modules, improved dependency management, and a new function for backwards spell-checking correction.

emacs

Emacs and Composability

A defence of Emacs' extensibility philosophy in response to discussions about Vim's composability. Exploring how Emacs' flexible architecture allows the community to implement any feature they value—including composability itself—whilst offering multiple paths to customisation.

emacs

flyspell-correct

Introducing flyspell-correct, a unified Emacs package that brings distraction-free spell-checking correction to your favourite completion framework. Learn how to correct misspelt words without leaving your current position, implement custom interfaces, and use rapid mode to fix multiple mistakes efficiently.

2015

3 posts
haskell

Cabal and executables

A historical look at solving Cabal Hell when installing Haskell executables. Learn how to use Cabal sandboxes to isolate dependencies and automate the process with custom Fish shell functions. Note: Stack and Nix-style builds have since made this approach obsolete.

fish

Make the Fish fly

A comprehensive review of the Fish shell after switching from Zsh. Discover how Fish's blazingly fast autocompletion, man page parsing, and sensible defaults provide an excellent out-of-the-box experience, plus the trade-offs you should consider regarding POSIX compatibility.

haskell

CanonicalPath v0.3.0.0

A summary of the third major release of CanonicalPath library, highlighting API changes, performance improvements, and enhanced testing infrastructure while maintaining compatibility with major Haskell package repositories.