<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" >

  <title>Erik L. Arneson — Writer and Software Developer</title>
  <subtitle>Erik L. Arneson is a freelance writer and software developer with WordPress experience. He is located in Portland, Oregon.</subtitle>
  <generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator>
  <link href="https://arnesonium.com/feeds/lisp.xml" rel="self" type="application/atom+xml" />
  <link href="https://arnesonium.com/" rel="alternate" type="text/html" />
  <updated>2026-06-18T15:03:10+00:00</updated>
  <id>https://arnesonium.com/feeds/lisp.xml</id>
  <author>
    <name>Erik L. Arneson</name>
  </author>
      <entry>
        
        <title>An Emacs Application Launcher for Regolith</title>
        <author>
          <name>Erik L. Arneson</name>
        </author>        
        <link href="https://arnesonium.com/2025/11/regolith-emacs-launcher" rel="alternate" type="text/html" title="An Emacs Application Launcher for Regolith" />
        <updated>2025-11-19T00:00:00+00:00</updated>
        <id>https://arnesonium.com/2025/11/regolith-emacs-launcher</id>
          <category term="emacs" />
        
          <category term="shell" />
        
          <category term="bash" />
        
          <category term="lisp" />
        
          <category term="programming" />
        
          <category term="ubuntu" />
        <content type="html" xml:base="https://arnesonium.com/2025/11/regolith-emacs-launcher">&lt;p&gt;I run the &lt;a href=&quot;https://regolith-desktop.com/&quot;&gt;Regolith Desktop Environment&lt;/a&gt; on my laptop, which I love because it provides a convenient GNOME wrapper and interface for the &lt;a href=&quot;https://i3wm.org/&quot;&gt;i3 tiling window manager&lt;/a&gt;. Regolith relies on a program called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ilia&lt;/code&gt; for application launching, and sometimes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ilia&lt;/code&gt; gets caught in some kind of CPU-churning state that locks up my whole system. I have not been able to figure out what is causing it, so I (of course) turned to Emacs for a solution.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;turning-to-consult-omni&quot;&gt;Turning to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;consult-omni&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;Armin Darvish has created a powerful Emacs package called &lt;a href=&quot;https://github.com/armindarvish/consult-omni&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;consult-omni&lt;/code&gt;&lt;/a&gt;, which provides a wrapper around &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;consult&lt;/code&gt; for searching through any number of information sources. I believe &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;consult-omni&lt;/code&gt; was originally intended to query web search engines and document databases, but Darvish has also provided a search mode for your local desktop applications, and can act as an application launcher.&lt;/p&gt;

&lt;p&gt;Darvish provides an example application launcher in his &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;consult-omni&lt;/code&gt; YouTube tutorial. The source code is straightforward, but I wanted to tweak it just a little. You can view &lt;a href=&quot;https://github.com/armindarvish/consult-omni/wiki/YouTube-Tutorial#create-a-launcher&quot;&gt;his original on the project’s wiki on GitHub&lt;/a&gt;. You can watch him explain his technique below.&lt;/p&gt;

&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/wNH2E7iT__c?start=8595&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;After a few tweaks, here is what I came up with.&lt;/p&gt;

&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;consult-launcher&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;&quot;A launcher suitable for use from a window manager.&quot;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;interactive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;width&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;floor&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.6&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;display-pixel-width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;height&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;floor&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.6&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;display-pixel-height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;left&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;floor&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;display-pixel-width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;top&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;floor&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;display-pixel-height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;params&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;omni-launcher&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;width&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cons&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;text-pixels&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
                   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;height&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cons&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;text-pixels&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
                   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;left&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;top&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;top&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;minibuffer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;only&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;frame&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;make-frame&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;with-selected-frame&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;frame&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;select-frame-set-input-focus&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;;; If i3 is running and there is a control socket, let&apos;s tell&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;;; it we are a floating frame.&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;getenv&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;I3SOCK&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;call-process&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;i3-msg&quot;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt;
                        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;[id=%s] floating enable&quot;&lt;/span&gt;
                                &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s-trim&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;shell-command-to-string&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;xdotool getactivewindow&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;unwind-protect&lt;/span&gt;
          &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;progn&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;consult-omni-apps-static&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;.*&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;propertize&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&amp;gt; &quot;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;face&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;consult-omni-path-face&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
                 &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;progn&lt;/span&gt;
          &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;when&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;frame-live-p&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;delete-frame&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
          &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I made two changes to get this to work nicely with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i3&lt;/code&gt;. First, I removed the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;yequake&lt;/code&gt; dependency. Second, I added a call to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i3-msg&lt;/code&gt; that sets the launcher frame as floating, which makes it much nicer to use. Like Darvish’s version, you can run this from the command line:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;emacsclient -e &apos;(consult-launcher)&apos;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;adding-an-ilia-fallback&quot;&gt;Adding an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ilia&lt;/code&gt; fallback&lt;/h2&gt;

&lt;p&gt;Don’t tell all the other Emacs users, but I don’t have Emacs set up to launch automatically when I start my computer and log into X11. I probably should, huh? Also, there are times when I (gasp!) shut down Emacs, usually to restart it or fix something that I have broken. When those times happen, I want to be able to launch applications, so I need a failsafe in case &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;consult-launcher&lt;/code&gt; isn’t available!&lt;/p&gt;

