~hedy's blogroll - BlogFlockThe blogroll listed on my website.
https://home.hedy.dev/blogroll/2026-08-03T04:35:22.229ZBlogFlockSeirdy, erock, James' Coffee Blog, Sloum, Manuel Moreale RSS Feed, Protesilaos Stavrou: Master feed with all updates, Ploum.net, ~hedy, Baty.netAugust - James' Coffee Bloghttps://jamesg.blog/2026/08/02/august2026-08-02T00:00:00.000Z
<p>The sun shines through the silvery sky. I look up and around to see where blue might peek through the blanket that covers the sky. There is one space where I can see shades of blue through the silver. I think about how the sky invites me to look up, and then around: to be curious. What can I see today? I do this in all seasons and skies. On the warmest summer days, my eyes focus on the contrast between the green hills and the blue skies. On the coolest, clearest winter days, where the beauty of the clear sky warms the heart despite the cold, I search to see if I can spot a cloud. What can I see today?</p><p>A welcome cool air has been blowing over the last few days; the breeze has characterised my walks, the way it blows on my cheeks with every step and gust. I think about how much of walking is not only about what I see, but about what I feel: the temperature, the feeling of putting one step in front of another, the thoughts I have that make me smile or sing or curious or inquisitive; the feeling of joy from seeing and hearing animals – rabbits sitting still on open planes of grass, the calls of pigeons – and how they remind me I am one small part of the community that lives here.</p>
<!--kg-card-begin: html-->
<p style="text-align: center;">⁂ ⁂ ⁂</p>
<!--kg-card-end: html-->
<p>My morning was warmed by a message from a friend, a video that shared a fusion of musical styles I didn’t expect to find myself listening to. I thought about how much I love sending messages to people of things they find interesting, and how much I enjoy receiving them, too; tiny gifts that brighten a moment.</p>
<!--kg-card-begin: html-->
<p style="text-align: center;">⁂ ⁂ ⁂</p>
<!--kg-card-end: html-->
<p>Sitting here hours later under the silvery sky of evening, I think back to the morning – the cool breeze under the shade of fully-grown trees, the warm sun, the music – and smile. And I look around to evening, and how the green tees look compared to the white sky above; how the clouds look lighter than light. I look forward to whether I will hear the call of a pigeon this evening – Oh! one just started to call! – and what colour the sunset will be. The amber of yesterday? Or the gold of today?</p>
On the absolute other - Protesilaos Stavrou: Master feed with all updateshttps://protesilaos.com/books/2026-08-02-on-absolute-other/2026-08-02T00:00:00.000Z<p>A comment on the cosmic continuum.</p>
<hr />
<p>1 The other is that which differs from the self in quality or degree.</p>
<p>1.1 Other and self with equal qualities in equal degrees are identical.</p>
<p>1.2 The other and the self constitute the dissimilar.</p>
<p>1.3 The constitution of the dissimilar is the formation of a relationship.</p>
<p>2 The absolute is that which has no degree.</p>
<p>2.1 The absolute other is that which differs from the self in quality.</p>
<p>3 Where there is a common quality, the dissimilar is not absolute.</p>
<p>3.1 The absolute other is that which has no quality in common with the self.</p>
<p>4 To have quality or degree is to exhibit pattern.</p>
<p>4.1 Pattern is that which presences have in common, regardless of quality or degree.</p>
<p>4.2 The absolute other is that which has no pattern.</p>
<p>4.3 The absolute dissimilar cannot be constituted, for relationship involves connection and thus similarity.</p>
<p>5 That which is reasoned about is connectable.</p>
<p>5.1 The connectable is the similar, at least in having presence.</p>
<p>5.2 The absolute other cannot be reasoned about and has no presence.</p>
<p>5.3 For as long as it is thought, the absolute other is not the absolute other.</p>
<p>6 The abstract is the common in a multitude of presences.</p>
<p>6.1 The absolutely abstract is that which is discerned in all presences.</p>
<p>6.2 Presences and abstractions, self and other, are on a continuum of pattern.</p>
<p>6.3 There is no absolute other as its absolute abstraction cannot be connected to the continuum.</p>
<p>6.4 The self and the other are equal in having pattern.</p>
<p>7 Pattern has no other.</p>A moment with a very warm summer - Manuel Moreale RSS Feedhttps://manuelmoreale.com/@/page/epbuiu8m8pyhiyfz2026-08-01T16:05:00.000Z<p>It’s a very chilling 38°C outside at the moment. Those are at least 35 more that the max temperature this dog considers acceptable. But he’s doing his best to ride the heatwave, like the rest of us.</p>
<figure class="media-container" data-template="with"><div class="media-content"><img class="media-img" loading="lazy" src="https://manuelmoreale.com/media/pages/thoughts/a-moment-with-a-very-warm-summer/a5e83bf9cd-1785600291/img_4810.jpeg" style="aspect-ratio:1500 / 2000"></div></figure> <hr>
<p>Thank you for keeping RSS alive. You're awesome.</p>
<p><a href="mailto:hello@manuelmoreale.com">Connect via email</a> ::
<a href="https://manuelmoreale.com/guestbook">Sign my guestbook</a> ::
<a href="https://ko-fi.com/manuelmoreale">Support for 1$/month</a></p>Countryside; Blaugust - James' Coffee Bloghttps://jamesg.blog/2026/08/01/countryside-blaugust2026-08-01T00:00:00.000Z
<p>With the window open and the breeze flowing through, I hear the calls and songs of birds. A calling pigeon in particular stands out. I love the calls of pigeons in the evening. The sound reminds me of childhood, looking out the window, onto Nature. A flock of birds fly by as the occasional person strolls down the street. While the sun set a little while ago, day is still here.</p><p>A gust of wind moves the leaves across a big tree, and then the breeze settles down, and picks up again. I think about the cycles of Nature: a breeze comes, and another. I watch the leaves that seem to dance with the wind; therein, a beautiful rhythm. The songs of other birds come to the fore, ones I don’t recognise but whose music is nevertheless soothing.</p><hr/><p>My eyes are heavy. The day was busier than normal, occupied with studies and essay writing and time with friends and watching the joy of community pop up around the <a href="https://nerdgirlthoughts.game.blog/2026/07/15/blaugust-2026-is-coming/" rel="noreferrer">Blaugust</a> challenge. It got me thinking again about what it means to write on the web. When we write on the web, we can do so in a broader context: as part of the communities we are in. Seeing all the people come around for Blaugust motivated me to write this piece, and to try and participate. With this challenge, we’re all writing together. Whether I will participate often or not, I am unsure, but I do know that, at minimum, I am abundantly excited to read what my friends write.</p><p>In the spirit of sharing, while I can’t bring the fresh air of a Scottish countryside to you, I can bring part of what I hear and see; a snippet of time, for you, dear reader. That is this blog post – a little part of the Scottish countryside, as seen through my eyes, on this evening, August 1st.</p><hr/><p><a href="https://aggronaut.com/" rel="noreferrer"><em>Mark Temple (Belghast)</em></a><em>, who started Blaugust, passed away on July 2nd, 2026. I didn't know Mark, but I am sincerely grateful to him for starting a challenge that brings the web together. Projects like Blaugust bring light to the beautiful potential of the web. May he rest in peace.</em></p>
<a class="tag" href="https://aggronaut.com/">Mark Temple (Belghast)</a>
<a class="tag" href="https://nerdgirlthoughts.game.blog/2026/07/15/blaugust-2026-is-coming/">Blaugust</a>
Emacs live with @linkarzu on his workflow, Org capture, and projects (2026-08-01 22:20 Europe/Athens) - Protesilaos Stavrou: Master feed with all updateshttps://protesilaos.com/codelog/2026-08-01-emacs-live-linkarzu-projects/2026-08-01T00:00:00.000Z<p>In about 40 minutes from now I will do a live stream with Christian
Arzu from the @linkarzu channel on YouTube. The video will be
recorded.</p>
<p>The topic of our meeting revolves around how Christian uses NeoVim and
Kitty to handle sessions and write fleeting thoughts. Then we will try
to do something along those lines using built-in Emacs functionality.</p>
<p>Christian did a video a couple of days ago about this topic and here
is my extensive commentary on it, with points that are useful in
general: <a href="https://protesilaos.com/codelog/2026-07-31-re-linkarzu-what-i-need-from-emacs/">https://protesilaos.com/codelog/2026-07-31-re-linkarzu-what-i-need-from-emacs/</a>.</p>Friday, July 31, 2026 - Baty.nethttps://baty.net/journal/31Jul26/2026-07-31T09:54:59.000Z<figure><img src="https://baty.net/img/2026/20260731-desk-2007.webp" alt="My desk in 2007"><figcaption>My desk (2007)</figcaption></figure><p>Have you ever felt like you've simply run out of things to say?</p>
<p><a href="mailto:jack@baty.net?subject=[Baty.net] Re: Friday%2C%20July%2031%2C%202026">✍️ Reply by email</a></p>Emacs: tmr version 1.4.0 - Protesilaos Stavrou: Master feed with all updateshttps://protesilaos.com/codelog/2026-07-31-emacs-tmr-1-4-0/2026-07-31T00:00:00.000Z<p>TMR provides facilities for setting timers using a convenient
notation. Lots of commands are available to operate on timers, while
there also exists a tabulated view to display all timers in a nice
grid.</p>
<ul>
<li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">tmr</code></li>
<li>Official manual: <a href="https://protesilaos.com/emacs/tmr">https://protesilaos.com/emacs/tmr</a></li>
<li>Change log: <a href="https://protesilaos.com/emacs/tmr-changelog">https://protesilaos.com/emacs/tmr-changelog</a></li>
<li>Git repositories:
<ul>
<li>GitHub: <a href="https://github.com/protesilaos/tmr">https://github.com/protesilaos/tmr</a></li>
<li>GitLab: <a href="https://gitlab.com/protesilaos/tmr">https://gitlab.com/protesilaos/tmr</a></li>
</ul>
</li>
<li>Video demonstration: <a href="https://protesilaos.com/codelog/2026-01-19-emacs-timers-tmr-demo/">https://protesilaos.com/codelog/2026-01-19-emacs-timers-tmr-demo/</a></li>
<li>Backronym: TMR May Ring; Timer Must Run.</li>
</ul>
<p>Below are the release notes.</p>
<hr />
<h2>Version 1.4.0 on 2026-07-31</h2>
<p>TMR is an efficient package that has been stable for years. This new
version introduces some nice new features as well as several smaller
internal refinements.</p>
<h3>Create a timer that repeats</h3>
<p>The command <code class="language-plaintext highlighter-rouge">tmr-repeat</code> prompts for a duration, like the standard
<code class="language-plaintext highlighter-rouge">tmr</code> command but also asks for a number of times to repeat the given
timer. When called with a prefix argument (<code class="language-plaintext highlighter-rouge">C-u</code> with default
keybindings), <code class="language-plaintext highlighter-rouge">tmr-repeat</code> will also ask for a description for the new
timer and whether it should be acknowledged or not after all
repetitions have elapsed.</p>
<p>Thanks to Óscar Fuentes for contributing the original implementation
of <code class="language-plaintext highlighter-rouge">tmr-repeat</code> (with many extra changes/features by me). This was
done in pull request 16: <a href="https://github.com/protesilaos/tmr/pull/16">https://github.com/protesilaos/tmr/pull/16</a>.
Óscar has assigned copyright to the Free Software Foundation.</p>
<h3>Modify the repeat count of an existing timer</h3>
<p>The command <code class="language-plaintext highlighter-rouge">tmr-edit-repeat-count</code> prompts for an existing timer and
updates its repeat count. If the repeat count is set to <code class="language-plaintext highlighter-rouge">0</code>, then the
timer is no longer considered repeatable.</p>
<p>As with all commands that operate on existing timers, <code class="language-plaintext highlighter-rouge">tmr-edit-repeat-count</code>
automatically applies to the timer at point when called from inside
the tabulated list of timers (per <code class="language-plaintext highlighter-rouge">tmr-tabulated-view</code>).</p>
<p>Modifying a timer’s repeat count does not start a new timer. It simply
updates the relevant data. Use the command <code class="language-plaintext highlighter-rouge">tmr-clone</code> to start a new
timer using the data of an existing timer.</p>
<h3>The tabulated view has more columns and all of them can be adjusted</h3>
<p>The tabulated list of timers, which is typically produced by the
command <code class="language-plaintext highlighter-rouge">tmr-tabulated-view</code>, now has extra columns for the data that
pertains to repeatable timers.</p>
<p>Users who want to control which columns are displayed, and in what
order, can modify the user option <code class="language-plaintext highlighter-rouge">tmr-tabulated-columns</code>. Its
documentation covers the technicalities. The default value is to
display all columns.</p>
<h3>Completion metadata for the prompt that selects a timer</h3>
<p>Advanced users can now modify all the <code class="language-plaintext highlighter-rouge">completion-metadata</code> associated
with the prompt that reads/selects one among the existing timer
objects (the function is <code class="language-plaintext highlighter-rouge">tmr-read-timer</code>). The relevant variable is
<code class="language-plaintext highlighter-rouge">tmr-completion-metadata</code>. I am not providing this as a user option,
because regular users will anyway not be able to do much with it as it
involves custom functions.</p>
<h3>Timers in the completion prompt are sorted by end time</h3>
<p>The prompt for selecting a timer now sorts candidates by their end
time. The closest end time appears at the top.</p>
<p>This affects all commands that operate on a timer, such as
<code class="language-plaintext highlighter-rouge">tmr-edit-repeat-count</code>, <code class="language-plaintext highlighter-rouge">tmr-cancel</code>, and more.</p>
<p>In the past, there was no sorting whatsoever. Users who prefer that
style can add the following to their configuration:</p>
<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">setq</span> <span class="nv">tmr-completion-metadata</span>
<span class="p">(</span><span class="nb">list</span>
<span class="p">(</span><span class="nb">cons</span> <span class="ss">'category</span> <span class="ss">'tmr-timer</span><span class="p">)</span>
<span class="p">(</span><span class="nb">cons</span> <span class="ss">'display-sort-function</span> <span class="nf">#'</span><span class="nb">identity</span><span class="p">)</span> <span class="c1">; THIS IS THE RELEVANT PART</span>
<span class="p">(</span><span class="nb">cons</span> <span class="ss">'annotation-function</span> <span class="nf">#'</span><span class="nv">tmr-completion-annotate</span><span class="p">)))</span>
</code></pre></div></div>
<h3>Miscellaneous</h3>
<ul>
<li>
<p>The manual is easier to read. I have rewritten it to group commands
and user options under appropriate headings.</p>
</li>
<li>
<p>Lots of internal refinements to the code. I tweaks things to make
the code easier to maintain and contribute to.</p>
</li>
<li>
<p>Thanks to Pavlo Lysov for adding a small example to the manual about
using TMR hooks to send a custom notification on the macOS. This was
done in pull request 25: <a href="https://github.com/protesilaos/tmr/pull/25">https://github.com/protesilaos/tmr/pull/25</a>.
Pavlo does not need to assign copyright to the Free Software
Foundation.</p>
</li>
<li>
<p>Thanks to Carlos Pajuelo Rojo for refining an earlier version of the
function that produces a message about the repeat count of a given
timer (I have since made lots of changes on this and other fronts).
Carlos’ contribution is in pull request 20: <a href="https://github.com/protesilaos/tmr/pull/20">https://github.com/protesilaos/tmr/pull/20</a>.
The change is small, meaning that Carlos does not need to assign
copyright to the Free Software Foundation.</p>
</li>
<li>
<p>Thanks to f6p for use the appropriate face for the paused indicator
in the tabulated view. This was done in pull request 17:
<a href="https://github.com/protesilaos/tmr/pull/17">https://github.com/protesilaos/tmr/pull/17</a>. The change is small,
meaning that the author does not need to assign copyright to the
Free Software Foundation.</p>
</li>
</ul>Of Day - James' Coffee Bloghttps://jamesg.blog/2026/07/31/of-day-22026-07-31T00:00:00.000Z
<p>I hear the birds singing as I sit by the window and look out on the horizon. I like looking at all the colours of the sky in the moments after sunset, when ambers recede and the sky becomes ever more blue before night time. I hear the sound of my fingers typing on my keyboard, too: nature and words are my evening.</p><p>Nature and words are my evening, and so too is music. Moments ago I was playing on the piano, two songs I love but haven’t played in as long as I can remember. And one more song that I play often: one that always makes me feel free to improvise; one where the piano shines through the recording to which I listen while I play; one where I can be an accompaniment to the melody.</p><p>A cool breeze comes through the periphery of a window; I had a window open earlier while I played music, hoping that perhaps someone would hear a note or two and feel in wonder. I remember a story a friend told me about how welcomed their music was by a neighbour. I don’t know what it is about music that makes me feel confident: I don’t need to be perfect, as long as I can play a few notes that sound good. (If only, however, my singing voice were better – someone, guide me.)</p><p>My week has been full: of tasks and ideas, assignments and readings, writing and chatting. But now, sitting here, I am starting to wind down. I look out the window to see what I can see: the tiny birds dancing around the air (which reminds me that I saw two butterflies dancing together recently; I had to write that down); the sky taking on a new blue as the sun goes even further beyond the horizon; a canvas of green; of trees whose age I will never know and whose beauty grows by the day.</p>
Lattes - James' Coffee Bloghttps://jamesg.blog/2026/07/31/lattes2026-07-31T00:00:00.000Z
<p>I watched the movie "Valentines Day" (2010) for the first time today, which stars, among others, Taylor Swift. <a href="https://youtu.be/FBTIoyJ7aQ4?t=66" rel="noreferrer">The energy in this scene</a> (especially the enthusiastic and excited way in which the words are said, while Taylor carries a huge bear) <sup class="footnote-reference" id="f-1"><a href="https://jamesg.blog/longform-feed#1">1</a></sup> fills me with joy:</p><blockquote>[call out: "Save the Lattes!"]<br/>Taylor: They're putting lattes in the vending machines? Finally!<br/>Taylor: Robbie, I am so glad you are taking care of this.<br/>Robbie: You got it.<br/>Taylor: And, I like caramel lattes, just FYI.</blockquote><p>I am not a fan of caramel lattes, but I do love this scene!</p>
<div class="footnote-definition" id="1"><sup class="footnote-definition-label" id="f-2">1</sup>
<p>1m06s to 1m18s in the linked video.</p>
<a href="https://jamesg.blog/longform-feed#f-1">[↩]</a></div>
<a class="tag" href="https://jamesg.blog/longform-feed#1">1</a>
<a class="tag" href="https://jamesg.blog/longform-feed#f-1">[↩]</a>
<a class="tag" href="https://youtu.be/FBTIoyJ7aQ4?t=66">The energy in this scene</a>
Thursday, July 30, 2026 - Baty.nethttps://baty.net/journal/30Jul26/2026-07-30T14:56:10.000Z<figure><img src="https://baty.net/img/2026/20260730-coffee.webp" alt="Coffee cup on table"><figcaption>Coffee (2008)</figcaption></figure><p>I don't know what's worse: the whining about macOS from Mac users or the constant bickering between Linux users.</p>
<hr />
<p>Well, I've retired the saltwater tank. I just couldn't keep ahead of it. Bad algae, unwanted critters, water changes, chemicals, testing, etc. It got to the point where the effort I was putting in wasn't worth the pleasure I was getting out of it. It was a good four-year run.</p>
<hr />
<p><a href="mailto:jack@baty.net?subject=[Baty.net] Re: Thursday%2C%20July%2030%2C%202026">✍️ Reply by email</a></p>what the double-fork? - erock's devloghttps://bower.sh/what-the-double-fork2026-07-30T00:00:00.000Z<div role="list">
<div role="listitem">
<div class="listitem-bullet">•</div>
<div class="listitem-text">I built zmx as a multi-faceted learning exercise. I wanted to learn more about zig, posix, daemons, ptys, libghostty, and terminals. Creating a program that fits into my core dev toolchain was merely a side-effect. While researching about how to create a daemon, buried in the implementation of abduco, I discovered the double-fork.</div>
</div>
<div role="listitem">
<div class="listitem-bullet">•</div>
<a class="listitem-text" href="https://github.com/martanne/abduco/blob/8c32909a159aaa9484c82b71f05b7a73321eb491/abduco.c#L394-L402">abduco.c</a>
</div>
<div role="listitem">
<div class="listitem-bullet">•</div>
<div class="listitem-text">Hidden behind the double-fork technique is a cascade of terms and concepts that are fundamental to how linux manages processes. This post is me coming to the surface and intended to be a reminder when I read zmx and say "what the double-fork?"</div>
</div>
</div>
<h2 class="text-xl font-bold"> what is a daemon?</h2>
<div role="list" aria-label=" what is a daemon?">
<div role="listitem">
<div class="listitem-bullet">•</div>
<div class="listitem-text">A daemon belongs to a session that has no controlling terminal. In linux terms, it does not have a controlling terminal. For example, when backgrounding a process using ctrl-z+bg or {cmd} &, the session still has a controlling terminal which means it can control those background processes. This is not ideal for a daemon.</div>
</div>
</div>
<h2 class="text-xl font-bold"> how does fork work in a program?</h2>
<div role="list" aria-label=" how does fork work in a program?">
<div role="listitem">
<div class="listitem-bullet">•</div>
<div class="listitem-text">When using fork(2) in a program, it will create a child process in addition to still running the parent process that called fork. This was hard for me to grok when building out zmx. It is as-if the program clones itself at that exact line and both copies continue independently from there. Typically when creating a daemon you would use the child process of the fork and then kill the parent process.</div>
</div>
<div role="listitem">
<div class="listitem-bullet">•</div>
<pre class="listitem-text">
fork()
│
┌────────────┴────────────┐
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ PARENT │ │ CHILD │
│ PID = 42 │ │ PID = 55 │
│ PPID = 10 │ │ PPID = 42 │
│ │ │ │
│ (continues │ │ (continues │
│ from the │ │ from the │
│ fork point) │ │ fork point) │
└─────────────────┘ └─────────────────┘</pre>
</div>
<div role="listitem">
<div class="listitem-bullet">•</div>
<div class="listitem-text">Identical memory at fork point (copy-on-write)</div>
</div>
<div role="listitem">
<div class="listitem-bullet">•</div>
<div class="listitem-text">Identical open file descriptors (shared offsets)</div>
</div>
<div role="listitem">
<div class="listitem-bullet">•</div>
<div class="listitem-text">Different return value from fork():</div>
</div>
<div role="list">
<div role="listitem">
<div class="listitem-bullet">•</div>
<div class="listitem-text">parent → child's PID (55)</div>
</div>
<div role="listitem">
<div class="listitem-bullet">•</div>
<div class="listitem-text">child → 0</div>
</div>
</div>
<div role="listitem">
<div class="listitem-bullet">•</div>
<div class="listitem-text">Both run independently from here</div>
</div>
</div>
<h2 class="text-xl font-bold"> what is a session?</h2>
<div role="list" aria-label=" what is a session?">
<div role="listitem">
<div class="listitem-bullet">•</div>
<div class="listitem-text">In linux, a session is a container for process groups.</div>
</div>
<div role="listitem">
<div class="listitem-bullet">•</div>
<div class="listitem-text">Process groups are a container for processes that receives signals from the same terminal.</div>
</div>
<div role="listitem">
<div class="listitem-bullet">•</div>
<div class="listitem-text">At-most one process group in a session can be in the foreground.</div>
</div>
<div role="listitem">
<div class="listitem-bullet">•</div>
<div class="listitem-text">It receives signals and can write to the terminal.</div>
</div>
<div role="listitem">
<div class="listitem-bullet">•</div>
<div class="listitem-text">All other process groups in the session are background, and SIGTTOU/SIGTTIN will stop them if they write to or read from the terminal.</div>
</div>
</div>
<h2 class="text-xl font-bold"> what is a controlling terminal?</h2>
<div role="list" aria-label=" what is a controlling terminal?">
<div role="listitem">
<div class="listitem-bullet">•</div>
<div class="listitem-text">Only a session leader can create a controlling terminal for the session.</div>
</div>
<div role="listitem">
<div class="listitem-bullet">•</div>
<div class="listitem-text">A session can have at-most one controlling terminal.</div>
</div>
<div role="listitem">
<div class="listitem-bullet">•</div>
<div class="listitem-text">The session leader that opens the terminal becomes the controlling process.</div>
</div>
</div>
<h2 class="text-xl font-bold"> why double-fork?</h2>
<div role="list" aria-label=" why double-fork?">
<div role="listitem">
<div class="listitem-bullet">•</div>
<div class="listitem-text">When launching a daemon, you normally set the child process of the fork to be the session leader via setsid() which creates a new session that removes the current controlling terminal but creates the authority to grab a new one. This is important because we don't want a controlling terminal for our daemon or else our daemon could receive signals to shutdown when the controlling terminal closes.</div>
</div>
<div role="listitem">
<div class="listitem-bullet">•</div>
<div class="listitem-text">However, if the first fork's child process is also the daemon process, then it's technically possible for the daemon to open a terminal device (e.g. open("/dev/console", O_RDWR)) and then it would acquire a controlling terminal! A controlling terminal would expose the daemon to terminal-generated signals (e.g. SIGINT) or SIGHUP from terminal disconnect which could kill the daemon.</div>
</div>
<div role="listitem">
<div class="listitem-bullet">•</div>
<div class="listitem-text">The first fork isn't arbitrary either: setsid() fails with EPERM if the caller is already a process group leader, which a process launched directly from a shell typically is. The first fork produces a child guaranteed not to be a group leader, so setsid() will succeed. By forking a second time, the grandchild process (the daemon) is not the session leader. Per POSIX, only a process that is the session leader can acquire a controlling terminal.</div>
</div>
<div role="listitem">
<div class="listitem-bullet">•</div>
<div class="listitem-text">Apparently this is "a bit paranoid," and on Linux it is arguable since a session leader only acquires a controlling terminal under implementation-defined conditions. But the double-fork is the portable way to guarantee the daemon can never acquire one, regardless of how a given POSIX implementation behaves. So we baked it into zmx.</div>
</div>
<div role="listitem">
<div class="listitem-bullet">•</div>
<pre class="listitem-text">
PID=42 SID=10 PGID=10 ← original (PG leader, has tty)
│
│ fork #1
├──────────┐
│ exit │ PID=55 SID=10 PGID=10 (not a PG leader)
✝ │
│ setsid()
▼
PID=55 SID=55 PGID=55 (session leader, no tty)
│
│ fork #2
├──────────┐
│ exit │ PID=73 SID=55 PGID=55
✝ │ PID≠SID → can't get a tty
▼
DAEMON ✓</pre>
</div>
</div>
<h2 class="text-xl font-bold"> beyond the double-fork</h2>
<div role="list" aria-label=" beyond the double-fork">
<div role="listitem">
<div class="listitem-bullet">•</div>
<div class="listitem-text">The double-fork detaches the daemon from any controlling terminal, but that's only one piece of a robust daemon. A daemon also needs to clean up everything it inherited from the parent that launched it like file descriptors, working directory, and standard streams.</div>
</div>
<div role="listitem">
<div class="listitem-bullet">•</div>
<div class="listitem-text">In zmx, after the second fork, the daemon does two more things:</div>
</div>
<div role="list">
<div role="listitem">
<div class="listitem-bullet">•</div>
<div class="listitem-text">First, it redirects stdin, stdout, and stderr to /dev/null via dup2(2). This is critical: if the parent was launched by a test harness like bats, those file descriptors might be pipes. As long as the daemon holds the write end open, the harness will hang waiting for EOF. Redirecting to /dev/null closes that loop.</div>
</div>
<div role="listitem">
<div class="listitem-bullet">•</div>
<div class="listitem-text">Second, it closes all inherited file descriptors from 3 up to 64 (skipping any that the caller explicitly wants to keep, like a server socket). This releases resources the daemon doesn't need and prevents the same hang on higher-numbered FDs.</div>
</div>
</div>
<div role="listitem">
<div class="listitem-bullet">•</div>
<pre class="listitem-text">
[1] fork() ── child is not a PG leader
[2] setsid() ── new session, drop tty, become leader
[3] fork() ── daemon is not the leader, can't get tty
─────────── double-fork ends, cleanup begins ───────────
[4] dup2 /dev/null ── stdin/stdout/stderr → /dev/null
[5] close fds 3-64 ── release inherited resources</pre>
</div>
</div>
<h2 class="text-xl font-bold"> refs</h2>
<div role="list" aria-label=" refs">
<div role="listitem">
<div class="listitem-bullet">•</div>
<a class="listitem-text" href="https://github.com/neurosnap/zmx/blob/0b44313223d97ea32c0a06a71c824cb9f1fadaa6/src/daemonize.zig#L166">zmx/daemonize.zig</a>
</div>
<div role="listitem">
<div class="listitem-bullet">•</div>
<a class="listitem-text" href="https://github.com/neurosnap/zmx/blob/0b44313223d97ea32c0a06a71c824cb9f1fadaa6/src/daemonize.zig#L199-L246">zmx/daemonize.zig (stdio + fd cleanup)</a>
</div>
<div role="listitem">
<div class="listitem-bullet">•</div>
<a class="listitem-text" href="https://man7.org/linux/man-pages/man2/fork.2.html">fork(2)</a>
</div>
<div role="listitem">
<div class="listitem-bullet">•</div>
<a class="listitem-text" href="http://www.faqs.org/faqs/unix-faq/programmer/faq/">1.7 How do I get my program to act like a daemon?</a>
</div>
<div role="listitem">
<div class="listitem-bullet">•</div>
<a class="listitem-text" href="https://stackoverflow.com/a/16317668">Why fork twice? (StackOverflow)</a>
</div>
<div role="listitem">
<div class="listitem-bullet">•</div>
<a class="listitem-text" href="https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap11.html#tag_11_01_03">The Controlling Terminal</a>
</div>
</div>Poem: Hymn to the rock (Ύμνος στον βράχο) - Protesilaos Stavrou: Master feed with all updateshttps://protesilaos.com/poems/2026-07-30-hymn-rock/2026-07-30T00:00:00.000Z<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>This rock I consecrate
recognising that it too
partakes of cosmic oneness
I open my hands towards the sky
to fill with energy
and I look around me
so that I may remember
that I too am
a member of the whole
and that as a passenger
on this earth
I have a duty to leave behind
a world that will receive
those who shall arrive
</code></pre></div></div>
<hr />
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Τον βράχο αυτό καθιερώνω
αναγνωρίζοντας πως κι αυτός
μετέχει της κοσμικής ενότητας
Ανοίγω τα χέρια μου προς τον ουρανό
να γεμίσω ενέργεια
και κοιτάζω γύρω μου
έστω να θυμηθώ
πως είμαι κι εγώ
μέρος του όλου
και πως ως περαστικός
σε αυτήν την γη
έχω καθήκον να αφήσω πίσω μου
έναν κόσμο που θα δεχτεί
αυτούς που θα'ρθουν
</code></pre></div></div>the writer’s mind - James' Coffee Bloghttps://jamesg.blog/2026/07/30/the-writers-mind2026-07-30T00:00:00.000Z
<p>making notes and reviewing quotes,<br/>collected from day and night:<br/>here, there are stories.</p><p>i revel in observing, and<br/>in place-<br/>making.<br/>where am i? how do i feel?<br/>what does this mean to me?</p><p>i think of the melody of words<br/>their cadence and shape and tense<br/>and from all, i feel:.<br/>from words, wonder;<br/><em>with words, wonder.</em></p>
The Dink (2026) ★★★ - Baty.nethttps://baty.net/posts/2026/07/the-dink-2026/2026-07-29T20:46:12.000Z<figure><img src="https://baty.net/img/2026/20260729-the-dink-card.webp" alt="The Dink movie poster"></figure><p>I wanted it to be better. It dragged a few chuckles out of me. I gave it an extra star because I love Mary Steenburgen.</p>
<p><a href="mailto:jack@baty.net?subject=[Baty.net] Re: The%20Dink%20(2026)%20%E2%98%85%E2%98%85%E2%98%85">✍️ Reply by email</a></p>Wednesday, July 29, 2026 - Baty.nethttps://baty.net/journal/29Jul26/2026-07-29T10:56:32.000Z<figure><img src="https://baty.net/img/2026/20260729-dogs.webp" alt="3 sleeping dogs"><figcaption>Remember that time I had 3 dogs?</figcaption></figure><p><a href="https://mojopad.app/">MojoPad</a> is kind of amazing. I've been following along for a while now and boy howdy the updates are coming fast and furious. Perhaps <em>too</em> fast. I mean, he's shipping major updates every few days. The app is certainly being vibe coded. In fact, I'm starting to notice that nearly everything about the project is LLM-generated. The release notes, obviously. The website with its almost cartoonish illustrations is off-putting. More and more I'm thinking even the developer's replies in the forums are often AI-written. It makes me uncomfortable. I could probably overlook all this, but this morning I imported part of my old Obsidian vault (1,000+ pages) and MojoPad's performance slowed to a crawl. I'll keep an eye on things, but for now I think I'll pass.</p>
<hr />
<p><a href="https://franktisellano.github.io/datatype/">Datatype — variable font that turns text into charts</a> is kind of wild. (via <a href="https://social.lol/@ctietze@mastodon.social/117002655992157543">Christian Tietze</a>)</p>
<hr />
<p>Why haven't I been using this blog's <a href="https://baty.net/notes">Notes</a> for little posts like these? Maybe because they are currently sent to Mastodon automatically and sometimes I feel like keeping everything here.</p>
<hr />
<p><a href="https://github.com/jchultarsky/mirador">Mirador</a> is fun. It's "An opinionated personal dashboard for your terminal — world clocks, calendar and agenda, weather, tasks, notes, markets and live system metrics in a tab you leave open all day"</p>
<hr />
<p><a href="mailto:jack@baty.net?subject=[Baty.net] Re: Wednesday%2C%20July%2029%2C%202026">✍️ Reply by email</a></p>On “Missives From” - Manuel Moreale RSS Feedhttps://manuelmoreale.com/@/page/bw1nnzlihuupj4zh2026-07-29T10:40:00.000Z<p>There is nothing I hate more than doing self-promotion. The idea of talking about something I’m doing, I’ve done, or I'm going to do makes my skin crawl. But the opposite, promoting things other people are doing—especially friends—fills me with so much joy that I’ll never miss out on the opportunity of doing it.</p>
<p>And that’s why I’m excited to let you know that my longtime friend <a href="https://mattiacompagnucci.com/?utm_source=manuelmoreale.com">Mattia</a> is about to embark on another of his trips, this time touching Taiwan, South Korea, and Japan, and as usual he’s going to share thoughts and pictures on his newsletter <a href="https://mattiacompagnucci.com/missives-from/?utm_source=manuelmoreale.com"><em>“Missives From”</em></a>. I’m sure he’ll figure out a way to get himself into some sketchy situation since he seems to have a knack for that.</p>
<p>So, <a href="https://mattiacompagnucci.com/missives-from/?utm_source=manuelmoreale.com"><em>“Missives From”</em> Taiwan, South Korea, and Japan</a>, first newsletter dropping sometime this week (maybe). Go sign up and tell Mattia Hi and let him know I sent you.</p> <hr>
<p>Thank you for keeping RSS alive. You're awesome.</p>
<p><a href="mailto:hello@manuelmoreale.com">Connect via email</a> ::
<a href="https://manuelmoreale.com/guestbook">Sign my guestbook</a> ::
<a href="https://ko-fi.com/manuelmoreale">Support for 1$/month</a></p>Emacs: default minibuffer completions overview (Emacs 31) - Protesilaos Stavrou: Master feed with all updateshttps://protesilaos.com/codelog/2026-07-29-emacs-default-minibuffer-completion-overview/2026-07-29T00:00:00.000Z<p>In this video I provide an overview of the default interface for minibuffer completions in Emacs. This is an interface that has been improved considerably over the years. In Emacs version 31, this interface gets some nice new features which make it even more appealing to use.</p>
<p>Below is the article I prepared for this video, with all the code samples.</p>
<h2>Table of Contents</h2>
<ol>
<li><a href="#orga3f5b35">The default settings are usable but inconvenient</a></li>
<li><a href="#orgbc1d3e6">Tweaks for a more refined default completion interface</a></li>
<li><a href="#org5532eef">The <code class="language-plaintext highlighter-rouge">completion-category-overrides</code> for maximum control</a>
<ol>
<li><a href="#org290e045">How to find the completion category</a></li>
<li><a href="#orgb29882c">Completion categories and all the other <code class="language-plaintext highlighter-rouge">completion-metadata</code></a></li>
</ol>
</li>
<li><a href="#orgbc5c84f">The default completions and related packages</a></li>
</ol>
<p>The core Emacs infrastructure for completions is quite capable. In a previous entry I covered the technicalities of in-buffer completion, the <code class="language-plaintext highlighter-rouge">completion-at-point-functions</code>, and related packages/modes like <code class="language-plaintext highlighter-rouge">corfu</code>, <code class="language-plaintext highlighter-rouge">company</code>, <code class="language-plaintext highlighter-rouge">completion-preview-mode</code>: <a href="https://protesilaos.com/codelog/2026-07-19-emacs-completion-at-point-functions/">https://protesilaos.com/codelog/2026-07-19-emacs-completion-at-point-functions/</a>.</p>
<p>For this article I will focus on the default user interface of completions as it is done through the minibuffer. Minibuffer completion is performed whenever we type, with default keybindings, <code class="language-plaintext highlighter-rouge">M-x</code> (<code class="language-plaintext highlighter-rouge">execute-extended-command</code>), <code class="language-plaintext highlighter-rouge">C-x b</code> (<code class="language-plaintext highlighter-rouge">switch-to-buffer</code>), <code class="language-plaintext highlighter-rouge">C-x C-f</code> (<code class="language-plaintext highlighter-rouge">find-file</code>), among many others.</p>
<p><a id="orga3f5b35"></a></p>
<h2>The default settings are usable but inconvenient</h2>
<p>They are designed to work like TAB-completion in a standard Bash shell. Insert some text, press <code class="language-plaintext highlighter-rouge">TAB</code>, and Emacs will interpret your input as a prefix to be completed against available candidates.</p>
<p>The <code class="language-plaintext highlighter-rouge">*Completions*</code> buffer pops up. At the top, it informs you about the keybindings you can press to select a candidate. The candidates themselves are presented in rows and columns.</p>
<p>If you type some extra characters or otherwise modify your initial input, the <code class="language-plaintext highlighter-rouge">*Completions*</code> buffer will not reflect the new list of candidates. To calculate that anew you have to press <code class="language-plaintext highlighter-rouge">TAB</code> again. As such, the <code class="language-plaintext highlighter-rouge">*Completions*</code> are static by default.</p>
<p><a id="orgbc1d3e6"></a></p>
<h2>Tweaks for a more refined default completion interface</h2>
<p>Lots of small refinements have been made over the years to expand what we can do with the <code class="language-plaintext highlighter-rouge">*Completions*</code> buffer (at least some are inspired by an old package of mine called <code class="language-plaintext highlighter-rouge">mct</code>). Here is the essence of my preferred configuration, with comments:</p>
<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">use-package</span> <span class="nv">minibuffer</span>
<span class="ss">:ensure</span> <span class="no">nil</span>
<span class="ss">:config</span>
<span class="c1">;; Do not inform me about the default keybindings to select a</span>
<span class="c1">;; candidate.</span>
<span class="p">(</span><span class="k">setq</span> <span class="nv">completion-show-help</span> <span class="no">nil</span><span class="p">)</span>
<span class="c1">;; Do not print messages in the echo area that pertain to</span>
<span class="c1">;; completion---those are distracting.</span>
<span class="p">(</span><span class="k">setq</span> <span class="nv">completion-show-inline-help</span> <span class="no">nil</span><span class="p">)</span>
<span class="c1">;; Show useful annotations in various minibuffer prompts (though the</span>
<span class="c1">;; `marginalia' package greatly improves this).</span>
<span class="p">(</span><span class="k">setq</span> <span class="nv">completions-detailed</span> <span class="no">t</span><span class="p">)</span>
<span class="c1">;; Do not use rows and columns for completions: a single vertical</span>
<span class="c1">;; list is easier to follow.</span>
<span class="p">(</span><span class="k">setq</span> <span class="nv">completions-format</span> <span class="ss">'one-column</span><span class="p">)</span>
<span class="c1">;; Put an upper limit to the Completions window, so that it does not</span>
<span class="c1">;; disorient me.</span>
<span class="p">(</span><span class="k">setq</span> <span class="nv">completions-max-height</span> <span class="mi">12</span><span class="p">)</span>
<span class="c1">;; Rely on previous inputs to surface candidates towards the top of</span>
<span class="c1">;; the list (enable the built-in `savehist-mode' to persist</span>
<span class="c1">;; history).</span>
<span class="p">(</span><span class="k">setq</span> <span class="nv">completions-sort</span> <span class="ss">'historical</span><span class="p">)</span>
<span class="c1">;; Show the Completions buffer if I hit TAB but there is no unique match yet.</span>
<span class="p">(</span><span class="k">setq</span> <span class="nv">completion-auto-help</span> <span class="no">t</span><span class="p">)</span>
<span class="c1">;; Never switch to the Completions buffer when I type TAB, because I</span>
<span class="c1">;; want to select candidates while the minibuffer is still in focus,</span>
<span class="c1">;; per `minibuffer-visible-completions'. This has the advantage of</span>
<span class="c1">;; auto-updating the completions as I type.</span>
<span class="p">(</span><span class="k">setq</span> <span class="nv">completion-auto-select</span> <span class="no">nil</span>
<span class="nv">minibuffer-visible-completions</span> <span class="no">t</span><span class="p">)</span>
<span class="c1">;; Those two are also relevant for the `completion-category-overrides', which I</span>
<span class="c1">;; cover elsewhere in this article.</span>
<span class="p">(</span><span class="k">setq</span> <span class="nv">completion-eager-display</span> <span class="no">t</span><span class="p">)</span>
<span class="p">(</span><span class="k">setq</span> <span class="nv">completion-eager-update</span> <span class="no">t</span><span class="p">))</span>
</code></pre></div></div>
<p><a id="org5532eef"></a></p>
<h2>The <code class="language-plaintext highlighter-rouge">completion-category-overrides</code> for maximum control</h2>
<p>The user option <code class="language-plaintext highlighter-rouge">completion-category-overrides</code> is for those power users who demand complete control of how the completions behave. Concretely, we target the metadata key of the <code class="language-plaintext highlighter-rouge">completion-category</code> to tell Emacs which <code class="language-plaintext highlighter-rouge">completion-styles</code> and other settings to use specifically for it. For example, we might want to have something like this:</p>
<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">;; Pattern-matching styles to interpret our input in every context.</span>
<span class="p">(</span><span class="k">setq</span> <span class="nv">completion-styles</span> <span class="o">'</span><span class="p">(</span><span class="nv">basic</span> <span class="nv">substring</span> <span class="nv">initials</span> <span class="nv">flex</span><span class="p">))</span>
<span class="c1">;; An exception to the above for the `file' category, where we</span>
<span class="c1">;; specifically want to use the `partial-completion' style:</span>
<span class="p">(</span><span class="k">setq</span> <span class="nv">completion-category-overrides</span>
<span class="o">'</span><span class="p">((</span><span class="nv">file</span> <span class="o">.</span> <span class="p">((</span><span class="nv">styles</span> <span class="nv">partial-completion</span><span class="p">)))))</span>
</code></pre></div></div>
<p><a id="org290e045"></a></p>
<h3>How to find the completion category</h3>
<p>I am not aware of a built-in way to do this, so I have my own function:</p>
<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">prot-common-completion-category</span> <span class="p">()</span>
<span class="s">"Return completion category."</span>
<span class="p">(</span><span class="nv">when-let*</span> <span class="p">((</span><span class="nv">window</span> <span class="p">(</span><span class="nv">active-minibuffer-window</span><span class="p">)))</span>
<span class="p">(</span><span class="nv">with-current-buffer</span> <span class="p">(</span><span class="nv">window-buffer</span> <span class="nv">window</span><span class="p">)</span>
<span class="p">(</span><span class="nv">completion-metadata-get</span>
<span class="p">(</span><span class="nv">completion-metadata</span> <span class="p">(</span><span class="nv">buffer-substring-no-properties</span>
<span class="p">(</span><span class="nv">minibuffer-prompt-end</span><span class="p">)</span>
<span class="p">(</span><span class="nb">max</span> <span class="p">(</span><span class="nv">minibuffer-prompt-end</span><span class="p">)</span> <span class="p">(</span><span class="nv">point</span><span class="p">)))</span>
<span class="nv">minibuffer-completion-table</span>
<span class="nv">minibuffer-completion-predicate</span><span class="p">)</span>
<span class="ss">'category</span><span class="p">))))</span>
</code></pre></div></div>
<p>To use this, you need to enable recursive minibuffers, which means that you want to be able to bring up a new minibuffer prompt that will affect the one that was already open. Here are the settings I use for that:</p>
<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">use-package</span> <span class="nv">minibuffer</span>
<span class="ss">:ensure</span> <span class="no">nil</span>
<span class="ss">:config</span>
<span class="p">(</span><span class="k">setq</span> <span class="nv">read-minibuffer-restore-windows</span> <span class="no">nil</span><span class="p">)</span>
<span class="p">(</span><span class="k">setq</span> <span class="nv">enable-recursive-minibuffers</span> <span class="no">t</span><span class="p">)</span>
<span class="p">(</span><span class="nv">minibuffer-depth-indicate-mode</span> <span class="mi">1</span><span class="p">))</span>
</code></pre></div></div>
<p>With that in place, whenever you want to know the completion category of a prompt, focus the minibuffer and type <code class="language-plaintext highlighter-rouge">M-:</code> (<code class="language-plaintext highlighter-rouge">eval-expression</code>). In the new prompt input <code class="language-plaintext highlighter-rouge">(prot-common-completion-category)</code> and press <code class="language-plaintext highlighter-rouge">RET</code>. In the echo area you will either get <code class="language-plaintext highlighter-rouge">nil</code> or the symbol of the category.</p>
<p>[ We can, of course, do this differently such as by defining a command that we bind to a key to ultimately copy the completion category to the <code class="language-plaintext highlighter-rouge">kill-ring</code>, but I wanted to keep it generic. ]</p>
<p>Now you can write more entries for the <code class="language-plaintext highlighter-rouge">completion-category-overrides</code>.</p>
<p><a id="orgb29882c"></a></p>
<h3>Completion categories and all the other <code class="language-plaintext highlighter-rouge">completion-metadata</code></h3>
<p>When we modify the <code class="language-plaintext highlighter-rouge">completion-category-overrides</code> we can set the variable <code class="language-plaintext highlighter-rouge">completion-styles</code> as well as every single function specified by the documentation of function <code class="language-plaintext highlighter-rouge">completion-metadata</code>. Here is the anatomy of an override:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(CATEGORY . ((styles STYLES)
(eager-update . BOOLEAN)
(eager-display . BOOLEAN)
(group-function . GROUP-FN)
(annotation-function . ANNOTATION-FN)
(affixation-function . AFFIXATION-FN)
(display-sort-function . SORT-FN)))
</code></pre></div></div>
<ul>
<li><code class="language-plaintext highlighter-rouge">STYLES</code> is one or more <code class="language-plaintext highlighter-rouge">completion-styles</code>.</li>
<li><code class="language-plaintext highlighter-rouge">BOOLEAN</code> is <code class="language-plaintext highlighter-rouge">nil</code> or <code class="language-plaintext highlighter-rouge">t</code>.</li>
<li><code class="language-plaintext highlighter-rouge">*-FN</code> are functions as explained by <code class="language-plaintext highlighter-rouge">completion-metadata</code>.</li>
</ul>
<p>A concrete yet basic example, with comments:</p>
<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">;; To set `eager-display' and `eager-update' in the overrides, we need</span>
<span class="c1">;; to have these variables configured accordingly:</span>
<span class="p">(</span><span class="k">setq</span> <span class="nv">completion-eager-display</span> <span class="ss">'auto</span>
<span class="nv">completion-eager-update</span> <span class="ss">'auto</span><span class="p">)</span>
<span class="p">(</span><span class="k">setq</span> <span class="nv">completion-category-overrides</span>
<span class="o">'</span><span class="p">((</span><span class="nv">file</span> <span class="o">.</span> <span class="p">((</span><span class="nv">styles</span> <span class="nv">partial-completion</span><span class="p">)</span>
<span class="c1">;; Do not automatically pop up the Completions buffer</span>
<span class="c1">;; because, for example, we have private files we do</span>
<span class="c1">;; not want to show while doing a live stream.</span>
<span class="p">(</span><span class="nv">eager-display</span> <span class="o">.</span> <span class="no">nil</span><span class="p">)</span>
<span class="c1">;; But if the Completions buffer is already</span>
<span class="c1">;; displayed, do update it as you type.</span>
<span class="p">(</span><span class="nv">eager-update</span> <span class="o">.</span> <span class="no">t</span><span class="p">)))</span>
<span class="c1">;; For buffers we do not care about showing them, so display</span>
<span class="c1">;; them outright and automatically update them as you type.</span>
<span class="p">(</span><span class="nv">buffer</span> <span class="o">.</span> <span class="p">((</span><span class="nv">eager-display</span> <span class="o">.</span> <span class="no">t</span><span class="p">)</span>
<span class="p">(</span><span class="nv">eager-update</span> <span class="o">.</span> <span class="no">t</span><span class="p">)))</span>
<span class="c1">;; For this I want the completion styles to either be</span>
<span class="c1">;; interpreted as a prefix or a substring, but I do not want,</span>
<span class="c1">;; for example, the flex style here. And then I want the same</span>
<span class="c1">;; behaviour as for the buffer category.</span>
<span class="p">(</span><span class="nv">imenu</span> <span class="o">.</span> <span class="p">((</span><span class="nv">styles</span> <span class="nv">basic</span> <span class="nv">substring</span><span class="p">)</span>
<span class="p">(</span><span class="nv">eager-display</span> <span class="o">.</span> <span class="no">t</span><span class="p">)</span>
<span class="p">(</span><span class="nv">eager-update</span> <span class="o">.</span> <span class="no">t</span><span class="p">)))))</span>
</code></pre></div></div>
<p>And here is an advanced example with all the custom functions:</p>
<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">prot-minibuffer-file-group</span> <span class="p">(</span><span class="nv">file</span> <span class="nv">transform</span><span class="p">)</span>
<span class="s">"Return FILE group name unless TRANSFORM is non-nil."</span>
<span class="p">(</span><span class="nb">cond</span>
<span class="c1">;; Here we have the power to completely change how candidates look</span>
<span class="c1">;; under a group, such as to remove a prefix. But I just want the</span>
<span class="c1">;; group title and otherwise want to keep the candidates as they</span>
<span class="c1">;; are by default.</span>
<span class="p">(</span><span class="nv">transform</span> <span class="nv">file</span><span class="p">)</span>
<span class="c1">;; Create a group for directories and give it the group title</span>
<span class="c1">;; "Directories".</span>
<span class="p">((</span><span class="nv">string-suffix-p</span> <span class="s">"/"</span> <span class="nv">file</span><span class="p">)</span> <span class="s">"Directories"</span><span class="p">)</span>
<span class="c1">;; Create a group for dotfiles and give it the group title</span>
<span class="c1">;; "Hidden files".</span>
<span class="p">((</span><span class="nv">string-prefix-p</span> <span class="s">"."</span> <span class="nv">file</span><span class="p">)</span> <span class="s">"Hidden files"</span><span class="p">)</span>
<span class="c1">;; Then group every other file by its file extension and name the</span>
<span class="c1">;; corresponding group like ".org", ".txt.", and so on.</span>
<span class="p">((</span><span class="nv">when-let*</span> <span class="p">((</span><span class="nv">extension</span> <span class="p">(</span><span class="nv">file-name-extension</span> <span class="nv">file</span> <span class="ss">:include-dot</span><span class="p">))</span>
<span class="p">(</span><span class="nv">_</span> <span class="p">(</span><span class="nb">not</span> <span class="p">(</span><span class="nv">string-blank-p</span> <span class="nv">extension</span><span class="p">))))</span>
<span class="nv">extension</span><span class="p">))</span>
<span class="c1">;; In every other case, just group the candidates under the "Other"</span>
<span class="c1">;; heading.</span>
<span class="p">(</span><span class="no">t</span> <span class="s">"Other"</span><span class="p">)))</span>
<span class="p">(</span><span class="nb">defun</span> <span class="nv">prot-minibuffer-file-sort</span> <span class="p">(</span><span class="nv">files</span><span class="p">)</span>
<span class="s">"Sort FILES to have directories first and the rest alphabetically.
Omit the .. directory from FILES."</span>
<span class="c1">;; Remove the implicit files from the candidates.</span>
<span class="p">(</span><span class="k">setq</span> <span class="nv">files</span> <span class="p">(</span><span class="nb">delete</span> <span class="s">"../"</span> <span class="nv">files</span><span class="p">))</span>
<span class="c1">;; Sort them alphabetically.</span>
<span class="p">(</span><span class="k">setq</span> <span class="nv">files</span> <span class="p">(</span><span class="nv">minibuffer-sort-alphabetically</span> <span class="nv">files</span><span class="p">))</span>
<span class="c1">;; Now put the directories before the rest.</span>
<span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">directory-p</span> <span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="nv">file</span><span class="p">)</span> <span class="p">(</span><span class="nv">string-suffix-p</span> <span class="s">"/"</span> <span class="nv">file</span><span class="p">))))</span>
<span class="p">(</span><span class="nb">nconc</span> <span class="p">(</span><span class="nv">seq-filter</span> <span class="nv">directory-p</span> <span class="nv">files</span><span class="p">)</span>
<span class="p">(</span><span class="nv">seq-remove</span> <span class="nv">directory-p</span> <span class="nv">files</span><span class="p">))))</span>
<span class="c1">;; To set `eager-display' and `eager-update' in the overrides, we need</span>
<span class="c1">;; to have these variables configured accordingly:</span>
<span class="p">(</span><span class="k">setq</span> <span class="nv">completion-eager-display</span> <span class="ss">'auto</span>
<span class="nv">completion-eager-update</span> <span class="ss">'auto</span><span class="p">)</span>
<span class="p">(</span><span class="k">setq</span> <span class="nv">completion-category-overrides</span>
<span class="o">'</span><span class="p">((</span><span class="nv">file</span> <span class="o">.</span> <span class="p">((</span><span class="nv">styles</span> <span class="nv">partial-completion</span><span class="p">)</span>
<span class="p">(</span><span class="nv">eager-display</span> <span class="o">.</span> <span class="no">nil</span><span class="p">)</span>
<span class="p">(</span><span class="nv">eager-update</span> <span class="o">.</span> <span class="no">t</span><span class="p">)</span>
<span class="c1">;; I am not including examples for the annotation and</span>
<span class="c1">;; affixation functions because those are more</span>
<span class="c1">;; involved and you anyway get the point.</span>
<span class="p">(</span><span class="nv">group-function</span> <span class="o">.</span> <span class="nv">prot-minibuffer-file-group</span><span class="p">)</span>
<span class="p">(</span><span class="nv">display-sort-function</span> <span class="o">.</span> <span class="nv">prot-minibuffer-file-sort</span><span class="p">)))</span>
<span class="p">(</span><span class="nv">buffer</span> <span class="o">.</span> <span class="p">((</span><span class="nv">eager-display</span> <span class="o">.</span> <span class="no">t</span><span class="p">)</span>
<span class="p">(</span><span class="nv">eager-update</span> <span class="o">.</span> <span class="no">t</span><span class="p">)))</span>
<span class="p">(</span><span class="nv">imenu</span> <span class="o">.</span> <span class="p">((</span><span class="nv">styles</span> <span class="nv">basic</span> <span class="nv">substring</span><span class="p">)</span>
<span class="p">(</span><span class="nv">eager-display</span> <span class="o">.</span> <span class="no">t</span><span class="p">)</span>
<span class="p">(</span><span class="nv">eager-update</span> <span class="o">.</span> <span class="no">t</span><span class="p">)))))</span>
</code></pre></div></div>
<p><a id="orgbc5c84f"></a></p>
<h2>The default completions and related packages</h2>
<p>The modern stack is <code class="language-plaintext highlighter-rouge">vertico</code>, <code class="language-plaintext highlighter-rouge">marginalia</code>, <code class="language-plaintext highlighter-rouge">orderless</code>, <code class="language-plaintext highlighter-rouge">embark</code>, and <code class="language-plaintext highlighter-rouge">consult</code>.</p>
<p>The default completion interface can be used instead of the <code class="language-plaintext highlighter-rouge">vertico</code> package. Though you can still benefit from <code class="language-plaintext highlighter-rouge">marginalia</code>, <code class="language-plaintext highlighter-rouge">orderless</code>, <code class="language-plaintext highlighter-rouge">embark</code>, and <code class="language-plaintext highlighter-rouge">consult</code>.</p>
<p>If you really want to customise everything extensively through the <code class="language-plaintext highlighter-rouge">completion-category-overrides</code>, then you can skip <code class="language-plaintext highlighter-rouge">marginalia</code> and maybe even get <code class="language-plaintext highlighter-rouge">completion-styles</code> that are still good enough without <code class="language-plaintext highlighter-rouge">orderless</code>.</p>
<p>But there still is no built-in alternative for the powerful <code class="language-plaintext highlighter-rouge">embark</code> and <code class="language-plaintext highlighter-rouge">consult</code> packages, so plan accordingly. Granted, you can be productive without <code class="language-plaintext highlighter-rouge">embark</code> and <code class="language-plaintext highlighter-rouge">consult</code>, but the advantage of those packages is that they make it easier to achieve those same tasks (plus extra features).</p>Wonders of Web Weaving, Episode 12 - James' Coffee Bloghttps://jamesg.blog/2026/07/28/www-122026-07-28T00:00:00.000Z
<p><a href="https://web-weaving.jamesg.blog/12" rel="noreferrer">The twelfth episode of Wonders of Web Weaving is out</a>:</p><blockquote>In Episode 12, I chat with <a href="https://hey.georgie.nu">Georgie</a>, the author of <a href="https://hey.georgie.nu">Hey Georgie</a> about, among other things, writing about travelling, blogging as a self-reflection tool, why someone should start a personal website today, and more.</blockquote><p>I hope you enjoy the episode!</p><p><a href="https://web-weaving.jamesg.blog/subscribe/" rel="noreferrer"><em>Wonders of Web Weaving also has an RSS feed</em></a><em> you can use to follow along from wherever you get your podcasts.</em></p>
<a class="tag" href="https://hey.georgie.nu">Georgie</a>
<a class="tag" href="https://hey.georgie.nu">Hey Georgie</a>
<a class="tag" href="https://web-weaving.jamesg.blog/12">The twelfth episode of Wonders of Web Weaving is out</a>
<a class="tag" href="https://web-weaving.jamesg.blog/subscribe/">Wonders of Web Weaving also has an RSS feed</a>
Poem: Hymn to the oak tree (Ύμνος στον δρυ) - Protesilaos Stavrou: Master feed with all updateshttps://protesilaos.com/poems/2026-07-28-hymn-oak-tree/2026-07-28T00:00:00.000Z<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Oh majestic oak tree
you who saw my ancestors
working in this place
you who shade the birds
the hours when the sun is mid sky
you who with your continuous presence
remind us of the link between generations
give me today the strength
to turn my attention
to this space that environs me
and to recognise that I am
part of the whole
and that here someday
the next ones must find a land
that will enable them
to continue
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Ω μεγαλοπρεπή δρυ
εσύ που είδες τους προγόνους μου
να εργάζονται σε αυτόν τον τόπο
εσύ που σκιάζεις τα πουλιά
τις ώρες που ο ήλιος μεσουρανεί
εσύ που με την διαρκή παρουσία σου
μας θυμίζεις την σύνδεση των γενεών
δώσε μου σήμερα την δύναμη
να στρέψω την προσοχή μου
στον χώρο αυτό που με περιβάλλει
και να αναγνωρίσω πως εγώ είμαι
μέρος του όλου
και πως εδώ κάποτε
θα πρέπει οι επόμενοι να βρουν μιαν γη
που θα τους δίνει την δυνατότητα
να συνεχίσουν
</code></pre></div></div>Poem: Hymn to the honeybee (Ύμνος στην μέλισσα) - Protesilaos Stavrou: Master feed with all updateshttps://protesilaos.com/poems/2026-07-28-hymn-honeybee/2026-07-28T00:00:00.000Z<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>From you the tireless honeybee
I draw an example for my own life
to remain consistent in my commitments
to never make discounts on my principles
and to always contribute
with whatever way I can
to the common good that unites us
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Από εσένα την ακούραστη μέλισσα
παίρνω παράδειγμα για την ζωή μου
να μένω συνεπείς στις δεσμεύσεις μου
να μην κάνω εκπτώσεις στις αρχές μου
και πάντοτε να συμβάλω
με όποιον τρόπο μπορώ
στο κοινό αγαθό που μας ενώνει
</code></pre></div></div>