~hedy's blogroll - BlogFlock The blogroll listed on my website. https://home.hedy.dev/blogroll/ 2026-07-20T03:54:47.186Z BlogFlock Seirdy, erock, James' Coffee Blog, Sloum, Manuel Moreale RSS Feed, Protesilaos Stavrou: Master feed with all updates, Ploum.net, ~hedy, Baty.net The Hawk (2026) ★★ - Baty.net https://baty.net/posts/2026/07/the-hawk-2026/ 2026-07-19T09:35:54.000Z <figure><img src="https://baty.net/img/2026/20260719-the-hawk-card.webp" alt="The Hawk card"></figure><p>I was really looking forward to &quot;The Hawk&quot;. I usually get a kick out of Will Ferrell. Not this time, I'm afraid. I don't mind if a show is silly, but it also needs to be funny. This is not funny. The problem is that the actors, especially Ferrell and Molly Shannon, seem to be playing themselves, not the actual characters. I gave it two episodes, but that's all I could handle.</p> <p><a href="mailto:jack@baty.net?subject=[Baty.net] Re: The%20Hawk%20(2026)%20%E2%98%85%E2%98%85">✍️ Reply by email</a></p> Of Day - James' Coffee Blog https://jamesg.blog/2026/07/19/of-day 2026-07-19T00:00:00.000Z <p>I close my eyes and listen to the church bells reverberate through the city — the air, the street, the park; the hearts.</p><p>Usually when I go into a bookshop, I find myself looking at all the books. Often, for nothing in particular, but rather to see what is new. Who knows what I might find; what stories might stand out today. My time spent wandering around the walls of words today, however, was characterised more by writing than by reading. The books were my anchor. The word was in my spirit. My disposition was to capture what I heard and saw and felt; to let my thoughts flow onto a new page.</p><p>I took notes on art galleries, places where we can feel both oriented and lost; where we can discover and ponder discovery; where we can let the present pass while considering the past and the future; where the colours of Monet and the shadows of Rembrandt exist a few rooms away. What does it mean that I can see Rembrandt and walk through a few rooms to see Monet?</p><p>I realised I was lost, not in place but in thought. I recognised the shelves in front of me while I stood at the frontier of my imagination, asking questions with increasing momentum – questions of magnetism and enchantment and on the nature of significance.</p><p>“My dream is to have one of each of these.” “The classics?” “Yeah.” “We should do it as a wee Christmassy thing: each of us should pick four or five that we like…” — a gift exchange? “Oh, that’s the one you keep telling me to read.”, as one of the three friends points to the shelf. The conversation flowed. “So you’re having a book stand in your next [flat?]”. I realised they spoke in the kind of sentences where you don’t need to finish for your friends to know what you mean – therein, the language of friendship.</p><p>I learned today that I can be in a bookshop and an art gallery at the same time, and that I can move between them; that the sounds and physicality of stories can ground me as my mind wanders. A book of poetry caught my eye. Opening the book to a page at random – Serendipity being my guide – I pondered the literal shape of the words in poems. One poem was a rectangle of aligned text. Another poem was written in couplets. One was short. Another, long. How does form influence what we read? I wonder. This is why I love bookshops.</p><p>After having walked around all of the shelves of fiction at a slow pace, I went back outside and let my legs take me where they wanted to go. I wandered, on my journey seeing Georgian architecture, hearing the roar of a lion from a parent entertaining their child, and feeling the fresh air of Scotland rush through my lungs as I looked up to the blue and white sky.</p><p>Eventually, I made my way to the National Gallery of Scotland, not the gallery of I was imagining earlier – that one was four hundred miles away – but one in which I always feel enchanted immediately after walking in. I found myself standing in front of works of Turner and Lievens, Da Vinci and Gainsborough, thinking about the nature of the space I had on my mind since the hour of wandering through the bookshop, and my imagination.</p> Emacs: Completion in the buffer with completion-at-point-functions - Protesilaos Stavrou: Master feed with all updates https://protesilaos.com/codelog/2026-07-19-emacs-completion-at-point-functions/ 2026-07-19T00:00:00.000Z <p>In this ~22-minute video I explain how Emacs performs completion in a buffer. I cover what happens behind the scenes with the variable completion-at-point-functions. Then I also go to the frontends, which affects the modalities of interaction. I cover t built-in Completions buffer, the packages Corfu and Company, and the built-in completion-preview-mode. Finally, I comment at some further length on how to control the grouping of results in the completion-at-point-functions. In that context I also mention the Cape package, as well as some extra functionality that the Company package provide. I wrote an article which covers all of what is in the video as well as code samples. Its text is below.</p> <h2>Table of Contents</h2> <ol> <li><a href="#org423cf05">Make <code class="language-plaintext highlighter-rouge">TAB</code> complete when it can</a></li> <li><a href="#org600a610">The in-buffer completion backends (<code class="language-plaintext highlighter-rouge">completion-at-point-functions</code>)</a> <ol> <li><a href="#orgff700e2">Common providers of CAPFs</a></li> </ol> </li> <li><a href="#org2bc4069">The completion frontends</a> <ol> <li><a href="#orgf435e66">Corfu for an in-buffer completion popup window</a> <ol> <li><a href="#org74094c3">My preferred <code class="language-plaintext highlighter-rouge">corfu</code> setup plus <code class="language-plaintext highlighter-rouge">cape</code></a></li> </ol> </li> <li><a href="#orgfd63733">Company for an in-buffer completion popup window</a> <ol> <li><a href="#org2338c9d">My preferred Company setup</a></li> </ol> </li> <li><a href="#org8a380be">The built-in <code class="language-plaintext highlighter-rouge">completion-preview-mode</code> for a minimalist single suggestion at a time</a> <ol> <li><a href="#org3eeaf41">My preferred setup for <code class="language-plaintext highlighter-rouge">completion-preview-mode</code></a></li> </ol> </li> </ol> </li> </ol> <p><a id="org423cf05"></a></p> <h2>Make <code class="language-plaintext highlighter-rouge">TAB</code> complete when it can</h2> <p>By default, Emacs uses <code class="language-plaintext highlighter-rouge">TAB</code> to align the current line or selected region of text. It does so based on the relevant rules provided by the major mode (e.g. a programming mode may have specific requirements for how the body of a function definition is indented).</p> <p>We can tell Emacs to also use <code class="language-plaintext highlighter-rouge">TAB</code> to perform completion once no further alignment is possible in the given context.</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">tab-always-indent</span> <span class="ss">'complete</span><span class="p">)</span> </code></pre></div></div> <p><a id="org600a610"></a></p> <h2>The in-buffer completion backends (<code class="language-plaintext highlighter-rouge">completion-at-point-functions</code>)</h2> <p>The <code class="language-plaintext highlighter-rouge">completion-at-point-functions</code> is a variable (technically an abnormal hook) that takes as its value a list of functions. We can call those “CAPFs”, for “completion at point functions”. Those are used to perform completion in the buffer, with the text right before the cursor as their input.</p> <p>When we request completion for the text at point, either via <code class="language-plaintext highlighter-rouge">TAB</code> or the command <code class="language-plaintext highlighter-rouge">completion-at-point</code> (<code class="language-plaintext highlighter-rouge">C-M-i</code> by default), Emacs looks at the value of the <code class="language-plaintext highlighter-rouge">completion-at-point-functions</code>, and calls the functions found there in order from first to last (or left to right).</p> <p>Normally, once a function returns results, Emacs will display those and will not move to the remaining functions in the <code class="language-plaintext highlighter-rouge">completion-at-point-functions</code>. So if we have many functions, we may not see of them at once. To do so we need more advanced solutions, which I comment on further below.</p> <p>The <code class="language-plaintext highlighter-rouge">completion-at-point-functions</code> typically has a buffer-local value. This means that the functions we run in one buffer will likely be different than what we have in another buffer. For example, in a programming mode it makes sense to use the Language Server Protocol to get comprehensive suggestions for the language we are programming in, whereas in Org mode we may only wish to see the correct spelling of a word.</p> <p>When the <code class="language-plaintext highlighter-rouge">completion-at-point-functions</code> has a buffer-local value, it will typically include a <code class="language-plaintext highlighter-rouge">t</code>. This is a reference to its corresponding global value. So if Emacs tries to complete and reaches the <code class="language-plaintext highlighter-rouge">t</code>, it then goes through the list with the global CAPFs.</p> <p><a id="orgff700e2"></a></p> <h3>Common providers of CAPFs</h3> <ul> <li>specialised minor modes;</li> <li>the major mode;</li> <li>the Language Server Protocol via its Emacs client (e.g. <code class="language-plaintext highlighter-rouge">eglot</code> or <code class="language-plaintext highlighter-rouge">lsp-mode</code>);</li> <li>the <code class="language-plaintext highlighter-rouge">cape</code> package;</li> <li>the <code class="language-plaintext highlighter-rouge">company</code> package;</li> <li>other packages that may extend <code class="language-plaintext highlighter-rouge">company</code> or related.</li> </ul> <p><a id="org2bc4069"></a></p> <h2>The completion frontends</h2> <p>For a few years now Emacs has a unified infrastructure at its core for how completions are done. Users should not mess around with that. What they can do instead is choose how the completions are displayed as well as the relevant modalities for filtering and selecting candidates.</p> <p><a id="orgf435e66"></a></p> <h3>Corfu for an in-buffer completion popup window</h3> <p>A package by Daniel Mendler, the developer of <code class="language-plaintext highlighter-rouge">vertico</code> and <code class="language-plaintext highlighter-rouge">consult</code>, among others, which is built on top of the <code class="language-plaintext highlighter-rouge">completion-at-point-functions</code>. It is designed to be fast and effective, with a good out-of-the-box experience and reasonable extensions.</p> <p>By default, <code class="language-plaintext highlighter-rouge">corfu</code> does not automatically pop up its window. Users must manually invoke completion or opt in to the auto-completing functionality.</p> <div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">;; Read the comprehensive documentation of Corfu for further customisation options.</span> <span class="p">(</span><span class="nb">use-package</span> <span class="nv">corfu</span> <span class="ss">:ensure</span> <span class="no">t</span> <span class="ss">:init</span> <span class="p">(</span><span class="k">setq</span> <span class="nv">tab-always-indent</span> <span class="ss">'complete</span><span class="p">)</span> <span class="ss">:config</span> <span class="c1">;; ;; If you want the popup window to appear automatically as you type:</span> <span class="c1">;;</span> <span class="c1">;; (setq corfu-auto t)</span> <span class="p">(</span><span class="nv">global-corfu-mode</span> <span class="mi">1</span><span class="p">))</span> </code></pre></div></div> <p><a id="org74094c3"></a></p> <h4>My preferred <code class="language-plaintext highlighter-rouge">corfu</code> setup plus <code class="language-plaintext highlighter-rouge">cape</code></h4> <p>This is just for your information. It fits my use-case, but I do not recommend it as a starting point. The <code class="language-plaintext highlighter-rouge">cape</code> package is also developed by Daniel Mendler.</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">corfu</span> <span class="ss">:ensure</span> <span class="no">t</span> <span class="ss">:init</span> <span class="p">(</span><span class="k">setq</span> <span class="nv">tab-always-indent</span> <span class="ss">'complete</span><span class="p">)</span> <span class="ss">:config</span> <span class="p">(</span><span class="k">setq</span> <span class="nv">corfu-preview-current</span> <span class="no">nil</span><span class="p">)</span> <span class="p">(</span><span class="k">setq</span> <span class="nv">corfu-min-width</span> <span class="mi">20</span><span class="p">)</span> <span class="p">(</span><span class="k">setq</span> <span class="nv">corfu-popupinfo-delay</span> <span class="o">'</span><span class="p">(</span><span class="mf">1.25</span> <span class="o">.</span> <span class="mf">0.5</span><span class="p">))</span> <span class="p">(</span><span class="nv">corfu-popupinfo-mode</span> <span class="mi">1</span><span class="p">)</span> <span class="c1">; shows documentation after `corfu-popupinfo-delay'</span> <span class="p">(</span><span class="nv">global-corfu-mode</span> <span class="mi">1</span><span class="p">)</span> <span class="c1">;; I also have (setq tab-always-indent 'complete) for TAB to complete</span> <span class="c1">;; when it does not need to perform an indentation change.</span> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">corfu-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"&lt;tab&gt;"</span><span class="p">)</span> <span class="nf">#'</span><span class="nv">corfu-complete</span><span class="p">)</span> <span class="c1">;; Sort by input history (no need to modify `corfu-sort-function').</span> <span class="p">(</span><span class="nv">with-eval-after-load</span> <span class="ss">'savehist</span> <span class="p">(</span><span class="nv">corfu-history-mode</span> <span class="mi">1</span><span class="p">)</span> <span class="p">(</span><span class="nv">add-to-list</span> <span class="ss">'savehist-additional-variables</span> <span class="ss">'corfu-history</span><span class="p">)))</span> <span class="p">(</span><span class="nb">use-package</span> <span class="nv">cape</span> <span class="ss">:ensure</span> <span class="no">t</span> <span class="ss">:after</span> <span class="nv">corfu</span> <span class="ss">:config</span> <span class="c1">;; This is for the global value.</span> <span class="p">(</span><span class="k">setq</span> <span class="nv">completion-at-point-functions</span> <span class="o">'</span><span class="p">(</span><span class="nv">cape-dabbrev</span> <span class="nv">cape-file</span><span class="p">))</span> <span class="p">(</span><span class="nb">defun</span> <span class="nv">prot/cape-super-set-local</span> <span class="p">(</span><span class="nv">capfs</span> <span class="k">&amp;optional</span> <span class="nv">individual-capfs</span><span class="p">)</span> <span class="s">"Set `completion-at-point-functions' to current value plus CAPFS. Treat CAPFS and the default value as a super CAPF. Then append the INDIVIDUAL-CAPFS to the list."</span> <span class="p">(</span><span class="k">let*</span> <span class="p">((</span><span class="nv">all-for-super</span> <span class="p">(</span><span class="nb">append</span> <span class="nv">completion-at-point-functions</span> <span class="nv">capfs</span><span class="p">))</span> <span class="p">(</span><span class="nv">all-minus-global</span> <span class="p">(</span><span class="nv">delq</span> <span class="no">t</span> <span class="nv">all-for-super</span><span class="p">))</span> <span class="p">(</span><span class="nv">cape-super</span> <span class="p">(</span><span class="nb">apply</span> <span class="nf">#'</span><span class="nv">cape-capf-super</span> <span class="nv">all-minus-global</span><span class="p">)))</span> <span class="p">(</span><span class="nv">setq-local</span> <span class="nv">completion-at-point-functions</span> <span class="p">(</span><span class="nb">append</span> <span class="p">(</span><span class="nb">list</span> <span class="nv">cape-super</span><span class="p">)</span> <span class="nv">individual-capfs</span> <span class="p">(</span><span class="nb">list</span> <span class="no">t</span><span class="p">)))))</span> <span class="p">(</span><span class="nb">defun</span> <span class="nv">prot/cape-prog-setup</span> <span class="p">()</span> <span class="s">"Set up Cape for programming."</span> <span class="p">(</span><span class="nv">prot/cape-super-set-local</span> <span class="o">'</span><span class="p">(</span><span class="nv">cape-dabbrev</span><span class="p">)</span> <span class="o">'</span><span class="p">(</span><span class="nv">cape-file</span><span class="p">)))</span> <span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'prog-mode-hook</span> <span class="nf">#'</span><span class="nv">prot/cape-prog-setup</span><span class="p">)</span> <span class="p">(</span><span class="nb">defun</span> <span class="nv">prot/cape-text-setup</span> <span class="p">()</span> <span class="s">"Set up Cape for prose."</span> <span class="p">(</span><span class="nv">prot/cape-super-set-local</span> <span class="o">'</span><span class="p">(</span><span class="nv">cape-dict</span> <span class="nv">cape-dabbrev</span> <span class="nv">cape-emoji</span><span class="p">)</span> <span class="o">'</span><span class="p">(</span><span class="nv">cape-file</span><span class="p">)))</span> <span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'text-mode-hook</span> <span class="nf">#'</span><span class="nv">prot/cape-text-setup</span><span class="p">))</span> </code></pre></div></div> <p><a id="orgfd63733"></a></p> <h3>Company for an in-buffer completion popup window</h3> <p>This package by Dmitry Gutov is older than <code class="language-plaintext highlighter-rouge">corfu</code> though remains in active development and has all the features of Corfu plus some extras. Fundamentally though, it does the same thing, so if you are already using one there is no pressing need to switch to the other.</p> <p>As of this writing (2026-07-19), <code class="language-plaintext highlighter-rouge">company</code> version <code class="language-plaintext highlighter-rouge">1.1.0</code> is still in development. It comes with many nice features, such as native support for <code class="language-plaintext highlighter-rouge">tab-always-indent</code>, child frames, and in-buffer completion in the minibuffer.</p> <p>By default, and unlike <code class="language-plaintext highlighter-rouge">corfu</code>, Company automatically pops up its window. You can opt out if you wish to.</p> <div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">;; Remember to read the comprehensive documentation of Company for all</span> <span class="c1">;; the customisation options and extra features.</span> <span class="p">(</span><span class="nb">use-package</span> <span class="nv">company</span> <span class="ss">:ensure</span> <span class="no">t</span> <span class="ss">:init</span> <span class="p">(</span><span class="k">setq</span> <span class="nv">tab-always-indent</span> <span class="ss">'complete</span><span class="p">)</span> <span class="ss">:config</span> <span class="p">(</span><span class="nv">global-company-mode</span> <span class="mi">1</span><span class="p">))</span> </code></pre></div></div> <p><a id="org2338c9d"></a></p> <h4>My preferred Company setup</h4> <p>The <code class="language-plaintext highlighter-rouge">company</code> includes several CAPFs, unlike <code class="language-plaintext highlighter-rouge">corfu</code> which spins them out into the separate <code class="language-plaintext highlighter-rouge">cape</code> pacakge. Company CAPFs can easily be grouped to collect the results of many functions into a single popup window.</p> <p>This is what I am currently using. Again, I am sharing it for your information and do not meant to imply that it is useful in general.</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">company</span> <span class="ss">:ensure</span> <span class="no">t</span> <span class="ss">:init</span> <span class="p">(</span><span class="k">setq</span> <span class="nv">tab-always-indent</span> <span class="ss">'complete</span><span class="p">)</span> <span class="ss">:config</span> <span class="c1">;; NOTE 2026-07-19 with the next version of Company, which may be</span> <span class="c1">;; 1.1.0, (setq tab-always-indent 'complete) is supported</span> <span class="c1">;; out-of-the-box, which means that we disable the automatic popup</span> <span class="c1">;; feature and rely on TAB to perform completion in the buffer.</span> <span class="p">(</span><span class="k">setq</span> <span class="nv">company-idle-delay</span> <span class="no">nil</span><span class="p">)</span> <span class="p">(</span><span class="k">setq</span> <span class="nv">company-tooltip-limit</span> <span class="mi">6</span><span class="p">)</span> <span class="p">(</span><span class="k">setq</span> <span class="nv">company-tooltip-minimum-width</span> <span class="mi">25</span><span class="p">)</span> <span class="p">(</span><span class="k">setq</span> <span class="nv">company-tooltip-align-annotations</span> <span class="no">t</span><span class="p">)</span> <span class="p">(</span><span class="k">setq</span> <span class="nv">company-dabbrev-code-completion-styles</span> <span class="no">t</span><span class="p">)</span> <span class="c1">; use the `completion-styles'</span> <span class="p">(</span><span class="k">setq</span> <span class="nv">company-transformers</span> <span class="o">'</span><span class="p">(</span><span class="nv">company-sort-by-occurrence</span> <span class="nv">company-sort-by-backend-importance</span> <span class="nv">company-sort-prefer-same-case-prefix</span><span class="p">))</span> <span class="p">(</span><span class="k">setq</span> <span class="nv">company-frontends</span> <span class="o">'</span><span class="p">(</span><span class="nv">company-childframe-unless-just-one-frontend</span> <span class="nv">company-preview-if-just-one-frontend</span> <span class="nv">company-echo-metadata-frontend</span><span class="p">))</span> <span class="c1">;; Notice the `(company-capf company-dabbrev)', which represents a</span> <span class="c1">;; grouping of CAPFs, whereas `company-files' shows results of its own.</span> <span class="p">(</span><span class="k">setq</span> <span class="nv">company-backends</span> <span class="o">'</span><span class="p">((</span><span class="nv">company-capf</span> <span class="nv">company-dabbrev</span><span class="p">)</span> <span class="nv">company-files</span><span class="p">))</span> <span class="c1">;; IGNORE THIS AS IT IS RELEVANT ONLY FOR MY CONFIGURATION which</span> <span class="c1">;; does a lot with the `display-buffer-alist'.</span> <span class="p">(</span><span class="nv">define-advice</span> <span class="nv">company-show-doc-buffer</span> <span class="p">(</span><span class="ss">:around</span> <span class="p">(</span><span class="k">&amp;rest</span> <span class="nv">args</span><span class="p">)</span> <span class="nv">prot</span><span class="p">)</span> <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">help-window-select</span> <span class="no">nil</span><span class="p">)</span> <span class="p">(</span><span class="nv">display-buffer-alist</span> <span class="no">nil</span><span class="p">)</span> <span class="p">(</span><span class="nv">display-buffer-overriding-action</span> <span class="o">'</span><span class="p">((</span><span class="nv">display-buffer-reuse-mode-window</span> <span class="nv">display-buffer-below-selected</span><span class="p">)</span> <span class="p">(</span><span class="nv">window-height</span> <span class="o">.</span> <span class="mf">0.3</span><span class="p">)</span> <span class="p">(</span><span class="nv">post-command-select-window</span> <span class="o">.</span> <span class="no">nil</span><span class="p">))))</span> <span class="p">(</span><span class="nb">apply</span> <span class="nv">args</span><span class="p">)))</span> <span class="p">(</span><span class="nb">defun</span> <span class="nv">prot/company-prog-backends</span> <span class="p">()</span> <span class="s">"Set `company-backends' locally to my preferred value for `prog-mode' and derivatives."</span> <span class="p">(</span><span class="nv">setq-local</span> <span class="nv">company-backends</span> <span class="o">'</span><span class="p">((</span><span class="nv">company-capf</span> <span class="nv">company-dabbrev-code</span><span class="p">)</span> <span class="nv">company-files</span><span class="p">)))</span> <span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'prog-mode-hook</span> <span class="nf">#'</span><span class="nv">prot/company-prog-backends</span><span class="p">)</span> <span class="p">(</span><span class="nb">defun</span> <span class="nv">prot/company-text-backends</span> <span class="p">()</span> <span class="s">"Set `company-backends' locally to my preferred value for `text-mode' and derivatives."</span> <span class="p">(</span><span class="nv">setq-local</span> <span class="nv">company-backends</span> <span class="o">'</span><span class="p">((</span><span class="nv">company-dabbrev</span> <span class="nv">company-ispell</span> <span class="nv">company-capf</span><span class="p">)</span> <span class="nv">company-files</span><span class="p">)))</span> <span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'text-mode-hook</span> <span class="nf">#'</span><span class="nv">prot/company-text-backends</span><span class="p">)</span> <span class="p">(</span><span class="nv">global-company-mode</span> <span class="mi">1</span><span class="p">))</span> <span class="p">(</span><span class="nb">use-package</span> <span class="nv">company-statistics</span> <span class="ss">:ensure</span> <span class="no">t</span> <span class="ss">:after</span> <span class="nv">company</span> <span class="ss">:config</span> <span class="p">(</span><span class="nv">company-statistics-mode</span> <span class="mi">1</span><span class="p">))</span> </code></pre></div></div> <p><a id="org8a380be"></a></p> <h3>The built-in <code class="language-plaintext highlighter-rouge">completion-preview-mode</code> for a minimalist single suggestion at a time</h3> <p>Since Emacs 30, there is the <code class="language-plaintext highlighter-rouge">completion-preview-mode</code> by Eshel Yaron. Unlike the other options, it displays only one suggestion at a time. It does it inline as you type. You can still cycle through suggestions or display more of them with either the default <code class="language-plaintext highlighter-rouge">*Completions*</code> buffer or one of the aforementioned packages.</p> <p>Note that Company also has the equivalent of <code class="language-plaintext highlighter-rouge">completion-preview-mode</code>. Check the <code class="language-plaintext highlighter-rouge">company-frontends</code> for more.</p> <p><code class="language-plaintext highlighter-rouge">completion-preview-mode</code> does not provide its own CAPFs directly or through some companion package. You will have to use one of the previous options or simply rely on what other providers (major modes, LSP, …) give you.</p> <div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">;; Do M-x describe-package and then search for completion-preview to</span> <span class="c1">;; read its commentary, or M-x find-library and then</span> <span class="c1">;; completion-preview to go straight to its source code (where you can</span> <span class="c1">;; read the commentary and browse through all the options).</span> <span class="p">(</span><span class="nb">use-package</span> <span class="nv">completion-preview</span> <span class="ss">:ensure</span> <span class="no">nil</span> <span class="ss">:config</span> <span class="p">(</span><span class="nv">global-completion-preview-mode</span> <span class="mi">1</span><span class="p">))</span> </code></pre></div></div> <p><a id="org3eeaf41"></a></p> <h4>My preferred setup for <code class="language-plaintext highlighter-rouge">completion-preview-mode</code></h4> <p>And here is what I have for this minor mode. Again, it is only for your information.</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">completion-preview</span> <span class="ss">:ensure</span> <span class="no">nil</span> <span class="ss">:demand</span> <span class="no">t</span> <span class="ss">:bind</span> <span class="p">(</span> <span class="ss">:map</span> <span class="nv">completion-preview-active-mode-map</span> <span class="p">(</span><span class="s">"M-n"</span> <span class="o">.</span> <span class="nv">completion-preview-next-candidate</span><span class="p">)</span> <span class="p">(</span><span class="s">"M-p"</span> <span class="o">.</span> <span class="nv">completion-preview-prev-candidate</span><span class="p">)</span> <span class="p">(</span><span class="s">"M-&lt;return&gt;"</span> <span class="o">.</span> <span class="nv">completion-preview-insert</span><span class="p">)</span> <span class="c1">;; This way you can combine it with another interface (like the</span> <span class="c1">;; generic Completions buffer or `corfu-mode') to display more</span> <span class="c1">;; candidates.</span> <span class="p">(</span><span class="s">"&lt;tab&gt;"</span> <span class="o">.</span> <span class="nv">completion-preview-complete</span><span class="p">))</span> <span class="ss">:config</span> <span class="p">(</span><span class="k">setq</span> <span class="nv">completion-preview-exact-match-only</span> <span class="no">nil</span><span class="p">)</span> <span class="p">(</span><span class="k">setq</span> <span class="nv">completion-preview-commands</span> <span class="o">'</span><span class="p">(</span><span class="nv">self-insert-command</span> <span class="nv">insert-char</span> <span class="nv">analyze-text-conversion</span> <span class="nv">completion-preview-insert-word</span><span class="p">))</span> <span class="p">(</span><span class="k">setq</span> <span class="nv">completion-preview-minimum-symbol-length</span> <span class="mi">2</span><span class="p">)</span> <span class="p">(</span><span class="k">setq</span> <span class="nv">completion-preview-idle-delay</span> <span class="mf">0.3</span><span class="p">)</span> <span class="p">(</span><span class="k">setq</span> <span class="nv">completion-preview-ignore-case</span> <span class="no">t</span><span class="p">)</span> <span class="p">(</span><span class="k">setq</span> <span class="nv">completion-preview-sort-function</span> <span class="nf">#'</span><span class="nb">identity</span><span class="p">)</span> <span class="p">(</span><span class="nv">global-completion-preview-mode</span> <span class="mi">1</span><span class="p">))</span> </code></pre></div></div> Saturday, July 18, 2026 - Baty.net https://baty.net/journal/18Jul26/ 2026-07-18T10:32:16.000Z <figure><img src="https://baty.net/img/2026/20260718-me-windsurfing-80s.webp" alt="Me, windsurfing"><figcaption>Me windsurfing in the 80s</figcaption></figure><div class="compact status"> <ul> <li><strong>STATUS</strong>: Family Reunion, today</li> <li><strong>TODO</strong>: Get through the reunion. I like everyone, but it's way too much peopleing</li> </ul> </div> <hr /> <p>I've really gone and over-complicated things now.</p> <hr /> <p><a href="mailto:jack@baty.net?subject=[Baty.net] Re: Saturday%2C%20July%2018%2C%202026">✍️ Reply by email</a></p> Français: La parrhésie - Protesilaos Stavrou: Master feed with all updates https://protesilaos.com/french/2026-07-18-la-parrhesie/ 2026-07-18T00:00:00.000Z <p>J’ai la confiance de faire des erreurs en public, pas seulement sur le sujet de pratiquer mon français mais sur tout ce que je fais. Je ne suis pas parfait. L’acceptante de ce fait simple me libère de la pression.</p> <p>Ce n’est pas facile de dire «je ne sais pas», «je fais des fautes», ou, simplement, de répondre négativement au manière ferme, de dire que tu a une opinion concrète et que tu va vivre avec discipline en accord avec la raison.</p> <p>J’ai la parrhésie, la qualité de personnage de m’exprimer sincèrement, d’être préparer d’accepter les conséquences de mes actions, et d’admettre tout mes erreurs avec l’honneur. La raison est que mon estime de soi ça dépend exclusivement à moi. Les opinions des autres personnes ne sont pas pertinent: j’aime que je suis et ça suffit.</p> <p>Je n’ai pas l’inquiétude. Je suis calme et content dans ma réalité, grâce à mon conception de valeur personnel comme une affaire privée. Les autres ne peuvent pas changer cette condition parce que il n’ont pas accès à l’intérieur de mon présence. Je ne suis pas extraordinaire ou l’exception: c’est vrai pour moi et pour toi.</p> <p>Quand ton valeur de soi déviant par les opinions des autres personnes, tu n’a pas de stabilité à ton vie. C’est une situation précaire. Aujourd’hui ils t’aiment, demain ils te détestent, et le lendemain ils t’ignorent—la éventualité que tu redoutes le plus.</p> <p>L’opinion publique est toujours important pour ton sécurité, mais pas pour ton estime de soi. La parrhésie est dangereuse sans conscience de la situation. Tu dois connaître quand tu va parler et quand tu va ne rien dire. C’est ça la raison judicieuse.</p> <p>Ceci est pour ma perception de soi. Aux autres sujets je veux savoir quelles sont les opinions ou méthodes que les gens avoir. J’étudie la condition humaine et les phénomènes en général. Donc je suis indépendant et j’ai aussi la disposition communautaire pour trouver les autres, pour savoir qui sont-ils vraiment, et pour découvrir d’autres aspects du cosmos.</p> On ethics and usefulness - Manuel Moreale RSS Feed https://manuelmoreale.com/@/page/frmbkbtabujvu4m4 2026-07-17T06:25:00.000Z <p><a href="https://overkill.wtf">Kevin</a> sent me a link to <a href="https://lore.kernel.org/linux-media/CAHk-=wi4zC+Ze8e+p3tMv8TtG_80KzsZ1syL9anBtmEh5Z40vg@mail.gmail.com/">this email</a> from Linus Torvalds the other day, and I found that to be a great example of something that has been bothering me for a while now. It’s about AI—everything is about AI these days, so damn boring—and, more specifically, Linus’ position when it comes to the use of LLMs.</p> <p>What I find bothersome is the lack of any consideration for the moral and ethical implications of the technology itself. The justification for its use essentially boils down to “it’s a useful tool”, which is a totally unconvincing argument in this context.</p> <p>In his defense, Linus also mentioned that <em>«There are other questions around AI»</em> but it’s telling that the one example he picked was «what the economy of it will actually look like in the end»* which, again, has nothing to do with anything related to the ethics around the use of these tools, how were made, and so on.</p> <p>And look, I understand that this is a very complex landscape to navigate since it touches A LOT of different aspects. But to quote Linus, <em>«the solution is not to put your head in the sand and sing "La La La, I can't hear you”»</em>. This is a technology that is deeply entangled with moral and societal issues, and you have to accept the fact that you need to confront those ethical and moral dilemmas. There’s no way around it. And if you decide to sweep everything under the “it’s useful” rug, well, that’s disappointing to say the least.</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> Multi-line links on my home page - James' Coffee Blog https://jamesg.blog/2026/07/17/multi-line-links-on-my-home-page 2026-07-17T00:00:00.000Z <style media="(prefers-color-scheme: dark)">pre { line-height: 125%; } td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } .highlight .hll { background-color: #49483e } .highlight { background: #272822; color: #F8F8F2 } .highlight .c { color: #959077 } /* Comment */ .highlight .err { color: #ED007E; background-color: #1E0010 } /* Error */ .highlight .esc { color: #F8F8F2 } /* Escape */ .highlight .g { color: #F8F8F2 } /* Generic */ .highlight .k { color: #66D9EF } /* Keyword */ .highlight .l { color: #AE81FF } /* Literal */ .highlight .n { color: #F8F8F2 } /* Name */ .highlight .o { color: #FF4689 } /* Operator */ .highlight .x { color: #F8F8F2 } /* Other */ .highlight .p { color: #F8F8F2 } /* Punctuation */ .highlight .ch { color: #959077 } /* Comment.Hashbang */ .highlight .cm { color: #959077 } /* Comment.Multiline */ .highlight .cp { color: #959077 } /* Comment.Preproc */ .highlight .cpf { color: #959077 } /* Comment.PreprocFile */ .highlight .c1 { color: #959077 } /* Comment.Single */ .highlight .cs { color: #959077 } /* Comment.Special */ .highlight .gd { color: #FF4689 } /* Generic.Deleted */ .highlight .ge { color: #F8F8F2; font-style: italic } /* Generic.Emph */ .highlight .ges { color: #F8F8F2; font-weight: bold; font-style: italic } /* Generic.EmphStrong */ .highlight .gr { color: #F8F8F2 } /* Generic.Error */ .highlight .gh { color: #F8F8F2 } /* Generic.Heading */ .highlight .gi { color: #A6E22E } /* Generic.Inserted */ .highlight .go { color: #66D9EF } /* Generic.Output */ .highlight .gp { color: #FF4689; font-weight: bold } /* Generic.Prompt */ .highlight .gs { color: #F8F8F2; font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #959077 } /* Generic.Subheading */ .highlight .gt { color: #F8F8F2 } /* Generic.Traceback */ .highlight .kc { color: #66D9EF } /* Keyword.Constant */ .highlight .kd { color: #66D9EF } /* Keyword.Declaration */ .highlight .kn { color: #FF4689 } /* Keyword.Namespace */ .highlight .kp { color: #66D9EF } /* Keyword.Pseudo */ .highlight .kr { color: #66D9EF } /* Keyword.Reserved */ .highlight .kt { color: #66D9EF } /* Keyword.Type */ .highlight .ld { color: #E6DB74 } /* Literal.Date */ .highlight .m { color: #AE81FF } /* Literal.Number */ .highlight .s { color: #E6DB74 } /* Literal.String */ .highlight .na { color: #A6E22E } /* Name.Attribute */ .highlight .nb { color: #F8F8F2 } /* Name.Builtin */ .highlight .nc { color: #A6E22E } /* Name.Class */ .highlight .no { color: #66D9EF } /* Name.Constant */ .highlight .nd { color: #A6E22E } /* Name.Decorator */ .highlight .ni { color: #F8F8F2 } /* Name.Entity */ .highlight .ne { color: #A6E22E } /* Name.Exception */ .highlight .nf { color: #A6E22E } /* Name.Function */ .highlight .nl { color: #F8F8F2 } /* Name.Label */ .highlight .nn { color: #F8F8F2 } /* Name.Namespace */ .highlight .nx { color: #A6E22E } /* Name.Other */ .highlight .py { color: #F8F8F2 } /* Name.Property */ .highlight .nt { color: #FF4689 } /* Name.Tag */ .highlight .nv { color: #F8F8F2 } /* Name.Variable */ .highlight .ow { color: #FF4689 } /* Operator.Word */ .highlight .pm { color: #F8F8F2 } /* Punctuation.Marker */ .highlight .w { color: #F8F8F2 } /* Text.Whitespace */ .highlight .mb { color: #AE81FF } /* Literal.Number.Bin */ .highlight .mf { color: #AE81FF } /* Literal.Number.Float */ .highlight .mh { color: #AE81FF } /* Literal.Number.Hex */ .highlight .mi { color: #AE81FF } /* Literal.Number.Integer */ .highlight .mo { color: #AE81FF } /* Literal.Number.Oct */ .highlight .sa { color: #E6DB74 } /* Literal.String.Affix */ .highlight .sb { color: #E6DB74 } /* Literal.String.Backtick */ .highlight .sc { color: #E6DB74 } /* Literal.String.Char */ .highlight .dl { color: #E6DB74 } /* Literal.String.Delimiter */ .highlight .sd { color: #E6DB74 } /* Literal.String.Doc */ .highlight .s2 { color: #E6DB74 } /* Literal.String.Double */ .highlight .se { color: #AE81FF } /* Literal.String.Escape */ .highlight .sh { color: #E6DB74 } /* Literal.String.Heredoc */ .highlight .si { color: #E6DB74 } /* Literal.String.Interpol */ .highlight .sx { color: #E6DB74 } /* Literal.String.Other */ .highlight .sr { color: #E6DB74 } /* Literal.String.Regex */ .highlight .s1 { color: #E6DB74 } /* Literal.String.Single */ .highlight .ss { color: #E6DB74 } /* Literal.String.Symbol */ .highlight .bp { color: #F8F8F2 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #A6E22E } /* Name.Function.Magic */ .highlight .vc { color: #F8F8F2 } /* Name.Variable.Class */ .highlight .vg { color: #F8F8F2 } /* Name.Variable.Global */ .highlight .vi { color: #F8F8F2 } /* Name.Variable.Instance */ .highlight .vm { color: #F8F8F2 } /* Name.Variable.Magic */ .highlight .il { color: #AE81FF } /* Literal.Number.Integer.Long */ .highlight .nn, .highlight .n{color: light-dark(black, var(--dark-foreground-color)) }</style><style media="(prefers-color-scheme: light)">pre { line-height: 125%; } td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } .highlight .hll { background-color: #ffffcc } .highlight { background: #f8f8f8; } .highlight .c { color: #3D7B7B; font-style: italic } /* Comment */ .highlight .err { border: 1px solid #F00 } /* Error */ .highlight .k { color: #008000; font-weight: bold } /* Keyword */ .highlight .o { color: #666 } /* Operator */ .highlight .ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */ .highlight .cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */ .highlight .cp { color: #9C6500 } /* Comment.Preproc */ .highlight .cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */ .highlight .c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */ .highlight .cs { color: #3D7B7B; font-style: italic } /* Comment.Special */ .highlight .gd { color: #A00000 } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */ .highlight .gr { color: #E40000 } /* Generic.Error */ .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ .highlight .gi { color: #008400 } /* Generic.Inserted */ .highlight .go { color: #717171 } /* Generic.Output */ .highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ .highlight .gt { color: #04D } /* Generic.Traceback */ .highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008000 } /* Keyword.Pseudo */ .highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #B00040 } /* Keyword.Type */ .highlight .m { color: #666 } /* Literal.Number */ .highlight .s { color: #BA2121 } /* Literal.String */ .highlight .na { color: #687822 } /* Name.Attribute */ .highlight .nb { color: #008000 } /* Name.Builtin */ .highlight .nc { color: #00F; font-weight: bold } /* Name.Class */ .highlight .no { color: #800 } /* Name.Constant */ .highlight .nd { color: #A2F } /* Name.Decorator */ .highlight .ni { color: #717171; font-weight: bold } /* Name.Entity */ .highlight .ne { color: #CB3F38; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #00F } /* Name.Function */ .highlight .nl { color: #767600 } /* Name.Label */ .highlight .nn { color: #00F; font-weight: bold } /* Name.Namespace */ .highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #19177C } /* Name.Variable */ .highlight .ow { color: #A2F; font-weight: bold } /* Operator.Word */ .highlight .w { color: #BBB } /* Text.Whitespace */ .highlight .mb { color: #666 } /* Literal.Number.Bin */ .highlight .mf { color: #666 } /* Literal.Number.Float */ .highlight .mh { color: #666 } /* Literal.Number.Hex */ .highlight .mi { color: #666 } /* Literal.Number.Integer */ .highlight .mo { color: #666 } /* Literal.Number.Oct */ .highlight .sa { color: #BA2121 } /* Literal.String.Affix */ .highlight .sb { color: #BA2121 } /* Literal.String.Backtick */ .highlight .sc { color: #BA2121 } /* Literal.String.Char */ .highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */ .highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */ .highlight .s2 { color: #BA2121 } /* Literal.String.Double */ .highlight .se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */ .highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */ .highlight .si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */ .highlight .sx { color: #008000 } /* Literal.String.Other */ .highlight .sr { color: #A45A77 } /* Literal.String.Regex */ .highlight .s1 { color: #BA2121 } /* Literal.String.Single */ .highlight .ss { color: #19177C } /* Literal.String.Symbol */ .highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #00F } /* Name.Function.Magic */ .highlight .vc { color: #19177C } /* Name.Variable.Class */ .highlight .vg { color: #19177C } /* Name.Variable.Global */ .highlight .vi { color: #19177C } /* Name.Variable.Instance */ .highlight .vm { color: #19177C } /* Name.Variable.Magic */ .highlight .il { color: #666 } /* Literal.Number.Integer.Long */</style> <style> @font-face { font-family: 'MonaspaceArgon'; src: url('/assets/fonts/MonaspaceArgon-Regular.woff2') format('woff2'); font-weight: 400; font-style: normal; } pre, code { font-family: 'MonaspaceArgon', ui-monospace, monospace; } </style> <p>Every so often, I publish a blog post with a longer title. When this happens, sometimes the post title wraps onto a second line in my list of blog posts on my site home page. This was a tiny detail, but one that I would often notice.</p><p>Last night, I brought the design to <a href="https://indieweb.org/events/2026-07-16-front-end-study-hall" rel="noreferrer">Front End Study Hall</a>, and asked what I could do to make the text better aligned. For context, the following screenshot shows the grid of links on my home page, with one post, the post about an IndieWeb event in the Southeast Asia / Pacific time zone, wrapping <sup class="footnote-reference" id="f-1"><a href="https://jamesg.blog/longform-feed#1">1</a></sup>:</p><figure><picture><img alt='A grid with two columns: one with the heading "Explore", the other with the heading "Recent essays". All links except for one, the third link down in the "Recent essays" column, span one line.' loading="lazy" src="https://editor.jamesg.blog/content/images/2026/07/links1.png" style=" max-width: 130%;"/></picture><div class="alt"><label><input aria-label="Toggle image alt text on screen" type="checkbox"/>ALT</label><div class="content">A grid with two columns: one with the heading "Explore", the other with the heading "Recent essays". All links except for one, the third link down in the "Recent essays" column, span one line.</div></div></figure><p>When a link overflowed to a new line, the text was subtly grouped together, so there was a visual indication that both lines were part of the same text. But, when this happened, the rest of the list would be misaligned with the first list to the left. This was the problem I wanted to solve in FrESH, but I came out with another idea.</p><p>We spoke about the grid alignment issue, but the bigger reservation I had became clearer: I was unhappy with how titles that spanned multiple lines appeared.</p><p>During the call, <a href="https://gregorlove.com/">gRegor</a> shared an idea related to distinguishing if a link had spanned multiple lines: what if I used <code>text-indent</code> to indent the text on a multi-line link? The results looked great. The rule we came up with was:</p><div class="highlight"><pre><span></span><span class="nt">nav</span><span class="w"> </span><span class="nt">ul</span><span class="w"> </span><span class="nt">li</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="k">text-indent</span><span class="p">:</span><span class="w"> </span><span class="mi">-1</span><span class="kt">rem</span><span class="p">;</span> <span class="w"> </span><span class="k">padding-left</span><span class="p">:</span><span class="w"> </span><span class="mi">1</span><span class="kt">rem</span><span class="p">;</span> <span class="p">}</span> </pre></div> <p>This would add left padding to all of the <code>li</code> elements, and indent the text by <code>-1rem</code>. The text indent rule only applies to the first line by default, so this rule would mean that all text except for the first line in each link would be pushed left.</p><p>After the call, I learned I can accomplish this in a single line:</p><div class="highlight"><pre><span></span><span class="nt">nav</span><span class="w"> </span><span class="nt">ul</span><span class="w"> </span><span class="nt">li</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="k">text-indent</span><span class="p">:</span><span class="w"> </span><span class="mi">1</span><span class="kt">rem</span><span class="w"> </span><span class="kc">hanging</span> <span class="p">}</span> </pre></div> <p><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/text-indent">Per the MDN documentation on text-hanging:</a></p><blockquote><code>hanging</code> <br/><br/> Inverts which lines are indented. All lines <em>except</em> the first line will be indented.</blockquote><p>Now, my site home page grid looks like this:</p><figure><picture><img alt="My home page grid with two columns. This time, the second line in the link that spans two lines is indented, creating a cleaner, clearer visual indication that there is a relationship between the first and second lines." loading="lazy" src="https://editor.jamesg.blog/content/images/2026/07/links2.png" style=" max-width: 130%;"/></picture><div class="alt"><label><input aria-label="Toggle image alt text on screen" type="checkbox"/>ALT</label><div class="content">My home page grid with two columns. This time, the second line in the link that spans two lines is indented, creating a cleaner, clearer visual indication that there is a relationship between the first and second lines.</div></div></figure><p>The second line in the long link is now indented. I really like this design. I didn’t consider the idea of indenting until gRegor mentioned it and we saw it on the page.</p><p>I also used this as an opportunity to clean the markup on my home page, moving several inline styles to the main CSS, removing unused styles, and simplifying the markup (which let me remove a few <code>div</code> tags – yay!). I added some more spacing between each link so that the lists breathe a bit more.</p><p>We had several ideas on how to keep both lists aligned, but this is something I might explore another day. For now, I am happy with the greater visual cue that the second line of a link is part of the first line afforded by indenting the second line (and subsequent lines) above the first line.</p><p><em>Thank you to everyone who attended Front End Study Hall and shared feedback and ideas related to this design problem.</em></p> <div class="footnote-definition" id="1"><sup class="footnote-definition-label" id="f-2">1</sup> <p>Note: The screenshot was taken from an archival copy of my site, so may not be exactly what it looked like on the page, but is close enough.</p> <a href="https://jamesg.blog/longform-feed#f-1">[↩]</a></div> <a class="tag" href="https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/text-indent">Per the MDN documentation on text-hanging:</a> <a class="tag" href="https://gregorlove.com/">gRegor</a> <a class="tag" href="https://indieweb.org/events/2026-07-16-front-end-study-hall">Front End Study Hall</a> <a class="tag" href="https://jamesg.blog/longform-feed#1">1</a> <a class="tag" href="https://jamesg.blog/longform-feed#f-1">[↩]</a> Thursday, July 16, 2026 - Baty.net https://baty.net/journal/16Jul26/ 2026-07-16T12:56:06.000Z <figure><img src="https://baty.net/img/2026/20260716-avatar-photo.jpg" alt="Black and white photo of man pushing woman in a wheelbarrow"><figcaption>The (found) photo I use for my avatar</figcaption></figure><p>The wildfire smoke here in west Michigan is the worst I've ever breathed. ::cough cough:: The sun looks like a copper penny left on the sidewalk.</p> <hr /> <p>I forgot to add the temp and date to today's photo and I don't feel like it now, so it remains plain.</p> <hr /> <p>A lot of the RSS feeds I follow lean macOS. Since I'm on Linux all day lately, I want to cover my ears and close my eyes and go &quot;La La La...&quot; whenever anyone writes about Mac stuff. Not because I'm not interested, but rather because I'm still <em>too</em> interested. Better to ignore it the best I can for a while or I'll never stick with Linux. FOMO runs deep.</p> <p><a href="mailto:jack@baty.net?subject=[Baty.net] Re: Thursday%2C%20July%2016%2C%202026">✍️ Reply by email</a></p> Re: An IndieWeb Event for Southeast Asia / Pacific Time Zones - James' Coffee Blog https://jamesg.blog/2026/07/16/indieweb-asia-pacific 2026-07-16T00:00:00.000Z <p><a href="https://burgeonlab.com/rsvps/2026/0715-1415/" rel="noreferrer">Naty is hosting a new Homebrew Website Club</a> event on Wednesday, August 5, 2026, at 5:30pm to 7:00pm Hong Kong Time (UTC+8). If there is interest, the event may turn become regular!</p><p>If the time works for you and you love chatting about websites, I recommend checking out the event. Homebrew Website Clubs are always fun, providing a place to chat about what people are building on their websites, the culture of the web, HTML/CSS, writing on the web, and more.</p><p>This event adds to several other online events, geared toward:</p><ul><li><a href="https://events.indieweb.org/2026/07/homebrew-website-club-europe-london-C7hLAVUWvWxs" rel="noreferrer">European timezones (HWC London/Europe)</a> (which I host!)</li><li><a href="https://events.indieweb.org/tag/eastern" rel="noreferrer">The US East Coast (HWC Eastern)</a></li><li><a href="https://events.indieweb.org/tag/pacific" rel="noreferrer">The US West Coast (HWC Pacific)</a></li></ul><p>Furthermore, there are in-person events that happen in several cities listed on the <a href="https://events.indieweb.org/" rel="noreferrer">IndieWeb Events community page</a>, and the <a href="https://blr.indiewebclub.org/" rel="noreferrer">IndieWebClub Bangalore website</a>, all of which are run to provide a place to chat for people passionate about websites.</p><script>(function(){function c(){var b=a.contentDocument||a.contentWindow.document;if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'a1c35a2bdf86f09c',t:'MTc4NDIyOTUwMA=='};var a=document.createElement('script');a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&amp;&amp;(document.onreadystatechange=e,c())}}}})();</script> <a class="tag" href="https://blr.indiewebclub.org/">IndieWebClub Bangalore website</a> <a class="tag" href="https://burgeonlab.com/rsvps/2026/0715-1415/">Naty is hosting a new Homebrew Website Club</a> <a class="tag" href="https://events.indieweb.org/">IndieWeb Events community page</a> <a class="tag" href="https://events.indieweb.org/2026/07/homebrew-website-club-europe-london-C7hLAVUWvWxs">European timezones (HWC London/Europe)</a> <a class="tag" href="https://events.indieweb.org/tag/eastern">The US East Coast (HWC Eastern)</a> <a class="tag" href="https://events.indieweb.org/tag/pacific">The US West Coast (HWC Pacific)</a> Emacs: ‘doric-lilac’ and ‘doric-borage’ coming to the ‘doric-themes’ - Protesilaos Stavrou: Master feed with all updates https://protesilaos.com/codelog/2026-07-16-emacs-doric-lilac-doric-borage/ 2026-07-16T00:00:00.000Z <p>I have been working on two new themes for my minimalist <code class="language-plaintext highlighter-rouge">doric-themes</code> package. The original plan was to publish them together as part of the version <code class="language-plaintext highlighter-rouge">1.2.0</code> from a few days ago (the version that also brought <code class="language-plaintext highlighter-rouge">doric-tiger</code> and <code class="language-plaintext highlighter-rouge">doric-lion</code>), but then I decided to refine them further.</p> <p><code class="language-plaintext highlighter-rouge">doric-lilac</code> is a light theme, while <code class="language-plaintext highlighter-rouge">doric-borage</code> is dark. I am still testing them, though in the screenshots below you can get a first look.</p> <p>Borage, by the way, occurs naturally in the mountains and there even is some in my land: all sorts of bees love it. I have seen lilac around, so I will need to transplant some of it here.</p> <h2>doric-lilac</h2> <p><a href="https://protesilaos.com/assets/images/attachments/2026-07-16-doric-lilac.png"><img alt="doric-lilac theme sample" src="https://protesilaos.com/assets/images/attachments/2026-07-16-doric-lilac.png" /></a></p> <h2>doric-borage</h2> <p><a href="https://protesilaos.com/assets/images/attachments/2026-07-16-doric-borage.png"><img alt="doric-borage theme sample" src="https://protesilaos.com/assets/images/attachments/2026-07-16-doric-borage.png" /></a></p> <h2>Part of development</h2> <p>The new themes will be available in version <code class="language-plaintext highlighter-rouge">1.3.0</code>. They already have the character I want from them, though I may still tweak some colour values.</p> <h2>Sources</h2> <p>The Doric themes use few colours and will appear monochromatic in many contexts. They are my most minimalist themes. Styles involve the careful use of typographic features and subtleties in colour gradients to establish a consistent rhythm.</p> <p>If you want maximalist themes in terms of colour, check my <code class="language-plaintext highlighter-rouge">ef-themes</code> package. For something in-between, which I would consider the best “default theme” for a text editor, opt for my <code class="language-plaintext highlighter-rouge">modus-themes</code>.</p> <ul> <li>Package name (GNU ELPA): <code class="language-plaintext highlighter-rouge">doric-themes</code></li> <li>Sample pictures: <a href="https://protesilaos.com/emacs/doric-themes-pictures">https://protesilaos.com/emacs/doric-themes-pictures</a></li> <li>Git repository: <a href="https://github.com/protesilaos/doric-themes">https://github.com/protesilaos/doric-themes</a></li> <li>Backronym: Doric Only Really Intensifies Conservatively … themes.</li> </ul> Wednesday, July 15, 2026 - Baty.net https://baty.net/journal/15Jul26/ 2026-07-15T12:36:46.000Z <figure><img src="https://baty.net/img/2026/20260715-tree-by-river-bw.webp" alt="Black and white photo of tree in front of a river"><figcaption>Tree in park (2026) - Rolleiflex 2.8D</figcaption></figure><div class="compact status"> <ul> <li><strong>STATUS</strong>: Cleaning up my Emacs config</li> <li><strong>TODO</strong>: Set up Mac Mini as a scanning station</li> <li><strong>READING</strong>: <a href="https://substack.magazinenongrata.com/p/how-i-learned-to-read-again">How I Learned to Read Again</a></li> <li><strong>LISTENING</strong>: Random music from my Navidrome server</li> </ul> </div> <p>After spending way too much time in the 100℉ heat yesterday, I plan to live in my little chair, in my little office, tinkering on my little computer, air-conditioned.</p> <hr /> <p>I like <a href="https://danklinux.org/">Dank Linux</a>, but Niri makes me think too much about window management. I know, a tiling window manager is supposed to help me <em>not</em> think about window management so much, but it does. Switched the desktop back to KDE for now.</p> <hr /> <p><a href="mailto:jack@baty.net?subject=[Baty.net] Re: Wednesday%2C%20July%2015%2C%202026">✍️ Reply by email</a></p> Fave and leas fave file formats - Baty.net https://baty.net/notes/2026/07/fave-and-leas-fave-file-formats/ 2026-07-15T12:09:35.000Z <p>This <a href="https://bsky.app/profile/mellymeldubs.bsky.social/post/3mqkxbvd3322n">post by @mellymeldubs on Bluesky</a> about favorite and least favorite file formats is fun. (via <a href="https://unsung.aresluna.org/if-heic-has-no-haters-im-dead/">“If HEIC has no haters I’m dead.” – Unsung</a>)</p> <p>Let's see...</p> <p>Favorite: .org</p> <p>Least favorite: .heic</p> <p><a href="mailto:jack@baty.net?subject=[Baty.net] Re: Fave%20and%20leas%20fave%20file%20formats">✍️ Reply by email</a></p> Improving my Emacs config a little - Baty.net https://baty.net/notes/2026/07/improving-my-emacs-config-a-little/ 2026-07-15T11:40:06.000Z <p>I've been cleaning up my Emacs config over the past couple of days.</p> <p>Capture templates are now consistent and sane. My inbox is explicit and forces review. Org-agenda files are calculated based on timestamps via org-mem. Claude added an org-node-dblocks function (mimicking denote) so I can embed org-node queries into files. I get behind on this sometimes and it feels nice to clean it up.</p> <p><a href="mailto:jack@baty.net?subject=[Baty.net] Re: Improving%20my%20Emacs%20config%20a%20little">✍️ Reply by email</a></p> Selfie: on a casual walk, facing the sun - Protesilaos Stavrou: Master feed with all updates https://protesilaos.com/selfies/2026-07-15-facing-sun-casual-walk/ 2026-07-15T00:00:00.000Z I was out on a walk and took this picture while looking in the direction of the sun. I unplugged the Mac Mini today - Baty.net https://baty.net/posts/2026/07/i-unplugged-the-mac-mini-today/ 2026-07-14T20:34:44.000Z <figure><img src="https://baty.net/img/2026/20260714-mac-mini-unplugged.jpg" alt="A Mac Mini and hard drive with loose cords around it"><figcaption>Unplugged.</figcaption></figure><p>I'm <em>really</em> enjoying Linux right now (both KDE and <a href="https://danklinux.com/">Dank Linux</a> with <a href="https://github.com/niri-wm/niri">Niri</a>). It could be just a mood (it usually is), but I've noticed that whenever I'm using the Mac, I just want to switch back. This is new to me.</p> <!-- more --> <p>On the other hand, I cannot resist the urge to try every new thing I read about that's macOS only. So, whenever some cool new app is mentioned, it's a simple matter of swapping one cable and pressing a button on the mouse and POOF!, I'm wasting half a day on some new toy that I'll probably only use for a week anyway.</p> <p>I've removed that temptation. The Mac Mini is now powered down, unplugged, and sitting in a corner of my office. What will likely happen is that I'll set it up as a film scanning station, since I'm still not all-in with Linux for that process. Most importantly, I can't reach for it every time I get the urge.</p> <p>OK, I still have the MacBook Air, but that's different. At least that's what I'm saying. It's a satellite machine, not the main desktop. I don't do much on the laptops, so it doesn't count :).</p> <p>One thing I had to deal with was the OWC &quot;MiniStack&quot; that was attached to the Mini. It has a 2TB SSD and an 8TB HDD in it. Both were formatted APFS, so I had to move things around, reformat as Ext4, and put stuff back. Now the MiniStack is attached to the little Beelink and seems to be working great.</p> <figure> <img src="https://baty.net/img/2026/20260714-beelink-devices.png" alt="List of hard drives" /> <figcaption>4 external drives</figcaption> </figure> <p>I even figured out the issues with Linux and the CalDigit hub. I needed to use an actual Thunderbolt port. The Beelink didn't have an extra, but the MiniStack does, which is nice.</p> <p>What this means is that I'm basically a full-time Linux user right now.</p> <p><a href="mailto:jack@baty.net?subject=[Baty.net] Re: I%20unplugged%20the%20Mac%20Mini%20today">✍️ Reply by email</a></p> Tuesday, July 14, 2026 - Baty.net https://baty.net/journal/14Jul26/ 2026-07-14T19:38:22.000Z <figure><img src="https://baty.net/img/2026/20260714-landscaping.webp" alt="Overgrown area in my yard"><figcaption>I let this go for way too long.</figcaption></figure><div class="compact status"> <ul> <li><strong>STATUS</strong>: Sweating my a$$ off</li> <li><strong>TODO</strong>: Landscaping when it's 100℉</li> <li><strong>READING</strong>: Still working through Middlemarch</li> <li><strong>WATCHING</strong>: &quot;Fisk&quot; - it's funny.</li> </ul> </div> <p>I deleted my LinkedIn account, today. That felt good.</p> <hr /> <p>Adding cover images to blog posts isn't hard, but it's not super easy either. Today, with Claude Code's help, I now have functions that do the work for me. All I do is invoke jab/baty-set-cover, select a file using Dired, type a caption, and the image is moved and renamed, and the front matter is filled in for me. It's a small quality of life thing, but it's great. We had it all put together in less than 30 minutes. I would never have bothered trying to tackle it alone. Crazy world.</p> <hr /> <p><a href="mailto:jack@baty.net?subject=[Baty.net] Re: Tuesday%2C%20July%2014%2C%202026">✍️ Reply by email</a></p> On planting seeds - Manuel Moreale RSS Feed https://manuelmoreale.com/@/page/joisowp0yvbww1jk 2026-07-14T13:10:00.000Z <p><a href="https://webcurios.co.uk/">Matt</a> asked me a question recently about the end of my People and Blogs run. The question was if I always thought I was going to hand it over at some point, and it’s an interesting question worth expanding on, which is why I told him I was going to write a post about it, rather than simply answering via email.</p> <p>I started and ended more online projects than I can remember at this point. I bought a dozen domain names, coded way too many sites, only to have them all inevitably bite the dust, sometimes months later, sometimes years later. But I don’t think I ever started a project with a set deadline in mind. All the projects were open-ended, always. </p> <p>Back in September 2021, <a href="https://manuelmoreale.com/thoughts/six-seven-eight">I posted about the shutting down of my thegallery.io</a>, a site I ran for almost 7 years, and in that post, I wrote</p> <blockquote> <p>Once the passion is gone, it is gone. There's no point in dragging things until you reach some random date in the future.</p> </blockquote> <p>When I started People and Blogs, the plan was to run it for a single year: 52 interviews, that was the plan. But then the end arrived, and people enjoyed the series, so I kept going. But at some point, I crossed the imaginary line that separates doing something because I enjoy it, and doing something because other people enjoy it. If you do something long enough, you almost always end up inevitably crossing that line. There are exceptions—there are always exceptions—but that’s what my experience taught me.</p> <p>And it’s weird how the process of realising that something is done works. Because at first I was simply carried forward by the momentum, by the established routines. I was sending emails, posting updates, and scheduling interviews. But the moment I considered the possibility of stopping, it was almost as if a seed got planted in the depths of my brain. This process kinda reminds me of the plot of the movie Inception. And once that seed was planted, it’s incredibly hard to eliminate. And it’s almost as if deep down I already knew the right thing to do but was too busy dealing with the routine to realise it. </p> <p>So to answer the original question, no, I didn’t know from the get go I was going to pass the series to someone else. But a part of me enjoys this process of seeing projects changing hands. I was happy to receive blogroll.org from <a href="https://alongtheray.com">Ray</a>, and I was equally as happy to hand over peopleandblogs.com to <a href="https://zacharykai.net">Zach</a>. It’s one of the many good qualities of this corner of the web I love to inhabit.</p> <p>The lesson I learned this time around is that projects need an endpoint! I’ll keep that in mind for the next time I inevitably start something new in a few years from now.</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> :: Games: Halo: The Master Chief Collection - Protesilaos Stavrou: Master feed with all updates https://protesilaos.com/games/2026-07-14-halo-master-chief-collection/ 2026-07-14T00:00:00.000Z <p><em>Halo: The Master Chief Collection</em> is not a single game. As its title suggests, it is a collection of games (<strong>spoilers throughout this article</strong>). They all belong to the first-person shooter genre. <em>Halo: Reach</em> and <em>Halo: ODST</em> do not feature the Master Chief, the protagonist of our story, but they are basically the same kind of game as the rest. All the games in the collection are nice. The controls are solid, the gameplay is engaging, the story is grand, and the music is outstanding.</p> <p><em>Halo</em> is set in a science fiction world far into the future. Humanity is warring against space aliens. The original antagonist is a coalition of different species known as the “Covenant”. Though early on we learn about a far greater danger described as the “Flood”. Then, in <em>Halo 4</em> we are introduced to “The Prometheans” with all the possible conflicts they can make possible.</p> <p>Humanity is technologically advanced. The culmination of its achievements is a transhumanist programme of supersoldiers known as “Spartans”. They are outfitted with the finest weaponry, their bodies are cybernetically augmented, and they can even have an actual artificial intelligence connected directly to their brain. In short, they are the absolute best warriors among the humans.</p> <p>Through most of the series we experience in first person the exploits of a certain Spartan known as the Master Chief. We learn that he is not necessarily the greatest of his kind in terms of physical prowess, though he has that intangible quality that lets him rise to the occasion and repeatedly prevail over his enemies.</p> <p>The Master Chief is a man of few words. Most of the talking is done by his superiors as well as his AI companion known as “Cortana”. As the story unfolds Master Chief and Cortana show signs of mutual feelings of Platonic love. Cortana eventually needs to be rescued and the Master Chief acts accordingly, making for a fine fit to the age-old trope of damsels in distress who are saved by some valiant warrior.</p> <p>Cortana is not some helpless lass though. She is a strong character with a nuanced story arc. Similarly, the Master Chief gives off the impression of a man who is bitterly defined by the circumstances of his life, has a hardened carapace around his core self, and allows no-one to get emotionally close. These are the kind of people who are empowered by their aloofness and resulting emotional stability, though they also are the ones who do not really relate to anyone. Their strength is their weakness.</p> <p>Cortana is probably the only one who understands the inner world of the Master Chief, in large part because she is, at times, directly wired to his brain. In a sense, she is less of a robot than the Master Chief because her emotional side is more pronounced. Whereas our hero finds solace in the role of the killing machine that others forced upon him when he was a little boy.</p> <p>Which brings me to the point of the Spartan programme. It is a clandestine operation of the regime, designed to develop soldiers who can counter any insurgency and keep revolutionaries at bay. The Spartans were not conceived as a noble end to contribute to the betterment of humankind, nor was their unit established in response to the formidable threat initially posed by the Covenant. The Spartans were—and might remain—mere tools in the hands of the bad guys.</p> <p>Yet herein lies an ancient insight about the world as admixture. Nothing is purely good or bad. It is both good and bad. More importantly, a good deed can have disastrous consequences while even the most horrific event can still produce benign results. We can only understand phenomena in this light when we are not invested in a specific outcome and are thus approaching them dispassionately.</p> <p>The Spartan programme reflects the unscrupulous nature of the powers that be. It is an abusive project in the service of a nefarious goal. Nevertheless, humanity would not survive the Covenant onslaught without the Spartans, let alone deal with the Flood. Nobody objects to being rescued by the Master Chief, for example, even though he truly is a potential weapon of mass destruction in the hands of tyranny. Each Spartan shall enforce the will of the establishment owning to years of indoctrination. To them it is their duty to protect, even though such is the conditioning of a ruthless apparatus of power.</p> <p>The state of admixture is everywhere beyond the science fiction setting. It is how our world is. The Iran war, for example, reminds us of the inexhaustible greed of our kind, here expressed through the machinations of the Western empire. Despite its horrors and attendant economic pressures, the ongoing conflict compels us to draw valuable lessons that can help us do something better for our future. If anything, there now is a greater sense of urgency to find solutions to the demand for energy. Those must be genuine alternatives to what worked hitherto. Whatever happens in the Strait of Hormuz, it is not viable that some sovereignist force can hold the rest of the world at ransom.</p> <p>Understanding the world as admixture does not mean that we offer a blank cheque for abuse, nor that we perform mental gymnastics to beautify—let alone justify—every atrocity imaginable. It simply is a matter of adopting a descriptive outlook, to recognise that one’s normative view of the world is not the world as-is, and then work with the state of affairs as it is made manifest.</p> <p>Coming back to the <em>Halo</em> universe, the otherwise terrifying prospect of the Flood consuming all life, engenders in members of humanity and the Covenant alike a sense of awareness in each other’s capacity for personhood. The Master Chief is no longer “the demon” in the eyes of his enemies, for example, but a stalwart fighter who epitomises the noble qualities that someone like the Arbiter also represents.</p> <p>This is not about a mere opportunistic political calculus, where the enemy of my enemy is an ally. It rather is a deeper realisation that the other side of this conflict is, in fact, not mindless and bestial as originally thought. The dynamic between the Master Chief and the Arbiter is one of cautiousness informed by respect. There remains distance due to all the bad blood, yet we can tell how there is hope for reconciliation no matter what has transpired.</p> <p>Same principle for the transhumanist agenda as such. Many parts of it can make us fearful of technology. I know I do not trust any moneyman with access to my brain and the rest of my body. Though such concerns also inspire us to explore what it means to be human and to become more humanised in the process.</p> <p>We are forced to look for the positives in our kind beyond the numerous negatives of domestic abuse, murder, serial killing, torture, genocide, and many more. Even if we think of transhumanism as the latent evil of our era, we have to acknowledge how it functions, including inadvertently, as a creative force that at once destroys our negativity about humanity and our romanticised view of humans, while giving us a reason to try our best and to seek the others.</p> <p>It then follows that we are presented with a mirror, which empowers us to be introspective and honest about our behaviour. It is not some figment of futuristic science that is robotising us, like, say, AI-capable computer chips attached to our body. We have been undergoing robotisation through analog means for decades, if not centuries, through systems of economic coordination that render us little more than cogs in a machine.</p> <p>Our values have been eroded, as we see everything, including romance, through the prism of money and prestige. The corruption is so deeply rooted that we conflate this with the natural order of things. In the meantime, we have abandoned the lands, extended families, and local communities that served us well for millennia to become mere numbers in the megalopoles of this world, suffering from permanent stress, insecurity, and some elusive dread.</p> <p>There is so much more to comment on regarding <em>Halo: The Master Chief Collection</em>, but I will leave it here. As you can tell, I am more interested in using the game as a pretext to expound on what I would have written about anyway, than to partake in the fanfare. Make no mistake though, <em>Halo</em> is a remarkable contribution to our culture.</p> Wonders of Web Weaving, Episode 10 - James' Coffee Blog https://jamesg.blog/2026/07/14/www-10 2026-07-14T00:00:00.000Z <p><a href="https://web-weaving.jamesg.blog/10" rel="noreferrer">The tenth episode of Wonders of Web Weaving is out</a>:</p><blockquote>In Episode 10, I chat with <a href="https://cloudlord.management/">Kristoffer</a> and <a href="https://elliott.computer">Elliott</a>, the creators of the <a href="https://internetphonebook.net/">Internet Phone Book</a>. We talk about, among other things, the history of the Internet Phone Book, the affordances of physical books for a community project, 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><script>(function(){function c(){var b=a.contentDocument||a.contentWindow.document;if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'a1aee4f48ba06c19',t:'MTc4NDAxNDk4NA=='};var a=document.createElement('script');a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&amp;&amp;(document.onreadystatechange=e,c())}}}})();</script> <a class="tag" href="https://cloudlord.management/">Kristoffer</a> <a class="tag" href="https://elliott.computer">Elliott</a> <a class="tag" href="https://internetphonebook.net/">Internet Phone Book</a> <a class="tag" href="https://web-weaving.jamesg.blog/10">The tenth 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> Running AOL Instant Messenger in 2026? - Baty.net https://baty.net/posts/2026/07/running-aol-instant-messenger/ 2026-07-13T12:59:53.000Z <p>There's a photo in my library from years ago showing my computer running AIM. A wave of nostalgia washed over me, as expected.</p> <!-- more --> <p>Then, yesterday I read <a href="https://veronicaexplains.net/open-oscar-server/">Here's how I host my own AIM server</a> and I had to try it.</p> <p>Read Veronica's post for everything you'd need, but basically all I did was...</p> <ol> <li>Run the server binary on a VPS with the IP configured as a listener</li> <li>Installed AIM 5.1 via the <a href="https://archive.org/details/aim513036">AIM installer from archive.org</a> using <a href="https://gitlab.winehq.org/wine/wine/-/wikis/Download">wine</a> (on Linux)</li> <li>Changed the AIM config to use my server IP.</li> </ol> <p>That was pretty much it.</p> <figure> <img src="https://baty.net/img/2026/20260713-aim.webp" alt="" /> <figcaption>AIM 5.1 for Windows running via wine on Linux</figcaption> </figure> <p>The chat sounds are so great to hear again. If you're interested in trying it and have an AIM or newer ICQ client installed, let me know and I'll add you to the server. It's fun!</p> <p><a href="mailto:jack@baty.net?subject=[Baty.net] Re: Running%20AOL%20Instant%20Messenger%20in%202026%3F">✍️ Reply by email</a></p>