&lt;p&gt;To solve this, I created a simple shell wrapper script, which looks like this:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Check if Emacs server is running by looking for the server socket&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Default server name is &quot;server&quot;, but you can change this if needed&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;SERVER_NAME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;EMACS_SERVER_NAME&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:-&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;SERVER_FILE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;XDG_RUNTIME_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:-&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;/tmp&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/emacs/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SERVER_NAME&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$SERVER_FILE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# Emacs is running, use emacsclient to launch your application&lt;/span&gt;
    emacsclient &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;(consult-launcher)&apos;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# Emacs is not running, fall back to ilia&lt;/span&gt;
    ilia &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; apps
&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you want to use this, the important part is that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SERVER_FILE&lt;/code&gt; points to the socket that your Emacs server uses. Make sure that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;emacsclient&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ilia&lt;/code&gt; are both in a reasonable location so your shell can find them, then bind this command to whatever you usually use to launch &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ilia&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;By the way, if you are using Regolith’s normal method of launching &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ilia&lt;/code&gt;, you can add your shell script to your Regolith configuration pretty easily. Open &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$HOME/.config/regolith3/Xresources&lt;/code&gt; in your text editor, and add the line:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;wm.program.launcher.app: /path/to/your/launcher.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can then run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xrdb -override $HOME/.config/regolith3/Xresources&lt;/code&gt; and it should work! Good luck.&lt;/p&gt;

&lt;h2 id=&quot;drawbacks&quot;&gt;Drawbacks&lt;/h2&gt;

&lt;p&gt;One of the nice things about &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ilia&lt;/code&gt; is that it keeps track of applications your run frequently, so they tend to bubble up to the top of its application listing. The Emacs method doesn’t do that. I don’t mind so much, I always end up typing in application names. It is fun to use Emacs as an application launcher, and I hope that it helps me avoid the CPU-churn problem that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ilia&lt;/code&gt; has been experiencing far too often.&lt;/p&gt;

&lt;p&gt;Have I come up with a clever solution, or a lazy workaround? I’m looking forward to hearing your thoughts.&lt;/p&gt;</content>
      </entry>
    
      <entry>
        
        <title>Interviewed on &quot;Prot Speaks&quot;</title>
        <author>
          <name>Erik L. Arneson</name>
        </author>        
        <link href="https://arnesonium.com/2025/08/interviewed-on-prot-speaks" rel="alternate" type="text/html" title="Interviewed on "Prot Speaks"" />
        <updated>2025-08-18T00:00:00+00:00</updated>
        <id>https://arnesonium.com/2025/08/prot-speaks-interview</id>
          <category term="emacs" />
        
          <category term="podcast" />
        
          <category term="programming" />
        
          <category term="org-mode" />
        
          <category term="lisp" />
        
          <category term="golang" />
        
          <category term="portland" />
        <content type="html" xml:base="https://arnesonium.com/2025/08/interviewed-on-prot-speaks">&lt;p&gt;Well-known Emacs package creator Protesilaos Stavrou interviewed me for his video podcast series, “Prot Asks.” We talked about a wide variety of topics, from Emacs to podcasting to Portland to public transit. I thought it was a great time, and perhaps you will like it, too!&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;You can read and view the video &lt;a href=&quot;https://protesilaos.com/codelog/2025-08-17-prot-asks-erik-emacs-1990s-portland-oregon-podcasting/&quot;&gt;on Prot’s website and blog&lt;/a&gt;, or you can go &lt;a href=&quot;https://www.youtube.com/watch?v=6wkfFdiwpyU&quot;&gt;straight to YouTube&lt;/a&gt;, or you can watch it embedded here below.&lt;/p&gt;

&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube-nocookie.com/embed/6wkfFdiwpyU?si=ocNz3f6ehqEYYC2G&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;Note that Prot is looking for people to talk to on this series! You can join in by &lt;a href=&quot;https://protesilaos.com/prot-asks/&quot;&gt;signing up on his website&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;P.S. In the video, I promised that I would do another Emacs Carnival blog post, and I will, I swear! It is in my org-mode to-do file.&lt;/p&gt;</content>
      </entry>
    
      <entry>
        
        <title>Configuring Emacs 29.1 for Go Development</title>
        <author>
          <name>Erik L. Arneson</name>
        </author>        
        <link href="https://arnesonium.com/2023/08/configuring-emacs-29-1-for-golang" rel="alternate" type="text/html" title="Configuring Emacs 29.1 for Go Development" />
        <updated>2023-08-01T00:00:00+00:00</updated>
        <id>https://arnesonium.com/2023/08/golang-emacs</id>
          <category term="emacs" />
        
          <category term="programming" />
        
          <category term="golang" />
        
          <category term="lisp" />
        
          <category term="emacs-lisp" />
        <content type="html" xml:base="https://arnesonium.com/2023/08/configuring-emacs-29-1-for-golang">&lt;p&gt;Now that I have &lt;a href=&quot;https://arnesonium.com/2023/07/emacs-29-1-on-ubuntu-22-04-lts&quot;&gt;installed Emacs 29.1&lt;/a&gt;, I needed to get it set up for Go development for a project. I was interested in taking advantage of both the new Tree-Sitter integration, and the new Eglot language server client. However, they were mildly tricky to set up! Here is what I did.
