<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://planet.emacslife.com/</id>
    <title>Planet Emacslife</title>
    <updated>2026-06-16T18:32:10.880Z</updated>
    <generator>https://github.com/gap-hub/feed</generator>
    <author>
        <name>Various authors</name>
    </author>
    <link rel="alternate" href="https://planet.emacslife.com/"/>
    <link rel="self" href="https://planet.emacslife.com/atom.xml"/>
    <rights>Various authors</rights>
    <entry>
        <title type="html"><![CDATA[Dave Pearson: become.el v1.4.0]]></title>
        <id>https://blog.davep.org/2026/06/16/become-el-v1-4-0.html</id>
        <link href="https://blog.davep.org/2026/06/16/become-el-v1-4-0.html"/>
        <updated>2026-06-16T15:19:59.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>In the last month or so, as I've mentioned a few times before, I've been
trying to tidy up some of my older personal <a href="https://blog.davep.org/tag/emacs-lisp/">Emacs Lisp</a>
packages. I <em>thought</em> I'd updated all the ones I commonly use, but it turns
out I hadn't. Somehow I'd missed
<a href="https://github.com/davep/become.el" target="_blank"><code>become.el</code></a>.</p>
<p>This is another one of those packages whose content started out as ad-hoc
commands, added to the <code>~/.emacs</code> that first started to emerge as I got to
know Emacs on OS/2 and then GNU/Linux back in the mid-1990s. I think it was
back in 2016<sup><a href="https://blog.davep.org/#fn:401-1">1</a></sup>, when I did <a href="https://blog.davep.org/2016/05/26/starting_fresh_with_gnu_emacs.html">a big revamp of my Emacs
environment</a>, that I moved
all of those roughly-related commands out into their own file.</p>
<p>Honestly, I think I can dump most of them now. There's stuff in there for
quickly and easily converting buffers between "DOS format" and "Unix format"
(from back when I was still working a lot on Windows machines, and sometimes
even in MS-DOS-based virtual machines, and often using the
<a href="https://www.delorie.com/djgpp/" target="_blank">DJGPP</a>-built version of Emacs).</p>
<p>One command I still use all the time is
<code>become-free-of-trailing-whitespace</code>, because I have that set up as part of
a <code>before-save-hook</code>:</p>
<div class="highlight"><pre><span></span><code><span class="p">(</span><span class="nb">use-package</span><span class="w"> </span><span class="nv">become</span>
<span class="w">  </span><span class="nb">:ensure</span><span class="w"> </span><span class="no">t</span>
<span class="w">  </span><span class="nb">:defer</span><span class="w"> </span><span class="no">t</span>
<span class="w">  </span><span class="nb">:vc</span><span class="w"> </span><span class="p">(</span><span class="nb">:url</span><span class="w"> </span><span class="s">"https://github.com/davep/become.el"</span><span class="w"> </span><span class="nb">:rev</span><span class="w"> </span><span class="nb">:newest</span><span class="p">)</span>
<span class="w">  </span><span class="nb">:commands</span><span class="w"> </span><span class="nv">become-free-of-trailing-whitespace</span>
<span class="w">  </span><span class="nb">:init</span>
<span class="w">  </span><span class="p">(</span><span class="nb">unless</span><span class="w"> </span><span class="nv">noninteractive</span>
<span class="w">    </span><span class="p">(</span><span class="nv">add-hook</span><span class="w"> </span><span class="ss">'before-save-hook</span><span class="w"> </span><span class="nf">#'</span><span class="nv">become-free-of-trailing-whitespace</span><span class="p">))</span>
<span class="w">  </span><span class="nb">:bind</span>
<span class="w">  </span><span class="p">(</span><span class="s">"&lt;f12&gt; &lt;tab&gt;"</span><span class="w"> </span><span class="o">.</span><span class="w"> </span><span class="nv">become-freshly-indented-no-tabs</span><span class="p">))</span>
</code></pre></div>

<p>While I know that there are better ways of handling the trailing space issue
these days, this is one I rolled for myself a couple of decades ago and it's
yet to fail me. You can see just how dated it is from this:</p>
<div class="highlight"><pre><span></span><code><span class="p">(</span><span class="nb">cl-flet</span><span class="w"> </span><span class="p">((</span><span class="nv">is-sig-line</span><span class="w"> </span><span class="p">()</span>
<span class="w">                       </span><span class="p">(</span><span class="k">save-excursion</span>
<span class="w">                         </span><span class="p">(</span><span class="nf">beginning-of-line</span><span class="p">)</span>
<span class="w">                         </span><span class="p">(</span><span class="nf">looking-at</span><span class="w"> </span><span class="s">"^-- $"</span><span class="p">)))</span>
<span class="w">          </span><span class="p">(</span><span class="nv">markdown-br-p</span><span class="w"> </span><span class="p">()</span>
<span class="w">                         </span><span class="p">(</span><span class="k">save-excursion</span>
<span class="w">                           </span><span class="p">(</span><span class="nf">beginning-of-line</span><span class="p">)</span>
<span class="w">                           </span><span class="p">(</span><span class="k">and</span><span class="w"> </span><span class="p">(</span><span class="nf">eq</span><span class="w"> </span><span class="nv">major-mode</span><span class="w"> </span><span class="ss">'markdown-mode</span><span class="p">)</span>
<span class="w">                                </span><span class="p">(</span><span class="nf">looking-at</span><span class="w"> </span><span class="s">"^.+[^ ]  $"</span><span class="p">)))))</span>
<span class="c1">; ...body removed</span>
<span class="p">)</span>
</code></pre></div>

<p>If you know, you'll know why <code>is-sig-line</code> is there<sup><a href="https://blog.davep.org/#fn:401-2">2</a></sup>.</p>
<p>I do still use <code>become-freshly-indented-no-tabs</code> on occasion too, and have
it bound to an easy-to-remember and obvious (to me) key.</p>
<p>And so, despite the fact that most of the content of <code>become.el</code> is probably
obsolete at this point, despite the fact that there are probably far better
and more idiomatic ways of doing these things these days... it's my little
personal package that has grown with me in the 3 (and a bit) decades I've
had Emacs under my fingertips. I'm going to keep it around just a little
longer.</p>
<div class="footnote">
<hr>
<ol>
<li>
<p>The header for <code>become.el</code> says 2017, but I think the header itself
came a little later when I <a href="https://blog.davep.org/2017/04/01/another_revamp_of_my_emacs_config.html">did some more work on my
config</a>.&nbsp;<a href="https://blog.davep.org/#fnref:401-1">↩</a></p>
</li>
<li>
<p>And if you don't know, <a href="https://en.wikipedia.org/wiki/Signature_block#Standard_delimiter" target="_blank">now you
do</a>.&nbsp;<a href="https://blog.davep.org/#fnref:401-2">↩</a></p>
</li>
</ol>
</div></body></html>]]></content>
        <author>
            <name>Dave Pearson</name>
            <uri>https://blog.davep.org</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Irreal: Scrolling PDFs In Other Windows]]></title>
        <id>https://irreal.org/blog/?p=13880</id>
        <link href="https://irreal.org/blog/?p=13880"/>
        <updated>2026-06-16T14:28:32.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>
Marcin Borkowski (mbork) has a useful post on scrolling PDFs in the other window. He wants to use the familiar <kbd>Ctrl</kbd>+<kbd>Meta</kbd>+<kbd>v</kbd> and <kbd>Ctrl</kbd>+<kbd>Meta</kbd>+<kbd>Shift</kbd>+<kbd>v</kbd> shortcuts for <a href="https://github.com/vedang/pdf-tools">pdf-tools</a>. Sadly, these don’t work for scrolling PDFs but as mbork says, <a href="https://mbork.pl/2026-06-15_Scrolling_pdfs_in_other_windows">“… [I]t’s Emacs, so it shouldn’t be difficult…”</a>. And, indeed, it isn’t.
</p>
<p>
His idea is simple. If the buffer in the other window isn’t a PDF, return <code>nil</code>. Otherwise simply call <code>pdf-view-scroll-up-or-next-page</code> or <code>pdf-view-scroll-down-or-previous-page</code>. Finally, he simply advises <code>scroll-other-window</code> and <code>scroll-other-window-down</code> to run his code first and skip the normal code unless his code returns <code>nil</code>. Take a look at his post for the code. As I said, it’s easy to understand.
</p>
<p>
The important takeaway from this, according to mbork, is how easy and understandable the solution is. The lesson, as it often is, is that if Emacs isn’t doing what you need, it’s usually pretty easy to make it do so.</p>
</body></html>]]></content>
        <author>
            <name>Irreal</name>
            <uri>https://irreal.org/blog</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Meta Redux: CIDER 1.22 (“São Miguel”)]]></title>
        <id>https://metaredux.com/posts/2026/06/16/cider-1-22.html</id>
        <link href="https://metaredux.com/posts/2026/06/16/cider-1-22.html"/>
        <updated>2026-06-16T09:00:00.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>Great news, everyone - <a href="https://github.com/clojure-emacs/cider/releases/tag/v1.22.0">CIDER 1.22</a> (“São Miguel”) is finally out!</p>

<p>And “finally” is the operative word here. This release took me way longer than
I wanted it to, but that’s because I decided to stop kicking a few cans down the
road and finally tackle some long-standing problems that had been bugging me for
years:</p>

<ul>
  <li>Session and connection management - the logic for figuring out which REPL a
buffer is associated with had grown into something I could barely follow myself.</li>
  <li>The decoupling of nREPL from CIDER’s UI layer - a piece of technical debt so
old it predates most of you reading this (the tracking issue, <a href="https://github.com/clojure-emacs/cider/issues/1099">#1099</a>, is from 2017).</li>
  <li>A full audit of the codebase and the documentation, hunting for
inconsistencies, dead code, broken menu entries, and gaps in the docs.</li>
</ul>

<p>None of this is the kind of work that makes for a flashy release announcement,
but it’s exactly the kind of work that keeps a 14 year old project healthy. I
genuinely think this is one of the most important CIDER releases in recent
memory, even though most of the changes aren’t really user-visible.</p>

<h2>Highlights</h2>

<p>Picking a handful of items out of a very long changelog, here’s what I’d call
the highlights:</p>

<ul>
  <li><strong>A huge editor responsiveness fix</strong> (<a href="https://github.com/clojure-emacs/cider/issues/3933">#3933</a>) - Clojure buffers no longer lag when there’s no REPL connected. The friendly-session matching used to scan the project classpath on every redisplay; now it does something far cheaper. If you’ve ever felt CIDER make your editing sluggish, this one’s for you.</li>
  <li><strong>Default sessions</strong> (<a href="https://github.com/clojure-emacs/cider/pull/3865">#3865</a>) - <code class="language-plaintext highlighter-rouge">cider-set-default-session</code> lets you bypass sesman’s project-based dispatch and pin a REPL as the default. Handy for all those workflows that never quite fit the project model.</li>
  <li><strong>nREPL is now decoupled from CIDER’s UI</strong> (<a href="https://github.com/clojure-emacs/cider/pull/3892">#3892</a>) - the transport layer no longer reaches into CIDER-specific handlers and UI strings. This finally closes <a href="https://github.com/clojure-emacs/cider/issues/1099">#1099</a> and opens the door for other tools to build on our nREPL client.</li>
  <li><strong>Faster connection completions</strong> (<a href="https://github.com/clojure-emacs/cider/pull/3888">#3888</a>) - repeated <code class="language-plaintext highlighter-rouge">cider-connect</code> completions no longer re-spawn a round of <code class="language-plaintext highlighter-rouge">ps</code>/<code class="language-plaintext highlighter-rouge">lsof</code> subprocesses every single time.</li>
  <li><strong>A massive discoverability pass on menus and keybindings</strong> - menus across the inspector, REPL history, log, spec browser, and more now actually expose the commands they were missing (often a dozen+ per mode), and <code class="language-plaintext highlighter-rouge">C-h m</code> now lists the active bindings for several modes. A lot of functionality that was technically there but practically invisible is now front and center.</li>
  <li><strong><code class="language-plaintext highlighter-rouge">cider-repl-history-doctor</code></strong> (<a href="https://github.com/clojure-emacs/cider/pull/3921">#3921</a>) - a new command that walks your REPL history, finds entries with unbalanced parens, and helps you clean them up. Born out of a real bug report about history rendering breaking.</li>
  <li><strong>Support for <a href="https://github.com/nooga/let-go">let-go</a></strong> (<a href="https://github.com/clojure-emacs/cider/pull/3926">#3926</a>) - a Clojure dialect implemented in Go is now recognized as a known nREPL runtime.</li>
  <li><strong>Better remote (TRAMP) jack-in and connect</strong> (<a href="https://github.com/clojure-emacs/cider/pull/3885">#3885</a>, <a href="https://github.com/clojure-emacs/cider/pull/3886">#3886</a>, <a href="https://github.com/clojure-emacs/cider/pull/3887">#3887</a>) - endpoint detection, command resolution, and SSH tunneling all behave correctly against remote hosts now.</li>
  <li><strong>Plenty of nREPL robustness fixes</strong> - plugged several request-id leaks, bounded the completed-requests table, and made a misbehaving response handler no longer able to drop later responses on the floor.</li>
  <li>Bumped the injected <code class="language-plaintext highlighter-rouge">nREPL</code> to 1.7.0 and <code class="language-plaintext highlighter-rouge">cider-nrepl</code> to 0.59.0.</li>
</ul>

<p>The full list is much longer - check out the <a href="https://github.com/clojure-emacs/cider/blob/master/CHANGELOG.md">changelog</a> if you want the gory details.</p>

<h2>A fun little detour: Port and Neat</h2>

<p>While I was doing the nREPL decoupling work, I got curious and started
experimenting with adding support for <a href="https://clojure.org/reference/repl_and_main#prepl">prepl</a>
(Clojure’s built-in socket REPL) as an alternative to nREPL. I even put together
a prototype (<a href="https://github.com/clojure-emacs/cider/pull/3899">cider#3899</a>). It
sort of worked, but it also reaffirmed my belief that prepl and nREPL are
different enough that bolting prepl onto CIDER would mean papering over its
limitations in dozens of subtle places. So instead of forcing it, that little
experiment grew into two brand new projects of mine:</p>

<ul>
  <li><a href="https://batsov.com/articles/2026/05/12/port-a-minimalist-prepl-client-for-emacs/"><strong>Port</strong></a> - a minimalist prepl client for Emacs.</li>
  <li><a href="https://batsov.com/articles/2026/05/20/neat-a-language-agnostic-nrepl-client-for-emacs/"><strong>Neat</strong></a> - a tiny, deliberately language-agnostic nREPL client.</li>
</ul>

<p>Both have write-ups of their own, so I won’t repeat the details here. I’m pretty
excited about where they might lead - a great example of how digging into old
technical debt can spark entirely new ideas.</p>

<h2>Epilogue</h2>

<p>This release is dedicated to São Miguel, the stunningly beautiful main island of
the Azores archipelago.<sup><a href="https://metaredux.com/#fn:1">1</a></sup> I got a lot of my recent inspiration for CIDER there,
and naming the release after it felt right.</p>

<p>As always, none of this happens in a vacuum. A huge thank you to Alex Yakushev
for his continued work on the inspector - it keeps getting better and better. And
of course a massive shoutout to <a href="https://www.clojuriststogether.org/">Clojurists Together</a>
and to all the other contributors and backers of my open-source work. You’re the
reason CIDER and friends keep moving forward.</p>

<p>That’s all I have for you today. I hope you’ll enjoy using CIDER 1.22 as much as
I enjoyed (eventually) shipping it. Keep hacking!</p>

<div class="footnotes">
  <ol>
    <li>
      <p>If you ever get the chance to visit, do it. Crater lakes, hot springs, and the greenest hills you’ve ever seen.&nbsp;<a href="https://metaredux.com/#fnref:1">↩</a></p>
    </li>
  </ol>
</div></body></html>]]></content>
        <author>
            <name>Meta Redux</name>
            <uri>https://metaredux.com/</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Raymond Zeitler: Emacs Carnival: diary, Part 1]]></title>
        <id>https://ray-on-emacs.blogspot.com/2026/06/emacs-carnival-diary-part-1.html</id>
        <link href="https://ray-on-emacs.blogspot.com/2026/06/emacs-carnival-diary-part-1.html"/>
        <updated>2026-06-16T03:38:44.378Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>When I adopted Emacs in July of 2000, I hunkered down to learn the
  keybindings.  But after I learned the basics<sup>1</sup> I started
  to RTFM (<code>C-h r</code>), and I was instantly drawn to the
  Calendar/Diary<sup>2</sup> node, which I consider to be an
  underappreciated Emacs built-in, and, therefore, the topic of Emacs
  Carnival for June 2026.</p>
<p>Back then I mistook "diary" to mean a blank-page-confidant into
    which we write our thoughts, fears, ambitions or even just what we
    had for dinner last night.  At that time I'd been writing in
    a journal for about 24 years (yes, since 1976, on and off), so my head
    swelled with ideas of using Emacs for a revamped computerized
    version.  I imagined being able to <code>forward-search-regexp</code>
  in order
    to find, for example, that weird dream I wrote about in which I
    caught a toad that was hopping around the kitchen and then turned
    into a hot coal sizzling in my hand...</p>
<p>I used <code>diary-block</code> functions to date my entries and
  organize the content.  I ended up making four such entries from 2003
  to 2004.  But each day following the entry, <code>M-x diary</code>
  would display a nearly blank buffer, showing only the day's date at
  the top followed by a line of equal signs and perhaps a holiday.
  Where did yesterday's entry go?!  It was disconcerting that those
  words "vanished" into thin air magnetic film or
  silicon.</p>
<p>Today, however, I appreciate the simplicity of that approach -- a
    clean slate sans distractions.  But back then I was accustomed to
    seeing a vast amount of my writing, which fed my ego.</p>
<p>But that's not all there is to appreciate.  There are several
    functions that can be used for "an entry" in addition to
    <code>diary-block</code>, such as <code>diary-anniversary</code>, <code>diary-cyclic</code>, <code>diary-float</code> or even just a simple line that begins with a date and a brief note.  This is not an all-inclusive list.</p>
<p>Every fancy diary buffer can show local time of sunrise and sunset;
    to do this, include <code>diary-sunrise-sunset</code> in the diary file.
    Include <code>diary-lunar-phases</code> to show one of the four
    phases of the moon when one is active on that day; the
    local time of that moon phase will be included.</p>
<p>What follows is an abbreviated and edited listing of my diary
  files.  Note how I've structured <code>diary</code> into a hierarchy
  using <code>include</code> statements.</p>
<p> The beauty of this is that these events will show up in Org Agenda
    at the appropriate times when <code>org-agenda-include-diary</code>
  is non-nil.</p>
<p>Four examples are shown below.  Here are some things to note:
  </p><ul>
    <li>The content that's derived from the diary file has "Diary" for value of CATEGORY.</li>
    <li>The Sunrise / Sunset lines are supposed to show the time of
    each occurance.  However, the time for Sunrise isn't displayed;
    rather, it's indicated by its position on the time grid.  The times for both the New Moon and the Solar Eclipse are indicated by the time grid, as well, and are expected to peak at 13:38 in my area.  That's something to look faroward to!</li>
    <li>Sometimes I include links in my headings.  In this case I can
    follow a link to the credit card website to pay the Visa
    card.</li>
    <li>Even a link in the dairy file will be rendered
    in the Agenda properly, as shown in the reference for Richard
    Stallman's birthday.</li>
    <li>
  </li></ul>

<blockquote>
  file listing: diary
  <pre>#    -*- mode: diary -*-<br>
#include "diary-anniversaries-property"
#include "diary-birthdays-friends"

%%(diary-sunrise-sunset)
%%(diary-lunar-phases)

%%(diary-remind '(diary-anniversary 3 16 1953) 14) [[https://html.duckduckgo.com/html/?q=Richard+Stallman+birthday][Richard Stallman's birthday]] in 14 days

%%(diary-block 6 21 2004 6 21 2004) The summer solstice.  I
always take time to observe the position of the sun on this
day, especially in the morning and evening.  Sunrise was at
5:16am and sunset will be at 8:29pm.  From today onward, the
days will be getting shorter.  At first it will be
imperceptible, but in September, it'll be quite noticeable.</pre>

file listing: diary-anniversaries-property
<pre>#    -*- mode: diary -*-
# Recurring Property events or records
%%(diary-remind '(diary-date 7 3 '(2023 2026 2029)) 30) Car Registration is due
%%(diary-anniversary 8 12 2022) Kitchen Cabinets Painted %d Years Ago</pre>

file listing: diary-birthdays-friends
<pre>#    -*- mode: diary -*-
# Birthdays of friends
%%(diary-anniversary 8 13) Bucky Thorndike Miller's Birthday (Does Dave still have his guitar amp?)
%%(diary-anniversary 2 13 1966) Ben's %d%s Birthday</pre>
</blockquote>

    
    <pre><span class="org-agenda-structure">Day-agenda (W11):</span>
<span class="org-agenda-date">Tuesday    16 March 2027</span>
<span class="org-agenda-diary">  Diary:       7:03 ┄┄┄┄┄ Sunrise (EDT), sunset 18:58 (EDT) at Home (11:54 hrs daylight)</span>
  <span class="org-time-grid">             8:00 ┄┄┄┄┄ ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄</span>
<span class="org-imminent-deadline">  BILLS:       9:00 ┄┄┄┄┄ Deadline:   </span><span class="org-todo">TODO</span><span class="org-imminent-deadline"> Visa Card </span><span class="org-imminent-deadline"><span class="org-link"><a href="https://www.example.com/">LINK</a></span></span>            <span class="org-imminent-deadline"><span class="org-tag">:Bills::Credit:</span></span>
  <span class="org-time-grid">            10:00 ┄┄┄┄┄ ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄</span>
  <span class="org-time-grid">            12:00 ┄┄┄┄┄ ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄</span>
  <span class="org-time-grid">            14:00 ┄┄┄┄┄ ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄</span>
  <span class="org-time-grid">            16:00 ┄┄┄┄┄ ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄</span>
  <span class="org-time-grid">            18:00 ┄┄┄┄┄ ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄</span>
  <span class="org-time-grid">            20:00 ┄┄┄┄┄ ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄</span>
<span class="org-agenda-diary">  Diary:      </span><span class="org-agenda-diary"><span class="org-link"><a href="https://html.duckduckgo.com/html/?q=Richard+Stallman+birthday">Richard Stallman's birthday</a></span></span><span class="org-agenda-diary"> in 14 days</span>
</pre>
<hr>
    <pre><span class="org-agenda-structure">Day-agenda (W23):</span>
<span class="org-agenda-date">Wednesday   3 June 2026</span>
<span class="org-agenda-diary">  Diary:       5:19 ┄┄┄┄┄ Sunrise (EDT), sunset 20:20 (EDT) at Home (15:00 hrs daylight)</span>
  <span class="org-time-grid">             8:00 ┄┄┄┄┄ ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄</span>
  <span class="org-time-grid">            10:00 ┄┄┄┄┄ ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄</span>
  <span class="org-time-grid">            12:00 ┄┄┄┄┄ ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄</span>
  <span class="org-time-grid">            14:00 ┄┄┄┄┄ ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄</span>
  <span class="org-time-grid">            16:00 ┄┄┄┄┄ ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄</span>
  <span class="org-time-grid">            18:00 ┄┄┄┄┄ ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄</span>
  <span class="org-time-grid">            20:00 ┄┄┄┄┄ ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄</span>
<span class="org-agenda-diary">  Diary:      Reminder: Only 30 days until Car Registration is due</span>
</pre>
<hr>
    <pre><span class="org-agenda-structure">Day-agenda (W33):</span>
<span class="org-agenda-date">Wednesday  12 August 2026</span>
<span class="org-agenda-diary">  Diary:       5:58 ┄┄┄┄┄ Sunrise (EDT), sunset 19:54 (EDT) at Home (13:56 hrs daylight)</span>
  <span class="org-time-grid">             8:00 ┄┄┄┄┄ ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄</span>
  <span class="org-time-grid">             9:00 ┄┄┄┄┄ ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄</span>
  <span class="org-time-grid">            10:00 ┄┄┄┄┄ ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄</span>
  <span class="org-time-grid">            12:00 ┄┄┄┄┄ ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄</span>
<span class="org-agenda-diary">  Diary:      13:38 ┄┄┄┄┄ New Moon (EDT) ** Solar Eclipse **</span>
  <span class="org-time-grid">            14:00 ┄┄┄┄┄ ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄</span>
  <span class="org-time-grid">            16:00 ┄┄┄┄┄ ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄</span>
  <span class="org-time-grid">            18:00 ┄┄┄┄┄ ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄</span>
  <span class="org-time-grid">            20:00 ┄┄┄┄┄ ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄</span>
<span class="org-agenda-diary">  Diary:      Kitchen Cabinets Painted 4 Years Ago</span>
</pre>
<hr>
    <pre><span class="org-agenda-structure">Day-agenda (W32):</span>
<span class="org-agenda-date-weekend">Saturday   13 August 2022</span>
<span class="org-agenda-diary">  Diary:       5:59 ┄┄┄┄┄ Sunrise (EDT), sunset 19:53 (EDT) at Home (13:53 hrs daylight)</span>
  <span class="org-time-grid">             8:00 ┄┄┄┄┄ ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄</span>
  <span class="org-time-grid">            10:00 ┄┄┄┄┄ ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄</span>
  <span class="org-time-grid">            12:00 ┄┄┄┄┄ ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄</span>
  <span class="org-time-grid">            14:00 ┄┄┄┄┄ ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄</span>
  <span class="org-time-grid">            16:00 ┄┄┄┄┄ ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄</span>
  <span class="org-time-grid">            18:00 ┄┄┄┄┄ ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄</span>
  <span class="org-time-grid">            20:00 ┄┄┄┄┄ ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄</span>
<span class="org-agenda-diary">  Diary:      Bucky Thorndike Miller's Birthday (Does Dave still have his guitar amp?)</span>
</pre>
<hr>
    <sup>1</sup>My requirements (the basics) for a text editor were:
    <ul>
      <li>column editing</li>
      <li>keystroke recording and playback</li>
      <li>regular expression search and replace</li>
      <li>undo</li>
      <li>support multiple files in multiple windows</li>
    </ul>
    <sup>2</sup><a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/index.html#SEC_Contents">Calendar/Diary in the GNU Emacs Manual</a>
</body></html>]]></content>
        <author>
            <name>Raymond Zeitler</name>
            <uri>https://ray-on-emacs.blogspot.com/search/label/Emacs</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Dave Pearson: More mode line tweaking]]></title>
        <id>https://blog.davep.org/2026/06/15/more-mode-line-tweaking.html</id>
        <link href="https://blog.davep.org/2026/06/15/more-mode-line-tweaking.html"/>
        <updated>2026-06-15T18:47:15.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>The <a href="https://blog.davep.org/2026/06/12/simplifying-my-mode-line.html">simplification of my mode
line</a> is sticking, in that I like
how it's turned out and I find it more useful to have it this simple. But I
did notice something was missing: I'm a pretty constant but pretty casual
user of <a href="https://github.com/bbatsov/projectile" target="_blank">projectile</a>. I know it's a
package that offers a wealth of tools, yet mostly I just use it as a project
bookmark system. For this, though, it works well.</p>
<p>Given this, having a quick and easy way to check that I'm in the project I
think I'm in is a good idea. While I also have
<a href="https://github.com/jaypei/emacs-neotree" target="_blank">neotree</a> open all the time, which
gives a fairly obvious clue, my eyes keep flitting down to the mode line.</p>
<p>The change I made the other day, deliberately, left the project off. I think
this was a simplification too far. So now it's back.</p>
<p><img alt="Slightly updated mode line" height="1660" loading="lazy" src="https://blog.davep.org/attachments/2026/06/15/mode-line-update.webp#centre" width="2070"></p>
<p>The core of <a href="https://github.com/davep/.emacs.d/blob/944e88b18df1147597e0f7be117887bf51c37a77/init.d/packages.d/melpa/mood-line.el" target="_blank">my mode line
configuration</a>
now looks like this:</p>
<div class="highlight"><pre><span></span><code><span class="p">(</span><span class="k">setq</span><span class="w"> </span><span class="nv">mood-line-format</span>
<span class="w">      </span><span class="p">(</span><span class="nv">mood-line-defformat</span>
<span class="w">       </span><span class="nb">:left</span>
<span class="w">       </span><span class="p">((</span><span class="k">or</span>
<span class="w">         </span><span class="p">(</span><span class="nv">mood-line-segment-buffer-status</span><span class="p">)</span>
<span class="w">         </span><span class="p">(</span><span class="nf">propertize</span>
<span class="w">          </span><span class="p">(</span><span class="nv">mood-line--get-glyph</span><span class="w"> </span><span class="nb">:buffer-modified</span><span class="p">)</span>
<span class="w">          </span><span class="ss">'face</span><span class="w"> </span><span class="ss">'my/mood-line-good-status</span><span class="p">))</span>
<span class="w">        </span><span class="s">" "</span>
<span class="w">        </span><span class="p">(</span><span class="nv">mood-line-segment-buffer-name</span><span class="p">)</span>
<span class="w">        </span><span class="p">(</span><span class="nv">my/mood-line-segment-project</span><span class="p">)</span>
<span class="w">        </span><span class="s">" "</span>
<span class="w">        </span><span class="p">(</span><span class="nv">mood-line-segment-major-mode</span><span class="p">))</span>
<span class="w">       </span><span class="nb">:right</span>
<span class="w">       </span><span class="p">((</span><span class="nv">my/mood-line-segment-vc</span><span class="p">)</span>
<span class="w">        </span><span class="s">" "</span>
<span class="w">        </span><span class="p">(</span><span class="nf">propertize</span>
<span class="w">         </span><span class="p">(</span><span class="nv">mood-line-segment-cursor-position</span><span class="p">)</span>
<span class="w">         </span><span class="ss">'face</span><span class="w"> </span><span class="ss">'my/mood-line-cursor-position</span><span class="p">))))</span>
</code></pre></div>

<p>A little busier than it started out, but still pretty clean. I do keep
wondering about the cursor position. In most buffers I have line numbers
showing to the left anyway, and it's rare (but not unknown) that I need to
know what column I'm in. I'm very tempted to remove the cursor position
altogether, then the right-hand side would just be the <code>vc</code> information, at
which point it might make sense to also move the project name over to the
right, given that the project and the repository information generally go
hand-in-hand.</p>
<p>I'll stick with this for now, but I can see this happening soon.</p></body></html>]]></content>
        <author>
            <name>Dave Pearson</name>
            <uri>https://blog.davep.org</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Marcin Borkowski: Scrolling pdfs in other windows]]></title>
        <id>https://mbork.pl/2026-06-15_Scrolling_pdfs_in_other_windows</id>
        <link href="https://mbork.pl/2026-06-15_Scrolling_pdfs_in_other_windows"/>
        <updated>2026-06-15T16:05:33.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body>I have written about pdf-tools quite a few times – it’s a fantastic Emacs package for viewing and annotating pdfs without leaving the comfort of Emacs. It is not ideal, though – or at least, not ideal for me. One feature of Emacs I often use is the scroll-other-window command (bound to C-M-v), and its sibling scroll-other-window-down (C-M-S-v). They are extremely useful for example when reading documentation or watching live Markdown preview, and I wish they worked with the TeX and pdf-tools duo, too. Well, it’s Emacs, so it shouldn’t be difficult to make them!</body></html>]]></content>
        <author>
            <name>Marcin Borkowski</name>
            <uri>https://mbork.pl/Homepage</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Sacha Chua: 2026-06-15 Emacs news]]></title>
        <id>https://sachachua.com/blog/2026/06/2026-06-15-emacs-news/</id>
        <link href="https://sachachua.com/blog/2026/06/2026-06-15-emacs-news/"/>
        <updated>2026-06-15T13:54:28.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>
Lots of discussion around Karthik's latest blog post <a href="https://karthinks.com/software/even-more-batteries-included-with-emacs/">Even More Batteries Included with Emacs</a> (<a href="https://www.reddit.com/r/emacs/comments/1u5pago/even_more_batteries_included_with_emacs_karthinks/">Reddit</a>, <a href="https://news.ycombinator.com/item?id=48535886">HN</a>, <a href="https://lobste.rs/s/wwbl1n/even_more_batteries_included_with_emacs">lobste.rs</a>). Check it out!
</p>

<ul>
<li>Emacs updates:
<ul>
<li><a href="https://copr.fedorainfracloud.org/coprs/bhavin192/emacs-pretest/">Emacs 31.0.90 pretest packages for Fedora</a> (<a href="https://www.reddit.com/r/emacs/comments/1u17dmp/emacs_31090_pretest_packages_for_fedora/">Reddit</a>)</li>
<li><a href="https://f-droid.org/en/packages/org.gnu.emacs/">Emacs 31.0.90 pretest packages for Android, via F-Droid</a> (<a href="https://www.reddit.com/r/emacs/comments/1u6ed1e/emacs_31090_pretest_packages_for_android_via/">Reddit</a>)</li>
</ul></li>
<li>Upcoming events (<a href="https://emacslife.com/calendar/emacs-calendar.ics">iCal file</a>, <a href="https://emacslife.com/calendar/">Org</a>):
<ul>
<li>M-x Research: TBA <a href="https://m-x-research.github.io/">https://m-x-research.github.io/</a> Wed Jun 17 0800 America/Vancouver - 1000 America/Chicago - 1100 America/Toronto - 1500 Etc/GMT - 1700 Europe/Berlin - 2030 Asia/Kolkata - 2300 Asia/Singapore</li>
<li>OrgDevMeetup <a href="https://bbb.emacsverse.org/rooms/orgdevmeetup">https://bbb.emacsverse.org/rooms/orgdevmeetup</a> Sat Jun 20 0900 America/Vancouver - 1100 America/Chicago - 1200 America/Toronto - 1600 Etc/GMT - 1800 Europe/Berlin - 2130 Asia/Kolkata – Sun Jun 21 0000 Asia/Singapore</li>
<li>EmacsSF (in person): coffee.el in SF <a href="https://www.meetup.com/emacs-sf/events/315192115/">https://www.meetup.com/emacs-sf/events/315192115/</a> Sat Jun 20 1100 America/Los_Angeles</li>
<li>Emacs Berlin: Emacs-Berlin Hybrid Meetup <a href="https://emacs-berlin.org/">https://emacs-berlin.org/</a> Wed Jun 24 1000 America/Vancouver - 1200 America/Chicago - 1300 America/Toronto - 1700 Etc/GMT - 1900 Europe/Berlin - 2230 Asia/Kolkata – Thu Jun 25 0100 Asia/Singapore</li>
<li>Emacs APAC: Emacs APAC meetup (virtual) <a href="https://emacs-apac.gitlab.io/announcements/">https://emacs-apac.gitlab.io/announcements/</a> Sat Jun 27 0130 America/Vancouver - 0330 America/Chicago - 0430 America/Toronto - 0830 Etc/GMT - 1030 Europe/Berlin - 1400 Asia/Kolkata - 1630 Asia/Singapore</li>
</ul></li>
<li>Beginner:
<ul>
<li><a href="https://www.youtube.com/watch?v=Lnj45uzDcLc">How to Install a Package on Emacs From Melpa</a> (04:09)</li>
</ul></li>
<li>Emacs configuration:
<ul>
<li><a href="https://rtzptz.xyz/posts/eat-replace-shell-pop.html">Replace shell-pop with built-in display-buffer-alist</a> (<a href="https://www.reddit.com/r/emacs/comments/1u1fmm5/replace_shellpop_with_builtin_displaybufferalist/">Reddit</a>)</li>
<li><a href="https://codeberg.org/salvari/emacs30_elpaca_public">salvari/emacs30_elpaca_public: My new configuration for Emacs using Elpaca as package manager - Codeberg.org</a> (<a href="https://mastodon.gal/@salvari/116720718764088405">@salvari@mastodon.gal</a>)</li>
</ul></li>
<li>Emacs Lisp:
<ul>
<li><a href="https://lars.ingebrigtsen.no/2026/06/11/web-scraping-is-getting-harder-all-the-time/">Lars Ingebrigtsen: Web scraping is getting harder all the time</a></li>
<li><a href="https://tv.dyne.org/w/d38i5Gmk4xpHEHdFq8mGfW">[22] Integrating Emacs Reader with Canvas - Dyne.org TV</a> (<a href="https://mathstodon.xyz/@divyaranjan/116737776379893396">@divyaranjan@mathstodon.xyz</a>)</li>
</ul></li>
<li>Appearance:
<ul>
<li><a href="https://github.com/kn66/halo.el">halo.el: an experimental minor mode for keeping point centered and dimming distant lines</a> (<a href="https://www.reddit.com/r/emacs/comments/1u5i881/haloel_an_experimental_minor_mode_for_keeping/">Reddit</a>)</li>
<li><a href="https://github.com/gonewest818/dimmer.el">dimmer.el – after a hiatus, new development underway</a> (<a href="https://www.reddit.com/r/emacs/comments/1u2af5n/dimmerel_after_a_hiatus_new_development_underway/">Reddit</a>) - dims inactive buffers; updates: reset when theme changes, handle child frames</li>
<li><a href="https://blog.davep.org/2026/06/12/simplifying-my-mode-line.html">Dave Pearson: Simplifying my mode line</a></li>
<li><a href="https://blog.davep.org/2026/06/13/it-got-darker.html">Dave Pearson: It got darker</a> - switched to a dark-mode</li>
<li><a href="https://github.com/kn66/vertico-buffer-frame">Inspired by nano-emacs: vertico-buffer-frame with nano-vertico</a> (<a href="https://www.reddit.com/r/emacs/comments/1u2zyp7/inspired_by_nanoemacs_verticobufferframe_with/">Reddit</a>)</li>
</ul></li>
<li>Navigation:
<ul>
<li><a href="https://github.com/dmgerman/bookmark-plusplus">modernizing bookmark+</a> (<a href="https://www.reddit.com/r/emacs/comments/1u4uzop/modernizing_bookmark/">Reddit</a>)- trying to get in touch with Drew Adams</li>
<li><a href="https://github.com/jamescherti/outline-indent.el">outline-indent, a modern Indentation-based Text Folding Mode for Emacs (Release 1.2.0)</a> (<a href="https://www.reddit.com/r/emacs/comments/1u18jlq/outlineindent_a_modern_indentationbased_text/">Reddit</a>)</li>
</ul></li>
<li>Dired:
<ul>
<li><a href="https://protesilaos.com/codelog/2026-06-13-emacs-flat-dired-for-regexp-since-days/">Protesilaos: Emacs: flat Dired listing for REGEXP, optionally up to DAYS since last  modification</a> (<a href="https://irreal.org/blog/?p=13875">Irreal</a>)</li>
</ul></li>
<li>Writing:
<ul>
<li><a href="https://batsov.com/articles/2026/06/11/emacs-loves-asciidoc/">Bozhidar Batsov: Emacs loves AsciiDoc</a> (<a href="https://irreal.org/blog/?p=13871">Irreal</a>)</li>
<li><a href="https://blog.davep.org/2026/06/14/blogmore-el-v5-3-0.html">Dave Pearson: blogmore.el v5.3.0</a> - adds blogmore-link-series</li>
<li><a href="https://gitlab.com/smaller-infinity/bibtex-format">New, Fast, BibTex Formatter</a> (<a href="https://www.reddit.com/r/emacs/comments/1u2djgg/new_fast_bibtex_formatter/">Reddit</a>) - Uses rust</li>
</ul></li>
<li>Denote:
<ul>
<li><a href="https://taonaw.com/2026/06/14/meta-journal-notes-in-denotejournal.html">TAONAW - Emacs and Org Mode: Meta Journal notes in Denote-Journal with Journelly</a></li>
</ul></li>
<li>Org Mode:
<ul>
<li><a href="https://sachachua.com/blog/2026/06/from-dc-toedt-copy-org-mode-as-markdown/">Sacha Chua: From DC Toedt: Copy Org Mode as Markdown</a></li>
<li><a href="https://ray-on-emacs.blogspot.com/2026/06/creating-reference-to-webpage-in-org.html">Raymond Zeitler: Creating a Reference to a Webpage in Org</a></li>
<li><a href="https://www.reddit.com/r/orgmode/comments/1u5gpmb/a_day_with_orgsupertag_one_persons_complete/">A Day with Org-SuperTag — One Person's Complete Workflow</a></li>
<li><a href="https://www.reddit.com/r/emacs/comments/1u31nrb/org_export_dispatcher_to_eisvogel_latex_template/">Org export dispatcher to Eisvogel LaTeX template</a></li>
<li><a href="https://tilde.town/~cryptk/blog/yaob.html">YAOB – Yet Another Org Blog · (interzone)</a> (<a href="https://mastodon.social/@cryptk/116722167175985830">@cryptk</a>)</li>
<li><a href="https://www.youtube.com/watch?v=t_mi-H9iFXA">Emacs Org-Roam: Gestione della Conoscenza a Grafi e Metodo Zettelkasten</a> (06:39)</li>
<li>Org development:
<ul>
<li><a href="https://git.savannah.gnu.org/cgit/emacs/org-mode.git/commit/etc/ORG-NEWS?id=0a7387385710c708d54af89ebcd3835eb8a2eb7a">ob-core: Obsolete `org-babel-remote-temporary-directory'</a></li>
<li><a href="https://git.savannah.gnu.org/cgit/emacs/org-mode.git/commit/etc/ORG-NEWS?id=4dc39c7eb3d481984fabfe2bfe578da51fb9c779">org-agenda-timerange-leaders: Allow functions as element values</a></li>
</ul></li>
</ul></li>
<li>Completion:
<ul>
<li><a href="https://utcc.utoronto.ca/~cks/space/blog/programming/EmacsUnderstandingEmbark">Chris's Wiki - blog/programming/EmacsUnderstandingEmbark</a> (<a href="https://lobste.rs/s/secptg/understanding_embark_gnu_emacs_bit_some">lobste.rs</a>, <a href="https://lemmy.ml/post/48522563?scrollToComments=true">lemmy.ml</a>)</li>
</ul></li>
<li>Coding:
<ul>
<li><a href="https://emacs.dyerdwelling.family/emacs/20260610061920-emacs--the-hidden-git-stash-keys-in-emacs-vc-directory-mode/">James Dyer: The Hidden Git Stash Keys in Emacs VC Directory Mode</a></li>
<li><a href="https://www.swift.org/documentation/articles/zero-to-swift-emacs.html">Configuring Emacs for Swift Development | Swift.org</a> (<a href="https://sfba.social/@kickingvegas/116734370211177731">@kickingvegas@sfba.social</a>)</li>
<li><a href="https://codeberg.org/zshaftel/tree-sitter-cl-syntax">Common Lisp tree-sitter grammar with a major-mode and Sly powered semantic highlighting</a> (<a href="https://www.reddit.com/r/emacs/comments/1u0pyfj/common_lisp_treesitter_grammar_with_a_majormode/">Reddit</a>)</li>
<li><a href="https://www.youtube.com/watch?v=i6i1omycw0Y">Corrigindo divergências entre arquivos de configuração do emacs</a> (01:37:06)</li>
</ul></li>
<li>Mail, news, and chat:
<ul>
<li><a href="https://github.com/laurynas-biveinis/mu4e-autotask/">mu4e-based email automation package</a> (<a href="https://www.reddit.com/r/emacs/comments/1u0iqtm/mu4ebased_email_automation_package/">Reddit</a>)</li>
<li><a href="https://git.securityops.co/cristiancmoises/whatsappel">Whatsappel - Run WhatsApp inside Emacs</a> (<a href="https://www.reddit.com/r/emacs/comments/1u58hb8/whatsappel_run_whatsapp_inside_emacs/">Reddit</a>)</li>
</ul></li>
<li>Doom Emacs:
<ul>
<li><a href="https://github.com/orgs/doomemacs/discussions/114">doom emacs 项目拆分为core和modules, doom emacs 将进入快速发展期</a> (<a href="https://www.reddit.com/r/DoomEmacs/comments/1u13u8o/doom_emacs_%E9%A1%B9%E7%9B%AE%E6%8B%86%E5%88%86%E4%B8%BAcore%E5%92%8Cmodules_doom_emacs_%E5%B0%86%E8%BF%9B%E5%85%A5%E5%BF%AB%E9%80%9F%E5%8F%91%E5%B1%95%E6%9C%9F/">Reddit</a>)</li>
</ul></li>
<li>Fun:
<ul>
<li><a href="https://www.youtube.com/watch?v=7tURkbpdUmo">The World Cup… in emacs! ⚽️💻</a> (04:41, <a href="https://www.reddit.com/r/emacs/comments/1u2q0o9/the_world_cup_in_emacs/">Reddit</a>)</li>
<li><a href="https://www.chiply.dev/post-emacs-svg-benchmark">Emacs SVG Benchmark Reveals Gaming-Caliber Frame Rates</a> (<a href="https://www.reddit.com/r/emacs/comments/1u2ycqp/emacs_svg_benchmark_reveals_gamingcaliber_frame/">Reddit</a>)</li>
</ul></li>
<li>AI:
<ul>
<li><a href="https://xenodium.com/agent-shell-0-55-updates">Alvaro Ramirez: agent-shell 0.55 updates</a> (<a href="https://lobste.rs/s/qulbgz/agent_shell_0_55_updates">lobste.rs</a>, <a href="https://www.reddit.com/r/emacs/comments/1u2x3ur/agentshell_055_updates/">Reddit</a>)</li>
<li><a href="https://github.com/dnouri/pi-coding-agent/releases/tag/v2.5.0">New Pi Emacs coding harness release has no trust issues!</a> (<a href="https://www.reddit.com/r/emacs/comments/1u4s8ks/new_pi_emacs_coding_harness_release_has_no_trust/">Reddit</a>)</li>
<li><a href="https://codeberg.org/martenlienen/emcp">EMCP - Emacs an an MCP server</a> (<a href="https://www.reddit.com/r/emacs/comments/1u5ef0v/emcp_emacs_an_an_mcp_server/">Reddit</a>)</li>
<li><a href="https://www.youtube.com/watch?v=8JgIE48vh6c">Vibe Coding with Emacs' Built-In AI - System Crafters Live!</a> (01:47:29)</li>
</ul></li>
<li>Community:
<ul>
<li><a href="https://v.redd.it/uxwyavj7646h1">Joshua Blais on Doom Emacs, Vanilla Emacs, Guix, and 34-Key Keyboards</a> (<a href="https://www.reddit.com/r/emacs/comments/1u0iy6b/joshua_blais_on_doom_emacs_vanilla_emacs_guix_and/">Reddit</a>)</li>
<li><a href="https://ray-on-emacs.blogspot.com/2026/05/emacs-its-worth-revealing-oneself-for.html">Raymond Zeitler: Emacs – It's Worth Revealing Oneself For</a></li>
<li><a href="https://www.rahuljuliato.com/posts/blog-on-gemini">My Blog Now Has a Gemini Mirror</a> (<a href="https://www.reddit.com/r/emacs/comments/1u1hxyf/my_blog_now_has_a_gemini_mirror/">Reddit</a>) - Rahul Juliato</li>
</ul></li>
<li><a href="https://rossabaker.com/blog/underappreciated-emacs-built-ins/">Emacs Carnival: Underappreciated Built-ins</a>:
<ul>
<li><a href="https://karthinks.com/software/even-more-batteries-included-with-emacs/">Even More Batteries Included With Emacs (Karthinks)</a> (<a href="https://www.reddit.com/r/emacs/comments/1u5pago/even_more_batteries_included_with_emacs_karthinks/">Reddit</a>, <a href="https://news.ycombinator.com/item?id=48535886">HN</a>, <a href="https://lobste.rs/s/wwbl1n/even_more_batteries_included_with_emacs">lobste.rs</a>)</li>
<li><a href="https://www.youtube.com/watch?v=yuJYEua0ZwA">Yay Emacs 33: Sacha and Prot Talk Emacs: Built-ins</a> (01:01:36)</li>
<li><a href="https://www.homepages.ucl.ac.uk/~ucecesf/blog/20260602.html">Emacs carnival: rec mode, an all-text database system</a> (<a href="https://lobste.rs/s/p78ttt/emacs_rec_mode_all_text_database_system">lobste.rs</a>)</li>
</ul></li>
<li>Other:
<ul>
<li><a href="https://github.com/tanrax/emacs-gpu">tanrax/emacs-gpu: GNU Emacs with a GPU-accelerated display backend · GitHub</a> (<a href="https://activity.andros.dev/@andros/statuses/01KTZV88P5V4VCQ2M9293R9BTZ">@andros@activity.andros.dev</a>)</li>
<li><a href="https://www.youtube.com/watch?v=imAgBN3brns">Xah Talk Show Ep793. emacs, install Xah Fly Keys in WSL linux emacs</a> (02:18:11)</li>
<li><a href="https://www.youtube.com/watch?v=teAgI3aoIpU">Xah Talk Show Ep792. install emacs on wsl Windows Subsystem for Linux</a> (01:47:31)</li>
<li><a href="https://sachachua.com/blog/2026/06/june-11-sacha-and-prot-talk-emacs-built-ins/">Sacha Chua: Yay Emacs 33: Sacha and Prot Talk Emacs: Built-ins</a> (<a href="https://protesilaos.com/codelog/2026-06-09-emacs-live-sacha-chua-built-ins/">Prot</a>)</li>
<li><a href="https://chrismaiorana.com/tmux-wm-emacs-no-gui/">Chris Maiorana: When tmux is your window manager</a> (<a href="https://irreal.org/blog/?p=13868">Irreal</a>)</li>
</ul></li>
<li>Emacs development:
<ul>
<li>emacs-devel:
<ul>
<li><a href="https://yhetil.org/emacs-devel/ed53dc2f-d0e2-427d-9415-45901f95ffcf@gutov.dev/">Re: master 1d91d9b717d: project-vc-dir: Use truenames - Dmitry Gutov</a> - discussion of when to use symlinks and when to use truenames</li>
<li><a href="https://yhetil.org/emacs-devel/87zf0y8w0y.fsf@linabee.uk/">Re: SDL terminal type - Lina</a> - anyone interested in trying to port Emacs UI to SDL rendering?</li>
</ul></li>
<li><a href="https://git.savannah.gnu.org/cgit/emacs.git/commit/etc/NEWS?id=15e5f404f05f7a1ca5bdd8eb6a7579e0546472da">Optional display of overlay-arrow in margin (bug#81109)</a></li>
<li><a href="https://git.savannah.gnu.org/cgit/emacs.git/commit/etc/NEWS?id=87133286d6b7ed20c2d6aa41c9bf00c10bc80d30">Revert "project-vc-dir: Use truenames"</a></li>
<li><a href="https://git.savannah.gnu.org/cgit/emacs.git/commit/etc/NEWS?id=78a10d17c69970687f8330f6c896170bcf936ef3">Convert outline-search-function to defcustom</a></li>
<li><a href="https://git.savannah.gnu.org/cgit/emacs.git/commit/etc/NEWS?id=194c28aaf22979d46f22cc424ba8f1bc78db27b3">Add outline-search-from-regexp generic helper</a></li>
<li><a href="https://git.savannah.gnu.org/cgit/emacs.git/commit/etc/NEWS?id=c6c4888ced296b6bda7752066df44d95f591cb06">'work-buffer–release' kill locals silently and reset the buffer (bug#81111)</a></li>
<li><a href="https://git.savannah.gnu.org/cgit/emacs.git/commit/etc/NEWS?id=725120ca3de9f30c8c6bbaeb237f9c803c12b442">Set user options in file/directory locals like 'setopt-local' (bug#81120)</a></li>
<li><a href="https://git.savannah.gnu.org/cgit/emacs.git/commit/etc/NEWS?id=e7e9c55ba745e5499dc4d2370fda481b7270d74a">Add outline-show-entry-and-parents to reveal entry hierarchy</a></li>
<li><a href="https://git.savannah.gnu.org/cgit/emacs.git/commit/etc/NEWS?id=f343f20b9449c14deceb9fed1a062687c1d52d38">Mark vc-dir-show-outgoing-count obsolete</a></li>
<li><a href="https://git.savannah.gnu.org/cgit/emacs.git/commit/etc/NEWS?id=1d91d9b717df1781c07d28f46af4ac2af19c16b4">project-vc-dir: Use truenames</a></li>
</ul></li>
<li>New packages:
<ul>
<li><a target="_blank" href="https://melpa.org/#/pure-light-theme">pure-light-theme</a>: A light colored theme for e-ink color monitors (MELPA)</li>
<li><a target="_blank" href="https://melpa.org/#/shexc-ts-mode">shexc-ts-mode</a>: Tree-sitter major mode for ShExC (MELPA)</li>
</ul></li>
</ul>

<p>
Links from <a href="https://www.reddit.com/r/emacs">reddit.com/r/emacs</a>, <a href="https://www.reddit.com/r/orgmode">r/orgmode</a>, <a href="https://www.reddit.com/r/spacemacs">r/spacemacs</a>, <a href="https://mastodon.social/tags/emacs">Mastodon #emacs</a>, <a href="https://bsky.app/hashtag/emacs">Bluesky #emacs</a>, <a href="https://hn.algolia.com/?query=emacs&amp;sort=byDate&amp;prefix&amp;page=0&amp;dateRange=all&amp;type=story">Hacker News</a>, <a href="https://lobste.rs/search?q=emacs&amp;what=stories&amp;order=newest">lobste.rs</a>, <a href="https://programming.dev/c/emacs?dataType=Post&amp;page=1&amp;sort=New">programming.dev</a>, <a href="https://lemmy.world/c/emacs">lemmy.world</a>, <a href="https://lemmy.ml/c/emacs?dataType=Post&amp;page=1&amp;sort=New">lemmy.ml</a>, <a href="https://planet.emacslife.com">planet.emacslife.com</a>, <a href="https://www.youtube.com/playlist?list=PL4th0AZixyREOtvxDpdxC9oMuX7Ar7Sdt">YouTube</a>, <a href="http://git.savannah.gnu.org/cgit/emacs.git/log/etc/NEWS">the Emacs NEWS file</a>, <a href="https://emacslife.com/calendar/">Emacs Calendar</a>, and <a href="https://lists.gnu.org/archive/html/emacs-devel/2026-06">emacs-devel</a>. Thanks to Andrés Ramírez for emacs-devel links. Do you have an Emacs-related link or announcement? Please e-mail me at <a href="mailto:sacha@sachachua.com">sacha@sachachua.com</a>. Thank you!</p>
<div><a href="https://sachachua.com/blog/2026/06/2026-06-15-emacs-news/index.org">View Org source for this post</a></div>
<p>You can <a href="https://social.sachachua.com/@sacha/statuses/01KV5XYWFASX9YDD8MN7QEGEC0" target="_blank">comment on Mastodon</a> or <a href="mailto:sacha@sachachua.com?subject=Comment%20on%20https%3A%2F%2Fsachachua.com%2Fblog%2F2026%2F06%2F2026-06-15-emacs-news%2F&amp;body=Name%20you%20want%20to%20be%20credited%20by%20(if%20any)%3A%20%0AMessage%3A%20%0ACan%20I%20share%20your%20comment%20so%20other%20people%20can%20learn%20from%20it%3F%20Yes%2FNo%0A">e-mail me at sacha@sachachua.com</a>.</p></body></html>]]></content>
        <author>
            <name>Sacha Chua</name>
            <uri>https://sachachua.com/blog/category/emacs/feed/index.xml</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Irreal: Dired Flat File Listings]]></title>
        <id>https://irreal.org/blog/?p=13875</id>
        <link href="https://irreal.org/blog/?p=13875"/>
        <updated>2026-06-14T14:57:27.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>
It turns out that if you call Dired from Elisp, you can pass it a list of files to display. Protesilaos Stavrou (Prot) leveraged that fact to <a href="https://protesilaos.com/codelog/2026-06-13-emacs-flat-dired-for-regexp-since-days/">write a bit of Elisp that provides him with a flat list of files matching a regular expression in a specified directory structure</a>. His post has the code so you can see how he did it but it’s mostly what you’d expect: after some setup, he calls <code>directory-file-recursively</code> to gather the list of files that he then passes on to Dired.
</p>
<p>
It’s a pretty nice system but after using it for a while, Prot realized that when he was dealing with large directories a bit of initial filtering of the most recently modified files would be useful. He solved that by adapting his previous code to do the filtering. He does it by taking the list of files from his first function and running them through <code>seq-filter</code> to get the files he’s interested in. Again, all the code is in his post but Prot says he won’t be updating the post so you should check out his <a href="https://protesilaos.com/emacs/dotemacs">configuration</a> for the latest version.
</p>
<p>
If you frequently generate Dired listings and would prefer to deal with a flat list of the files without worrying about what directory they’re in, take a look at Prot’s post for an excellent solution.
</p>
<p>
<b>Update</b> <span class="timestamp-wrapper"><span class="timestamp">[2026-06-15 Mon 10:06]</span></span>: Fixed link to Prot’s post.</p>
</body></html>]]></content>
        <author>
            <name>Irreal</name>
            <uri>https://irreal.org/blog</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[TAONAW - Emacs and Org Mode: Meta Journal notes in Denote-Journal with Journelly]]></title>
        <id>https://taonaw.com/2026/06/14/meta-journal-notes-in-denotejournal.html</id>
        <link href="https://taonaw.com/2026/06/14/meta-journal-notes-in-denotejournal.html"/>
        <updated>2026-06-14T13:41:16.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>Wow, I’m so good at overcomplicating things, I already made you go “huh?!” with the title alone! I have some mad skillz!</p>
<p>On with the show:</p>
<p>In the last couple of weeks, I slowly improved and tinkered with my Linux environment (Kubuntu). I’m not sure if it was a single thing that nudged me to do that, but between installing the <a href="https://taonaw.com/2026/05/31/installing-harper-on-kubuntu-the.html">latest version of Harper</a> and <a href="https://taonaw.com/2026/06/07/trying-out-vivaldi-on-linux.html">switching to Vivaldi</a> with its <a href="https://taonaw.com/2026/06/11/enjoying-vivaldi.html">great features I keep discovering</a>, I also started using <a href="https://protesilaos.com/emacs/denote-journal">denote-journal</a>.</p>
<p>Denote-journal, from the prolific Prot who also made Denote, was something I wanted to try for a while. I didn’t really have a good reason to, because I’ve been <a href="https://taonaw.com/archive/?q=journelly">using Journelly</a> for a long time, and on my Mac or Linux desktop, I’d call a capture template that would append to the file, adding my additional entries.</p>
<p>But I always had one major issue with journaling on my iPhone: privacy. My iPhone is owned and regulated (with a system profile) by my workplace. So even if I’m fine writing personal notes on my Mac (I’m not, I’m iffy about it as well, I don’t trust Apple to respect my privacy much more than I trust Google), at the end of the day, these notes also sync to my iPhone.</p>
<p>On a day-to-day basis, for quick thoughts and work notes, Journelly and my iPhone are great, but when it comes to writing longer notes about my future plans, how I spent the weekend with my partners, and basically anything else that involves people whose privacy I respect, I always self-censor.</p>
<p>For this reason, I came up with a way to <a href="https://taonaw.com/2025/07/31/denote-with-a-different-root.html">create private notes with Denote only on Linux</a>. These notes only live on my Linux Desktop, with a few of those syncing to my Android<sup><a href="https://taonaw.com/categories/emacs-org-mode/#fn.1">1</a></sup> (again, not great, but at least it’s not work-managed).</p>
<p>I always feel more like myself on Linux because I <em>am</em> more myself - whether it’s customizing my shortcuts and workflow exactly how I like it, or if it’s the built-in privacy that can be further fortified and inspected. Journaling on Linux, without the world’s biggest nanny peeping over my shoulder, is where I really open up and write my most personal thoughts.</p>
<p>A couple of times I looked at my Journelly notes, those that I wrote on the Mac where I could write at length and use the full power of Emacs, and compared them to my older journal on Linux. Well, there <em>is no</em> comparison. And while creating a private note in Denote in Linux and linking it back to the original works<sup><a href="https://taonaw.com/categories/emacs-org-mode/#fn.2">2</a></sup>, it introduces friction that hinders the flow of my thoughts.</p>
<p>So I looked into denote-journal, realized it’s very easy to use, and gave it a try one day, and since then:</p>
<img src="https://cdn.uploads.micro.blog/96826/2026/screenshot-20260613-172153.png" width="326" height="394" alt="Auto-generated description: A list of journal files, organized by date and day of the week, is shown in a directory format.">
<p>Essentially, it’s what I used to do when I <a href="https://taonaw.com/2025/04/27/a-month-with-journelly.html">started using Journelly</a>: refile my Journelly headers into my journal files when I get the chance. Or, as a matter of fact, I use <code>org-refile-copy</code>, which does exactly what it says, because I want to keep the original in Journelly. Since I now use individual journal files instead of a big file split into weeks (as I did in the past), this process is even easier. The only catch is the images.</p>
<p>Images in Journelly are saved in its <code>/Journelly.org.assets</code> folder, where my journal files can’t see them directly; and even if it did, these images are <a href="https://taonaw.com/2026/02/25/i-think-i-found-what.html">too big and cause freezes</a>, and also <a href="https://taonaw.com/2026/06/03/correcting-photo-orientation-for-orgmode.html">oriented the wrong way</a>, so they need at least a minimal treatment. For these reasons, <a href="https://taonaw.com/2026/03/08/display-images-with-orgattach-and.html">I attach each image</a> to the correct header in the journal daily file which I moved over from Journelly.</p>
<p>These journal notes are fantastic. I have my quick notes from the day available, but when I want to extend, all I do now is just write a new entry for that day (which looks just like the Journelly entries) and write to my heart’s content. There’s also a bonus: <code>denote-journal</code> allows me to make up for days if I didn’t create a “meta journal note” for the day (so far this happened only once) directly from the calendar, so if I miss a day, I go to the calendar, point at the missing day, and use <code>denote-journal-new-or-existing-entry</code> to take care of things. If I already have an entry, it jumps to it; if I don’t, it creates one.</p>
<p>Between my journal on Linux, the emails I write to other bloggers, my blog posts, and the occasional instructions I write in Denote, I think I write more than I did in my entire life. I’m thinking I need to start capturing it in some sort of book, though I have no idea what it will be about and how to edit my writings in a way that makes sense. This is only a vague concept at the moment.</p>
<h3>Footnotes</h3>
<p><sup><a href="https://taonaw.com/categories/emacs-org-mode/#fnr.1">1</a></sup> : I keep skirting around this issue so I’ll just mention it quickly: I <a href="https://taonaw.com/2023/05/14/trying-out-grapheneos.html">used GrapheneOS in the past</a>, and it’s great for these kinds of things, but GrapheneOS protects your phone to an extent that certain apps don’t work.</p>
<p><sup><a href="https://taonaw.com/categories/emacs-org-mode/#fnr.2">2</a></sup> : I’ve been doing this often enough that I have a whole tag in Denote called “supplemental” with additional thoughts and notes. In Journelly, I was just linking to those, and writing something like “I have more to say about this” and this would include a <a href="https://protesilaos.com/emacs/denote#h:fc913d54-26c8-4c41-be86-999839e8ad31">Denote link</a> to the Linux-only note.</p>
</body></html>]]></content>
        <author>
            <name>TAONAW - Emacs and Org Mode</name>
            <uri>https://taonaw.com/categories/emacs-org-mode/</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Dave Pearson: blogmore.el v5.3.0]]></title>
        <id>https://blog.davep.org/2026/06/14/blogmore-el-v5-3-0.html</id>
        <link href="https://blog.davep.org/2026/06/14/blogmore-el-v5-3-0.html"/>
        <updated>2026-06-14T07:49:14.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>I've released <a href="https://github.com/davep/blogmore.el" target="_blank"><code>blogmore.el</code></a> v5.3.0.
This is a pretty small release but adds a command I realised I'd forgotten
to add a couple of releases ago.</p>
<p>Now that <a href="https://blogmore.davep.dev/" target="_blank">BlogMore</a> has the concept of a post
series, and now that <code>blogmore.el</code> lets you add and remove a series from a
post, it makes sense that I'd want to <em>link</em> to a series in a post from time
to time, like I can and do with categories and tags.</p>
<p>So v5.3.0 adds a <code>blogmore-link-series</code> command. It can also be found in the
transient menu.</p></body></html>]]></content>
        <author>
            <name>Dave Pearson</name>
            <uri>https://blog.davep.org</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Karthik Chikmagalur: Even More Batteries Included with Emacs]]></title>
        <id>https://karthinks.com/software/even-more-batteries-included-with-emacs/</id>
        <link href="https://karthinks.com/software/even-more-batteries-included-with-emacs/"/>
        <updated>2026-06-14T07:05:00.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>Emacs features have a discoverability problem, and we’re chipping away at it one
demo at a time.  The years since I wrote the last one of these have yielded more
surprising and useful finds, so it’s time again for a “batteries included”
report.</p>

Note
<div class="details">
<p>This is the third in a series of articles highlighting useful but lesser-known
features included in Emacs.</p>
<p>Parts 1 &amp; 2:</p>
<ul>
<li><a href="https://karthinks.com/software/batteries-included-with-emacs/">Batteries included with Emacs</a></li>
<li><a href="https://karthinks.com/software/more-batteries-included-with-emacs/">More batteries included with emacs</a></li>
</ul>
<p>“Lesser-known” is a subjective judgment.  Roughly, it means that at the time of
writing, I have seen these features mentioned fewer than five times – and often
never – in the past two decades of dipping in and out of online Emacs
discourse.  Some of the features covered in past entries <em>are</em> well known and
often recommended today.  I claim no credit.</p>
</div>

<p>If you’re a new Emacs user, <em>don’t start here</em>.  This is not a getting-started
guide.  You will be better served by grokking basic Emacs concepts and sticking
to the most widely recommended packages.  Once you’ve experienced the Emacs
equivalents of thoughts like “Why didn’t anyone think to put wheels on luggage
until 1990?”, this series might be more helpful.
<span class="sidenote-number"><small>
My rule of thumb is that if you aren’t yet aware of undo-in-region, there is
much low hanging fruit for the picking, and you can come back to this article
after that supply has run out!
</small></span>
.</p>
<p>Veteran Emacs users tend to use some relatively niche Emacs features, but in my
experience it’s always a different subset for each user.  So if you’ve been
around the block a few times, I promise there will still be surprises below for
you as well!</p>
<p>Same rules as before:</p>
<ul>
<li>
<p>No packages, <strong>stock Emacs only</strong></p>
</li>
<li>
<p>No steep learning curves. <strong>Learn each feature in under five minutes or bust</strong>.</p>
</li>
<li>
<p><strong>No gimmicks</strong>. No <code>doctor</code>, <code>tetris</code>, <code>snake</code>, <code>dunnet</code>, <code>zone</code>,
<code>butterfly</code>… yes, we know about <code>dissociated-press</code>.  Let’s move on.</p>
</li>
<li>
<p><strong>Just the deltas</strong>. No commonly mentioned packages like Flymake, doc-view,
outline-minor-mode, gnus or eww. Nothing that Emacs brings up automatically or
a nonspecific Google search gets you.</p>
</li>
<li>
<p>Assume a modern Emacs, 28.1+.</p>
<p>Also, if you’re new to Emacs and still reading:</p>
<table>
<thead>
<tr>
<th>Emacs jargon</th>
<th>Modern parlance</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>M-x</code></td>
<td>Alt + x</td>
</tr>
<tr>
<td><code>C-x</code></td>
<td>Ctrl + x</td>
</tr>
<tr>
<td>Frame</td>
<td>Emacs window</td>
</tr>
<tr>
<td>Window</td>
<td>split/pane</td>
</tr>
<tr>
<td>Buffer</td>
<td>Contiguous chunk of text/data</td>
</tr>
<tr>
<td>Point</td>
<td>Cursor position in buffer</td>
</tr>
<tr>
<td>Active Region</td>
<td>Text selection</td>
</tr>
<tr>
<td>Region</td>
<td>Text selection (not highlighted)</td>
</tr>
<tr>
<td>Face</td>
<td>Font, color and display properties</td>
</tr>
</tbody>
</table>
<p>I’m Sorry.</p>
</li>
</ul>
<p>Okay? Let’s go:</p>
<h2>Dictionary on hover (<code>M-x dictionary-tooltip-mode</code>)</h2>
<p>Turn on <code>dictionary-tooltip-mode</code> to see word meanings in tooltips when you
hover over them:</p>
<figure><img src="https://karthinks.com/img/dictionary-tooltip-01.png">
</figure>

<p>Of course, <code>tooltip-mode</code> will need to be enabled as well, but that’s the
default.</p>
<p>If you have local dictionaries set up, it will try those first.  Note that
Emacs’ dictionary can look up contemporary jargon and lingo too, usually via
Wiktionary:</p>
<video>

<a href="https://karthinks.com/img/dictionary-tooltip-demo-01.mp4&quot;">[VIDEO: Emacs dictionary-tooltip-mode demo]</a></video>
<h2><code>find-file</code> and <code>dired</code> with wildcards</h2>
<p>A surprisingly little known utility of two of the most used Emacs commands: you
can use wildcards when using both <code>find-file</code> and <code>dired</code> interactively.</p>
<ul>
<li>When finding files with <code>find-file</code> (<code>C-x C-f</code>), open multiple files at once
with a wildcard like <code>*foo*.txt</code>.</li>
<li>When opening a directory with Dired, produce a custom listing of specific
files by specifying a filename wildcard.</li>
</ul>
<p>Here’s a demo where both features are used to clean up some (very) old TeX
compilation artifacts and then open a bunch of LaTeX files at once:</p>
<video>

<a href="https://karthinks.com/img/dired-wildcard-demo-01.mp4&quot;">[VIDEO: Emacs Dired and Find-File wildcards demo]</a></video>

Play by play
<div class="details">
<ul>
<li>Run Dired with a “two-level” wildcard <code>*/*_region_*</code>: look for all files with
<code>"_region_"</code>  in their name, but only in sub-directories.</li>
<li>Dired produces a listing of these files.  (These are temporary files created by
AucTeX.)</li>
<li>Select them all (with <code>dired-toggle-marks</code>, bound to <code>t</code>) and delete them.</li>
<li>Run <code>find-file</code> with a wildcard, opening all TeX files in sub-directories.</li>
<li>Check the list of buffers to see that several TeX files have been opened.</li>
</ul>
<p>(The command used to see the list of open buffers is <code>consult-buffer</code>, and the
completions are displayed by <code>Corfu</code>.)</p>
</div>

<p>The fact that this is possible when calling them programmatically is evident
from their function signatures.  But realizing that this capability is also
available during interactive use requires reading through the full docstring,
and no one has the time for that!</p>
<p>In practice the Dired wildcard capability is superseded by a modern workflow
like <code>consult-find</code> exported as a Dired buffer by <code>embark-export</code>, but this
works out of the box.</p>
<h2>List all URIs with <code>M-x ffap-menu</code></h2>
<p>You might be familiar with Emacs’ “find-file-at-point” feature, <code>M-x ffap</code>, that
checks if the cursor is on a valid file path and offers to open it.</p>
<p>This is accompanied by <code>ffap-menu</code>, a less well known but equally handy command.
<code>ffap-menu</code> scans the whole buffer for anything that looks like a file path or
URL and presents you with all of them:</p>
<video>

<a href="https://karthinks.com/img/ffap-menu-demo-01.mp4&quot;">[VIDEO: Emacs ffap-menu demo]</a></video>
<p>Since it offers a <code>completing-read</code> interface, this opens up a small universe of
possibilities: you can export the list of (possibly filtered) completions into a
buffer, copy or open all or any subset of them, or otherwise act on them right
away with Embark.</p>
<h3>Addendum: Listing propertized links</h3>
<p>Many Emacs applications (like EWW) include URLs as text properties and not
plain-text links, and <code>ffap-menu</code> misses them.  Inspired by <code>ffap-menu</code>, I use a
home-brew version that fetches such links as well.</p>
<video>

<a href="https://karthinks.com/img/search-occur-browse-url-01.mp4&quot;">[VIDEO: Find all URLs demo]</a></video>

Play by play
<div class="details">
<ul>
<li>Start with EWW showing a Wikipedia page, with imenu on the left.</li>
<li>Call <code>my/search-occur-browse-url</code>, a custom command inspired by <code>ffap-menu</code></li>
<li>Scroll through the list of page links, and scroll through the page itself.</li>
</ul>
</div>

<p>The enhanced version:</p>

Searching for all URLs in the buffer
<div class="details">
<div class="highlight"><pre><code class="language-emacs-lisp"><span><span>(<span>defun</span> <span>my/search-occur-browse-url</span> (<span>&amp;optional</span> <span>use-generic-p</span>)
</span></span><span><span>  <span>"Point browser at a URL in the buffer using completion.
</span></span></span><span><span><span>Which web browser to use depends on the value of the variable
</span></span></span><span><span><span></span><span>`browse-url-browser-function'</span><span>.
</span></span></span><span><span><span>
</span></span></span><span><span><span>Also see </span><span>`my/search-occur-url'</span><span>."</span>
</span></span><span><span>  (<span>interactive</span> <span>"P"</span>)
</span></span><span><span>  (<span>let</span> ((<span>match</span> <span>nil</span>)
</span></span><span><span>        (<span>match-data</span> <span>nil</span>)
</span></span><span><span>        (<span>context</span>
</span></span><span><span>         (<span>lambda</span> (<span>beg</span> <span>&amp;optional</span> <span>shrp</span>)
</span></span><span><span>           (<span>let*</span> ((<span>before</span> (<span>string-replace</span>
</span></span><span><span>                           <span>"\n"</span> <span>""</span>
</span></span><span><span>                           (<span>buffer-substring-no-properties</span>
</span></span><span><span>                            <span>beg</span> (<span>max</span> (<span>line-beginning-position</span>) (<span>-</span> <span>beg</span> <span>30</span>)))))
</span></span><span><span>                  (<span>link</span> (<span>string-replace</span>
</span></span><span><span>                         <span>"\n"</span> <span>""</span> (<span>buffer-substring-no-properties</span> <span>beg</span> (<span>point</span>))))
</span></span><span><span>                  (<span>after</span> (<span>buffer-substring-no-properties</span>
</span></span><span><span>                          (<span>point</span>) (<span>min</span> (<span>line-end-position</span>) (<span>+</span> (<span>point</span>) <span>30</span>)))))
</span></span><span><span>             (<span>concat</span> (<span>propertize</span> <span>" "</span> <span>'display</span> <span>'</span>(<span>space</span> <span>:align-to</span> <span>65</span>))
</span></span><span><span>                     (<span>propertize</span> (<span>concat</span> <span>"…"</span> <span>before</span>) <span>'face</span> <span>'shadow</span>)
</span></span><span><span>                     (<span>if</span> <span>shrp</span>
</span></span><span><span>                         (<span>propertize</span> <span>link</span> <span>'face</span> <span>'</span>(<span>:inherit</span> <span>shadow</span> <span>:weight</span> <span>bold</span>
</span></span><span><span>                                                           <span>:underline</span> <span>t</span>))
</span></span><span><span>                       <span>link</span>)
</span></span><span><span>                     (<span>propertize</span> (<span>concat</span> <span>after</span> <span>"…"</span>) <span>'face</span> <span>'shadow</span>))))))
</span></span><span><span>    (<span>save-excursion</span>
</span></span><span><span>      (<span>goto-char</span> (<span>point-min</span>))
</span></span><span><span>      (<span>while</span> (<span>search-forward-regexp</span> <span>my/search-url-regexp</span> <span>nil</span> <span>t</span>)
</span></span><span><span>        (<span>push</span> (<span>cons</span> (<span>match-string-no-properties</span> <span>0</span>)
</span></span><span><span>                    (<span>funcall</span> <span>context</span> (<span>match-beginning</span> <span>0</span>)))
</span></span><span><span>              <span>match-data</span>))
</span></span><span><span>      (<span>goto-char</span> (<span>point-min</span>))
</span></span><span><span>      (<span>while</span> (<span>setq</span> <span>match</span> (<span>text-property-search-forward</span> <span>'shr-url</span> <span>nil</span> <span>nil</span>))
</span></span><span><span>        (<span>push</span> (<span>cons</span> (<span>prop-match-value</span> <span>match</span>)
</span></span><span><span>                    (<span>funcall</span> <span>context</span> (<span>prop-match-beginning</span> <span>match</span>) <span>'shrp</span>))
</span></span><span><span>              <span>match-data</span>)))
</span></span><span><span>    (<span>let*</span> ((<span>completion-extra-properties</span>
</span></span><span><span>            <span>`</span>(<span>:annotation-function</span>
</span></span><span><span>              <span>,</span>(<span>lambda</span> (<span>cand</span>) (<span>concat</span> <span>" "</span> (<span>cdr</span> (<span>assoc</span> <span>cand</span> <span>match-data</span>))))))
</span></span><span><span>           (<span>url</span> (<span>completing-read</span> <span>"Browse URL: "</span> <span>match-data</span> <span>nil</span> <span>t</span>)))
</span></span><span><span>      (<span>if</span> <span>use-generic-p</span>
</span></span><span><span>          (<span>browse-url-generic</span> <span>url</span>)
</span></span><span><span>        (<span>browse-url</span> <span>url</span>)))))
</span></span></code></pre></div></div>

<h2>Compare windows (<code>M-x compare-windows</code>)</h2>
<p>There are more commands for comparing buffers and files in Emacs than you can
shake a stick at: there’s <code>diff</code>, <code>diff-buffers</code>, <code>diff-backup</code>,
<code>diff-buffer-with-file</code>, <code>dired-diff</code>, <code>vc-diff</code>, and a whole constellation of
<code>ediff-</code>, <code>ediff-merge-</code> and <code>ediff-directories-</code> commands.  I lost count at
around twenty two, and can’t remember most of them.</p>
<p>But my favorite diff command is the lightweight <code>compare-windows</code>, which does
something very obvious and simple in a context-agnostic way.</p>
<p>It compares the text of two windows starting from their respective cursor
positions, and stops at and reports the next mismatch.  The two windows are the
active one and whatever <code>other-window</code> would select.  Obviously less powerful,
but so much easier and faster to run than Ediff
<span class="sidenote-number"><small>
Have you tried <code>ediff-regions-linewise</code>?  Setting this up is a four step
process, involving selecting buffers, marking regions and calling
<code>exit-recursive-edit</code> repeatedly, an advanced command that most Emacs users
should never encounter!
</small></span>
or diff:</p>
<video>

<a href="https://karthinks.com/img/compare-windows-demo.mp4&quot;">[VIDEO: compare-windows Emacs demo]</a></video>

Play by play
<div class="details">
<ol>
<li>Move the cursor to the beginnings of the text to compare in two windows.</li>
<li><code>M-x compare-windows</code></li>
<li>That’s it.  It moves the cursors to the first mismatch and reports it.</li>
</ol>
</div>

<p><code>compare-windows</code> is only concerned with the actual text in the two windows, and
not the provenance of this text.  The buffer type, modification state, file,
version-control status – all irrelevant!  You can even compare a
chunk of text in a buffer against another chunk a little further down in the
same buffer by displaying it in both windows.  In a silly yet effective way, it
can even compare directory contents, including file attributes:</p>
<video>

<a href="https://karthinks.com/img/compare-windows-demo-02.mp4&quot;">[VIDEO: compare-windows Emacs demo 2]</a></video>

Play by play
<div class="details">
<ol>
<li>Two directories containing some similar-looking files.</li>
<li>Place the cursors on the same file in both windows.</li>
<li><code>M-x compare-windows</code></li>
<li>The cursors stop at the first reported mismatch, which is a file modification
time here.</li>
</ol>
</div>

<p>And yes, you can call it with a prefix argument to ignore whitespace differences.</p>
<p><code>compare-windows</code> is what you use when you find yourself playing
spot-the-difference between two views of any kind.  It is my most used “diff”
command.</p>
<h2>Compare directories with Dired (<code>M-x dired-compare-directories</code>)</h2>
<p>But speaking of comparing directories, Dired does (of course) provide a less
hacky way to do that.  <code>M-x dired-compare-directories</code> in Dired prompts for a
directory to compare with, and marks all files whose names differ in both Dired
listings.  That covers the most common use case, and might be everything you
need.</p>
<p>But we already did that with the rudimentary <code>compare-windows</code>.
<code>dired-compare-directories</code> is an actual file-level comparison, so you can
provide custom matching predicates involving any file attribute, like
modification times or sizes.  For instance,</p>
<ul>
<li>you can mark the more recently modified version of a file with <code>(&gt; mtime2 mtime1)</code>,</li>
<li>or mark files with the same name but different sizes with <code>(/= size1 size2)</code></li>
</ul>
<p>In this example, <code>dired-compare-directories</code> has marked (i) files that are not
common to the two listings and (ii) files with differing modification times:</p>
<figure><img src="https://karthinks.com/img/dired-compare-directories-01.png">
</figure>


An Ediff for every season
<div class="details">
<p>If you want something more interactive/prescribed there is also an
<code>ediff-directories</code>, because there is an Ediff command for every occasion.</p>
</div>

<h2>Highlight buffer changes (<code>M-x highlight-changes-mode</code>)</h2>
<p>While we’re on the topic of spotting differences, <code>highlight-changes-mode</code> is a
handy way to emphasize changes to the file, and a “live” alternative to diff
commands like <code>diff-buffer-with-file</code>:</p>
<video>

<a href="https://karthinks.com/img/highlight-changes-mode-demo-01.mp4&quot;">[VIDEO: Emacs highlight-changes-mode demo]</a></video>

Play by play
<div class="details">
<ul>
<li>Run the below code block syncing <code>highlight-changes-mode</code> with <code>save-buffer</code>.
Now changes are highlighted until the next save.</li>
<li>Make some changes.  Notice that added/changed text is colored differently.</li>
<li>Save the buffer, clearing the highlights in the process.</li>
<li>Repeat the last two steps a couple of times.</li>
</ul>
</div>

<p>Visualization with highlight-changes is determined only by the mode itself, and
changes are highlighted from the time the mode is turned on until it’s turned
off.  In general, this is not what we want.  What we would like instead is to
highlight <em>unsaved</em> changes
<span class="sidenote-number"><small>
There is <code>M-x highlight-compare-with-file</code>, but this is non-ergonomic enough to
the point of being unusable.
</small></span>
.  We could do this with some finesse, or just throw in a couple of hooks:</p>
<div class="highlight"><pre><code class="language-emacs-lisp"><span><span>(<span>defun</span> <span>highlight-changes-mode-turn-off</span> ()
</span></span><span><span>  (<span>and</span> <span>highlight-changes-mode</span> (<span>highlight-changes-mode</span> <span>-1</span>)))
</span></span><span><span>
</span></span><span><span>(<span>defun</span> <span>highlight-changes-auto</span> ()
</span></span><span><span>  (<span>when</span> (<span>buffer-file-name</span>)
</span></span><span><span>    (<span>highlight-changes-mode-turn-on</span>)
</span></span><span><span>    (<span>add-hook</span> <span>'after-save-hook</span> <span>#'</span><span>highlight-changes-mode-turn-on</span> <span>nil</span> <span>t</span>)
</span></span><span><span>    (<span>add-hook</span> <span>'before-save-hook</span> <span>#'</span><span>highlight-changes-mode-turn-off</span> <span>nil</span> <span>t</span>)))
</span></span><span><span>
</span></span><span><span>(<span>add-hook</span> <span>'text-mode-hook</span> <span>#'</span><span>highlight-changes-auto</span>)
</span></span></code></pre></div><p>Now all changes in text-mode buffers are automatically highlighted.</p>

<code>highlight-unsaved</code> as a standalone feature
<div class="details">
<p>The highlight-changes visualization can be customized to be more subtle, but you
probably don’t want it turned on all the time nevertheless.  The above hook
logic can easily be turned into a minor-mode in its own right:</p>
<div class="highlight"><pre><code class="language-emacs-lisp"><span><span>(<span>require</span> <span>'hilit-chg</span>)
</span></span><span><span>(<span>defun</span> <span>highlight-changes-mode-turn-off</span> ()
</span></span><span><span>  (<span>and</span> <span>highlight-changes-mode</span> (<span>highlight-changes-mode</span> <span>-1</span>)))
</span></span><span><span>
</span></span><span><span>(<span>define-minor-mode</span> <span>highlight-unsaved-mode</span>
</span></span><span><span>  <span>"Highlight all changes until the buffer is saved."</span>
</span></span><span><span>  <span>:lighter</span> <span>"H"</span>
</span></span><span><span>  (<span>cond</span>
</span></span><span><span>   ((<span>not</span> (<span>buffer-file-name</span>))
</span></span><span><span>    (<span>user-error</span> <span>"Highlight-until-save-mode is only meant for use in file-visiting buffers"</span>))
</span></span><span><span>   (<span>highlight-until-save-mode</span>
</span></span><span><span>    (<span>highlight-changes-mode</span> <span>1</span>)
</span></span><span><span>    (<span>add-hook</span> <span>'after-save-hook</span> <span>#'</span><span>highlight-changes-mode-turn-on</span> <span>nil</span> <span>t</span>)
</span></span><span><span>    (<span>add-hook</span> <span>'before-save-hook</span> <span>#'</span><span>highlight-changes-mode-turn-off</span> <span>nil</span> <span>t</span>))
</span></span><span><span>   (<span>t</span> (<span>highlight-changes-mode</span> <span>-1</span>)
</span></span><span><span>      (<span>remove-hook</span> <span>'after-save-hook</span> <span>#'</span><span>highlight-changes-mode-turn-on</span> <span>t</span>)
</span></span><span><span>      (<span>remove-hook</span> <span>'before-save-hook</span> <span>#'</span><span>highlight-changes-mode-turn-off</span> <span>t</span>))))
</span></span></code></pre></div></div>

<hr>
<p>Finally, <code>highlight-changes-mode</code> provides an auxiliary capability: you can jump
to the next and previous change in the buffer with
<code>highlight-changes-next-change</code> and <code>highlight-changes-previous-change</code>.  Since
this is an independent consequence of change tracking you can use just this
navigation and turn off the change visualization with <code>M-x highlight-changes-remove-highlight</code>.</p>
<h2>Actually useful file backups (<code>vc-diff</code> variants)</h2>
<p>One last excursion to close out the theme of spotting and diffing changes.</p>
<p>This will require a tangent through the topic of Emacs backup files and is
pushing both the five minute limit and the idea of a built-in, so please bear
with me.</p>
<h3>Let’s back up</h3>
<p>By default, Emacs makes a periodic backup of any file you edit and save.
This backup system is usually mentioned only in the context of being something
annoying you should disable (via <code>make-backup-files</code>).  If you want actual
backups you could just use version control, right?</p>
<p>If you have security concerns with sensitive files being copied to elsewhere on
disk, I sympathize.  But otherwise, I think this is largely an ergonomics issue.</p>
<ul>
<li>Emacs litters your working directory with the backups, and</li>
<li>doesn’t make it easy to peruse and work with the backup files.</li>
</ul>
<p>Changing the former is a user option
<span class="sidenote-number"><small>
For example, see <code>backup-directory-alist</code>, <code>kept-old-versions</code> and
<code>kept-new-versions</code>.
</small></span>
, but the latter is entirely the case of a missing user interface.</p>
<p>The external package <a href="https://github.com/lewang/backup-walker">backup-walker</a> provides this “time-machine” interface,
along with a couple of others.  But there is a simpler, satisfying fix available
that simultaneously solves another problem.</p>
<h3>VC (until V don’t)</h3>
<p>Emacs’ built-in VC package offers an interface for viewing past versions of
version-controlled files:</p>
<dl>
<dt><code>vc-diff</code> (<code>C-x v =</code>)</dt>
<dd>Diffs the file against its immediate previous
version, or against a prescribed version when called with a prefix argument.</dd>
<dt><code>vc-ediff</code></dt>
<dd>Runs Ediff against the file’s previous version, or against a
prescribed version.</dd>
<dt><code>vc-revision-other-window</code> (<code>C-x v ~</code>)</dt>
<dd>Displays a previous version (immediate or
specified) of the file next to this one.</dd>
</dl>
<p>This is a handy interface
<span class="sidenote-number"><small>
and not git-specific, unlike magit’s versions of these commands.
</small></span>
, but of course they do nothing in files that aren’t version controlled.</p>
<p>In the spirit of getting the most out of every fiber of muscle memory, we can
extend the <code>vc-</code> interface for the purpose of inspecting backups as well.</p>
<h3>The bridge</h3>
<p>We can overload all three VC commands so they <em>always</em> do something useful in a
file:</p>
<ul>
<li>If the file is unsaved, <code>vc-diff</code> (<code>vc-ediff</code>) generates a diff of (runs Ediff
on) the buffer against the file.</li>
<li>If the file is version controlled, run <code>vc-diff</code> (<code>vc-ediff</code>,
<code>vc-revision-other-window</code>) as usual.</li>
<li>If the file is not version controlled, diff against (Ediff, show) the latest
numbered backup, or a prescribed numbered backup when called with a prefix
argument.</li>
</ul>
<p>This forces functions into a single consistent mental model:</p>
<blockquote>
<p>Compare against the previous version, for whatever “previous” means in this
context.</p>
</blockquote>
<p>As a bonus, we are also free to forget about a few different diff commands that
have been subsumed here, such as <code>diff-buffer-with-file</code> and <code>ediff-current-file</code>.</p>

Augmenting <code>vc-*</code> commands
<div class="details">
<div class="highlight"><pre><code class="language-emacs-lisp"><span><span>(<span>defun</span> <span>my/read-backup-file-name</span> (<span>file</span>)
</span></span><span><span>  (<span>if-let*</span> ((<span>backup-files</span> (<span>file-backup-file-names</span> <span>file</span>)))
</span></span><span><span>      (<span>completing-read</span> <span>"Backup version: "</span> <span>backup-files</span> <span>nil</span> <span>t</span>)
</span></span><span><span>    (<span>user-error</span> <span>"No backup files available for file %s"</span> (<span>buffer-file-name</span>))))
</span></span><span><span>
</span></span><span><span>(<span>defun</span> <span>my/vc-diff</span> (<span>&amp;optional</span> <span>arg</span>)
</span></span><span><span>  <span>"Compare current buffer with its file, or file with backup or revision.
</span></span></span><span><span><span>With prefix ARG, compare the file with a selected backup when the file
</span></span></span><span><span><span>is not under version control."</span>
</span></span><span><span>  (<span>interactive</span> <span>"P"</span>)
</span></span><span><span>  (<span>if</span> (<span>buffer-modified-p</span>)
</span></span><span><span>      (<span>diff-buffer-with-file</span> (<span>current-buffer</span>))
</span></span><span><span>    (<span>condition-case</span> <span>errdata</span> (<span>call-interactively</span> <span>#'</span><span>vc-diff</span>)
</span></span><span><span>      (<span>error</span>
</span></span><span><span>       (<span>if</span> (<span>string-match-p</span> <span>"not under version control"</span> (<span>cadr</span> <span>errdata</span>))
</span></span><span><span>           (<span>if</span> <span>arg</span>
</span></span><span><span>               (<span>diff</span> (<span>my/read-backup-file-name</span> (<span>buffer-file-name</span>))
</span></span><span><span>                     (<span>buffer-file-name</span>))
</span></span><span><span>             (<span>diff-backup</span> (<span>buffer-file-name</span>)))
</span></span><span><span>         (<span>apply</span> <span>#'</span><span>signal</span> <span>errdata</span>))))))
</span></span><span><span>
</span></span><span><span>(<span>defun</span> <span>my/vc-ediff</span> (<span>&amp;optional</span> <span>arg</span>)
</span></span><span><span>  <span>"Run Ediff on the current buffer, file, or backup.
</span></span></span><span><span><span>With prefix ARG, compare the file with a selected backup when the file
</span></span></span><span><span><span>is not under version control."</span>
</span></span><span><span>  (<span>interactive</span> <span>"P"</span>)
</span></span><span><span>  (<span>if</span> (<span>buffer-modified-p</span>)
</span></span><span><span>      (<span>call-interactively</span> <span>#'</span><span>ediff-current-file</span>)
</span></span><span><span>    (<span>condition-case</span> <span>errdata</span> (<span>call-interactively</span> <span>#'</span><span>vc-ediff</span>)
</span></span><span><span>      (<span>error</span>
</span></span><span><span>       (<span>if</span> (<span>string-match-p</span> <span>"not under version control"</span> (<span>cadr</span> <span>errdata</span>))
</span></span><span><span>           (<span>if</span> <span>arg</span>
</span></span><span><span>               (<span>ediff-files</span> (<span>my/read-backup-file-name</span> (<span>buffer-file-name</span>))
</span></span><span><span>                            (<span>buffer-file-name</span>))
</span></span><span><span>             (<span>ediff-backup</span> (<span>buffer-file-name</span>)))
</span></span><span><span>         (<span>apply</span> <span>#'</span><span>signal</span> <span>errdata</span>))))))
</span></span><span><span>
</span></span><span><span>(<span>defun</span> <span>my/vc-revision-other-window</span> (<span>&amp;optional</span> <span>arg</span>)
</span></span><span><span>  <span>"Visit the current file's past revision or backup in another window.
</span></span></span><span><span><span>With prefix ARG, visit a selected backup when the file is not under
</span></span></span><span><span><span>version control."</span>
</span></span><span><span>  (<span>interactive</span> <span>"P"</span>)
</span></span><span><span>  (<span>condition-case</span> <span>errdata</span> (<span>call-interactively</span> <span>#'</span><span>vc-revision-other-window</span>)
</span></span><span><span>    (<span>error</span>
</span></span><span><span>     (<span>if</span> (<span>string-match-p</span> <span>"not under version control"</span> (<span>cadr</span> <span>errdata</span>))
</span></span><span><span>         (<span>if</span> <span>arg</span>
</span></span><span><span>             (<span>find-file-other-window</span> (<span>my/read-backup-file-name</span> (<span>buffer-file-name</span>)))
</span></span><span><span>           (<span>if-let*</span> ((<span>backup</span> (<span>file-newest-backup</span> (<span>buffer-file-name</span>))))
</span></span><span><span>               (<span>find-file-other-window</span> <span>backup</span>)
</span></span><span><span>             (<span>user-error</span> <span>"No backup files available for %s"</span> (<span>buffer-file-name</span>))))
</span></span><span><span>       (<span>apply</span> <span>#'</span><span>signal</span> <span>errdata</span>)))))
</span></span></code></pre></div></div>

<p>See <a href="https://karthinks.com/tags/emacs/#scroll-all-windows--m-x-scroll-all-mode">scroll all windows</a> for a demonstration of the
generalized <code>vc-diff</code> working with backup files.</p>
<h2>The apropos <em>family</em></h2>
<p>If you only use one help keybinding, it should be <code>C-h k</code>, <code>describe-key</code>, since
the very fact that every key press invokes a first-class function that you can
live-inspect and mess with can be a revelation.</p>
<p>If you learn two, there is a strong case for <code>apropos</code> being the second.  It
bridges the gap between not knowing what to search for and getting a full
picture of how things are laid out.  It’s a foot-in-the-door command.</p>
<p>But you already know <code>apropos</code>.  What’s less evident is that <code>apropos</code> is a
whole family of commands that do increasingly specialized but useful look-ups
<span class="sidenote-number"><small>
It’s ironic that the extended apropos family is itself not very discoverable.
</small></span>
.</p>
<p>Bind them all under <code>C-h a</code>, replacing <code>apropos</code>:</p>
<div class="highlight"><pre><code class="language-emacs-lisp"><span><span>(<span>defvar-keymap</span> <span>help-apropos-map</span>
</span></span><span><span>  <span>:doc</span> <span>"Keymap for apropos subcommands."</span>
</span></span><span><span>  <span>"a"</span>   <span>#'</span><span>apropos</span>
</span></span><span><span>  <span>"l"</span>   <span>#'</span><span>apropos-library</span>
</span></span><span><span>  <span>"f"</span>   <span>#'</span><span>apropos-function</span>
</span></span><span><span>  <span>"x"</span>   <span>#'</span><span>apropos-command</span>
</span></span><span><span>  <span>"v"</span>   <span>#'</span><span>apropos-variable</span>
</span></span><span><span>  <span>"V"</span>   <span>#'</span><span>apropos-local-variable</span>
</span></span><span><span>  <span>"u"</span>   <span>#'</span><span>apropos-user-option</span>
</span></span><span><span>  <span>"d"</span>   <span>#'</span><span>apropos-documentation</span>
</span></span><span><span>  <span>"C-f"</span> <span>#'</span><span>customize-apropos-faces</span>
</span></span><span><span>  <span>"g"</span>   <span>#'</span><span>customize-apropos-groups</span>
</span></span><span><span>  <span>"o"</span>   <span>#'</span><span>customize-apropos-options</span>
</span></span><span><span>  <span>"c"</span>   <span>#'</span><span>customize-apropos</span>
</span></span><span><span>  <span>"i"</span>   <span>#'</span><span>info-apropos</span>)
</span></span><span><span>(<span>keymap-set</span> <span>help-map</span> <span>"a"</span> <span>help-apropos-map</span>)
</span></span></code></pre></div>
<code>prefix-help-command</code>
<div class="details">
<p>You don’t need to remember any of these!  If you don’t already use a prompter like
<code>which-key</code>, you can press <code>C-h</code> after the prefix <code>C-h a</code> to bring up a listing of the
available commands.</p>
</div>

<p>My favorite of these is <code>customize-apropos</code>: it produces a bespoke customization
buffer for perusing or changing all options matching the thing you searched for:</p>
<video>

<a href="https://karthinks.com/img/customize-apropos-demo-01.mp4&quot;">[VIDEO: Emacs customize-apropos demo]</a></video>

Play by play
<div class="details">
<ul>
<li>Invoke the apropos map prefix (<code>C-h a</code>)</li>
<li>Press <code>C-h</code> to see available commands under this prefix.  I used Embark for
this feature, but you should see a list of available commands no matter what.</li>
<li>Pick <code>customize-apropos</code> and search for “async”</li>
<li>It produces a customize buffer with all options, faces and groups matching “async”.</li>
</ul>
</div>

<h2><code>find-func</code> goodies (<code>M-x find-function-on-key</code>, <code>M-x find-function</code>)</h2>
<p>One of the most useful things you can do in Emacs, if you don’t like what a
keybinding does (or if you’re simply curious), is to jump to the definition of
the command it calls to see how to modify its behavior live.  Normally this is a
multi-step process:</p>
<ol>
<li>Find the command invoked by the key: <code>describe-key</code> or <code>C-h k</code> + your key
sequence.</li>
<li>Jump to its definition by pressing <code>s</code> (for “source”).</li>
<li>Get hacking or reading.</li>
</ol>
<p><code>find-function-on-key</code> obviates step 2, and takes you from keybinding to the
source.  Bind it to a key and you’re off to the races.</p>
<p><code>C-h M-k</code> for me, as it’s a variation of <code>describe-key</code>:</p>
<div class="highlight"><pre><code class="language-emacs-lisp"><span><span>(<span>keymap-set</span> <span>help-map</span> <span>"M-k"</span> <span>#'</span><span>find-function-on-key</span>)
</span></span></code></pre></div><p>Going from a keybinding to the source of the function in one step is a minor
shortcut for the common route, but it’s magical the first time you try it.
<span class="sidenote-number"><small>
No video demo, because the effect is so instantaneous a video would be both (i)
confusing and (ii) underwhelming!
</small></span></p>
<h2><code>copy-from-above-command</code> and <code>duplicate-dwim</code></h2>
<p>Emacs recently added some missing editing commands that have been part of most
users’ tool-belts for decades.  The two most useful of these are for duplicating
text with the cursor as the destination and source.  Respectively,</p>
<ul>
<li><code>copy-from-above-command</code> copies text from the first non-blank line above the
current one, similar to Vim’s <code>C-y</code>.</li>
<li><code>duplicate-dwim</code> copies text on the current line (or active region) below the
current one, similar to Vim’s <code>yy&lt;N&gt;p</code><sup><a href="https://karthinks.com/tags/emacs/#fn:1">1</a></sup>.</li>
</ul>
<p>In typical Emacs fashion, slight tweaks can make these commands work how your
brain does:</p>
<ul>
<li>
<p><code>copy-from-above-command</code> copies as many characters from the above line as the
prefix argument.  I typically want to copy the whole line, so I change the
prefix argument interpretation to “copy the above line and comment it out”, a
very common action when experimenting with code or prose:</p>
<div class="highlight"><pre><code class="language-emacs-lisp"><span><span>  (<span>define-advice</span> <span>copy-from-above-command</span> (<span>:around</span> (<span>func</span> <span>&amp;optional</span> <span>arg</span>) <span>comment</span>)
</span></span><span><span>    (<span>if</span> (<span>equal</span> <span>current-prefix-arg</span> <span>'</span>(<span>4</span>))
</span></span><span><span>        (<span>progn</span>
</span></span><span><span>          (<span>funcall</span> <span>func</span>)
</span></span><span><span>          (<span>save-excursion</span>
</span></span><span><span>            (<span>forward-line</span> <span>0</span>)
</span></span><span><span>            (<span>let</span> ((<span>ln</span> (<span>line-number-at-pos</span> (<span>point</span>))))
</span></span><span><span>              (<span>backward-char</span>)
</span></span><span><span>              (<span>skip-chars-backward</span> <span>"\n\t "</span>)
</span></span><span><span>              (<span>unless</span> (<span>=</span> (<span>line-number-at-pos</span>) <span>ln</span>)
</span></span><span><span>                (<span>comment-line</span> <span>1</span>)))))
</span></span><span><span>      (<span>funcall</span> <span>func</span> <span>arg</span>)))
</span></span></code></pre></div><p>Note that the original prefix argument behavior still works, and you can copy
a fixed number of characters from above with a numeric prefix argument
(<code>C-&lt;N&gt;</code>).</p>
</li>
<li>
<p><code>duplicate-dwim</code> has a choice to make about where to place the cursor after
the duplication: does the user mean to continue working with the duplicated
text or the original?</p>
<p>You can make that choice for yourself by setting a user option.  I prefer to
move the cursor and region to the duplicated text:</p>
<div class="highlight"><pre><code class="language-emacs-lisp"><span><span>  (<span>setq</span> <span>duplicate-region-final-position</span> <span>-1</span>
</span></span><span><span>        <span>duplicate-line-final-position</span> <span>-1</span>)
</span></span></code></pre></div></li>
</ul>
<h2>Turn keystrokes into macros (<code>M-x kmacro-edit-lossage</code>)</h2>
<p>Three facts about Emacs keyboard macros:</p>
<ol>
<li>They are far more powerful than many users realize
<span class="sidenote-number"><small>
See Mickey Peterson’s excellent article <a href="https://www.masteringemacs.org/article/keyboard-macros-are-misunderstood">Keyboard Macros are Misunderstood</a>
</small></span>
.  We tend to associate macros with text transformations, but they capture
and playback <em>any</em> sequence of actions in Emacs, including mouse clicks.  And
since this is Emacs, actions don’t have to correspond to text editing at all.
All the short video demos in this article were copied across Dired buffers,
processed with FFmpeg, renamed and inserted into the draft using a single
keyboard macro.</li>
<li>They require a lot of premeditation and focus to use.  Unfortunately
“thinking in macros” is cognitively taxing.  Any error or non-generalizable
movement can scupper the whole attempt.  The <a href="https://github.com/magnars/multiple-cursors.el">multiple-cursors</a> package and
others like it present alternative interfaces to keyboard macros that lower
the mental strain.</li>
<li>But they still don’t solve the “foresight” problem: I need to know before the
fact that a sequence of actions will need to be repeatable, and start a
recording.  Coupled with the fact that you’re unlikely to get a complex
sequence right the first time, we’re back to the previous problem again.</li>
</ol>
<p>Vim’s <code>.</code> (dot) command is a solution here, since Vim is effectively
always recording a macro of your edits, and Emacs’ <code>dot-mode</code> package emulates this
with some success.  But these are still limited to buffer edits, and not full
fledged keyboard macros.</p>
<p>Well.  Emacs provides the confusingly named <code>kmacro-edit-lossage</code> command that
addresses this foresight problem, albeit in a manual way.  At any time, you can
view your “lossage”, a record of the last 300 or so key-presses with the
<code>view-lossage</code> (<code>C-h l</code>) command.</p>
<p><code>kmacro-edit-lossage</code> takes this further, and lets you create a macro from your
key-press history at any time.  The lossage is truly editable, you can and will
want to insert new commands into the lossage when creating a macro.  An example
of creating a macro from a keystroke sequence that is setting up a window split:</p>
<figure><img src="https://karthinks.com/img/kmacro-edit-lossage.png">
</figure>

<blockquote>
<p>“Oh, I need to do the complex thing I just did 200 times”</p>
</blockquote>
<p>In practice, I edit macros I’ve already defined with <code>edit-kbd-macro</code> (<code>C-x C-k e</code>) more than I fashion new ones from the lossage, but on the infrequent
occasions that call for <code>kmacro-edit-lossage</code>, it’s a real lifesaver
<span class="sidenote-number"><small>
The editing process generally requires a generous sprinkling of
<code>kbd-macro-query</code> calls into the lossage to be truly generalizable.
</small></span>
.</p>
<h2><code>subword-mode</code>, <code>superword-mode</code> and word syntax</h2>
<p>Emacs offers word-based navigation and editing commands (<code>forward-word</code>,
<code>forward-to-word</code>, <code>kill-word</code>…) and major-mode-specific <em>syntax tables</em>,
leaving the question of “what is a word?” up to you.</p>
<p><code>subword-mode</code> and <code>superword-mode</code> are two different answers to this
question. With <code>subword-mode</code> turned on, each component of a CamelCase symbol
counts as a word.  As the documentation helpfully illustrates:</p>
<div class="highlight"><pre><code class="language-emacs-lisp"><span><span>  <span>Nomenclature</span>           <span>Subwords</span>
</span></span><span><span>  <span>===========================================================</span>
</span></span><span><span>  <span>GtkWindow</span>          <span>=&gt;</span>  <span>"Gtk"</span> <span>and</span> <span>"Window"</span>
</span></span><span><span>  <span>EmacsFrameClass</span>    <span>=&gt;</span>  <span>"Emacs"</span><span>,</span> <span>"Frame"</span> <span>and</span> <span>"Class"</span>
</span></span><span><span>  <span>NSGraphicsContext</span>  <span>=&gt;</span>  <span>"NS"</span><span>,</span> <span>"Graphics"</span> <span>and</span> <span>"Context"</span>
</span></span></code></pre></div><p>When <code>superword-mode</code> is turned on, snake_case symbols like <code>this_is_a_symbol</code>
counts as one word
<span class="sidenote-number"><small>
The <a href="https://github.com/akicho8/string-inflection">string-inflection</a> package provides a command to easily cycle between these
styles: <code>this_is_a_symbol</code> –&gt; <code>this-is-a-symbol</code> –&gt; <code>This_Is_A_Symbol</code> –&gt;
<code>thisIsASymbol</code> –&gt; <code>ThisIsASymbol</code>.
</small></span>
.  In practice, this is less useful than <code>subword-mode</code>, since acting on
symbols is already well supported in Emacs via the <code>*-sexp</code> commands.</p>
<p>More generally, it can be worth taking a few minutes to modify the syntax table
of a major mode to fix annoyances you might be experiencing with structural
navigation.  In Lisp-y contexts, my most useful change is to make “:” be
considered part of a word, so that I can <code>backward-kill-word</code> through keywords
like <code>:foo</code>:</p>
<div class="highlight"><pre><code class="language-emacs-lisp"><span><span>(<span>add-hook</span> <span>'lisp-data-mode-hook</span>
</span></span><span><span>          (<span>lambda</span> () (<span>modify-syntax-entry</span> <span>?:</span> <span>"w"</span>)))
</span></span></code></pre></div><p>In Org mode, it’s treating the delimiters <code>=</code> and <code>~</code> as word constituents:</p>
<div class="highlight"><pre><code class="language-emacs-lisp"><span><span>(<span>add-hook</span> <span>'org-mode-hook</span>
</span></span><span><span>          (<span>lambda</span> ()
</span></span><span><span>            (<span>modify-syntax-entry</span> <span>?=</span> <span>"w"</span>)
</span></span><span><span>            (<span>modify-syntax-entry</span> <span>?~</span> <span>"w"</span>))
</span></span></code></pre></div><p>See <code>describe-syntax</code> (<code>C-h s</code>) and <code>modify-syntax-entry</code> for how to specify the
syntax of characters.</p>
<h2>Manipulate image display</h2>
<p>Almost everywhere that Emacs displays an image, you can manipulate the display
by placing the cursor on the image and pressing <code>i</code>.  Here is an example with
images displayed in Elfeed (an RSS feed reader) and in Org mode:</p>
<video>

<a href="https://karthinks.com/img/image-bindings-demo-01.mp4&quot;">[VIDEO: Demo of image-map bindings in Emacs]</a></video>

Play by play
<div class="details">
<ul>
<li>Preview an Org mode link to an image with <code>org-link-preview</code></li>
<li>Zoom in with <code>i +</code>.</li>
<li>Subsequent zooms and rotation don’t require the <code>i</code> prefix because I use <code>repeat-mode</code>.</li>
<li>Do the same to the image displayed in the Elfeed entry buffer.</li>
</ul>
</div>

<p>I used the keyboard in this demo, but you could just use the <code>C-&lt;wheel&gt;</code>
shortcut familiar from browsers and other applications.</p>
<p>The most useful bindings are <code>i +</code> and <code>i -</code> to zoom, and maybe <code>i r</code> to rotate the
image by 90 degrees.  But you can do other things like cropping the image with <code>i c</code> – see
<code>M-x describe-keymap⮐  image-map</code>.</p>
<p>If you use <a href="https://karthinks.com/software/it-bears-repeating/">repeat-mode</a>, you don’t need the <code>i</code> prefix after the first invocation
either, you can repeat with just <code>+</code>, <code>-</code> or <code>r</code>.</p>
<p>This functionality is provided via a keymap placed over images, and nothing
needs to be turned on for this.  Note that only the image display is modified,
not the image on disk.</p>
<p>In web-pages and rendered-HTML buffers, there is one more useful command:
pressing <code>z</code> (<code>shr-zoom-image</code>) will split the image into horizontal strips
across several lines, and cycle through different image sizes.  It’s an odd
command, probably intended to mitigate Emacs’ display engine limitations when
dealing with large images.  But mitigate it does.  Useful if you visit websites
with huge images in Emacs.</p>
<h2>Make all text visible (<code>M-x visible-mode</code>)</h2>
<p>Emacs can make buffer text selectively invisible.  Marking text as invisible is
the basis of all “folding” behavior – think magit-section buffers, Outline
mode, Org mode and so on.  Every mode that provides folding also provides
keybindings to toggle the fold state, and pressing <code>TAB</code> usually works.
<em>Usually</em>.</p>
<p>In practice, these keybindings tend to be all over the place.  For when you
can’t be bothered to learn mode-specific conventions because you don’t use the
mode enough
<span class="sidenote-number"><small>
Or because the interface is <em>bonkers</em>, like the default <code>outline-minor-mode</code> keybindings.
</small></span>
and just want to see all hidden text, you’ve got <code>visible-mode</code>.</p>
<video>

<a href="https://karthinks.com/img/visible-mode-demo-01.mp4&quot;">[VIDEO: visible-mode Emacs demo]</a></video>

Play by play
<div class="details">
<ul>
<li>In a buffer with <code>outline-minor-mode</code> enabled, run <code>visible-mode</code>.  All text
is revealed.</li>
<li>Run <code>visible-mode</code> again to restore the previous text invisibilty state.</li>
<li>Switch to a magit buffer and run <code>visible-mode</code> for similar effects.</li>
</ul>
</div>

<p><code>visible-mode</code> is somewhat low-level, it simply disables text invisibility
across the buffer until you call it again.  So if the buffer is presenting a
“reactive” UI where (un)folding text has dynamic effects, things can appear
broken until you disable <code>visible-mode</code>.  As such, it’s intended as a temporary
measure or a debugging tool, but since it <em>always</em> works it’s my go-to button
for showing all buffer text uniformly with one command.</p>
<h2>Ignore invisible text (<code>isearch-toggle-invisible</code>)</h2>
<p>And speaking of <code>visible-mode</code>, some Emacs commands like Isearch ignore
text invisibility out of the box, making it easy to search across the actual
document text
<span class="sidenote-number"><small>
As usual, the full behavior is more complicated.  Isearch also <em>restores</em> the
invisibility when you move out of an invisible region that was temporarily
revealed.
</small></span>
.</p>
<p>But this behavior also has a downside.  When the buffer as presented is intended
as a guide, automatically revealing invisible text breaks our assumptions about
what Isearch will do.  This is a problem when using Isearch as a navigation (and
not a search) tool.</p>
<p>You can toggle searching invisible text when using Isearch with
<code>isearch-toggle-invisible</code>, bound to <code>M-s i</code> when searching:</p>
<video>

<a href="https://karthinks.com/img/isearch-toggle-invisible-demo-01.mp4&quot;">[VIDEO: Emacs isearch-toggle-invisible demo]</a></video>

Play by play
<div class="details">
<ul>
<li>With the intent to jump to one of the last headings in this Org document, Isearch for “zero”.</li>
<li>The search skips to a match in a folded region instead.</li>
<li>Cancel the match with <code>isearch-abort</code> (<code>C-g</code>)</li>
<li>Start Isearch again, and run <code>isearch-toggle-invisible</code> (<code>M-s i</code>)</li>
<li>Search for “zero”, jumping only to matches in the visible text</li>
<li>Exit Isearch at the desired match.</li>
</ul>
</div>

<p>This keybinding is not arbitrary – all the Isearch behavior toggles are under
the <code>M-s</code> keymap, mirroring Isearch’s default binding of <code>C-s</code>.  (But that’s a
whole article unto itself.)</p>
<h2>Ruler (<code>M-x ruler-mode</code>)</h2>
<p>At some point in its eventful past, Emacs was intended to possess WYSIWYG
word-processing features.  This is not surprising, it’s difficult to find
computing applications that Emacs doesn’t implement in its own janky, special
way.</p>
<p>One of the byproducts of this ambition is that there are some semi-buried
WYSIWYG features lingering around.  The <code>center-</code> commands are one such feature,
centering lines, paragraphs and regions relative to <code>fill-column</code>.  Useful for
fancy comments in code… and not much else, unless you like to print from Emacs
buffers.</p>
<p>But customizable display margin and fringe widths are a welcome addition, as a
lot of functionality can be stuffed into this screen estate.  The only problem
with specifying widths like margins is actually doing it.
<span class="sidenote-number"><small>
You might think that the handily named <code>set-left-margin</code> and <code>set-right-margin</code>
commands do this, but they actually work like the <code>center</code> commands, indenting
the actual buffer text.
</small></span>
It’s surprisingly messy.  There is no direct command for this, and setting the
display margins does not take effect until the window is displayed again.</p>
<p><code>ruler-mode</code> has you covered:</p>
<video>

<a href="https://karthinks.com/img/ruler-mode-demo-01.mp4&quot;">[VIDEO: Demo of ruler-mode for Emacs]</a></video>

Play by Play
<div class="details">
<ul>
<li>Turn on <code>ruler-mode</code>.</li>
<li>Hover over the header-line for a tooltip with instructions.</li>
<li>Use <code>S-&lt;mouse-1&gt;</code> and <code>S-&lt;mouse-3&gt;</code> to set the left and right margin for the buffer.</li>
<li>Drag <code>&lt;mouse-2&gt;</code> to set the <code>fill-column</code>.</li>
<li>Fill a paragraph to demonstrate the changed <code>fill-column</code>.</li>
<li>Restore the margins and turn off <code>ruler-mode</code>.</li>
</ul>
</div>

<p>As a bonus you can set the <code>fill-column</code> too.
<span class="sidenote-number"><small>
You can also set the <em>goal column</em>, but that’ll have to wait.
</small></span>
Of course, you could use the <code>visual-fill-column</code> or <code>olivetti</code> packages for
this, but if you like to change the margins on the fly instead of toggling
between preset widths, ruler-mode is arguably even more user-friendly.</p>
<h2>Refill text (<code>M-x refill-mode</code>)</h2>
<p>On the theme of text widths, Emacs provides a handy series of <code>fill-</code> commands
and an <code>auto-fill-mode</code> for filling text as you type.</p>
<p>The fact that <code>auto-fill-mode</code> features prominently in Emacs’ tutorial,
among the first things you’re expected to learn, suggests that Emacs takes
text filling very seriously, considering it a crucial text-editing feature.</p>
<p>Personally, the only people I know devoting any of their attention to text
widths on computer screens are professional typesetters… and some Emacs users.
If you’re reading this you might be one of them, so I ask you: isn’t it odd that
<code>auto-fill-mode</code> is not actually automatic? It <em>only wraps the line you’re on</em>,
leaving any earlier misalignment in the paragraph (caused by pasting text from
elsewhere, say) to be fixed manually.</p>
<p><code>refill-mode</code> is Emacs’ actual automatic text-filling feature.  It ensures that
your document stays wrapped at the <code>fill-column</code>:</p>
<video>

<a href="https://karthinks.com/img/refill-mode-demo-01.mp4&quot;">[VIDEO: Refill mode for Emacs demo]</a></video>
<p><code>M-x refill-mode</code> and you’re set.</p>
<h2>Scroll all windows (<code>M-x scroll-all-mode</code>)</h2>
<p>There are two commonly recommended scroll-related commands that new Emacs users
find surprising, in the sense that they make you wonder why other software
doesn’t have them.</p>
<p>The first is <code>scroll-other-window</code>, for scrolling the window that isn’t selected
without having to switch to it first.  This is very handy when the next window
contains material that’s a reference for our work in this one.  The second is
<code>follow-mode</code> (covered in an <a href="https://karthinks.com/software/batteries-included-with-emacs/">earlier installment</a>), giving you a contiguous view
of a single buffer across multiple windows.</p>
<p><code>scroll-all-mode</code> is almost as useful, but lesser known than these two.  This
mode scrolls all windows on the frame simultaneously: very handy when you’re
looking at buffers that need to be “synced” in some way.  A common use for me is
eyeballing two versions of a file without having to get locked into an Ediff
session:</p>
<video>

<a href="https://karthinks.com/img/scroll-all-mode-demo-01.mp4&quot;">[VIDEO: scroll-mode for Emacs demo]</a></video>

Play by play
<div class="details">
<ul>
<li>Open a specific previous backup of the current file with
<code>vc-revision-other-window</code> (actually <a href="https://karthinks.com/tags/emacs/#always-useful-vc-diff-commands">my spin on it, covered above</a>)</li>
<li>Turn on <code>scroll-all-mode</code></li>
<li>Scroll the window as usual.  All windows scroll simultaneously.</li>
</ul>
</div>

<p>It’s just <code>M-x scroll-all-mode</code>.</p>
<h2>Bonus: scrolling other windows and <code>master-mode</code></h2>
<p>While we’re on the topic of scrolling other windows, a common question is what
happens if you have more than two windows on screen, and the window you want to
scroll is <em>not</em> the “next-window” that Emacs picks
<span class="sidenote-number"><small>
This tip is recycled from <a href="https://karthinks.com/software/emacs-window-management-almanac/">The Emacs Window Management Almanac</a>, but I wouldn’t
blame you for missing it in a 15,000 word sea of blather.
</small></span>
.</p>
<p>One solution is the built-in <code>master-mode</code>, where you can pre-designate (or
live-designate) buffers that should be scrollable from other buffers.</p>
<p>But a more immediately useful method is to set the strategy used to find the
window to scroll.  One option is</p>
<div class="highlight"><pre><code class="language-emacs-lisp"><span><span>(<span>setq</span> <span>other-window-scroll-default</span> <span>#'</span><span>get-lru-window</span>)
</span></span></code></pre></div><p>which will always scroll the least-recently-used window.  This is useful if the
window you want to scroll contains reference material that you won’t be editing,
so the window will rarely be selected.</p>
<p>Alternatively, you might have two windows (of many), both of which see frequent
edits.  You’d then use the most-recently-used window as the other window to scroll:</p>
<div class="highlight"><pre><code class="language-emacs-lisp"><span><span>(<span>setq</span> <span>other-window-scroll-default</span>
</span></span><span><span>      (<span>lambda</span> ()
</span></span><span><span>        (<span>or</span> (<span>get-mru-window</span> <span>nil</span> <span>nil</span> <span>'not-this-one-dummy</span>)
</span></span><span><span>            (<span>next-window</span>)               <span>;fall back to next window</span>
</span></span><span><span>            (<span>next-window</span> <span>nil</span> <span>nil</span> <span>'visible</span>))))
</span></span></code></pre></div><p>Some combination of these should make <code>scroll-other-window</code> always
do-what-you-mean.</p>
<h2>Refuse to terminate (<code>M-x emacs-lock-mode</code>)</h2>
<p>If you try to quit Emacs with unsaved files, Emacs refuses until you answer the
question of what to do about each of them.  Annoying perhaps, but a useful
check.</p>
<p><code>emacs-lock-mode</code> extends this idea and hands <em>you</em> the controls.  Call it in any
buffer to “lock” it.</p>
<p>Until the lock is disengaged, the buffer will refuse to be killed, throwing up a
message instead:</p>
<pre><code class="language-nil">    Buffer "*scratch*" is locked and cannot be killed
</code></pre><p>and Emacs will refuse to exit:</p>
<pre><code class="language-nil">    Emacs cannot exit because buffer "*scratch*" is locked
</code></pre><p>This is handy for non-file-visiting buffers containing information you don’t
want to accidentally lose, or just as a reminder that a task in that buffer is
pending, and you shouldn’t throw away the context.</p>
<p>In a post Org-capture world, the former is rarely an issue, but locking is still
useful in shell and compilation buffers, websites or other special applications
that contain output or state you don’t want to lose.</p>
<h2>Undelete frames (<code>M-x undelete-frame-mode</code> and <code>M-x undelete-frame</code>)</h2>
<p>If you accidentally close an Emacs frame with a carefully curated workspace,
<code>M-x undelete-frame</code> has your back. Uh, if you’ve turned on
<code>undelete-frame-mode</code>, that is.</p>
<p>It does exactly what the more widely recommended (also built-in) <code>winner</code> and
<code>tab-bar-history</code> packages do, but for frames instead of windows.  Turn on
<code>undelete-frame-mode</code> with your Emacs and don’t worry about closing frames
again.  It can restore up to the last 16 deleted frames.</p>
<hr>
<h2>The leftovers</h2>
<p>That’s twenty Emacs features I collided with in the last six years that have
survived contact with the reality of using Emacs in 2026.  Several more Emacs
libraries discovered by fat-fingering the keyboard ended up being more
interesting as archaeological artifacts than as reliable solutions to common
user needs.  <code>allout-mode</code> is Org mode from a parallel universe, an outline
manager with features like Org’s speed-keys and even per-subtree encryption.
<code>shadowfile</code> is implementing <a href="https://github.com/bcpierce00/unison">unison</a> from inside Emacs, with questionable
utility.  <code>double-mode</code> is a key-translation-based input-method for typing
non-keyboard characters that predates <a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Input-Methods.html">quail</a>.  The <code>bs</code> library was someone’s
attempt at a smarter <code>list-buffers</code> command, but <code>ibuffer</code> blew everything else
out of the water so there’s no reason to use it.</p>
<p>Other ostensibly handy features, like wrapping regions with delimiters using
<code>electric-pair-mode</code>, didn’t make the cut because the ratio of finickiness to
utility is too high.  It’s better to just use an external package like
<code>wrap-region</code>, <code>smartparens</code> or <code>embrace</code> for this.</p>
<p>Then there’s the constellation of included Org and Org-adjacent libraries (like
<code>appt</code>) that add interesting but obscure features to Org mode.  But that’s an
expansive story, best covered in a dedicated article.</p>
<p>Finally, a lot of my serendipitous finds were libraries new and old that
are primarily of interest to Elisp developers.  The <code>thunk</code> library is an
example of this.  These too deserve their own write-up.</p>
<p>Still, I hope you found at least a couple of useful tips among the batteries
that passed testing.  The lisp directory that ships with Emacs isn’t <em>that</em> big,
but somehow this barrel never runs dry.  I don’t doubt that more batteries
remain to be found, even if it takes me a few more years of typos to stumble
onto them.  Until then, happy Emacsing!</p>
<section>
<hr>
<ol>
<li>
<p>A mini rant: This is your cue to tell me that <code>yyp</code>
is not a Vim command but a shining example of its <em>command composition
language</em>, where <code>yy</code> and <code>p</code> do different things.  And mine to tell you that no
Vim user, including you or me, thinks about an exceedingly common action like
<code>yyp</code> this way in practice.  Your fingers memorized the sequence years ago and
carry it out before you can muster the wherewithal to consider that you are
composing a yank and a paste.  It’s simply not a high-level cognitive action, so
this is a distinction without a difference.&nbsp;<a href="https://karthinks.com/tags/emacs/#fnref:1">↩︎</a></p>
</li>
</ol>
</section>
</body></html>]]></content>
        <author>
            <name>Karthik Chikmagalur</name>
            <uri>https://karthinks.com/tags/emacs/</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Bicycle for Your Mind: Separate Writing and Formatting]]></title>
        <id>https://bicycleforyourmind.com/separate-writing-from-formatting</id>
        <link href="https://bicycleforyourmind.com/separate-writing-from-formatting"/>
        <updated>2026-06-14T07:00:00.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p><img src="https://cdn.blot.im/blog_c4a729f3205a44e5a9669523ddfb8b2e/_image_cache/803bef64-d9f9-41ad-a6fb-634909bd1f86/pexels-pixabay-163116a.jpg" alt="writing" width="3000" height="2000"><span class="caption">writing</span></p>

<p>I have been thinking of <a href="https://ia.net/topics/separate-writing-and-formatting" target="_blank">Separate Writing and Formatting</a>. This is an interesting discourse on the need to separate the acts of writing from the act of preparing to present. I agree with the premise.</p>
<h2>The Notion of a Canvas</h2>
<p>Conceptually I look on the task of writing as starting with a blank canvas. The words then come in and fill the page. I don’t think of how it will look on the final document. Most of the time, I don’t care for the output. It is going to remain a text document in the Org format or Markdown format, depending on what I need.</p>
<h2>The Different Types of Writing</h2>
<p>I do two kinds of writing. The first kind is stream of consciousness writing. I have some idea of the topic and I type. I don’t know the topic completely, or don’t know how I feel about it. It is the act of writing that sheds light on my opinions or feelings. It is a dialog with myself. There is not much structure to it, but there is the belief that structure will come. After I have exhausted my exposition of the idea/topic on the page do I go through the task of editing and structuring. I like this process.</p>
<p>The second kind of writing I do is when I start with the structure. I think this is dependent on the topic I am writing on. If I know the topic well or have clearly formed ideas about the topic does this kind of writing work. I start with the structure. The structure leads me to the nature of the argument I am making. Once I have the structure laid out, I fill in the meat to the structure by writing it out. This process seems to lead to two diverse results. The structure changes. The argument flows differently. Most of the time, the arguments become more nuanced. Very few things in life are black or white. The calibration of the argument leads to nuances and an abundance of grays.</p>
<p>Most of the time, the writing happens in Emacs. Org-mode in Emacs. That has the advantage of being conducive to structure or the lack of it.</p>
<p>I notice that I like switching the applications around without any conscious thought. Sometimes, like this document I am working on, it starts as an OmniOutliner document. When I am done with it, this is going to get exported to a plain text file. It is going to be opened in Emacs for a look through or iA Writer for editing. Only after that will it be exported to the format I need to share (Markdown, PDF, Word, or HTML).</p>
<h2>Necessary Conditions</h2>
<ul>
<li>I want the document to be full-screen. I don’t want distractions.</li>
<li>I want typewriter scrolling. I hate looking at the bottom of the screen all the time when I write.</li>
<li>I want to be able to focus on sections/paragraphs when I write.</li>
</ul>
<p>OmniOutliner has the ability to let me focus on sections of the document. It lets me reduce the noise and concentrate on a section of the document and ignore everything else. I can concentrate on writing a particular section and not be affected by the others. iA Writer has the ability to focus on a paragraph or on a sentence, and I have been using that for a long time.</p>
<p>In Emacs, I can achieve the same effect by calling a function <code>recursive-narrow-or-widen-dwim</code>. It performs the same task of narrowing my focus to the section that I am writing. Call it again, and you are back to the whole document. This is from the package <a href="https://melpa.org/#/recursive-narrow" target="_blank">Recursive Narrow</a>.</p>
<h2>They are Separate</h2>
<p>The act of writing and the act of organizing the writing are separate activities. I find myself more productive when I am conscious of the separation and make sure that I am not allowing one to bleed into the other. Obviously during the editing phase, it becomes one. The act of structuring the argument leads to both changes to the structure and some changes to the nature of the content. This is my writing process.</p>
<h2>The iA Folks</h2>
<p>The iA folks make the argument that writing and formatting should be different steps. I have no disagreement with that view. I think the process of writing, structuring, editing, and formatting are all better off being different steps. Those are separate functions and my writing improves when I am conscious of that.</p>
<h2>Is Writing Hard?</h2>
<p>Thinking is hard. Writing is thinking. So writing is hard.</p>
<p>This is not prophetic. Everyone knows this. The question which is relevant here is how do you make it easier?</p>
<p>I don’t have the answer.</p>
<p>I made it easier for myself by sticking to a process. Whatever process you are comfortable with and have repeated success with is the cure to your problem with writing. It is not the same for everyone. Nor is the same process the most efficient for the same person all the time. That is the logic behind me relying on a mixture of applications to produce my writing. It works for me. Your mileage may vary.</p>
<h2>Presentation is Integral to Influence</h2>
<p>Presentation of any kind of writing is a crucial part of the process of influence. Structure and Formatting are elements of that effort. I must admit that I am not an expert in this field. In other words, I have no idea how to make a document look persuasive. I concentrate on the contents of the document, the structure of the argument and the cleanliness of both the content and the presentation. That is the extent of my effort at persuasion through presentation.</p>
<p>This is a nice way of saying that I don’t concentrate on the presentation as much as I should. I try to persuade with my content rather than the presentation of said content. I don’t know whether that is the best solution but that is what I find myself doing. Most of my writing is for myself. I am persuaded, that is why it came out the way it did. Persuading other people? I am not so sure.</p>
<h2>Takeaway</h2>
<p>I am sure that the process is important. Separate the functions of writing, editing, and formatting into discrete tasks, because they are. Vomit it all out on the page, then edit and format the content to ensure that you are presenting well thought-out, reasoned arguments. That is the key to persuasive writing.</p>
<p>macosxguru at the gmail thingie.</p>
<p><strong>Thanks to</strong>: Photo by Pixabay: <a href="https://www.pexels.com/photo/remington-standard-typewriter-in-greyscale-photography-163116/" target="_blank">https://www.pexels.com/photo/remington-standard-typewriter-in-greyscale-photography-163116/</a></p> </body></html>]]></content>
        <author>
            <name>Bicycle for Your Mind</name>
            <uri>https://bicycleforyourmind.com</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Dave Pearson: It got darker]]></title>
        <id>https://blog.davep.org/2026/06/13/it-got-darker.html</id>
        <link href="https://blog.davep.org/2026/06/13/it-got-darker.html"/>
        <updated>2026-06-13T09:49:48.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>By pure coincidence, it's <a href="https://blog.davep.org/2020/06/14/my-journey-to-the-dark-side-is-complete.html">six years ago
tomorrow</a> that I
finally, after years of running <a href="https://blog.davep.org/category/emacs/">Emacs</a> with a bright
white background, moved to using a dark theme. It took a little bit of
getting used to but eventually I got very comfortable with it, and since
then have run everything I can in a dark mode too.</p>
<p>On occasion, in the last year or so, I've had this urge to move to something
darker. Also, in part, it's an urge to change things up a little. I felt it
was time for a refresh of how my Emacs looks. I've tried a few themes, but
none have ever stuck. When trying them I've run into various issues:</p>
<ul>
<li>It just didn't look nice at all</li>
<li>Too many other things I use in Emacs didn't get themed</li>
<li>It looked like there was going to be too much work to do to really theme
  things well</li>
<li>It caused Emacs to crash<sup><a href="https://blog.davep.org/#fn:404-1">1</a></sup></li>
</ul>
<p>However, yesterday evening, after <a href="https://blog.davep.org/2026/06/12/simplifying-my-mode-line.html">making an effort to simplify my mode
line</a>, I was determined to find a
darker theme that I would be happy with. I think I finally managed!</p>
<p><img alt="An even darker Emacs" height="2052" loading="lazy" src="https://blog.davep.org/attachments/2026/06/13/darker-emacs.webp#centre" width="2588"></p>
<p>I've settled on <code>modus-vivendi</code> from <a href="https://protesilaos.com/emacs/modus-themes" target="_blank">modus
themes</a>. Out of the box it felt
right, and from what I can see in the documentation there's an amazing
amount of customisation you can do. The key point there too is the
documentation; there's so much of it, it's incredibly comprehensive.</p>
<p>For example: the default choice for the mode line is to have an unsubtle
border around it -- presumably to create a good contrast. I found that far
too distracting and was wondering what I could do about it. I didn't have to
wonder long, <a href="https://protesilaos.com/emacs/modus-themes#h:80ddba52-e188-411f-8cc0-480ebd75befe" target="_blank">the documentation addresses exactly that
situation</a>.</p>
<p>Another downside I ran into is that the colours that were showing in the
mode line, when I switched to <code>mood-line</code> yesterday, were gone. I spent a
short amount of time last night, and a good hour or so this morning, trying
to wrangle <code>mood-line</code> into something I liked, but I just couldn't get
anything sensible going. Eventually I cracked, fired up
<a href="https://blog.davep.org/tag/antigravity/">Antigravity</a>, prompted it with:</p>
<blockquote>
<p>I am using mood-line for my mode line -- see
<code>init.d/packages.d/melpa/mood-line.el</code> and
https://github.com/emacsmirror/mood-line</p>
<p>I am using https://protesilaos.com/emacs/modus-themes as my theme</p>
<p>I would like to have finer control over the parts of the mode line I've
configured. For example, I'd like the buffer name to stand out in an
informative colour, but one that is part of the modus theme's colour
scheme.</p>
<p>Don't make changes yet, but help me understand how I should do this in a
maintainable way.</p>
</blockquote>
<p>and then spent about 20 minutes going back and forth, refining what I
wanted; this <a href="https://github.com/davep/.emacs.d/blob/b9db88bae8f69f7e04f648642a88fe6f5ee02db2/init.d/packages.d/melpa/mood-line.el" target="_blank">got me a
result</a>
I'm happy with from a visual point of view. I still need to fully review the
code and the approach it took, but it isn't <em>too</em> far removed from what I'd
been trying myself.</p>
<p>Overall I'm pleased with the result, and this is the longest I've stuck with
a new theme (at this point I'm probably about 4 or 5 hours into working in
it). I think that says something significant. I can see myself still wanting
to tweak some aspects of it though. For example, the left-hand fringe
doesn't feel quite right, in a way I can't quite put my finger on. While I
want it to stand out from the main editing area, it feels... disconnected in
some way. Also the background colour of the mode line still feels like it
doesn't quite blend how I'd like.</p>
<p>Now to see if this lasts...</p>
<div class="footnote">
<hr>
<ol>
<li>
<p>Seriously, just the once, but that happened. I took that as a sign
from the Lisp gods that I was doing something sinful.&nbsp;<a href="https://blog.davep.org/#fnref:404-1">↩</a></p>
</li>
</ol>
</div></body></html>]]></content>
        <author>
            <name>Dave Pearson</name>
            <uri>https://blog.davep.org</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Protesilaos: Emacs: flat Dired listing for REGEXP, optionally up to DAYS since last modification]]></title>
        <id>https://protesilaos.com/codelog/2026-06-13-emacs-flat-dired-for-regexp-since-days/</id>
        <link href="https://protesilaos.com/codelog/2026-06-13-emacs-flat-dired-for-regexp-since-days/"/>
        <updated>2026-06-13T00:00:00.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>When we call <code class="language-plaintext highlighter-rouge">dired</code> from Lisp, we can pass it a list of files instead
of a directory. This gives us a fully fledged Dired buffer for those
files. My most common use-case is to produce flat listing, so that I
do not have to go searching in exactly which directory some file is
(e.g. in the Downloads folder there is some zip archive that I
downloaded with a bunch of files in a complex structure).</p>

<h2>A flat Dired listing</h2>

<p>For a while now I have been using my own command to create a Dired
buffer from the current directory (which can always be updated on
demand with <code class="language-plaintext highlighter-rouge">M-x cd</code>). It is <code class="language-plaintext highlighter-rouge">prot-dired-search-flat-list</code>. Here is
the code:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre><code><span class="p">(</span><span class="nb">defvar</span> <span class="nv">prot-dired-regexp-history</span> <span class="no">nil</span>
  <span class="s">"Minibuffer history of `prot-dired-regexp-prompt'."</span><span class="p">)</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">prot-dired-regexp-prompt</span> <span class="p">()</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">default</span> <span class="p">(</span><span class="nb">car</span> <span class="nv">prot-dired-regexp-history</span><span class="p">)))</span>
    <span class="p">(</span><span class="nv">read-regexp</span>
     <span class="p">(</span><span class="nv">format-prompt</span> <span class="s">"Files matching REGEXP"</span> <span class="nv">default</span><span class="p">)</span>
     <span class="nv">default</span> <span class="ss">'prot-dired-regexp-history</span><span class="p">)))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">prot-dired--get-files</span> <span class="p">(</span><span class="nv">regexp</span><span class="p">)</span>
  <span class="s">"Return files matching REGEXP, recursively from `default-directory'."</span>
  <span class="p">(</span><span class="nv">directory-files-recursively</span> <span class="nv">default-directory</span> <span class="nv">regexp</span> <span class="no">nil</span><span class="p">))</span>

<span class="c1">;;;###autoload</span>
<span class="p">(</span><span class="nb">defun</span> <span class="nv">prot-dired-search-flat-list</span> <span class="p">(</span><span class="nv">regexp</span><span class="p">)</span>
  <span class="s">"Return a Dired buffer for files matching REGEXP.
Perform the search recursively from the current directory."</span>
  <span class="p">(</span><span class="nv">interactive</span> <span class="p">(</span><span class="nb">list</span> <span class="p">(</span><span class="nv">prot-dired-regexp-prompt</span><span class="p">)))</span>
  <span class="p">(</span><span class="nv">if-let*</span> <span class="p">((</span><span class="nv">files</span> <span class="p">(</span><span class="nv">prot-dired--get-files</span> <span class="nv">regexp</span><span class="p">))</span>
            <span class="p">(</span><span class="nv">relative-paths</span> <span class="p">(</span><span class="nb">mapcar</span> <span class="nf">#'</span><span class="nv">file-relative-name</span> <span class="nv">files</span><span class="p">)))</span>
      <span class="p">(</span><span class="nv">dired</span> <span class="p">(</span><span class="nb">cons</span> <span class="p">(</span><span class="nb">format</span> <span class="s">"prot-flat-dired for `%s'"</span> <span class="nv">regexp</span><span class="p">)</span> <span class="nv">relative-paths</span><span class="p">))</span>
    <span class="p">(</span><span class="nb">error</span> <span class="s">"No files matching `%s'"</span> <span class="nv">regexp</span><span class="p">)))</span>
</code></pre></div></div>

<p>I could modify <code class="language-plaintext highlighter-rouge">prot-dired-search-flat-list</code> to also prompt for a
directory, though I optimise for the common workflow of operating from
where I am (and I generally do not like overloading the <code class="language-plaintext highlighter-rouge">C-u</code> with
special cases that I will never remember—a new command with a name I
can search for is better).</p>

<h2>Flat listing limited to last modified since DAYS</h2>

<p>Yesterday I had the need to browse a massive directory, but only
wanted to get a couple of files out of it. I realised that I had to
filter my last modified, so I extended my above use-case with the new
command <code class="language-plaintext highlighter-rouge">prot-dired-search-flat-list-since-days</code>. Here is what I came
up with:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre><code><span class="p">(</span><span class="nb">defvar</span> <span class="nv">prot-dired-days-prompt-history</span> <span class="no">nil</span>
  <span class="s">"Minibuffer history for `prot-dired-days-prompt'."</span><span class="p">)</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">prot-dired-days-prompt</span> <span class="p">()</span>
  <span class="s">"Prompt for days and return them as a number."</span>
  <span class="p">(</span><span class="k">let*</span> <span class="p">((</span><span class="nb">first</span> <span class="p">(</span><span class="nb">car</span> <span class="nv">prot-dired-days-prompt-history</span><span class="p">))</span>
         <span class="p">(</span><span class="nv">default</span> <span class="p">(</span><span class="nb">when</span> <span class="p">(</span><span class="nb">stringp</span> <span class="nb">first</span><span class="p">)</span>
                    <span class="p">(</span><span class="nv">string-to-number</span> <span class="nb">first</span><span class="p">))))</span>
    <span class="p">(</span><span class="nv">read-number</span> <span class="s">"Number of days: "</span> <span class="nv">default</span> <span class="ss">'prot-dired-days-prompt-history</span><span class="p">)))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">prot-dired--get-last-modified</span> <span class="p">(</span><span class="nv">files</span> <span class="nv">days</span><span class="p">)</span>
  <span class="s">"Return list of FILES last modified since DAYS."</span>
  <span class="p">(</span><span class="nv">seq-filter</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">and-let*</span> <span class="p">((</span><span class="nv">attributes</span> <span class="p">(</span><span class="nv">file-attributes</span> <span class="nv">file</span><span class="p">))</span>
                <span class="p">(</span><span class="nv">last-modified</span> <span class="p">(</span><span class="nb">nth</span> <span class="mi">5</span> <span class="nv">attributes</span><span class="p">))</span>
                <span class="p">(</span><span class="nv">last-modified-seconds</span> <span class="p">(</span><span class="nv">time-to-seconds</span> <span class="nv">last-modified</span><span class="p">))</span>
                <span class="p">(</span><span class="nv">current-time</span> <span class="p">(</span><span class="nv">current-time</span><span class="p">))</span>
                <span class="p">(</span><span class="nv">current-time-seconds</span> <span class="p">(</span><span class="nv">time-to-seconds</span> <span class="nv">current-time</span><span class="p">))</span>
                <span class="p">(</span><span class="nv">delta-seconds</span> <span class="p">(</span><span class="nb">*</span> <span class="nv">days</span> <span class="mi">24</span> <span class="mi">60</span> <span class="mi">60</span><span class="p">))</span>
                <span class="p">(</span><span class="nv">oldest-seconds</span> <span class="p">(</span><span class="nb">-</span> <span class="nv">current-time-seconds</span> <span class="nv">delta-seconds</span><span class="p">))</span>
                <span class="p">(</span><span class="nv">_</span> <span class="p">(</span><span class="nb">&gt;=</span> <span class="nv">last-modified-seconds</span> <span class="nv">oldest-seconds</span><span class="p">)))))</span>
   <span class="nv">files</span><span class="p">))</span>

<span class="c1">;;;###autoload</span>
<span class="p">(</span><span class="nb">defun</span> <span class="nv">prot-dired-search-flat-list-since-days</span> <span class="p">(</span><span class="nv">regexp</span> <span class="nv">days</span><span class="p">)</span>
  <span class="s">"Return Dired buffer with files matching REGEXP up to DAYS since last modification.
Perform the search recursively from the current directory."</span>
  <span class="p">(</span><span class="nv">interactive</span>
   <span class="p">(</span><span class="nb">list</span>
    <span class="p">(</span><span class="nv">prot-dired-regexp-prompt</span><span class="p">)</span>
    <span class="p">(</span><span class="nv">prot-dired-days-prompt</span><span class="p">)))</span>
  <span class="p">(</span><span class="nv">if-let*</span> <span class="p">((</span><span class="nv">files</span> <span class="p">(</span><span class="nv">prot-dired--get-files</span> <span class="nv">regexp</span><span class="p">)))</span>
      <span class="p">(</span><span class="nv">if-let*</span> <span class="p">((</span><span class="nv">files-filtered</span> <span class="p">(</span><span class="nv">prot-dired--get-last-modified</span> <span class="nv">files</span> <span class="nv">days</span><span class="p">))</span>
                <span class="p">(</span><span class="nv">relative-paths</span> <span class="p">(</span><span class="nb">mapcar</span> <span class="nf">#'</span><span class="nv">file-relative-name</span> <span class="nv">files-filtered</span><span class="p">)))</span>
          <span class="p">(</span><span class="nv">dired</span> <span class="p">(</span><span class="nb">cons</span> <span class="p">(</span><span class="nb">format</span> <span class="s">"prot-flat-dired since %d days for `%s'"</span> <span class="nv">days</span> <span class="nv">regexp</span><span class="p">)</span> <span class="nv">relative-paths</span><span class="p">))</span>
        <span class="p">(</span><span class="nb">error</span> <span class="s">"No files last modified within the last %d days"</span> <span class="nv">days</span><span class="p">))</span>
    <span class="p">(</span><span class="nb">error</span> <span class="s">"No files matching `%s'"</span> <span class="nv">regexp</span><span class="p">)))</span>
</code></pre></div></div>

<p>Note that I always design my minibuffer prompts to have their own
history, because then I only get relevant entries when I press <code class="language-plaintext highlighter-rouge">M-p</code>
(<code class="language-plaintext highlighter-rouge">previous-history-element</code>) and <code class="language-plaintext highlighter-rouge">M-n</code> (<code class="language-plaintext highlighter-rouge">next-history-element</code>) at the
prompt (and the built-in <code class="language-plaintext highlighter-rouge">savehist-mode</code> takes care to persist those).</p>

<p>Everything is part of my Emacs configuration: <a href="https://protesilaos.com/emacs/dotemacs">https://protesilaos.com/emacs/dotemacs</a>.
I will not be updating this article, so make sure to check for any
further refinements there.</p>
        </body></html>]]></content>
        <author>
            <name>Protesilaos</name>
            <uri>https://protesilaos.com/codelog</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Dave Pearson: Simplifying my mode line]]></title>
        <id>https://blog.davep.org/2026/06/12/simplifying-my-mode-line.html</id>
        <link href="https://blog.davep.org/2026/06/12/simplifying-my-mode-line.html"/>
        <updated>2026-06-12T18:06:26.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>Every so often I get the urge to change how Emacs looks. Ever since I
finally <a href="https://blog.davep.org/2020/06/14/my-journey-to-the-dark-side-is-complete.html">fell to the dark
side</a>, my Emacs
has stayed looking pretty much the same. I like how it looks, but I do keep
having this urge to find a darker theme, and to also make things just a wee
bit more minimal.</p>
<p>At one point I was very much about, and in favour of, having as much
information as possible in <a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Mode-Line.html" target="_blank">the mode
line</a>.
Eventually I realised I didn't use that much and tried to declutter
somewhat, mostly cleaning up minor mode information with
<a href="https://www.gnu.org/software/emacs/manual/html_node/use-package/Diminish.html" target="_blank">diminish</a>.
Even then though, I had this feeling that there was still more information
in the mode line than I really needed.</p>
<p>So, just now, as an experiment, I've decided to start fairly clean. I've
dropped <a href="https://github.com/milkypostman/powerline" target="_blank">powerline</a> and instead
decided to have a play with
<a href="https://github.com/emacsmirror/mood-line" target="_blank">mood-line</a>. Rather than use one
of its pre-configured formats, I've had a go at rolling my own:</p>
<div class="highlight"><pre><span></span><code><span class="p">(</span><span class="k">setq</span><span class="w"> </span><span class="nv">mood-line-format</span>
<span class="w">      </span><span class="p">(</span><span class="nv">mood-line-defformat</span>
<span class="w">       </span><span class="nb">:left</span>
<span class="w">       </span><span class="p">(((</span><span class="nv">mood-line-segment-buffer-status</span><span class="p">)</span><span class="w"> </span><span class="o">.</span><span class="w"> </span><span class="s">" "</span><span class="p">)</span>
<span class="w">        </span><span class="p">((</span><span class="nv">mood-line-segment-buffer-name</span><span class="p">)</span><span class="w"> </span><span class="o">.</span><span class="w"> </span><span class="s">" : "</span><span class="p">)</span>
<span class="w">        </span><span class="p">(</span><span class="nv">mood-line-segment-major-mode</span><span class="p">))</span>
<span class="w">       </span><span class="nb">:right</span>
<span class="w">       </span><span class="p">(((</span><span class="nv">mood-line-segment-vc</span><span class="p">)</span><span class="w"> </span><span class="o">.</span><span class="w"> </span><span class="s">"  "</span><span class="p">)</span>
<span class="w">        </span><span class="p">(</span><span class="nv">mood-line-segment-cursor-position</span><span class="p">))))</span>
</code></pre></div>

<p>So far I'm really pleased with the result.</p>
<p><img alt="My GNU Emacs" height="1716" loading="lazy" src="https://blog.davep.org/attachments/2026/06/12/mood-line-emacs.webp#centre" width="1818"></p>
<p>For any given buffer the mode line display is now:</p>
<ul>
<li>The status of the buffer</li>
<li>The name of the buffer</li>
<li>The major mode of the buffer</li>
<li>The git status for what I'm working on</li>
<li>The cursor position</li>
</ul>
<p>Honestly, I'm struggling to think of anything else I really need to see.
Sure, I can imagine there's the odd minor mode I might need to know about,
but generally I either have them enabled all the time anyway, or it's
something so obvious that I know when it's not enabled.</p>
<p>I'm going to run with this for a while now and see how I feel. I can sense
that I might want to tweak a couple of things (at the moment the left-hand
side will move when I change the unsaved status of the buffer; on the right
there's nothing that tells me that this file I'm editing right now is new to
the repo and not part of it yet), but this basic configuration feels clean
and right.</p>
<p>Meanwhile... the search for <a href="https://emacsthemes.com/" target="_blank">a theme</a> that is
darker and I actually prefer over <a href="https://github.com/purcell/color-theme-sanityinc-tomorrow" target="_blank">the sanityinc-tomorrow
themes</a>
continues. I fear this is going to be a lot harder.</p></body></html>]]></content>
        <author>
            <name>Dave Pearson</name>
            <uri>https://blog.davep.org</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Irreal: AsciiDoc In Emacs]]></title>
        <id>https://irreal.org/blog/?p=13871</id>
        <link href="https://irreal.org/blog/?p=13871"/>
        <updated>2026-06-12T14:22:51.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>
Bozhidar Batsov has a post <a href="https://batsov.com/articles/2026/06/11/emacs-loves-asciidoc/#fn:2">announcing a couple of new Emacs modes for AsciiDoc</a>. In the usual Batsov way, he’s significantly improved the support for <a href="https://asciidoc.org/">AsciiDoc</a> in Emacs. He loves AsciiDoc but found it hard to use in Emacs because the support was so bad.
</p>
<p>
I’ve never used AsciiDoc so I don’t know why Batsov prefers it to Org mode. Org mode can be and has been used to produce first class technical documentation. If needed, it can bring to bear all the power of LaTeX to produce a polished product.
</p>
<p>
As far as I can see, the only reason not to use Org mode is because you’re not an Emacs user or are collaborating on a document with someone who isn’t. It offers everything you’re apt to need short of bringing in a heavyweight dedicated document preparation system. I’m sure Irreal readers not as ignorant as I about the situation can tell us why we should prefer AsciiDoc. Our lines are open.
</p>
<p>
If you <i>are</i> an AsciiDoc user, Batsov’s two new modes are sure to be a blessing. The update to <a href="https://github.com/bbatsov/adoc-mode/releases/tag/v0.7.0">adoc-mode</a> is designed to work with all versions of Emacs and updates the regex-based font-locking to the current AsciiDoc grammar. It’s perfect for an AsciiDoc user who’s running an older version of Emacs. <a href="https://github.com/bbatsov/asciidoc-mode">Asciidoc-mode</a> is the more modern solution using tree-sitter to handle things like font-locking but it only runs on Emacs 30.1+.
</p>
<p>
Take a look at Batsov’s post for the details on the two modes. And if you know why an Org mode user should care, leave a comment.</p>
</body></html>]]></content>
        <author>
            <name>Irreal</name>
            <uri>https://irreal.org/blog</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Dave Pearson: blogmore.el v5.2.0]]></title>
        <id>https://blog.davep.org/2026/06/12/blogmore-el-v5-2-0.html</id>
        <link href="https://blog.davep.org/2026/06/12/blogmore-el-v5-2-0.html"/>
        <updated>2026-06-12T07:31:15.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>Another quick update to
<a href="https://github.com/davep/blogmore.el" target="_blank"><code>blogmore.el</code></a>, again to fix an issue
I've run into with the new frontmatter-handling code. This time it's to
address an actual crash that could happen if a property was available but
empty. For example, if a post had frontmatter that looked like this:</p>
<div class="highlight"><pre><span></span><code><span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="s">"blogmore.el</span><span class="nv"> </span><span class="s">v5.2.0"</span>
<span class="nt">date</span><span class="p">:</span><span class="w"> </span><span class="s">"2026-06-12</span><span class="nv"> </span><span class="s">08:31:15+0100"</span>
<span class="nt">category</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Emacs</span>
<span class="nt">tags</span><span class="p">:</span>
</code></pre></div>

<p>And I then went to use <code>blogmore-add-tag</code>, I'd get a crash saying:</p>
<div class="highlight"><pre><span></span><code>Wrong type argument: sequencep, :null
</code></pre></div>

<p>The reason being that <code>tags</code> was being parsed with a value of <code>:null</code>,
rather than (as before) having a value of <code>nil</code> (which of course meant I had
a nice empty list to do things with). It was an easy enough fix.</p>
<p>At this point I think I've managed to shake out any serious issues with the
proper YAML-parsing approach to frontmatter, as I've used it to write a
handful of posts now.</p></body></html>]]></content>
        <author>
            <name>Dave Pearson</name>
            <uri>https://blog.davep.org</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Dave Pearson: blogmore.el v5.1.0]]></title>
        <id>https://blog.davep.org/2026/06/11/blogmore-el-v5-1-0.html</id>
        <link href="https://blog.davep.org/2026/06/11/blogmore-el-v5-1-0.html"/>
        <updated>2026-06-11T18:06:24.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>A quick little update to
<a href="https://github.com/davep/blogmore.el" target="_blank"><code>blogmore.el</code></a> to fix a couple of
issues introduced by the new YAML-parsing approach to reading frontmatter;
both pretty much stemming from how falsy values are handled.</p>
<p>Simply put, both boolean <code>false</code> values, and also empty values (something
that could commonly happen with <code>tags</code> and <code>series</code>) would end up showing up
in the frontmatter as <code>null</code>. This release handles that situation.</p>
<p>Also, under the hood, I cleaned up some repeated boilerplate related to how
the cached dump calls to <a href="https://blogmore.davep.dev/" target="_blank">BlogMore</a> took place.
The code for categories, tags and series data was almost exactly the same,
save for the actual name of the thing being dumped. So I turned it all into
a macro:</p>
<div class="highlight"><pre><span></span><code><span class="p">(</span><span class="nb">defmacro</span><span class="w"> </span><span class="nv">blogmore--cache-dump</span><span class="w"> </span><span class="p">(</span><span class="nv">dump-name</span><span class="p">)</span>
<span class="w">  </span><span class="s">"Generate a function to get DUMP-NAME from BlogMore, with caching."</span>
<span class="w">  </span><span class="p">(</span><span class="k">let</span><span class="w"> </span><span class="p">((</span><span class="nv">cache-name</span><span class="w"> </span><span class="p">(</span><span class="nf">intern</span><span class="w"> </span><span class="p">(</span><span class="nf">format</span><span class="w"> </span><span class="s">"blogmore--current-%s-cache"</span><span class="w"> </span><span class="nv">dump-name</span><span class="p">)))</span>
<span class="w">        </span><span class="p">(</span><span class="nv">getter-name</span><span class="w"> </span><span class="p">(</span><span class="nf">intern</span><span class="w"> </span><span class="p">(</span><span class="nf">format</span><span class="w"> </span><span class="s">"blogmore--current-%s"</span><span class="w"> </span><span class="nv">dump-name</span><span class="p">))))</span>
<span class="w">    </span><span class="o">`</span><span class="p">(</span><span class="k">progn</span>
<span class="w">       </span><span class="p">(</span><span class="k">defvar</span><span class="w"> </span><span class="o">,</span><span class="nv">cache-name</span><span class="w"> </span><span class="no">nil</span>
<span class="w">         </span><span class="o">,</span><span class="p">(</span><span class="nf">format</span><span class="w"> </span><span class="s">"Cache for the list of %s from existing posts."</span><span class="w"> </span><span class="nv">dump-name</span><span class="p">))</span>
<span class="w">       </span><span class="p">(</span><span class="nb">defun</span><span class="w"> </span><span class="o">,</span><span class="nv">getter-name</span><span class="w"> </span><span class="p">()</span>
<span class="w">         </span><span class="o">,</span><span class="p">(</span><span class="nf">format</span><span class="w"> </span><span class="s">"Get a list of %s from existing posts."</span><span class="w"> </span><span class="nv">dump-name</span><span class="p">)</span>
<span class="w">         </span><span class="p">(</span><span class="k">or</span><span class="w"> </span><span class="o">,</span><span class="nv">cache-name</span><span class="w"> </span><span class="p">(</span><span class="k">setq</span><span class="w"> </span><span class="o">,</span><span class="nv">cache-name</span><span class="w"> </span><span class="p">(</span><span class="nv">blogmore--list-of</span><span class="w"> </span><span class="o">,</span><span class="p">(</span><span class="nf">symbol-name</span><span class="w"> </span><span class="nv">dump-name</span><span class="p">))))))))</span>
</code></pre></div>

<p>and now the <code>defvar</code> that creates the variable that holds the cache, and the
<code>defun</code> that creates the getter function for the data, are reduced to this
for all three collections of values:</p>
<div class="highlight"><pre><span></span><code><span class="p">(</span><span class="nv">blogmore--cache-dump</span><span class="w"> </span><span class="nv">categories</span><span class="p">)</span>
<span class="p">(</span><span class="nv">blogmore--cache-dump</span><span class="w"> </span><span class="nv">tags</span><span class="p">)</span>
<span class="p">(</span><span class="nv">blogmore--cache-dump</span><span class="w"> </span><span class="nv">series</span><span class="p">)</span>
</code></pre></div>

<p>Sure, I probably could have done all of this in a single global, a central
getter function, and a <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Hash-Tables.html" target="_blank">hash
table</a>,
but the macro approach feels so much more elegant, and more... lispy.</p></body></html>]]></content>
        <author>
            <name>Dave Pearson</name>
            <uri>https://blog.davep.org</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Lars Ingebrigtsen: Web scraping is getting harder all the time]]></title>
        <id>https://lars.ingebrigtsen.no/2026/06/11/web-scraping-is-getting-harder-all-the-time/</id>
        <link href="https://lars.ingebrigtsen.no/2026/06/11/web-scraping-is-getting-harder-all-the-time/"/>
        <updated>2026-06-11T16:06:01.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p><a href="https://lars.ingebrigtsen.no/wp-content/uploads/2026/06/2026-06-11-1.jpeg"><img src="https://lars.ingebrigtsen.no/wp-content/uploads/2026/06/2026-06-11-1-scaled.jpeg" alt="" width="840" height="478" srcset="https://lars.ingebrigtsen.no/wp-content/uploads/2026/06/2026-06-11-1-scaled.jpeg 2560w, https://lars.ingebrigtsen.no/wp-content/uploads/2026/06/2026-06-11-1-300x171.jpeg 300w, https://lars.ingebrigtsen.no/wp-content/uploads/2026/06/2026-06-11-1-1024x583.jpeg 1024w, https://lars.ingebrigtsen.no/wp-content/uploads/2026/06/2026-06-11-1-768x437.jpeg 768w, https://lars.ingebrigtsen.no/wp-content/uploads/2026/06/2026-06-11-1-1536x875.jpeg 1536w, https://lars.ingebrigtsen.no/wp-content/uploads/2026/06/2026-06-11-1-2048x1166.jpeg 2048w"></a></p>
<p>And it’s understandable — <a href="https://www.jwz.org/blog/2026/06/today-in-the-scraperpocalypse/">things are getting worse and worse</a> all the time, and anybody who is running a web site (that has interesting information) is under constant attack from badly programmed AI scrapers.</p>
<p>But where does that leave us li’l smol peeps who are just scrapin’ a li’l data for ourselves so that we don’t have to type as much?</p>
<p>I’ve got two small use cases that have been torpedoed by this arms race lately — I use the imdb search to find the data on movies I’ve ripped from blu rays that I’ve bought.  And I use the Goodreads search when I’m entering (manually) e-books that I’ve bought into <a href="https://lars.ingebrigtsen.no/2025/04/15/a-book-tracking-package-for-emacs/">the Emacs package for that</a>.  (Physical books have ISBNs printed in bar code form, so I can use various APIs for that and don’t need to resort to anything as tawdry as web scraping.)</p>
<p>These are just minor convenience things I’ve gotten used to over the years, so I could give them up…  or I could go raging, raging against the dying of the open web.</p>
<p>Guess what I chose!</p>
<p><video poster="https://lars.ingebrigtsen.no/wp-content/uploads/2026/06/posterGnw21A001.jpg"></video></p>
<p>The result is on <a href="https://github.com/larsmagne/fetch-dom.el">Microsoft Github</a>.</p>
<p>The idea is:</p>
<ol>
<li>First try to fetch the URL using the normal, fast method.
</li><li>If this fails, use Selenium headless.  This involves spinning up a web browser and then dumping the resulting DOM.
</li><li>If this fails, spin up Selenium and a web browser window.  This will allow the user to click around a bit, answering any challenges.
</li></ol>
<p>In 2) and 3), fetch-dom will save and reuse cookies, so that<br>
hopefully 3) doesn’t happen as much, and 1) and 2) will be successful<br>
more often.</p>
<p>So this requires a Python/Selenium installation that works, and<br>
Chromium installed.</p>
<p>fetch-dom is synchronous by default, but is asynchronous if you give it the :callback keyword parameter.</p>
<p>This seems to work for my use cases — things usually work automatically, but once in a while it pops up a browser window, and I click a bit, and then things work headlessly for a while again.</p>
<p>*sigh*</p>
<p>These are the days of your life…</p>
</body></html>]]></content>
        <author>
            <name>Lars Ingebrigtsen</name>
            <uri>https://lars.ingebrigtsen.no</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Raymond Zeitler: Creating a Reference to a Webpage in Org]]></title>
        <id>https://ray-on-emacs.blogspot.com/2026/06/creating-reference-to-webpage-in-org.html</id>
        <link href="https://ray-on-emacs.blogspot.com/2026/06/creating-reference-to-webpage-in-org.html"/>
        <updated>2026-06-11T15:42:30.885Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>I was asked recently, "Do you use Org Mode protocol ... for browser
to Emacs interaction? If so, were there any complications to set it up
on Windows? Is there like bookmarklets for capturing or doing
  things?"<sup>1</sup></p>
<p>At the time I wasn't doing anything too fancy to incorporate Web
Content into Org.  I'd copy the URL from Vivaldi's address bar to the
clipboard and (if applicable) the Web Content I'm interested
  in.<sup>2</sup>  Then
in Org, I'd yank the Web Content (if applicable), mark it and then do
org-insert-link (C-c C-l) to turn it into a hyperlink.  The marked
text becomes what you see in the document.  But I usually just specify
the link Description simply as "LINK." In fact I created a macro
(bound to the Insert key) to do this.</p>
<p>But I've started to use eww as my web browser for this.  If I write
something that I need to verify, I'll mark it and invoke
eww-search-words (M-s M-w), which brings me to a DuckDuckGo page of
search results.  If I follow a search result that I like, I'll mark a
small section and invoke org-store-link (C-c l) and create the link
with org-insert-link, with the marked content as the Description.
Thus org-store-link captures both the location and the context in one
magical swoop.  Here's an animated GIF that illustrates the process.
Note that the video shows me capturing and referring to part of Sacha
Chua's website that shows some neat solutions to launching a web
browser from Emacs.<sup>3</sup></p>

<div class="separator"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvTadQW88KQZgsnlJsseOEC7dM_VioA4lvnNZ4b9AO6EYncYzKqRDqc-OM_79trnnq9gUYAu9_JGQOshax6MeZ_JDLJHKo00qBKIYjEV4uMV2q1fyFrKXT77yDQpP1uGJ0iVrPSKzX03sYzgOhL8QZWvrycBgpf3N-12hRwnK7qhtN4mu7SFpVFsncBDg/s1124/new_eww_to_org.gif"><img alt="" width="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvTadQW88KQZgsnlJsseOEC7dM_VioA4lvnNZ4b9AO6EYncYzKqRDqc-OM_79trnnq9gUYAu9_JGQOshax6MeZ_JDLJHKo00qBKIYjEV4uMV2q1fyFrKXT77yDQpP1uGJ0iVrPSKzX03sYzgOhL8QZWvrycBgpf3N-12hRwnK7qhtN4mu7SFpVFsncBDg/s400/new_eww_to_org.gif"></a></div>

<hr>
<sup>1</sup>
<span><a href="https://sachachua.com/blog/2026/05/emacs-chat-with-raymond-zeitler/#ID-ec23-transcript">Sacha
Chua's Emacs Chat with Raymond Zeitler transcript</a>.  Please scroll to
35:50</span><br>

<p><sup>2</sup> I use a clipboard manager so that I can copy content
to the clipboard multiple times without clobbering all but the most
recent item.</p>

<sup>3</sup>
<a href="https://sachachua.com/blog/2025/07/emacs-open-urls-or-search-the-web-plus-browse-url-handlers/">https://sachachua.com/blog/2025/07/emacs-open-urls-or-search-the-web-plus-browse-url-handlers/</a>

</body></html>]]></content>
        <author>
            <name>Raymond Zeitler</name>
            <uri>https://ray-on-emacs.blogspot.com/search/label/Emacs</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Irreal: An Emacs Based Writerdeck]]></title>
        <id>https://irreal.org/blog/?p=13868</id>
        <link href="https://irreal.org/blog/?p=13868"/>
        <updated>2026-06-11T14:48:00.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>
If you follow writers at all, you’ll have noticed that many prefer to write their prose in long hand even if they began their writing career with a computer. Tess Gerretsen and Neal Stephenson are two examples that come to mind. Both are serious, established writers who have no need for performative resistance to computers. Indeed, they both use computers to produce the final manuscript. They say they write in longhand to slow things down or to avoid premature editing.
</p>
<p>
I understand their urge but could never work that way. Writing by hand is excruciatingly slow and even painful to me. I didn’t start writing a lot until I got a computer and could do it without so much effort and discomfort. A middle ground is what’s often called a “writerdeck”. The idea is that it’s a device that’s completely dedicated to writing and is as simple as possible.
</p>
<p>
Chris Maiorana wrote an article that <a href="https://chrismaiorana.com/writerdecks-distraction-free-writing-environments/">argued a pad and pen is the ultimate writedeck</a>. I reject that for the reasons I stated above. Maiorana recognizes that often a computer is a good idea and has <a href="https://chrismaiorana.com/tmux-wm-emacs-no-gui/">an article that describes building his own writerdeck.</a> He wanted something free or cheap so he used a Raspberry Pi 4 that he had lying around, put Linux and Emacs on it, and restricted it to text mode. Later he added a few utilities such as Git but it remains a text only machine dedicated to writing with Emacs. Maiorana considers it the “maximum digital minimalism” but I’m more inclined to think of it as a minimal acceptable writing environment.
</p>
<p>
I don’t do social media other than Irreal, if you consider that social media, so I have no difficulty concentrating on my writing while using my everyday laptop. Not everybody is like that, of course, so if you find it’s hard to resist doom scrolling while you’re supposed to be writing, you may want to take a look at Maiorana’s post on his writerdeck.</p>
</body></html>]]></content>
        <author>
            <name>Irreal</name>
            <uri>https://irreal.org/blog</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Raymond Zeitler: Emacs -- It's Worth Revealing Oneself For]]></title>
        <id>https://ray-on-emacs.blogspot.com/2026/05/emacs-its-worth-revealing-oneself-for.html</id>
        <link href="https://ray-on-emacs.blogspot.com/2026/05/emacs-its-worth-revealing-oneself-for.html"/>
        <updated>2026-06-11T14:41:42.159Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>"...how can people keep up with what you're learning?"<sup>1</sup>
</p>
<p>I've always kept a low profile on the Internet.&nbsp; It can be a
  scary place!&nbsp; But I've been asked to show glimpses of my online
  work to the people I was meeting in real life.
</p>
<p>I agreed to chat with <a target="_blank" href="https://sachachua.com/">Sacha Chua</a> about Emacs and Life
  (but not the Universe -- that'll be next time).&nbsp; Emacs is worth
  revealing oneself for.&nbsp; If people really do want to keep up
  with what I'm learning, they can visit here.
</p>
<p>My init file<sup>2</sup> shows only a small aspect of how I have Emacs
  configured.&nbsp; You'll want to see an example of my org file(s),
  my diary file, and the Lisp I have tucked away under my home
  directory.
</p>
<p>Aside from Emacs, my workflow relies on Vivaldi and LibreOffice, so
  I'll try to show what I'm doing with them, as well.&nbsp; Perhaps I
  can provide screen recordings, too!
</p>
<p>"Sometimes it just takes somebody saying, your stuff is
  interesting. I'm telling you, your stuff is interesting."<sup>3</sup>
</p>
<p>Thank you, again, Sacha!
</p>
<hr>
<sup>1</sup>Sacha Chua, <a target="_blank" href="https://sachachua.com/blog/2026/05/emacs-chat-with-raymond-zeitler/#ID-ec23-transcript">https://sachachua.com/blog/2026/05/emacs-chat-with-raymond-zeitler/#ID-ec23-transcript</a><br>
<sup>2</sup><a target="_blank" href="https://www.emacswiki.org/emacs/RaymondZeitler">https://www.emacswiki.org/emacs/RaymondZeitler</a><br>
<sup>3</sup>Sacha Chua, ibid.<br><br>
2026-06-11 Fix link in footnote 1.
</body></html>]]></content>
        <author>
            <name>Raymond Zeitler</name>
            <uri>https://ray-on-emacs.blogspot.com/search/label/Emacs</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Charlie Holland: Emacs SVG Benchmark Reveals Gaming-Caliber Frame Rates]]></title>
        <id>https://www.chiply.dev/post-emacs-svg-benchmark</id>
        <link href="https://www.chiply.dev/post-emacs-svg-benchmark"/>
        <updated>2026-06-11T12:10:09.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><div class="outline-2">
<h2><span class="section-number-2">1.</span> TLDR</h2>
<div class="outline-text-2">
<video src="https://www.chiply.dev/videos/svg-perf-text.mp4">
</video>

<p>
Rendering an Emacs status bar as an SVG image, like with my <a href="https://www.chiply.dev/post-svg-line"><code>svg-line</code></a> package (<a href="https://youtu.be/AZiVhhIfYk8">demo</a>), really <i>is</i> several times heavier than the native text engine.  The skeptics were right.  But it <b>doesn't matter</b> in practice: even a fully-repainted 3000-pixel ultrawide bar holds ~77 fps, and a thin inline animation rasterizing a fresh frame every tick runs at 130–520 fps.  To put that into perspective, this is still well above the high frame rates that even applications like video games target.  More than enough for a text editor if you ask me!
</p>

<p>
I got two real take-aways from this benchmark.  First, the rendering cost of SVG scales with the SVG's <b>pixel area</b>, not with what's drawn on it (text and icons cost the same as you'll see).  Second, in any real Emacs config the bottleneck is the <b>content query</b> (I'm looking at you, git), not the renderer (I'm looking at you, SVG, with doe eyes).
</p>
</div>
</div>
<div class="outline-2">
<h2><span class="section-number-2">2.</span> Clarifications Before we Dive In</h2>
<div class="outline-text-2">
<p>
I'm not saying that SVG should be the basis of a game engine in Emacs.  I <i>am</i> saying that Emacs has more than enough headroom over the frame rates that games target.  24fps is considered the minimum for a perceivable animation (30fps for a smooth one, 60fps for a good one), and competetive gamers target fps in the 200s.  As you will see from the data, Emacs meets these thresholds and then some.
</p>

<p>
I'm also not saying that Emacs's SVG frame rates hold linear time complexity <code>O(1)</code> across all pixel scales.  In fact, the benchmark demonstrates the opposite (SVG rendering fps decreases as pixel scale increases).  I <i>am</i> saying that Emacs SVG rendering is more than performant enough for its common use cases, like rendering responsive status bars.
</p>
</div>
</div>
<div class="outline-2">
<h2><span class="section-number-2">3.</span> Why Benchmark This?</h2>
<div class="outline-text-2">
<p>
The skepticism is reasonable.  Emacs is optimized for a <i>small number</i> of cached images, while a status bar that changes on every redisplay can generate a new image many, many times per second.  Intuitively, that should be slow.
</p>

<p>
But other Emacs SVG projects show smooth 60 fps animation, as <a href="https://www.reddit.com/r/emacs/comments/1u069gm/comment/oqho5z6/?utm_source=share&amp;utm_medium=web3x&amp;utm_name=web3xcss&amp;utm_term=1&amp;utm_content=share_button">one redditor pointed out</a>, and anecdotally <code>svg-line</code> felt fast on my end.
</p>

<p>
I felt compelled to measure it, so I did, with a self-contained harness (to borrow the redditor's term) that runs in bare <code>emacs -Q</code>.
</p>
</div>
</div>
<div class="outline-2">
<h2><span class="section-number-2">4.</span> Results: SVG vs Native Text Engine</h2>
<div class="outline-text-2">
<p>
You can run the <a href="https://github.com/chiply/.zetta.d/blob/main/svg-bench/svg-bench.el">benchmark</a> yourself, in a bare <code>emacs -Q</code> or your own Emacsen.  My setup is Emacs 31.0.50 (native-compiled), librsvg (linked into my build), on a 2025 M5 Mac running Tahoe 26.1.
</p>

<p>
Three renderers draw the same thing at three widths (a narrow split, a normal window, and an ultrawide monitor): an SVG bar of text, an SVG bar of Nerd-Font icon glyphs, and (as the baseline) the native text engine drawing the same characters.
</p>
</div>
<div class="outline-3">
<h3><span class="section-number-3">4.1.</span> SVG Rendering Text</h3>
<div class="outline-text-3">
<table>


<colgroup>
<col>

<col>

<col>

<col>

<col>

<col>
</colgroup>
<thead>
<tr>
<th>SVG / text</th>
<th>mean ms</th>
<th>min ms</th>
<th>max ms</th>
<th>mean fps</th>
<th>min fps</th>
</tr>
</thead>
<tbody>
<tr>
<td>narrow  800px, 65c</td>
<td>3.44</td>
<td>3.09</td>
<td>3.96</td>
<td>290</td>
<td>253</td>
</tr>

<tr>
<td>medium 1800px,149c</td>
<td>7.49</td>
<td>6.98</td>
<td>7.91</td>
<td>134</td>
<td>126</td>
</tr>

<tr>
<td>large  3000px,249c</td>
<td>12.91</td>
<td>12.39</td>
<td>13.37</td>
<td>77</td>
<td>75</td>
</tr>
</tbody>
</table>

<video src="https://www.chiply.dev/videos/svg-perf-text.mp4">
</video>
</div>
</div>
<div class="outline-3">
<h3><span class="section-number-3">4.2.</span> SVG Rendering Icons</h3>
<div class="outline-text-3">
<table>


<colgroup>
<col>

<col>

<col>

<col>

<col>

<col>
</colgroup>
<thead>
<tr>
<th>SVG / icons</th>
<th>mean ms</th>
<th>min ms</th>
<th>max ms</th>
<th>mean fps</th>
<th>min fps</th>
</tr>
</thead>
<tbody>
<tr>
<td>narrow  800px, 65c</td>
<td>3.60</td>
<td>3.37</td>
<td>3.80</td>
<td>278</td>
<td>263</td>
</tr>

<tr>
<td>medium 1800px,149c</td>
<td>7.85</td>
<td>7.47</td>
<td>8.53</td>
<td>127</td>
<td>117</td>
</tr>

<tr>
<td>large  3000px,249c</td>
<td>13.31</td>
<td>12.67</td>
<td>14.10</td>
<td>75</td>
<td>71</td>
</tr>
</tbody>
</table>

<video src="https://www.chiply.dev/videos/svg-perf-icons.mp4">
</video>
</div>
</div>
<div class="outline-3">
<h3><span class="section-number-3">4.3.</span> Built-in Rendering Text</h3>
<div class="outline-text-3">
<table>


<colgroup>
<col>

<col>

<col>

<col>

<col>

<col>
</colgroup>
<thead>
<tr>
<th>BUILT-IN / text</th>
<th>mean ms</th>
<th>min ms</th>
<th>max ms</th>
<th>mean fps</th>
<th>min fps</th>
</tr>
</thead>
<tbody>
<tr>
<td>narrow  800px, 65c</td>
<td>0.16</td>
<td>0.13</td>
<td>0.23</td>
<td>6377</td>
<td>4378</td>
</tr>

<tr>
<td>medium 1800px,149c</td>
<td>0.21</td>
<td>0.19</td>
<td>0.37</td>
<td>4789</td>
<td>2686</td>
</tr>

<tr>
<td>large  3000px,249c</td>
<td>0.26</td>
<td>0.24</td>
<td>0.33</td>
<td>3842</td>
<td>3046</td>
</tr>
</tbody>
</table>

<video src="https://www.chiply.dev/videos/builtin-perf-text.mp4">
</video>
</div>
</div>
<div class="outline-3">
<h3><span class="section-number-3">4.4.</span> Analysis</h3>
<div class="outline-text-3">
<p>
<b>SVGs perform at all widths.</b>  Even the <b>large</b> 3000-pixel bar (an ultrawide-monitor width), repainted every frame, stays above 60 fps: ~77 fps for text and ~75 fps for icons, and the worst trial across the run is still 71 fps.
</p>

<p>
<b>Text and icons cost essentially the same</b> (290 vs 278, 134 vs 127, 77 vs 75).  The cost is dominated by rasterizing the SVG as a whole, so what is painted on it doesn't seem to matter.  The relevant correlate is the SVG's <b>pixel area</b>.
</p>

<p>
<b>The native engine is ~20–50× faster.</b>  The skeptics are right that SVG is heavier because a monolithic image is re-rasterized in full whenever any pixel changes, while the text engine updates incrementally from cached glyphs, and the gap widens with width for that reason.  But!!!  <i>This doesn't matter in practice.</i>  Even in the worst case, SVG never drops below the gaming gold standard, which is more than enough for a text editor.
</p>
</div>
</div>
</div>
<div class="outline-2">
<h2><span class="section-number-2">5.</span> A Live Inline Animation</h2>
<div class="outline-text-2">
<p>
Why talk frame rates without an animation?  Here, three purple icons (Emacs, Org, Image) glide back and forth along a thin white bar, measured across three widths.
</p>

<table>


<colgroup>
<col>

<col>

<col>

<col>

<col>

<col>
</colgroup>
<thead>
<tr>
<th>line animation</th>
<th>mean ms</th>
<th>min ms</th>
<th>max ms</th>
<th>mean fps</th>
<th>min fps</th>
</tr>
</thead>
<tbody>
<tr>
<td>small  300x56px</td>
<td>1.94</td>
<td>1.77</td>
<td>2.26</td>
<td>517</td>
<td>443</td>
</tr>

<tr>
<td>medium 700x56px</td>
<td>4.03</td>
<td>3.75</td>
<td>4.55</td>
<td>248</td>
<td>220</td>
</tr>

<tr>
<td>large 1400x56px</td>
<td>7.45</td>
<td>7.04</td>
<td>7.77</td>
<td>134</td>
<td>129</td>
</tr>
</tbody>
</table>

<p>
An inline animation rasterizing a fresh SVG every frame runs at <b>130–520 fps</b>, and the worst trial is still ~129 fps.
</p>

<video src="https://www.chiply.dev/videos/svg-perf-animation.mp4">
</video>

<p>
<i>NOTE: My screen recording can't convey the real frame rate because my screen-capture tool is capped at 60 fps.</i>
</p>

<p>
Run the demo yourself (below) to see the true smoothness.
</p>
</div>
</div>
<div class="outline-2">
<h2><span class="section-number-2">6.</span> How I Measured It</h2>
<div class="outline-text-2">
<p>
The harness renders a status-bar-shaped image (or, for the baseline, native text) into a buffer, re-renders it every frame, forces a redisplay, and times the wall-clock per frame in milliseconds (which the tables also report as fps).
</p>

<div class="org-src-container">
<pre><span>(</span><span>defun</span> <span>svg-bench--time</span> <span>(</span>render-fn reps<span>)</span>
  <span>"Render REPS frames, forcing redisplay, and return ms per frame."</span>
  <span>(</span><span>let</span> <span>(</span><span>(</span>gc-cons-threshold most-positive-fixnum<span>)</span><span>)</span>
    <span>(</span>clear-image-cache<span>)</span>
    <span>(</span>funcall render-fn 0<span>)</span> <span>(</span>redisplay t<span>)</span>             <span>; </span><span>warm-up, untimed
</span>    <span>(</span><span>let</span> <span>(</span><span>(</span>t0 <span>(</span>float-time<span>)</span><span>)</span><span>)</span>
      <span>(</span><span>dotimes</span> <span>(</span>i reps<span>)</span> <span>(</span>funcall render-fn <span>(</span>1+ i<span>)</span><span>)</span> <span>(</span>redisplay t<span>)</span><span>)</span>
      <span>(</span>/ <span>(</span>* 1e3 <span>(</span>- <span>(</span>float-time<span>)</span> t0<span>)</span><span>)</span> reps<span>)</span><span>)</span><span>)</span><span>)</span>
</pre>
</div>

<p>
Some details on what makes this demo reflect practical use of SVG in Emacs:
</p>

<ul>
<li><b>I ran it in a real GUI frame.</b>  If you ran this with <code>--batch</code> or <code>emacs -nw</code> there's no display and rasterization is skipped.</li>
<li><b>I set <code>gc-cons-threshold</code></b> during timing and I <b>discard a warm-up frame</b> (because the first render loads librsvg).</li>
<li><b>I force a miss in Emacs's image cache.</b>  Emacs caches each rasterized image by its full data string, so if a frame's string repeats, the cache serves the bitmap and the benchmark measures a cache hit rather than a real render.  Rotating through a small pool of content (say ten icons, or a short alphabet) repeats every few frames.  So each frame in my benchmark carries a 2px per-frame colour <b>marker</b> (a tiny non-text rectangle) that makes the whole-image data string unique and guarantees a genuine re-rasterization.</li>
</ul>
</div>
</div>
<div class="outline-2">
<h2><span class="section-number-2">7.</span> In Practice, the Bottleneck Is Not the SVG</h2>
<div class="outline-text-2">
<p>
The benchmarks above use synthetic content precisely so they measure the <b>rendering</b>, not the performance of any indicator you might put in a status bar.
</p>

<p>
In a real configuration, a single synchronous <code>git</code> query in the version-control segment runs ~7.6 ms, which is on the order of painting the entire SVG bar, and far more than rendering the one segment it occupies.  A native mode line showing the same version-control state would pay this cost too.
</p>

<p>
When an Emacs status bar feels slow, an I/O-bound content function is almost certainly the reason.
</p>
</div>
</div>
<div class="outline-2">
<h2><span class="section-number-2">8.</span> Conclusion</h2>
<div class="outline-text-2">
<p>
SVG status bars <b>are</b> several times more expensive than the native text engine — and <b>also</b> far faster than 60 fps, even at ultrawide widths.  The native engine keeps an order of magnitude in reserve, but SVG has plenty for the job, and in practice the slow part of a status bar is the content it <i>queries</i>, not the engine that <i>paints</i> it.
</p>
</div>
</div>
<div class="outline-2">
<h2><span class="section-number-2">9.</span> Run it on Your End</h2>
<div class="outline-text-2">
<p>
The harness is one self-contained file, <code>svg-bench.el</code>, in my <a href="https://github.com/chiply/.zetta.d/tree/main/svg-bench/svg-bench.el">Emacs configuration repository</a> (built-in <code>svg</code> and <code>cl-lib</code> only).  In a graphical Emacs:
</p>

<div class="org-src-container">
<pre>emacs -Q svg-bench/svg-bench.el
</pre>
</div>

<p>
Then <code>M-x eval-buffer</code>, and run any of the demos — <code>svg-perf-text</code>, <code>svg-perf-icons</code>, <code>builtin-perf-text</code>, <code>svg-perf-animation</code>.  The full report comes from <code>svg-perf-benchmark</code> (the three status-bar tables) and <code>svg-perf-animation-benchmark</code> (the animation table).
</p>
</div>
</div></body></html>]]></content>
        <author>
            <name>Charlie Holland</name>
            <uri>https://www.chiply.dev</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Bozhidar Batsov: Emacs loves AsciiDoc]]></title>
        <id>https://batsov.com/articles/2026/06/11/emacs-loves-asciidoc/</id>
        <link href="https://batsov.com/articles/2026/06/11/emacs-loves-asciidoc/"/>
        <updated>2026-06-11T06:00:00.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>Regular readers know I have a soft spot for
<a href="https://asciidoc.org/">AsciiDoc</a> – I’ve written about it more than once, and
it’s the markup behind the documentation of most of my bigger OSS projects
(CIDER, nREPL, Projectile, RuboCop). It hits a sweet spot Markdown never quite
reaches: rich enough for proper technical writing (admonitions, includes, real
tables, cross-references), without dragging in the full ceremony of something
like DocBook.</p>

<p>There was just one problem, and it nagged at me for years: editing AsciiDoc in
Emacs was never much fun.</p>

<h2>Background</h2>

<p>For years the only real option was <code class="language-plaintext highlighter-rouge">adoc-mode</code>, and it was showing its age. The
font-locking was uneven, it predated modern Asciidoctor syntax, and it lagged
far behind what <code class="language-plaintext highlighter-rouge">markdown-mode</code> (and <code class="language-plaintext highlighter-rouge">org-mode</code>) offered. So I’d catch myself
reaching for Markdown in situations where AsciiDoc was clearly the better
tool – not because Markdown was better, but because <code class="language-plaintext highlighter-rouge">markdown-mode</code> was. That
always bugged me.</p>

<p>Eventually the itch got bad enough that I did something about it. Back in 2023 I
<a href="https://metaredux.com/posts/2023/03/12/adoc-mode-reborn.html">took over maintenance of adoc-mode</a>,
which had been dormant for years, and set myself a clear goal: get it to feature
parity with <code class="language-plaintext highlighter-rouge">markdown-mode</code>. More recently I also started a brand-new
<a href="https://github.com/bbatsov/asciidoc-mode">asciidoc-mode</a> built on top of
tree-sitter. The target for both is the same – AsciiDoc support in Emacs that’s
on par with Markdown, and ideally not far off from Org.</p>

<h2>Less is more, unless it’s modes</h2>

<p>Why two modes? They scratch slightly different itches:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">adoc-mode</code> is the classic, regexp-based mode. It works on any reasonably
modern Emacs, has no external dependencies, and now ships a pile of
interactive features (markup commands, list editing, image preview, tempo
templates).</li>
  <li><code class="language-plaintext highlighter-rouge">asciidoc-mode</code> is the newer, tree-sitter-based mode. It leans on a real
grammar for robust, accurate highlighting and good performance in large
documents. It’s leaner by design, and it needs Emacs 30.1+ with tree-sitter.<sup><a href="https://batsov.com/#fn:1">1</a></sup></li>
</ul>

<p>If you want the kitchen sink on any Emacs, reach for <code class="language-plaintext highlighter-rouge">adoc-mode</code>. If you’re on a
recent Emacs and want highlighting backed by an actual parser, try
<code class="language-plaintext highlighter-rouge">asciidoc-mode</code>. Pick whichever fits your setup – both are actively maintained.</p>

<h2>Recent developments</h2>

<p>I’ve spent a good chunk of the past month bringing both modes to a place I’m
genuinely happy with, and they’re now mostly feature-complete as far as I’m
concerned. Some highlights:</p>

<ul>
  <li><strong>Modern AsciiDoc, not legacy AsciiDoc.py.</strong> Both modes now track the modern
Asciidoctor spec – something I’d
<a href="https://batsov.com/articles/2024/02/22/asciidoc-language-specification/">wanted to do for a while</a>.
<code class="language-plaintext highlighter-rouge">+text+</code> and <code class="language-plaintext highlighter-rouge">++text++</code> are treated as passthroughs rather
than monospace, curved-quote syntax (<code class="language-plaintext highlighter-rouge">"`text`"</code>) is recognized, the block
ID shorthand <code class="language-plaintext highlighter-rouge">[#id]</code> is supported, checklists are highlighted, and the menus
and templates dropped a bunch of deprecated AsciiDoc.py leftovers.</li>
  <li><strong>More uniform font-locking.</strong> I went through the faces in both modes and
aligned them with <code class="language-plaintext highlighter-rouge">markdown-mode</code> and <code class="language-plaintext highlighter-rouge">org-mode</code>: bold renders as plain bold,
emphasis as plain italic, structural markup (delimiters, list markers) fades
into the background, and dedicated semantic faces cover metadata, URLs,
footnotes, highlights, and roles. Switching between Markdown and AsciiDoc no
longer feels jarring.</li>
  <li><strong>Navigation that actually works.</strong> Clickable cross-references and links, an
<code class="language-plaintext highlighter-rouge">xref</code> backend over anchors, context-aware completion, and – for <code class="language-plaintext highlighter-rouge">adoc-mode</code>
– cross-file Antora cross-reference resolution.</li>
  <li><strong>Tooling integration.</strong> Asciidoctor-backed preview/export and a Flymake
checker that reports parser errors inline.</li>
  <li><strong>Native code-block fontification.</strong> <code class="language-plaintext highlighter-rouge">[source,LANG]</code> blocks in <code class="language-plaintext highlighter-rouge">asciidoc-mode</code>
are highlighted using the language’s own major mode, just like in
<code class="language-plaintext highlighter-rouge">markdown-mode</code> and <code class="language-plaintext highlighter-rouge">org-mode</code>. <code class="language-plaintext highlighter-rouge">adoc-mode</code> had added support for this a while
back.</li>
</ul>

<p>Getting <code class="language-plaintext highlighter-rouge">asciidoc-mode</code> where I wanted it also meant sending a few fixes
upstream to the
<a href="https://github.com/cathaysia/tree-sitter-asciidoc">tree-sitter-asciidoc</a>
grammar it builds on. A grammar-backed mode is only as good as its grammar, so
some of the work happened a layer below Emacs. If you’re curious about that side
of things, I wrote up the broader experience in
<a href="https://batsov.com/articles/2026/02/27/building-emacs-major-modes-with-treesitter-lessons-learned/">building Emacs major modes with Tree-sitter</a>.</p>

<h2>Give it a try</h2>

<p>If you’ve been avoiding AsciiDoc in Emacs because the tooling wasn’t there – I
get it, that was me too. But the situation is genuinely different now. Grab
<a href="https://github.com/bbatsov/adoc-mode">adoc-mode</a> or
<a href="https://github.com/bbatsov/asciidoc-mode">asciidoc-mode</a>, point it at one of
your <code class="language-plaintext highlighter-rouge">.adoc</code> files, and see how it feels.</p>

<p>And please share your feedback. Both projects are at the stage where real-world
usage surfaces the rough edges I can’t see myself. Bug reports, ideas, and PRs
are all very welcome on the respective issue trackers.</p>

<p>Together we can make AsciiDoc a first-class citizen of the Emacs ecosystem!<sup><a href="https://batsov.com/#fn:2">2</a></sup></p>

<p>That’s all from me, folks! Keep hacking!</p>

<div class="footnotes">
  <ol>
    <li>
      <p>Also, I really wanted to name something <code class="language-plaintext highlighter-rouge">asciidoc-mode</code>.&nbsp;<a href="https://batsov.com/#fnref:1">↩︎</a></p>
    </li>
    <li>
      <p>Afterwards we’ll aim for world domination, of course.&nbsp;<a href="https://batsov.com/#fnref:2">↩︎</a></p>
    </li>
  </ol>
</div></body></html>]]></content>
        <author>
            <name>Bozhidar Batsov</name>
            <uri>https://batsov.com/</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Alvaro Ramirez: agent-shell 0.55 updates]]></title>
        <id>https://xenodium.com/agent-shell-0-55-updates</id>
        <link href="https://xenodium.com/agent-shell-0-55-updates"/>
        <updated>2026-06-11T00:00:00.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>It's been a little while since my <a href="https://xenodium.com/agent-shell-0-47-1-updates">last agent-shell update</a>, so let's go through the latest highlights as of v0.55.</p>
<h2>What's <code>agent-shell</code>?</h2>
<p><a href="https://github.com/xenodium/agent-shell">agent-shell</a> is a native <a href="https://www.gnu.org/software/emacs/">Emacs</a> mode to interact with AI agents powered by ACP (<a href="https://agentclientprotocol.com/">Agent Client Protocol</a>).</p>
<h2>Picking up where I left off</h2>
<p>If you noticed slower project activity in April, <a href="https://xenodium.com/and-then-there-were-three">this is why</a>. I'm getting better at the <a href="https://xenodium.com/and-then-there-were-three">new 24-hour job</a>, so <a href="https://github.com/xenodium/agent-shell/commits/main/">I've resumed working on agent-shell</a>.</p>
<p>I'm still chipping away at the backlog that built up while I was away, but if there's anything in particular you'd like me to look at, feel free to ping.</p>
<h2>Anthropic, Google, and why ACP matters</h2>
<p>With Anthropic's <a href="https://zed.dev/blog/anthropic-subscription-changes">SDK subscription support changing</a>, Google's <a href="https://developers.googleblog.com/an-important-update-transitioning-gemini-cli-to-antigravity-cli/">Gemini CLI deprecation</a>, and <a href="https://github.com/google-antigravity/antigravity-cli/issues/31">Antigravity's unclear support for the Agent Client Protocol (ACP)</a>, vendor-neutral tools matter more than ever.</p>
<p>Luckily, <code>agent-shell</code> is built on <a href="https://agentclientprotocol.com/">ACP</a>, which sidesteps the problem. When a vendor changes course, you can swap providers and keep using your preferred tool. No need to reshape that hard-earned muscle memory.</p>
<p>On that note, the list of agents supported by <code>agent-shell</code> continues to grow.</p>
<h3>Supported agents</h3>
<p>Here's a list of the latest agents now supported by <code>agent-shell</code>.</p>
<p><img src="https://xenodium.github.io/images/agent-shell-0-55-updates/agents.png" alt=""></p>
<ul>
<li><a href="https://docs.augmentcode.com/cli/overview">Auggie</a></li>
<li><a href="https://code.claude.com/docs/en/overview">Claude</a></li>
<li><a href="https://cline.bot/cli">Cline</a></li>
<li><a href="https://www.codebuddy.ai/">CodeBuddy</a> (<a href="https://github.com/xenodium/agent-shell/pull/483">new</a> by <a href="https://github.com/illidan127">@illidan127</a>)</li>
<li><a href="https://github.com/openai/codex">Codex</a></li>
<li><a href="https://github.com/blowmage/cursor-agent-acp-npm">Cursor</a></li>
<li><a href="https://factory.ai">Factory Droid</a></li>
<li><a href="https://github.com/google-gemini/gemini-cli">Gemini CLI</a></li>
<li><a href="https://github.com/github/copilot-cli">GitHub Copilot CLI</a></li>
<li><a href="https://block.github.io/goose/">Goose</a></li>
<li><a href="https://hermes-agent.nousresearch.com/">Hermes</a> (<a href="https://github.com/xenodium/agent-shell/pull/583">new</a> by <a href="https://github.com/yitang">@yitang</a>)</li>
<li><a href="https://www.kimi.com/code">Kimi Code</a> (<a href="https://github.com/xenodium/agent-shell/pull/528">new</a> by <a href="https://github.com/nicolaisingh">@nicolaisingh</a>)</li>
<li><a href="https://kiro.dev/">Kiro</a></li>
<li><a href="https://github.com/mistralai/mistral-vibe">Mistral Vibe</a></li>
<li><a href="https://opencode.ai/">OpenCode</a></li>
<li><a href="https://github.com/badlogic/pi-mono/tree/main/packages/coding-agent">Pi</a></li>
<li><a href="https://github.com/QwenLM/qwen-code">Qwen Code</a></li>
</ul>
<h2>agent-shell needs your support</h2>
<p>Speaking of vendor-neutral tools being more important than ever, there are a couple of ways to help keep <code>agent-shell</code> going. Some cost money, others just a click. All are appreciated ;)</p>
<h3>Sponsorships for agent-shell longevity</h3>
<p><code>agent-shell</code> has been attracting quite a few users. It's nice to hear folks are using <code>agent-shell</code> on a daily basis. They are often relieved <code>agent-shell</code> exists as an alternative to AI-tools commonly mandated at work. Those tools have well-funded engineering teams behind them, while <code>agent-shell</code> is just me, an indie dev ;) Time spent on <code>agent-shell</code> is time away from work that pays the bills, so if it's useful to you, please consider <a href="https://github.com/sponsors/xenodium">sponsoring</a> the project.</p>
<p>Every individual sponsorship genuinely helps keep the project going. And if your employer benefits from your <code>agent-shell</code> use, they're typically in a position to contribute at a scale individuals can't, so nudge them to chip in too.</p>
<p>Hey, I'm looking at you, folks at <strong>Google</strong>, <strong>GitHub</strong>, <strong>GitLab</strong>, <strong>NVIDIA</strong>, <strong>Oracle</strong>, <strong>Red Hat</strong>, Yelp, Venmo, <strong>ARM</strong>, <strong>Spotify</strong>, <strong>Augment Code</strong>, Hinge, Mercury, Nubank, Veeva… Some of you are using <code>agent-shell</code>. Nudge your employer ;)</p>
<h3>GitHub stars for Anthropic credit</h3>
<p><a href="https://claude.com/contact-sales/claude-for-oss">Anthropic offers 6 months of free Claude Max 20x</a> for qualifying open-source projects with at least 5,000+ GitHub stars. <a href="https://github.com/xenodium/agent-shell/">Starring agent-shell</a> costs nothing and can save me some money. We're only a 5th of the way there ;) so if you don't mind a couple of clicks, the project can really use <a href="https://github.com/xenodium/agent-shell/">another GitHub star</a>.</p>
<p>Speaking of GitHub stars, <code>agent-shell</code> is now my most popular Emacs package, recently overtaking <a href="https://github.com/xenodium/chatgpt-shell/">chatgpt-shell</a>.</p>
<p><a href="https://www.star-history.com/#xenodium/agent-shell&amp;xenodium/chatgpt-shell&amp;Date"> <img src="https://api.star-history.com/svg?repos=xenodium/agent-shell,xenodium/chatgpt-shell&amp;type=Date" alt="Star History Chart" width="100%"> </a></p>
<h2>New markdown renderer</h2>
<p>agent-shell now ships with a brand new, more performant inline markdown renderer. This is the <a href="https://github.com/xenodium/agent-shell/pull/597">biggest internal change</a> in some time. Enabled by default via <code>agent-shell-markdown-render-function</code> (moving away from the overlay-based renderer in shell-maker).</p>
<h3>Access/navigate table content</h3>
<p>Table content is now accessible. Point can land on any cell, which wasn't possible with the previous overlay implementation. In addition, tables are now also navigable: <code>TAB</code> and <code>S-TAB</code> move between cells.</p>
<p><img src="https://xenodium.github.io/images/agent-shell-0-55-updates/table.gif" alt=""></p>
<h3>Improved source block support (enabled by default)</h3>
<p>Source-block syntax highlighting is now on by default. The per-snippet copy button is now keyboard-accessible too (previously mouse-click only, due to the overlay implementation).</p>
<p><img src="https://xenodium.github.io/images/agent-shell-0-55-updates/blocks.png" alt=""></p>
<h3>New blockquotes support</h3>
<p>Blockquotes now render in both shell and viewport. More importantly, you can select text in either a viewport page (or the shell itself), press <code>r</code> (for reply) and the selection becomes a blockquote in a fresh prompt.</p>
<p>Viewport</p>
<p><img src="https://xenodium.github.io/images/agent-shell-0-55-updates/viewport-quote.gif" alt=""></p>
<p>Shell</p>
<p><img src="https://xenodium.github.io/images/agent-shell-0-55-updates/shell-quote.gif" alt=""></p>
<h2>Session restoration</h2>
<p>Session restoration got a meaningful overhaul (<a href="https://github.com/xenodium/agent-shell/pull/605">#605</a> by <a href="https://github.com/nhojb">@nhojb</a>), now exposed via <code>agent-shell-session-restore-verbosity</code>, with four levels:</p>
<ul>
<li><code>minimal</code> (default): title only, so restore is fast and quiet (needs <code>session/resume</code> support).</li>
<li><code>last</code>: render the last prompt turn (needs <code>session/load</code> support).</li>
<li><code>first-last</code>: render the first and last prompt turns (needs <code>session/load</code> support).</li>
<li><code>full</code>: replay the whole conversation (needs <code>session/load</code> support).</li>
</ul>
<p>Feature availability is agent-specific, requiring either <code>session/resume</code> or <code>session/load</code> request support. <code>agent-shell</code> degrades as needed, ultimately falling back to creating a new session.</p>
<p>Note that anything but <code>minimal</code> verbosity is fairly new, so please <a href="https://github.com/xenodium/agent-shell/issues">report bugs or rough edges</a>.</p>
<p>Relatedly, <code>agent-shell-session-strategy</code> now defaults to <code>'prompt</code>, and <code>'new-deferred</code> has been retired.</p>
<h2>Session forking</h2>
<p>You can now fork the current session, starting a new shell that shares the conversation history so far and diverges from there. Invoke via <code>M-x agent-shell-fork</code>.</p>
<h2>Restart/reload session</h2>
<p>You can now restart the current shell anew (drop history) via <code>M-x agent-shell-restart</code> or reload (keep history) via <code>agent-shell-reload</code>.</p>
<h2>Downloads/Temp shells</h2>
<p>The new <code>agent-shell-new-downloads-shell</code> and <code>agent-shell-new-temp-shell</code> commands create agents anchored at either <code>~/Downloads</code> or a temp directory. Both are also reachable via <code>C-u M-x agent-shell</code>.</p>
<p><img src="https://xenodium.github.io/images/agent-shell-0-55-updates/starting.png" alt=""></p>
<h2>TRAMP support</h2>
<p><a href="https://github.com/xenodium/acp.el/pull/20">acp.el #20</a> by <a href="https://github.com/martenlienen">@martenlienen</a> landed support for ACP connections over TRAMP, now making it possible to drive remote agents from <code>agent-shell</code>. Pair it with <a href="https://github.com/junyi-hou/agent-shell-tramp">agent-shell-tramp</a> for the user-facing integration.</p>
<h2>Viewport improvements</h2>
<p>Viewport interaction <code>(setq agent-shell-prefer-viewport-interaction t)</code> continues to be my primary way to interact with agents. It is focused (see only the latest interaction), fast (single-key bindings: <code>y</code> = yes, <code>c</code> = continue, <code>m</code> = more…), and offers a richer editing experience (dedicated prompt-crafting buffer).</p>
<p>The viewport is just a viewport to shell content. You can have your cake and eat it too, by jumping to the related shell buffer if needed.</p>
<h3>Queueing</h3>
<p>From a viewport, you can press <code>r</code> to reply to the latest agent response. In the past, you could only reply to idle agents. You can now press <code>r</code> to reply to busy agents too, automatically queuing requests on submission.</p>
<h3>List editing mode</h3>
<p>A new (basic) <code>agent-shell-list-edit-mode</code> lets you edit list-style content inside the viewport.</p>
<p><img src="https://xenodium.github.io/images/agent-shell-0-55-updates/lists.gif" alt=""></p>
<h2>Improved buffer selection</h2>
<p>Some commands prompt you to pick one of your active shell buffers (e.g. <code>M-x agent-shell-send-region-to</code>). The picker now shows extra context for each buffer to help you choose.</p>
<p><img src="https://xenodium.github.io/images/agent-shell-0-55-updates/select.png" alt=""></p>
<p>The same mechanism is now used by the new <code>M-x agent-shell-switch-buffer</code> command. More on the underlying API later.</p>
<h2>Improved folding</h2>
<p>Folding got smarter (<a href="https://github.com/xenodium/agent-shell/pull/608">#608</a> by <a href="https://github.com/codeluggage">@codeluggage</a>):</p>
<ul>
<li><code>M-x agent-shell-ui-toggle-fragment</code> toggles the fragment at or near point (DWIM).</li>
<li><code>M-x agent-shell-ui-toggle-all-fragments</code> cycles globally between all-expanded and all-collapsed.</li>
</ul>
<p>Together they replace the previous <code>agent-shell-ui-toggle-fragment-at-point</code>, which is now an internal primitive.</p>
<h2><code>c</code> joins the viewport reply gang</h2>
<p>You can now press <code>c</code> from a viewport to quickly send a "continue" request, joining the rest of the single-key reply shortcuts:</p>
<ul>
<li><code>c</code>: replies "continue" (new)</li>
<li><code>y</code>: replies "yes"</li>
<li><code>m</code>: replies "more"</li>
<li><code>a</code>: replies "again"</li>
<li><code>1</code> … <code>9</code>: replies with the corresponding numbered choice</li>
<li><code>r</code>: opens the reply compose buffer</li>
<li><code>R</code>: same as <code>r</code>, with the agent response quoted</li>
</ul>
<p><img src="https://xenodium.github.io/images/agent-shell-0-55-updates/single-bindings.png" alt=""></p>
<h2>More compact status rendering</h2>
<p>Tool call status is now rendered as a compact icon-based label by default (<code>agent-shell--inverse-icon-status-kind-label</code>). <code>agent-shell-styles.el</code> ships several alternatives, picked via <code>agent-shell-status-kind-label-function</code>.</p>
<p><img src="https://xenodium.github.io/images/agent-shell-0-55-updates/compact.png" alt=""></p>
<p>To get the previous word-based label back:</p>
<pre><code class="language-{.commonlisp">(setq agent-shell-status-kind-label-function
      #'agent-shell--inverse-label-status-kind-label)
</code></pre>
<h2>Codex defaults</h2>
<p>You can now set a default model and session mode for Codex via <code>agent-shell-openai-default-model-id</code> and <code>agent-shell-openai-default-session-mode-id</code> (<a href="https://github.com/xenodium/agent-shell/pull/405">#405</a> by <a href="https://github.com/robjgray">@robjgray</a>). Both must match an ID from Codex's "Available models" / "Available modes" listings.</p>
<p><img src="https://xenodium.github.io/images/agent-shell-0-55-updates/header.png" alt=""></p>
<h2>Emacs 31 fixes</h2>
<p>Headers had a few rendering hiccups on Emacs 31. These are now fixed (<a href="https://github.com/xenodium/agent-shell/pull/588">#588</a> and <a href="https://github.com/xenodium/agent-shell/pull/590">#590</a> by <a href="https://github.com/nhojb">@nhojb</a>, <a href="https://github.com/xenodium/agent-shell/pull/463">#463</a> by <a href="https://github.com/ftlio">@ftlio</a>). Warnings from deprecated <code>when-let</code> usage were also cleared.</p>
<h2>Wayland clipboard support</h2>
<p><code>wl-paste</code> is now a supported clipboard handler for pasting images on Wayland (<a href="https://github.com/xenodium/agent-shell/pull/461">#461</a> by <a href="https://github.com/martenlienen">@martenlienen</a>).</p>
<h2>Windows clipboard support</h2>
<p>Similarly, pasting clipboard images now works on Windows via PowerShell (<a href="https://github.com/xenodium/agent-shell/pull/572">#572</a> by <a href="https://github.com/repelliuss">@repelliuss</a>).</p>
<h2>Header improvements</h2>
<p>The graphical header got minor tweaks here and there. For example, thought level is now displayed in the header. It can be changed via <code>M-x agent-shell-viewport-set-session-thought-level</code> as well as menus (<a href="https://github.com/xenodium/agent-shell/pull/601">#601</a> by <a href="https://github.com/martenlienen">@martenlienen</a>).</p>
<p><img src="https://xenodium.github.io/images/agent-shell-0-55-updates/model.png" alt=""></p>
<p><img src="https://xenodium.github.io/images/agent-shell-0-55-updates/mode.png" alt=""></p>
<p><img src="https://xenodium.github.io/images/agent-shell-0-55-updates/thought.png" alt=""></p>
<h2>Session config options</h2>
<p>agent-shell now supports ACP session config options (<a href="https://github.com/xenodium/agent-shell/pull/553">#553</a> by <a href="https://github.com/greggroth">@greggroth</a> and <a href="https://github.com/xenodium/agent-shell/pull/613">#613</a> by <a href="https://github.com/catern">@catern</a>). Bind <code>C-c C-s</code> (or call <code>agent-shell-set-session-config-option</code>) to pick from the options the agent advertises. Broadcasted as <code>config-option-update</code> and available externally via <code>agent-shell-subscribe-to</code>.</p>
<h2>Interrupt confirmation</h2>
<p>You can now skip interrupt confirmations by unsetting <code>agent-shell-confirm-interrupt</code> (<a href="https://github.com/xenodium/agent-shell/pull/424">#424</a> by <a href="https://github.com/emil-e">@emil-e</a>).</p>
<h2>Public functions</h2>
<h3>Resume sessions by ID</h3>
<p>You can now resume an existing session by its ID via <code>M-x agent-shell-resume-session</code> (<a href="https://github.com/xenodium/agent-shell/pull/332">#332</a>). Primarily useful for external integrations.</p>
<h3>Outgoing request decorator</h3>
<p>You can now use <code>agent-shell-outgoing-request-decorator</code> to tag or transform outgoing requests.</p>
<h3>Subscribe to idle events</h3>
<p><code>agent-shell-subscribe-to</code> now broadcasts <code>idle</code> events (<a href="https://github.com/xenodium/agent-shell/pull/509">#509</a> by <a href="https://github.com/arthurgleckler">@arthurgleckler</a>).</p>
<h3>Getting shell buffers</h3>
<p><code>agent-shell-shell-buffer</code> returns the underlying shell buffer for the current context.</p>
<h3>Last vs interaction at point</h3>
<p><code>agent-shell-goto-last-interaction</code> jumps to the latest prompt/response pair, while <code>agent-shell-interaction-at-point</code> returns the interaction at point as data.</p>
<h3>Shell status</h3>
<p><code>agent-shell-status</code> returns <code>'busy</code>, <code>'blocked</code>, or <code>'ready</code> status for any shell buffer.</p>
<h3>Session title</h3>
<p>The agent-supplied session title is now exposed via the <code>session-title-changed</code> event (delivered via <code>agent-shell-subscribe-to</code>) (<a href="https://github.com/xenodium/agent-shell/pull/559">#559</a> by <a href="https://github.com/smagnuso">@smagnuso</a>). Can be handy for buffer names, bookmarks, or recent listings.</p>
<h2>New third-party packages</h2>
<p>The <code>agent-shell</code> family of third-party packages keeps growing. Recent additions:</p>
<ul>
<li><a href="https://github.com/xenodium/agent-shell-knockknock">agent-shell-knockknock</a>: Notifications for <code>agent-shell</code> via <a href="https://github.com/konrad1977/knockknock">knockknock.el</a>.</li>
<li><a href="https://github.com/zackattackz/agent-shell-notifications">agent-shell-notifications</a>: Desktop notifications for <code>agent-shell</code> events.</li>
<li><a href="https://github.com/nohzafk/agent-shell-hud">agent-shell-hud</a>: Real-time <code>agent-shell</code> status overlay via a floating dashboard.</li>
<li><a href="https://github.com/lgmoneda/agent-shell-pet">agent-shell-pet</a>: Codex-like pets that broadcast agent-shell session states.</li>
<li><a href="https://github.com/junyi-hou/agent-shell-tramp">agent-shell-tramp</a>: Tramp integration for <code>agent-shell</code>.</li>
<li><a href="https://github.com/Embedded-Focus/agent-circus">agent-circus</a>: Run AI coding agents in sandboxed Docker containers.</li>
</ul>
<h2>Pull requests</h2>
<p>Thank you to all contributors for these improvements!</p>
<ul>
<li><a href="https://github.com/xenodium/agent-shell/pull/308">#308</a>: Fix heartbeat nil value crash in timer and busy indicator (<a href="https://github.com/ElleNajt">@ElleNajt</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/340">#340</a>: Add documentation about the OAuth Anthropic authentication (<a href="https://github.com/chemtov">@chemtov</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/397">#397</a>: Add detailed context usage indicator mode (<a href="https://github.com/emil-e">@emil-e</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/398">#398</a>: Expose outgoing-request-decorator as a defcustom (<a href="https://github.com/emil-e">@emil-e</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/405">#405</a>: Codex defaults for session mode and model (<a href="https://github.com/robjgray">@robjgray</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/408">#408</a>: Use diff-command for diffing (<a href="https://github.com/timfel">@timfel</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/413">#413</a>: Track and manage diff buffers for each permission request (<a href="https://github.com/emil-e">@emil-e</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/418">#418</a>: Add defvar for agent-shell-mode-hook + test (<a href="https://github.com/emil-e">@emil-e</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/420">#420</a>: Replace all references to "Claude Code Agent" with "Claude Agent" (<a href="https://github.com/jinnovation">@jinnovation</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/421">#421</a>: Add agent-shell-clear (<a href="https://github.com/Makesesama">@Makesesama</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/424">#424</a>: Add agent-shell-confirm-interrupt option (<a href="https://github.com/emil-e">@emil-e</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/425">#425</a>: README: Update all references to Claude Code (<a href="https://github.com/jinnovation">@jinnovation</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/429">#429</a>: Viewport attachment fixes (<a href="https://github.com/nhojb">@nhojb</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/438">#438</a>: Fix for structured input from toolCall.rawInput.plan (<a href="https://github.com/timfel">@timfel</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/442">#442</a>: Add related project <code>agent-circus</code> to README.org (<a href="https://github.com/rpoisel">@rpoisel</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/445">#445</a>: Use project-name instead of default-directory in header (<a href="https://github.com/bcc32">@bcc32</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/446">#446</a>: Droid: use native acp client and support default model and mode (<a href="https://github.com/kohnish">@kohnish</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/450">#450</a>: Fix restart using wrong default-directory (<a href="https://github.com/zackattackz">@zackattackz</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/453">#453</a>: Ensure that viewport compiles (<a href="https://github.com/martenlienen">@martenlienen</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/457">#457</a>: Prefer cache directory over tmp for caching (<a href="https://github.com/martenlienen">@martenlienen</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/460">#460</a>: Unhandled method returns an error, unblocking client (<a href="https://github.com/0x6362">@0x6362</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/461">#461</a>: Add wl-paste as a Wayland image handler (<a href="https://github.com/martenlienen">@martenlienen</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/463">#463</a>: Fix header text invisible when font-get :size returns 0 (<a href="https://github.com/ftlio">@ftlio</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/469">#469</a>: Do not create a file if no image in Wayland clipboard (<a href="https://github.com/martenlienen">@martenlienen</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/473">#473</a>: Caching project files completions for improved performance (<a href="https://github.com/Gleek">@Gleek</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/477">#477</a>: Handle non-text content in user_message_chunk during session load (<a href="https://github.com/Gleek">@Gleek</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/483">#483</a>: Add CodeBuddy agent support (<a href="https://github.com/illidan127">@illidan127</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/489">#489</a>: Snapshot session strategy in any case (<a href="https://github.com/timfel">@timfel</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/492">#492</a>: Update claude-agent-acp repository (<a href="https://github.com/Gleek">@Gleek</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/498">#498</a>: Normalize missing MCP transport collection fields for ACP compatibility (<a href="https://github.com/CsBigDataHub">@CsBigDataHub</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/503">#503</a>: Add agent-shell-macext to related projects (<a href="https://github.com/cxa">@cxa</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/509">#509</a>: Add <code>agent-shell-idle-alert-functions</code> (<a href="https://github.com/arthurgleckler">@arthurgleckler</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/513">#513</a>: Quote reply to the complete response with <code>R</code> (<a href="https://github.com/martenlienen">@martenlienen</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/515">#515</a>: Make detection of binary files more robust (<a href="https://github.com/martenlienen">@martenlienen</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/523">#523</a>: Add agent-shell-org-transcript to Related projects (<a href="https://github.com/lllShamanlll">@lllShamanlll</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/528">#528</a>: Add support for Kimi Code CLI using ACP (<a href="https://github.com/nicolaisingh">@nicolaisingh</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/529">#529</a>: Sort the session list based on recency (<a href="https://github.com/smagnuso">@smagnuso</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/530">#530</a>: Add simple blinking circle as busy indicator (<a href="https://github.com/rudolf-adamkovic">@rudolf-adamkovic</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/532">#532</a>: Fix removing queued messages (<a href="https://github.com/Gleek">@Gleek</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/536">#536</a>: Add programmatic query API: agent-shell-query and agent-shell-shell-buffer (<a href="https://github.com/eddof13">@eddof13</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/539">#539</a>: Add ob-agent-shell to related projects in readme (<a href="https://github.com/eddof13">@eddof13</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/545">#545</a>: Keep buffer name on agent-shell-reload and -restart (<a href="https://github.com/timfel">@timfel</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/550">#550</a>: Add agent-recall to related projects (<a href="https://github.com/Marx-A00">@Marx-A00</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/551">#551</a>: Avoid gitignore update for external data dirs (<a href="https://github.com/Silex">@Silex</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/552">#552</a>: Use helper function from shell-maker rather than eob (<a href="https://github.com/smagnuso">@smagnuso</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/553">#553</a>: Add ACP session config options support (<a href="https://github.com/greggroth">@greggroth</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/554">#554</a>: Fix error when cancelling session selection prompt (<a href="https://github.com/Gleek">@Gleek</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/555">#555</a>: Add some niceties useful for <code>agent-shell-list</code> (<a href="https://github.com/vermiculus">@vermiculus</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/559">#559</a>: Expose topic in agent-shell (<a href="https://github.com/smagnuso">@smagnuso</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/561">#561</a>: Update Pi coding agent logo to look more official (<a href="https://github.com/jeff-phil">@jeff-phil</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/565">#565</a>: Enable @ and / completion when reading queued prompts (<a href="https://github.com/Gleek">@Gleek</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/571">#571</a>: Fix unkillable buffer after major-mode change (<a href="https://github.com/Scott-Guest">@Scott-Guest</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/572">#572</a>: Add clipboard image support for Windows (<a href="https://github.com/repelliuss">@repelliuss</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/574">#574</a>: Add agent-shell-pet link to README (<a href="https://github.com/lgmoneda">@lgmoneda</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/582">#582</a>: Add a few additional forward declarations (<a href="https://github.com/tychoish">@tychoish</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/583">#583</a>: Add Hermes Agent support (<a href="https://github.com/yitang">@yitang</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/588">#588</a>: Fix header foreground color (emacs 31) (<a href="https://github.com/nhojb">@nhojb</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/589">#589</a>: Only trim response region when region is active (<a href="https://github.com/martenlienen">@martenlienen</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/590">#590</a>: Fix context-limit header color (emacs-31) (<a href="https://github.com/nhojb">@nhojb</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/595">#595</a>: Fix <code>/</code> completion regression in viewport buffers (<a href="https://github.com/Gleek">@Gleek</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/600">#600</a>: Do not emit permission-request for auto-handled permissions (<a href="https://github.com/Gleek">@Gleek</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/601">#601</a>: Expose thought level (reasoning effort) in header, mode line and keymaps (<a href="https://github.com/martenlienen">@martenlienen</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/602">#602</a>: Update README with Opencode and Ollama setup instructions (<a href="https://github.com/dvictori">@dvictori</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/605">#605</a>: Add <code>agent-shell-restore-context</code> defcustom (<a href="https://github.com/nhojb">@nhojb</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/608">#608</a>: Toggle folding for everything &amp; comfortably fold at point (<a href="https://github.com/codeluggage">@codeluggage</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/609">#609</a>: Prevent accidental auto-scrolling in viewport buffers on tool calls (<a href="https://github.com/martenlienen">@martenlienen</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/611">#611</a>: Fix <code>agent-shell-hermes-acp-command</code> (<a href="https://github.com/TamsynUlthara">@TamsynUlthara</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/613">#613</a>: Improve completion for set-session-config-option (<a href="https://github.com/catern">@catern</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/618">#618</a>: Fix header not showing session mode name (<a href="https://github.com/deftsp">@deftsp</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/621">#621</a>: Reindent Elisp files (<a href="https://github.com/bcc32">@bcc32</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/623">#623</a>: Add agent-shell-hud to related packages (<a href="https://github.com/nohzafk">@nohzafk</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/625">#625</a>: Fix source-block face background not rendering when theme loads after package (<a href="https://github.com/phairoh">@phairoh</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/627">#627</a>: Hermes: add default-session-mode-id to match other agents (<a href="https://github.com/yitang">@yitang</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/629">#629</a>: Write <code>.agent-shell/</code> to <code>.git/info/exclude</code> instead of <code>.gitignore</code> (<a href="https://github.com/phairoh">@phairoh</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/632">#632</a>: Render tool call parameters for non-standard tools like MCP calls (<a href="https://github.com/martenlienen">@martenlienen</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/633">#633</a>: Add GitHub Actions workflow for ERT tests (<a href="https://github.com/phairoh">@phairoh</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/634">#634</a>: Update art generated by <code>agent-shell-hermes--ascii-art</code> (<a href="https://github.com/TamsynUlthara">@TamsynUlthara</a>)</li>
<li><a href="https://github.com/xenodium/agent-shell/pull/639">#639</a>: Preserve window position when restarting (<a href="https://github.com/Gleek">@Gleek</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li><a href="https://github.com/xenodium/agent-shell/issues/202">#202</a>: Header icon is double the expected size</li>
<li><a href="https://github.com/xenodium/agent-shell/issues/278">#278</a>: Heartbeat causes high CPU usage with many agent buffers</li>
<li><a href="https://github.com/xenodium/agent-shell/issues/366">#366</a>: <code>.agent-shell/</code> directory at risk when switching git branches</li>
<li><a href="https://github.com/xenodium/agent-shell/issues/400">#400</a>: <code>agent-shell-viewport-reply-1</code> errors with "Text is read-only"</li>
<li><a href="https://github.com/xenodium/agent-shell/issues/401">#401</a>: Garbled characters output when using non-English languages</li>
<li><a href="https://github.com/xenodium/agent-shell/issues/412">#412</a>: Diff buffer management is messy</li>
<li><a href="https://github.com/xenodium/agent-shell/issues/414">#414</a>: <code>agent-shell-mode-hook</code> timing makes subscribing to events difficult</li>
<li><a href="https://github.com/xenodium/agent-shell/issues/417">#417</a>: Unhandled notifications with kiro</li>
<li><a href="https://github.com/xenodium/agent-shell/issues/426">#426</a>: Starting conversation before agent has initialized leaves "dangling" text</li>
<li><a href="https://github.com/xenodium/agent-shell/issues/431">#431</a>: Heartbeat timer keeps running after failed/abandoned authentication in OpenAI</li>
<li><a href="https://github.com/xenodium/agent-shell/issues/435">#435</a>: <code>xclip</code> clipboard handler silently saves text as PNG in terminal mode</li>
<li><a href="https://github.com/xenodium/agent-shell/issues/441">#441</a>: Background agent notifications treated as stale after <code>session/prompt</code> response</li>
<li><a href="https://github.com/xenodium/agent-shell/issues/443">#443</a>: <code>image-type</code>: Invalid image type <code>'svg</code> on calling agent-shell</li>
<li><a href="https://github.com/xenodium/agent-shell/issues/455">#455</a>: agent-shell enters frozen/hanging state when receiving unknown notifications</li>
<li><a href="https://github.com/xenodium/agent-shell/issues/462">#462</a>: Header text invisible when <code>font-get :size</code> returns 0</li>
<li><a href="https://github.com/xenodium/agent-shell/issues/465">#465</a>: Session load crashes on non-text user message chunks (e.g. images)</li>
<li><a href="https://github.com/xenodium/agent-shell/issues/466">#466</a>: <code>agent-shell-diff-accept-all</code> / <code>-reject-all</code> now focus the originating shell</li>
<li><a href="https://github.com/xenodium/agent-shell/issues/468">#468</a>: <code>wl-paste-image-handler</code> breaks pasting text</li>
<li><a href="https://github.com/xenodium/agent-shell/issues/481">#481</a>: History input rolls back in <code>insert</code> editing mode while pressing up/down arrows</li>
<li><a href="https://github.com/xenodium/agent-shell/issues/485">#485</a>: Shells created in other workspaces no longer display</li>
<li><a href="https://github.com/xenodium/agent-shell/issues/493">#493</a>: Tables rendered in agent-shell break cursor (point) navigation</li>
<li><a href="https://github.com/xenodium/agent-shell/issues/533">#533</a>: Can't install agent-shell from MELPA</li>
<li><a href="https://github.com/xenodium/agent-shell/issues/548">#548</a>: Copied highlighted text from agent output includes trailing backtick</li>
<li><a href="https://github.com/xenodium/agent-shell/issues/563">#563</a>: "Cannot modify map in-place" when starting agents</li>
<li><a href="https://github.com/xenodium/agent-shell/issues/577">#577</a>: <code>agent-shell-get-config</code> does not work in an <code>agent-shell-command-prefix</code> function</li>
<li><a href="https://github.com/xenodium/agent-shell/issues/587">#587</a>: Long region preview's "Expand…" button is sent literally to the agent</li>
<li><a href="https://github.com/xenodium/agent-shell/issues/617">#617</a>: OpenCode: consent prompt shows empty input when <code>request_permission</code> arrives before <code>tool_call_update</code> populates <code>rawInput</code></li>
</ul>
<h3>Lots of polish</h3>
<p>Beyond what's showcased, I've poured much love and effort into polishing the <code>agent-shell</code> experience. Interested in the nitty-gritty? Have a look through <a href="https://github.com/xenodium/agent-shell/commits/main/">my regular commits</a>.</p>
<h2>Make the work sustainable</h2>
<p>If <a href="https://github.com/xenodium/agent-shell">agent-shell</a> is useful to you, please consider <a href="https://github.com/sponsors/xenodium">sponsoring</a> the project. I'm now back to working on <code>agent-shell</code> daily.</p>
<p>LLM tokens aren't free, and neither is the time dedicated to building this stuff (especially as an indie dev). I also have bills to pay ;)</p>
<p>Unless I can make this work sustainable, I will have to shift my focus to work on something else that is.</p>
<p>✨ <a href="https://github.com/sponsors/xenodium">Sponsor agent-shell</a> ✨</p>
</body></html>]]></content>
        <author>
            <name>Alvaro Ramirez</name>
            <uri>https://xenodium.com</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Irreal: Emacs In Pop Culture]]></title>
        <id>https://irreal.org/blog/?p=13866</id>
        <link href="https://irreal.org/blog/?p=13866"/>
        <updated>2026-06-10T15:35:57.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>
Ian Pan has curated a nice collection of <a href="https://ianyepan.github.io/posts/emacs-in-pop-culture/">Emacs caught in the wild</a>. By “in the wild” I mean “in popular culture”: things like movies and comics. Most of us have seen the familiar scene from Tron but Pan has a bunch of others.
</p>
<p>
One example is the famous scene from <a href="https://en.wikipedia.org/wiki/Silicon_Valley_(TV_series)">Silicon Valley</a> in which Richie and Winnie start arguing about Tabs versus Spaces and end up discovering that one is a Vim user and the other an Emacs user. I’ve seen that scene many times but didn’t realize where it came from so I learned something new from his post.
</p>
<p>
The other surprising thing—to me—is that Emacs also makes appearances in comics. What’s interesting is that you rarely see any editor other than Emacs or Vi(m) mentioned outside geek circles. Perhaps the current cohort of hackers will change that and we’ll start seeing references to VS Code. Or maybe not. VS Code <i>does</i> have a lot of users but I haven’t seen the same culture grow up around it. We’ll see.</p>
</body></html>]]></content>
        <author>
            <name>Irreal</name>
            <uri>https://irreal.org/blog</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Chris Maiorana: When tmux is your window manager]]></title>
        <id>https://chrismaiorana.com/tmux-wm-emacs-no-gui/</id>
        <link href="https://chrismaiorana.com/tmux-wm-emacs-no-gui/"/>
        <updated>2026-06-10T11:56:45.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>I recently wrote a post about <a href="https://chrismaiorana.com/writerdecks-distraction-free-writing-environments/">writerdecks and minimalist “distraction-free” writing environments</a> in general. I concluded that the most minimalist writing environment you could get is a cheap notebook and Bic pen you could get at any supermarket.</p>
<p>However, as a digital minimalist, and one who writes at a high enough volume, a writerdeck starts to make a lot of sense. So I thought I’d try to make one.</p>
<p>But, I wanted it to be a “low buy” or “no buy” situation. Luckily, I had a Raspberry Pi 4 lying around unused, so I snapped it up. I installed a lightweight, minimalist distribution of Debian called DietPi and installed Emacs with no GUI. (Of course, I also installed git and a lot of other stuff by now, but I am keeping it GUI-free.)</p>
<p><img src="https://chrismaiorana.com/wp-content/uploads/2026/06/emacs-no-gui-1024x576.png" alt="" width="1024" height="576" srcset="https://chrismaiorana.com/wp-content/uploads/2026/06/emacs-no-gui-1024x576.png 1024w, https://chrismaiorana.com/wp-content/uploads/2026/06/emacs-no-gui-300x169.png 300w, https://chrismaiorana.com/wp-content/uploads/2026/06/emacs-no-gui-768x432.png 768w, https://chrismaiorana.com/wp-content/uploads/2026/06/emacs-no-gui-1536x864.png 1536w, https://chrismaiorana.com/wp-content/uploads/2026/06/emacs-no-gui-678x381.png 678w, https://chrismaiorana.com/wp-content/uploads/2026/06/emacs-no-gui.png 1920w"></p>
<p><strong>We’re talking MAXIMUM digital minimalism here.</strong></p>
<p>I am using tmux as a sort of window manager, spawning sessions and windows and switching between them as needed. I’ve also opted to run Emacs as a daemon and connect to it with <code>emacsclient</code>, so no matter what session or window I’m in, I’m attached to the same running Emacs state. This means I can view any and all available buffers and have Claude edit Emacs lisp files and see live results without having to reload Emacs.</p>
<p><img src="https://chrismaiorana.com/wp-content/uploads/2026/06/amber_crt.png" alt="" width="564" height="503" srcset="https://chrismaiorana.com/wp-content/uploads/2026/06/amber_crt.png 564w, https://chrismaiorana.com/wp-content/uploads/2026/06/amber_crt-300x268.png 300w">For aesthetic reasons, I’ve opted for an “amber CRT” color scheme with the available 16-color palette in the text interface. This makes my workstation feel like a DOS-era word processor.</p>
<p>I love this so much it’s hard to contain my excitement.</p>
<p>I plan on making a more in-depth video on this topic later to actually demonstrate the system live and show some of the config-mongering I went through to get it just right.</p>
<p>I’ve really enjoyed the results as I’ve grown accustomed to a purely text-based (no mouse!) workflow. The only downside is that it reverses the classic Emacs paradigm of having Emacs colonize my desktop. Instead, Emacs is a guest in tmux. <em>C’est la vie.</em></p>
<p>Thanks for reading, be sure to check out my books about similar topics: <a href="https://chris-maiorana.kit.com/products/emacs-for-writers">Emacs For Writers</a> and <a href="https://chris-maiorana.kit.com/products/git-for-writers">Git For Writers</a>.</p>
<p>The post <a href="https://chrismaiorana.com/tmux-wm-emacs-no-gui/">When tmux is your window manager</a> appeared first on <a href="https://chrismaiorana.com">Chris Maiorana</a>.</p>
</body></html>]]></content>
        <author>
            <name>Chris Maiorana</name>
            <uri>https://chrismaiorana.com/category/emacs/</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Dave Pearson: blogmore.el v5.0.0]]></title>
        <id>https://blog.davep.org/2026/06/10/blogmore-el-v5-0-0.html</id>
        <link href="https://blog.davep.org/2026/06/10/blogmore-el-v5-0-0.html"/>
        <updated>2026-06-10T09:22:12.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>When I released <a href="https://blog.davep.org/2026/06/09/blogmore-el-v4-7-0.html"><code>blogmore.el</code> v4.7.0</a>
yesterday I finished off by saying that it was my intention, at some point,
to rework the frontmatter-handling code so that it did proper YAML parsing.
As often happens with these sorts of things, "some point" ended up being
that evening.</p>
<p>I've rewritten everything to do with handling properties in the frontmatter
so that it now uses <a href="https://github.com/zkry/yaml.el" target="_blank"><code>yaml.el</code></a>. This has a
number of knock-on effects. The first and most obvious effect is that
anything that is a list/array in the frontmatter is actually properly
treated as a list. A good example here is <code>tags</code>. Now you can have your tags
look like:</p>
<div class="highlight"><pre><span></span><code><span class="nt">tags</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">[</span><span class="nv">BlogMore</span><span class="p p-Indicator">,</span><span class="w"> </span><span class="nv">Emacs</span><span class="p p-Indicator">,</span><span class="w"> </span><span class="s">"Emacs</span><span class="nv"> </span><span class="s">Lisp"</span><span class="p p-Indicator">,</span><span class="w"> </span><span class="nv">Lisp</span><span class="p p-Indicator">,</span><span class="w"> </span><span class="s">"blogmore.el"</span><span class="p p-Indicator">,</span><span class="w"> </span><span class="nv">coding</span><span class="p p-Indicator">]</span>
</code></pre></div>

<p>or:</p>
<div class="highlight"><pre><span></span><code><span class="nt">tags</span><span class="p">:</span>
<span class="w">  </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">BlogMore</span>
<span class="w">  </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Emacs</span>
<span class="w">  </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Emacs Lisp</span>
<span class="w">  </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Lisp</span>
<span class="w">  </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">blogmore.el</span>
<span class="w">  </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">coding</span>
</code></pre></div>

<p>and <code>blogmore.el</code> will still handle things fine. The same holds for <code>series</code>
too.</p>
<p>It should be noted, however, that because I'm now using actual YAML
serialisation code, most other forms of a list will all end up being
transformed into this kind:</p>
<div class="highlight"><pre><span></span><code><span class="nt">tags</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">[</span><span class="nv">BlogMore</span><span class="p p-Indicator">,</span><span class="w"> </span><span class="nv">Emacs</span><span class="p p-Indicator">,</span><span class="w"> </span><span class="s">"Emacs</span><span class="nv"> </span><span class="s">Lisp"</span><span class="p p-Indicator">,</span><span class="w"> </span><span class="nv">Lisp</span><span class="p p-Indicator">,</span><span class="w"> </span><span class="s">"blogmore.el"</span><span class="p p-Indicator">,</span><span class="w"> </span><span class="nv">coding</span><span class="p p-Indicator">]</span>
</code></pre></div>

<p>So if you have a bare list:</p>
<div class="highlight"><pre><span></span><code><span class="nt">tags</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">BlogMore, Emacs, "Emacs Lisp", Lisp, "blogmore.el", coding</span>
</code></pre></div>

<p>and you make an edit to the tags via <code>blogmore.el</code>, it will end up as the
version enclosed in <code>[]</code>. <a href="https://blogmore.davep.dev/" target="_blank">BlogMore</a> itself
supports all three versions so this works fine.</p>
<p>There is a breaking change here too, which in part explains the reason I
bumped the version to 5.0.0: because <code>series</code> can now be treated as a list
I've removed the <code>blogmore-set-series</code> command and instead replaced it with
<code>blogmore-add-series</code> and <code>blogmore-remove-series</code>. Both can of course be
found in the transient menu.</p>
<p>Another big change in this release is the way that existing values are
loaded up from your blog. Previously, when you went to add a category, tag
or series, <code>blogmore.el</code> would use
<a href="https://github.com/burntsushi/ripgrep" target="_blank">ripgrep</a> (or a combination of <code>find</code>
and <code>grep</code> if <code>rg</code> wasn't available) to pull out values to help populate a
completion list. This worked fine as long as a) the frontmatter property was
all on one line and b) the body of a post didn't contain something that
looked like a frontmatter property. With this release of <code>blogmore.el</code> I've
dropped this approach in favour of calling <code>blogmore</code> itself and using the
<a href="https://blogmore.davep.dev/command_line/#dump-command" target="_blank">dump command</a> to get
the actual lists of categories, tags and series.</p>
<p>This does mean that BlogMore needs to be installed in a location where
<code>blogmore.el</code> can see it, and to help with this I've added a new <code>defcustom</code>
called <code>blogmore-command</code>. By default this is set to call whatever version
of <code>blogmore</code> can be found in your <code>exec-path</code>; if this results in
unexpected behaviour you can set <code>blogmore-command</code> to point to a specific
copy of <code>blogmore</code>.</p>
<p>There is, however, a small downside to this beneficial<sup><a href="https://blog.davep.org/#fn:377-1">1</a></sup> approach: calling
on <code>blogmore</code> and parsing all posts to get the values is generally going to
be slower. With this in mind I've built in a cache for these values. The
first time you load up the categories, tags or series, the values are held
on to so that subsequent prompts are instantaneous (meaning there is no
further call to <code>blogmore</code>). To ensure this doesn't confuse things, when you
switch blog (<code>blogmore-work-on</code>) the caches are cleared. In the unlikely
event that there is a problem with this approach, I've also added a
<code>blogmore-clear-caches</code> command to force the clearing of the caches.</p>
<p>There are some other small QoL changes under the hood and also to the
interface. I've moved some things around in the transient menu, and also
ensured that a couple of options are better-disabled depending on the
context.</p>
<p><img alt="The current menu" height="227" loading="lazy" src="https://blog.davep.org/attachments/2026/06/10/blogmore-menu.webp#centre" width="619"></p>
<p>All of this makes the package even more robust. Something that started as a
quick hack <a href="https://blog.davep.org/2026/03/19/some-blogmore-elisp.html">back in March</a> has turned
into a tool I heavily lean on. Hopefully, for anyone who might happen to use
BlogMore <em>and</em> GNU Emacs, it'll be a useful daily-driver for them too.</p>
<div class="footnote">
<hr>
<ol>
<li>
<p>The benefits being: only values in frontmatter appear, inconsistent
casing is cleaned up, etc.&nbsp;<a href="https://blog.davep.org/#fnref:377-1">↩</a></p>
</li>
</ol>
</div></body></html>]]></content>
        <author>
            <name>Dave Pearson</name>
            <uri>https://blog.davep.org</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[James Dyer: The Hidden Git Stash Keys in Emacs VC Directory Mode]]></title>
        <id>https://emacs.dyerdwelling.family/emacs/20260610061920-emacs--the-hidden-git-stash-keys-in-emacs-vc-directory-mode/</id>
        <link href="https://emacs.dyerdwelling.family/emacs/20260610061920-emacs--the-hidden-git-stash-keys-in-emacs-vc-directory-mode/"/>
        <updated>2026-06-10T05:19:00.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>
My ongoing journey with <code>vc-dir</code> and <code>vc-mode</code> led me into wanting to delete a stash (not to pop). There are "z" keybindings in <code>vc-dir</code>:
</p>

<div class="org-src-container">
<pre>z c	vc-git-stash
z p	vc-git-stash-pop
z s	vc-git-stash-snapshot
</pre>
</div><br>
<p>
but what about delete?, and are there any others?
</p>

<p>
In <code>vc-dir</code> you get a rather nice little <b>Stash</b> section tacked on at the bottom listing all your stashes:
</p>


<div class="figure">
<p><img loading="lazy" src="https://emacs.dyerdwelling.family/static/emacs/20260610061920-emacs--The-Hidden-Git-Stash-Keys-in-Emacs-VC-Directory-Mode.jpg" alt="20260610061920-emacs--The-Hidden-Git-Stash-Keys-in-Emacs-VC-Directory-Mode.jpg" width="100%">
</p>
</div>

<p>
I genuinely assumed I was missing something obvious, so I did the sensible Emacs thing and hit <code>C-h m</code> to describe the mode, scrolled through the whole keymap, and, nothing about stashes at all.
</p>

<p>
Well how about <code>C-h b</code> (describe-bindings)?, initially nothing!, however I stumbled on a solution, if the point is on a stash name, the following is exposed!
</p>

<div class="org-src-container">
<pre>C-k	vc-git-stash-delete-at-point
RET	vc-git-stash-show-at-point
=	vc-git-stash-show-at-point
A	vc-git-stash-apply-at-point
C	vc-git-stash
P	vc-git-stash-pop-at-point
S	vc-git-stash-snapshot
</pre>
</div><br>
<p>
Surprisingly difficult to find.
</p>

<p>
and C-k does obviously seem a natural fit to delete a stash, but what wasn't obvious was the fact that the point had to be on the stash name.
</p>

<p>
I couldn't quite understand why these keybindings were so difficult to find, so I went digging into <code>vc-git.el</code> and there it was, the bindings are not part of <code>vc-dir-mode-map</code> at all, they live in their own little keymap:
</p>

<div class="org-src-container">
<pre>(<span>defvar-keymap</span> vc-git-stash-map
  <span>:parent</span> vc-git-stash-shared-map
  <span>"&lt;down-mouse-3&gt;"</span> #'vc-git-stash-menu
  <span>"C-k"</span>            #'vc-git-stash-delete-at-point
  <span>"="</span>              #'vc-git-stash-show-at-point
  <span>"RET"</span>            #'vc-git-stash-show-at-point
  <span>"A"</span>              #'vc-git-stash-apply-at-point
  <span>"P"</span>              #'vc-git-stash-pop-at-point)
</pre>
</div><br>
<p>
And the crucial detail, this keymap is not installed as the major mode map, it is slapped directly onto the stash lines as a <code>keymap</code> text property when those lines are rendered.  So the bindings are only live when point is literally sitting on a stash, which is rather elegant actually, but it does mean <code>describe-mode</code> never sees them, because <code>C-h m</code> only reports the major mode's own keymap, and a text-property keymap is invisible to it.  That explained my confusion completely, I was not going mad after all!
</p>

<p>
And the Emacs manual, well I did have a little look but found nothing. It seems these keybindings are almost impossible to find, but now I have found them this blog post should help me to remember.
</p>

<p>
So, lesson learned, and a genuinely useful one I think, <code>C-h m</code> is not the whole story.  When a mode renders interactive regions, buttons, clickable lines, embedded widgets, those often carry their own text-property keymaps that <code>describe-mode</code> will never show you, and the move in those situations is <code>C-h k</code> or <code>C-h b</code> with point actually on the thing.
</p>

<p>
Anyway, <code>C-k</code> on a stash line to drop it, that is the headline, write it on a sticky note, you will want it eventually!, if you are a <code>vc-mode</code> user of course, I suspect that <code>magit</code> has this very discoverable already through the stash menu.
</p>
</body></html>]]></content>
        <author>
            <name>James Dyer</name>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[TAONAW - Emacs and Org Mode: ]]></title>
        <id>https://taonaw.com/2026/06/09/sometimes-you-just-gotta-laugh.html</id>
        <link href="https://taonaw.com/2026/06/09/sometimes-you-just-gotta-laugh.html"/>
        <updated>2026-06-10T02:09:24.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>Sometimes you just gotta laugh at yourself.</p>
<p><strong>Interview with an Emacs Enthusiast in 2023 with Emerald McS., PhD</strong></p>

<blockquote>
<p>People don’t quit Emacs. They just die at some point.</p>
</blockquote>
<p>Brilliant.</p>
</body></html>]]></content>
        <author>
            <name>TAONAW - Emacs and Org Mode</name>
            <uri>https://taonaw.com/categories/emacs-org-mode/</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Rahul Juliato: This Blog Now Has a Gemini Mirror]]></title>
        <id>https://rahuljuliato.com/posts/blog-on-gemini</id>
        <link href="https://rahuljuliato.com/posts/blog-on-gemini"/>
        <updated>2026-06-09T20:55:00.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>Quick announcement: this blog now lives on the small net too. If you have a
Gemini client around, point it at:</p>
<p><code>gemini://gemini.rahuljuliato.com</code></p>
<p>You'll find the same posts there, rendered as plain gemtext.</p>
<h2>Wait, Gemini?</h2>
<p><a href="https://geminiprotocol.net">Gemini</a> (the protocol, in case the name now
reminds you of other things) is a small internet protocol that sits somewhere
between Gopher and the early web. It works like this: the client sends a single
request, receives a single response, and the connection is done, always over
TLS. Pages are written in a tiny markup format called gemtext, which gives you
headings, links, lists, preformatted blocks, and that's about it. A link is
always its own line, so pages end up reading like a well-organized text file.</p>
<p>The whole spec is short enough to read in an afternoon, and people have written
servers and clients for it in pretty much every language you can think of. The
community around it is usually called the "small net" or "smolnet": personal
capsules (that's what sites are called over there), gemlogs, and a general
feeling of the web before it became an application platform.</p>
<p>I've been lurking in Geminispace for a while and finally decided this blog
should have a capsule of its own. The mirror is generated from the same
Markdown sources as the web version, so both stay in sync.</p>
<h2>Browsing it from Emacs</h2>
<p>This site has always been totally browsable on EWW, I wanted that by design,
the web version degrades gracefully to plain HTML and reads just fine in a text
buffer. But EWW speaks HTTP only. For Gemini (and Gopher, and Finger), the
package you want is <a href="https://thelambdalab.xyz/elpher/">elpher</a>. It's available
on <a href="https://elpa.nongnu.org/nongnu/elpher.html">NonGNU ELPA</a>, so a plain <code>M-x package-install RET elpher RET</code> gets you there. Then:</p>
<p><code>M-x elpher-go RET gemini://gemini.rahuljuliato.com RET</code></p>
<p>It renders gemtext beautifully in a buffer, history and bookmarks included, and
it integrates gracefully with EWW: bump into an <code>http://</code> link inside elpher
and it opens in EWW, follow a <code>gemini://</code> link from EWW and elpher picks it up.
EWW for the big web, elpher for the small one, and you never leave Emacs.</p>
<h2>Other clients</h2>
<p>The official project site keeps a list of clients for every taste, from TUI
ones like amfora to full GUI browsers like Lagrange:</p>
<p><a href="https://geminiprotocol.net/software/">geminiprotocol.net/software</a></p>
<p>Pick one, type in the address above, and enjoy the quiet side of the internet.
See you there!</p>
</body></html>]]></content>
        <author>
            <name>Rahul Juliato</name>
            <uri>https://rahuljuliato.com</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Sacha Chua: From DC Toedt: Copy Org Mode as Markdown]]></title>
        <id>https://sachachua.com/blog/2026/06/from-dc-toedt-copy-org-mode-as-markdown/</id>
        <link href="https://sachachua.com/blog/2026/06/from-dc-toedt-copy-org-mode-as-markdown/"/>
        <updated>2026-06-09T15:49:08.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><div class="update">
<p>
<span class="timestamp-wrapper"><time>[2026-06-10 Wed]</time></span>: Add embark way to do things.
</p>

</div>

<p>
DC Toedt is a lawyer and professor of practice who uses Emacs and Org Mode. He wanted a small Emacs Lisp function to convert Org Mode syntax to Markdown and copy it to the clipboard to make it easier to copy the materials he's writing for a course on contract drafting. This seems to be a common need, and here are several other approaches:
</p>

<ul>
<li><code>embark-org-copy-as-markdown</code> in <a target="_blank" href="https://melpa.org/#/embark">embark</a></li>
<li><a href="https://mbork.pl/2021-05-02_Org-mode_to_Markdown_via_the_clipboard">Marcin Borkowski: 2021-05-02 Org-mode to Markdown via the clipboard</a></li>
<li><a href="https://mmk2410.org/2026/04/14/copy-an-org-mode-region-as-markdown">Marcel Kapfer - Copy an Org Mode region as Markdown</a></li>
<li><a href="https://www.reddit.com/r/emacs/comments/17um2fk/does_anyone_have_a_function_they_use_to_quickly/">Reddit</a></li>
<li><a href="https://www.reddit.com/r/emacs/comments/e98yyf/send_output_of_orgmdexportasmarkdownstraight_to/">Reddit</a></li>
</ul>

<p>
Anyway, DC shared how he used Claude to generate a simple function to do it, which is here under public domain:
</p>


<div class="org-src-container">
<pre><code>(<span class="org-keyword">defun</span> <span class="org-function-name">my/org-to-markdown-clipboard</span> ()
  <span class="org-doc">"Export org region (or buffer) to Markdown and copy to clipboard.</span>
<span class="org-doc">With no active region, exports the whole buffer."</span>
  (<span class="org-keyword">interactive</span>)
  (<span class="org-keyword">require</span> <span class="org-highlight-quoted-quote">'</span><span class="org-constant">ox-md</span>)
  (<span class="org-keyword">let*</span> ((text (<span class="org-keyword">if</span> (use-region-p)
                   (buffer-substring-no-properties (region-beginning)
(region-end))
                 (buffer-substring-no-properties (point-min) (point-max))))
         (md (org-export-string-as text <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">md</span> t <span class="org-highlight-quoted-quote">'</span>(<span class="org-builtin">:with-toc</span> nil
                                                <span class="org-builtin">:with-author</span> nil
                                                <span class="org-builtin">:with-date</span> nil
                                                <span class="org-builtin">:with-title</span> nil))))
    (kill-new md)
    (message <span class="org-string">"Markdown copied (%d chars)"</span> (length md))))
(<span class="org-keyword">with-eval-after-load</span> <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">org</span>
  (define-key org-mode-map (kbd <span class="org-string">"C-c m"</span>) <span class="org-highlight-quoted-quote">#'</span><span class="org-highlight-quoted-symbol">my/org-to-markdown-clipboard</span>))
</code></pre>
</div>

<div><a href="https://sachachua.com/blog/2026/06/from-dc-toedt-copy-org-mode-as-markdown/index.org">View Org source for this post</a></div>
<p>You can <a href="mailto:sacha@sachachua.com?subject=Comment%20on%20https%3A%2F%2Fsachachua.com%2Fblog%2F2026%2F06%2Ffrom-dc-toedt-copy-org-mode-as-markdown%2F&amp;body=Name%20you%20want%20to%20be%20credited%20by%20(if%20any)%3A%20%0AMessage%3A%20%0ACan%20I%20share%20your%20comment%20so%20other%20people%20can%20learn%20from%20it%3F%20Yes%2FNo%0A">e-mail me at sacha@sachachua.com</a>.</p></body></html>]]></content>
        <author>
            <name>Sacha Chua</name>
            <uri>https://sachachua.com/blog/category/emacs/feed/index.xml</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Dave Pearson: blogmore.el v4.7.0]]></title>
        <id>https://blog.davep.org/2026/06/09/blogmore-el-v4-7-0.html</id>
        <link href="https://blog.davep.org/2026/06/09/blogmore-el-v4-7-0.html"/>
        <updated>2026-06-09T07:42:40.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>A quick update to <a href="https://github.com/davep/blogmore.el" target="_blank"><code>blogmore.el</code></a>.
Having <a href="https://blog.davep.org/2026/06/06/blogmore-v2-40-0.html">recently added series support to
BlogMore</a> it made sense that I then add a
quick way of adding a post to a series in the package.</p>
<p><img alt="Selecting a series" height="718" loading="lazy" src="https://blog.davep.org/attachments/2026/06/09/select-a-series.webp#centre" width="706"></p>
<p>You can, of course, set a new one too, but the idea here (as with categories
and tags) is that you can quickly find back an existing series and add the
current post to it.</p>
<p>Also, as with tags, the expectation is that either a single series is being
used, or if more than one series is in play for a post they'll be listed as
a comma-separated list. The issue here is that while BlogMore supports this:</p>
<div class="highlight"><pre><span></span><code><span class="nt">series</span><span class="p">:</span>
<span class="w">  </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Some series of posts</span>
<span class="w">  </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Some other series of posts</span>
<span class="w">  </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Yet another series of posts</span>
</code></pre></div>

<p>the frontmatter-handling code in <code>blogmore.el</code> isn't very sophisticated at
all; it doesn't actually handle it as actual YAML, instead just treating it
as a set of key/value pairs separated by a colon.</p>
<p>At some point soon I want to give <code>blogmore.el</code> a revamp and base all of the
frontmatter-handling code on something like
<a href="https://github.com/zkry/yaml.el" target="_blank"><code>yaml.el</code></a>. I did do some experimenting
last night to drop it in and handle proper lists. It worked well enough, but
I abandoned the work as I realised I really wanted to start again from
scratch and build <code>blogmore.el</code> from the bottom up using that package.</p>
<p>Some time soon...</p></body></html>]]></content>
        <author>
            <name>Dave Pearson</name>
            <uri>https://blog.davep.org</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Sacha Chua: Yay Emacs 33: Sacha and Prot Talk Emacs: Built-ins]]></title>
        <id>https://sachachua.com/blog/2026/06/june-11-sacha-and-prot-talk-emacs-built-ins/</id>
        <link href="https://sachachua.com/blog/2026/06/june-11-sacha-and-prot-talk-emacs-built-ins/"/>
        <updated>2026-06-09T02:51:39.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><div class="update">
<p>
<span class="timestamp-wrapper"><time>[2026-06-15 Mon]</time></span>: Updated transcript
</p>

</div>

<p>
I chatted with <a href="https://protesilaos.com">Prot</a> about the Emacs Carnival June 2026 topic <a href="https://rossabaker.com/blog/underappreciated-emacs-built-ins/">Underappreciated Emacs Built-ins</a>. Thanks to Ross A. Baker for hosting the carnival!
<video src="https://archive.org/download/yay-emacs-33-sacha-and-prot-talk-emacs-built-ins/yay-emacs-33-sacha-and-prot-talk-emacs-built-ins.mp4" poster="https://sachachua.com/blog/2026/06/june-11-sacha-and-prot-talk-emacs-built-ins/2026-06-08_22-53-17.png"><track><span>Video not supported. Thumbnail:<br><img src="https://sachachua.com/blog/2026/06/june-11-sacha-and-prot-talk-emacs-built-ins/2026-06-08_22-53-17.png" alt="Thumbnail"></span></video>
</p>

<p>
<a href="https://archive.org/details/yay-emacs-33-sacha-and-prot-talk-emacs-built-ins/">View in the Internet Archive</a>, <a href="https://youtube.com/live/yuJYEua0ZwA">watch or comment on YouTube</a>, <a href="https://sachachua.com/blog/category/emacs/feed/index.xml#ID-yay-emacs-33-sacha-and-prot-talk-emacs-built-ins-transcript">read the transcript online</a>, <a href="https://sachachua.com/blog/2026/06/june-11-sacha-and-prot-talk-emacs-built-ins/yay-emacs-33-sacha-and-prot-talk-emacs-built-ins.vtt">download the transcript</a>, or <a href="mailto:sacha@sachachua.com">e-mail me</a>.
</p>

<p>
Related links:
</p>

<ul>
<li><a href="https://rossabaker.com/blog/underappreciated-emacs-built-ins/">Underappreciated Emacs Built-ins</a></li>
<li><a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/index.html">Top (GNU Emacs Manual)</a></li>
<li><a href="https://sachachua.com/blog/2026/04/yay-emacs-sacha-and-prot-talk-emacs-newbies-starter-kits/">YE24: Sacha and Prot Talk Emacs - Newbies/Starter Kits</a></li>
<li><a href="https://protesilaos.com/codelog/2026-04-30-emacs-decent-default-sacha-chua/">Emacs: decent defaults I shared with Sacha Chua | Protesilaos</a></li>
<li><a href="https://www.emacswiki.org/emacs/Carnival">EmacsWiki: Carnival</a></li>
</ul>
<div class="outline-3">
<h3><a href="https://sachachua.com/blog/category/emacs/feed/index.xml#yay-emacs-33-sacha-and-prot-talk-emacs-built-ins-chapters">Chapters</a></h3>
<div class="outline-text-3">
<p>
</p><ul>
<li><span class="audio-time">0:00</span> Starting up</li>
<li><span class="audio-time">2:27</span> Focus and distraction</li>
<li><span class="audio-time">3:54</span> Org Mode and other note-taking, task-management systems</li>
<li><span class="audio-time">4:58</span> Kill ring</li>
<li><span class="audio-time">6:50</span> Registers</li>
<li><span class="audio-time">9:58</span> Narrowing</li>
<li><span class="audio-time">12:04</span> org-narrow-to-subtree</li>
<li><span class="audio-time">12:13</span> narrow-to-defun</li>
<li><span class="audio-time">13:19</span> Indirect buffers</li>
<li><span class="audio-time">14:50</span> Undoing within a region</li>
<li><span class="audio-time">15:53</span> Bookmarks</li>
<li><span class="audio-time">17:41</span> isearch</li>
<li><span class="audio-time">18:21</span> Tip: Add a counter to isearch</li>
<li><span class="audio-time">19:26</span> C-x C-x (exchange-point-and-mark)</li>
<li><span class="audio-time">20:55</span> Popping to marks - going back to where you were</li>
<li><span class="audio-time">21:49</span> Selecting what you just pasted</li>
<li><span class="audio-time">22:33</span> Indenting pasted or selected text with indent-rigidly</li>
<li><span class="audio-time">23:24</span> Popping to mark after xref or imenu</li>
<li><span class="audio-time">24:05</span> Adding other packages like consult</li>
<li><span class="audio-time">24:44</span> Tip about indicating isearch wrapping</li>
<li><span class="audio-time">25:26</span> Navigating by sentence or s-expression</li>
<li><span class="audio-time">27:45</span> Navigating to other errors</li>
<li><span class="audio-time">28:29</span> Tags</li>
<li><span class="audio-time">28:47</span> Imenu</li>
<li><span class="audio-time">30:19</span> Projects</li>
<li><span class="audio-time">32:10</span> Putting projects in tabs or frames</li>
<li><span class="audio-time">32:35</span> Tabs</li>
<li><span class="audio-time">34:41</span> Navigating frames</li>
<li><span class="audio-time">36:07</span> These navigation shortcuts work for prose, too</li>
<li><span class="audio-time">37:09</span> follow-mode</li>
<li><span class="audio-time">37:50</span> Ediff</li>
<li><span class="audio-time">42:12</span> Calling functions by name</li>
<li><span class="audio-time">42:52</span> Completion</li>
<li><span class="audio-time">44:13</span> Manuals</li>
<li><span class="audio-time">45:57</span> Menus</li>
<li><span class="audio-time">47:46</span> Automation - abbreviations</li>
<li><span class="audio-time">49:56</span> Quoting the next character with C-q</li>
<li><span class="audio-time">50:31</span> Mapping abbreviations to code</li>
<li><span class="audio-time">51:51</span> Taking notes with org-capture</li>
<li><span class="audio-time">52:08</span> Navigating back to captures or refiles</li>
<li><span class="audio-time">53:49</span> dabbrev</li>
<li><span class="audio-time">54:44</span> Keyboard macros</li>
<li><span class="audio-time">57:52</span> Editable grep and occur</li>
<li><span class="audio-time">1:01:01</span> Emacs Carnival June 2026: Underappreciated built-ins</li>
</ul>

<p></p>
</div>
</div>
<div class="outline-3">
<h3><a href="https://sachachua.com/blog/category/emacs/feed/index.xml#yay-emacs-33-sacha-and-prot-talk-emacs-built-ins-transcript-section">Transcript</a></h3>
<div class="outline-text-3">
<a name="ID-yay-emacs-33-sacha-and-prot-talk-emacs-built-ins-transcript"></a>Expand this to read the transcript
<p>
</p><div class="full-transcript"><p></p><div class="transcript-heading"><span class="audio-time">0:00</span> <strong>Starting up</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong>  There's a 10-second delay, so I can</span> <span class="audio-time caption">never quite tell when I'm starting to start, but</span> <span class="audio-time caption">I think I'm going to do that now.</span> <span class="audio-time caption">Okay, let's go.</span> <span class="audio-time caption">Okay, I have pressed the Go Live button.</span> <span class="audio-time caption">Let's see how it goes.</span> <span class="audio-time caption">So this is Yay Emacs 33 with Prot:</span> <span class="audio-time caption">Sacha and Prot Talk Emacs.</span> <span class="audio-time caption">Today, we're going to be talking about</span> <span class="audio-time caption">underappreciated Emacs built-ins, which is the</span> <span class="audio-time caption">theme for this month's Emacs carnival.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong> Kind of like this, you know, shared, lots of</span> <span class="audio-time caption">people writing or talking about a specific topic.</span> <span class="audio-time caption">This one is hosted by Ross A. Baker.</span> <span class="audio-time caption">(Thanks for hosting that!)</span> <span class="audio-time caption">Anyway, so I'm here with Prot. I was very</span> <span class="audio-time caption">tempted to just dive into this brain dump like</span> <span class="audio-time caption">last time about...</span> <span class="audio-time caption">Let's start with the kinds of problems that</span> <span class="audio-time caption">newcomers and intermediate users might run into,</span> <span class="audio-time caption">especially the problems they don't even know</span> <span class="audio-time caption">about because Emacs would allow them to do things</span> <span class="audio-time caption">that other editors might not offer.</span> <span class="audio-time caption">But they've got to think about it first, right?</span> <span class="audio-time caption">They've got to discover that this is a need of theirs</span> <span class="audio-time caption">and that Emacs can help them with it.</span> <span class="audio-time caption">So maybe this conversation can be a high-level</span> <span class="audio-time caption">discussion of these concepts to help people</span> <span class="audio-time caption">develop this intuition for what's out there,</span> <span class="audio-time caption">particularly for the things that Emacs does</span> <span class="audio-time caption">differently compared to other editors.</span> <span class="audio-time caption">And if we start with a problem, and I have</span> <span class="audio-time caption">several that I often run into in my own life, you</span> <span class="audio-time caption">might suggest others as well.</span> <span class="audio-time caption">Then we can talk about how the things that</span> <span class="audio-time caption">are built into Emacs can support that and how</span> <span class="audio-time caption">they fit together at a high level. We don't</span> <span class="audio-time caption">have to go into "This is precisely how</span> <span class="audio-time caption">to start a keyboard macro and how to stop it."</span> <span class="audio-time caption">People can look that up in the manual. But the</span> <span class="audio-time caption">idea of a keyboard macro and how it's useful,</span> <span class="audio-time caption"><b>that</b> would probably be a good thing for a</span> <span class="audio-time caption">conversation.</span> <span class="audio-time caption">Then for the advanced users who are listening</span> <span class="audio-time caption">to this, we can sprinkle in some things we've</span> <span class="audio-time caption">seen about some really advanced uses of these</span> <span class="audio-time caption">built-ins, because there's a lot of high-level</span> <span class="audio-time caption">use that I haven't even got into yet.</span> <span class="audio-time caption">So Prot is here, which means that because you've</span> <span class="audio-time caption">got two people, you can see how these same tools</span> <span class="audio-time caption">can be used in different ways to support</span> <span class="audio-time caption">different workflows.</span> <span class="audio-time caption">I'm going to suggest some problems that I have.</span> <span class="audio-time caption">Of course, you can share some from your</span> <span class="audio-time caption">experience and from the times that you've coached</span> <span class="audio-time caption">other people.</span> <p></p><div class="transcript-heading"><span class="audio-time">2:27</span> <strong>Focus and distraction</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong> My main problem with life in general.</span> <span class="audio-time caption">is focus and distraction.</span> <span class="audio-time caption">Because I have a kid, my focus time is very</span> <span class="audio-time caption">unpredictable.</span> <span class="audio-time caption">It can be interrupted any moment by somebody</span> <span class="audio-time caption">needing help.</span> <span class="audio-time caption">My life over the last 10 years has mostly</span> <span class="audio-time caption">been about five minutes here, 10 minutes there,</span> <span class="audio-time caption">maybe 15, one hour of focus time if I'm lucky.</span> <span class="audio-time caption">This is a universal challenge.</span> <span class="audio-time caption">Well, some people actually get to focus, but my</span> <span class="audio-time caption">brain is not one of those focusable things.</span> <span class="audio-time caption">It has to work in stops and starts.</span> <span class="audio-time caption">Any chance this is a problem that you also run into?</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  Not to that extent, but I have the</span> <span class="audio-time caption">propensity to go down rabbit holes.</span> <span class="audio-time caption">I will go really deep, like really deep.</span> <span class="audio-time caption">You give me something which I know nothing about,</span> <span class="audio-time caption">I will become an expert in it.</span> <span class="audio-time caption">But of course, this is a problem when you combine</span> <span class="audio-time caption">it with curiosity, because now you want to learn</span> <span class="audio-time caption">everything.</span> <span class="audio-time caption">Thankfully, I have learned to control myself.</span> <span class="audio-time caption">If you give me something I don't know about,</span> <span class="audio-time caption">I will say, OK, sounds very tempting, but I will</span> <span class="audio-time caption">not even try.</span> <span class="audio-time caption">I won't even go down the rabbit hole.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  So these are</span> <span class="audio-time caption">two sides of the same problem,</span> <span class="audio-time caption">and something that a lot of people will resonate</span> <span class="audio-time caption">with... When you're working on something and you</span> <span class="audio-time caption">realize, okay, I've got to go do this other thing</span> <span class="audio-time caption">first or, oh, I'm curious about this question</span> <span class="audio-time caption">that has come up in my brain.</span> <span class="audio-time caption">I want to go down that rabbit hole.</span> <span class="audio-time caption">How do we manage this?</span> <span class="audio-time caption">Emacs is here to help.</span> <p></p><div class="transcript-heading"><span class="audio-time">3:54</span> <strong>Org Mode and other note-taking, task-management systems</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong> My first recommendation for this problem is:</span> <span class="audio-time caption">take advantage of Org Mode or other</span> <span class="audio-time caption">built-in note-taking task management support</span> <span class="audio-time caption">systems because it...</span> <span class="audio-time caption">Sometimes people think, okay, an IDE is just an</span> <span class="audio-time caption">IDE, right?</span> <span class="audio-time caption">If they're programmers, it's just for code.</span> <span class="audio-time caption">Sometimes people are writing. They're using</span> <span class="audio-time caption">a text editor just for writing their novel.</span> <span class="audio-time caption">But because Emacs has these built-in ways to</span> <span class="audio-time caption">support managing your to-dos and all that stuff,</span> <span class="audio-time caption">it's very easy just to stuff that task in there.</span> <span class="audio-time caption">Have a quick shortcut to go to your to-do list</span> <span class="audio-time caption">and put something in. Then it gets out of</span> <span class="audio-time caption">your brain so that you can try to focus on the</span> <span class="audio-time caption">thing that you're trying to get done.</span> <span class="audio-time caption">That's my quick underappreciated...</span> <span class="audio-time caption">actually, a lot of people really appreciate</span> <span class="audio-time caption">this, but it's one of those things</span> <span class="audio-time caption">people coming to Emacs from other editors might</span> <span class="audio-time caption">not immediately catch on to.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  You might not understand the</span> <span class="audio-time caption">extent of how valuable it is.</span> <span class="audio-time caption">It's the gift that keeps giving, basically.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Yeah, yeah.</span> <span class="audio-time caption">When your to-dos and your notes are just a couple</span> <span class="audio-time caption">of keystrokes away, and they can save the context</span> <span class="audio-time caption">of whatever you were looking at.</span> <p></p><div class="transcript-heading"><span class="audio-time">4:58</span> <strong>Kill ring</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong> There are all sorts of other small</span> <span class="audio-time caption">conveniences that Emacs has that also help with</span> <span class="audio-time caption">distraction and focus.</span> <span class="audio-time caption">For example, the kill ring.</span> <span class="audio-time caption">It's such a simple thing, right?</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  It's super simple, but super useful.</span> <span class="audio-time caption">Just to say on the kill ring, it has been</span> <span class="audio-time caption">part of Emacs for several versions now, but it's</span> <span class="audio-time caption">not obvious.</span> <span class="audio-time caption">If you type <code>M-y</code> without <code>C-y</code> beforehand,</span> <span class="audio-time caption">you get completion.</span> <span class="audio-time caption">So you can select something that you had in your</span> <span class="audio-time caption">kill-ring like a few kills ago.</span> <span class="audio-time caption">Clipboard navigation,</span> <span class="audio-time caption">which is something that you don't see right away.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  If people are coming</span> <span class="audio-time caption">from outside Emacs and they're like, "What is this</span> <span class="audio-time caption">thing that you're talking about?"</span> <span class="audio-time caption">People are used to having a clipboard, right?</span> <span class="audio-time caption">As soon as you copy something, your program</span> <span class="audio-time caption">forgets the thing that you previously copied.</span> <span class="audio-time caption">On mobile phones now, if you press</span> <span class="audio-time caption">paste, you can see a selection of the</span> <span class="audio-time caption">previous things you've copied before.</span> <span class="audio-time caption">It's like that, but larger.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong> Prot points out: you can use completion</span> <span class="audio-time caption">with it.</span> <span class="audio-time caption">So <code>M-y</code> is <code>yank-pop</code> I think?</span> <span class="audio-time caption">What I find useful about this is</span> <span class="audio-time caption">sometimes I'll copy something because I want to</span> <span class="audio-time caption">go paste it somewhere else, and then on the way to</span> <span class="audio-time caption">that somewhere else, I get distracted by something,</span> <span class="audio-time caption">and I need to copy that, but I know that the</span> <span class="audio-time caption"><code>kill-ring</code> will have the other copies that I meant to</span> <span class="audio-time caption">put somewhere else.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  By completion here, we mean you</span> <span class="audio-time caption">can type and match that thing, narrow down to it.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong> You don't have to go searching for it and,</span> <span class="audio-time caption">"Okay, which one exactly is it," right?</span> <p></p><span class="audio-time caption"><strong>Prot:</strong> You can find it more easily.</span> <p></p><div class="transcript-heading"><span class="audio-time">6:50</span> <strong>Registers</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong>  Registers.</span> <span class="audio-time caption">It's the other thing that I like to use when I</span> <span class="audio-time caption">know that I'm copying several things and I need</span> <span class="audio-time caption">to paste them, possibly in different order.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong> Again, that's another thing that people are</span> <span class="audio-time caption">like, "What is this thing, even?"</span> <span class="audio-time caption">Do you find yourself explaining registers to</span> <span class="audio-time caption">people who are new to Emacs?</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  Yes. Registers is</span> <span class="audio-time caption">something that is underutilized, because of course,</span> <span class="audio-time caption">why would you need them when you can have a</span> <span class="audio-time caption">kill-ring with a history, right? Why do I need to</span> <span class="audio-time caption">store things in a register when I can just have</span> <span class="audio-time caption">them one after the other in the kill-ring.</span> <span class="audio-time caption">The answer is because if you do something more</span> <span class="audio-time caption">advanced, such as with a keyboard macro,</span> <span class="audio-time caption">it will always be correct.</span> <span class="audio-time caption">It's precise.</span> <span class="audio-time caption">It's not "Give me the last thing on the kill ring,"</span> <span class="audio-time caption">or last thing minus two or whatever.</span> <span class="audio-time caption">Give me that, right,</span> <span class="audio-time caption">and you specify what that is.</span> <span class="audio-time caption">It's an expression of intent.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong> Plus more advanced things,</span> <span class="audio-time caption">like incrementing a number or whatever.</span> <span class="audio-time caption">I think that's super specialized.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  I don't even use that very much,</span> <span class="audio-time caption">but I know some people who use that</span> <span class="audio-time caption">to great effect.</span> <span class="audio-time caption">So that's one of those little Easter eggs for</span> <span class="audio-time caption">advanced users.</span> <span class="audio-time caption">If you're watching this and you're like, okay, I</span> <span class="audio-time caption">know about these built-ins, but there's more.</span> <span class="audio-time caption">Emacs has this fractal complexity.</span> <span class="audio-time caption">It just keeps getting more interesting</span> <span class="audio-time caption">the more you dig into it.</span> <span class="audio-time caption">Okay, so, registers.</span> <span class="audio-time caption">Registers can store text that you're copying,</span> <span class="audio-time caption">but they can also store other things.</span> <span class="audio-time caption">I think, like, do you use them for window</span> <span class="audio-time caption">configurations, Prot?</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  I have used them for framesets:</span> <span class="audio-time caption">frames and their window configurations.</span> <span class="audio-time caption">If you have three frames and they are</span> <span class="audio-time caption">split in different ways, you restore that.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  You can do all of that with</span> <span class="audio-time caption">just one register.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  With a register, yeah.</span> <span class="audio-time caption">I have created another register of mine just</span> <span class="audio-time caption">to see how it works, where it saves a</span> <span class="audio-time caption">file with a specific location,</span> <span class="audio-time caption">but it's supposed to be in memory,</span> <span class="audio-time caption">not like a bookmark.</span> <span class="audio-time caption">I did it just for testing.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  I have that too.</span> <span class="audio-time caption">I use registers to files so that I can jump to</span> <span class="audio-time caption">things like my Emacs configuration or my notes or</span> <span class="audio-time caption">something like that.</span> <span class="audio-time caption">I use that instead of bookmarks so that I can</span> <span class="audio-time caption">just have a keyboard shortcut go straight to that</span> <span class="audio-time caption">register.</span> <span class="audio-time caption">I can do the [<code>jump-to-register</code>] and then I can just</span> <span class="audio-time caption">easily press one more key</span> <span class="audio-time caption">to get to the file that I want.</span> <span class="audio-time caption">So registers, again, if you're not used to Emacs,</span> <span class="audio-time caption">this is a built-in that's got a lot of features</span> <span class="audio-time caption">for helping you save text to things, especially</span> <span class="audio-time caption">if you're going to use them in keyboard macros</span> <span class="audio-time caption">because you can say, okay, insert text A and then</span> <span class="audio-time caption">insert text C and then insert text B. But you can</span> <span class="audio-time caption">also use them for other things like frameset,</span> <span class="audio-time caption">like the way that your windows and your buffers</span> <span class="audio-time caption">are arranged, or files that you want to go back to.</span> <p></p><div class="transcript-heading"><span class="audio-time">9:58</span> <strong>Narrowing</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong> Another built-in that I find really helpful for</span> <span class="audio-time caption">managing my focus and distraction is narrowing.</span> <span class="audio-time caption">I get distracted by all the other stuff, or I</span> <span class="audio-time caption">worry about accidentally revealing private</span> <span class="audio-time caption">information when I am streaming, or something else.</span> <span class="audio-time caption">So instead I narrow it to just the task that I'm</span> <span class="audio-time caption">working on or just the function that I'm editing.</span> <span class="audio-time caption">That's super useful not only for keeping me</span> <span class="audio-time caption">focused, but also for making sure that my changes</span> <span class="audio-time caption">don't affect more text than I mean to.</span> <span class="audio-time caption">If I'm using substitute.el... You can select the</span> <span class="audio-time caption">region, and a lot of the functions in Emacs will</span> <span class="audio-time caption">operate only within that region.</span> <span class="audio-time caption">But reselecting the region several times, if you</span> <span class="audio-time caption">end up needing to do multiple operations, it's a</span> <span class="audio-time caption">bit annoying.</span> <span class="audio-time caption">So instead, I'll just narrow and then it can work</span> <span class="audio-time caption">on the whole thing.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  Yes. When you narrow, you can</span> <span class="audio-time caption">also be less careful, in a sense.</span> <span class="audio-time caption">Like, you do a <code>query-replace</code>,</span> <span class="audio-time caption">when you do <code>!</code>, it means yes to all,</span> <span class="audio-time caption">but if you are in a narrowed region,</span> <span class="audio-time caption">yes to all means only within</span> <span class="audio-time caption">that portion of the buffer.</span> <span class="audio-time caption">So if you take care to</span> <span class="audio-time caption">narrow to where you want to be,</span> <span class="audio-time caption">then okay yes to all, you don't even have to check.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  And I think this is</span> <span class="audio-time caption">underappreciated enough that, in fact, if you try</span> <span class="audio-time caption">to use… Is it <code>C-x n</code>?</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  That's the prefix key.</span> <span class="audio-time caption"><code>C-x n</code> for narrowing.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  The first time Emacs will</span> <span class="audio-time caption">say, are you really, really sure?</span> <span class="audio-time caption">It's one of those disabled commands, right?</span> <span class="audio-time caption">You've got to enable it for yourself.</span> <span class="audio-time caption">You've got to say, "Okay, I know what I'm doing.</span> <span class="audio-time caption">I'm not going to panic if the rest of my file</span> <span class="audio-time caption">disappears."</span> <span class="audio-time caption">I know it's there.</span> <span class="audio-time caption">I'm just choosing to focus on it.</span> <span class="audio-time caption">I think it's actually available off the menu as</span> <span class="audio-time caption">well, but I haven't</span> <span class="audio-time caption">used it off the menu bar.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  Yeah, I don't use the menu, so I</span> <span class="audio-time caption">cannot tell.</span> <span class="audio-time caption">But I remember that prompt,</span> <span class="audio-time caption">"Are you really sure?"</span> <span class="audio-time caption">It's disabled by default.</span> <span class="audio-time caption">Please make sure you know what you want.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Keyboard shortcut.</span> <span class="audio-time caption">That's the way to do it anyway.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  The thing is that I do use it extensively.</span> <p></p><div class="transcript-heading"><span class="audio-time">12:04</span> <strong>org-narrow-to-subtree</strong></div><p></p><span class="audio-time caption"><strong>Prot:</strong> Narrowing, of course, is generic.,</span> <span class="audio-time caption">Org also has its own narrowing.</span> <span class="audio-time caption">The most common one is [<code>org-narrow-to-subtree</code>].</span> <p></p><div class="transcript-heading"><span class="audio-time">12:13</span> <strong>narrow-to-defun</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong>  Narrowing to defun feels easier</span> <span class="audio-time caption">than trying to mark the function before search</span> <span class="audio-time caption">and replace.</span> <span class="audio-time caption">I love narrowing.</span> <span class="audio-time caption">In fact, I narrow to functions</span> <span class="audio-time caption">or sets of functions a lot,</span> <span class="audio-time caption">because I do a lot of work with</span> <span class="audio-time caption">with Javascript in HTML files,</span> <span class="audio-time caption">just a single file HTML that I can upload.</span> <span class="audio-time caption">It's got CSS and regular HTML in it as well.</span> <span class="audio-time caption">But I often just need to copy</span> <span class="audio-time caption">the particular snippet of JavaScript</span> <span class="audio-time caption">so I can paste it into the console as</span> <span class="audio-time caption">I'm making changes.</span> <span class="audio-time caption">I have a function that</span> <span class="audio-time caption">looks for certain text:</span> <span class="audio-time caption">"start of focus", "end of focus".</span> <span class="audio-time caption">Then it narrows to that section, which might</span> <span class="audio-time caption">include several functions.</span> <span class="audio-time caption">Then I have another keyboard shortcut that</span> <span class="audio-time caption">just copies the entire buffer and adds a little</span> <span class="audio-time caption">text at the end, so I can run whatever function I</span> <span class="audio-time caption">need to test.</span> <span class="audio-time caption">I can paste that into the browser.</span> <span class="audio-time caption">Narrowing either to one function or to a</span> <span class="audio-time caption">predefined region or whatever else is very useful.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  Yes, very nice.</span> <p></p><div class="transcript-heading"><span class="audio-time">13:19</span> <strong>Indirect buffers</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong>  Then people are like, yeah, but</span> <span class="audio-time caption">what if I want to narrow to two</span> <span class="audio-time caption">parts of the same file?</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  That's why you have indirect buffers there.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  It's Emacs, of course there's a way</span> <span class="audio-time caption">to do it.</span> <span class="audio-time caption">Indirect buffers is another one of those</span> <span class="audio-time caption">built-ins that's a little hard to wrap your head</span> <span class="audio-time caption">around, because you're like, okay, you're opening</span> <span class="audio-time caption">a file twice, but you can have it narrowed to a</span> <span class="audio-time caption">different part of it, or you can be looking at a</span> <span class="audio-time caption">different part of it, or you can even have it in</span> <span class="audio-time caption">a different major mode.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  Yeah, yeah.</span> <span class="audio-time caption">And the point, like the practical one, is the</span> <span class="audio-time caption">different levels of narrow, really...</span> <span class="audio-time caption">The most common one, I mean,</span> <span class="audio-time caption">where it's like, okay, you focus on this heading</span> <span class="audio-time caption">and now you focus on this other heading.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  I'll often split my buffer if I</span> <span class="audio-time caption">know that I'm not going to narrow.</span> <span class="audio-time caption">So that way, if I need to refer to two parts of</span> <span class="audio-time caption">the file at the same time, I can have one window</span> <span class="audio-time caption">focusing on one part of it and the other window</span> <span class="audio-time caption">focusing on the other part of it.</span> <span class="audio-time caption">It might even be a different frame.</span> <span class="audio-time caption">And that way, I don't</span> <span class="audio-time caption">have to keep switching back and forth.</span> <span class="audio-time caption">I don't have to scroll up and down all the time.</span> <span class="audio-time caption">I can just look at one and then look at the other</span> <span class="audio-time caption">and arrange my windows and my desktop as I see fit.</span> <span class="audio-time caption">But if you want to do something more complicated,</span> <span class="audio-time caption">like more narrowing or different modes or</span> <span class="audio-time caption">whatever, then cloning an indirect buffer is the</span> <span class="audio-time caption">way to do it.</span> <p></p><div class="transcript-heading"><span class="audio-time">14:50</span> <strong>Undoing within a region</strong></div><p></p><span class="audio-time caption"><strong>Prot:</strong>  I don't know if you have this,</span> <span class="audio-time caption">but because you</span> <span class="audio-time caption">mentioned the region earlier, I will say it.</span> <span class="audio-time caption">Maybe you have it somewhere, I don't see it there.</span> <span class="audio-time caption">You know regular undo in Emacs and how it works,</span> <span class="audio-time caption">but when you have a region selected, undo works</span> <span class="audio-time caption">in the region.</span> <span class="audio-time caption">So you make a change here, you go make some</span> <span class="audio-time caption">changes up there, you come back here, you mark</span> <span class="audio-time caption">this region, undo only works here, it doesn't</span> <span class="audio-time caption">work up there anymore.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Oh yeah, that's definitely a</span> <span class="audio-time caption">built-in that people will benefit from if they develop</span> <span class="audio-time caption">an intuition for it.</span> <span class="audio-time caption">If you've made a bunch of changes to your file</span> <span class="audio-time caption">and you notice that something's wrong in just</span> <span class="audio-time caption">this section, you can select the region and then</span> <span class="audio-time caption">undo within it to just fix those things.</span> <span class="audio-time caption">Those are some of the things that I've thought</span> <span class="audio-time caption">about for focus or distraction or getting tempted</span> <span class="audio-time caption">to go down rabbit holes.</span> <span class="audio-time caption">Do you use any of the other Emacs built-ins to</span> <span class="audio-time caption">help you with your tendency to dive really deep</span> <span class="audio-time caption">into something?</span> <p></p><div class="transcript-heading"><span class="audio-time">15:53</span> <strong>Bookmarks</strong></div><p></p><span class="audio-time caption"><strong>Prot:</strong>  So the other one would be bookmarks.</span> <span class="audio-time caption">You mentioned it already,</span> <span class="audio-time caption">but it really is worth having it there,</span> <span class="audio-time caption">because the nice thing with bookmarks is that not</span> <span class="audio-time caption">only it's a way to go to a place, but you also</span> <span class="audio-time caption">give it a name.</span> <span class="audio-time caption">So the counterpart...</span> <span class="audio-time caption">Like you said, okay, I have a key to quickly go</span> <span class="audio-time caption">to my init file, for example, my configuration file.</span> <span class="audio-time caption">But what if I want to have something by name that</span> <span class="audio-time caption">doesn't quite fit nicely in all the keys, right?</span> <span class="audio-time caption">Then I can have a descriptive name.</span> <span class="audio-time caption">Maybe it's long.</span> <span class="audio-time caption">For example, my notes for my meeting with Sacha,</span> <span class="audio-time caption">which is in mid-June, blah, blah, blah, right?</span> <span class="audio-time caption">I can have a long name like that, which</span> <span class="audio-time caption">is descriptive and gives me context.</span> <span class="audio-time caption">Then I use a bookmark for that.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  And that's a great built-in</span> <span class="audio-time caption">solution for the general problem of finding your</span> <span class="audio-time caption">way around.</span> <span class="audio-time caption">So in case you're trying to find your way around</span> <span class="audio-time caption">different files or different projects or</span> <span class="audio-time caption">different places in various files, bookmarks are</span> <span class="audio-time caption">great for that because you can give it a name.</span> <span class="audio-time caption">That means you can file more things than will fit</span> <span class="audio-time caption">on your keyboard.</span> <span class="audio-time caption">Kind of an advanced</span> <span class="audio-time caption">use of it, I was talking to Ben</span> <span class="audio-time caption">in the previous Emacs Chat about</span> <span class="audio-time caption">So he bookmarks Elfeed searches,</span> <span class="audio-time caption">and based on his naming convention,</span> <span class="audio-time caption">if he names his bookmark a certain way,</span> <span class="audio-time caption">then it becomes available for</span> <span class="audio-time caption">these other functions that he has.</span> <span class="audio-time caption">So if you have a naming convention for your</span> <span class="audio-time caption">bookmarks, you can do other things with it from</span> <span class="audio-time caption">Emacs Lisp.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  Yeah, exactly.</span> <span class="audio-time caption">That's the more advanced power user thing.</span> <span class="audio-time caption">It's just data and you have access to it.</span> <p></p><div class="transcript-heading"><span class="audio-time">17:41</span> <strong>isearch</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong>  Going back to something a little</span> <span class="audio-time caption">more basic for the problem of finding your way</span> <span class="audio-time caption">around, I think that isearch is one of those</span> <span class="audio-time caption">built-ins that people coming from a different</span> <span class="audio-time caption">editor might not think of using.</span> <span class="audio-time caption">"Find in page" is an annoying experience in a</span> <span class="audio-time caption">browser or in other editors.</span> <span class="audio-time caption">You have to go to the menu, you do it, and then</span> <span class="audio-time caption">there's things you have to click on in order to</span> <span class="audio-time caption">go to the next one or the previous one and so</span> <span class="audio-time caption">forth.</span> <span class="audio-time caption">But isearch lets you just keep typing and then</span> <span class="audio-time caption">you can just press the isearch shortcut again,</span> <span class="audio-time caption"><code>C-s</code>, to search for the next one, or you can</span> <span class="audio-time caption">go to the previous one very easily.</span> <span class="audio-time caption">So isearch is great.</span> <p></p><div class="transcript-heading"><span class="audio-time">18:21</span> <strong>Tip: Add a counter to isearch</strong></div><p></p><span class="audio-time caption"><strong>Prot:</strong>  Yeah, yeah, it is.</span> <span class="audio-time caption">I think one nice quality of life improvement to</span> <span class="audio-time caption">it, which again is several Emacs versions old, is</span> <span class="audio-time caption">a counter.</span> <span class="audio-time caption">Like it shows you are on number 3 out of</span> <span class="audio-time caption">10, for example.</span> <span class="audio-time caption">You have a sense of where you are going.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Otherwise, I find I just wrap</span> <span class="audio-time caption">around to the beginning and I</span> <span class="audio-time caption">take a moment to reorient myself because it has</span> <span class="audio-time caption">wrapped around.</span> <span class="audio-time caption">The other thing that I want to point out</span> <span class="audio-time caption">related to isearch as well is using it to help</span> <span class="audio-time caption">you mark a region.</span> <span class="audio-time caption">This is something that people aren't</span> <span class="audio-time caption">used to because in other editors, you highlight</span> <span class="audio-time caption">things with your mouse, right?</span> <span class="audio-time caption">Here in Emacs, we say, okay,</span> <span class="audio-time caption">press C-SPC to say</span> <span class="audio-time caption">you're going to start a region,</span> <span class="audio-time caption">and then just search for the end of the region,</span> <span class="audio-time caption">navigate to it somewhere, and</span> <span class="audio-time caption">the text between</span> <span class="audio-time caption">when you press C-SPC</span> <span class="audio-time caption">and where your cursor is now,</span> <span class="audio-time caption">that's the region.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  Yes, exactly.</span> <p></p><div class="transcript-heading"><span class="audio-time">19:26</span> <strong>C-x C-x (exchange-point-and-mark)</strong></div><p></p><span class="audio-time caption"><strong>Prot:</strong> On this note, <code>C-x C-x</code>.</span> <span class="audio-time caption">By default, it’s <code>exchange-point-and-mark</code>.</span> <span class="audio-time caption">Which, if your cursor is here and where you</span> <span class="audio-time caption">started is up there, it moves the cursor up there</span> <span class="audio-time caption">and now where you started is down at that point.</span> <span class="audio-time caption">You can expand the region both ways.</span> <span class="audio-time caption">You can keep switching and expanding.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  I have never thought about using it</span> <span class="audio-time caption">for expanding the region.</span> <span class="audio-time caption">I usually just use it to confirm that, yes, I am</span> <span class="audio-time caption">actually selecting the parts that I meant to</span> <span class="audio-time caption">select.</span> <span class="audio-time caption">Because by the time, of course, I've found the</span> <span class="audio-time caption">thing that I wanted to end the region with, I've</span> <span class="audio-time caption">forgotten or I'm not entirely sure I have the</span> <span class="audio-time caption">right start.</span> <span class="audio-time caption">So I was using <code>C-x C-x</code> to</span> <span class="audio-time caption">quickly verify and have everything nicely</span> <span class="audio-time caption">highlighted.</span> <span class="audio-time caption">But expanding the region, yeah, that's a thing</span> <span class="audio-time caption">you can do with it.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  Yeah, yeah, of course.</span> <span class="audio-time caption">Now it's obvious, right?</span> <span class="audio-time caption">But it's something that you may notice by</span> <span class="audio-time caption">mistake, by accident.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  [interrupted by life]</span> <span class="audio-time caption">@charliemcmackin4859 says, "I love that you can make those</span> <span class="audio-time caption">marking tricks part of a keyboard macro."</span> <p></p><div class="transcript-heading"><span class="audio-time">20:55</span> <strong>Popping to marks - going back to where you were</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong> Oh, the other thing I want to say with marks is</span> <span class="audio-time caption">you can also navigate by mark.</span> <span class="audio-time caption">C-x SPC?</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  <code>C-u C-SPC</code>.</span> <span class="audio-time caption">I think it’s <code>pop-to-mark</code> is the concept.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Popping to mark.</span> <span class="audio-time caption">We'll just go with the concept because people can</span> <span class="audio-time caption">search for the key binding.</span> <span class="audio-time caption">Which basically means for all the places where</span> <span class="audio-time caption">you were before you went off searching for</span> <span class="audio-time caption">something else or doing some other command,</span> <span class="audio-time caption">you can go back to those places in sequence.</span> <span class="audio-time caption">I think there are even some commands to let</span> <span class="audio-time caption">you easily navigate through all the places</span> <span class="audio-time caption">you've been previously.</span> <span class="audio-time caption">That is a thing that you can do with Emacs</span> <span class="audio-time caption">built-ins.</span> <span class="audio-time caption">It's called popping the mark.</span> <span class="audio-time caption">It lets you revisit places.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  Yeah, yeah.</span> <span class="audio-time caption">Another point related to this and also related to</span> <span class="audio-time caption">yank that we said earlier...</span> <p></p><div class="transcript-heading"><span class="audio-time">21:49</span> <strong>Selecting what you just pasted</strong></div><p></p><span class="audio-time caption"><strong>Prot:</strong> Imagine you have copied something and you are</span> <span class="audio-time caption">pasting it now in your Emacs.</span> <span class="audio-time caption">Then what you want to do is select it, maybe</span> <span class="audio-time caption">to do something with it, such as to</span> <span class="audio-time caption">make it all up case or whatever, right?</span> <span class="audio-time caption">Instead of selecting it manually, you can just</span> <span class="audio-time caption">do <code>C-x C-x</code>. Because when you paste</span> <span class="audio-time caption">something or when you do I search or whatever, it</span> <span class="audio-time caption">has the effect of updating the mark.</span> <span class="audio-time caption">Then you can work with that.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Yeah, that one I use fairly often.</span> <span class="audio-time caption">Also, that way, you can easily</span> <span class="audio-time caption">see what it highlights, the part that you've just</span> <span class="audio-time caption">pasted, and then you can do your other</span> <span class="audio-time caption">replacements or uppercasing or whatever else</span> <span class="audio-time caption">to it.</span> <p></p><div class="transcript-heading"><span class="audio-time">22:33</span> <strong>Indenting pasted or selected text with indent-rigidly</strong></div><p></p><span class="audio-time caption"><strong>Prot:</strong>  The nice part for this is the</span> <span class="audio-time caption"><code>indent-rigidly</code>,</span> <span class="audio-time caption"><code>C-x C-i</code> by default, where you can now</span> <span class="audio-time caption">have a region of text including an implicit</span> <span class="audio-time caption">region between mark and point, and you just shift</span> <span class="audio-time caption">it around, literally left or right.</span> <span class="audio-time caption">Try it.</span> <span class="audio-time caption">It's very nice.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  <code>C-x C-i</code>.</span> <span class="audio-time caption">I think you can even use the arrow keys to</span> <span class="audio-time caption">move things,</span> <span class="audio-time caption">so you can just nudge it until it looks right,</span> <span class="audio-time caption">which is great because sometimes, when you paste</span> <span class="audio-time caption">things, the indentation isn't the same</span> <span class="audio-time caption">as all of the rest of your stuff.</span> <span class="audio-time caption">You might want to put it all the way into an</span> <span class="audio-time caption">Org list or whatever else, code block, whatever.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  Okay.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  So <code>C-x C-x</code>, very handy</span> <span class="audio-time caption">even after you paste.</span> <p></p><div class="transcript-heading"><span class="audio-time">23:24</span> <strong>Popping to mark after xref or imenu</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong> Oh, @hmelman also points out the fact that</span> <span class="audio-time caption">things like xref or imenu push the last location</span> <span class="audio-time caption">before jumping means popping the mark is an easy</span> <span class="audio-time caption">way to go back from various navigation mechanisms.</span> <span class="audio-time caption">In general, if you have navigated away from</span> <span class="audio-time caption">something using some magical Emacs command that</span> <span class="audio-time caption">has taken you far from where you are, you can</span> <span class="audio-time caption">always find your way back home or back to where</span> <span class="audio-time caption">you were by popping the mark.</span> <span class="audio-time caption">I think there's even a distinction between</span> <span class="audio-time caption">popping the mark in your buffer</span> <span class="audio-time caption">versus popping your global mark.</span> <span class="audio-time caption">You can go to a different buffer that you were</span> <span class="audio-time caption">just in if you wanted to.</span> <p></p><div class="transcript-heading"><span class="audio-time">24:05</span> <strong>Adding other packages like consult</strong></div><p></p><span class="audio-time caption"><strong>Prot:</strong>  Very nice.</span> <span class="audio-time caption">Many of these are also augmented by</span> <span class="audio-time caption">packages. When you install a package, it doesn't</span> <span class="audio-time caption">introduce completely new functionality. It adds to</span> <span class="audio-time caption">existing one. For example, the consult package,</span> <span class="audio-time caption">which is very useful, very nice, has something to</span> <span class="audio-time caption">do with what we just mentioned. Like,</span> <span class="audio-time caption">navigating the mark in a visual way,</span> <span class="audio-time caption">so you get to see it.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  @hmelman points out that local and global</span> <span class="audio-time caption">marks are useful to navigate through.</span> <span class="audio-time caption">Check out all these other packages for adding</span> <span class="audio-time caption">extra functionality around that.</span> <p></p><div class="transcript-heading"><span class="audio-time">24:44</span> <strong>Tip about indicating isearch wrapping</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong> @matthewjorgensen9115 says,</span> <span class="audio-time caption">"thinking about isearch wrapping</span> <span class="audio-time caption">around search,</span> <span class="audio-time caption">gwhen you get to the bottom of your file, when</span> <span class="audio-time caption">you're isearching and there's no other matches to</span> <span class="audio-time caption">be found, it will by default wrap you around to</span> <span class="audio-time caption">the beginning of the file so you can keep</span> <span class="audio-time caption">searching from there."</span> <span class="audio-time caption">Matthew says you can either have scroll to</span> <span class="audio-time caption">position to know the direction</span> <span class="audio-time caption">(it also indicates the position in your mode line),</span> <span class="audio-time caption">or you can have your mode line flash to see it</span> <span class="audio-time caption">move from last to first.</span> <span class="audio-time caption">I don't have that configured.</span> <span class="audio-time caption">I should look into how to get that configured</span> <span class="audio-time caption">because it's like all these little things, right?</span> <span class="audio-time caption">But sometimes you don't need</span> <span class="audio-time caption">to make a big navigational jump.</span> <span class="audio-time caption">You just need to move forward by a little bit.</span> <p></p><div class="transcript-heading"><span class="audio-time">25:26</span> <strong>Navigating by sentence or s-expression</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong> Emacs has built-in shortcuts for navigating</span> <span class="audio-time caption">by expression, maybe things inside the</span> <span class="audio-time caption">parentheses or things inside the quotes, as well</span> <span class="audio-time caption">as natural language shortcuts like navigating by</span> <span class="audio-time caption">word or by sentence.</span> <span class="audio-time caption">Those are some very useful built-ins that are</span> <span class="audio-time caption">well worth learning the keyboard shortcuts for.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  Yes, indeed.</span> <span class="audio-time caption">Of course, we call them</span> <span class="audio-time caption">S-expressions and the terminology of the commands</span> <span class="audio-time caption">alludes to Lisp, but they work in other</span> <span class="audio-time caption">programming languages as well.</span> <span class="audio-time caption">For example, there is the</span> <span class="audio-time caption"><code>forward-sexp</code>, but it works in other languages</span> <span class="audio-time caption">which don't have this Lispy syntax.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  So if you skipped over that part of</span> <span class="audio-time caption">the tutorial or the manual, go back and read it</span> <span class="audio-time caption">because it can save you some time.</span> <span class="audio-time caption">In a pinch, it will also help you</span> <span class="audio-time caption">make sure that your parentheses are matched up</span> <span class="audio-time caption">correctly and you go to where you expect them to go.</span> <span class="audio-time caption">There are other ways to make it easier to match</span> <span class="audio-time caption">up parentheses or braces or brackets or quotes</span> <span class="audio-time caption">like [ <code>show-paren-mode</code> ] or whatever.</span> <span class="audio-time caption">Sometimes I just go forward and back to see</span> <span class="audio-time caption">whether I end up in the right place.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  A small trick here,</span> <span class="audio-time caption">if you are writing specifically Emacs Lisp,</span> <span class="audio-time caption">there is a very common mistake of adding</span> <span class="audio-time caption">an extra parenthesis, and it says "end of</span> <span class="audio-time caption">file during parsing", or one less parenthesis, what</span> <span class="audio-time caption">you can do with a combination of keyboard macros...</span> <span class="audio-time caption">You go to the beginning</span> <span class="audio-time caption">and you do <code>C-M-e</code> to go to the end of the defun,</span> <span class="audio-time caption">and then, in a keyboard macro, you keep doing that.</span> <span class="audio-time caption">Next, next, next, end, end, end, right? Until it stops,</span> <span class="audio-time caption">and you know where your error is.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Oh, and I should tell people, if</span> <span class="audio-time caption">you give the <code>execute-kbd-macro</code> a negative</span> <span class="audio-time caption">argument, it'll run until error.</span> <span class="audio-time caption">So you just do that</span> <span class="audio-time caption">and it'll drop you where it ends.</span> <span class="audio-time caption">You don’t have to manually press <code>e</code> 500 times.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  Exactly.</span> <span class="audio-time caption">The "run until error" happens when you are in a</span> <span class="audio-time caption">narrowed region as well.</span> <span class="audio-time caption">Error here means end of region, end of buffer.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  I should point out in the specific</span> <span class="audio-time caption">case where you're trying to hunt down a stray</span> <span class="audio-time caption">parenthesis, you should also just use</span> <span class="audio-time caption">check-parens, which will tell you.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  Of course.</span> <p></p><div class="transcript-heading"><span class="audio-time">27:45</span> <strong>Navigating to other errors</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong>  And for other errors</span> <span class="audio-time caption">not just limited to missing quotation marks or</span> <span class="audio-time caption">parentheses,</span> <span class="audio-time caption">it's well worth taking the time to set up</span> <span class="audio-time caption">flycheck or flymake or whatever error checking</span> <span class="audio-time caption">thing you want to use, because then you can</span> <span class="audio-time caption">navigate to the previous and next errors as</span> <span class="audio-time caption">easily as you would with keyboard shortcuts.</span> <span class="audio-time caption">If you get the hang of doing that, you can</span> <span class="audio-time caption">also use the same mental model to navigate through...</span> <span class="audio-time caption">If you're doing a keyword search with grep, then</span> <span class="audio-time caption">you can use the <code>next-error</code>, <code>previous-error</code>
to</span> <span class="audio-time caption">also go to just the next match or the previous match.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  That's very useful.</span> <p></p><div class="transcript-heading"><span class="audio-time">28:29</span> <strong>Tags</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong>  I am not using tags nearly as much</span> <span class="audio-time caption">as I probably should for navigating symbols.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  Tags, yeah, in the context of</span> <span class="audio-time caption">programming.</span> <span class="audio-time caption">Me, I haven't used that, no.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Oh, yeah?</span> <span class="audio-time caption">I guess because you primarily work with</span> <span class="audio-time caption">Emacs Lisp, it's easy enough</span> <span class="audio-time caption">to find the definition from there.</span> <p></p><div class="transcript-heading"><span class="audio-time">28:47</span> <strong>Imenu</strong></div><p></p><span class="audio-time caption"><strong>Prot:</strong>  But imenu is the other one, along those lines.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  That's interesting.</span> <span class="audio-time caption">You don't use the menu bar, but you use imenu.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  Yes, imenu is useful because, of</span> <span class="audio-time caption">course, it's with completion.</span> <span class="audio-time caption">Now, I should say here, of course, that the</span> <span class="audio-time caption">default imenu has this concept of going in steps,</span> <span class="audio-time caption">but you can flatten the list, which is more</span> <span class="audio-time caption">interesting for the purpose of completion.</span> <span class="audio-time caption">I believe what I'm saying is the case, but I</span> <span class="audio-time caption">don't remember anymore.</span> <span class="audio-time caption">But you can have a flattened list, at which point</span> <span class="audio-time caption">you navigate the file with completion.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  I should try that because I really</span> <span class="audio-time caption">like the way that Org, when you're navigating by</span> <span class="audio-time caption">the outline, you can also configure it to flatten</span> <span class="audio-time caption">the list so you don't have to complete the</span> <span class="audio-time caption">heading and the next setting and all that stuff.</span> <span class="audio-time caption">@hmelman says you don't actually need flymake for the</span> <span class="audio-time caption">error navigation thing.</span> <span class="audio-time caption">You can just use <code>next-error</code></span> <span class="audio-time caption">and <code>previous-error</code> which works with</span> <span class="audio-time caption"><code>compile</code> and <code>grep</code> and <code>occur</code></span> <span class="audio-time caption">and a bunch of other things that have the</span> <span class="audio-time caption">same convention.</span> <span class="audio-time caption">So yes, if you use the <code>M-x compile</code> command to</span> <span class="audio-time caption">run whatever your compilation step is, it will</span> <span class="audio-time caption">parse the output of many compilation systems,</span> <span class="audio-time caption">programs, and it will let you jump to the next</span> <span class="audio-time caption">error.</span> <span class="audio-time caption">It will also even show you the errors, I think.</span> <span class="audio-time caption">Anyway, so you don't need flymake.</span> <span class="audio-time caption">Flymake just gives you the squiggly underlines.</span> <span class="audio-time caption">But you can use <code>next-error</code> right away.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  Yeah, yeah, yeah.</span> <span class="audio-time caption">Flymake is more narrow.</span> <span class="audio-time caption">Yeah, correct.</span> <p></p><div class="transcript-heading"><span class="audio-time">30:19</span> <strong>Projects</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong>  I think projects and project-based</span> <span class="audio-time caption">navigation is another big chunk of Emacs built-in</span> <span class="audio-time caption">functionality that is useful for people who have</span> <span class="audio-time caption">a hard time finding their way around.</span> <span class="audio-time caption">You don't have to manually find each file.</span> <span class="audio-time caption">You can set up shortcuts so you can say, I want</span> <span class="audio-time caption">to go to this project.</span> <span class="audio-time caption">Then from within this project, I can find a</span> <span class="audio-time caption">file very easily.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  This is indeed very</span> <span class="audio-time caption">powerful. The thing is you don't have to also</span> <span class="audio-time caption">think in terms of the structure of the project,</span> <span class="audio-time caption">like the tree structure of the project, because if</span> <span class="audio-time caption">you find the file in the project, it</span> <span class="audio-time caption">will flatten the structure for you, so then you</span> <span class="audio-time caption">use completion to find it or find the directory</span> <span class="audio-time caption">where something is. Of course, you can still</span> <span class="audio-time caption">use the tree view as well.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  This is great because</span> <span class="audio-time caption">for example, in Java projects, the</span> <span class="audio-time caption">directory structure gets very deep because they</span> <span class="audio-time caption">have to be their domain name and</span> <span class="audio-time caption">package names and all that stuff.</span> <span class="audio-time caption">Just have either project or projectile index all</span> <span class="audio-time caption">of your files for you, and then you can jump to a</span> <span class="audio-time caption">file by name anywhere in your structure.</span> <span class="audio-time caption">You can tell it also to ignore certain files,</span> <span class="audio-time caption">which is handy so that you don't have to go into</span> <span class="audio-time caption">your node-modules.</span> <span class="audio-time caption">That would be silly.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  Yeah, that would be a nightmare.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Do we have basically the Emacs</span> <span class="audio-time caption">built-ins for finding your way around well</span> <span class="audio-time caption">covered here, or other other recommendations that</span> <span class="audio-time caption">people should go check out?</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  These are already very useful, yeah.</span> <span class="audio-time caption">Most of these, if not all, are augmented by packages.</span> <span class="audio-time caption">So the core functionality is there, and then you</span> <span class="audio-time caption">can do more stuff with them.</span> <p></p><div class="transcript-heading"><span class="audio-time">32:10</span> <strong>Putting projects in tabs or frames</strong></div><p></p><span class="audio-time caption"><strong>Prot:</strong> For example, with projects, you may want to have</span> <span class="audio-time caption">an arrangement where you put them in separate</span> <span class="audio-time caption">tabs, and then you use a package like tabspaces</span> <span class="audio-time caption">so that each tab has its own buffer list, or</span> <span class="audio-time caption">my package beframe so that you put them in</span> <span class="audio-time caption">separate frames.</span> <span class="audio-time caption">Each frame has its own buffer list,</span> <span class="audio-time caption">so that basically when you search for buffers,</span> <span class="audio-time caption">you only see those related to the project.</span> <p></p><div class="transcript-heading"><span class="audio-time">32:35</span> <strong>Tabs</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong>  I am not using tabs nearly as much</span> <span class="audio-time caption">as I probably could,</span> <span class="audio-time caption">so that is one of my underappreciated Emacs</span> <span class="audio-time caption">built-ins here.</span> <span class="audio-time caption">I'm getting the sense that people use tabs to</span> <span class="audio-time caption">say, okay, this is the set of windows related to</span> <span class="audio-time caption">managing my mail, or this is a set of tabs</span> <span class="audio-time caption">related to this project.</span> <span class="audio-time caption">This is a set of windows related to this project,</span> <span class="audio-time caption">or this is a set of windows related to managing</span> <span class="audio-time caption">my notes about something.</span> <span class="audio-time caption">Is that what you use tabs for?</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  I seldom use them.</span> <span class="audio-time caption">I use them specifically only within the context</span> <span class="audio-time caption">of popping into a Magit interface.</span> <span class="audio-time caption">So I have my project that I'm working on.</span> <span class="audio-time caption">Let's say it's split in three windows.</span> <span class="audio-time caption">And then I want to leave everything intact and</span> <span class="audio-time caption">just go into Magit to do some Git operation.</span> <span class="audio-time caption">I configure <code>display-buffer-alist</code></span> <span class="audio-time caption">so when I do Emacs Magit,</span> <span class="audio-time caption">magit-status or whatever, it goes in a new tab.</span> <span class="audio-time caption">Then I leave my work where it is.</span> <span class="audio-time caption">I do the git thing,</span> <span class="audio-time caption">then I quit those. I'm back to my layout.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  I know you're a</span> <span class="audio-time caption">good advocate of checking out</span> <span class="audio-time caption">display-buffer-alist and all the wonderful</span> <span class="audio-time caption">things it can do.</span> <span class="audio-time caption">I should definitely look into having it set up a</span> <span class="audio-time caption">tab because that sounds a lot nicer than trying</span> <span class="audio-time caption">to remember, okay, I need to save my window</span> <span class="audio-time caption">configuration to register and then do this thing.</span> <span class="audio-time caption">I have it set up actually so that I can</span> <span class="audio-time caption"><code>winner-undo</code> in order to get back to my previous</span> <span class="audio-time caption">configuration.</span> <span class="audio-time caption">But of course, if I need to flip back and forth</span> <span class="audio-time caption">between two different views, like Magit and</span> <span class="audio-time caption">my project code, then a tab would work much</span> <span class="audio-time caption">better for this purpose, I think.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  Yes, and it scales better as well,</span> <span class="audio-time caption">like if you need to have three tabs or whatever.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Or a new frame.</span> <span class="audio-time caption">But sometimes managing frames gets a little</span> <span class="audio-time caption">annoying too.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  Of course, of course.</span> <span class="audio-time caption">There are pros and cons.</span> <p></p><div class="transcript-heading"><span class="audio-time">34:41</span> <strong>Navigating frames</strong></div><p></p><span class="audio-time caption"><strong>Prot:</strong> Speaking of frames, one nice thing is that there</span> <span class="audio-time caption">is completion again to select frames.</span> <span class="audio-time caption">So I forget how it's called.</span> <span class="audio-time caption">[ <code>select-frame</code> ], I think, is the command.</span> <span class="audio-time caption">If you have lots of frames and you don't know</span> <span class="audio-time caption">where they are, you can use completion for that.</span> <span class="audio-time caption">If you want, you can also name frames.</span> <span class="audio-time caption">I believe it’s rename frame. [<code>set-frame-name</code>]</span> <span class="audio-time caption">I forget now the command.</span> <span class="audio-time caption">Basically, you can give it a specific name</span> <span class="audio-time caption">rather than it changing the name all the time.</span> <span class="audio-time caption">So you can say, OK, this is my super</span> <span class="audio-time caption">important note for our livestream, right?</span> <span class="audio-time caption">That's the frame for you.</span> <span class="audio-time caption">Now you can find it.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  I should look into that.</span> <span class="audio-time caption">I also underutilize frames because for the most</span> <span class="audio-time caption">part, I have a keyboard shortcut like Super 1</span> <span class="audio-time caption">which jumps back to Emacs, raises my</span> <span class="audio-time caption">Emacs window.</span> <span class="audio-time caption">But it doesn't work so well if I have multiple</span> <span class="audio-time caption">Emacs window, like multiple Emacs frames.</span> <span class="audio-time caption">If I can figure out how to get mentally</span> <span class="audio-time caption">through that or if I switch to EXWM as my window</span> <span class="audio-time caption">manager,</span> <span class="audio-time caption">then I'm sure that managing multiple Emacs frames</span> <span class="audio-time caption">will be a lot easier.</span> <span class="audio-time caption">But at least</span> <span class="audio-time caption">tabs, I can probably use within that one frame in</span> <span class="audio-time caption">order to manage different windows.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  I would say tabs is the first thing</span> <span class="audio-time caption">you want to check.</span> <span class="audio-time caption">Frames is a little bit more... You have to change</span> <span class="audio-time caption">your mental model a little bit.</span> <p></p><div class="transcript-heading"><span class="audio-time">36:07</span> <strong>These navigation shortcuts work for prose, too</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong>  @hmelman has one more tip to</span> <span class="audio-time caption">include in this section on finding your way</span> <span class="audio-time caption">around.</span> <span class="audio-time caption">You can use these S-expression commands</span> <span class="audio-time caption">in prose too.</span> <span class="audio-time caption">Like for example, <code>C-M-u</code> or
<code>backwards-up-list</code></span> <span class="audio-time caption">moves you out of a quote or a parenthesis</span> <span class="audio-time caption">and then you can <code>C-M-e</code> to go to the end of it.</span> <span class="audio-time caption">So even if you're writing, for example, a novel,</span> <span class="audio-time caption">and you're saying, okay, I want to</span> <span class="audio-time caption">get out of this quote and go to the next sentence,</span> <span class="audio-time caption">you can either isearch to the start of it,</span> <span class="audio-time caption">or you can go up out of the quote and then</span> <span class="audio-time caption">go to the end of the quote.</span> <span class="audio-time caption">Also very handy to learn the commands for killing</span> <span class="audio-time caption">an S expression [ <code>kill-sexp</code> ],</span> <span class="audio-time caption">which again also works with</span> <span class="audio-time caption">other stuff like quotes or parentheses, because</span> <span class="audio-time caption">then you can copy and paste things or you can</span> <span class="audio-time caption">kill it.</span> <span class="audio-time caption">You don't have to paste it back.</span> <span class="audio-time caption">It's just you delete it and then you type</span> <span class="audio-time caption">something else in.</span> <span class="audio-time caption">It's fine.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  Exactly, exactly.</span> <span class="audio-time caption">And one of those is the <code>mark-sexp</code>, which</span> <span class="audio-time caption">is very useful.</span> <p></p><div class="transcript-heading"><span class="audio-time">37:09</span> <strong>follow-mode</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong>  Oh yeah, oh yeah.</span> <span class="audio-time caption">And <span class="citation">@matthewjorgensen9115</span> shares:
<code>follow-mode</code> allows the same</span> <span class="audio-time caption">file with multiple frames like a book.</span> <span class="audio-time caption">So follow mode can work with two, three or more</span> <span class="audio-time caption">windows.</span> <span class="audio-time caption">You have an ultra wide, right?</span> <span class="audio-time caption">So like, okay, you can have several columns</span> <span class="audio-time caption">following the same file and you can scroll and</span> <span class="audio-time caption">all of them will scroll in sync.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  Yeah, yeah.</span> <span class="audio-time caption">It's quite nice.</span> <span class="audio-time caption">Quite nice.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  I forget, does follow mode work</span> <span class="audio-time caption">with different files?</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  With different files?</span> <span class="audio-time caption">I don't think so.</span> <span class="audio-time caption">Like kind of a scroll lock for all windows?</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Yeah, yeah, yeah.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  I don't know.</span> <span class="audio-time caption">I don't think so.</span> <span class="audio-time caption">I haven't tried it.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Worth looking into. [<code>scroll-all-mode</code>]</span> <p></p><div class="transcript-heading"><span class="audio-time">37:50</span> <strong>Ediff</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong> If you do find yourself needing to compare one</span> <span class="audio-time caption">file with another manually, then maybe</span> <span class="audio-time caption">like ediff?</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  Ediff would do that.</span> <span class="audio-time caption">You would have them side by side.</span> <span class="audio-time caption">But the thing with Ediff is that you don't get a</span> <span class="audio-time caption">scroll lock for both.</span> <span class="audio-time caption">It's only navigation through the differences.</span> <span class="audio-time caption">So that wouldn't be exactly that.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  For the purposes of</span> <span class="audio-time caption">comparing, Ediff will let you compare two files,</span> <span class="audio-time caption">but you can even use it to compare two buffers.</span> <span class="audio-time caption">However, Prot does have some recommendations in</span> <span class="audio-time caption">the one on the defaults that you shared before on</span> <span class="audio-time caption">how to make Ediff more manageable.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  Yeah, I think by default it's not</span> <span class="audio-time caption">intuitive, because by default, when you do Ediff</span> <span class="audio-time caption">without any configuration, it will display its</span> <span class="audio-time caption">panel in a separate frame.</span> <span class="audio-time caption">If you have never used many frames, that's</span> <span class="audio-time caption">already your first problem.</span> <span class="audio-time caption">Like you don't even know what happened.</span> <span class="audio-time caption">The second problem is that the layout will be one</span> <span class="audio-time caption">above the other, which depending on your screen,</span> <span class="audio-time caption">you have like a wide screen, so it's not as easy</span> <span class="audio-time caption">of a layout.</span> <span class="audio-time caption">Then you have to figure out where the other</span> <span class="audio-time caption">frame with the panel is.</span> <span class="audio-time caption">Basically two variables where you change them</span> <span class="audio-time caption">and you have the panel at the bottom, the control</span> <span class="audio-time caption">panel and then file A here, file B there.</span> <span class="audio-time caption">And of course you can do it with three files</span> <span class="audio-time caption">as well.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  I will find it and put it in the</span> <span class="audio-time caption">show notes.</span> <span class="audio-time caption">Matthew also points out the following also works</span> <span class="audio-time caption">with <code>centered-cursor-mode</code> [(it’s a package)],</span> <span class="audio-time caption">which will keep the</span> <span class="audio-time caption">cursor position in the middle of the frame.</span> <span class="audio-time caption">So I can't remember whether there's also like a</span> <span class="audio-time caption">scroll lock or whatever.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  <code>scroll-lock-mode</code>.</span> <span class="audio-time caption">Yeah, there is `scroll-lock mode.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Or there was another</span> <span class="audio-time caption">Emacs built-in that someone mentioned that</span> <span class="audio-time caption">scrolls it one line at a time, keeping it</span> <span class="audio-time caption">centered, I guess, which the person found very</span> <span class="audio-time caption">useful because their cat was sitting on their</span> <span class="audio-time caption">laptop.</span> <span class="audio-time caption">So moral lesson is: learn about the Emacs built-in</span> <span class="audio-time caption">because you never know when a small mammal will</span> <span class="audio-time caption">be obscuring half of your screen.</span> <span class="audio-time caption">You can still use Emacs.</span> <span class="audio-time caption">Which actually is an interesting segue into this</span> <span class="audio-time caption">thing about discoverability because Emacs is</span> <span class="audio-time caption">quite unlike many other editors.</span> <span class="audio-time caption">It is very well documented and if you can figure</span> <span class="audio-time caption">out how to navigate and find that documentation</span> <span class="audio-time caption">and even how to make this fun for you, then you</span> <span class="audio-time caption">can do all sorts of interesting things with it.</span> <span class="audio-time caption">Okay, so self-documentation.</span> <span class="audio-time caption">I love telling people, okay, you can just press</span> <span class="audio-time caption"><code>C-h k</code> or <code>describe-key</code> to describe
anything.</span> <span class="audio-time caption">You can <code>C-h f</code> any function.</span> <span class="audio-time caption">You can, you know, <code>C-h v</code> any variable.</span> <span class="audio-time caption"><code>describe-</code> whatever is great.</span> <span class="audio-time caption">Of course, adding <code>C-h</code> to the end of the</span> <span class="audio-time caption">keyboard shortcut that you've started but you've</span> <span class="audio-time caption">forgotten how to finish, especially if you've</span> <span class="audio-time caption">turned on <code>which-key</code> mode,</span> <span class="audio-time caption">is great for listing the actual shortcuts that</span> <span class="audio-time caption">start with that sequence.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  And even without <code>which-key</code>, it will</span> <span class="audio-time caption">put all those shortcuts in a Help buffer,</span> <span class="audio-time caption">and it will show the key and the name of the</span> <span class="audio-time caption">command.</span> <span class="audio-time caption">Of course, you can click on the command to</span> <span class="audio-time caption">read about it.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Someday I think it would be amazing</span> <span class="audio-time caption">if Emacs comes with a completion interface that's</span> <span class="audio-time caption">easy for people to understand and get started with,</span> <span class="audio-time caption">but in the meantime, if you don't already have</span> <span class="audio-time caption">completion set up, that is well worth taking the</span> <span class="audio-time caption">time to figure out.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  Yeah, yeah.</span> <span class="audio-time caption">The built-in one has improved tremendously.</span> <span class="audio-time caption">I mean minibuffer.el here</span> <span class="audio-time caption">has improved tremendously over the various recent</span> <span class="audio-time caption">versions.</span> <span class="audio-time caption">But you still need to be aware of all the user</span> <span class="audio-time caption">options to configure it.</span> <span class="audio-time caption">So to get, for example, a single column view</span> <span class="audio-time caption">instead of a grid with 100 options...</span> <span class="audio-time caption">That requires some effort.</span> <span class="audio-time caption">Out of the box, if you really want something</span> <span class="audio-time caption">that is built into Emacs and does completion in a</span> <span class="audio-time caption">way that is fairly easy to understand, it would</span> <span class="audio-time caption">be icomplete-vertical-mode or fido or</span> <span class="audio-time caption">fido-vertical-mode.</span> <p></p><div class="transcript-heading"><span class="audio-time">42:12</span> <strong>Calling functions by name</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong>  Another thing that Emacs does</span> <span class="audio-time caption">differently that might be good for people to</span> <span class="audio-time caption">learn about is that in Emacs, it is totally okay</span> <span class="audio-time caption">to not remember the keyboard shortcuts for</span> <span class="audio-time caption">everything or not use the menus for everything,</span> <span class="audio-time caption">because not everything will fit in the menus</span> <span class="audio-time caption">either.</span> <span class="audio-time caption">If you kind of remember the name of the function,</span> <span class="audio-time caption">you can use M-x and possibly completion to go</span> <span class="audio-time caption">run that function,</span> <span class="audio-time caption">which is helpful because sometimes knowing the</span> <span class="audio-time caption">words to call a function is a lot easier to</span> <span class="audio-time caption">remember than remembering the shortcut for it.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  Exactly.</span> <span class="audio-time caption">And I would say completion...</span> <p></p><div class="transcript-heading"><span class="audio-time">42:52</span> <strong>Completion</strong></div><p></p><span class="audio-time caption"><strong>Prot:</strong> If you have to configure one part of Emacs,</span> <span class="audio-time caption">it's completion.</span> <span class="audio-time caption">If you improve that part of it, it will help you</span> <span class="audio-time caption">everywhere.</span> <span class="audio-time caption">Like we were saying earlier about bookmarks, it</span> <span class="audio-time caption">helps you there.</span> <span class="audio-time caption">The kill-ring, it helps you there.</span> <span class="audio-time caption">Finding files, it helps you there.</span> <span class="audio-time caption">Switching to buffers and so on.</span> <span class="audio-time caption">Like what we are now talking about.</span> <span class="audio-time caption">It's always useful.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  When you set up a completion, also</span> <span class="audio-time caption">learn how your favorite completion system lets</span> <span class="audio-time caption">you put in things that look like they should</span> <span class="audio-time caption">match something on the list, but you actually</span> <span class="audio-time caption">want just the partial part or just the blank part.</span> <span class="audio-time caption">For example, in some systems, you press</span> <span class="audio-time caption"><code>M-RET</code> or <code>M-p</code> to send what you already
have</span> <span class="audio-time caption">there instead of selecting one of the completion</span> <span class="audio-time caption">options.</span> <span class="audio-time caption">This is helpful because sometimes you'll want</span> <span class="audio-time caption">to name a file something that is a substring of</span> <span class="audio-time caption">another file and you want to be able to say,</span> <span class="audio-time caption">yeah, that is actually what I meant, not the</span> <span class="audio-time caption">completion part.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  Yeah, yeah.</span> <span class="audio-time caption">I think that's the only rough edge with most of</span> <span class="audio-time caption">those, yeah.</span> <span class="audio-time caption">Where you have to be mindful of that or, you</span> <span class="audio-time caption">know, I have to select the prompt or I have to</span> <span class="audio-time caption">type a special key for this edge case.</span> <span class="audio-time caption">Yeah.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Once you get that sorted out and</span> <span class="audio-time caption">you've drilled it into your fingers, it's very,</span> <span class="audio-time caption">very helpful to have completion sorted out.</span> <p></p><div class="transcript-heading"><span class="audio-time">44:13</span> <strong>Manuals</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong> Emacs also comes with extensive manuals.</span> <span class="audio-time caption">You like to write very thorough manuals for your</span> <span class="audio-time caption">packages, which I also appreciate.</span> <span class="audio-time caption">Flipping through manuals for fun is something</span> <span class="audio-time caption">that we've discussed in previous...</span> <span class="audio-time caption">This is such a great practice.</span> <span class="audio-time caption">You learn something new every day.</span> <span class="audio-time caption">I was going through the Emacs manual in</span> <span class="audio-time caption">preparation for this conversation and I was just</span> <span class="audio-time caption">highlighting things that I need to dig into.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  It's very useful and again to point</span> <span class="audio-time caption">out completion.</span> <span class="audio-time caption"><code>C-h R</code> is how you can search for the</span> <span class="audio-time caption">manual of a package.</span> <span class="audio-time caption">Like for example, I'm interested in Org.</span> <span class="audio-time caption"><code>C-h R</code>, Org.</span> <span class="audio-time caption">I find Org from anywhere, right?</span> <span class="audio-time caption"><code>C-h R</code> and then I will search for</span> <span class="audio-time caption">something else, right?</span> <span class="audio-time caption">Elisp, for example, to go to the Emacs Lisp</span> <span class="audio-time caption">reference manual.</span> <span class="audio-time caption">Again, very useful.</span> <span class="audio-time caption">From inside the manuals, <code>g</code> to go to a</span> <span class="audio-time caption">chapter, also known as a node, <code>i</code> to go to a</span> <span class="audio-time caption">topic, an index, and <code>m</code> if you want, but <code>g</code>
and <code>i</code>.</span> <span class="audio-time caption">Just think of <code>g</code> and <code>i</code>. Very, very
useful.</span> <span class="audio-time caption"><code>m</code> is also useful to navigate the menu of the</span> <span class="audio-time caption">current node.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  I use <code>s</code> also for search.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  And there's for research</span> <span class="audio-time caption">throughout, yes.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Yes.</span> <span class="audio-time caption">I have not been using <code>C-h R</code>.</span> <span class="audio-time caption">I have been using <code>C-h i</code> to look at the whole</span> <span class="audio-time caption">list of info manuals and then using <code>m</code> or isearch</span> <span class="audio-time caption">like a newbie.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  That works.</span> <span class="audio-time caption">The problem with that is that if you have already</span> <span class="audio-time caption">gone into a manual,</span> <span class="audio-time caption"><code>C-h i</code> will take you back to that manual.</span> <span class="audio-time caption">So you have to click it and then start again.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Okay.</span> <span class="audio-time caption">Alright.</span> <span class="audio-time caption">Well, I'm learning new things.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  Nice.</span> <p></p><div class="transcript-heading"><span class="audio-time">45:57</span> <strong>Menus</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong>  Okay, you mentioned you are not a</span> <span class="audio-time caption">fan of... you don't use the menus and I know a</span> <span class="audio-time caption">lot of people...</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  But I appreciate that.</span> <span class="audio-time caption">And in one of my... oh, in a couple</span> <span class="audio-time caption">of my packages I have menu entry.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Yeah, and I know a lot of people</span> <span class="audio-time caption">turn the menu bar off in their</span> <span class="audio-time caption">"this is how you configure Emacs" sort</span> <span class="audio-time caption">of tutorials.</span> <span class="audio-time caption">But if you are new to Emacs, and even if</span> <span class="audio-time caption">you're an intermediate user, I strongly</span> <span class="audio-time caption">recommend, sacrificing that tiny sliver</span> <span class="audio-time caption">of vertical space for the menu bar,</span> <span class="audio-time caption">because it's a great way to discover</span> <span class="audio-time caption">commands that are related to your</span> <span class="audio-time caption">particular major mode or other things.</span> <span class="audio-time caption">It's just fun to go through it and see what's</span> <span class="audio-time caption">been deemed worthy of including in one of those</span> <span class="audio-time caption">menus.</span> <span class="audio-time caption">There are some efforts now to get the right-click</span> <span class="audio-time caption">mouse menus to also have lots of interesting</span> <span class="audio-time caption">options, but definitely the menu bar at the top,</span> <span class="audio-time caption">which can also be accessed if you use F10 if you</span> <span class="audio-time caption">don't want to use the mouse.</span> <span class="audio-time caption">The menu bar is even working on terminal,</span> <span class="audio-time caption">which is nice.</span> <span class="audio-time caption">So yes, menu bar at the top has a lot of useful</span> <span class="audio-time caption">suggestions for discovering things.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  Yes, yes, excellent.</span> <span class="audio-time caption">The part you mentioned about key navigation,</span> <span class="audio-time caption">that's also good.</span> <span class="audio-time caption">You may be like, don't want to use</span> <span class="audio-time caption">the mouse.</span> <span class="audio-time caption">There you have it.</span> <span class="audio-time caption">You don't have...</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  And speaking of key navigation, if</span> <span class="audio-time caption">you press <code>C-h k</code>, which is <code>describe-key</code>,
it</span> <span class="audio-time caption">will work on menu items as well.</span> <span class="audio-time caption">If you're finding yourself always going to the</span> <span class="audio-time caption">menu to do this thing, sometimes the menu items</span> <span class="audio-time caption">are not named the same as their commands, but you</span> <span class="audio-time caption">can use <code>C-h k</code> to find out what that function</span> <span class="audio-time caption">is and what keyboard shortcuts it's bound to.</span> <span class="audio-time caption">Then you can call it with M-x directly, or</span> <span class="audio-time caption">you can memorize the keyboard shortcuts.</span> <p></p><div class="transcript-heading"><span class="audio-time">47:46</span> <strong>Automation - abbreviations</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong> Okay, shall we move on to automation,</span> <span class="audio-time caption">for which Emacs has a ton of built-in things?</span> <span class="audio-time caption">Using abbreviations and things like that is</span> <span class="audio-time caption">actually something I picked up from reading your</span> <span class="audio-time caption">config, I think, because you use abbreviations a lot.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  Yeah. Very nice. Very useful.</span> <span class="audio-time caption">Even for basic things.</span> <span class="audio-time caption">For example, I want to write, you know, my</span> <span class="audio-time caption">fancy French expressions, like, this is so</span> <span class="audio-time caption">déjà vu, you know?</span> <span class="audio-time caption">I want to have the accents correct.</span> <span class="audio-time caption">I just write <code>deja vu</code> with English, and then I</span> <span class="audio-time caption">have the French equivalent with all the fancy</span> <span class="audio-time caption">accents.</span> <span class="audio-time caption">Stuff like that you can do, like...</span> <span class="audio-time caption">something you keep misspelling the whole time you</span> <span class="audio-time caption">actually do it, right, something that is with an</span> <span class="audio-time caption">annoying spelling, like annoying capitalization</span> <span class="audio-time caption">like LaTeX. Nobody knows how that is written. You</span> <span class="audio-time caption">just write it latex, all lowercase, and then expand</span> <span class="audio-time caption">to whatever it should expand. This sort of thing</span> <span class="audio-time caption">is very useful. Of course, you can just have</span> <span class="audio-time caption">some short text which expands into very long</span> <span class="audio-time caption">text.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  We should also point out if you</span> <span class="audio-time caption">type something that is normally an abbreviation</span> <span class="audio-time caption">like LaTeX, but in this case you actually want to</span> <span class="audio-time caption">write the word latex, then how do you do the</span> <span class="audio-time caption">abbreviation without it being expanded into</span> <span class="audio-time caption">whatever that is?</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  Of course you would rather avoid</span> <span class="audio-time caption">that situation with your abbreviation. It wouldn't</span> <span class="audio-time caption">be like that, but otherwise you will have to undo.</span> <span class="audio-time caption">When you do SPC and it expands, you undo.</span> <span class="audio-time caption">That is a little bit annoying, for sure. But I</span> <span class="audio-time caption">would say, just make sure to have abbreviations</span> <span class="audio-time caption">that are not ordinary words.</span> <span class="audio-time caption">They are a little bit contrived, so you don't get</span> <span class="audio-time caption">false positives.</span> <span class="audio-time caption">A good use case here, like what I have in my</span> <span class="audio-time caption">configuration, like you can have your</span> <span class="audio-time caption">abbreviations behind a</span> <span class="audio-time caption">character such as the semicolon.</span> <span class="audio-time caption">Then of course it's very unlikely that you will</span> <span class="audio-time caption">have semicolon later.</span> <p></p><div class="transcript-heading"><span class="audio-time">49:56</span> <strong>Quoting the next character with C-q</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong>  The other thing that you could</span> <span class="audio-time caption">potentially do is use <code>C-q</code> to quote the next</span> <span class="audio-time caption">character literally.</span> <span class="audio-time caption">So here for example, I have <code>ot</code> expand to the</span> <span class="audio-time caption">current time, but if I say <code>ot</code> <code>C-q</code> SPC, this
helps.</span> <span class="audio-time caption">And in general, this idea of <code>C-q</code> to quote</span> <span class="audio-time caption">the next character is also useful in other places</span> <span class="audio-time caption">where you might, for example, need to add a</span> <span class="audio-time caption">literal new line to a search or something like that,</span> <span class="audio-time caption">or a literal tab.</span> <p></p><div class="transcript-heading"><span class="audio-time">50:31</span> <strong>Mapping abbreviations to code</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong> The other thing that I want to add to</span> <span class="audio-time caption">abbreviations here is your abbreviations are not</span> <span class="audio-time caption">limited to just text.</span> <span class="audio-time caption">You can use them to run things, which means you</span> <span class="audio-time caption">can use them to run things that expand to text,</span> <span class="audio-time caption">or I think you might even get away with using</span> <span class="audio-time caption">them to run commands.</span> <span class="audio-time caption">So it's pretty limitless.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  Yeah, yeah.</span> <span class="audio-time caption">Of course, it's how determined you are to write</span> <span class="audio-time caption">custom code for that.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Or how resourceful you are in</span> <span class="audio-time caption">finding other people's custom code that you can</span> <span class="audio-time caption">copy, at least.</span> <span class="audio-time caption">Good motivation to learn Emacs Lisp.</span> <span class="audio-time caption">I do not remember if Yasnippet is built-in.</span> <span class="audio-time caption">It feels like it's built-in.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  No, but it's one of those that</span> <span class="audio-time caption">basically everybody uses.</span> <span class="audio-time caption">Yasnippet or Tempel.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  A couple of questions from chat.</span> <span class="audio-time caption">When highlighting parts of the manual, how are</span> <span class="audio-time caption">you doing this?</span> <span class="audio-time caption">In bookmarks, bookmark-region, using Org Remark,</span> <span class="audio-time caption">other ways?</span> <span class="audio-time caption">I was doing this at the playground the other day,</span> <span class="audio-time caption">so I just had it in my iPad and I had it in one</span> <span class="audio-time caption">of those graphical note-taking things and I was</span> <span class="audio-time caption">highlighting with the Pencil.</span> <span class="audio-time caption">But I've heard good things about Org Remark,</span> <span class="audio-time caption">which is a package.</span> <p></p><div class="transcript-heading"><span class="audio-time">51:51</span> <strong>Taking notes with org-capture</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong> You can also use just <code>org-capture</code> if you’re</span> <span class="audio-time caption">reading the manuals from within Emacs, which you</span> <span class="audio-time caption">can.</span> <span class="audio-time caption">If you <code>org-capture</code>, you can even select sections</span> <span class="audio-time caption">of the manual and it'll automatically save that</span> <span class="audio-time caption">in the capture template along with a link back to</span> <span class="audio-time caption">where you were looking.</span> <span class="audio-time caption">This is great.</span> <p></p><div class="transcript-heading"><span class="audio-time">52:08</span> <strong>Navigating back to captures or refiles</strong></div><p></p><span class="audio-time caption"><strong>Prot:</strong>  Since you mentioned <code>org-capture</code></span> <span class="audio-time caption">and we talked about bookmarks earlier, when you</span> <span class="audio-time caption">do <code>org-capture</code> or <code>org-refile</code>, it stores
a</span> <span class="audio-time caption">bookmark.</span> <span class="audio-time caption">You can go back to the last capture, the last</span> <span class="audio-time caption">refile.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Yeah, yeah, which is handy.</span> <span class="audio-time caption">Also, you can use <code>org-refile</code> to navigate your Org
files.</span> <span class="audio-time caption">In addition to using it to jump to the last</span> <span class="audio-time caption">thing that you filed because you were like, "Oh,</span> <span class="audio-time caption">yeah, wait, I forgot.</span> <span class="audio-time caption">I want to add more to that note,"</span> <span class="audio-time caption">you can also use it to jump to any of your</span> <span class="audio-time caption">projects, for example, or any of your notes,</span> <span class="audio-time caption">assuming you’ve set up your <code>org-refile-targets</code></span> <span class="audio-time caption">appropriately.</span> <span class="audio-time caption">Okay, @RandCode has question.</span> <span class="audio-time caption">Does Emacs have a grammar checker like Harper's LSP?</span> <span class="audio-time caption">I know there are packages that people can use to</span> <span class="audio-time caption">work with Harper and other things.</span> <span class="audio-time caption">Do you know of any other built-in things?</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  Built-in, it's flyspell, but</span> <span class="audio-time caption">that's not grammar.</span> <span class="audio-time caption">That's spelling.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Okay, all right.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  I cannot think of something.</span> <span class="audio-time caption">No, I don't think there is for grammar.</span> <span class="audio-time caption">So Harper or anything like that would plug into</span> <span class="audio-time caption">Flymake.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  @greggr0th has a question.</span> <span class="audio-time caption">What are your favorite completion plugins?</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  Yeah, I think it's really vertico.</span> <span class="audio-time caption">I prefer it over the built-in options, over</span> <span class="audio-time caption">icomplete.</span> <span class="audio-time caption">So it's vertico, and then with that, I would</span> <span class="audio-time caption">say, at minimum, orderless.</span> <span class="audio-time caption">So vertico and orderless, at minimum.</span> <span class="audio-time caption">But then, of course, if you want a little bit</span> <span class="audio-time caption">more, which is very useful, Marginalia, Consult,</span> <span class="audio-time caption">Embark, maybe I'm forgetting something, save-hist,</span> <span class="audio-time caption">it's built-in.</span> <span class="audio-time caption">But yeah, those, those for sure.</span> <p></p><div class="transcript-heading"><span class="audio-time">53:49</span> <strong>dabbrev</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong>  @hmelman says dabbrev for dynamic</span> <span class="audio-time caption">abbreviations is underrated.</span> <span class="audio-time caption">You don't need to predefine them.</span> <span class="audio-time caption">You just type the start of a word or symbol and</span> <span class="audio-time caption">type <code>M-/</code>, and it will search the buffer for</span> <span class="audio-time caption">something starting with what's on the left side</span> <span class="audio-time caption">of your point and then expand it.</span> <span class="audio-time caption">I can't remember if it's dabbrev or hippie-expand,</span> <span class="audio-time caption">but you can also set it up so that it can try</span> <span class="audio-time caption">words from other buffers or other things that</span> <span class="audio-time caption">you've got or contacts or whatever.</span> <span class="audio-time caption">Anyway, so dynamic abbreviations.</span> <span class="audio-time caption">If you search for dabbrev and if you look also for</span> <span class="audio-time caption">hippie-expand, you will find lots of things that</span> <span class="audio-time caption">you can configure to fit your particular workflow.</span> <span class="audio-time caption">So you can expand abbreviations without having to</span> <span class="audio-time caption">define them.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  Yeah, yeah, yeah.</span> <span class="audio-time caption">Super powerful.</span> <span class="audio-time caption">Super useful.</span> <span class="audio-time caption">I use it more than tab completion, you know, like</span> <span class="audio-time caption">with core.</span> <span class="audio-time caption">I use dabbrev more.</span> <span class="audio-time caption">It's very nice.</span> <span class="audio-time caption">Yeah.</span> <p></p><div class="transcript-heading"><span class="audio-time">54:44</span> <strong>Keyboard macros</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong>  Okay, so we've mentioned keyboard</span> <span class="audio-time caption">macros very briefly, but this is another very</span> <span class="audio-time caption">powerful chunk of things that people might not be</span> <span class="audio-time caption">used to if they're coming from an editor that is</span> <span class="audio-time caption">not Emacs.</span> <span class="audio-time caption">So keyboard macros, what's kind of like the thing</span> <span class="audio-time caption">that we can use to explain?</span> <span class="audio-time caption">How do we explain it to people who are new to</span> <span class="audio-time caption">this?</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  In its simplest form, you record</span> <span class="audio-time caption">what you type and you can play it back in its</span> <span class="audio-time caption">simplest form.</span> <span class="audio-time caption">But the thing with Emacs is that you don't just</span> <span class="audio-time caption">record typing motions, typing actions.</span> <span class="audio-time caption">You also record all the Emacs motions.</span> <span class="audio-time caption">You can have a keyboard macro that includes</span> <span class="audio-time caption">stuff such as move to another window or create a</span> <span class="audio-time caption">new split or whatever.</span> <span class="audio-time caption">You can do more advanced things like that.</span> <span class="audio-time caption">This has very nice qualities to it where it's</span> <span class="audio-time caption">like, oh, I just want to copy all these symbols</span> <span class="audio-time caption">and move them to my shell buffer and then I will</span> <span class="audio-time caption">do something with them,</span> <span class="audio-time caption">pipe it to something like a program</span> <span class="audio-time caption">outside of Emacs. So it has</span> <span class="audio-time caption">a lot of nice applications like that.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  I think that if people can get the</span> <span class="audio-time caption">hang of: very carefully set up their</span> <span class="audio-time caption">keyboard macro, think what's a series of</span> <span class="audio-time caption">steps that I can do so that I can do the change</span> <span class="audio-time caption">and then move my cursor to the start of where the</span> <span class="audio-time caption">next change should be...</span> <span class="audio-time caption">For example, I'll start the keyboard</span> <span class="audio-time caption">macro, I'll delete the word, I'll type in</span> <span class="audio-time caption">something new, or maybe I'll paste in a register</span> <span class="audio-time caption">I'll use isearch to find the next point at which</span> <span class="audio-time caption">I need to do something.</span> <span class="audio-time caption">If you define your keyboard macros like this,</span> <span class="audio-time caption">then you're giving yourself the ability to</span> <span class="audio-time caption">interactively confirm whether you're still on the</span> <span class="audio-time caption">right track and then make the change because that</span> <span class="audio-time caption">way, it's not just like a search and</span> <span class="audio-time caption">replace and you're hoping it all works out.</span> <span class="audio-time caption">Although the recent search and replaces are great</span> <span class="audio-time caption">because they show you the changes.</span> <span class="audio-time caption">But for something that's more complex, especially</span> <span class="audio-time caption">if you're not used to regular expressions,</span> <span class="audio-time caption">keyboard macros can help you</span> <span class="audio-time caption">interactively do it in small steps.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  Yeah, exactly.</span> <span class="audio-time caption">Of course, search and replace will be more</span> <span class="audio-time caption">tricky if you have to go through many files and</span> <span class="audio-time caption">perform multiple edits in each,</span> <span class="audio-time caption">because then the concept of regular expressions</span> <span class="audio-time caption">breaks down.</span> <span class="audio-time caption">You don't want to think in those terms where it's</span> <span class="audio-time caption">like, I will have to make a change somewhere</span> <span class="audio-time caption">towards the top and then somewhere in the middle</span> <span class="audio-time caption">and then somewhere towards the end. Keyboard</span> <span class="audio-time caption">macros combined with Dired combined with going to</span> <span class="audio-time caption">file... Very nice.</span> <span class="audio-time caption">Just to say another thing about keyboard macros</span> <span class="audio-time caption">is... Let's say you have written your very nice</span> <span class="audio-time caption">keyboard macro. You're recording it, and somewhere</span> <span class="audio-time caption">towards the end, you make a small mistake.</span> <span class="audio-time caption">Keep going and then <code>C-x C-k C-e</code> to</span> <span class="audio-time caption">edit your macro.</span> <span class="audio-time caption">It's a text buffer. You just remove what you</span> <span class="audio-time caption">don't want.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  You can save these keyboard macros</span> <span class="audio-time caption">as well.</span> <span class="audio-time caption">You can use them in a future Emacs session or</span> <span class="audio-time caption">even turn them into your first Emacs Lisp</span> <span class="audio-time caption">function.</span> <span class="audio-time caption">You can give it a name and you can run it that way.</span> <p></p><div class="transcript-heading"><span class="audio-time">57:52</span> <strong>Editable grep and occur</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong> In the next three minutes before the kiddo runs</span> <span class="audio-time caption">out for lunch break, I also want to mention,</span> <span class="audio-time caption">since we talked about making changes in multiple</span> <span class="audio-time caption">files, that grep and occur are both editable.</span> <span class="audio-time caption">You can do your grep and you can search for</span> <span class="audio-time caption">things.</span> <span class="audio-time caption">And then you can say <code>C-x C-q</code> which turns it</span> <span class="audio-time caption">from read-only to something you can change,</span> <span class="audio-time caption">then you can do your search and replace in that,</span> <span class="audio-time caption">and you can <code>C-x C-q</code> again</span> <span class="audio-time caption">and those changes can get put back</span> <span class="audio-time caption">into all those different files.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  It's amazing.</span> <span class="audio-time caption">On this note, specifically for grep, if you</span> <span class="audio-time caption">edit many files with the grep edit mode that is</span> <span class="audio-time caption">built into Emacs 31, it will not save them for you.</span> <span class="audio-time caption">So <code>C-x s</code>, instead of <code>C-x C-s</code>,</span> <span class="audio-time caption">allows you to save multiple buffers.</span> <span class="audio-time caption">And every time, it gives you a prompt and you can</span> <span class="audio-time caption">type <code>d</code> to see the diff.</span> <span class="audio-time caption">Like, okay, what exactly did I change?</span> <span class="audio-time caption">If you have many unsaved files, <code>d</code> to see what</span> <span class="audio-time caption">you're about to save so you never make any</span> <span class="audio-time caption">mistakes.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Mm-hmm.</span> <span class="audio-time caption">Taking advantage of these diffing tools is</span> <span class="audio-time caption">great also.</span> <span class="audio-time caption">Even if you're new to Emacs or you don't have a</span> <span class="audio-time caption">programming background, if you find yourself</span> <span class="audio-time caption">making changes to lots of files, I strongly</span> <span class="audio-time caption">recommend learning more about version control</span> <span class="audio-time caption">systems like Git and then using something like</span> <span class="audio-time caption">Magit or even the built-in VC.</span> <span class="audio-time caption">If you use VC, you can use it and you have set up</span> <span class="audio-time caption">something like a git repository.</span> <span class="audio-time caption">You can use `C-x v =` to diff to see</span> <span class="audio-time caption">the changes between your file and the previous</span> <span class="audio-time caption">thing that you had saved.</span> <span class="audio-time caption">Which makes sense so that you can see, okay,</span> <span class="audio-time caption">these are the changes.</span> <span class="audio-time caption">Also it means that you can experiment with</span> <span class="audio-time caption">different changes.</span> <span class="audio-time caption">You can experiment with different ways of</span> <span class="audio-time caption">writing a paragraph or whatever, and you know</span> <span class="audio-time caption">that all of your previous versions are saved and</span> <span class="audio-time caption">you don't have "really, really final</span> <span class="audio-time caption">version two."</span> <span class="audio-time caption">You don't clutter your directory with a lot of</span> <span class="audio-time caption">copies of the same file.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  But even if you don't have any of</span> <span class="audio-time caption">the version control system set up, a very simple</span> <span class="audio-time caption">thing is <code>diff-buffer-with-file</code>.</span> <span class="audio-time caption">So you have a file you are working on and now you</span> <span class="audio-time caption">make some edits.</span> <span class="audio-time caption">The buffer, what is in memory, is different</span> <span class="audio-time caption">than what is on disk.</span> <span class="audio-time caption">You can compare the difference between the two.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Okay, I'm going to try to wrap up</span> <span class="audio-time caption">here because the kid is going to run and say hi</span> <span class="audio-time caption">very soon.</span> <span class="audio-time caption">Thank you so much for joining me.</span> <span class="audio-time caption">Of course, there's a lot more to talk about the</span> <span class="audio-time caption">Emacs built-ins, but I hope we've given a quick</span> <span class="audio-time caption">tour of some of the things that are definitely</span> <span class="audio-time caption">worth learning more about and the situations for</span> <span class="audio-time caption">which they are absurdly useful.</span> <span class="audio-time caption">Thanks to everyone in chat also for coming and</span> <span class="audio-time caption">hanging out.</span> <span class="audio-time caption">I will post the show notes eventually and get the</span> <span class="audio-time caption">transcripts sorted out.</span> <span class="audio-time caption">Thanks.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  You're welcome.</span> <span class="audio-time caption">You're welcome.</span> <span class="audio-time caption">Take care.</span> <span class="audio-time caption">Of course, good luck with everything.</span> <span class="audio-time caption">Didn't she show up here?</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  If she shows up, she will.</span> <span class="audio-time caption">It's inevitable.</span> <p></p><div class="transcript-heading"><span class="audio-time">1:01:01</span> <strong>Emacs Carnival June 2026: Underappreciated built-ins</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong> Also, if folks are interested, even if you've</span> <span class="audio-time caption">never blogged before, the Emacs carnival theme</span> <span class="audio-time caption">for June 2026 is "Underappreciated Emacs</span> <span class="audio-time caption">built-ins," which is why we had this conversation.</span> <span class="audio-time caption">Feel free to write about something and either</span> <span class="audio-time caption">send [Ross and] me a link,</span> <span class="audio-time caption">or you can even send me the post</span> <span class="audio-time caption">and I'll post it on my blog with your name on it</span> <span class="audio-time caption">and other things like that so you can share your</span> <span class="audio-time caption">appreciation for these built-ins.</span> <span class="audio-time caption">All right.</span> <span class="audio-time caption">Okay, I hear movement.</span> <span class="audio-time caption">I gotta go.</span> <span class="audio-time caption">All right.</span> <p></p><span class="audio-time caption"><strong>Prot:</strong>  Take care, Sacha.</span> <span class="audio-time caption">Take care, folks.</span> <span class="audio-time caption">Goodbye.</span></div>
<p></p>


<a name="end-yay-emacs-33-sacha-and-prot-talk-emacs-built-ins-transcript"></a>
</div>
</div>
<div class="outline-3">
<h3><a href="https://sachachua.com/blog/category/emacs/feed/index.xml#yay-emacs-33-sacha-and-prot-talk-emacs-built-ins-chat">Chat</a></h3>
<div class="outline-text-3">
<ul>
<li><span class="nick">protesilaos:</span> ​Looking forward to this! Talk to you soon.</li>
<li><span class="nick">gr1maldi:</span> ​​Yo, and stuff.🙂</li>
<li><span class="nick">charliemcmackin4859:</span> ​​I just checked, there are 11 items in my kill-ring at the moment. Some of them are several lines long</li>
<li><span class="nick">charliemcmackin4859:</span> ​narrowing to defun feels easier than trying to mark the function before search-and-replacing… I love narrowing</li>
<li><span class="nick">charliemcmackin4859:</span> ​…and I love that you can make those marking tricks part of a keyboard macro</li>
<li><span class="nick">hmelman:</span> ​​both local and global marks are useful to navigate through</li>
<li><span class="nick">pratikmishra4073:</span> ​​just tried indirect buffer. didn't know it existed</li>
<li><span class="nick">hmelman:</span> ​and the fact that things like xref or imenu push the last location before jumping, means popping the mark is an easy way to go back from various navigation mechanisms</li>
<li><span class="nick">matthewjorgensen9115:</span> ​​thinking about isearrch wrap around search losing your place. either have scrroll to posisiotn to know the direction and how far it was away, or have mode line flash to say it moved from last to first</li>
<li><span class="nick">hmelman:</span> ​Don't need flymake for that just M-g M-n (next-error) which works with compile, grep, occur (I think).</li>
<li><span class="nick">hmelman:</span> ​One I keep forgetting about, you mentioned using sexp commands in other languages, works in prose too. C-M-u (backwards-up-list) moves you out of a "quote" or (paren) and then C-M-e to the end of it.</li>
<li><span class="nick">matthewjorgensen9115:</span> ​​follow mode alllows the smae file with multiple frames, like a book. follow mode can work with 2 3 or more windows</li>
<li><span class="nick">matthewjorgensen9115:</span> ​also works with centered cursor mode which will keep the cusor possion in the middle of the frame</li>
<li><span class="nick">RandCode:</span> ​​Damn I am late, hello everyone! 🙂</li>
<li><span class="nick">matthewjorgensen9115:</span> ​when highlighting parts of the manual how are you doing this? in bookmarks, bookmark region, using org-remark? other ways?</li>
<li><span class="nick">RandCode:</span> ​​Does emacs have a grammar checker like harper's lsp?</li>
<li><span class="nick">greggr0th:</span> ​​What are your favorite completion plugins?</li>
<li><span class="nick">RandCode:</span> ​​Also, looking fresh Prot ;)</li>
<li><span class="nick">protesilaos:</span> ​​Thanks!</li>
<li><span class="nick">hmelman:</span> ​dabbrev is underrated. You don't need to pre-define them, just type the start of a word/symbol and type M-/ and it will search the buffer for something starting with what's left of point and expand it</li>
<li><span class="nick">RandCode:</span> ​There is so much to learn that I feel like I have been missing out on all of emacs somehow lol</li>
<li><span class="nick">RandCode:</span> ​Since you mentioned built-in completion framewworks, how does the built-in (vertical) completions compare to corfu btw?</li>
<li><span class="nick">charliemcmackin4859:</span> ​not grammar, but if you have a dictionary server running (like dicod on linux) emacs can be made to communicate with it to give definitions at point</li>
<li><span class="nick">RandCode:</span> ​Ohh, that is a cool! ^</li>
<li><span class="nick">matthewjorgensen9115:</span> ​​virtico multiform mode allows custom settings command, for example for files I use grid and alphabetical, but vertico recommendations normally. This allows more value of completion knowledge</li>
<li><span class="nick">RandCode:</span> ​Thank you so mcuh for this wonderful stream everyone!!!</li>
</ul>
</div>
</div>
<div><a href="https://sachachua.com/blog/2026/06/june-11-sacha-and-prot-talk-emacs-built-ins/index.org">View Org source for this post</a></div>
<p>You can <a href="mailto:sacha@sachachua.com?subject=Comment%20on%20https%3A%2F%2Fsachachua.com%2Fblog%2F2026%2F06%2Fjune-11-sacha-and-prot-talk-emacs-built-ins%2F&amp;body=Name%20you%20want%20to%20be%20credited%20by%20(if%20any)%3A%20%0AMessage%3A%20%0ACan%20I%20share%20your%20comment%20so%20other%20people%20can%20learn%20from%20it%3F%20Yes%2FNo%0A">e-mail me at sacha@sachachua.com</a>.</p></body></html>]]></content>
        <author>
            <name>Sacha Chua</name>
            <uri>https://sachachua.com/blog/category/emacs/feed/index.xml</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Protesilaos: Emacs live with Sacha Chua about ‘Underappreciated Built-ins’ on Thursday 11 June 17:30 Europe/Athens]]></title>
        <id>https://protesilaos.com/codelog/2026-06-09-emacs-live-sacha-chua-built-ins/</id>
        <link href="https://protesilaos.com/codelog/2026-06-09-emacs-live-sacha-chua-built-ins/"/>
        <updated>2026-06-09T00:00:00.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>Raw link: <a href="https://www.youtube.com/watch?v=yuJYEua0ZwA">https://www.youtube.com/watch?v=yuJYEua0ZwA</a></p>
         
         <p>I will join Sacha’s live stream this Thursday to talk about
underappreciated features that are built into Emacs. There are a lot
of nice things that are available out-of-the-box (plus many packages
that build on top of them). I am looking forward to it!</p>

<p>The video will be recorded for future reference.</p>
        </body></html>]]></content>
        <author>
            <name>Protesilaos</name>
            <uri>https://protesilaos.com/codelog</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Sacha Chua: 2026-06-08 Emacs news]]></title>
        <id>https://sachachua.com/blog/2026/06/2026-06-08-emacs-news/</id>
        <link href="https://sachachua.com/blog/2026/06/2026-06-08-emacs-news/"/>
        <updated>2026-06-08T18:36:11.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>
It's <a href="https://rossabaker.com/blog/underappreciated-emacs-built-ins/">Emacs Built-ins appreciation month</a>! I'm coming to appreciate the menu bar more. What built-ins do you appreciate? Write about it and <a href="https://rossabaker.com/blog/underappreciated-emacs-built-ins/">send Ross a link</a>!
</p>

<ul>
<li>Emacs updates:
<ul>
<li><a href="https://lists.gnu.org/archive/html/emacs-devel/2026-06/msg00118.html">Emacs 31.0.90 pretest is available</a> (<a href="https://www.reddit.com/r/emacs/comments/1tycwh7/emacs_31090_pretest_released_speed_boosts_ui/">Reddit</a>, <a href="https://www.linuxcompatible.org/story/emacs-31090-pretest-released-speed-boosts-ui-tweaks-bug-fixes/">Linux Compatible</a>, <a href="https://irreal.org/blog/?p=13858">Irreal</a>)</li>
</ul></li>
<li>Upcoming events (<a href="https://emacslife.com/calendar/emacs-calendar.ics">iCal file</a>, <a href="https://emacslife.com/calendar/">Org</a>):
<ul>
<li>Emacs Berlin: In-Person-Only Emacs-Berlin Stammtisch <a href="https://emacs-berlin.org/">https://emacs-berlin.org/</a> Tue Jun 9 1900 Europe/Berlin</li>
<li>OrgMeetup (virtual) <a href="https://orgmode.org/worg/orgmeetup.html">https://orgmode.org/worg/orgmeetup.html</a> Wed Jun 10 0900 America/Vancouver - 1100 America/Chicago - 1200 America/Toronto - 1600 Etc/GMT - 1800 Europe/Berlin - 2130 Asia/Kolkata – Thu Jun 11 0000 Asia/Singapore</li>
<li>Atelier Emacs Montpellier (in person) <a href="https://lebib.org/date/atelier-emacs">https://lebib.org/date/atelier-emacs</a> Fri Jun 12 1800 Europe/Paris</li>
<li>M-x Research: TBA <a href="https://m-x-research.github.io/">https://m-x-research.github.io/</a> Wed Jun 17 0800 America/Vancouver - 1000 America/Chicago - 1100 America/Toronto - 1500 Etc/GMT - 1700 Europe/Berlin - 2030 Asia/Kolkata - 2300 Asia/Singapore</li>
</ul></li>
<li>Beginner:
<ul>
<li><a href="https://www.youtube.com/watch?v=diPparUrHGw">How to Install Emacs on a Chromebook in 2026</a> (07:15)</li>
<li><a href="https://www.youtube.com/watch?v=CVtYtcFvutw">How to Setup Emacs on a Chromebook Without Elisp in 2026</a> (10:37)</li>
</ul></li>
<li>Emacs configuration:
<ul>
<li><a href="https://wiki.plexwave.org/useful-emacs-key-bindings">Useful Emacs key bindings</a> (<a href="https://gts.plexwave.org/@spnw/statuses/01KT4TKGRQ2VZ62CD1N9APSG20">@spnw@plexwave.org</a>)</li>
<li><a href="https://www.reddit.com/r/emacs/comments/1tzo8jz/this_is_my_best_emacs_function_written_in_my/">function to list bindings</a></li>
<li><a href="https://ray-on-emacs.blogspot.com/2026/06/emacs-and-numeric-keypad.html">Raymond Zeitler: Emacs and the Numeric Keypad</a></li>
<li><a href="https://mathstodon.xyz/@oantolin/116698855002229972">new embark-automatic-prefix-help-mode (@oantolin@mathstodon.xyz)</a></li>
<li><a href="https://www.youtube.com/watch?v=ZCELm1zUcH0">How I structure my Emacs init.el file</a> (27:05, <a href="https://github.com/maxfriis/my-emacs-config">GitHub</a>)</li>
<li><a href="https://github.com/jamescherti/minimal-emacs.d">minimal-emacs.d: A Customizable init.el and early-init.el for Optimized Startup and Better Emacs Defaults [Release 1.5.0]​</a> (<a href="https://www.reddit.com/r/emacs/comments/1tuowci/minimalemacsd_a_customizable_initel_and/">Reddit</a>)</li>
<li><a href="https://github.com/scovl/dotfiles/tree/main/OpenBSD/.emacs.d">dotfiles/OpenBSD/.emacs.d at main · scovl/dotfiles · GitHub</a> (<a href="https://hachyderm.io/@lobocode/116677349851718741">@lobocode@hachyderm.io</a>)</li>
</ul></li>
<li>Emacs Lisp:
<ul>
<li><a href="https://github.com/k3jph/stops-el">k3jph/stops-el: stops: Guards in Emacs Lisp · GitHub</a> (<a href="https://mastodon.social/@k3jph/116693120049548169">@k3jph</a>)</li>
<li><a href="https://codeberg.org/imarko/vared.el">imarko/vared.el: Emacs command for interactively editing a variable - Codeberg.org</a> (<a href="https://fosstodon.org/@zrzz/116711371610663138">@zrzz@fosstodon.org</a>)</li>
</ul></li>
<li>Appearance:
<ul>
<li><a href="https://github.com/jamescherti/vim-tab-bar.el">vim-tab-bar: A Vim inspired Emacs tab-bar that adapts to any Emacs theme [Release 1.1.5]​</a> (<a href="https://www.reddit.com/r/emacs/comments/1tu64xu/vimtabbar_a_vim_inspired_emacs_tabbar_that_adapts/">Reddit</a>)</li>
<li><a href="https://www.chiply.dev/post-svg-line">svg-line: Better Status Bars for Emacs</a> (<a href="https://www.reddit.com/r/emacs/comments/1u069gm/svgline_better_status_bars_for_emacs/">Reddit</a>, <a href="https://lobste.rs/s/bqjxzj/svg_line_better_status_bars_for_emacs">lobste.rs</a>)</li>
<li><a href="https://ray-on-emacs.blogspot.com/2026/06/change-emacs-cursor-to-indicate.html">Raymond Zeitler: Change Emacs Cursor to Indicate Overwrite Mode</a></li>
<li><a href="https://source.cipherbliss.com/tykayn/emacs-theming">tykayn/emacs-theming</a> (<a href="https://mastodon.cipherbliss.com/@tykayn/116697952623553128">@tykayn@mastodon.cipherbliss.com</a>)</li>
<li><a href="https://github.com/lucasobx/pixel-themes">Emacs themes inspired by pixel art palettes</a> (<a href="https://www.reddit.com/r/emacs/comments/1tx56oj/emacs_themes_inspired_by_pixel_art_palettes/">Reddit</a>)</li>
<li><a href="https://www.youtube.com/watch?v=FSdPbKTBWaQ">How to Change Themes in Emacs</a> (01:31)</li>
<li><a href="https://www.youtube.com/watch?v=7Gz-FOq9AIs">How to Inhibit the Welcome Screen in Emacs</a> (01:12)</li>
<li><a href="https://www.youtube.com/watch?v=Cr9IHzj_APQ">How to Maximize Emacs' Screen Upon Startup</a> (01:24)</li>
<li><a href="https://www.youtube.com/watch?v=Rsgg-uVJlIw">How to Hide the Tool Bar, Scroll Bar, and Menu Bar in Emacs</a> (02:00)</li>
<li><a href="https://www.youtube.com/watch?v=XTgIJUwmz0Q">Nicolas Rougier's Talk at 39C3 - The art of text (rendering)</a> (<a href="https://www.reddit.com/r/emacs/comments/1txnsrr/nicolas_rougiers_talk_at_39c3_the_art_of_text/">Reddit</a>) see discussion for more thoughts on SVG in Emacs</li>
</ul></li>
<li>Navigation:
<ul>
<li><a href="https://www.reddit.com/r/emacs/comments/1tu9wvg/post_a_solution_embarkactonlastmessage/">Post a solution: embark-act-on-last-message</a></li>
<li><a href="https://github.com/vmargb/project-x">Project-x revived with Emacs 30+ support!</a> (<a href="https://www.reddit.com/r/emacs/comments/1tylkdz/projectx_revived_with_emacs_30_support/">Reddit</a>) - session persistence</li>
<li><a href="https://www.reddit.com/r/emacs/comments/1txrf6o/little_llm_helper_function_for_copying_fileline/">Little LLM helper function for copying file:line coordinates</a></li>
<li><a href="https://github.com/jamescherti/kirigami.el">kirigami: A unified Emacs method to fold and unfold text in Emacs: outline, outline-indent, org-mode, markdown-mode, vdiff, hideshow, treesit-fold… [Release 1.1.2]​</a> (<a href="https://www.reddit.com/r/emacs/comments/1tup3tb/kirigami_a_unified_emacs_method_to_fold_and/">Reddit</a>)</li>
</ul></li>
<li>Writing:
<ul>
<li><a href="https://github.com/mmarshall540/electric-sentence">mmarshall540/electric-sentence: Automatically add the extra space between sentences in Emacs. · GitHub</a> (<a href="https://www.reddit.com/r/emacs/comments/1tynlmb/wrote_a_package_to_add_the_2nd_space_between/">Reddit</a>)</li>
<li><a href="https://github.com/jamescherti/quick-sdcv.el">quick-sdcv: Emacs offline dictionary using 'sdcv' [Release 1.0.5]​</a> (<a href="https://www.reddit.com/r/emacs/comments/1tu6u91/quicksdcv_emacs_offline_dictionary_using_sdcv/">Reddit</a>, <a href="https://irreal.org/blog/?p=13848">Irreal</a>)</li>
<li><a href="https://www.reddit.com/r/emacs/comments/1tvrwet/notes_linking_and_tagging_systems_in_emacs/">Notes, Linking and Tagging systems in Emacs</a></li>
<li><a href="https://mahmoodsh.com/blk.html">blk</a>: creating and navigating titles of text files, linking between them</li>
<li><a href="https://blog.davep.org/2026/06/05/blogmore-el-v4-6-0.html">Dave Pearson: blogmore.el v4.6.0</a> - show toc, show toc inline</li>
</ul></li>
<li>Org Mode:
<ul>
<li><a href="https://bicycleforyourmind.com/much-ado-about-emacs-014">Much Ado About Emacs 014: Org-Mode and the Capture System</a>, creating headings at different levels, and changing bindings</li>
<li><a href="https://taonaw.com/2026/06/03/correcting-photo-orientation-for-orgmode.html">TAONAW - Emacs and Org Mode: Correcting photo orientation for org-mode in Linux</a> (<a href="https://irreal.org/blog/?p=13860">Irreal</a>)</li>
<li><a href="https://citum.org/news/citing-with-citum-in-emacs-org-mode.html">Citing with Citum in Emacs org-mode | News | Citum</a> (<a href="https://mas.to/@bdarcus/116677048360094778">@bdarcus@mas.to</a>)</li>
<li><a href="https://eugene-andrienko.com/it/2024/12/01/emacs-plugin-jekyll-blog.html">How I wrote an Emacs plugin to build my blog</a> (<a href="https://mastodon.bsd.cafe/@evgandr/116687815479622870">@evgandr@bsd.cafe</a>)</li>
<li><a href="https://thecloudlet.github.io/technical/emacs/org-zola-workflow/">Migrating a Zola blog from Markdown to Org-mode — with a lint/export/check pipeline to keep them in sync | The Cloudlet</a></li>
<li>Org development: <a href="https://git.savannah.gnu.org/cgit/emacs/org-mode.git/commit/etc/ORG-NEWS?id=3ea1682731fa061115bc690e76ce7d1d2955f810">Generate images in TOC for HTML export</a></li>
</ul></li>
<li>Completion:
<ul>
<li><a href="https://www.chiply.dev/post-incremental-suggesting-read">Beyond ICR: Incremental 'Suggesting' Read in Emacs</a> (<a href="https://www.youtube.com/watch?v=UnAavHqekp0">YouTube</a> 20:10, <a href="https://www.reddit.com/r/emacs/comments/1tvjp8l/beyond_icr_incremental_suggesting_read_in_emacs/">Reddit</a>, <a href="https://fosstodon.org/@chiply/116685381663629482">@chiply@fosstodon.org</a>)</li>
</ul></li>
<li>Coding:
<ul>
<li><a href="https://github.com/rschmukler/magit-difftastic">Introducing magit-difftastic: integrate difftastic into magit</a> (<a href="https://www.reddit.com/r/emacs/comments/1twq1bg/introducing_magitdifftastic_integrate_difftastic/">Reddit</a>)</li>
<li><a href="https://github.com/phye/inline-review">inline-review: review merge/pull requests directly within emacs</a> (<a href="https://www.reddit.com/r/emacs/comments/1ttw2qg/inlinereview_review_mergepull_requests_directly/">Reddit</a>)</li>
<li><a href="https://www.alcarney.me/blog/2026/alc-jj-log-view-mode/">Building alc-jj-log-view-mode — Alex Carney</a> (<a href="https://mastodon.social/@alcarney/116711382373829868">@alcarney</a>)</li>
<li><a href="https://wassimans.com/blog/building-ios-apps-with-doom-emacs/">Building IOS Apps With Doom Emacs | Wassim Mansouri</a> (<a href="https://news.ycombinator.com/item?id=48388710">HN</a>)</li>
<li><a href="https://www.youtube.com/watch?v=thPsF9C2b10">CEDET for  Plan 9 coding</a> (01:14)</li>
<li><a href="https://oylenshpeegul.gitlab.io/blog/posts/20260601/">Tim Heaney: Ziglings</a></li>
</ul></li>
<li>Shells:
<ul>
<li><a href="https://www.alcarney.me/blog/2026/eshell-integration/">A Simple jj Integration for eshell — Alex Carney</a> (<a href="https://mastodon.social/@alcarney/116703207672988666">@alcarney</a>)</li>
<li><a href="https://ray-on-emacs.blogspot.com/2026/06/exeln-execute-line.html">Raymond Zeitler: exeln: EXEcute LiNe</a>
<ul>
<li><a href="https://ray-on-emacs.blogspot.com/2026/06/follow-on-to-exeln.html">Follow-on to exeln</a></li>
</ul></li>
</ul></li>
<li>Web:
<ul>
<li><a href="https://irreal.org/blog/?p=13846">Irreal: My Growing Appreciation For EWW</a></li>
</ul></li>
<li>Mail, news, and chat:
<ul>
<li><a href="https://ashishpanigrahi.com/blog/o365-offline-email/">Setting up offline email for Microsoft O365 with notmuch and emacs | Ashish Panigrahi</a> (<a href="https://ioc.exchange/@paniash/116711092886642906">@paniash@ioc.exchange</a>)</li>
<li><a href="https://lars.ingebrigtsen.no/2026/06/05/super-simple-spam-splitting-for-gnus/">Lars Ingebrigtsen: Super Simple Spam Splitting for Gnus</a></li>
<li><a href="https://github.com/emacs-elfeed/elfeed/blob/main/NEWS.org#version-400-2026-06-06">New Elfeed 4.0.0 release</a> (<a href="https://irreal.org/blog/?p=13862">Irreal</a>, <a href="https://news.ycombinator.com/item?id=48428652">HN</a>)</li>
<li><a href="https://en.andros.dev/blog/1a6f3018/chatting-via-meshtastic-in-emacs/">Chatting via Meshtastic in Emacs | Andros Fenollosa</a></li>
</ul></li>
<li>Multimedia:
<ul>
<li><a href="https://mbork.pl/2026-06-06_Copying_images_in_Emacs">Marcin Borkowski: Copying images in Emacs</a></li>
<li><a href="https://www.youtube.com/watch?v=iUrTC4PrBpM">Kokoro-onnx with Cuda for text to speech with Emacs</a> (01:26:56)</li>
</ul></li>
<li>Fun:
<ul>
<li><a href="https://github.com/modeverv/wasmacs">I ported GNU Emacs 30.2 to the browser with WebAssembly</a> (<a href="https://www.reddit.com/r/emacs/comments/1tzy72g/i_ported_gnu_emacs_302_to_the_browser_with/">Reddit</a>)</li>
<li><a href="https://ianyepan.github.io/posts/emacs-in-pop-culture/">Emacs Appearance in Pop Culture</a> (<a href="https://www.reddit.com/r/emacs/comments/1u02d0v/emacs_appearance_in_pop_culture/">Reddit</a>, <a href="https://news.ycombinator.com/item?id=48474274">HN</a>, <a href="https://irreal.org/blog/?p=13866">Irreal</a>)</li>
</ul></li>
<li>AI:
<ul>
<li><a href="https://kevinlynagh.com/newsletter/2026_05_difftron/">Structural diffing in Emacs; deterministic agent harnesses</a> (<a href="https://github.com/lynaghk/difftron/">GitHub</a>)</li>
<li><a href="https://github.com/ananthakumaran/pi.el">Emacs client for Pi Coding Agent</a> (<a href="https://www.reddit.com/r/emacs/comments/1tz40nr/emacs_client_for_pi_coding_agent/">Reddit</a>)</li>
<li><a href="https://github.com/jaketothepast/codetutor">jaketothepast/codetutor: An AI Pair Programmer, that teaches you to code as you write, for Emacs · GitHub</a> (<a href="https://news.ycombinator.com/item?id=48449430">HN</a>)</li>
</ul></li>
<li>Community:
<ul>
<li><a href="https://www.reddit.com/r/emacs/comments/1tueedh/fortnightly_tips_tricks_and_questions_20260602/">Fortnightly Tips, Tricks, and Questions — 2026-06-02 / week 22</a></li>
<li><a href="https://www.reddit.com/r/emacs/comments/1tudad3/learning_emacs_with_progressive_vision_loss/">Learning Emacs with Progressive Vision Loss</a></li>
<li><a href="https://kelar.org/~bandali/news/fsa-202605.html">Amin Bandali: Free software activities in May 2026</a></li>
<li><a href="https://sachachua.com/blog/2026/06/june-4-emacs-chat-with-ben-zanin-gnomon-mastodon-social/">Emacs Chat 25: Ben Zanin (@gnomon@mastodon.social)</a> (<a href="https://www.youtube.com/watch?v=ax4f5uaOHA8">YouTube</a> 59:30)</li>
<li><a href="https://sachachua.com/blog/2026/05/emacs-carnival-may-2026-may-i-recommend/">Sacha Chua: Emacs Carnival May 2026 wrap-up: "May I recommend…"</a></li>
<li><a href="https://sachachua.com/blog/2026/06/transcript-of-chat-with-matei-candea-about-emacs-and-ai/">Sacha Chua: Transcript of chat with Matei Candea about Emacs and AI</a></li>
<li><a href="https://www.youtube.com/watch?v=UqashZncNj4">This perfect text editor doesn't exist</a> (15:57)</li>
<li><a href="https://linuxblog.io/teco-neovim-text-editing-unix-linux/">From TECO to Neovim: 50 Years of Text Editing on Unix and Linux</a> (<a href="https://www.reddit.com/r/emacs/comments/1tzo58i/from_teco_to_neovim_50_years_of_text_editing_on/">Reddit</a>)</li>
<li><a href="https://www.swi-prolog.org/PceEmacs.md">PceEmacs is an Emacs written in Prolog instead of Lisp! It also seems to support LSP</a> (<a href="https://www.reddit.com/r/emacs/comments/1tvn264/pceemacs_is_an_emacs_written_in_prolog_instead_of/">Reddit</a>)</li>
</ul></li>
<li><a href="https://rossabaker.com/blog/underappreciated-emacs-built-ins/">Emacs Carnival: Underappreciated Emacs Builtins</a>:
<ul>
<li><a href="https://www.homepages.ucl.ac.uk/~ucecesf/blog/20260602.html">Emacs carnival: rec mode, an all-text database system</a> (<a href="https://fediscience.org/@ericsfraga/116681034174534204">@ericsfraga@fediscience.org</a>)</li>
<li><a href="https://www.cyan.sh/blog/posts/radical-builtins.html">Jakub Nowak: Radical Builtins</a></li>
<li><a href="https://wiki.plexwave.org/emacs-dwim-case-commands">Emacs DWIM case commands</a> by spnw</li>
</ul></li>
<li>Other:
<ul>
<li><a href="https://github.com/ErikPrantare/phony.el">phony.el: Define voice commands in Emacs</a> (<a href="https://www.reddit.com/r/emacs/comments/1tubei6/phonyel_define_voice_commands_in_emacs/">Reddit</a>)</li>
<li><a href="https://bicycleforyourmind.com/much_ado_about_emacs_013">Bicycle for Your Mind: Much Ado About Emacs 013</a> - anddo.el (todos), substitute</li>
<li><a href="https://lars.ingebrigtsen.no/2026/06/03/todo-lists-and-procrastination/">Lars Ingebrigtsen: Todo Lists and Procrastination</a></li>
<li><a href="https://github.com/jamescherti/inhibit-mouse.el">jamescherti/inhibit-mouse.el 1.0.4</a> (<a href="https://www.reddit.com/r/emacs/comments/1tvwk7l/inhibitmouse_disable_the_mouse_in_emacs_release/">Reddit</a>, <a href="https://irreal.org/blog/?p=13853">Irreal</a>)</li>
<li><a href="http://yummymelon.com/devnull/revisiting-emacs-keyboard-macros-with-a-mouse.html">Charles Choi: Revisiting Emacs Keyboard Macros with a Mouse</a></li>
<li><a href="https://sachachua.com/blog/2026/06/emacs-pdf-view-replace-current-page-with-file-using-pdftk/">Sacha Chua: Emacs PDF View: Replace current page with file using PDFtk</a></li>
<li><a href="https://www.yakshaving.co.uk/posts/conquering-the-emacs-daemon/">conquering the Emacs daemon - Blog In Isolation</a> (<a href="https://mastodon.me.uk/@andyc/116697585241088161">@andyc@mastodon.me.uk</a>)</li>
<li><a href="https://github.com/tanrax/emacs-gpu">tanrax/emacs-gpu: GNU Emacs with a GPU-accelerated display backend · GitHub</a> (<a href="https://activity.andros.dev/@andros/statuses/01KT8T7D12K9A22FCZX0NXDV43">@andros@activity.andros.dev</a>)
<ul>
<li><a href="https://yhetil.org/emacs-devel/0CAC2512-C560-4D1C-964B-46BBEF5228BF@subvertising.org/">emacs-devel re: overlap with Canvas patch</a>,<a href="https://yhetil.org/emacs-devel/571c261a-a4fc-4d7f-9ccb-afc6cb530547@gutov.dev/"> can't accept LLM-generated contributions</a></li>
</ul></li>
<li><a href="https://fedora-sysexts.github.io/fedora/emacs/">emacs | extensions.fcos.fr (Fedora)</a> (<a href="https://mastodon.social/@alcarney/116687391476450331">@alcarney</a>) - emacs sysext for Fedora image-based systems</li>
<li><a href="https://github.com/nohzafk/emacs-workspace-hud">I built a floating HUD for Emacs, rendered in Rust egui via WASM</a> (<a href="https://www.reddit.com/r/emacs/comments/1tw7u87/i_built_a_floating_hud_for_emacs_rendered_in_rust/">Reddit</a>) macOS</li>
<li><a href="http://yummymelon.com/devnull/opening-macos-finder-folders-in-emacs-with-scrim.html">Charles Choi: Opening macOS Finder Folders in Emacs with Scrim</a> (<a href="https://sfba.social/@kickingvegas/116678063857985054">@kickingvegas@sfba.social</a>)</li>
<li><a href="https://unixbhaskar.wordpress.com/2026/06/03/damn-emacs-regex-problem/">Damn! Emacs Regex problem | Unixbhaskar's Blog</a> (<a href="https://fosstodon.org/@unixbhaskar/116682966197832720">@unixbhaskar@fosstodon.org</a>)</li>
<li><a href="https://www.youtube.com/watch?v=omoGBS3rzEw">самый хайповый гайд на Emacs</a> (15:40)</li>
</ul></li>
<li>Emacs development:
<ul>
<li>emacs-devel: <a href="https://yhetil.org/emacs-devel/m2mrxes3bs.fsf@gmail.com/">markdown-ts-mode and markdown-ts-view-mode demoted on the release branch</a></li>
<li><a href="https://git.savannah.gnu.org/cgit/emacs.git/commit/etc/NEWS?id=1d91d9b717df1781c07d28f46af4ac2af19c16b4">project-vc-dir: Use truenames</a></li>
<li><a href="https://git.savannah.gnu.org/cgit/emacs.git/commit/etc/NEWS?id=66e02b3123a2f6845b1ec6e192f3820bb74d4a7b">(Fmarkers_in): New function (bug#81153)</a></li>
<li><a href="https://git.savannah.gnu.org/cgit/emacs.git/commit/etc/NEWS?id=2db5a145acbbe84042128806d8b2e333495cf70e">Support Ansible messages in compilation-mode</a></li>
</ul></li>
<li>New packages:
<ul>
<li><a target="_blank" href="https://melpa.org/#/bluesky">bluesky</a>: A Bluesky client (MELPA)</li>
<li><a target="_blank" href="https://melpa.org/#/cui">cui</a>: AI-LLM chat blocks for org-mode (MELPA)</li>
<li><a target="_blank" href="https://melpa.org/#/desert-theme">desert-theme</a>: A warm earthy port of Vim's desert theme (MELPA)</li>
<li><a target="_blank" href="https://elpa.nongnu.org/nongnu/flamegraph.html">flamegraph</a>: Flame graphs for Emacs's native profiler and folded stacks files (NonGNU ELPA)</li>
<li><a target="_blank" href="https://melpa.org/#/sleek-modeline">sleek-modeline</a>: Minimal and elegant modeline (MELPA)</li>
</ul></li>
</ul>

<p>
Links from <a href="https://www.reddit.com/r/emacs">reddit.com/r/emacs</a>, <a href="https://www.reddit.com/r/orgmode">r/orgmode</a>, <a href="https://www.reddit.com/r/spacemacs">r/spacemacs</a>, <a href="https://mastodon.social/tags/emacs">Mastodon #emacs</a>, <a href="https://bsky.app/hashtag/emacs">Bluesky #emacs</a>, <a href="https://hn.algolia.com/?query=emacs&amp;sort=byDate&amp;prefix&amp;page=0&amp;dateRange=all&amp;type=story">Hacker News</a>, <a href="https://lobste.rs/search?q=emacs&amp;what=stories&amp;order=newest">lobste.rs</a>, <a href="https://programming.dev/c/emacs?dataType=Post&amp;page=1&amp;sort=New">programming.dev</a>, <a href="https://lemmy.world/c/emacs">lemmy.world</a>, <a href="https://lemmy.ml/c/emacs?dataType=Post&amp;page=1&amp;sort=New">lemmy.ml</a>, <a href="https://planet.emacslife.com">planet.emacslife.com</a>, <a href="https://www.youtube.com/playlist?list=PL4th0AZixyREOtvxDpdxC9oMuX7Ar7Sdt">YouTube</a>, <a href="http://git.savannah.gnu.org/cgit/emacs.git/log/etc/NEWS">the Emacs NEWS file</a>, <a href="https://emacslife.com/calendar/">Emacs Calendar</a>, and <a href="https://lists.gnu.org/archive/html/emacs-devel/2026-06">emacs-devel</a>. Thanks to Andrés Ramírez for emacs-devel links. Do you have an Emacs-related link or announcement? Please e-mail me at <a href="mailto:sacha@sachachua.com">sacha@sachachua.com</a>. Thank you!
</p>
<div><a href="https://sachachua.com/blog/2026/06/2026-06-08-emacs-news/index.org">View Org source for this post</a></div>
<p>You can <a href="https://social.sachachua.com/@sacha/statuses/01KTMYVZBS50B5EFDW77VQJC0F" target="_blank">comment on Mastodon</a> or <a href="mailto:sacha@sachachua.com?subject=Comment%20on%20https%3A%2F%2Fsachachua.com%2Fblog%2F2026%2F06%2F2026-06-08-emacs-news%2F&amp;body=Name%20you%20want%20to%20be%20credited%20by%20(if%20any)%3A%20%0AMessage%3A%20%0ACan%20I%20share%20your%20comment%20so%20other%20people%20can%20learn%20from%20it%3F%20Yes%2FNo%0A">e-mail me at sacha@sachachua.com</a>.</p></body></html>]]></content>
        <author>
            <name>Sacha Chua</name>
            <uri>https://sachachua.com/blog/category/emacs/feed/index.xml</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Raymond Zeitler: Emacs and the Numeric Keypad]]></title>
        <id>https://ray-on-emacs.blogspot.com/2026/06/emacs-and-numeric-keypad.html</id>
        <link href="https://ray-on-emacs.blogspot.com/2026/06/emacs-and-numeric-keypad.html"/>
        <updated>2026-06-08T15:51:22.851Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>If you have a numeric keypad<sup>1</sup>, try this in the *scratch* buffer:
enable numlock and press the zero on the numeric keyboard
(Num-0). Then press the zero located between the alpha keys and the
  function keys (0). Okay, you see 00, no big deal.</p>
<p>Why do I bring this up?  Emacs interprets Num-0 keypress as &lt;kp-0&gt; while it interprets 0 as
0.  This means that you could bind Num-0 to a function without
affecting the other 0. You could configure Num-0 to insert "zero" by
entering and evaluating this in the *scratch* buffer:</p>

<pre>(keymap-local-set <span>"&lt;kp-0&gt;"</span> #'(<span>lambda</span> () (<span>interactive</span>) (insert <span>"zero"</span>)))
</pre>

 <p>That's a trivial example, of course.  But it implies that you can
      have ten more keys to play with.  Similarly, the arithmetic
      operator keys on the numeric keyboard differ from the "regular
      ones" that are grouped with the alpha keys.  They can be bound
      to functions, referenced
      as &lt;kp-add&gt;, &lt;kp-subtract&gt;, &lt;kp-multiply&gt;, &lt;kp-divide&gt;.  But
      these also accept the standard C- M- S- modifier keys, which
      gives you twelve more possibilities.  This is true also for the
      Insert key &lt;kp-insert&gt; and the Delete key &lt;kp-delete&gt; that
      double as Num-0 and Num-., respectively.</p>

<p>I have a "Calc" key above the numeric keypad.  Unfortunately I
can't seem to use it for anything in Emacs -- it opens the OS's
calc.exe program regardless of what modifiers I use with it.  This is
a shame because it would be the ideal mapping for M-x calc.  Perhaps
this can be altered in BIOS.</p>

<p>But I do use my Win key as a modifier (sometimes). And I've heard
that the Caps Lock key can be repurposed.  These are topics for
  other posts.</p>

<hr>
<a href="https://en.wikipedia.org/wiki/Numeric_keypad">https://en.wikipedia.org/wiki/Numeric_keypad</a>
</body></html>]]></content>
        <author>
            <name>Raymond Zeitler</name>
            <uri>https://ray-on-emacs.blogspot.com/search/label/Emacs</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Irreal: Elfeed 4.0.0]]></title>
        <id>https://irreal.org/blog/?p=13862</id>
        <link href="https://irreal.org/blog/?p=13862"/>
        <updated>2026-06-08T14:46:14.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>
Daniel Mendler, who took over as maintainer of the world’s best RSS reader, <a href="https://github.com/emacs-elfeed/elfeed">Elfeed</a>, has <a href="https://www.reddit.com/r/emacs/comments/1tyq0xz/new_elfeed_400_release/?solution=16b207f9fd9c61a116b207f9fd9c61a1&amp;js_challenge=1&amp;token=7afd7253fec22262ff1c52b1703fe9ece35831f9f1fd8ae830c5acdc446ec168&amp;jsc_orig_r=">announced the release of Elfeed 4.0.0</a>. You can read the <a href="https://github.com/emacs-elfeed/elfeed/blob/main/NEWS.org#version-400-2026-06-06">Change File</a> to see what’s new but the most important point for me is that the maintainership of Elfeed has successfully transitioned from Chris Wellons to Mendler.
</p>
<p>
When Wellons <a href="https://irreal.org/blog/?p=13775">announced his retirement from the Emacs ecosphere</a>, I, and I’m sure others, had a moment of apprehension. We all wondered if anyone could fill Wellons’ large shoes. I’m happy to say that Mendler has shown himself up to the task and is doing a great job moving Elfeed forward.
</p>
<p>
As I’ve said before, I consider Elfeed an almost perfect RSS reader. It’s easy to configure it to operate the way you need it to. One of Mendler’s changes that I <i>really</i> like is the ability to pop into EWW if you need to. I use it from the default Elfeed text buffer but also from the WebKit mediated display if there are too many ads and blinkenlights on the default page. As I’ve <a href="https://irreal.org/blog/?p=13846">said before</a>, I have a growing appreciation of EWW and am a bit surprised to find it becoming one of my go to tools.
</p>
<p>
The important point, though, is that if you’re an Emacs user who has an RSS feed, you should definitely try out Elfeed. You won’t, believe me, want to go back.</p>
</body></html>]]></content>
        <author>
            <name>Irreal</name>
            <uri>https://irreal.org/blog</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Charlie Holland: svg-line: Better Status Bars for Emacs]]></title>
        <id>https://www.chiply.dev/post-svg-line</id>
        <link href="https://www.chiply.dev/post-svg-line"/>
        <updated>2026-06-08T11:58:29.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><div class="outline-2">
<h2><span class="section-number-2">1.</span> TLDR</h2>
<div class="outline-text-2">
<p>
Emacs provides four useful status bars (<code>mode-line</code>, <code>header-line</code>, <code>tab-bar</code>, and <code>tab-line</code>), but each imposes different, inconsistent limits on multi-line layout, alignment, icons, and interactivity.  <code>svg-line</code> (see code on <a href="https://github.com/chiply/svg-line">GitHub</a>) solves this by rendering them as SVG images, and normalizes a rich feature set across all status bars with a consistent configuration.  <code>svg-line</code> works by defining a small rendering engine built on Emacs's native SVG support.  Configuring status bars is easy: you simply write one <code>:content</code> function and call <code>svg-line-activate</code>.  You can see my custom configuration of <a href="https://github.com/chiply/.zetta.d/blob/main/modules/ui/modeline-svg.el"><code>mode-line</code></a>, <a href="https://github.com/chiply/.zetta.d/blob/main/modules/ui/header-line-svg.el"><code>header-line</code></a>, <a href="https://github.com/chiply/.zetta.d/blob/main/modules/ui/tab-line-svg.el"><code>tab-line</code></a>, and <a href="https://github.com/chiply/.zetta.d/blob/main/modules/ui/tab-bar-svg.el"><code>tab-bar</code></a> in my <a href="https://github.com/chiply/.zetta.d">Emacs config</a>.
</p>

<p>
</p><div class="youtube-container">


</div>
<p></p>


<div class="figure">
<p><img src="https://www.chiply.dev/images/svg-line-annotated.png" alt="svg-line-annotated.png">
</p>
<p><span class="figure-number">Figure 1: </span>Every <code>*-line</code> in this frame is one SVG image drawn by <code>svg-line</code>.</p>
</div>
</div>
</div>
<div class="outline-2">
<h2><span class="section-number-2">2.</span> About</h2>
<div class="outline-text-2">
<p>
Emacs gives us four status bars, the <code>mode-line</code>, the <code>header-line</code>, the <code>tab-bar</code>, and the <code>tab-line</code> (<i>*-lines</i> for short).  These are useful for providing a dynamic 'heads-up display', for important context, like what buffer you're in, the active major mode, and really any arbitrary thing you can define.  
</p>

<p>
I'm a heavy user of the *-lines in Emacs, and I have them all enabled, but the issue that has plagued me is that, natively, each one behaves differently and each has unique limitations.  For example, multi-line status (necessary on my small laptop) is possible, but only in the <code>tab-bar</code>.  Right alignment is possible in the <code>tab-bar</code>, but only in the last line, and this alignment feature is only available in the <code>tab-bar</code>.  I can display icons from all-the-icons in the <code>mode-line</code> and <code>header-line</code>, but not the <code>tab-bar</code> or <code>tab-line</code>.  Etc….
</p>

<p>
What I really want is consistent behaviour and configuration across all these status bars, and I want the multi-line, alignment, and icons features available in all of them.  It turns out that SVG (<a href="https://en.wikipedia.org/wiki/SVG">scaled vector graphics</a>) is the key to solving this.
</p>

<p>
Inspired by Nicolas Rougier's <a href="https://gist.github.com/rougier/8d5a712aa43e3cc69e7b0e325c84eab4">dual-header gist</a>, I built <code>svg-line</code>, which provides this experience by utilizing Emacs's built-in SVG rendering support.  At first, this approach seemed like a hack, or abuse of the *-lines, or neglect of the built-in status bar behaviour.  But I kept it and created a package because I was literally shocked how well this works and how native this feels (see the screenshot and video above).
</p>

<p>
Note that even if you only use the <code>mode-line</code>, <code>svg-line</code> is still useful — likely <i>more</i> so, since a single status bar has to render all your indicators on its own.
</p>
</div>
</div>
<div class="outline-2">
<h2><span class="section-number-2">3.</span> <code>svg-line</code>'s Features</h2>
<div class="outline-text-2">
<ul>
<li><b>Multi-line everywhere</b>, with per-row left/center/right alignment.</li>
<li><b>A <code>tab-line</code> that wraps</b> overflowing tabs onto new rows instead of hiding them, including with file-type glyphs, a current-tab highlight, and an unsaved tint.</li>
<li><b>Clickable anything.</b>  Any segment can carry a left-click action, a right-click menu, and hover help with a highlight.  This works uniformly across all four bars, including the otherwise-uncooperative <code>tab-bar</code>.</li>
<li><b>Icons as text.</b>  Using <a href="https://www.nerdfonts.com/#home">Nerd Fonts</a> and an icon is just a character that flows with everything else.  SVG rendering also enables a full-height "masthead" glyph option on status bars that can span multiple lines.</li>
<li><b>Dynamic and animated indicators</b>: a buffer-position pie, progress bars, active vs. inactive styling per window.</li>
<li><b>It respects text scale.</b>  The bars track <code>text-scale</code>, re-rendering crisply instead of blurring.</li>
</ul>

<p>
A meta feature is that the configuration surface is uniform across all status bars, which is a pleasant improvement over the diverse configuration strategies for the native APIs.
</p>
</div>
</div>
<div class="outline-2">
<h2><span class="section-number-2">4.</span> Why SVG Works</h2>
<div class="outline-text-2">
<p>
When using <code>svg-line</code>, each line becomes <b>one SVG image</b>, and SVG images are more featureful than the native text engine:
</p>

<ol>
<li><b>It can be any height.</b>  Multi-row bars are now possible in every *-line.</li>
<li><b>Everything is placed at exact pixel coordinates.</b>  Left, right, and center alignment work identically on every row.</li>
<li><b>It draws whatever you want.</b>  Text, yes, but also wrapped tab flows, geometric progress bars and pies, and (with a Nerd Font) icon glyphs inline with the text, the same on all four lines.  Anything you can render in an SVG (just about anything) is fair game.</li>
<li><b>The engine remembers where it drew.</b>  It can detect the mouse against those placements, so clicks, right-click menus, and hover all work on any element of any line.</li>
</ol>
</div>
</div>
<div class="outline-2">
<h2><span class="section-number-2">5.</span> Configuration</h2>
<div class="outline-text-2">
<p>
Configuring <code>svg-line</code> is deliberately simple.  You write a <code>:content</code> function that returns rows, supply it to <code>svg-line-define</code>, and call <code>svg-line-activate</code> on the defined line.  This configuration pattern is identical for all four bars.  The engine has two layouts: <code>lines</code> (the default — rows of segments, used for the <code>mode-line</code>, <code>header-line</code>, and <code>tab-bar</code>) and <code>wrap</code> (a flow that wraps, used for the <code>tab-line</code>).
</p>
</div>
<div class="outline-3">
<h3><span class="section-number-3">5.1.</span> Mode-line</h3>
<div class="outline-text-3">
</div>
<div class="outline-4">
<h4><span class="section-number-4">5.1.1.</span> Simple <code>mode-line</code></h4>
<div class="outline-text-4">
<p>
The smallest useful line is a single row: a label on the left, the cursor position on the right.
</p>

<div class="org-src-container">
<pre><span>(</span>svg-line-define 'my-mode-line
  <span>:target</span> 'mode-line
  <span>:content</span> <span>(</span><span>lambda</span> <span>()</span>
             <span>;; </span><span>one row: (LEFT-SEGMENTS . RIGHT-SEGMENTS)
</span>             <span>(</span>list <span>(</span>cons <span>(</span>list <span>(</span>buffer-name<span>)</span><span>)</span>
                         <span>(</span>list <span>(</span>format-mode-line <span>"%l:%c"</span><span>)</span><span>)</span><span>)</span><span>)</span><span>)</span><span>)</span>

<span>(</span>svg-line-activate 'my-mode-line<span>)</span>
</pre>
</div>

<p>
This trivial example clarifies the pattern: <code>define</code> then <code>activate</code>:
</p>

<ul>
<li><code>:content</code> is the only required key: a function returning a list of <i>rows</i>.  Each row is a <code>(LEFT . RIGHT)</code> cons, and each side is a <i>list of segments</i> — here just plain strings.</li>
<li>with no <code>:background</code>, <code>:foreground</code>, or <code>:active</code>, the line picks sensible defaults and is always drawn as active.</li>
<li><code>svg-line-activate</code> enables it, and <code>svg-line-deactivate</code> / <code>svg-line-toggle</code> disable it, restoring the native <code>mode-line</code> untouched.</li>
</ul>
</div>
</div>
<div class="outline-4">
<h4><span class="section-number-4">5.1.2.</span> Rich <code>mode-line</code></h4>
<div class="outline-text-4">
<p>
Here's a more complicated <code>mode-line</code> configuration that demonstrates <code>svg-line</code>'s feature scope.  It defines two rows, three-way alignment, a masthead icon, a custom segment, a clickable button, dynamic theme colours, and active/inactive styling:
</p>

<div class="org-src-container">
<pre><span>;; </span><span>A custom segment is just a zero-argument function returning a string.
</span><span>;; </span><span>This one shows how far point sits through the buffer, as a percentage.
</span><span>(</span><span>defun</span> <span>my/buffer-percent</span> <span>()</span>
  <span>(</span>format <span>" %d%%"</span> <span>(</span>/ <span>(</span>* 100 <span>(</span>point<span>)</span><span>)</span> <span>(</span>max 1 <span>(</span>point-max<span>)</span><span>)</span><span>)</span><span>)</span><span>)</span>

<span>(</span>svg-line-define 'my-mode-line
  <span>:target</span>     'mode-line
  <span>:active</span>     #'mode-line-window-selected-p
  <span>:icon</span>       <span>(</span><span>lambda</span> <span>()</span> <span>(</span>nerd-icons-icon-for-mode major-mode<span>)</span><span>)</span>
  <span>:background</span> <span>(</span><span>lambda</span> <span>()</span> <span>(</span>face-background 'mode-line nil t<span>)</span><span>)</span>
  <span>:foreground</span> <span>(</span><span>lambda</span> <span>()</span> <span>(</span>face-foreground 'default nil t<span>)</span><span>)</span>
  <span>:content</span>
  <span>(</span><span>lambda</span> <span>()</span>
    <span>(</span>list
     <span>;; </span><span>row 1 — three independently-aligned segments on one row
</span>     <span>(</span>list <span>:left</span>   <span>(</span>list <span>(</span>buffer-name<span>)</span><span>)</span>
           <span>:center</span> <span>(</span>list <span>(</span>symbol-name major-mode<span>)</span><span>)</span>
           <span>:right</span>  <span>(</span>list <span>(</span>format-time-string <span>"%H:%M"</span><span>)</span><span>)</span><span>)</span>
     <span>;; </span><span>row 2 — custom segment + position on the left, a button on the right
</span>     <span>(</span>cons <span>(</span>list #'my/buffer-percent <span>(</span>format-mode-line <span>" %l:%c"</span><span>)</span><span>)</span>
           <span>(</span>list <span>(</span>svg-line-seg <span>"save"</span>
                               <span>:id</span> 'ml-save
                               <span>:help</span> <span>"buffer actions"</span>
                               <span>:action</span> #'save-buffer
                               <span>:action-help</span> <span>"save"</span>
                               <span>:menu</span> '<span>(</span><span>(</span><span>"Revert"</span> . revert-buffer<span>)</span>
                                       <span>(</span><span>"Kill"</span>   . kill-current-buffer<span>)</span><span>)</span><span>)</span><span>)</span><span>)</span><span>)</span><span>)</span><span>)</span>

<span>(</span>svg-line-activate 'my-mode-line<span>)</span>
</pre>
</div>

<p>
Line by line:
</p>

<ul>
<li><code>my/buffer-percent</code> — any zero-argument function can be a segment; this one returns a string.</li>
<li><code>:active #'mode-line-window-selected-p</code> — a predicate; when it's false (an unfocused window) the engine applies the <code>:inactive-*</code> colours instead.</li>
<li><code>:icon</code> — a full-height "masthead" glyph drawn once on the left edge, spanning <i>both</i> rows.  This is a function, so it tracks the current buffer's mode.</li>
<li><code>:background</code> / <code>:foreground</code> — literal colours, or (as here) zero-argument functions evaluated on every render, so the bar follows your theme automatically.</li>
<li><i>row 1</i> — a <code>:left/:center/:right</code> plist puts three independently-aligned segments on a single row.</li>
<li><i>row 2</i> — a plain <code>(LEFT . RIGHT)</code> cons.  Its left side mixes the custom <i>function</i> with an ordinary <code>%l:%c</code> string.</li>
<li><code>svg-line-seg</code> — turns a segment into a button: left-click runs <code>:action</code>, right-click opens the <code>:menu</code>, and <code>:help</code> shows on hover in the echo area.</li>
</ul>
</div>
</div>
</div>
<div class="outline-3">
<h3><span class="section-number-3">5.2.</span> Tab-line</h3>
<div class="outline-text-3">
<p>
The <code>tab-line</code> is where the <code>wrap</code> layout is most useful: instead of scrolling overflow off the edge, it flows tabs onto subsequent rows.
</p>

<div class="org-src-container">
<pre><span>(</span>svg-line-define 'my-tab-line
  <span>:target</span>  'tab-line
  <span>:layout</span>  'wrap
  <span>:content</span> <span>(</span><span>lambda</span> <span>()</span>
             <span>;; </span><span>each item is (LABEL . STATE)
</span>             <span>(</span>mapcar <span>(</span><span>lambda</span> <span>(</span>buf<span>)</span>
                       <span>(</span>cons <span>(</span>buffer-name buf<span>)</span>
                             <span>(</span>list <span>:current</span>  <span>(</span>eq buf <span>(</span>current-buffer<span>)</span><span>)</span>
                                   <span>:modified</span> <span>(</span>buffer-modified-p buf<span>)</span><span>)</span><span>)</span><span>)</span>
                     <span>(</span>tab-line-tabs-window-buffers<span>)</span><span>)</span><span>)</span>
  <span>:current-background</span>  <span>(</span><span>lambda</span> <span>()</span> <span>(</span>face-background 'highlight nil t<span>)</span><span>)</span>
  <span>:modified-foreground</span> <span>"</span><span>#ebcb8b</span><span>"</span><span>)</span>

<span>(</span>svg-line-activate 'my-tab-line<span>)</span>
</pre>
</div>

<ul>
<li><code>:layout 'wrap</code> — switches from rows of segments to a wrapping flow; overflowing tabs land on a new row rather than scrolling out of sight.</li>
<li>each item is <code>(LABEL . STATE)</code>, where <code>:current</code> and <code>:modified</code> in the state plist drive the per-tab highlight and unsaved tint.</li>
<li><code>:current-background</code> / <code>:modified-foreground</code> — the same value-or-function styling as the <code>lines</code> layout, just with current- and modified-tab variants.</li>
</ul>
</div>
</div>
</div>
<div class="outline-2">
<h2><span class="section-number-2">6.</span> Acknowledgement</h2>
<div class="outline-text-2">
<p>
Credit where it's due: this started as an experiment off <a href="https://github.com/rougier">Nicolas Rougier</a>'s work.  His SVG explorations and that dual-header gist demonstrated that this was possible, and showed me how well this approach works.
</p>
</div>
</div></body></html>]]></content>
        <author>
            <name>Charlie Holland</name>
            <uri>https://www.chiply.dev</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Sacha Chua: June 18: Emacs Chat with Ross A. Baker]]></title>
        <id>https://sachachua.com/blog/2026/06/emacs-chat-with-ross-a-baker/</id>
        <link href="https://sachachua.com/blog/2026/06/emacs-chat-with-ross-a-baker/"/>
        <updated>2026-06-07T18:28:45.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>
On June 18, I'll chat with <a href="https://rossabaker.com/">Ross Baker</a> about Emacs and life.
</p>

<p>
</p><div class="yt-video"><a href="https://youtube.com/live/_tEcqbi_2o8">Watch on YouTube</a></div>
<p></p>

<p>
<span class="timestamp-wrapper"><time>&lt;2026-06-18 Thu 10:30&gt;–&lt;2026-06-18 Thu 11:30&gt;</time></span> America/Toronto = Thu Jun 18 1030H EDT / 0930H CDT / 0830H MDT / 0730H PDT / 1430H UTC / 1630H CEST / 1730H EEST / 2000H IST / 2230H +08 / 2330H JST
</p>

<ul>
<li><a href="https://rossabaker.com/blog/">Blog</a>
<ul>
<li><a href="https://rossabaker.com/tags/emacs/">Posts tagged #emacs</a></li>
</ul></li>
<li><a href="https://rossabaker.com/configs/emacs/">Emacs config</a>
<ul>
<li><a href="https://rossabaker.com/configs/emacs/early-init/">Emacs Early Init</a></li>
<li><a href="https://rossabaker.com/configs/emacs/khlav-kalash/">Khlav Kalash Emacs</a></li>
<li><a href="https://rossabaker.com/configs/emacs/crab-juice/">Crab Juice Emacs</a></li>
<li><a href="https://rossabaker.com/configs/emacs/rab-starter/">Starter Emacs configuration</a></li>
</ul></li>
</ul>

<p>
This session will be recorded, and I'll update this blog post with notes.
<a href="https://sachachua.com/blog/2026/06/emacs-chat-with-ross-a-baker/">https://sachachua.com/blog/2026/06/emacs-chat-with-ross-a-baker/</a>
</p>

<p>
Find more Emacs Chats or join the fun: <a href="https://sachachua.com/emacs-chat">https://sachachua.com/emacs-chat</a>
</p>
<div><a href="https://sachachua.com/blog/2026/06/emacs-chat-with-ross-a-baker/index.org">View Org source for this post</a></div>
<p>You can <a href="mailto:sacha@sachachua.com?subject=Comment%20on%20https%3A%2F%2Fsachachua.com%2Fblog%2F2026%2F06%2Femacs-chat-with-ross-a-baker%2F&amp;body=Name%20you%20want%20to%20be%20credited%20by%20(if%20any)%3A%20%0AMessage%3A%20%0ACan%20I%20share%20your%20comment%20so%20other%20people%20can%20learn%20from%20it%3F%20Yes%2FNo%0A">e-mail me at sacha@sachachua.com</a>.</p></body></html>]]></content>
        <author>
            <name>Sacha Chua</name>
            <uri>https://sachachua.com/blog/category/emacs/feed/index.xml</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Irreal: Correcting The Orientation of macOS Photos on Linux]]></title>
        <id>https://irreal.org/blog/?p=13860</id>
        <link href="https://irreal.org/blog/?p=13860"/>
        <updated>2026-06-07T14:12:28.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>
JTR over at <a href="https://taonaw.com">The Art Of Not Asking Why</a> describes a problem—and its resolution—that I didn’t know existed. The TL;DR is that photographs taken with an iPhone are always captured in landscape mode but Apple’s software detects portrait photos and corrects the orientation on the fly.
</p>
<p>
That leads to the problem: <a href="https://taonaw.com/2026/06/03/correcting-photo-orientation-for-orgmode.html">when iPhone portrait mode photos are shown on Linux using Org mode they are shown in landscape mode</a>. You can get the details from JTR’s post.
</p>
<p>
The fix is pretty easy. He uses the <a href="https://imagemagick.org/mogrify/#gsc.tab=0">mogrify</a> tool of <a href="https://imagemagick.org/#gsc.tab=0">ImageMagick</a> to auto-orient the photos based on their EXIF data. Since he’s viewing these photos in Org mode he wants an easy way of making the conversion from within Emacs. That’s a perfect job for Álvaro Ramírez’s <a href="https://github.com/xenodium/dwim-shell-command">dwim-shell-command</a>, which JTR uses.
</p>
<p>
Take a look at the code and see how simple it is. Even if you aren’t an Elisp expert, it’s easy to do things like this with <code>dwim-shell-command</code> right from Emacs.</p>
</body></html>]]></content>
        <author>
            <name>Irreal</name>
            <uri>https://irreal.org/blog</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Bicycle for Your Mind: Much Ado About Emacs 014]]></title>
        <id>https://bicycleforyourmind.com/much-ado-about-emacs-014</id>
        <link href="https://bicycleforyourmind.com/much-ado-about-emacs-014"/>
        <updated>2026-06-07T07:00:00.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p><img src="https://cdn.blot.im/blog_c4a729f3205a44e5a9669523ddfb8b2e/_image_cache/9e504949-34a4-4d13-a541-0032c2c31bfc.png" alt="Emacs" width="512" height="512"><span class="caption">Emacs</span></p>

<h2>Org-Mode and the Capture System</h2>
<p><a href="https://orgmode.org/" target="_blank">Org-mode</a> has a capture system. You can be in any file in Emacs and invoke the capture system. Press a few keys and add text to a org heading in any file that you have set up a capture for.</p>
<p>It is easy to set it up. Firstly you assign a keyboard command to the capture system. In my case,</p>
<p><code>:bind ("C-c c" . org-capture)</code></p>
<p><img src="https://cdn.blot.im/blog_c4a729f3205a44e5a9669523ddfb8b2e/_image_cache/bd250ce1-71e9-41df-b8ca-7b107e062d4b/oc1.png" alt="Org-capture" width="697" height="988"><span class="caption">Org-capture</span></p>
<p>You get this.</p>
<p><img src="https://cdn.blot.im/blog_c4a729f3205a44e5a9669523ddfb8b2e/_image_cache/36306078-163f-4b88-988c-c7a9dab149e4/oc2.png" alt="Journal Entry" width="932" height="317"><span class="caption">Journal Entry</span></p>
<p>You press a key. Let’s say you want to add a journal entry. Press <code>j</code> and get this.</p>
<p>Type what you want to say in the buffer and when done, press <code>⌃C ⌃C</code>. This saves the additions to the journal and closes the buffer. Leaving you in the buffer you were in before you invoked the capture function.</p>
<p>My setup for the journal capture looks like this:</p>
<pre><code>("j" "journal" entry (file+datetree "~/Dropbox/org/diary2026.org")
"* %&lt;%R: &gt;\n%? \n" :empty-lines-before 1)</code></pre>
<p>This is the code-snippet which does the heavy lifting. <code>"* %&lt;%R: &gt;\n%? \n"</code></p>
<p>The explanation:</p>
<ul>
<li><code>*</code>: Creates a level-1 heading.</li>
<li><code>%&lt;%R: &gt;</code>: This is a time format code. It inserts the current time in 24-hour format (e.g., 21:45: ).</li>
<li><code>\n</code>: Inserts a line break (a new line).</li>
<li><code>%?</code>: This is where your flashing cursor will start, you can begin typing your journal entry without having to move the cursor yourself.</li>
</ul>
<p>If you set up a capture system, you can easily add content to files without having to open them.</p>
<p>It is one of the useful features of Org-mode.</p>
<h3>Tweaking the Capture System for Bookmarks</h3>
<p>I paid for lifetime access for <a href="https://pinboard.in/" target="_blank">pinboard.in</a>. But I get the feeling that this project is on maintenance mode and the developer has moved on. It still works but I want to stop relying on it and move my archived bookmarks to a plain-text Org file. I started a bookmarks.org file with this structure:</p>
<p><img src="https://cdn.blot.im/blog_c4a729f3205a44e5a9669523ddfb8b2e/_image_cache/faedbd71-21d2-4905-9dd3-174dc0a5385c/oc3.png" alt="Bookmark" width="1244" height="849"><span class="caption">Bookmark</span></p>
<p>I came up with a capture template:</p>
<pre><code>          ("b" "Bookmark" entry
           (file+headline "~/Dropbox/org/bookmark.org" "Bookmark")
           ,(concat "* %^{Title}\n")
           :empty-lines-after 1)</code></pre>
<p>The capture would put the entries under the Bookmark header and I would refile the URL’s into appropriate sections periodically. Worked for a while. I learned more about capture templates and realized that I could lessen my work by filing the URL’s into their appropriate sections at the time of capture.</p>
<p><img src="https://cdn.blot.im/blog_c4a729f3205a44e5a9669523ddfb8b2e/_image_cache/f5520aa8-e4e6-4ee9-941b-a7283b927543/oc4.png" alt="Org-capture" width="739" height="792"><span class="caption">Org-capture</span></p>
<p>I didn’t like that. I wanted to be able to file the URL under it’s relevant heading when I captured it Now when I invoke capture I get this.</p>
<p><img src="https://cdn.blot.im/blog_c4a729f3205a44e5a9669523ddfb8b2e/_image_cache/b605c864-d5b0-4123-91e5-a54c8c55e9d8/oc5.png" alt="Bookmark Choices" width="547" height="465"><span class="caption">Bookmark Choices</span></p>
<p>Press <code>b</code> and I get this.</p>
<p>I can press the relevant key for the section I want and then paste in the URL. It gets inserted to the appropriate section.</p>
<p>Makes it easy.</p>
<p>This is an excerpt from the relevant section in my init.el.</p>
<pre><code>;; org-capture
(use-package org-capture
  :ensure nil
  :bind ("C-c c" . org-capture)
  :config
  (setq org-capture-templates
        `(("b" "Bookmark Templates")
          ("bc" "Computer" entry
           (file+headline "~/Dropbox/org/bookmark.org" "Computer")
           "** %?"
           :empty-lines-after 1)
          ("be" "Emacs" entry
           (file+headline "~/Dropbox/org/bookmark.org" "Emacs")
           "** %?"
           :empty-lines-after 1)
          ("bm" "Misc" entry
           (file+headline "~/Dropbox/org/bookmark.org" "Misc")
           "** %?"
           :empty-lines-after 1)
          ("bp" "Politics" entry
           (file+headline "~/Dropbox/org/bookmark.org" "Politics")
           "** %?"
           :empty-lines-after 1)
          ("br" "Religion" entry
           (file+headline "~/Dropbox/org/bookmark.org" "Religion")
           "** %?"
           :empty-lines-after 1)
          ("bs" "Shop" entry
           (file+headline "~/Dropbox/org/bookmark.org" "Shop")
           "** %?"
           :empty-lines-after 1)
          ("bw" "Writing" entry
           (file+headline "~/Dropbox/org/bookmark.org" "Writing")
           "** %?"
           :empty-lines-after 1)

          ("j" "journal" entry (file+datetree "~/Dropbox/org/diary2026.org")
           "* %&lt;%R: &gt;\n%? \n" :empty-lines-before 1))))</code></pre>
<p>This feature is one of the many that makes me love Org-mode.</p>
<h2>Tweaking Org-mode</h2>
<p>I am used to outlining programs. I have been using them for a long time. There is muscle memory build up over the years and I wanted to bring those into Org-mode. I am sure that the OG’s of Emacs are used to the Org-mode keybindings but I wanted to feel more comfortable using it. That comfort would increase if I used the keybindings I am used to.</p>
<h3>New Org Header Outside/Inside</h3>
<p>I wanted the new heading either to be a sub-heading within the current heading which conceptually is a daughter to me. Or the heading to be on the same level as the current heading I am under, conceptually a sibling. The third alternative, the new heading would be mom. That is a heading level higher than the one I was on. I wanted to be able to press a keyboard command and be at the start of the text of the new heading, mom, sibling or daughter. This piece of code does that:</p>
<pre><code>(defun my/get-org-level-at-point ()
  "Find the level of the headline the cursor is currently inside of by searching backward."
  (save-excursion
    (beginning-of-line)
    ;; 1. Check if the CURRENT line is a headline
    (if (looking-at "^\\*+")
        (length (match-string 0))
      ;; 2. If not, search backward for the nearest headline
      (if (re-search-backward "^\\*+" (point-min) t)
          (length (match-string 0))
        0))))

(defun my/org-insert-child-headline ()
  "Insert a new headline that is a child (Level + 1) at the end of the current subtree."
  (interactive)
  (let ((level (my/get-org-level-at-point)))
    (if (&gt; level 0)
        (progn
          (org-end-of-subtree) 
          (newline)
          (insert (make-string (+ level 1) ?*) " "))
      (user-error "Not inside an Org headline"))))

(defun my/org-insert-sibling-headline ()
  "Insert a new headline at the same level at the end of the current subtree."
  (interactive)
  (let ((level (my/get-org-level-at-point)))
    (if (&gt; level 0)
        (progn
          (org-end-of-subtree) 
          (newline)
          (insert (make-string level ?*) " "))
      (user-error "Not inside an Org headline"))))

(defun my/org-insert-promoted-headline ()
  "Insert a new headline one level higher (Level - 1) at the end of the current subtree."
  (interactive)
  (let ((level (my/get-org-level-at-point)))
    (if (&gt; level 0)
        (let ((new-level (max 1 (- level 1))))
          (org-end-of-subtree) 
          (newline)
          (insert (make-string new-level ?*) " "))
      (user-error "Not inside an Org headline"))))</code></pre>
<h3>Tweaking Some More</h3>
<p>I am fond of the keybinding <code>M-&lt;right&gt;</code> and <code>M-&lt;left&gt;</code> as navigation keys in Emacs. In Org-mode it is bound to <code>org-metaright</code> and <code>org-metaleft</code>. That didn’t sound good to me. I was used to <code>C-s-&lt;right&gt;</code> and <code>C-s-&lt;left&gt;</code> for this function. Similarly <code>M-&lt;up&gt;</code> and <code>M-&lt;down&gt;</code> didn’t make sense to me. Too many years of using <code>C-s-&lt;up&gt;</code> and <code>C-s-&lt;down&gt;</code> for this function. So I changed them.</p>
<p>And I added keybindings for the functions I talk about in the previous section.</p>
<pre><code>(use-package org
  :bind (:map org-mode-map
              ("M-s-i" . my/org-insert-child-headline)
              ("M-s-s" . my/org-insert-sibling-headline)
              ("M-s-o" . my/org-insert-promoted-headline)
              ("C-s-&lt;right&gt;" . org-metaright)
              ("C-s-&lt;left&gt;" . org-metaleft)
              ("C-s-&lt;up&gt;" . org-metaup)
              ("C-s-&lt;down&gt;" . org-metadown))
  :config
  ;; Optional: Unbind originals
  (define-key org-mode-map (kbd "M-&lt;right&gt;") nil)
  (define-key org-mode-map (kbd "M-&lt;left&gt;") nil)
  (define-key org-mode-map (kbd "M-&lt;up&gt;") nil)
  (define-key org-mode-map (kbd "M-&lt;down&gt;") nil))</code></pre>
<p>This is all I have for today.</p>
<p>macosxguru at the gmail thingie.</p>
<p><strong>Update</strong>: Howard Melman improved the unbinding code with this alternative:</p>
<pre><code>  (keymap-unset org-mode-map "M-&lt;right&gt;")
  (keymap-unset org-mode-map "M-&lt;left&gt;")</code></pre>
<p><strong>Note</strong>: I had help from Ollama with the code.</p> </body></html>]]></content>
        <author>
            <name>Bicycle for Your Mind</name>
            <uri>https://bicycleforyourmind.com</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Sacha Chua: Emacs PDF View: Replace current page with file using PDFtk]]></title>
        <id>https://sachachua.com/blog/2026/06/emacs-pdf-view-replace-current-page-with-file-using-pdftk/</id>
        <link href="https://sachachua.com/blog/2026/06/emacs-pdf-view-replace-current-page-with-file-using-pdftk/"/>
        <updated>2026-06-07T00:35:27.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>
I needed to replace a page in a PDF with another PDF. This was a bit
of an annoying process on my iPad involving copying and pasting pages
in Noteful and then re-exporting them as a PDF, but it was easy to do
in Emacs thanks to <a target="_blank" href="https://melpa.org/#/pdf-tools">pdf-tools</a> and <a href="https://www.pdflabs.com/tools/pdftk-server/">PDFtk</a>.
</p>


<div class="org-src-container">
<pre><code><span class="org-comment-delimiter">;;;</span><span class="org-comment">###</span><span class="org-comment"><span class="org-warning">autoload</span></span>
(<span class="org-keyword">defun</span> <span class="org-function-name">sacha-pdf-view-replace-current-page-with-file</span> (file)
  <span class="org-doc">"Replace the current page in PDF View with FILE.</span>
<span class="org-doc">Requires pdftk."</span>
  (<span class="org-keyword">interactive</span> <span class="org-string">"FFile to insert: "</span>)
  (<span class="org-keyword">let</span> ((temp-file (concat (make-temp-name <span class="org-string">"pdf-view"</span>) <span class="org-string">".pdf"</span>)))
    (call-process
     <span class="org-string">"pdftk"</span>
     nil nil nil
     (concat <span class="org-string">"A="</span> (expand-file-name (buffer-file-name)))
     (concat <span class="org-string">"B="</span> (expand-file-name file))
     <span class="org-string">"cat"</span>
     (format <span class="org-string">"A%d-%d"</span>
             1
             (1- (<span class="org-keyword">pdf-view-current-page</span>)))
     <span class="org-string">"B"</span>
     (format <span class="org-string">"A%d-end"</span>
             (1+ (<span class="org-keyword">pdf-view-current-page</span>)))
     <span class="org-string">"output"</span>
     temp-file)
    (rename-file temp-file (buffer-file-name) t)))
</code></pre>
</div>


<div class="note">This is part of my <a href="https://sachachua.com/dotemacs#navigation-pdf-view-emacs-pdf-view-replace-current-page-with-file-using-pdftk">Emacs configuration.</a></div><div><a href="https://sachachua.com/blog/2026/06/emacs-pdf-view-replace-current-page-with-file-using-pdftk/index.org">View Org source for this post</a></div>
<p>You can <a href="mailto:sacha@sachachua.com?subject=Comment%20on%20https%3A%2F%2Fsachachua.com%2Fblog%2F2026%2F06%2Femacs-pdf-view-replace-current-page-with-file-using-pdftk%2F&amp;body=Name%20you%20want%20to%20be%20credited%20by%20(if%20any)%3A%20%0AMessage%3A%20%0ACan%20I%20share%20your%20comment%20so%20other%20people%20can%20learn%20from%20it%3F%20Yes%2FNo%0A">e-mail me at sacha@sachachua.com</a>.</p></body></html>]]></content>
        <author>
            <name>Sacha Chua</name>
            <uri>https://sachachua.com/blog/category/emacs/feed/index.xml</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Raymond Zeitler: Follow-on to exeln]]></title>
        <id>https://ray-on-emacs.blogspot.com/2026/06/follow-on-to-exeln.html</id>
        <link href="https://ray-on-emacs.blogspot.com/2026/06/follow-on-to-exeln.html"/>
        <updated>2026-06-06T23:41:48.603Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>Sebastián Monía<sup>1</sup> offered some alternatives to
the <code>exeln</code> function that I posted on June
4.<sup>2</sup></p>

<p>First, he pointed out that there's no need to
bind <code>asynch</code> with the <code>let</code> function. Instead he
suggested that I use <code>(when arg "&amp;")</code> to append the
ampersand when there's a prefix argument.
Thus, <code>shell-command</code> can be called this way:</p>

<pre>(shell-command (concat
                (buffer-substring
                 (line-beginning-position) (line-end-position))
                (<span>when</span> arg <span>"&amp;"</span>)))
</pre>

<p>Second, call <code>async-shell-command</code> rather
  than <code>shell-command</code> with the "&amp;" as suggested
  in <code>shell-command</code>'s doc string, which says, "You can
  also use <code>async-shell-command</code> that automatically adds
  '&amp;'."<sup>3</sup></p>

<p>Third, use <code>thing-at-point</code> from the built-in
  thingatpt.el library to return the line at point rather
  than calling <code>buffer-substring</code>.</p>

<pre>(<span>defun</span> <span>exeln</span> (arg)
  <span>"Execute current line as a shell command.</span>
<span>With prefix ARG, run asynchronously."</span>
  (<span>interactive</span> <span>"P"</span>)
  (funcall (<span>if</span> arg
               #'async-shell-command
             #'shell-command)
           (thing-at-point 'line t)))
</pre>

<p>And although he didn't mention it explicitly, he reworded the doc
  string -- it blends in seamlessly with the native functions' doc strings.</p>

<p>I set out to contribute to the Emacs community, but I'm getting so
  much more out of it than I expected!  Thank you again, Sebastián Monía!</p>
  
<hr>
<sup>1</sup> <a href="https://site.sebasmonia.com/">https://site.sebasmonia.com/</a><br>
<sup>2</sup> <a href="https://ray-on-emacs.blogspot.com/search/label/exeln-execute-line.html">exeln-execute-line.html</a><br>
<sup>3</sup> <a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Single-Shell.html#index-shell_002dcommand">GNU Emacs online shell-command help</a><br>
</body></html>]]></content>
        <author>
            <name>Raymond Zeitler</name>
            <uri>https://ray-on-emacs.blogspot.com/search/label/Emacs</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Irreal: Emacs 31.0.90 Pretest]]></title>
        <id>https://irreal.org/blog/?p=13858</id>
        <link href="https://irreal.org/blog/?p=13858"/>
        <updated>2026-06-06T14:42:58.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>
Sean Whitton writes to tell us that <a href="https://lists.gnu.org/archive/html/emacs-devel/2026-06/msg00118.html">the first Emacs 31 pretest, emacs.31.0.90, is available</a> for download. It’s been almost two years since the first Emacs 30 pretest came out so we’re pretty much on schedule for our yearly major release.
</p>
<p>
As always, Irreal wants to give a huge shout out of thanks to all the developers who work so hard to keep the Emacs development bandwagon rolling. They do all this for free so we each owe them a word of thanks and, as I always say, the drinks are on us if we find ourselves in the same bar as one of them.
</p>
<p>
Whitton’s post has all the details concerning downloading and verifying the latest tarball. If you don’t mind living on the edge, give it a try and report any problems.</p>
</body></html>]]></content>
        <author>
            <name>Irreal</name>
            <uri>https://irreal.org/blog</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Marcin Borkowski: Copying images in Emacs]]></title>
        <id>https://mbork.pl/2026-06-06_Copying_images_in_Emacs</id>
        <link href="https://mbork.pl/2026-06-06_Copying_images_in_Emacs"/>
        <updated>2026-06-06T04:54:01.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body>A few weeks ago I was on vacation. Of course I brought back quite a few pictures with me. When I got back, I sat to select some of them to make a gallery for my family and friends. I started with copying all pictures from two mobile phones and a camera to my laptop. Then I wanted to copy a few carefully chosen images to one directory. To my surprise, Emacs’ Image mode does not have a command to copy the currently viewed image to another directory.</body></html>]]></content>
        <author>
            <name>Marcin Borkowski</name>
            <uri>https://mbork.pl/Homepage</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Dave Pearson: blogmore.el v4.6.0]]></title>
        <id>https://blog.davep.org/2026/06/05/blogmore-el-v4-6-0.html</id>
        <link href="https://blog.davep.org/2026/06/05/blogmore-el-v4-6-0.html"/>
        <updated>2026-06-05T19:01:30.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>After <a href="https://blog.davep.org/2026/06/04/blogmore-v2-38-0.html">adding floating and inline tables of contents in
BlogMore</a> the other day, it was time to
update <a href="https://github.com/davep/blogmore.el" target="_blank"><code>blogmore.el</code></a> to include
commands to toggle the related frontmatter.</p>
<p>So, with the release of <a href="https://github.com/davep/blogmore.el/releases/tag/v4.6.0" target="_blank"><code>blogmore.el</code>
v4.6.0</a>, two new
commands are now available:</p>
<ul>
<li><code>blogmore-toggle-show-toc</code> toggles the <code>show_toc</code> frontmatter property.</li>
<li><code>blogmore-toggle-show-toc-inline</code> toggles the <code>show_toc_inline</code>
  frontmatter property.</li>
</ul>
<p>Both have also been added to the transient menu so they're easy to discover
and use.</p></body></html>]]></content>
        <author>
            <name>Dave Pearson</name>
            <uri>https://blog.davep.org</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Lars Ingebrigtsen: Super Simple Spam Splitting for Gnus]]></title>
        <id>https://lars.ingebrigtsen.no/2026/06/05/super-simple-spam-splitting-for-gnus/</id>
        <link href="https://lars.ingebrigtsen.no/2026/06/05/super-simple-spam-splitting-for-gnus/"/>
        <updated>2026-06-05T11:44:55.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p><a href="https://lars.ingebrigtsen.no/wp-content/uploads/2026/06/2026-06-05.jpeg"><img loading="lazy" src="https://lars.ingebrigtsen.no/wp-content/uploads/2026/06/2026-06-05.jpeg" alt="" width="840" height="1048" srcset="https://lars.ingebrigtsen.no/wp-content/uploads/2026/06/2026-06-05.jpeg 1392w, https://lars.ingebrigtsen.no/wp-content/uploads/2026/06/2026-06-05-240x300.jpeg 240w, https://lars.ingebrigtsen.no/wp-content/uploads/2026/06/2026-06-05-820x1024.jpeg 820w, https://lars.ingebrigtsen.no/wp-content/uploads/2026/06/2026-06-05-768x959.jpeg 768w, https://lars.ingebrigtsen.no/wp-content/uploads/2026/06/2026-06-05-1230x1536.jpeg 1230w"></a></p>
<p>Spam is an eternal problem, and while SpamAssassin is pretty good (I get around 700 mails per day, of which 670 are rejected as spam), there’s still some stuff that persistently gets through.  A goodly portion of that is traditional random spam from random accounts, and there’s not much to be done about that, but there’s a recent trend of legitimate-looking things coming from persistent accounts — like BackerHome and BackerHive.</p>
<p>I’m guessing that eventually these will get so bad reputations that they end up on RBLs and will disappear into the mists, but meanwhile…  I just thought that there should be a mechanism in Gnus to split these message to the spam group — without having to do much work.</p>
<p><video poster="https://lars.ingebrigtsen.no/wp-content/uploads/2026/06/postereOZYNV001.jpg"></video></p>
<p>Tada!</p>
<p>It’s a small package, and you can find it on <a href="https://github.com/larsmagne/gnus-spsl.el">Microsoft Github</a>.  It’s basically a tiny minor mode that adds a couple of commands, so you just hit z, check the entry (or not) and then C-c C-c.</p>
<p>(There’s also a command to edit the split data if things go off the rails, or just because you want to.)</p>
<p><a href="https://lars.ingebrigtsen.no/wp-content/uploads/2026/06/2026-06-05-1.jpeg"><img loading="lazy" src="https://lars.ingebrigtsen.no/wp-content/uploads/2026/06/2026-06-05-1.jpeg" alt="" width="840" height="207" srcset="https://lars.ingebrigtsen.no/wp-content/uploads/2026/06/2026-06-05-1.jpeg 1391w, https://lars.ingebrigtsen.no/wp-content/uploads/2026/06/2026-06-05-1-300x74.jpeg 300w, https://lars.ingebrigtsen.no/wp-content/uploads/2026/06/2026-06-05-1-1024x253.jpeg 1024w, https://lars.ingebrigtsen.no/wp-content/uploads/2026/06/2026-06-05-1-768x189.jpeg 768w"></a></p>
<p>B t to check the split trace, as normal.</p>
<p>So there you go.  May your inboxes be slightly less spammy.</p>
<p>(And it’s fun doing some Gnus work again for the first time in years…  I’ve forgotten what all the functions are called, though, so I had to use Claude to remind me.  *gulp*)</p>
</body></html>]]></content>
        <author>
            <name>Lars Ingebrigtsen</name>
            <uri>https://lars.ingebrigtsen.no</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Raymond Zeitler: exeln: EXEcute LiNe]]></title>
        <id>https://ray-on-emacs.blogspot.com/2026/06/exeln-execute-line.html</id>
        <link href="https://ray-on-emacs.blogspot.com/2026/06/exeln-execute-line.html"/>
        <updated>2026-06-04T17:53:49.163Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>The following exeln function passes the current line to the system
  shell, which executes it, thus EXEcuting LiNe.</p>
<p>On Windows x86, my GNU Emacs has shell-file-name set to
  cmdproxy.exe, which is provided by x86_64-w64-mingw32, with which
  Emacs was compiled.</p>
<p>shell is invoked synchronously by default; a prefix argument can
  change this to asynchronous.</p>
<p>In the video below, point is on a line of text that would print the
  contents of hello_whirled.txt when entered at the Windows command
  prompt (or DOS prompt).  I press <code>C-c x</code>, which is bound
  to exeln.  The command is executed and the output is shown in *Shell
  Command Output*, the default buffer used for synchronous output from
  <code>shell-command</code>.</p><div class="separator"></div>
<div class="org-src-container">
<pre>(<span>defun</span> <span>exeln</span> (arg)
    <span>"Execute the current line as a shell command.</span>
<span>With prefix arg, operate asynchronously, same as calling</span>
<span>(shell-command COMMAND) where COMMAND ends in '</span><span>&amp;</span><span>'.</span>
<span>Otherwise, execute synchronously."</span>
  (<span>interactive</span> <span>"P"</span>)
  (<span>let</span> (asynch)
    (<span>if</span> arg
        (<span>setq</span> asynch <span>"&amp;"</span>))
    (shell-command (concat
                    (buffer-substring
                     (line-beginning-position) (line-end-position))
                    asynch))))
</pre>
</div>
<hr>
<p>2026-06-04 Add demo video </p>

</body></html>]]></content>
        <author>
            <name>Raymond Zeitler</name>
            <uri>https://ray-on-emacs.blogspot.com/search/label/Emacs</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Charles Choi: Revisiting Emacs Keyboard Macros with a Mouse]]></title>
        <id>http://yummymelon.com/devnull/revisiting-emacs-keyboard-macros-with-a-mouse.html</id>
        <link href="http://yummymelon.com/devnull/revisiting-emacs-keyboard-macros-with-a-mouse.html"/>
        <updated>2026-06-04T16:35:00.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>“No-code automation” has been in Emacs far longer than its usage as a term of art. Better known as <em>keyboard macros</em>, this feature has allowed Emacs users to achieve their bespoke needs for decades, all without needing to know a whit about Lisp. I can testify to this personally: though I’ve been using Emacs since the early 90’s, only in the past three years has writing Elisp played any part in it. For most of my Emacs journey, I got by with just making keyboard macros.</p>
<p>If you’re unfamiliar with them, here are two links you should get to know:</p>
<ul>
<li><a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Keyboard-Macros.html">The official Emacs manual for keyboard macros</a> ((emacs) Keyboard Macros)</li>
<li>Mickey Petersen’s post - <a href="https://www.masteringemacs.org/article/keyboard-macros-are-misunderstood">“Keyboard Macros are Misunderstood”</a></li>
</ul>
<p>My addition to the knowledge of those posts is to boost this fact: <strong>mouse events can also be captured by a keyboard macro</strong>. If you know where a command <em>is</em> in a menu, you can also record clicking on it. I think the ability to combine both keyboard and mouse events in a keyboard macro is compelling, so much so that I decided to emphasize this in Anju.</p>
<p>The recent <a href="https://github.com/kickingvegas/anju">Anju</a> v1.5.0 release added the menu “Tools › Macro Recorder” to the menu bar as shown below.</p>
<p><img alt="img" src="http://yummymelon.com/devnull/images/anju-kmacros/anju-main-menu-tools-kmacro.png"></p>
<p>With this, mouse enthusiasts can create and run keyboard macros without need to recall keybindings or deal with inconsistent command naming, as observed in Petersen’s post.</p>
<p>One thing that I TILed about keyboard macros in building this menu was the command <code>list-keyboard-macros</code> (see <a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Kmacro-Menu.html">(emacs) Kmacro menu</a>). This command is available in the “Macro Recorder” menu as the item “List macros”. This lets you manage multiple keyboard macros that have been defined during a session.</p>
<p>If this interests you, I invite you install <a href="https://melpa.org/#/anju">Anju from MELPA</a> and give it a try. Let me know <a href="https://github.com/kickingvegas/anju/discussions/121">what you think</a>!</p></body></html>]]></content>
        <author>
            <name>Charles Choi</name>
            <uri>http://yummymelon.com/devnull/</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Irreal: Inhibit The Mouse In Emacs]]></title>
        <id>https://irreal.org/blog/?p=13853</id>
        <link href="https://irreal.org/blog/?p=13853"/>
        <updated>2026-06-04T15:20:56.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>
James Cherti has a new version (Release 1.0.4) of his <a href="https://github.com/jamescherti/inhibit-mouse.el">inhibit-mouse</a> package available. As the name suggests, it disables the mouse while you’re using Emacs. I’ve <a href="https://irreal.org/blog/?p=13286">written about inhibit-mouse before</a>. As I said in my previous post my first thought was that I don’t need this because I’ve already trained myself not to use the mouse while I’m in Emacs.
</p>
<p>
The thing is, though, that I mainly use my laptop—a MacBook Pro—which has a trackpad for mouse operations. Since I often use my laptop on my lap while sitting on the couch, it’s easy to inadvertently touch the trackpad with my palm and change focus from one window to another. Turning off the mouse would eliminate that from happening. Still, I <i>do</i> use my trackpad to scroll Web pages and emails that are displayed with WebKit because there’s no other decent way of doing so. Happily, inhibit-mouse is very configurable and you can, in particular, disable it’s use in any major modes you like. That may solve my WebKit problem.
</p>
<p>
Inhibit-mouse is a reimagining of Steve Purcell’s <a href="https://github.com/purcell/disable-mouse">disable-mouse</a> package. Cherti claims inhibit-mouse has some advantages—such as being more efficient—over disable-mouse. Take a look at the repository to see what they are.
</p>
<p>
If you’re looking for a way to banish the mouse from your Emacs experience, this seems like a good way of doing so. You can even leave a couple of escape hatches if you need to.</p>
</body></html>]]></content>
        <author>
            <name>Irreal</name>
            <uri>https://irreal.org/blog</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Sacha Chua: Emacs Chat 25: Ben Zanin (@gnomon@mastodon.social)]]></title>
        <id>https://sachachua.com/blog/2026/06/june-4-emacs-chat-with-ben-zanin-gnomon-mastodon-social/</id>
        <link href="https://sachachua.com/blog/2026/06/june-4-emacs-chat-with-ben-zanin-gnomon-mastodon-social/"/>
        <updated>2026-06-04T12:50:07.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><div class="update">
<p>
<span class="timestamp-wrapper"><time>[2026-06-10 Wed]</time></span>: Updated the transcript
</p>

</div>

<p>
I chatted with Ben Zanin about music, Org Mode, Emacs in terminals and on an Android, keyboards, elfeed, and more.
<video src="https://archive.org/download/emacs-chat-25-ben-zanin/emacs-chat-25-ben-zanin.mp4" poster="https://sachachua.com/blog/2026/06/june-4-emacs-chat-with-ben-zanin-gnomon-mastodon-social/2026-05-02-12-18-58%20ben-zanin.png"><track><span>Video not supported. Thumbnail:<br><img src="https://sachachua.com/blog/2026/06/june-4-emacs-chat-with-ben-zanin-gnomon-mastodon-social/2026-05-02-12-18-58%20ben-zanin.png" alt="Thumbnail"></span></video>
</p>

<p>
<a href="https://archive.org/details/emacs-chat-25-ben-zanin/">View in the Internet Archive</a>, <a href="https://youtube.com/live/ax4f5uaOHA8">watch or comment on YouTube</a>, <a href="https://sachachua.com/blog/category/emacs/feed/index.xml#ID-emacs-chat-25-ben-zanin-transcript">read the transcript online</a>, <a href="https://sachachua.com/blog/2026/06/june-4-emacs-chat-with-ben-zanin-gnomon-mastodon-social/emacs-chat-25-ben-zanin.vtt">download the transcript</a>, or <a href="mailto:sacha@sachachua.com">e-mail me</a>.
</p>
<div class="outline-3">
<h3><a href="https://sachachua.com/blog/category/emacs/feed/index.xml#emacs-chats-emacs-chat-25-ben-zanin-gnomon-mastodon-social-related-links">Related links</a></h3>
<div class="outline-text-3">
<ul>
<li><a href="https://mastodon.social/@gnomon">Ben Zanin (@gnomon@mastodon.social) - Mastodon</a>: Robertson screwdriver owner, believer in the value of personal-scale computing and skeptic of the value of computing scales any larger than that</li>
<li><a href="https://git.sr.ht/~gnomon/emacs-config-gnomon">~gnomon/emacs-config-gnomon - An edited/truncated subset of my dotfiles repo to pick out only those commits and files that are pertinent to my emacs configuration, as of 2026-05-06 - sourcehut git</a></li>
<li><a href="https://git.sr.ht/~gnomon/">~gnomon's git repositories</a></li>
<li><a target="_blank" href="https://melpa.org/#/elfeed">elfeed</a>, <a target="_blank" href="https://melpa.org/#/elfeed-curate">elfeed-curate</a></li>
<li><a target="_blank" href="https://melpa.org/#/versuri">versuri</a> and <a target="_blank" href="https://melpa.org/#/mpdel">mpdel</a> - lyrics, music</li>
<li><a target="_blank" href="https://melpa.org/#/avy">avy</a></li>
<li><a href="https://wezterm.org/index.html">WezTerm - Wez's Terminal Emulator</a></li>
<li><a href="https://keychron.ca/products/keychron-b11-pro-ultra-slim-wireless-foldable-keyboard-us-ansi-layout">Keychron B11 Pro Ultra-Slim Wireless Foldable Keyboard (US ANSI Layout – Keychron Canada</a></li>
<li>tea-timer and <a target="_blank" href="https://elpa.gnu.org/packages/tmr.html">tmr</a></li>
<li>mytoots</li>
<li><a href="https://public-inbox.org/README">public-inbox</a> for reading mailing lists</li>
</ul>

<p>
You can add the iCal for upcoming Emacs Chat episodes to your calendar. <a href="https://sachachua.com/topic/emacs-chat/upcoming-emacs-chats.ics">https://sachachua.com/topic/emacs-chat/upcoming-emacs-chats.ics</a>
</p>

<p>
Find more Emacs Chats or join the fun: <a href="https://sachachua.com/emacs-chat">https://sachachua.com/emacs-chat</a>
</p>
</div>
</div>
<div class="outline-3">
<h3><a href="https://sachachua.com/blog/category/emacs/feed/index.xml#emacs-chat-25-ben-zanin-chapters">Chapters</a></h3>
<div class="outline-text-3">
<p>
</p><ul>
<li><span class="audio-time">0:00</span> How Ben got started with Emacs</li>
<li><span class="audio-time">2:19</span> Ben got into Emacs because of twittering-mode</li>
<li><span class="audio-time">4:30</span> Emacs as a media playback platform with Versuri and Mpdel</li>

<li><span class="audio-time">9:13</span> Emacs on Android with Termux</li>
<li><span class="audio-time">13:44</span> Keyboards and other devices</li>
<li><span class="audio-time">16:44</span> Benefits of a split keyboard</li>
<li><span class="audio-time">18:22</span> Meeting workflow</li>
<li><span class="audio-time">21:11</span> Narrowing</li>
<li><span class="audio-time">22:58</span> There's even an internal Slack channel about Emacs at Ben's company</li>
<li><span class="audio-time">24:50</span> Ben keeps Org capture templates as individual files and adapts them to different meeting flows</li>
<li><span class="audio-time">28:45</span> Personal-scale software and the journey</li>

<li><span class="audio-time">34:07</span> vc-git-grep for finding notes again</li>
<li><span class="audio-time">36:55</span> Add keywords to make things easier to find again</li>
<li><span class="audio-time">37:47</span> Keybindings and terminals; wezterm</li>
<li><span class="audio-time">42:38</span> Timers: tea-timer, tmr</li>
<li><span class="audio-time">43:57</span> Different stages of package use</li>
<li><span class="audio-time">44:47</span> Elfeed</li>
<li><span class="audio-time">48:36</span> Spoilers</li>

<li><span class="audio-time">49:53</span> Comparing different news sources</li>
<li><span class="audio-time">53:13</span> Bookmark naming conventions</li>
<li><span class="audio-time">53:24</span> Naming conventions simplify building new workflows</li>
<li><span class="audio-time">53:50</span> elfeed-curate for annotations</li>

<li><span class="audio-time">55:46</span> mytoots archives Mastodon toots</li>
<li><span class="audio-time">57:06</span> Mentoring offer</li>
<li><span class="audio-time">58:02</span> A local instance of public-inbox can let you use Gnus to read mailing lists quickly</li>
</ul>

<p></p>
</div>
</div>
<div class="outline-3">
<h3><a href="https://sachachua.com/blog/category/emacs/feed/index.xml#emacs-chat-25-ben-zanin-transcript-section">Transcript</a></h3>
<div class="outline-text-3">
<a name="ID-emacs-chat-25-ben-zanin-transcript"></a>Expand this to read the transcript
<p>
</p><div class="full-transcript"><p></p><div class="transcript-heading"><span class="audio-time">0:00</span> <strong>How Ben got started with Emacs</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong>  I forgot to ask you how your last</span> <span class="audio-time caption">name is pronounced.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  Oh, Zanin.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  This is Emacs chat number 25 and here I am with</span> <span class="audio-time caption">Ben Zanin.</span> <span class="audio-time caption">You have a math background and now you're in IT.</span> <span class="audio-time caption">Where did you encounter Emacs in the journey?</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  So the reason I have a math</span> <span class="audio-time caption">background is that I wanted to get into</span> <span class="audio-time caption">programming language design and at the time so</span> <span class="audio-time caption">that led me over to lambda calculus and that kind</span> <span class="audio-time caption">of thing and at the time it was at the time I was</span> <span class="audio-time caption">getting into university in like 2005-2006</span> <span class="audio-time caption">It was impossible to get into the computer programs,</span> <span class="audio-time caption">but I could get into math.</span> <span class="audio-time caption">I figured that would move me in the direction that I wanted</span> <span class="audio-time caption">to go in, so I did.</span> <span class="audio-time caption">Got to third year, and then every professor</span> <span class="audio-time caption">who taught any of the courses I cared about</span> <span class="audio-time caption">all left the faculty at the same time.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Oh no!</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  Yeah. Anyhow, that's a different story.</span> <span class="audio-time caption">But yeah, I got into Emacs because in the process</span> <span class="audio-time caption">of learning about Lambda Calculus, the Lisp</span> <span class="audio-time caption">weenies found me.</span> <span class="audio-time caption">And yeah, I spent a bunch of time learning about</span> <span class="audio-time caption">that.</span> <span class="audio-time caption">And it wasn't until like 10 years after I got</span> <span class="audio-time caption">into Common Lisp and Scheme that I actually got</span> <span class="audio-time caption">into Emacs at all.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  That's interesting.</span> <span class="audio-time caption">Usually people, like, if they're doing Lispy</span> <span class="audio-time caption">things, they get into Emacs right away because</span> <span class="audio-time caption">Lisp.</span> <span class="audio-time caption">But okay, so 10 years after.</span> <span class="audio-time caption"></span> <span class="audio-time caption">You're already well-used to parentheses at that point.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  Yes.</span> <span class="audio-time caption">But I guess it wasn't until about ten years ago,</span> <span class="audio-time caption">like around 2015 or so,</span> <span class="audio-time caption">that I started really getting into Emacs.</span> <span class="audio-time caption">I would still consider myself to be a beginner on that front.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Oh yeah? So what got you to get into it more?</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  I found that I was looking for more structured</span> <span class="audio-time caption">data management processes.</span> <span class="audio-time caption">Basically, I was looking for personal information</span> <span class="audio-time caption">management.</span> <span class="audio-time caption">And I kept bouncing off Emacs because I wanted to</span> <span class="audio-time caption">get into those tasks, but Emacs was such a rich</span> <span class="audio-time caption">learning process that I kept getting sidetracked,</span> <span class="audio-time caption">so I kept bouncing off of it.</span> <p></p><div class="transcript-heading"><span class="audio-time">2:19</span> <strong>Ben got into Emacs because of twittering-mode</strong></div><p></p><span class="audio-time caption"><strong>Ben:</strong> But I have to admit that one of the things that</span> <span class="audio-time caption">originally actually got me into Emacs was</span> <span class="audio-time caption">twittering mode.</span> <span class="audio-time caption">Oh yeah?</span> <span class="audio-time caption">Because I was looking for a tool that would let</span> <span class="audio-time caption">me, we'll probably get into this later in the</span> <span class="audio-time caption">chat, but I was looking for a tool that would let</span> <span class="audio-time caption">me keep a larger window of context about the</span> <span class="audio-time caption">conversations that I've been in.</span> <span class="audio-time caption">The Twitter apps and the Twitter website</span> <span class="audio-time caption">implemented a really narrow window.</span> <span class="audio-time caption">I wanted to be able to search back a couple</span> <span class="audio-time caption">of weeks for stuff that I had seen or talked</span> <span class="audio-time caption">about previously.</span> <span class="audio-time caption">Twittering-mode gave me the ability to keep</span> <span class="audio-time caption">days or weeks of context in a single buffer</span> <span class="audio-time caption">that I could then immediately search.</span> <span class="audio-time caption">So I didn't actually get into Emacs as a text editor,</span> <span class="audio-time caption">I got into it as an application platform,</span> <span class="audio-time caption">and then gradually learned the rest of it.</span> <span class="audio-time caption">This is actually fantastic. So I kind of stuck around after that.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  That is the first time I've heard of someone</span> <span class="audio-time caption">coming to Emacs because of Twitter.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  No, it's deeply embarrassing.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  No, it's wonderful.</span> <span class="audio-time caption">I love that there's just so many</span> <span class="audio-time caption">reasons why people come and the fact that you</span> <span class="audio-time caption">could find something that would let you take</span> <span class="audio-time caption">those notes and see that context and reply to it,</span> <span class="audio-time caption">and even, as I see in your config, work around</span> <span class="audio-time caption">slow keyboard response issues.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  And also the fact that that's still</span> <span class="audio-time caption">in the config despite Twitter itself...</span> <span class="audio-time caption">I think I abandoned it in 2017, but it takes me a</span> <span class="audio-time caption">little while to rip things out of my config.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Yeah, I see you're a lot more</span> <span class="audio-time caption">active in Mastodon these days. I see your</span> <span class="audio-time caption">Monsterdon posts scrolled by my feed every so often.</span> <span class="audio-time caption">Yeah, so we dove right into that because a lot</span> <span class="audio-time caption">of the stuff in your config is interesting and</span> <span class="audio-time caption">your workflows too.</span> <span class="audio-time caption">My idea for these Emacs chats is to</span> <span class="audio-time caption">show people the kind of stuff that isn't</span> <span class="audio-time caption">immediately obvious to newbies when they're</span> <span class="audio-time caption">looking at someone's config.</span> <span class="audio-time caption">Because a lot of the stuff is new workflows and</span> <span class="audio-time caption">how the keyboard shortcuts work together and how</span> <span class="audio-time caption">this stuff fits into your life.</span> <span class="audio-time caption">That's not immediately obvious from the code.</span> <span class="audio-time caption">I've taken a look at your config, but before</span> <span class="audio-time caption">we jump into the gazillion things I wanted to ask</span> <span class="audio-time caption">you about, are there things that you particularly</span> <span class="audio-time caption">love about your Emacs workflow?</span> <p></p><div class="transcript-heading"><span class="audio-time">4:30</span> <strong>Emacs as a media playback platform with Versuri and Mpdel
</strong></div><p></p><a href="https://sachachua.com/blog/2026/06/june-4-emacs-chat-with-ben-zanin-gnomon-mastodon-social/emacs-chat-25-ben-zanin-00-07-24-567.jpg"><img loading="lazy" src="https://sachachua.com/blog/2026/06/june-4-emacs-chat-with-ben-zanin-gnomon-mastodon-social/emacs-chat-25-ben-zanin-00-07-24-567.jpg" alt="image from video 00:07:24.567"></a><span class="audio-time caption"><strong>Ben:</strong>  I'm probably going to get</span> <span class="audio-time caption">a little bit of deserved flak for this, but I</span> <span class="audio-time caption">use Emacs a lot as a media playback platform.</span> <span class="audio-time caption">I spend a lot of time using Emacs to listen to</span> <span class="audio-time caption">music through MPV.</span> <span class="audio-time caption">And I've got some integration with Versuri, which</span> <span class="audio-time caption">lets me...</span> <span class="audio-time caption">I think you've seen those customizations</span> <span class="audio-time caption">where what I've done is I've kind of duct-taped</span> <span class="audio-time caption">the two together.</span> <span class="audio-time caption">Versuri is an Emacs package for being able to</span> <span class="audio-time caption">quickly search through lyrics for songs.</span> <span class="audio-time caption">What I've done is I've bound Versuri to the</span> <span class="audio-time caption">point where</span> <span class="audio-time caption">I've pulled up a page of lyrics, I now have a</span> <span class="audio-time caption">hotkey that bounces me over to a search of my MPD</span> <span class="audio-time caption">library for where that song is, and vice versa.</span> <span class="audio-time caption">I've got MPD rigged up so that when I've got a</span> <span class="audio-time caption">song currently playing, I can bounce into</span> <span class="audio-time caption">Verisuri to display the lyrics for that</span> <span class="audio-time caption">particular song.</span> <span class="audio-time caption">Something you probably have not seen in my config</span> <span class="audio-time caption">yet because I haven't finished it yet...</span> <span class="audio-time caption">What I'm working on is actually integrating</span> <span class="audio-time caption">Org Mode with MPD, because I'd really like to be able to</span> <span class="audio-time caption">streamline my process where occasionally when I'm</span> <span class="audio-time caption">listening to something, I'll take notes either</span> <span class="audio-time caption">about the lyrics or about the song. I'd like</span> <span class="audio-time caption">to be able to link from Org Mode directly to</span> <span class="audio-time caption">either that song, that album, or that particular</span> <span class="audio-time caption">timecode.</span> <span class="audio-time caption">I don't have that yet, but I'm working on it.</span> <span class="audio-time caption">I think I'll probably lean on it quite a bit once</span> <span class="audio-time caption">I have it.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Yeah, yeah.</span> <span class="audio-time caption">I saw your tweet from May, I think, where you're</span> <span class="audio-time caption">talking about coming up with this</span> <span class="audio-time caption">way of taking notes.</span> <span class="audio-time caption">think if you come up with maybe a custom</span> <span class="audio-time caption">Org Mode link type that can store the annotation</span> <span class="audio-time caption">and then let you go to it, I think that would be</span> <span class="audio-time caption">really interesting.</span> <span class="audio-time caption">Especially if you figure out, okay, like, are you</span> <span class="audio-time caption">taking notes in the album?</span> <span class="audio-time caption">Are you taking notes on the song?</span> <span class="audio-time caption">Are you taking notes on this moment in the song?</span> <span class="audio-time caption">That could all be very cool.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  Actually, do you mind if I share my screen?</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Please.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  So one of the things I wanted to</span> <span class="audio-time caption">kind of note was... Let me... Oh yeah, this is</span> <span class="audio-time caption">actually going to be further embarrassing.</span> <span class="audio-time caption">I'm a terminal Emacs user.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  I saw.</span> <span class="audio-time caption">Can you increase the font size, though?</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  Absolutely, yeah.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Resizing your terminal so it's smaller</span> <span class="audio-time caption">makes everything look bigger...</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  Is that better?</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  More.</span> <span class="audio-time caption">Some of us are older.</span> <span class="audio-time caption">Thank you.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  One of the things that's kind of unusual about</span> <span class="audio-time caption">my MPD configuration is I've got a satellite config.</span> <span class="audio-time caption">Sorry, the line wrap is a little bit off here.</span> <span class="audio-time caption">What this means is that I have...</span> <span class="audio-time caption">the household file server maintains the MPD</span> <span class="audio-time caption">library, but I've got multiple playback nodes</span> <span class="audio-time caption">around the house. What that lets me do is...</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  You can play stuff on this...</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  So what this means is that I'm controlling the...</span> <span class="audio-time caption">well, in this case, that's a little</span> <span class="audio-time caption">MeLE Quieter3C that I've got in the living room</span> <span class="audio-time caption">that's kind of like the</span> <span class="audio-time caption">the home media server, the home playback machine.</span> <span class="audio-time caption">Fundamentally, I'm an ops guy, I'm a sys admin,</span> <span class="audio-time caption">and I've got, unfortunately, a fleet of machines around the house.</span> <span class="audio-time caption">What this lets me do is easily control each</span> <span class="audio-time caption">one of them.</span> <span class="audio-time caption">Instead of each one maintaining its own</span> <span class="audio-time caption">library of music files, the file server itself</span> <span class="audio-time caption">indexes them, which means that library updates</span> <span class="audio-time caption">are almost instantaneous, instead of having to</span> <span class="audio-time caption">read over the network to pull metadata out of</span> <span class="audio-time caption">each individual file.</span> <span class="audio-time caption">So having a satellite setup lets me...</span> <span class="audio-time caption">The real benefit is that MPD tracks albums,</span> <span class="audio-time caption">directories, and files as URLs.</span> <span class="audio-time caption">That means that I have a single global</span> <span class="audio-time caption">namespace of URLs for all of the media that's</span> <span class="audio-time caption">currently in the library, which means that I can</span> <span class="audio-time caption">annotate from any machine, but have it mean one thing.</span> <span class="audio-time caption">It makes it convenient for navigation, but it</span> <span class="audio-time caption">also makes it convenient for keeping notes, which</span> <span class="audio-time caption">I'm currently doing manually and working on those</span> <span class="audio-time caption">Org link types to be able to make it a little bit</span> <span class="audio-time caption">more smooth than it currently is.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  So you've got your central store of music files.</span> <span class="audio-time caption">You've got URLs for them so you can talk about them.</span> <span class="audio-time caption">That's just one identifier per song.</span> <span class="audio-time caption">You've got multiple speakers that you can use</span> <span class="audio-time caption">your completing interface to say, okay, I want to</span> <span class="audio-time caption">play this over there.</span> <span class="audio-time caption">You have Emacs controlling all of that.</span> <p></p><div class="transcript-heading"><span class="audio-time">9:13</span> <strong>Emacs on Android with Termux</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong> Now, is that Emacs on your laptop and you just</span> <span class="audio-time caption">take it around and you say, okay, I'm going to</span> <span class="audio-time caption">sit in the living room for a little bit or</span> <span class="audio-time caption">whatever and play there.</span> <span class="audio-time caption">Or do you... Ah, there you go.</span> <span class="audio-time caption">That's what I was going to ask.</span> <span class="audio-time caption">All right.</span> <span class="audio-time caption">So Emacs on your phone.</span> <span class="audio-time caption">The Android port or Termux?</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  I have both installed.</span> <span class="audio-time caption">I think you actually saw this a few months</span> <span class="audio-time caption">ago when I was running performance comparisons</span> <span class="audio-time caption">between the Termux version of Emacs and the</span> <span class="audio-time caption">native port, and found that the native port</span> <span class="audio-time caption">generally ran anything CPU-intensive</span> <span class="audio-time caption">roughly twice as fast.</span> <span class="audio-time caption">But I still use the Termux version because it's...</span> <span class="audio-time caption">I'm not sure if you played around with the</span> <span class="audio-time caption">Android terminal virtualization layer at all, but</span> <span class="audio-time caption">it's not great.</span> <span class="audio-time caption">I really appreciate the integration that</span> <span class="audio-time caption">Termux gives me with Android features.</span> <span class="audio-time caption">For example, being able to query the sensors,</span> <span class="audio-time caption">such as GPS or temperature sensors, and I can</span> <span class="audio-time caption">actually pull those in from the Emacs side.</span> <span class="audio-time caption">And that's something I kind of want to get into.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  What do you think of using the</span> <span class="audio-time caption">temperature sensors for?</span> <span class="audio-time caption">What can Emacs do with that?</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  It's not so much the fact that I</span> <span class="audio-time caption">use the temperature sensors as that when I pull</span> <span class="audio-time caption">the sensors, that's the most remarkable value</span> <span class="audio-time caption">that I get out of it.</span> <span class="audio-time caption">But one of the interesting things is the</span> <span class="audio-time caption">barometric pressure sensor, which gives me</span> <span class="audio-time caption">height, which matters because when I'm out and</span> <span class="audio-time caption">about and if I stop to record an entry in my</span> <span class="audio-time caption">journal, for example, I'll just pull the sensors</span> <span class="audio-time caption">and dump them into the header in the entry that I'm writing.</span> <span class="audio-time caption">The barometric sensor, I'll get the GPS, so</span> <span class="audio-time caption">that'll tell me what the actual height is at that</span> <span class="audio-time caption">location on the earth. The barometric sensor</span> <span class="audio-time caption">also gives me a little bit of insight into the weather.</span> <span class="audio-time caption">So it's not so much the temperature sensor</span> <span class="audio-time caption">is what my temperature is, but just like if</span> <span class="audio-time caption">it's a hot day or not.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  I am very curious about that setup.</span> <span class="audio-time caption">So if you happen to share your, I don't know, Org</span> <span class="audio-time caption">capture for Termux that includes all these things...</span> <span class="audio-time caption">You don't have to show me the actual stuff, but</span> <span class="audio-time caption">you know, at some point I think other people will</span> <span class="audio-time caption">be curious about what kind of benefits they can</span> <span class="audio-time caption">get from running Emacs on their phones.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  So, I mean, I guess I'll...</span> <span class="audio-time caption">One of the benefits that I get is the ability to</span> <span class="audio-time caption">keep shopping.</span> <span class="audio-time caption">So I'm a little bit of a militant cyclist.</span> <span class="audio-time caption">One of the things that I often do is leave</span> <p></p><a href="https://sachachua.com/blog/2026/06/june-4-emacs-chat-with-ben-zanin-gnomon-mastodon-social/emacs-chat-25-ben-zanin-00-12-04-333.jpg"><img loading="lazy" src="https://sachachua.com/blog/2026/06/june-4-emacs-chat-with-ben-zanin-gnomon-mastodon-social/emacs-chat-25-ben-zanin-00-12-04-333.jpg" alt="image from video 00:12:04.333"></a><span class="audio-time caption"><strong>Ben:</strong> notes about things that I need to take care of in</span> <span class="audio-time caption">particular areas of the city.</span> <span class="audio-time caption">The nice thing is that I can just drop them</span> <span class="audio-time caption">directly in commits right as I'm going.</span> <span class="audio-time caption">So I often have a long list of updates that are</span> <span class="audio-time caption">from Emacs on my phone, just because it's convenient.</span> <span class="audio-time caption">All right.</span> <span class="audio-time caption">There we go for Monsterdon, in fact.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Nice, nice.</span> <span class="audio-time caption">Then that's</span> <span class="audio-time caption">Syncthing or whatever else to just get it copied back</span> <span class="audio-time caption">to your laptop or just on your phone?</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  Straight Magit mode.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Oh, yeah?</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  That's one of the things that I</span> <span class="audio-time caption">found was a little bit clunkier when I was</span> <span class="audio-time caption">running virtualized Emacs under the Android</span> <span class="audio-time caption">emulator and also the native Android port of</span> <span class="audio-time caption">Emacs.</span> <span class="audio-time caption">They are a little bit more troublesome to get</span> <span class="audio-time caption">Magit to work.</span> <span class="audio-time caption">Because I rely on that for syncing back and</span> <span class="audio-time caption">forth from my phone,</span> <span class="audio-time caption">that's one of the reasons why I stuck with Termux.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Very cool, very cool.</span> <span class="audio-time caption">I like Termux's little bar of extra</span> <span class="audio-time caption">keyboard keys that you can have, so you can have</span> <span class="audio-time caption">a regular keyboard and then you can just have</span> <span class="audio-time caption">your Controls and your Alts and whatever on that</span> <span class="audio-time caption">little extra bar.</span> <span class="audio-time caption">Termux is quite interesting.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  I think I'm probably pushing it</span> <span class="audio-time caption">harder than it is meant to be pushed.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  That's the fun of it.</span> <span class="audio-time caption">I don't exactly know how everything will shake</span> <span class="audio-time caption">out, but probably with Google trying to lock down</span> <span class="audio-time caption">the developer ecosystem</span> <span class="audio-time caption">in a few months, right?</span> <span class="audio-time caption">They're saying, oh, you know, it's got to be ADB</span> <span class="audio-time caption">in order to get these unsigned apps on.</span> <span class="audio-time caption">We'll have to see how it all shakes out.</span> <span class="audio-time caption">But I'm hoping Termux can survive because I like</span> <span class="audio-time caption">that one too.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  Yeah, me too.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Okay, so you've got interesting</span> <span class="audio-time caption">music, an interesting music setup with lyrics and</span> <span class="audio-time caption">playback and all that stuff.</span> <span class="audio-time caption">You've got your phone, which also runs Emacs and</span> <span class="audio-time caption">from which you can, you've also set it up so you</span> <span class="audio-time caption">can control your music from your phone?</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  Yes.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Okay.</span> <p></p><div class="transcript-heading"><span class="audio-time">13:44</span> <strong>Keyboards and other devices</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong> When I was reading through your toots, I noticed</span> <span class="audio-time caption">you like to play around with other keyboards and</span> <span class="audio-time caption">other devices like the 8BitDo.</span> <span class="audio-time caption">Do you have any of that talking to Emacs too?</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  [Keychron B11 Pro is] the keyboard I'm currently using.</span> <span class="audio-time caption">I got this so I could keep it in my purse and</span> <span class="audio-time caption">just like walk around with it, but it turns out</span> <span class="audio-time caption">it's super comfortable and I'm accidentally using</span> <span class="audio-time caption">it as a daily driver.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  All right.</span> <span class="audio-time caption">Name-drop the keyboard for all the people who</span> <span class="audio-time caption">like the device recommendations.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  It's a Keychron B11 Pro.</span> <span class="audio-time caption">It runs ZMK.</span> <span class="audio-time caption">ZMK, I suppose.</span> <span class="audio-time caption">And if you've seen me interacting with</span> <span class="audio-time caption">Pete Johanson on Mastodon, he's the lead developer of</span> <span class="audio-time caption">that firmware package.</span> <span class="audio-time caption">It's a little bit like QMK, except that</span> <span class="audio-time caption">fundamentally QMK is a polling architecture, and</span> <span class="audio-time caption">it works really well for very restricted</span> <span class="audio-time caption">microcontrollers.</span> <span class="audio-time caption">ZMK is interrupt-based, which means it is</span> <span class="audio-time caption">tremendously more efficient in terms of power draw.</span> <span class="audio-time caption">So if you want a Bluetooth keyboard, you should</span> <span class="audio-time caption">probably run ZMK on it.</span> <span class="audio-time caption">Anyhow, yeah, it's fantastic.</span> <span class="audio-time caption">And I do have a bit of a keyboard problem where I</span> <span class="audio-time caption">tend to...</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Many Emacs people have keyboard problems.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  Right? I feel like I'm in good company right now.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Yeah, yeah, yeah.</span> <span class="audio-time caption">So, devices, yep, gotcha.</span> <span class="audio-time caption">And this has become your main keyboard even for</span> <span class="audio-time caption">regular computing?</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  In the last couple of weeks, yeah.</span> <span class="audio-time caption">It's super comfortable.</span> <span class="audio-time caption">Because it's so flat, I can get away without</span> <span class="audio-time caption">having to use palm rests to actually keep in a</span> <span class="audio-time caption">decent posture,</span> <span class="audio-time caption">because of the curvature of it..</span> <span class="audio-time caption">Like, it's an Alice layout.</span> <span class="audio-time caption">The key travel isn't too bad.</span> <span class="audio-time caption">It's actually quite comfortable.</span> <span class="audio-time caption">I found that I needed a little bit of</span> <span class="audio-time caption">acclimatization to get used to split keyboards.</span> <span class="audio-time caption">This one has roughly the spread of a split,</span> <span class="audio-time caption">but it seems to be easier for my muscle memory.</span> <span class="audio-time caption">So yeah, I didn't intend to leave it on my desk,</span> <span class="audio-time caption">but it stuck and has kind of stayed there for now.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Does it have any special ergonomics</span> <span class="audio-time caption">for all the modifiers that we like to do?</span> <span class="audio-time caption">Or do you just use Caps as Control or whatever else?</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  Actually, I don't use Caps as</span> <span class="audio-time caption">Control and I actually really need to get into</span> <span class="audio-time caption">remapping that.</span> <span class="audio-time caption">ZMK has a very rich remapping story, as I expect</span> <span class="audio-time caption">you to imagine, from a custom firmware.</span> <span class="audio-time caption">The macros are intense, and you can get</span> <span class="audio-time caption">really deep in customization.</span> <span class="audio-time caption">I have done none of that on this keyboard</span> <span class="audio-time caption">yet, because it's only, I think, a couple of</span> <span class="audio-time caption">months old at this point.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  You've been settling in.</span> <span class="audio-time caption">As you said, this has been your</span> <span class="audio-time caption">main keyboard for a little while.</span> <span class="audio-time caption">Charlie Baker says, "yeah, I love the split keyboard.</span> <span class="audio-time caption">Recently bought one myself.</span> <span class="audio-time caption">I was getting so much neck pain, you know,</span> <span class="audio-time caption">shoulder and neck pain from so many hours keeping</span> <span class="audio-time caption">hands close together."</span> <span class="audio-time caption">But the split lets his shoulders relax.</span> <span class="audio-time caption">So probably you're getting the same, like, ha, my arms.</span> <p></p><div class="transcript-heading"><span class="audio-time">16:44</span> <strong>Benefits of a split keyboard</strong></div><p></p><span class="audio-time caption"><strong>Ben:</strong>  The two things that I first noticed</span> <span class="audio-time caption">when I moved to a split keyboard was one, my</span> <span class="audio-time caption">wrists started feeling a lot nicer and two, I was</span> <span class="audio-time caption">immediately able to bench press like 20 pounds</span> <span class="audio-time caption">more the next week.</span> <span class="audio-time caption">It was amazing how much of a difference it made</span> <span class="audio-time caption">and it showed up in the data.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Wow.</span> <span class="audio-time caption">There was a weightlifting talk at EmacsConf last year, I think.</span> <span class="audio-time caption">So there's a surprising overlap between the</span> <span class="audio-time caption">people who are checking their weightlifting stats</span> <span class="audio-time caption">and the people who are into Emacs.</span> <span class="audio-time caption">Naturally, with Org Mode.</span> <span class="audio-time caption">There you go.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  Let's not look at those numbers too closely.</span> <span class="audio-time caption">I'm not too proud of a bunch of them.</span> <span class="audio-time caption">But yes, I find that Org capture templates let me</span> <span class="audio-time caption">keep on top of that and not really think about</span> <span class="audio-time caption">it, which is great because you don't want to</span> <span class="audio-time caption">think about it.</span> <span class="audio-time caption">You want to gather the data and think about it</span> <span class="audio-time caption">separately so that you can</span> <span class="audio-time caption">stay emotionally divested from what the numbers mean.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  I know.</span> <span class="audio-time caption">I'm totally happy to dig into the Org capture,</span> <span class="audio-time caption">especially if you do any graphing.</span> <span class="audio-time caption">People always love graphing their progress, right?</span> <span class="audio-time caption">But if you're like, I don't really want to show</span> <span class="audio-time caption">my numbers at the moment, that is also</span> <span class="audio-time caption">understandable and okay.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  I don't, I'm afraid. Sorry.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  That's okay.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  It took me a couple years to get</span> <span class="audio-time caption">used to being on camera at all.</span> <span class="audio-time caption">I don't really like my appearance very much.</span> <span class="audio-time caption">I'm working on that, as you can see.</span> <span class="audio-time caption">I've had to work on that to be able to work remotely.</span> <span class="audio-time caption">It's a work in progress.</span> <span class="audio-time caption">I'm getting through it.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  You know us. We're very much focused on text.</span> <span class="audio-time caption">In fact, you even use Emacs in the terminal.</span> <span class="audio-time caption">That's very text-y.</span> <p></p><div class="transcript-heading"><span class="audio-time">18:22</span> <strong>Meeting workflow</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong> One of the interesting things actually that I</span> <span class="audio-time caption">wanted to ask you about since you mentioned</span> <span class="audio-time caption">meetings is you probably also have the role of</span> <span class="audio-time caption">designated note-taker.</span> <span class="audio-time caption">You mentioned in one of your toots that you take</span> <span class="audio-time caption">notes and people are like, what are you doing that in?</span> <span class="audio-time caption">How are you taking your notes?</span> <span class="audio-time caption">And it's Emacs.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  Yes, so actually that's one of the</span> <span class="audio-time caption">things I should lead off with as an apology.</span> <span class="audio-time caption">I probably won't be able to share</span> <span class="audio-time caption">many of my capture templates because I don't use</span> <span class="audio-time caption">them in my personal life very much.</span> <span class="audio-time caption">They're mostly on my work machine. I've</span> <span class="audio-time caption">got capture templates for impromptu meetings</span> <span class="audio-time caption">where it's just like an exploratory, we have a</span> <span class="audio-time caption">problem we need to solve, we're kind of talking</span> <span class="audio-time caption">through a discussion,</span> <span class="audio-time caption">a separate capture template for meetings with</span> <span class="audio-time caption">agendas to make sure that we stay on them and</span> <span class="audio-time caption">that we log decisions,</span> <span class="audio-time caption">and a separate set of templates for... So I have</span> <span class="audio-time caption">a team of direct reports and they each have</span> <span class="audio-time caption">different cares and different topics that we're</span> <span class="audio-time caption">working to develop in their professional careers.</span> <span class="audio-time caption">I find that it's really useful to be able to</span> <span class="audio-time caption">keep some continuity between our conversations.</span> <span class="audio-time caption">It also makes it very easy to export that</span> <span class="audio-time caption">entire dataset, share it with them to make sure</span> <span class="audio-time caption">that they can consult it at the same time.</span> <span class="audio-time caption">If I got anything wrong, I can fold their</span> <span class="audio-time caption">corrections in.</span> <span class="audio-time caption">But all of those templates, unfortunately, are on</span> <span class="audio-time caption">my work machine.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  We'll just sketch out the general</span> <span class="audio-time caption">idea in abstract details and then people who want</span> <span class="audio-time caption">to implement it for themselves can fill in the blanks.</span> <span class="audio-time caption">For example, when you're having a meeting with</span> <span class="audio-time caption">your direct reports, are the tasks related to</span> <span class="audio-time caption">them in an Org agenda?</span> <span class="audio-time caption">Are you using dynamic blocks?</span> <span class="audio-time caption">Is it tracked somewhere else or is it in Org?</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  It's straight in Org mode.</span> <span class="audio-time caption">So most of the touch points that we have are more</span> <span class="audio-time caption">about professional development and their cares</span> <span class="audio-time caption">and concerns, rather than specific deliverables.</span> <span class="audio-time caption">Usually deliverables we manage at a team level.</span> <span class="audio-time caption">But if there are specific things that individuals</span> <span class="audio-time caption">are working on, they will be in to-dos under</span> <span class="audio-time caption">their subheadings in a way that show up on the</span> <span class="audio-time caption">agenda if we have assigned deadlines for them.</span> <span class="audio-time caption">But generally, if there's a deadline on a task,</span> <span class="audio-time caption">it's because</span> <span class="audio-time caption">I'm doing something and they need to track it, or</span> <span class="audio-time caption">they're doing something and I need to track it.</span> <span class="audio-time caption">If I'm the only guy using Emacs, then Org</span> <span class="audio-time caption">Mode won't work for that,</span> <span class="audio-time caption">so there aren't a lot of those.</span> <span class="audio-time caption">But if it's just something that I need to check</span> <span class="audio-time caption">up on to make sure that</span> <span class="audio-time caption">something that... Like they've got planned leave for</span> <span class="audio-time caption">example, or they have a cousin's wedding that</span> <span class="audio-time caption">they need to go off to, or something that I just</span> <span class="audio-time caption">need to keep in my brain that's not necessarily</span> <span class="audio-time caption">deliverable, then it would be</span> <span class="audio-time caption">appropriate to keep that in a place where it'll</span> <span class="audio-time caption">only show up on my agenda.</span> <span class="audio-time caption">So that's the kind of decision making that I</span> <span class="audio-time caption">apply there.</span> <p></p><div class="transcript-heading"><span class="audio-time">21:11</span> <strong>Narrowing</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong>  And you mentioned you have a</span> <span class="audio-time caption">subheading, I guess a subheading per person or</span> <span class="audio-time caption">sort of... Or do you use tags to keep track</span> <span class="audio-time caption">of something that might touch several people?</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  Usually a section per person, and</span> <span class="audio-time caption">that's more of a convenience than anything else.</span> <span class="audio-time caption">That lets me narrow to just that subheading and</span> <span class="audio-time caption">share my screen during the meetings.</span> <span class="audio-time caption">Then I don't have to worry about accidentally</span> <span class="audio-time caption">leaking anybody else's information into the</span> <span class="audio-time caption">screen share or anything like that.</span> <span class="audio-time caption">Obviously we let off with conversations about</span> <span class="audio-time caption">them being all right with that.</span> <span class="audio-time caption">But the ability to very clearly and simply</span> <span class="audio-time caption">delineate</span> <span class="audio-time caption">"This domain of my notes pertains to this person"</span> <span class="audio-time caption">and being able to be confident and share that</span> <span class="audio-time caption">confidence that there will be no leakage means</span> <span class="audio-time caption">that we can explore topics and talk about them in</span> <span class="audio-time caption">a way that might otherwise be a little bit more</span> <span class="audio-time caption">restrictive.</span> <span class="audio-time caption">So being able to do that simply, and being able to</span> <span class="audio-time caption">establish a very clear delineation around whose</span> <span class="audio-time caption">information belongs where and where it should be</span> <span class="audio-time caption">shared turns out to be pretty valuable.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Yeah, and that's a technique I</span> <span class="audio-time caption">think that especially people who are new to Emacs</span> <span class="audio-time caption">and who aren't used to narrowing and widening</span> <span class="audio-time caption">might not know how to use effectively.</span> <span class="audio-time caption">I think narrow is even one of the commands that's</span> <span class="audio-time caption">disabled by default.</span> <span class="audio-time caption">You've got to say, yeah, you know, I'm not scared.</span> <span class="audio-time caption">I know what to do.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  Yeah, it's kind of bizarre to me</span> <span class="audio-time caption">that it is, but yeah.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  I can imagine people accidentally</span> <span class="audio-time caption">triggering it and they're like, oh no, the rest</span> <span class="audio-time caption">of my file is missing.</span> <span class="audio-time caption">But if you know how to narrow to a region, and</span> <span class="audio-time caption">Org even has those commands to easily narrow to a subtree...</span> <span class="audio-time caption">I think it's even part of the default speed</span> <span class="audio-time caption">command so you can trigger it right from a heading.</span> <span class="audio-time caption">But it's great for that kind of restriction.</span> <p></p><div class="transcript-heading"><span class="audio-time">22:58</span> <strong>There's even an internal Slack channel about Emacs at Ben's company</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong> Okay, so the reason why I was asking about that</span> <span class="audio-time caption">is because some people are working with people</span> <span class="audio-time caption">who are not using Emacs, so it's very interesting</span> <span class="audio-time caption">to see what the kinds of... It's very rare for</span> <span class="audio-time caption">people to work with other people who actually</span> <span class="audio-time caption">use... Are there any other Emacs people in your</span> <span class="audio-time caption">company, for example?</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  There's an entire Emacs Slack topic</span> <span class="audio-time caption">about that, yeah.</span> <span class="audio-time caption">It's kind of great.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  What is that like to have co-workers who do Emacs?</span> <span class="audio-time caption">Because this is a rare experience.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  It's super cool.</span> <span class="audio-time caption">It's also neat to see the very, very different</span> <span class="audio-time caption">ways that people use it.</span> <span class="audio-time caption">But yeah, oftentimes people will talk about</span> <span class="audio-time caption">problems that they have with particular internal</span> <span class="audio-time caption">tools, and somebody's like, oh yeah, go check out</span> <span class="audio-time caption">this repo on GitLab that I published last week</span> <span class="audio-time caption">where I got sick of it and decided to solve that</span> <span class="audio-time caption">problem categorically.</span> <span class="audio-time caption">It's actually super cool.</span> <span class="audio-time caption">And some of the folks at...</span> <span class="audio-time caption">Generally, I tried not to mention my current</span> <span class="audio-time caption">employer at any point.</span> <span class="audio-time caption">Obviously, it's not secret.</span> <span class="audio-time caption">It's in the init file.</span> <span class="audio-time caption">But yeah, I don't tend to get into that deeply.</span> <span class="audio-time caption">But some of the other people who work at my</span> <span class="audio-time caption">company, they maintain venerable Emacs packages.</span> <span class="audio-time caption">So it's awesome to be able to go and talk with</span> <span class="audio-time caption">some of the folks who</span> <span class="audio-time caption">I've been working on the code that I've been</span> <span class="audio-time caption">using for a decade and we are now coworkers.</span> <span class="audio-time caption">It's lovely.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Oh, that's so nice.</span> <span class="audio-time caption">I'm glad you have that kind of little community</span> <span class="audio-time caption">in there.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  Yeah. Bunch of nerds.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  So I suspect some people will be looking up your</span> <span class="audio-time caption">company after this.</span> <span class="audio-time caption">I think it's also mentioned in LinkedIn and sort</span> <span class="audio-time caption">of like, okay, let's see if there's any job</span> <span class="audio-time caption">openings.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  If it's mentioned on LinkedIn, that</span> <span class="audio-time caption">is somebody else.</span> <span class="audio-time caption">I haven't logged into LinkedIn in 15 years and I</span> <span class="audio-time caption">never will.</span> <p></p><div class="transcript-heading"><span class="audio-time">24:50</span> <strong>Ben keeps Org capture templates as individual files and adapts them to different meeting flows</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong>  We do have a question from Shae.</span> <span class="audio-time caption">Shae is asking, how do you make a capture</span> <span class="audio-time caption">template to stay on agenda and record decisions?</span> <span class="audio-time caption">You got any tips for that?</span> <span class="audio-time caption">I'm guessing this is more of a human thing rather</span> <span class="audio-time caption">than an Org thing, but maybe you have some ideas</span> <span class="audio-time caption">on how you keep something on track.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  So I'll actually push back on the</span> <span class="audio-time caption">"It's a human thing rather than an Org thing".</span> <span class="audio-time caption">I strongly believe that one of the real values</span> <span class="audio-time caption">of Org Mode is that it's a very plastic system.</span> <span class="audio-time caption">Fundamentally, I think that it is a human system</span> <span class="audio-time caption">because it allows you to express exactly those</span> <span class="audio-time caption">kinds of trade-offs in a really, really fluid way.</span> <span class="audio-time caption">I love the personal information management that</span> <span class="audio-time caption">Palm Pilots provided, for example,</span> <span class="audio-time caption">but it was pretty restrictive.</span> <span class="audio-time caption">One of the things that I love about Org Mode</span> <span class="audio-time caption">is that if you find that a particular person has</span> <span class="audio-time caption">a particular conversation style, it's really easy</span> <span class="audio-time caption">to modify your Org Mode capture templates to be</span> <span class="audio-time caption">able to capture that particular flow that you</span> <span class="audio-time caption">have with that person.</span> <span class="audio-time caption">Or with a particular group of a recurring</span> <span class="audio-time caption">meeting, for example, that tends to flow in a</span> <span class="audio-time caption">particular way.</span> <span class="audio-time caption">Super easy to update the templates that I use to</span> <span class="audio-time caption">capture those particular meetings to make it</span> <span class="audio-time caption">easier to match the general conversation flow</span> <span class="audio-time caption">with the notes that I will be taking about it.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Wow, that sounds pretty</span> <span class="audio-time caption">sophisticated.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  Well, I mean, that's the thing.</span> <span class="audio-time caption">It's not sophisticated.</span> <span class="audio-time caption">It tracks the human process very easily.</span> <span class="audio-time caption">So it's really lightweight.</span> <span class="audio-time caption">So you don't have to have a lot of sophistication</span> <span class="audio-time caption">to make it very, very useful.</span> <span class="audio-time caption">You just have to have a feedback loop that you</span> <span class="audio-time caption">can tune every time with one or two minutes of effort.</span> <span class="audio-time caption">And that's one of the reasons why I depend on</span> <span class="audio-time caption">Magit mode so much is that it lets me track</span> <span class="audio-time caption">those things.</span> <span class="audio-time caption">But yeah, to answer Shae's question about how do</span> <span class="audio-time caption">I track those particular things.</span> <span class="audio-time caption">So if it's a meeting where one of my direct reports</span> <span class="audio-time caption">has a particular set of topics that we</span> <span class="audio-time caption">tend to investigate, like somebody who's</span> <span class="audio-time caption">concentrated on career growth.</span> <span class="audio-time caption">So we're talking about the areas in which we want</span> <span class="audio-time caption">to see development.</span> <span class="audio-time caption">I'll absolutely update the capture templates for</span> <span class="audio-time caption">that particular person to say, all right, here's</span> <span class="audio-time caption">what we talked about last time.</span> <span class="audio-time caption">Here are the things that were done between our</span> <span class="audio-time caption">last two conversations about how we move in that direction.</span> <span class="audio-time caption">Were they successful or not?</span> <span class="audio-time caption">Did it require a lot of effort?</span> <span class="audio-time caption">So was it something that more effort should be</span> <span class="audio-time caption">put into to be able to drive down the work over time,</span> <span class="audio-time caption">to be able to produce those results?</span> <span class="audio-time caption">But yeah, that goes into the templates</span> <span class="audio-time caption">and that goes into the cadence of conversations that we</span> <span class="audio-time caption">talked about in Capture.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  So that's really interesting.</span> <span class="audio-time caption">You modify the capture templates with the</span> <span class="audio-time caption">notes that you want to have easily available the</span> <span class="audio-time caption">next time you chat with them.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  Exactly, yeah.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  The capture templates are still defined as a</span> <span class="audio-time caption">setq somewhere in your thing, or are you</span> <span class="audio-time caption">going into the customized interface?</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  So I actually keep the capture mode</span> <span class="audio-time caption">templates as raw files that are referred to, and</span> <span class="audio-time caption">that makes it easier to version them in a way</span> <span class="audio-time caption">that like, I mean, sure, like my Emacs init file,</span> <span class="audio-time caption">if you look at the Git history of it, it has a</span> <span class="audio-time caption">whole bunch of different...</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  I had not considered having capture</span> <span class="audio-time caption">templates as files files.</span> <span class="audio-time caption">It worked out really well.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  So you can see that... It's a little</span> <span class="audio-time caption">bit hard to see with the font this small, but you</span> <span class="audio-time caption">can see that I've got a lot of changes to, for</span> <span class="audio-time caption">example, my init file, but keeping them in</span> <span class="audio-time caption">individual capture mode template files makes it a</span> <span class="audio-time caption">little bit easier to just look at the history of</span> <span class="audio-time caption">that particular file and see why particular</span> <span class="audio-time caption">changes were made.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  I'm going to try that.</span> <span class="audio-time caption">I think that's a great idea because it allows you</span> <span class="audio-time caption">to be a lot more granular about the notes.</span> <p></p><div class="transcript-heading"><span class="audio-time">28:45</span> <strong>Personal-scale software and the journey
</strong></div><p></p><a href="https://sachachua.com/blog/2026/06/june-4-emacs-chat-with-ben-zanin-gnomon-mastodon-social/emacs-chat-25-ben-zanin-00-28-28-300.jpg"><img loading="lazy" src="https://sachachua.com/blog/2026/06/june-4-emacs-chat-with-ben-zanin-gnomon-mastodon-social/emacs-chat-25-ben-zanin-00-28-28-300.jpg" alt="image from video 00:28:28.300"></a><span class="audio-time caption"><strong>Sacha:</strong> I saw in that very brief flash of your change</span> <span class="audio-time caption">log message that you like to write</span> <span class="audio-time caption">fairly detailed commit messages that talk about</span> <span class="audio-time caption">why a change was made instead of just "a new</span> <span class="audio-time caption">function, new command,"</span> <span class="audio-time caption">very terse updates that I sometimes just try to</span> <span class="audio-time caption">get away with.</span> <span class="audio-time caption">Tell us more about that, because I think you've</span> <span class="audio-time caption">had a couple of toots about reading source code</span> <span class="audio-time caption">and reading commits.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  Yeah.</span> <span class="audio-time caption">So I guess one of the things that I most appreciate about</span> <span class="audio-time caption">software in general, and specifically personal</span> <span class="audio-time caption">software, like personal-scale software that's</span> <span class="audio-time caption">been written by an amount of people that you</span> <span class="audio-time caption">could fit into a room to have a conversation</span> <span class="audio-time caption">about it...</span> <span class="audio-time caption">One of the things that I most appreciate about</span> <span class="audio-time caption">that is that almost all software written that way</span> <span class="audio-time caption">is fundamentally a diary about the way that a</span> <span class="audio-time caption">person learned how to solve a set of problems</span> <span class="audio-time caption">that they might not have known about when they</span> <span class="audio-time caption">decided to at the beginning.</span> <span class="audio-time caption">It's this fascinating process of</span> <span class="audio-time caption">tracking somebody's voyage through the problem</span> <span class="audio-time caption">landscape as they discover other people who have</span> <span class="audio-time caption">touched on topics that are tangential to the</span> <span class="audio-time caption">problem being solved by that software package.</span> <span class="audio-time caption">It's such a personal and fascinating experience</span> <span class="audio-time caption">to see somebody go from "I know just enough about</span> <span class="audio-time caption">a problem to be able to decide that I want to</span> <span class="audio-time caption">build a machine that works on it" to "I have</span> <span class="audio-time caption">this deeper understanding of how the problem</span> <span class="audio-time caption">actually exists in the broader set of things that</span> <span class="audio-time caption">people care about,</span> <span class="audio-time caption">oriented along the axis of what machinery can</span> <span class="audio-time caption">do to help solve parts of that problem."</span> <span class="audio-time caption">The commit logs for a program are</span> <span class="audio-time caption">like a map through that territory.</span> <span class="audio-time caption">It's wonderful to read.</span> <span class="audio-time caption">It gives you a lot of insight into the person</span> <span class="audio-time caption">doing the navigation.</span> <span class="audio-time caption">When you see 16 commits on December 24th of 2023,</span> <span class="audio-time caption">like, that person probably had a little</span> <span class="audio-time caption">bit of time to work on it.</span> <span class="audio-time caption">Then, when you see a bunch of commits that are</span> <span class="audio-time caption">5 p.m. Monday to Friday, like, okay, this is</span> <span class="audio-time caption">probably done in a particular way.</span> <span class="audio-time caption">It's this deeply personal process of</span> <span class="audio-time caption">seeing how problems are learned about.</span> <span class="audio-time caption">I just really appreciate that.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  I think what you're saying about</span> <span class="audio-time caption">personal-scale software and getting a</span> <span class="audio-time caption">sense of people's journey as they learn to</span> <span class="audio-time caption">understand a problem and as they start to</span> <span class="audio-time caption">prototype a solution... Because you never quite come</span> <span class="audio-time caption">across the right solution the first time around.</span> <span class="audio-time caption">You're figuring things out,</span> <span class="audio-time caption">You're borrowing things from other people.</span> <span class="audio-time caption">I think that will resonate a lot with lots of</span> <span class="audio-time caption">people in the Emacs community, because Emacs use</span> <span class="audio-time caption">is so personal, as you mentioned when you were</span> <span class="audio-time caption">looking at the Slack channel.</span> <span class="audio-time caption">I was wondering, in your personal practice, as</span> <span class="audio-time caption">you figure things out, what kinds of things help you?</span> <span class="audio-time caption">Is it mostly a matter of actually sitting down</span> <span class="audio-time caption">and taking the time to write the literate</span> <span class="audio-time caption">programming stuff around the code blocks or the</span> <span class="audio-time caption">commit messages,</span> <span class="audio-time caption">or are there other tools or techniques that help</span> <span class="audio-time caption">you do that?</span> <span class="audio-time caption">Are there tools or techniques that help me write</span> <span class="audio-time caption">down your journey along the way as you think</span> <span class="audio-time caption">about the code?</span> <span class="audio-time caption">What's your practice?</span> <span class="audio-time caption">For example, when you come across something that</span> <span class="audio-time caption">you want to figure out, how do you go about doing it?</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  So it depends on how I'm</span> <span class="audio-time caption">approaching the project.</span> <span class="audio-time caption">One of the neat things about software is that</span> <span class="audio-time caption">it's a document and a device at the same time.</span> <span class="audio-time caption">You can care about it because of the thing</span> <span class="audio-time caption">that it does, or you can care about it because of</span> <span class="audio-time caption">the information that it captures.</span> <span class="audio-time caption">If I'm digging into a program because it does</span> <span class="audio-time caption">a thing that I want to learn, then I'll pay</span> <span class="audio-time caption">attention to the device aspect of it.</span> <span class="audio-time caption">That usually means that I'll start with its</span> <span class="audio-time caption">own documentation.</span> <span class="audio-time caption">If it has a man page, I'll read that.</span> <span class="audio-time caption">If it has user docs, I'll read those.</span> <span class="audio-time caption">Usually, I'll start keeping notes in</span> <span class="audio-time caption">an Org Mode file, because it's easy to hyperlink</span> <span class="audio-time caption">back to it and add my own annotations in parallel to the</span> <span class="audio-time caption">actual authoritative source.</span> <span class="audio-time caption">If I'm reading software primarily as a document,</span> <span class="audio-time caption">then I'll start by reading the source code and</span> <span class="audio-time caption">the commit logs, usually the most recent ones,</span> <span class="audio-time caption">and then I'll jump back to the beginning of the</span> <span class="audio-time caption">project and read upwards at the beginning, and</span> <span class="audio-time caption">then fill in the blanks iteratively, if it's a</span> <span class="audio-time caption">project that's small enough or has little enough</span> <span class="audio-time caption">history that I can do that.</span> <span class="audio-time caption">Again, I'll usually start an Org Mode file</span> <span class="audio-time caption">specific to that particular exploration that will</span> <span class="audio-time caption">let me organize my notes as I go.</span> <span class="audio-time caption">I really do rely on the external brain that I can</span> <span class="audio-time caption">keep in an Org Mode file.</span> <span class="audio-time caption">I tend to have a pretty decent long-term memory,</span> <span class="audio-time caption">but being able to bridge the gap between</span> <span class="audio-time caption">short-term memory and long-term memory is super,</span> <span class="audio-time caption">super useful.</span> <span class="audio-time caption">Leaving myself hints that let me dredge things</span> <span class="audio-time caption">back out of long-term and</span> <span class="audio-time caption">reload it into the hot cache of short-term really,</span> <span class="audio-time caption">really helps out, because that lets me maintain</span> <span class="audio-time caption">that flow state or get back into that flow state.</span> <span class="audio-time caption">When you've got like the whole program, all the</span> <span class="audio-time caption">context that you've absorbed up until now and the</span> <span class="audio-time caption">ideas of the areas that you want to</span> <span class="audio-time caption">investigate,</span> <span class="audio-time caption">being able to hot-reload all of that and then</span> <span class="audio-time caption">pick up where I left off is super useful.</span> <span class="audio-time caption">But the meat brain can't do it.</span> <span class="audio-time caption">I need the machine brain too.</span> <p></p><div class="transcript-heading"><span class="audio-time">34:07</span> <strong>vc-git-grep for finding notes again</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong>  Tell me about this dredging up process.</span> <span class="audio-time caption">Are you a lots of little files person?</span> <span class="audio-time caption">A couple of large files?</span> <span class="audio-time caption">A project file,</span> <span class="audio-time caption">there's an Org file in each project that you look up?</span> <span class="audio-time caption">How do you find things, especially if you don't</span> <span class="audio-time caption">remember the exact words?</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  So it's usually like an Org Mode</span> <span class="audio-time caption">per category, and they get consolidated.</span> <span class="audio-time caption">Let me shrink this down a little bit.</span> <span class="audio-time caption">So usually it's an Org Mode category per file.</span> <span class="audio-time caption">If there's something super specific, then usually</span> <span class="audio-time caption">it'll live out in its own place until I</span> <span class="audio-time caption">get around to...</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  I love that you have an Org File</span> <span class="audio-time caption">specifically for Mug Cake.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  But that's the thing.</span> <span class="audio-time caption">It'll live off in its own thing until it gets</span> <span class="audio-time caption">integrated into the list where the long-term</span> <span class="audio-time caption">stuff lives.</span> <span class="audio-time caption">I promise this is pertinent to</span> <span class="audio-time caption">your actual question.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  No, no, this is very pertinent.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  Usually, lots of little</span> <span class="audio-time caption">files while I'm still working on something,</span> <span class="audio-time caption">and then as that something becomes part of my larger life</span> <span class="audio-time caption">and has links to other things,</span> <p></p><span class="audio-time caption"><strong>Ben:</strong> then it'll kind of get centralized into one of the Org Mode</span> <span class="audio-time caption">files that has a broader topic purpose basically.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  If it's very long-term and you can't remember</span> <span class="audio-time caption">the exact words to find something, how do you generally find</span> <span class="audio-time caption">find your notes?</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  That way.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  You start grepping various keywords and try to</span> <span class="audio-time caption">find it.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  Yeah.</span> <span class="audio-time caption">So one of the things that I don't yet have turned</span> <span class="audio-time caption">on, and actually you inspired me to look into</span> <span class="audio-time caption">this, was so... Actually, do we have enough time?</span> <span class="audio-time caption">Yeah, okay.</span> <span class="audio-time caption">I'm just looking at the clock.</span> <span class="audio-time caption">One of the things that I wanted to get into was</span> <span class="audio-time caption">long-term searching and searchability.</span> <span class="audio-time caption">Yeah.</span> <span class="audio-time caption">So I use SQLite's indexing for a lot of things,</span> <span class="audio-time caption">and I really appreciate its porter stemming</span> <span class="audio-time caption">because it lets you search for stemmed words,</span> <span class="audio-time caption">which are kind of approximate matches, which is</span> <span class="audio-time caption">useful, but less useful than vector databases.</span> <span class="audio-time caption">You actually put a little bit of work into</span> <span class="audio-time caption">indexing topics based on vector similarity.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Which I haven't gotten back to, so</span> <span class="audio-time caption">I'm glad to see you managed to</span> <span class="audio-time caption">experiment with it,</span> <span class="audio-time caption">see what you come up with.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  I don't have anything to show</span> <span class="audio-time caption">yet, except that it's an interesting topic.</span> <span class="audio-time caption">Because I'm word-oriented, I will often remember</span> <span class="audio-time caption">individual keywords, or I'll have enough patience</span> <span class="audio-time caption">that I can sift through a list of potential</span> <span class="audio-time caption">keywords as I'm grepping for stuff.</span> <p></p><div class="transcript-heading"><span class="audio-time">36:55</span> <strong>Add keywords to make things easier to find again</strong></div><p></p><span class="audio-time caption"><strong>Ben:</strong> If I find that my first three or four</span> <span class="audio-time caption">attempts at searching for a keyword don't find</span> <span class="audio-time caption">the topic that I'm looking for, once I do</span> <span class="audio-time caption">eventually dig up the topic, I will add those</span> <span class="audio-time caption">keywords that I was searching for just so I can</span> <span class="audio-time caption">find it next time, expecting that future me will</span> <span class="audio-time caption">probably behave more or less like current me.</span> <span class="audio-time caption">But yeah, being able to use a vector</span> <span class="audio-time caption">database to search for headings that include</span> <span class="audio-time caption">related topics instead of related words...</span> <span class="audio-time caption">I'd really like to get there.</span> <span class="audio-time caption">I'm not there yet,</span> <span class="audio-time caption">and I think that's going to be interesting and useful.</span> <span class="audio-time caption">I also think it's going to be challenging to</span> <span class="audio-time caption">represent Org Mode's hierarchical structure</span> <span class="audio-time caption">to restrict the training</span> <span class="audio-time caption">of particular vector sets</span> <span class="audio-time caption">to be able to cast an increasingly wide net</span> <span class="audio-time caption">for where I want the searches to run.</span> <span class="audio-time caption">I don't know how that's going to be solved yet,</span> <span class="audio-time caption">but I'm going to be looking into it.</span> <p></p><div class="transcript-heading"><span class="audio-time">37:47</span> <strong>Keybindings and terminals; wezterm</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong>  @PuercoPop has a question regarding</span> <span class="audio-time caption">terminal Emacs.</span> <span class="audio-time caption">"Do you need to change any of the keybindings to</span> <span class="audio-time caption">avoid clashes with the terminal?"</span> <span class="audio-time caption">Some keybindings don't work on</span> <span class="audio-time caption">terminals, or some terminals already have these</span> <span class="audio-time caption">keybindings set.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  So I have good news and bad news there.</span> <span class="audio-time caption">The good news is that... One of the terminals</span> <span class="audio-time caption">that I'm using right now on most of my systems is</span> <span class="audio-time caption">Wezterm.</span> <span class="audio-time caption">It's really good.</span> <span class="audio-time caption">I started off with [meant to say Kitty], and I kind of bounced</span> <span class="audio-time caption">off that project because of some of the behavior</span> <span class="audio-time caption">of the lead developers.</span> <span class="audio-time caption">I won't get too deep into it, but what I found is</span> <span class="audio-time caption">that Wezterm...</span> <span class="audio-time caption">It gives me very little friction that way.</span> <span class="audio-time caption">It doesn't have a lot of its own keybindings,</span> <span class="audio-time caption">and that's a relief.</span> <span class="audio-time caption">It means that I really don't have to... I don't</span> <span class="audio-time caption">think I've had to put any time into customizing</span> <span class="audio-time caption">Wezterm to get out of the way of Emacs or Screen.</span> <span class="audio-time caption">I should mention, I am running Emacs within</span> <span class="audio-time caption">Screen,</span> <span class="audio-time caption">so that introduces another layer.</span> <span class="audio-time caption"><code>C-a a</code>, for example, is
<code>beginning-of-line</code></span> <span class="audio-time caption">for me, even though <code>C-a</code> itself is the</span> <span class="audio-time caption">default Emacs keybinding.</span> <span class="audio-time caption">But yeah, I think that I ended up choosing</span> <span class="audio-time caption">terminal software specifically on that merit, so</span> <span class="audio-time caption">that it doesn't get in the way.</span> <span class="audio-time caption">That's actually one of the things that Termux is...</span> <span class="audio-time caption">The default Google keyboard keeps stealing key bindings.</span> <span class="audio-time caption">It'll update, and all of a sudden, I can't use a</span> <span class="audio-time caption">particular Alt key combination anymore, because</span> <span class="audio-time caption">now it invokes a Google keyboard shortcut for</span> <span class="audio-time caption">pulling things out of the Android clipboard, for</span> <span class="audio-time caption">example, which is really kind of annoying.</span> <span class="audio-time caption">But yeah, in terms of terminals on full-fledged</span> <span class="audio-time caption">machines, I generally don't have that particular</span> <span class="audio-time caption">problem.</span> <span class="audio-time caption">Except for... What was the name of it?</span> <span class="audio-time caption">It was... It was a zap-to on-the-screen package</span> <span class="audio-time caption">that alphapapa wrote, I believe, that I...</span> <span class="audio-time caption">Actually, let me just look it up.</span> <span class="audio-time caption">Yeah, Avy.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Oh yeah?</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  So I wanted to start picking this</span> <span class="audio-time caption">up in 2021, and yeah, control colon doesn't work</span> <span class="audio-time caption">in terminals.</span> <span class="audio-time caption">So the mode itself is fantastic, and when I'm</span> <span class="audio-time caption">using it in a GUI Emacs, it's very useful, and I</span> <span class="audio-time caption">rarely use it now specifically because of that</span> <span class="audio-time caption">particular terminal problem.</span> <span class="audio-time caption">That is self-inflicted.</span> <span class="audio-time caption">That is not a problem with the package.</span> <span class="audio-time caption">That is a me problem.</span> <span class="audio-time caption">But yeah, I think this is the notable one that I</span> <span class="audio-time caption">bounced off of.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Yeah, just trying to find the</span> <span class="audio-time caption">right, you know, a key binding that will pass.</span> <span class="audio-time caption">Because you can't get used to key binding in one</span> <span class="audio-time caption">system and then not have it available in other</span> <span class="audio-time caption">systems.</span> <span class="audio-time caption">It's just going to mess with your brain.</span> <span class="audio-time caption">So yeah, Ray points out, yeah, Google steals</span> <span class="audio-time caption">Control Shift K, which he uses to kill tabs to</span> <span class="audio-time caption">the right.</span> <span class="audio-time caption">So it's like, oh.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  Infuriating.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Yeah, yeah.</span> <span class="audio-time caption">And of course, none of the standard keyboards</span> <span class="audio-time caption">have a super key on the thing, so you can't just</span> <span class="audio-time caption">tack on another modifier that'll get through.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  That's actually one of the reasons</span> <span class="audio-time caption">that I picked up this particular keyboard is</span> <span class="audio-time caption">Brian Carlson.</span> <span class="audio-time caption">Another Torontonian.</span> <span class="audio-time caption">He works on Git LFS and some other stuff.</span> <span class="audio-time caption">He was specifically looking for a keyboard that</span> <span class="audio-time caption">had a super key that he could remap.</span> <span class="audio-time caption">So four keys to the right of space, which this</span> <span class="audio-time caption">one has.</span> <span class="audio-time caption">And because it's ZMK, it's remappable.</span> <span class="audio-time caption">I think this might be suitable for his purpose,</span> <span class="audio-time caption">except that he wants a QMK keyboard, specifically</span> <span class="audio-time caption">because the development tools for QMK are</span> <span class="audio-time caption">packaged in W, and that's a plus for him.</span> <span class="audio-time caption">Anyhow, yes, I agree.</span> <span class="audio-time caption">Like, not having a super and a hyper key on a</span> <span class="audio-time caption">keyboard</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  feels like like one of your fingers</span> <span class="audio-time caption">that are cramped up we need more modifiers well I</span> <span class="audio-time caption">mean you know pipe organ</span> <span class="audio-time caption">Tell us about that.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  What is this?</span> <span class="audio-time caption">Oh yeah, foot pedals.</span> <span class="audio-time caption">Yeah, and I actually do have these wired into a</span> <span class="audio-time caption">little Atmel microcontroller running QMK.</span> <span class="audio-time caption">I honestly tried the foot pedal thing for a</span> <span class="audio-time caption">little while.</span> <span class="audio-time caption">It was hilarious.</span> <span class="audio-time caption">I did not find it useful.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  I don't have the hand-eye-foot</span> <span class="audio-time caption">coordination to do that thing at the same time.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  Maybe if I had learned piano as a</span> <span class="audio-time caption">kid, it would have been good.</span> <span class="audio-time caption">But yeah, I don't seem to be able to do it.</span> <span class="audio-time caption">But I gave it the old college try and it was fun.</span> <p></p><div class="transcript-heading"><span class="audio-time">42:38</span> <strong>Timers: tea-timer, tmr</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong>  Okay, I had a couple of things I</span> <span class="audio-time caption">wanted to ask about in your config.</span> <span class="audio-time caption">You have two types of timers.</span> <span class="audio-time caption">You have tea-timer and you have Prot's TMR.</span> <span class="audio-time caption">Do you use them for different purposes?</span> <span class="audio-time caption">What's going on here?</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  So I'm trying them out.</span> <span class="audio-time caption">I tried TTimer first because it was the first one</span> <span class="audio-time caption">that I found, and it was useful.</span> <span class="audio-time caption">I was actually using it in meetings because I</span> <span class="audio-time caption">would, when I was trying to keep us on topic, I</span> <span class="audio-time caption">would use that to remind us that, oh, we've got</span> <span class="audio-time caption">four other topics we need to get through.</span> <span class="audio-time caption">We're trying to give this one five minutes.</span> <span class="audio-time caption">We're running up on four.</span> <span class="audio-time caption">And it was just because it was super low overhead.</span> <span class="audio-time caption">It was easy to pick up.</span> <span class="audio-time caption">It was easy to have it displayed on my screen.</span> <span class="audio-time caption">And it didn't feel like I was...</span> <span class="audio-time caption">Running a chess timer on everyone.</span> <span class="audio-time caption">It's very subtle in the mode line.</span> <span class="audio-time caption">It was useful.</span> <span class="audio-time caption">But what I found was that when I was...</span> <span class="audio-time caption">Running multiple timers simultaneously.</span> <span class="audio-time caption">TMR, just the fact that you can list all the</span> <span class="audio-time caption">timers and manage them in a separate buffer.</span> <span class="audio-time caption">It's richer and I appreciated some of its</span> <span class="audio-time caption">documentation more.</span> <span class="audio-time caption">I haven't fully switched over to it yet.</span> <span class="audio-time caption">I'm still in exploratory mode.</span> <span class="audio-time caption">In fact, this is probably like... So I actually</span> <span class="audio-time caption">have a bunch more packages installed than I'm</span> <span class="audio-time caption">currently using.</span> <span class="audio-time caption">So I'm going to shrink this down a little bit</span> <span class="audio-time caption">just so that it doesn't line wrap.</span> <p></p><div class="transcript-heading"><span class="audio-time">43:57</span> <strong>Different stages of package use</strong></div><p></p><span class="audio-time caption"><strong>Ben:</strong> But yeah, so I've got, I think about 140 packages</span> <span class="audio-time caption">locally cloned.</span> <span class="audio-time caption">I've got, as you can see in my init,</span> <span class="audio-time caption">about half of that actually installed.</span> <span class="audio-time caption">There are various phases. I've got a clone, but I don't</span> <span class="audio-time caption">have it in my init. Or I have it in my init, but</span> <span class="audio-time caption">there's another package that offers</span> <span class="audio-time caption">similar functionality. Or I'm all-in on this particular</span> <span class="audio-time caption">choice and I'm removing the other ones.</span> <span class="audio-time caption">It's a gradual kind of progression.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Yeah, we're all auditioning</span> <span class="audio-time caption">packages to see if they fit in our workflow and</span> <span class="audio-time caption">all that stuff.</span> <span class="audio-time caption">I was curious also about your elfeed things.</span> <span class="audio-time caption">You have a few things related to elfeed.</span> <span class="audio-time caption">Actually, do you want to talk about the thing you</span> <span class="audio-time caption">just highlighted first?</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  No, we'll get back to it in a sec.</span> <span class="audio-time caption">I'm keeping an eye on the clock.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  But yeah, elfeed.</span> <p></p><div class="transcript-heading"><span class="audio-time">44:47</span> <strong>Elfeed</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong> Yeah, you've got a couple of interesting things</span> <span class="audio-time caption">in your elfeed setup, including picking a search</span> <span class="audio-time caption">from a bookmark or other shortcuts like that.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  So I have discovered in my</span> <span class="audio-time caption">conversations with the new maintainers for elfeed</span> <span class="audio-time caption">that my elfeed habits are very deviant.</span> <span class="audio-time caption">So let me actually start off by going through...</span> <span class="audio-time caption">You can see that like the top of my elfeed list is</span> <span class="audio-time caption">kind of in one format and down at the bottom, the</span> <span class="audio-time caption">ones that are closer to present day are organized</span> <span class="audio-time caption">in a different way.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  You've got tags now.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  So my feed list is, I mean, it</span> <span class="audio-time caption">started in Google Reader.</span> <span class="audio-time caption">It's kind of been forward ported since then.</span> <span class="audio-time caption">It's long.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  I love the comments.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  But one of the consequences of</span> <span class="audio-time caption">having a long feed list is that I have an</span> <span class="audio-time caption">enormous elfeed database.</span> <span class="audio-time caption">And I use it for completely different purposes.</span> <span class="audio-time caption">So for example, I'm going to show off that little</span> <span class="audio-time caption">default search.</span> <span class="audio-time caption">I keep an eye on projects that have releases</span> <span class="audio-time caption">that aren't packaged by Debian, for example.</span> <span class="audio-time caption">So I've got this little ATS Mini.</span> <span class="audio-time caption">basically a small AM FM radio that happens to run</span> <span class="audio-time caption">on ESP32 and the firmware for this community</span> <span class="audio-time caption">developed and it's kind of interesting but like</span> <span class="audio-time caption">that's not packaged by Debian so I pay attention</span> <span class="audio-time caption">to or I subscribe to the release feed for that</span> <span class="audio-time caption">particular project.</span> <span class="audio-time caption">I do keep in keep an eye on the Linux kernel</span> <span class="audio-time caption">especially these days because</span> <span class="audio-time caption">The gallop of security vulnerabilities coming out</span> <span class="audio-time caption">of mythos analyses right now means that I have to</span> <span class="audio-time caption">pay more attention than usual to fresh updates.</span> <span class="audio-time caption">So generally I run Debian stable, but I do run</span> <span class="audio-time caption">kernels from backports and I want to know when</span> <span class="audio-time caption">those are available.</span> <span class="audio-time caption">MeshTastic.</span> <span class="audio-time caption">I was paying more attention to this a couple of</span> <span class="audio-time caption">weeks ago.</span> <span class="audio-time caption">I'm not going to reach that right now.</span> <span class="audio-time caption">But yeah, the local MeshTastic community in</span> <span class="audio-time caption">Toronto is plagued by a couple of griefers that</span> <span class="audio-time caption">make it a lot less fun.</span> <span class="audio-time caption">So I'm paying a bit less attention to that right</span> <span class="audio-time caption">now.</span> <span class="audio-time caption">But yeah, so like one of the bookmarks that I</span> <span class="audio-time caption">have is software currency.</span> <span class="audio-time caption">Another one is, for example, the YouTube channels</span> <span class="audio-time caption">that I subscribe to.</span> <span class="audio-time caption">Thank goodness for Elf YouTube.</span> <span class="audio-time caption">It is so nice to be able to get the transcripts</span> <span class="audio-time caption">for things directly in there.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  There's even a sponsor block</span> <span class="audio-time caption">integration so you can skip all the promotions</span> <span class="audio-time caption">and stuff.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  Yeah, I mean, so again, my use of</span> <span class="audio-time caption">YouTube is also deviant in that I pretty much</span> <span class="audio-time caption">strictly subscribe to RSS feeds and they're</span> <span class="audio-time caption">downloaded onto the file server.</span> <span class="audio-time caption">So when a new recording comes out, it gets</span> <span class="audio-time caption">dropped there.</span> <span class="audio-time caption">I'll watch it.</span> <span class="audio-time caption">And then I've got a little widget that scans</span> <span class="audio-time caption">through my Kodi database for watched files.</span> <span class="audio-time caption">Once YouTube files show up in the watch list,</span> <span class="audio-time caption">they're automatically purged.</span> <span class="audio-time caption">And it means I just never see an ad.</span> <span class="audio-time caption">It's not just satisfying.</span> <span class="audio-time caption">I don't think that I would be able to pay</span> <span class="audio-time caption">attention if I was being constantly interrupted</span> <span class="audio-time caption">because of the way that my brain works.</span> <span class="audio-time caption">But yeah, so being able to quickly search for</span> <span class="audio-time caption">YouTube is one thing.</span> <p></p><div class="transcript-heading"><span class="audio-time">48:36</span> <strong>Spoilers
</strong></div><p></p><a href="https://sachachua.com/blog/2026/06/june-4-emacs-chat-with-ben-zanin-gnomon-mastodon-social/emacs-chat-25-ben-zanin-00-48-40-433.jpg"><img loading="lazy" src="https://sachachua.com/blog/2026/06/june-4-emacs-chat-with-ben-zanin-gnomon-mastodon-social/emacs-chat-25-ben-zanin-00-48-40-433.jpg" alt="image from video 00:48:40.433"></a><span class="audio-time caption"><strong>Ben:</strong> I do have articles that I've marked as spoilers for media</span> <span class="audio-time caption">that I haven't watched or read yet.</span> <span class="audio-time caption">Maybe I go to an extreme degree, but I'll try to</span> <span class="audio-time caption">avoid previews for new movies, for example.</span> <span class="audio-time caption">I do want to actually go back to them later on.</span> <span class="audio-time caption">Marking articles as having spoilers that I want</span> <span class="audio-time caption">to revisit later on is an easy way of not having</span> <span class="audio-time caption">to worry about it anymore.</span> <span class="audio-time caption">For a while, back in the days when I was</span> <span class="audio-time caption">paying more attention to... Enter the Dragon was</span> <span class="audio-time caption">the sequel to... What was that TV show?</span> <span class="audio-time caption">George R.R. Martin... Seven seasons and it went badly off the</span> <span class="audio-time caption">rails in season six.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Game of Thrones.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  Thank you.</span> <span class="audio-time caption">So when I was watching that for a while, several</span> <span class="audio-time caption">of the sites that I was reading would have</span> <span class="audio-time caption">individual episode updates.</span> <span class="audio-time caption">I really appreciated having a list of Elfeed keywords</span> <span class="audio-time caption">that I could automatically apply those tags to.</span> <span class="audio-time caption">I wouldn't even see the headlines because it</span> <span class="audio-time caption">was problematic enough.</span> <span class="audio-time caption">I've become less...</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Nice.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  I've been putting less effort into</span> <span class="audio-time caption">maintaining that now, but the infrastructure is</span> <span class="audio-time caption">still there, and I can lean on it if I need to.</span> <p></p><div class="transcript-heading"><span class="audio-time">49:53</span> <strong>Comparing different news sources</strong></div><p></p><span class="audio-time caption"><strong>Ben:</strong> One of the things that I don't have set up right now</span> <span class="audio-time caption">is a quick search for the municipal topics that I cover.</span> <span class="audio-time caption">I tend to subscribe to a lot of news because I</span> <span class="audio-time caption">found that, for example, it's interesting to see</span> <span class="audio-time caption">how the Toronto Star covers stuff differently</span> <span class="audio-time caption">from other local newspapers.</span> <span class="audio-time caption">It's useful to be able to quickly pull up</span> <span class="audio-time caption">the five or six publications that cover</span> <span class="audio-time caption">news in the same way and then look through the</span> <span class="audio-time caption">annotations for them or add the annotations</span> <span class="audio-time caption">myself. I can see that this particular story</span> <span class="audio-time caption">was covered by this journalist in this</span> <span class="audio-time caption">publication in this way, and then it lets me</span> <span class="audio-time caption">cross-reference so that I can pay attention to</span> <span class="audio-time caption">topics that are under-covered or publications</span> <span class="audio-time caption">that habitually leave out particular aspects of</span> <span class="audio-time caption">news stories.</span> <span class="audio-time caption">It lets me pay more attention to</span> <span class="audio-time caption">the trends of publications as well as to the</span> <span class="audio-time caption">stories that they're covering.</span> <span class="audio-time caption">The consequence of that is that my Elfeed</span> <span class="audio-time caption">database is 4.5 gigs.</span> <span class="audio-time caption">It's common for me... I don't know if</span> <span class="audio-time caption">that actually shows.</span> <span class="audio-time caption">It's common for me to have like 65,000 articles</span> <span class="audio-time caption">in like the six month horizon for the default Elfeed</span> <span class="audio-time caption">searches.</span> <span class="audio-time caption">That means that searches and redraws are</span> <span class="audio-time caption">expensive, even on a relatively performant machine.</span> <span class="audio-time caption">You've probably seen some of the workarounds</span> <span class="audio-time caption">that I've got.</span> <span class="audio-time caption">This little bookmark selector is one of those</span> <span class="audio-time caption">workarounds.</span> <span class="audio-time caption">Elfeed's interactive search: super, super useful.</span> <span class="audio-time caption">But if you're trying to do it like this...</span> <span class="audio-time caption">Actually, it's not so bad.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  I love this.</span> <span class="audio-time caption">When you see someone using Elfeed for 65,000</span> <span class="audio-time caption">items, you get a sense of what it can be used</span> <span class="audio-time caption">for when you're really stressing it.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  And the organization of the bookmarks that I have</span> <span class="audio-time caption">means that I do have one river of news</span> <span class="audio-time caption">of all of the things that I want to pay attention to.</span> <span class="audio-time caption">But it's seven or eight pretty divergent topics</span> <span class="audio-time caption">with not a lot of overlap.</span> <span class="audio-time caption">It's neat to be able to</span> <span class="audio-time caption">think of Elfeed as the thing where news</span> <span class="audio-time caption">information comes in. The individual</span> <span class="audio-time caption">bookmarks are the topics that are grouped</span> <span class="audio-time caption">together that I actually care about and want to</span> <span class="audio-time caption">read about in concert with each other.</span> <span class="audio-time caption">If I specifically narrow it down to just Emacs</span> <span class="audio-time caption">stuff, one of the things that I can easily do is</span> <span class="audio-time caption">add a bookmark for that search. If I name it...</span> <span class="audio-time caption">Now that I've got that bookmark saved...</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  And then it's like, bookmark annotation.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  Right. It ends up in my dot file as a git commit.</span> <p></p><div class="transcript-heading"><span class="audio-time">53:13</span> <strong>Bookmark naming conventions</strong></div><p></p><span class="audio-time caption"><strong>Ben:</strong> Now that that bookmark exists, simply because of</span> <span class="audio-time caption">the naming (elfeed-search-...), now it shows up in</span> <span class="audio-time caption">completion.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Precisely this sort of stuff.</span> <span class="audio-time caption">I am under-utilizing bookmarks, I think.</span> <p></p><div class="transcript-heading"><span class="audio-time">53:24</span> <strong>Naming conventions simplify building new workflows</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong> I love this idea of using bookmarks</span> <span class="audio-time caption">with a naming convention</span> <span class="audio-time caption">and then writing Emacs Lisp</span> <span class="audio-time caption">to take advantage of that naming convention</span> <span class="audio-time caption">to make that easy to jump to, easy to use in other things.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  Yeah, it means I don't really have...</span> <span class="audio-time caption">When I notice that there's a thing I don't have,</span> <span class="audio-time caption">it diminishes the activation energy for</span> <span class="audio-time caption">building a new workflow.</span> <span class="audio-time caption">It means that I don't have to put a lot of</span> <span class="audio-time caption">thought into it.</span> <span class="audio-time caption">I can quickly do it.</span> <span class="audio-time caption">If it turns out to not be useful, I can</span> <span class="audio-time caption">quickly get rid of it.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Very cool.</span> <p></p><div class="transcript-heading"><span class="audio-time">53:50</span> <strong>elfeed-curate for annotations
</strong></div><p></p><a href="https://sachachua.com/blog/2026/06/june-4-emacs-chat-with-ben-zanin-gnomon-mastodon-social/emacs-chat-25-ben-zanin-00-54-52-533.jpg"><img loading="lazy" src="https://sachachua.com/blog/2026/06/june-4-emacs-chat-with-ben-zanin-gnomon-mastodon-social/emacs-chat-25-ben-zanin-00-54-52-533.jpg" alt="image from video 00:54:52.533"></a><span class="audio-time caption"><strong>Sacha:</strong> I had one more thing that I wanted to ask you</span> <span class="audio-time caption">about elfeed that I want to squeeze in,</span> <span class="audio-time caption">in the five minutes that I have before the kiddo comes out</span> <span class="audio-time caption">for lunch break.</span> <span class="audio-time caption">This elfeed-curate that you're using, this is the</span> <span class="audio-time caption">first time I've come across it in the config.</span> <span class="audio-time caption">Are you sharing your notes or your selections</span> <span class="audio-time caption">with other people, or just for yourself?</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  No. It's just for myself.</span> <span class="audio-time caption">What I'm trying to replicate is,</span> <span class="audio-time caption">back in Google Reader days,</span> <span class="audio-time caption">I really appreciated how when you added an annotation</span> <span class="audio-time caption">to an article that you were reading,</span> <span class="audio-time caption">by default, that annotation would be viewable by</span> <span class="audio-time caption">other people in your social graph.</span> <span class="audio-time caption">That was super interesting.</span> <span class="audio-time caption">Sometimes you could also add personal-only annotations.</span> <span class="audio-time caption">Actually, I don't think that's the keyword that it uses.</span> <span class="audio-time caption">I think it’s just <code>+ann</code>.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Also, because you have an Emacs</span> <span class="audio-time caption">keyword on it, so I don't know whether you have</span> <span class="audio-time caption">any annotated Emacs ones.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  Yeah.</span> <span class="audio-time caption">Well, I mean, generally, if I've added an</span> <span class="audio-time caption">annotation, it will be.</span> <span class="audio-time caption">So, for example, here.</span> <span class="audio-time caption">Right? Super useful.</span> <span class="audio-time caption">Well, super useful for me, anyhow.</span> <span class="audio-time caption">If I find that there's an annotation that is more...</span> <span class="audio-time caption">This is inflammatory.</span> <span class="audio-time caption">It doesn't need to go out on the web.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Sorry, did you need me to kill the stream?</span> <span class="audio-time caption">I have a 10-second window.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  No, it's all good.</span> <span class="audio-time caption">I'm not worried about sharing this, but it's not</span> <span class="audio-time caption">something I've posted.</span> <span class="audio-time caption">What the nice thing is, is that if it is</span> <span class="audio-time caption">something that I want to share, it's really,</span> <span class="audio-time caption">really easy to just drop this into Mastodon mode.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Very cool.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  That's one of the ways that I use it.</span> <span class="audio-time caption">Because the annotations are just Org Mode</span> <span class="audio-time caption">files, you can add links to other things and it</span> <span class="audio-time caption">becomes just as useful as anything else.</span> <p></p><div class="transcript-heading"><span class="audio-time">55:46</span> <strong>mytoots archives Mastodon toots</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong>  You're saying this can flow</span> <span class="audio-time caption">into Mastodon and from there, once you toot it...</span> <span class="audio-time caption">I think you're using mytoots</span> <span class="audio-time caption">that you mentioned in your config for</span> <span class="audio-time caption">archiving it?</span> <span class="audio-time caption">Or searching, yeah, okay.</span> <span class="audio-time caption">Oh, except it's currently not working.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  Yeah, I don't have it loaded right now.</span> <span class="audio-time caption">So mytoots, it just loads the backup of</span> <span class="audio-time caption">your export archive.</span> <span class="audio-time caption">So it loads the...</span> <span class="audio-time caption">What's the most recent one?</span> <span class="audio-time caption">So yeah, it was your outbox JSON file, which is</span> <span class="audio-time caption">the most recent one here.</span> <span class="audio-time caption">I've got an Org Mode reminder to download it</span> <span class="audio-time caption">roughly quarterly.</span> <span class="audio-time caption">My outbox is about 100 megs right now.</span> <span class="audio-time caption">Compared to 4.5 gigs for elfeed,</span> <span class="audio-time caption">it's not so big.</span> <span class="audio-time caption">That's not going to redraw properly.</span> <span class="audio-time caption">I was just going to show it. My resident</span> <span class="audio-time caption">Emacs memory size right now is about like five or</span> <span class="audio-time caption">six gigs.</span> <span class="audio-time caption">It's a little bit embarrassing.</span> <span class="audio-time caption">By comparison, 100 megs of JSON in RAM is not so</span> <span class="audio-time caption">bad, but having an instant search for</span> <span class="audio-time caption">everything that you posted and being able to</span> <span class="audio-time caption">bounce back from your local archive to the</span> <span class="audio-time caption">conversation thread that's live and see anything</span> <span class="audio-time caption">new that comes in...</span> <span class="audio-time caption">Again, it lets me exercise that outboard brain</span> <span class="audio-time caption">kind of idea.</span> <span class="audio-time caption">So yeah, mytoots is super useful.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  I like it a lot.</span> <p></p><div class="transcript-heading"><span class="audio-time">57:06</span> <strong>Mentoring offer</strong></div><p></p><span class="audio-time caption"><strong>Sacha:</strong> The last thing that I want to ask</span> <span class="audio-time caption">before the kiddo (because I have two</span> <span class="audio-time caption">minutes) is that you have a mentoring offer</span> <span class="audio-time caption">pinned in your Mastodon, too.</span> <span class="audio-time caption">Have people taken you up on it, especially if</span> <span class="audio-time caption">they've taken you up on Emacs?</span> <span class="audio-time caption">Is that ongoing or forgotten about or whatever?</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  Not forgotten about.</span> <span class="audio-time caption">Very much real.</span> <span class="audio-time caption">Still open.</span> <span class="audio-time caption">I haven't refreshed that offer recently, but it's</span> <span class="audio-time caption">still pinned for a reason.</span> <span class="audio-time caption">I think maybe a dozen or so folks have</span> <span class="audio-time caption">asked for that.</span> <span class="audio-time caption">9 or 10 success stories, I think.</span> <span class="audio-time caption">Nobody's asked for Emacs tutorialship yet.</span> <span class="audio-time caption">That's fine.</span> <span class="audio-time caption">Again, I love Emacs.</span> <span class="audio-time caption">I use it.</span> <span class="audio-time caption">I don't often recommend it.</span> <span class="audio-time caption">But if anybody was curious about that, I would be</span> <span class="audio-time caption">very open to the idea.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  All right, so if people want to</span> <span class="audio-time caption">also develop a very interesting elfeed setup,</span> <span class="audio-time caption">they know who to talk to.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  Please, I would love that conversation.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Thank you so much.</span> <span class="audio-time caption">Yes, go ahead.</span> <p></p><div class="transcript-heading"><span class="audio-time">58:02</span> <strong>A local instance of public-inbox can let you use Gnus to read mailing lists quickly</strong></div><p></p><span class="audio-time caption"><strong>Ben:</strong>  Oh yeah, there's just one last</span> <span class="audio-time caption">thing I want to mention, and I realize we're</span> <span class="audio-time caption">right up against time.</span> <span class="audio-time caption">I use Gnus. I use mu4e for email,</span> <span class="audio-time caption">but I use Gnus for reading mailing lists.</span> <span class="audio-time caption">I just wanted to strongly recommend to</span> <span class="audio-time caption">anybody who is thinking about it... This is amazing.</span> <span class="audio-time caption">You gotta do this.</span> <span class="audio-time caption">public-inbox lets you keep a complete local</span> <span class="audio-time caption">archive of the entire mailing list.</span> <span class="audio-time caption">Searches are instant.</span> <span class="audio-time caption">Tracking threads is instant.</span> <span class="audio-time caption">Check it out.</span> <span class="audio-time caption">It's fantastic.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  That's great because</span> <span class="audio-time caption">Emacs-devel has a gazillion threads. How do you</span> <span class="audio-time caption">even keep track of all this stuff? But if you've</span> <span class="audio-time caption">got Gnus and if you've got this set up,</span> <span class="audio-time caption">then you're no longer dependent on the good</span> <span class="audio-time caption">graces of Gmane being around as an NNTP to</span> <span class="audio-time caption">mailing list gateway.</span> <span class="audio-time caption">@JonKishore11 wants to know if you have a</span> <span class="audio-time caption">YouTube channel. I'm guessing you don't yet.</span> <p></p><span class="audio-time caption"><strong>Ben:</strong>  I don't really like my face very much.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong>  Ping Ben on Mastodon and ask about this mentoring</span> <span class="audio-time caption">thing and then share your notes so we can all</span> <span class="audio-time caption">learn from it.</span> <span class="audio-time caption">Thank you so much for today.</span> <span class="audio-time caption">I look forward to chatting with you more through toots.</span> <span class="audio-time caption">What is the verb, you know, in the fediverse?</span> <span class="audio-time caption">All right.</span> <span class="audio-time caption">Thank you so much.</span> <p></p><span class="audio-time caption"><strong>Sacha:</strong> </span></div>
<p></p>


<a name="end-emacs-chat-25-ben-zanin-transcript"></a>
</div>
</div>
<div class="outline-3">
<h3><a href="https://sachachua.com/blog/category/emacs/feed/index.xml#emacs-chats-emacs-chat-25-ben-zanin-gnomon-mastodon-social-chat">Chat</a></h3>
<div class="outline-text-3">
<ul>
<li><span class="nick">sachactube:</span> ​​only slightly panicking behind the scenes 🙂 Nudged Ben by Mastodon in case we got our wires crossed</li>
<li><span class="nick">sachactube:</span> ​​yay, he's here, just getting sound sorted</li>
<li><span class="nick">symbiopoyesis:</span> Good morning</li>
<li><span class="nick">x_goose_x:</span> ​​hey gnomonnnnnn</li>
<li><span class="nick">CharlieBaker707:</span> ​yay! love the split keyboard. recently bought one myself. i was getting shoulder and neck pain from so many hours keeping by hands close together, but the split let's my shoulder's relax.</li>
<li><span class="nick">ShaeErisson:</span> ​How do you make a capture template to stay on-agenda and record decisions? Any tips?</li>
<li><span class="nick">PuercoPop:</span> ​​Regarding terminal emacs, did they need to adapt any keybindings to avoid clashses with the terminal keybindings?</li>
<li><span class="nick">AyanRaza-n1x:</span> ​​is that the creator of emacs?</li>
<li><span class="nick">Ray-On-Emacs:</span> ​Yes! Google steals C-S-k, which I use to kill tabs to the right on Vivaldi!</li>
<li><span class="nick">CharlieBaker707:</span> ​elfeed is like a distraction alleviation machine. I agree with Ben, I don't think I could consume any of this information outside of Emacs. Ads and even varying formats distract me too much.</li>
<li><span class="nick">JonKishore11:</span> ​​do he have YT</li>
<li><span class="nick">sachactube:</span> ​​Thanks for hanging out, everyone! =)</li>
<li><span class="nick">gnomon027:</span> Thanks so much for running this whole series, @sachactube !!</li>
</ul>
</div>
</div>
<div><a href="https://sachachua.com/blog/2026/06/june-4-emacs-chat-with-ben-zanin-gnomon-mastodon-social/index.org">View Org source for this post</a></div>
<p>You can <a href="mailto:sacha@sachachua.com?subject=Comment%20on%20https%3A%2F%2Fsachachua.com%2Fblog%2F2026%2F06%2Fjune-4-emacs-chat-with-ben-zanin-gnomon-mastodon-social%2F&amp;body=Name%20you%20want%20to%20be%20credited%20by%20(if%20any)%3A%20%0AMessage%3A%20%0ACan%20I%20share%20your%20comment%20so%20other%20people%20can%20learn%20from%20it%3F%20Yes%2FNo%0A">e-mail me at sacha@sachachua.com</a>.</p></body></html>]]></content>
        <author>
            <name>Sacha Chua</name>
            <uri>https://sachachua.com/blog/category/emacs/feed/index.xml</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[TAONAW - Emacs and Org Mode: Correcting photo orientation for org-mode in Linux]]></title>
        <id>https://taonaw.com/2026/06/03/correcting-photo-orientation-for-orgmode.html</id>
        <link href="https://taonaw.com/2026/06/03/correcting-photo-orientation-for-orgmode.html"/>
        <updated>2026-06-03T12:29:09.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>Here’s a niche problem: When viewing iPhone-captured photos in org-mode on Linux, they always appear in landscape orientation, even if you took them in portrait.</p>
<p>The reason is that the sensor of the camera on the phone is physically embedded in landscape mode, so all photos are in landscape mode; when you hold the phone in portrait mode (which is how you hold it most of the time), the phone detects that and implements a fix in the EXIF data file. Essentially, a software fix to a hardware design issue.</p>
<p>Since most photos I take are usually in portrait orientation, it means I need to twist my neck and view images at a 90-degree angle when I look at my Journelly entries.</p>
<p>The source of the problem seems to stem from how org-mode interprets EXIF data in the photo: it doesn’t. It relies on other parts of Emacs, which in turn rely on parts of the OS, to do the job. On Linux (at least on Kubuntu, which is what I use these days), those parts don’t handle EXIF orientation information. Why and how, I am not sure, it’s more digging than I have the time for right now… but anyway - there’s a simple fix.</p>
<p><a href="https://imagemagick.org/command-line-options/#auto-orient">Auto-orient</a>, which is part of <a href="https://imagemagick.org/mogrify/">ImageMagick’s mogrify tool</a>. And if you use Emacs on Linux, good chance it’s already installed:</p>
<blockquote>
<p>This operator reads and resets the EXIF image profile setting ‘Orientation’ and then performs the appropriate 90 degree rotation on the image to orient the image, for correct viewing.</p>
</blockquote>
<p>To execute on an image file: <code>mogrify -auto-orient &lt;file&gt;</code>.</p>
<p>And because I use Emacs, of course there’s a <a href="https://github.com/xenodium/dwim-shell-command">dwim-shell-command</a> solution:</p>
<div class="highlight"><pre><code class="language-elisp"><span><span>    (defun jtr/dwim-image-auto-orient ()
</span></span><span><span>      <span>"Auto-orient images based on EXIF data using mogrify."</span>
</span></span><span><span>      (interactive)
</span></span><span><span>      (dwim-shell-command-on-marked-files
</span></span><span><span>       <span>"Auto-orient images"</span>
</span></span><span><span>       <span>"mogrify -auto-orient '&lt;&lt;f&gt;&gt;'"</span>
</span></span><span><span>       :utils <span>"mogrify"</span>
</span></span><span><span>       :silent-success <span>t</span>))
</span></span></code></pre></div><p>That last part,<code>:silent-success</code>, closes the empty buffer that pops up after successful execution, as mogrify doesn’t really produce an output window. So, it will just bring us back to Dired.</p>
</body></html>]]></content>
        <author>
            <name>TAONAW - Emacs and Org Mode</name>
            <uri>https://taonaw.com/categories/emacs-org-mode/</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Lars Ingebrigtsen: Todo Lists and Procrastination]]></title>
        <id>https://lars.ingebrigtsen.no/2026/06/03/todo-lists-and-procrastination/</id>
        <link href="https://lars.ingebrigtsen.no/2026/06/03/todo-lists-and-procrastination/"/>
        <updated>2026-06-03T10:34:21.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p><a href="https://lars.ingebrigtsen.no/wp-content/uploads/2026/05/2026-05-31-4.jpeg"><img loading="lazy" src="https://lars.ingebrigtsen.no/wp-content/uploads/2026/05/2026-05-31-4.jpeg" alt="" width="840" height="106" srcset="https://lars.ingebrigtsen.no/wp-content/uploads/2026/05/2026-05-31-4.jpeg 1372w, https://lars.ingebrigtsen.no/wp-content/uploads/2026/05/2026-05-31-4-300x38.jpeg 300w, https://lars.ingebrigtsen.no/wp-content/uploads/2026/05/2026-05-31-4-1024x130.jpeg 1024w, https://lars.ingebrigtsen.no/wp-content/uploads/2026/05/2026-05-31-4-768x97.jpeg 768w"></a></p>
<p>Two years ago I wrote a <a href="https://lars.ingebrigtsen.no/2024/06/17/a-super-simple-todo-package-for-emacs/">super simple todo package for Emacs</a> to see whether I could get over my tendency to 1) procrastinate a lot and 2) being annoyed at my tendency to procrastinate.</p>
<p>Reader, you won’t believe the answer: Yes and no.  Or rather, no and yes.</p>
<p>That is, I still procrastinate a lot (but less than before), but I’m way less annoyed about it.</p>
<p>As you can clearly see from the Emacs mode line above, I’ve got 27 “new” things on the todo list, 4 things that are “in progress” and…  tada!  616 things that have been done!</p>
<p>It cannot be!  That’s about one thing per day!  (Although it’s more like no things most days and then eight things on a random day.)</p>
<p><a href="https://lars.ingebrigtsen.no/wp-content/uploads/2026/05/anddo.jpg"><img loading="lazy" src="https://lars.ingebrigtsen.no/wp-content/uploads/2026/05/anddo.jpg" alt="" width="840" height="1071" srcset="https://lars.ingebrigtsen.no/wp-content/uploads/2026/05/anddo.jpg 1367w, https://lars.ingebrigtsen.no/wp-content/uploads/2026/05/anddo-235x300.jpg 235w, https://lars.ingebrigtsen.no/wp-content/uploads/2026/05/anddo-803x1024.jpg 803w, https://lars.ingebrigtsen.no/wp-content/uploads/2026/05/anddo-768x980.jpg 768w, https://lars.ingebrigtsen.no/wp-content/uploads/2026/05/anddo-1204x1536.jpg 1204w"></a></p>
<p>I’ve had a look at other todo systems, but like I said two years ago, they seem to be specifically made to enable further procrastination:  You can tinker endlessly with priorities, deadlines and arranging things in hierarchies.  So you can spend an hour working on your todo list and then feel you’ve really made some progress.  Which is a total lie, of course.</p>
<p>And open sores todo lists encourage further meta-tweaking — altering the todo software itself, so that you can add even more features.  I’m proud to say that after starting to use it two years ago, I haven’t touched the <a href="https://github.com/larsmagne/anddo.el">anddo</a> code even once!  Behold the Microsoft Github repo!</p>
<p>So it’s just a list of tasks, and the ones that are new or in progress are shown.  You can edit them and add notes, and you can change status, but that’s it.  No dates, no priorities, no nothing.  Just do it.</p>
<p>This system has really made me actually take care of a lot of annoyances and stuff, but even more importantly: Instead of looking at the lamp that’s sitting on the hall table every day and going “oh yeah, I should hang that on the wall somewhere; I must remember that”, I just put it on the todo list…  and then my brain stops doing that every time I see the lamp on the hall table.</p>
<p>The system works!</p>
<p>(And then I might even hang it on the wall one day when I’m in the mood to do something, and I pull up the todo list…  I might.)</p>
<p>I sort of…  postpone the procrastination.</p>
<p>Anyway.  That’s the life hack.</p>
</body></html>]]></content>
        <author>
            <name>Lars Ingebrigtsen</name>
            <uri>https://lars.ingebrigtsen.no</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Charlie Holland: Beyond ICR: Incremental 'Suggesting' Read in Emacs]]></title>
        <id>https://www.chiply.dev/post-incremental-suggesting-read</id>
        <link href="https://www.chiply.dev/post-incremental-suggesting-read"/>
        <updated>2026-06-03T08:41:15.000Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><div class="outline-2">
<h2><span class="section-number-2">1.</span> TLDR</h2>
<div class="outline-text-2">
<p>
This is the sixth post in my series on Emacs completion.  The <a href="https://www.chiply.dev/post-icr-primer">first</a> argued that <a href="https://www.chiply.dev/post-icr-primer#what-is-incremental-completing-read-">Incremental Completing Read (ICR)</a> is a <i>structural</i> property of an interface, not an interface itself; the next four made it concrete with the <a href="https://www.chiply.dev/post-vompeccc">VOMPECCC</a> framework, my Spotify client (<a href="https://www.chiply.dev/post-vompeccc-spot"><code>spot</code>)</a>, a <a href="https://www.chiply.dev/post-vompeccc-fruits">produce picker</a>, and a <a href="https://www.chiply.dev/post-vompeccc-showcase">VOMPECCC showcase</a>.  This one coins a term for a special case, <i>Incremental Suggesting Read</i> (ISR), where the candidate set produced by incrementally typed input is a <i>suggestion</i>, rather than a literal <i>completion</i> of that input.  The ability to generate inferred matches in addition to literal matches vastly expands the scope of what a 'completion' system can do.  Two conceptual sources supply the suggestions: 1) semantic retrieval and 2) generative synthesis.
</p>

<p>
This post is more speculative than useful, so carry that pinch of salt with you as you watch the video or read this post.
</p>

<p>
</p><div class="youtube-container">


</div>
<p></p>
</div>
</div>
<div class="outline-2">
<h2><span class="section-number-2">2.</span> From completing to suggesting&nbsp;&nbsp;&nbsp;<span class="tag"><span class="icr">icr</span>&nbsp;<span class="isr">isr</span>&nbsp;<span class="definition">definition</span></span></h2>
<div class="outline-text-2">
<p>
<a href="https://www.chiply.dev/post-icr-primer#what-is-incremental-completing-read-">The initial post in this series</a> broke down the 3 key words in ICR: <i>read</i> (type input), <i>completing</i> (match input against a candidate set), and <i>incremental</i> (recompute matches on every keystroke).
</p>

<p>
ISR is perfectly analgous, except the materialized candidate set is not a list of literal match candidates, but rather a list of inferred suggestions. 
</p>

<p>
Put another way, in <i>completing</i> read, the candidates <b>lexically correspond</b> to your input. In <i>suggesting</i> read, a model <b>infers</b> candidates from your input.
</p>

<p>
In this post and video above, I discuss two sources of ISR:
</p>

<ol>
<li><i>Semantic retrieval</i>: the candidates are generated from concrete, existing data (notes, mail, code), and ISR ranks them by meaning, or semantic proximity to the input.  A well established demo of this in Emacs is John Kitchin's <a href="https://www.youtube.com/watch?v=bB7rywlahSc">"semantic completing read"</a>, which ranks Org files by embedding similarity to what your input 'means'.</li>
<li><i>Generative synthesis</i>: the candidate is written on demand (by an LLM) and is effectively non-existent prior to your input, which can appropriately be called a 'prompt' in these cases.</li>
</ol>
</div>
</div>
<div class="outline-2">
<h2><span class="section-number-2">3.</span> The same machinery, a different source&nbsp;&nbsp;&nbsp;<span class="tag"><span class="substrate">substrate</span>&nbsp;<span class="thesis">thesis</span></span></h2>
<div class="outline-text-2">
<p>
Because Emacs built-ins (and of course VOMPECCC) are so strong, they can be used to support ISR use-cases.  Everything we demonstrated in prior posts is relevant here, most of all the consult package.
</p>

<p>
The key enabler of ISR is the fact that <code>completing-read</code>'s candidate collection can be a <i>function</i>: Emacs passes your input to a function, and that function returns the inferred suggestions.  That's powerful in the abstract, and concretely it enables our semantic retreival and generative synthesis use cases.
</p>

<p>
Because Emacs clearly already supports this abstraction, everything downstream of the source (everything we've demonstrated in this series up until this point) is re-usable.  In line with a common theme in Emacs, our precious, hard-earned muscle memory transfers perfectly from ICR to ISR.
</p>

<p>
<a href="https://github.com/minad/consult"><code>consult</code></a> is especially enabling of ISR because it is functionally optimized to supply candidates from a <i>backend</i> rather than a materialized list.  We've already shown how we can hand consult a function (that hits an API) and consult supplies asynchronous fetching, keystroke debouncing, live preview, grouping, narrowing, and (optionally) <a href="https://github.com/oantolin/embark">Embark</a> actions.  
</p>

<p>
There are already public examples of ISR in action:
</p>

<p>
In the generative syntehsis case, an integration between 2 packages provides a beautful example.  Armin's <a href="https://github.com/armindarvish/consult-omni"><code>consult-omni</code></a>  ships with a consult interface to karthink's <a href="https://github.com/karthink/gptel">gptel</a> in <a href="https://github.com/armindarvish/consult-omni/blob/main/sources/consult-omni-gptel.el">gptel source</a>.  This integration with gptel's <i>suggesting</i> backend is defined the same way as it would be with a <i>completing</i> backend, whether that's <a href="https://github.com/BurntSushi/ripgrep">ripgrep</a> or a search API.  Another generative synthesis example would be completing for the possible LLM expansions of inline code or prose (think <a href="https://github.com/copilot-emacs/copilot.el">GitHub Copilot's Emacs extensions</a>).
</p>

<p>
In the semantic retreival case, I implemented an example borrowing from John Kitchin's <a href="https://github.com/jkitchin/org-db-v3"><code>org-db-v3</code></a> for the embeddings.  
</p>

<p>
The point of this section is that the existing ICR machinery (especially consult in this case) can be re-used for ISR.  Below you can see how I reuse it.  Pay special attention to <code>consult--read</code> and <code>consult--dynamic-collection</code> in my <code>chiply-isr-semantic-read</code> command:
</p>

<div class="org-src-container">
<pre>(defun chiply-isr--collection (input)
  (mapcar (lambda (r)
            (cons (format "%-22s  %s"
                          (file-name-nondirectory (alist-get 'filename r))
                          (alist-get 'chunk_text r))
                  (alist-get 'filename r)))
          (chiply-isr--search input)))    ; embedding search over my sample corpus

;; consult drives that function as a live, per-keystroke source.
(defun chiply-isr-semantic-read ()
  (interactive)
  (find-file
   (consult--read
    (consult--dynamic-collection #'chiply-isr--collection
      :min-input 3 :debounce 0.3)
    :prompt "Suggesting read (by meaning): "
    :lookup #'consult--lookup-cdr
    :require-match t :sort nil)))
</pre>
</div>

<p>
The <i>suggesting</i> <code>--collection</code> function is the only thing that differs from a <i>completing</i> character-matching source.  The <a href="https://github.com/chiply/.zetta.d/blob/main/modules/completion/chiply-isr.el">full <code>chiply-isr</code> module</a> lives in my Emacs config, but I built it for this demo, so I don't recommend you use it.
</p>
</div>
</div>
<div class="outline-2">
<h2><span class="section-number-2">4.</span> What makes suggestion special&nbsp;&nbsp;&nbsp;<span class="tag"><span class="hci">hci</span>&nbsp;<span class="cognition">cognition</span></span></h2>
<div class="outline-text-2">
<p>
The <a href="https://www.chiply.dev/post-icr-primer#recognition--recall--and-the-third-option">primer</a> praised ICR for its <i>cued recall</i>, an alleviation of the burden on recall, with a small tax on recognition. With ICR, you supply a fragment (almost an 'intuition' considering <a href="https://github.com/oantolin/orderless">Orderless</a>'s flexible matching capabilities), then pay the incredibly cheap cognitive cost of recognizing your target from a winnowed candidate set.  
</p>

<p>
ISR moves further from recall, and opens the door to speculation.  In semantic retrieval you supply only a gesture at <i>meaning</i>, and in generative synthesis you supply a <i>question</i>.  In this way, I think about the goal of ISR as exploration and discovery, and the goal of ICR as arriving at a destination. 
</p>

<p>
In my opinion, ISR's real value props are 1) reaching candidates that literal matching can't (semantic retreival), and 2) providing detailed answers to open questions and possible expansions (generative synthesis).
</p>
</div>
</div>
<div class="outline-2">
<h2><span class="section-number-2">5.</span> Notes on the demo</h2>
<div class="outline-text-2">
<p>
The demos from the companion video, and where their code lives in my <a href="https://github.com/chiply/.zetta.d">Emacs config</a>:
</p>

<ul>
<li><i>Semantic retrieval</i> (match candidates by meaning)
<ul>
<li>John Kitchin's <a href="https://www.youtube.com/watch?v=bB7rywlahSc">semantic completing read</a> (linked above); my own implementation, <code>chiply-isr-semantic-read</code>, lives in <a href="https://github.com/chiply/.zetta.d/blob/main/modules/completion/chiply-isr.el"><code>chiply-isr.el</code></a>.</li>
</ul></li>
<li><i>Generative synthesis</i> (generated output from LLMs)
<ul>
<li>Multiple prompt responses with gptel + consult-omni: <a href="https://github.com/chiply/.zetta.d/blob/main/modules/completion/consult-omni.el"><code>consult-omni.el</code></a></li>
<li>Multiple inline code-expansion suggestions with Copilot: <a href="https://github.com/chiply/.zetta.d/blob/main/modules/completion/copilot-isr.el"><code>copilot-isr.el</code></a></li>
</ul></li>
</ul>
</div>
</div></body></html>]]></content>
        <author>
            <name>Charlie Holland</name>
            <uri>https://www.chiply.dev</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Raymond Zeitler: Change Emacs Cursor to Indicate Overwrite Mode]]></title>
        <id>https://ray-on-emacs.blogspot.com/2026/06/change-emacs-cursor-to-indicate.html</id>
        <link href="https://ray-on-emacs.blogspot.com/2026/06/change-emacs-cursor-to-indicate.html"/>
        <updated>2026-06-02T23:00:38.304Z</updated>
        <content type="html"><![CDATA[<html><head></head><body><p>The text editor I'd used for 20 years on an MS-DOS platform would
change the shape of the cursor to distinguish between insert mode and
overwrite mode. A filled rectangle (or box, in Emacs terms) indicated
overwrite mode; an underscore (hbar), insert mode.  It's a nice way to
make overwrite mode obvious.</p>

<p>The video starts out with Emacs in Insert Mode.  Then Overwrite
Mode is activated, which changes cursor-type from hbar to box.  The
word "Overwrite" replaces "Insert" to demonstrate the effect.</p>

<div class="separator"></div>

<p>Incidentally, you might enjoy listening to some sound while playing
back the video.  One of my favorites is "<a href="https://mynoise.net/NoiseMachines/voiceInTheWoods.php">Forest
Voice</a>" from <a href="https://mynoise.net">https://mynoise.net</a>,
by <a href="https://stephanepigeon.com/">Dr. Stéphane Pigeon</a>.</p>

<p>Anyway, here's a function to implement that behavior in Emacs:</p>

<div class="org-src-container">
<pre>(<span>defun</span> <span>zeit-change-cursor-shape</span> ()
  <span>"Set cursor shape depending on overwrite mode.</span>
<span>When overwrite-mode is nil (off), set cursor-type to hbar.</span>
<span>Otherwise, set it to box."</span>
  (<span>interactive</span>)
  (<span>if</span> (not overwrite-mode)
      (<span>setq</span> cursor-type 'hbar)
    (<span>setq</span> cursor-type 'box)))

(add-hook 'overwrite-mode-hook 'zeit-change-cursor-shape)
</pre>
</div>
<hr><p>2026-06-02 Add add-hook&nbsp;&nbsp;as suggested by @Howitzer105mm@pdx.social</p>
<p>2026-06-02 Move hook outside function</p></body></html>]]></content>
        <author>
            <name>Raymond Zeitler</name>
            <uri>https://ray-on-emacs.blogspot.com/search/label/Emacs</uri>
        </author>
    </entry>
</feed>