Compare commits

..
3 Commits
Author SHA1 Message Date
Firehose Bot f6229ebf77 Drag and drop images for blog posts 2026-07-03 14:05:34 +01:00
Firehose Bot bcc973f9f7 correct dir-locals for dragging 2026-06-28 22:40:08 +02:00
Firehose Bot 98d0debb43 add file location 2026-06-28 10:16:02 +02:00
6 changed files with 40 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
((markdown-mode . ((qwan-markdown-attachment-dir . "app/priv/static/images/blog/2026"))))
+1
View File
@@ -8,3 +8,4 @@ app/priv/blog/engineering/2026/04-24-what-it-takes-to-get-started-with-the-pi-co
transcripts/ transcripts/
.pi/skills/demo/chrome .pi/skills/demo/chrome
.rodney/ .rodney/
.dir-locals.el
+3
View File
@@ -3,6 +3,9 @@
This project has a *zero defects policy*. This project has a *zero defects policy*.
When you are unsure about something, ALWAYS ask the user. When you are unsure about something, ALWAYS ask the user.
You run in a `nono` sandbox. Always ask the user to run commands that require privilege, like docker, sudo or package installation.
# Repository structure # Repository structure
This is an Elixir monorepo with two parts: This is an Elixir monorepo with two parts:
@@ -94,3 +94,7 @@ Some of my blogposts seem to help other people, which was the stated aim, and it
[Backing up your work to the internet](https://lkml.iu.edu/hypermail/linux/kernel/9607.2/0292.html) is great. I hope you enjoyed this yak shaving adventure. [Backing up your work to the internet](https://lkml.iu.edu/hypermail/linux/kernel/9607.2/0292.html) is great. I hope you enjoyed this yak shaving adventure.
The rabbit hole of emacs is deep, but removing friction from my workflows is not that onerous. And I needed to tinker with a small bit of code to recover from developing a more conceptual talk and a new workshop. The rabbit hole of emacs is deep, but removing friction from my workflows is not that onerous. And I needed to tinker with a small bit of code to recover from developing a more conceptual talk and a new workshop.
# Where is the code?
I forgot about that the first time around. For now it lives in [init.el](https://gitea.apps.sustainabledelivery.com/mostalive/firehose/src/branch/main/init.el) in the firehose repository. I want it to load when I open a markdown file in the repository. So it works on my other machines, and in the unlikely event that someone else uses firehose for their blog and uses Emacs to write posts, they should have the code to enjoy images too.
@@ -0,0 +1,29 @@
%{
title: "Removing a special cause of variation in small steps",
author: "Willem van den Ende",
tags: ~w(Emacs AI Pi.dev ),
description: "Next annoying variation in my blog writing workflow is adding images to a post. I wanted to add drag and drop. I let a coding agent generate something that almost worked, and then did the finishing touches by hand, simplifying the UX and code as I went.",
published: true
}
---
The next annoying variation in my blog writing workflow is adding images to a post. I wanted to add drag and drop. I let a coding agent generate something that almost worked, and then did the finishing touches by hand, simplifying the UX and code as I went, and learning more about writing tests and debugging in Emacs Lisp as I went.
Adding images is something I want to do in the flow, while looking at images. Thinking about where to store them is _accidental friction_ during the writing and edting process.
In [the previous post](/blog/engineering/an-example-would-be-handy-right-now) I made images visible (to me) while editing blog posts. Adding said images was still as annoying as it was in other static sites I write in. Including the QWAN slides repository. Images are not next to blog posts. I repeated that mistake here when creating Firehose. Fixing that is a bigger step. I wanted a small step, and even when images are next to blog posts, I still have to go into the terminal and copy files around. Often I want to add a screenshot, so I find the screenshot, then remember (aka look up) where images are stored, ~cp~ the image in the right place, and then make the link in markdown.
![Screenshot of Emacs, with a dropped image in a blog post in the left pane.](/images/blog/2026/drag-drop-image-emacs-markdown.png)
_Screenshot of working environment. Blog post with dropped image on the left, printed debug messages at the bottom, commit history on the right_.
I used [Pi.dev](https//pi.dev) to rummage through the scrapheap of Emacs lisp code on my machine. Programming by similarity is something LLMs can do. Since I found out recently that I can drop an image on an org-mode file and link it ("Attaching" org-mode calls that), I wanted the same in markdown. So I asked how that could work, and then had a function generated and wired into ~markdown-mode~ through a 'hook'. It almost worked, but not quite.
DeepseekV4-flash had generated a function with the usual LLM 'fallbacks'. What if the image does not exist? what if the directory does not exist?
I applied the usual 'fail fast' principle and deleted the fallbacks, replacing some of them with a call to ~error~. I am upskilling in Emacs Lisp as I go - I found a call to ~error~, looked up what it does: it throws an exception. I also wrote some tests, like in the previous blog post. More to get going. But as usual, it helped me simplify. The act of writing a test forces me to be very precise in what I want.
The generated code was, like much 'normal' Emacs Lisp from libraries very tied to the UI. I extracted a function to determine if something was an image. This was written as two variable assignments. Having worked with Haskell and Clojure, I would write code like that sometimes, and then extract to a function or a pipe later, once I understood the dependencies between the steps better. Having been on the road for the last week and now teaching others to work with coding agents in small steps, I am moving from _knowing what good looks like_ to _knowing what good feels like_. Intuition, judgement, guided by (bad ;-)) experience.
I won't bore you with the details of my code here. Suffice it to say, I have one excuse less to not publish posts. Screenshots are easily made, now they are also easy to publish. A small step etc.
Binary file not shown.

After

Width:  |  Height:  |  Size: 700 KiB