&lt;!--more--&gt;&lt;/p&gt;

&lt;h2 id=&quot;configuring-tree-sitter-for-go&quot;&gt;Configuring Tree-Sitter for Go&lt;/h2&gt;

&lt;p&gt;If you follow the excellent &lt;a href=&quot;https://www.masteringemacs.org/article/how-to-get-started-tree-sitter&quot;&gt;How to Get Started with Tree-Sitter&lt;/a&gt; instructions from Mickey Peterson, you will have a great head-start on getting Tree-Sitter working for most of your favorite languages (and probably Java, too). However, those instructions didn’t cover everything I needed for Go. When I tried running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-x go-ts-mode&lt;/code&gt;, Emacs complained about a missing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gomod&lt;/code&gt; module. Baffling!&lt;/p&gt;

&lt;p&gt;I couldn’t find any information in the Emacs documentation about where to find this missing module. I looked around on the net and found &lt;a href=&quot;https://github.com/camdencheek/tree-sitter-go-mod&quot;&gt;Camden Cheek’s tree-sitter-go-mod&lt;/a&gt;, and added that to my list of recipes. My &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;treesit-language-source-alist&lt;/code&gt; then looked like this:&lt;/p&gt;

&lt;div class=&quot;language-elisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;treesit-language-source-alist&lt;/span&gt;
 &lt;span class=&quot;o&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;bash&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://github.com/tree-sitter/tree-sitter-bash&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cmake&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://github.com/uyha/tree-sitter-cmake&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;css&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://github.com/tree-sitter/tree-sitter-css&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;elisp&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://github.com/Wilfred/tree-sitter-elisp&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;go&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://github.com/tree-sitter/tree-sitter-go&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;gomod&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://github.com/camdencheek/tree-sitter-go-mod&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dockerfile&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://github.com/camdencheek/tree-sitter-dockerfile&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;html&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://github.com/tree-sitter/tree-sitter-html&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;javascript&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://github.com/tree-sitter/tree-sitter-javascript&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;master&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;src&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;json&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://github.com/tree-sitter/tree-sitter-json&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;make&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://github.com/alemuller/tree-sitter-make&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;markdown&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://github.com/ikatyang/tree-sitter-markdown&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;python&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://github.com/tree-sitter/tree-sitter-python&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;toml&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://github.com/tree-sitter/tree-sitter-toml&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tsx&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://github.com/tree-sitter/tree-sitter-typescript&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;master&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;tsx/src&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;typescript&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://github.com/tree-sitter/tree-sitter-typescript&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;master&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;typescript/src&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;yaml&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://github.com/ikatyang/tree-sitter-yaml&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note that the package is named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;go-mod&lt;/code&gt; but &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;go-ts-mode&lt;/code&gt; expects it to be named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gomod&lt;/code&gt;. I wish this were documented somewhere! In any case, I was then able to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-x treesit-install-language-grammar&lt;/code&gt; for both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;go&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gomod&lt;/code&gt;. Finally, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-x go-ts-mode&lt;/code&gt; worked!&lt;/p&gt;

&lt;p&gt;After going through this process, I found &lt;a href=&quot;https://robbmann.io/posts/emacs-treesit-auto/&quot;&gt;Robert Enzmann’s post about automatically using Tree-Sitter&lt;/a&gt;. He has created the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;treesit-auto&lt;/code&gt; package, now available on MELPA, that does most of this work for you. It is a much faster way of solving the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gomod&lt;/code&gt; mystery, so give it a shot!&lt;/p&gt;

&lt;h2 id=&quot;configuring-eglot-for-go&quot;&gt;Configuring Eglot for Go&lt;/h2&gt;

&lt;p&gt;I’d been using &lt;a href=&quot;https://github.com/emacs-lsp/lsp-mode&quot;&gt;lsp-mode&lt;/a&gt; for ages, but with Emacs 29.1 including &lt;a href=&quot;https://joaotavora.github.io/eglot/&quot;&gt;Eglot&lt;/a&gt;, I decided to make the switch.&lt;/p&gt;

&lt;p&gt;In my Go project, I ran &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-x eglot&lt;/code&gt; and was immediately met with an error:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[eglot] Server reports (type=1): Error loading workspace folders (expected 1, got 0)
failed to load view for file:///path/to/my/project: err: go command required, not found: exec: &quot;go&quot;: executable file not found in $PATH: stderr: 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I’ve got Go installed in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/local/go&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/local/go/bin&lt;/code&gt; is definitely in my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exec-path&lt;/code&gt; variable in Emacs. It looked like Eglot wasn’t propagating &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exec-path&lt;/code&gt; down to its subprocesses. How annoying! I did a quick search through the list of Eglot-related variables and the Eglot documentation and no solution seemed immediately forthcoming.&lt;/p&gt;

&lt;p&gt;So I took the cheap way out and made a symlink. In my shell, I ran:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo ln&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-sf&lt;/span&gt; /usr/local/go/bin/go /usr/local/bin/go
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It is a dumb trick, and I am sure there is a better way to solve it. Do you know of one? Please comment and let me know!&lt;/p&gt;

&lt;h2 id=&quot;what-else&quot;&gt;What Else?&lt;/h2&gt;

&lt;p&gt;My exploration has revealed that there’s a lot of work left to do in the Emacs Tree-Sitter world. There are plenty of languages major modes that don’t yet have a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ts-mode&lt;/code&gt; equivalent, and plenty of others that still need a lot of work.&lt;/p&gt;

&lt;p&gt;It’s too soon for me to say if this setup is preferrable to my previous configuration. But I am really looking forward to playing around with Eglot’s features and exploring the capabilities of Tree-Sitter.&lt;/p&gt;</content>
      </entry>
    
      <entry>
        
        <title>Pattern Matching and Tail Recursion in Emacs Lisp</title>
        <author>
          <name>Erik L. Arneson</name>
        </author>        
        <link href="https://arnesonium.com/2022/11/pattern-matching-tail-recursion-emacs-lisp" rel="alternate" type="text/html" title="Pattern Matching and Tail Recursion in Emacs Lisp" />
        <updated>2022-11-19T00:00:00+00:00</updated>
        <id>https://arnesonium.com/2022/11/tco-pattern-emacs-lisp</id>
          <category term="emacs" />
        
          <category term="programming" />
        
          <category term="emacs-lisp" />
        
          <category term="lisp" />
        <content type="html" xml:base="https://arnesonium.com/2022/11/pattern-matching-tail-recursion-emacs-lisp">&lt;p&gt;Functional programming offers a bunch of really cool programming patterns. Two that I really enjoy are &lt;a href=&quot;https://stackoverflow.com/questions/310974/what-is-tail-call-optimization&quot;&gt;tail recursion&lt;/a&gt; and &lt;a href=&quot;https://sodocumentation.net/ocaml/topic/2656/pattern-matching&quot;&gt;pattern matching&lt;/a&gt;, especially how they are implemented in OCaml. However, I spend a lot of time writing Emacs Lisp now, and I was wondering if I could find a way to use these patterns in that language.
&lt;!--more--&gt;&lt;/p&gt;

&lt;p&gt;It turns out that it is possible, thanks to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;named-let&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pcase&lt;/code&gt;. It isn’t as pretty and elegant as OCaml, but at least I get to keep excercising those parts of my programming brain. Maybe next I’ll try to figure out currying in Emacs Lisp.&lt;/p&gt;

&lt;p&gt;Note that this blog post includes some &lt;em&gt;really dumb&lt;/em&gt; examples, because that’s usually how I learn these things best.&lt;/p&gt;

&lt;h2 id=&quot;pattern-matching-with-pcase&quot;&gt;Pattern Matching with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pcase&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;Most programmers will be familiar with the granddaddy of pattern matching, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;switch/case&lt;/code&gt; construct. This is present in many, many programming languages, especially those in the ALGOL family.&lt;/p&gt;

&lt;p&gt;However, pattern matching can be so much more! Instead of simple equality checks, pattern matching extends the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;switch/case&lt;/code&gt; concept to include testing for all kinds of patterns and conditionals.&lt;/p&gt;

&lt;p&gt;Lisp programmers will already be familiar with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cond&lt;/code&gt;, which can be used to sequentially test for conditionals. However, functional language programmers have probably fallen in love with a more mature and sophisticated form of pattern matching that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cond&lt;/code&gt; doesn’t totally satisfy.&lt;/p&gt;

&lt;p&gt;Fortunately, Emacs Lisp has &lt;a href=&quot;https://www.gnu.org/software/emacs/manual/html_node/elisp/Pattern_002dMatching-Conditional.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pcase&lt;/code&gt;, the pattern-matching conditional&lt;/a&gt;. Here is an example of its use to duplicate &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;car&lt;/code&gt;, which is the dumbest possible example I could think of.&lt;/p&gt;

&lt;div class=&quot;language-elisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ela/car&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;lst&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pcase&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;lst&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;nv&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;
     &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can see that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pcase&lt;/code&gt; has a backquote syntax for matching various constructs, such as with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;`(,head . ,_)&lt;/code&gt; piece. This matches a cons cell and binds the CAR to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;head&lt;/code&gt; while ignoring the CDR.&lt;/p&gt;

&lt;p&gt;The next case is just &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_&lt;/code&gt;, which is a catch-all matching operator.&lt;/p&gt;

&lt;p&gt;In the real world, you’d probably want some type checking and error correction, but I promised very simple examples. Check out the full range of &lt;a href=&quot;https://www.gnu.org/software/emacs/manual/html_node/elisp/pcase-Macro.html&quot;&gt;matching capabilities for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pcase&lt;/code&gt;&lt;/a&gt;, and then &lt;a href=&quot;https://www.gnu.org/software/emacs/manual/html_node/elisp/Backquote-Patterns.html&quot;&gt;read about all of the backquote patterns you can also use&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;tail-call-optimization-with-named-let&quot;&gt;Tail Call Optimization with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;named-let&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;Tail call optimization (TCO) is the programming language feature that allows efficient tail recursion without overflowing your stack. It is increasingly common in languages today, though from what I’ve seen, it always involves caveats.&lt;/p&gt;

&lt;p&gt;In Emacs Lisp, the easiest way to use TCO that I’ve come across is the &lt;a href=&quot;https://www.gnu.org/software/emacs/manual/html_node/elisp/Local-Variables.html#index-named_002dlet&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;named-let&lt;/code&gt; macro&lt;/a&gt;. With it, you define a function that can get “unrolled” inside another function. For example, here is a simple function that calculates a factorial using tail recursion.&lt;/p&gt;

&lt;div class=&quot;language-elisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ela/fact&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;in-num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;named-let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;rec-fact&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;accu&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                       &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;in-num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pcase&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;num&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;guard&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
       &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;rec-fact&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;accu&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;
       &lt;span class=&quot;nv&quot;&gt;accu&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In this example, you will notice that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rec-fact&lt;/code&gt; is the locally named function that gets called at the end of the first &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pcase&lt;/code&gt; pattern. This is a tail call! It will get optimized.&lt;/p&gt;

&lt;p&gt;You can check this out by running something like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(ela/fact 5)&lt;/code&gt; and getting 120 as the result. Try using a ridiculously big number and see if you get a stack overflow! You shouldn’t.&lt;/p&gt;

&lt;h2 id=&quot;another-example-summing-a-list&quot;&gt;Another Example: Summing a List&lt;/h2&gt;

&lt;p&gt;This is just a nostalgic example, since it’s probably the first tail recursive pattern matching function I ever wrote when learning OCaml a zillion years ago. This function will take a list of numbers and then add them all together. There are much better ways to write this in Emacs Lisp, like with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apply&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-elisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ela/sum&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;numbers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;named-let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;sum-list&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;accu&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                       &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;lst&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;numbers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pcase&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;lst&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;sum-list&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;accu&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;tail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;
       &lt;span class=&quot;nv&quot;&gt;accu&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can then call it like this:&lt;/p&gt;

&lt;div class=&quot;language-elisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ela/sum&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And you will end up with exactly the result you expect. I was amused to see that the documentation page for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;named-let&lt;/code&gt; has a different implementation of this function that doesn’t use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pcase&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Oh heck, let’s get fancy and rewrite &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apply&lt;/code&gt; using this approach.&lt;/p&gt;

&lt;div class=&quot;language-elisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ela/apply&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&amp;amp;rest&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;arguments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;&quot;Apply FN to each element of ARGUMENTS and return the accumulated result.&quot;&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;;; Set up accumulator to the right type.&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;arguments-flat&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;flatten-list&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;arguments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;initial-value&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pcase&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;car&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;arguments-flat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                          &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pred&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;integerp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                          &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pred&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;stringp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                          &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;named-let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;apply-rec&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;accumulator&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;initial-value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                          &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;input-list&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;arguments-flat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pcase&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;input-list&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;apply-rec&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;funcall&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;accumulator&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;tail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;
         &lt;span class=&quot;nv&quot;&gt;accumulator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I am certain this version of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apply&lt;/code&gt; has bugs, but it works for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;concat&lt;/code&gt;, so that’s good enough for a simple example. And it uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pcase&lt;/code&gt; twice!&lt;/p&gt;

&lt;p&gt;Hopefully this has been a useful blog post for somebody out there. Let me know in the comments if there are other fun things you have done with TCO and pattern matching in Emacs Lisp!&lt;/p&gt;</content>
      </entry>
    
      <entry>
        
        <title>New MELPA Package: ddate</title>
        <author>
          <name>Erik L. Arneson</name>
        </author>        
        <link href="https://arnesonium.com/2022/11/new-melpa-package-ddate" rel="alternate" type="text/html" title="New MELPA Package: ddate" />
        <updated>2022-11-01T00:00:00+00:00</updated>
        <id>https://arnesonium.com/2022/11/ddate-on-melpa</id>
          <category term="emacs" />
        
          <category term="discordian" />
        
          <category term="melpa" />
        
          <category term="lisp" />
        <content type="html" xml:base="https://arnesonium.com/2022/11/new-melpa-package-ddate">&lt;p&gt;I recently wrote an Emacs Lisp package to support the &lt;a href=&quot;https://github.com/bo0ts/ddate&quot;&gt;ddate&lt;/a&gt; command, a classic
command-line utility to display dates from the &lt;a href=&quot;https://en.wikipedia.org/wiki/Discordian_calendar&quot;&gt;Discordian calendar&lt;/a&gt;.
&lt;!--more--&gt;&lt;/p&gt;

&lt;p&gt;The package is now &lt;a href=&quot;https://melpa.org/#/ddate&quot;&gt;available on MELPA&lt;/a&gt;! That means that if you have &lt;a href=&quot;https://ianyepan.github.io/posts/setting-up-use-package/&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;use-package&lt;/code&gt;
installed&lt;/a&gt;, you can get &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ddate&lt;/code&gt; easily like this:&lt;/p&gt;

&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;use-package&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ddate&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:ensure&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Once you have the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ddate&lt;/code&gt; package installed, you can use it to add the Discordian date to your &lt;a href=&quot;https://github.com/emacs-dashboard/emacs-dashboard&quot;&gt;dashboard&lt;/a&gt; with code like
this:&lt;/p&gt;

&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ela/dashboard-insert-ddate&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;list-size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;&quot;Insert the Discordian date into the dashboard.&quot;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ddate-string&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ddate-pretty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dashboard-center-line&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ddate-string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;insert&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ddate-string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;use-package&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;dashboard&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;:init&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dashboard-setup-startup-hook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;:config&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;;; Add the ddate item provider to the list.&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-to-list&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;dashboard-item-generators&lt;/span&gt;
               &lt;span class=&quot;o&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ddate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ela/dashboard-insert-ddate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;;; Set up your items with ddate at the top.&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;dashboard-items&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ddate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                          &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;recents&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                          &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;bookmarks&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                          &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;registers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can view the &lt;a href=&quot;https://git.sr.ht/~earneson/emacs-ddate&quot;&gt;source code for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ddate&lt;/code&gt; on Sourcehut&lt;/a&gt;.&lt;/p&gt;</content>
      </entry>
    
      <entry>
        
        <title>Yasnippet and Emacs for Writing</title>
        <author>
          <name>Erik L. Arneson</name>
        </author>        
        <link href="https://arnesonium.com/2022/09/yasnippet-emacs-writing" rel="alternate" type="text/html" title="Yasnippet and Emacs for Writing" />
        <updated>2022-09-28T00:00:00+00:00</updated>
        <id>https://arnesonium.com/2022/09/yasnippet-emacs-writing</id>
          <category term="emacs" />
        
          <category term="writing" />
        
          <category term="lisp" />
        
          <category term="org-mode" />
        
          <category term="markdown" />
        
          <category term="podcast" />
        <content type="html" xml:base="https://arnesonium.com/2022/09/yasnippet-emacs-writing">&lt;p&gt;As a &lt;a href=&quot;/writing/&quot;&gt;freelance writer&lt;/a&gt;, I need to be ready to deliver high quality copy in a timely fashion. My editor of choice for writing is
Emacs. I have found that &lt;a href=&quot;https://github.com/joaotavora/yasnippet&quot;&gt;Yasnippet&lt;/a&gt; templates have streamlined my writing process.
&lt;!--more--&gt;&lt;/p&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#what-is-yasnippet&quot; id=&quot;markdown-toc-what-is-yasnippet&quot;&gt;What is Yasnippet?&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#installing-yasnippet&quot; id=&quot;markdown-toc-installing-yasnippet&quot;&gt;Installing Yasnippet&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#markdown-and-jekyll&quot; id=&quot;markdown-toc-markdown-and-jekyll&quot;&gt;Markdown and Jekyll&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#bonus-snippets&quot; id=&quot;markdown-toc-bonus-snippets&quot;&gt;Bonus Snippets&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#org-mode-templates&quot; id=&quot;markdown-toc-org-mode-templates&quot;&gt;Org Mode Templates&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#org2blog-and-podcast-show-notes&quot; id=&quot;markdown-toc-org2blog-and-podcast-show-notes&quot;&gt;org2blog and Podcast Show Notes&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#more-bonus-snippets&quot; id=&quot;markdown-toc-more-bonus-snippets&quot;&gt;More Bonus Snippets&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#writing-faster-is-writing-smarter&quot; id=&quot;markdown-toc-writing-faster-is-writing-smarter&quot;&gt;Writing Faster is Writing Smarter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;what-is-yasnippet&quot;&gt;What is Yasnippet?&lt;/h2&gt;

&lt;p&gt;As a templating system for Emacs, Yasnippet is well known by programmers. It can quickly expand
function definitions, control structures, and other templates into blocks of source code. Source code is just text.&lt;/p&gt;

&lt;p&gt;Since most of my writing originates in text format, templates are great for speeding up document
creation and avoiding common errors and omissions.&lt;/p&gt;

&lt;h2 id=&quot;installing-yasnippet&quot;&gt;Installing Yasnippet&lt;/h2&gt;

&lt;p&gt;With &lt;a href=&quot;https://github.com/jwiegley/use-package&quot;&gt;use-package&lt;/a&gt;, you can get started quickly with Yasnippet by including the following in your
Emacs init file.&lt;/p&gt;

&lt;div class=&quot;language-elisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;use-package&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;yasnippet&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;:ensure&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;t&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;:config&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;yas-global-mode&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;use-package&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;yasnippet-snippets&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;:ensure&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;t&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;:after&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;yasnippet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For more detailed installation instructions, &lt;a href=&quot;https://joaotavora.github.io/yasnippet/&quot;&gt;check the Yasnippet documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;markdown-and-jekyll&quot;&gt;Markdown and Jekyll&lt;/h2&gt;

&lt;p&gt;This blog is primarily written in Markdown for Jekyll, which means that each file needs a YAML block at the top with specific
information. I have a template that looks like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# -*- mode: snippet -*-
# name: blogtop
# key: blogtop
# --
---
title: ${1:Title}
author: &quot;Erik L. Arneson&quot;
layout: post
permalink: `(format-time-string &quot;/%Y/%m/&quot;)`$2
comments: ${3:$$(yas-choose-value &apos;(&quot;true&quot; &quot;false&quot;))}
tags:
    - $4
---

$0
&amp;lt;!--more--&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Not only does this template save me from needing to remember the format of the YAML block, but it ensures that frequently forgetten items
are included, such as the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;permalink&lt;/code&gt; setting and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;!--more--&amp;gt;&lt;/code&gt; tag.&lt;/p&gt;

&lt;h3 id=&quot;bonus-snippets&quot;&gt;Bonus Snippets&lt;/h3&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/AndreaCrotti/yasnippet-snippets&quot;&gt;official snippet collection&lt;/a&gt; contains a bunch of extra Markdown templates. 
&lt;a href=&quot;https://github.com/AndreaCrotti/yasnippet-snippets/tree/master/snippets/markdown-mode&quot;&gt;Check them out here.&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;org-mode-templates&quot;&gt;Org Mode Templates&lt;/h2&gt;

&lt;p&gt;My &lt;a href=&quot;https://orgmode.org/&quot;&gt;Org Mode&lt;/a&gt; files are more complex. Many writing clients expect deliveries in Microsoft Word files, but
I also frequently find myself needing to produce OpenDocument files, HTML, and even Markdown. The headers for these files need to support
all of these options.&lt;/p&gt;

&lt;p&gt;I use the following template to support all of the Org Mode configuration and options I require.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# -*- mode: snippet -*-
# name: header
# key: header
# --
#+TITLE: $1
#+LANGUAGE: ${2:en}
#+AUTHOR: ${3:$$(yas/choose-value &apos;(&quot;Erik L. Arneson&quot; &quot;Some Other Name&quot;))}
#+EMAIL: ${4:$$(yas/choose-value &apos;(&quot;list-of-email-addresses&quot;))}${5:
#+DESCRIPTION: $6}${7:
#+KEYWORDS: $8}
#+OPTIONS: num:nil toc:nil
#+ODT_STYLES_FILE: ${9:$$(yas/choose-value &apos;(&quot;list-of-template-files&quot;))}
#+bibliography: /path/to/MyLibrary.bib
#+cite_export: csl ${10:$$(yas/choose-value &apos;(&quot;chicago-fullnote-bibliography.csl&quot; &quot;modern-language-association.csl&quot; &quot;apa.csl&quot;))}
#+WWG: ${11:$$(yas/choose-value &apos;(&quot;0&quot; &quot;250&quot; &quot;500&quot; &quot;1000&quot;))}

$0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;org2blog-and-podcast-show-notes&quot;&gt;org2blog and Podcast Show Notes&lt;/h3&gt;

&lt;p&gt;I also use Org Mode to publish to WordPress websites using &lt;a href=&quot;https://github.com/org2blog/org2blog&quot;&gt;org2blog&lt;/a&gt;. For one of these websites, I
write show notes for podcast episodes. I use a template that looks like this.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# -*- mode: snippet -*-
# name: podcast
# key: podcast
# --
* $1
  :PROPERTIES:
  :POST_TAGS: $2
  :BLOG:      arnemancy
  :CATEGORY:  Podcast
  :POST_DATE: `(format-time-string &quot;[%Y-%m-%d %a %H:%M]&quot; nil nil)`
  :END:

$0

** Links

** Credits

#+begin_export html
Support me on Patreon: &amp;lt;a rel=&quot;payment&quot; href=&quot;https://www.patreon.com/arnemancy&quot;&amp;gt;https://www.patreon.com/arnemancy&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;
#+end_export
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This template reminds me of important items I need to include in all show notes, like links, credits, and a Patreon link.&lt;/p&gt;

&lt;h3 id=&quot;more-bonus-snippets&quot;&gt;More Bonus Snippets&lt;/h3&gt;

&lt;p&gt;The official snippet collection also contains a bunch of Org Mode snippets. &lt;a href=&quot;https://github.com/AndreaCrotti/yasnippet-snippets/tree/master/snippets/org-mode&quot;&gt;Here is the whole
list.&lt;/a&gt; Since Org Mode contains so many complicated
structures like source blocks and optional keywords, these are great time savers. There are also snippets for supporting
&lt;a href=&quot;https://github.com/yjwen/org-reveal&quot;&gt;org-reveal&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;writing-faster-is-writing-smarter&quot;&gt;Writing Faster is Writing Smarter&lt;/h2&gt;

&lt;p&gt;Don’t let your tools get in the way of your writing. Frequently, Emacs is portrayed as cumbersome and filled with obscure keybindings and
weird commands. However, I have found that it is an excellent tool for writing. Yasnippet templates let me get started on new documents
quickly without fretting over different syntaxes for configuration.&lt;/p&gt;

&lt;p&gt;And Yasnippet is just one of the tools I use when writing with Emacs. I will discuss more of these tools in the future.&lt;/p&gt;</content>
      </entry>
    
      <entry>
        
        <title>Typing Chinuk Wawa in Emacs</title>
        <author>
          <name>Erik L. Arneson</name>
        </author>        
        <link href="https://arnesonium.com/2021/10/typing-chinuk-wawa-in-emacs/" rel="alternate" type="text/html" title="Typing Chinuk Wawa in Emacs" />
        <updated>2021-10-11T17:01:00+00:00</updated>
        <id>https://arnesonium.com/2021/10/typing-chinuk-wawa-in-emacs</id>
          <category term="chinuk-wawa" />
        
          <category term="emacs" />
        
          <category term="input-methods" />
        
          <category term="keyboard" />
        
          <category term="languages" />
        
          <category term="learning" />
        
          <category term="linux" />
        
          <category term="lisp" />
        
          <category term="emacs" />
        
          <category term="dvorak" />
        <content type="html" xml:base="https://arnesonium.com/2021/10/typing-chinuk-wawa-in-emacs/">&lt;p&gt;Back in 2015, I took a course in being an ally for local Native American communities from the
&lt;a href=&quot;https://www.pugspdx.com/&quot;&gt;Portland Underground Grad School (PUGS)&lt;/a&gt;. One suggested action was
learning the local language, but it proved difficult to find opportunities. When the pandemic forced
school closures, though, Lane Community College began offering classes online. I found out about
this thanks to the &lt;a href=&quot;https://kaltashwawa.ca/2021/09/07/non-credit-enrollment-is-open-for-chinuk-wawa-classes-at-lane-community-college/&quot;&gt;Kaltash Wawa blog&lt;/a&gt;, and this fall I signed up to take a remote &lt;a href=&quot;https://www.lanecc.edu/llc/language/chinuk-wawa&quot;&gt;Chinuk
Wawa class through Lane Community College&lt;/a&gt;.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;what-is-chinuk-wawa&quot;&gt;What is Chinuk Wawa?&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Chinook_Jargon&quot;&gt;Chinuk Wawa&lt;/a&gt; originated as a type of creole or pidgin trade language in the Pacific Northwest,
incorporating loan words from more than a dozen indigenous and European languages. Though it has a
small lexicon, it is an interesting language with an impressive array of new phonemes for me to
learn. There are 12 different variations on “k”, for instance! As you can imagine, with this
variety, it is pretty difficult to type Chinuk Wawa using the standard Latin alphabet. I am learning
the &lt;a href=&quot;https://www.grandronde.org/services/education/chinuk-wawa-education-program/&quot;&gt;Grand Ronde dialect&lt;/a&gt;, which uses an IPA-based alphabet.&lt;/p&gt;

&lt;h2 id=&quot;keyman-for-linux&quot;&gt;Keyman for Linux&lt;/h2&gt;

&lt;p&gt;Under Linux, the easiest way to add an IPA-based input method is using the &lt;a href=&quot;https://keyman.com/keyboards/sil_ipa&quot;&gt;IPA (SIL) keyboard for
Keyman&lt;/a&gt;. This integrates nicely under GNOME 3 with Ubuntu 20.04. However, I’m a Dvorak typist,
so having to switch back to a QWERTY-style keyboard is frustrating, and was slowing me
down. Instead, I came up with this method for inputing Chinuk Wawa compatible IPA using Emacs.&lt;/p&gt;

&lt;h2 id=&quot;emacs-input-methods&quot;&gt;Emacs Input Methods&lt;/h2&gt;

&lt;p&gt;Emacs has an easy method for switching between input methods, which you can &lt;a href=&quot;https://www.gnu.org/software/emacs/manual/html_node/emacs/Select-Input-Method.html&quot;&gt;read more about
in the Emacs manual&lt;/a&gt;. It comes with a number of IPA input methods, and after taking a look at all
of them, I chose &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ipa-x-sampa&lt;/code&gt;, as it seemed to have the best coverage of symbols needed by
Chinuk Wawa. However, it was missing a way to input the character “x̣”, which was
needed by one of the first words I learned, “yax̣al”!&lt;/p&gt;

&lt;p&gt;I added the following code to my startup file to remedy this. This adds the ability to type &lt;strong&gt;x_.&lt;/strong&gt;
to get &lt;strong&gt;x̣&lt;/strong&gt; and &lt;strong&gt;?/&lt;/strong&gt; to get &lt;strong&gt;?&lt;/strong&gt;, both of which make typing Chinuk Wawa &lt;em&gt;much&lt;/em&gt; easier for me.&lt;/p&gt;

&lt;div class=&quot;language-elisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;chinuk-wawa-quail-rules&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;&quot;Add Chinuk Wawa rules to the `ipa-x-sampa` input map.&quot;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;interactive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;string-equal&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;ipa-x-sampa&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;quail-name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;quail-define-rules&lt;/span&gt;
       &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;append&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
       &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;_.&quot;&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#x0323&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;;; allows for x with dot beneath&lt;/span&gt;
       &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;?/&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;?&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;     &lt;span class=&quot;c1&quot;&gt;;; allows for ? character &lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-hook&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;quail-activate-hook&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;chinuk-wawa-quail-rules&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As you can see, this method allows plenty of additional characters to be added to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ipa-x-sampa&lt;/code&gt;,
so if it turns out I missed anything, I can expand on it later.&lt;/p&gt;

&lt;p&gt;The biggest downside of this is that I can only input Chinuk Wawa easily in Emacs, but since I do
most of my work there—including writing this blog post—it doesn’t feel that bad to me. It’s
definitely better than typing QWERTY!&lt;/p&gt;

&lt;p&gt;aɬqi!&lt;/p&gt;</content>
      </entry>
    
</feed>
