<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
 xmlns:content="http://purl.org/rss/1.0/modules/content/"
 xmlns:wfw="http://wellformedweb.org/CommentAPI/"
 xmlns:dc="http://purl.org/dc/elements/1.1/"
 xmlns:atom="http://www.w3.org/2005/Atom"
 xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
 xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
 xmlns:georss="http://www.georss.org/georss"
 xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"
 xmlns:media="http://search.yahoo.com/mrss/">
<channel>
<atom:link href="https://taingram.org/blog/blog-rss.xml" rel="self" type="application/rss+xml" />
<title>Thomas Ingram's Blog</title>
<link>https://taingram.org/</link>
<description><![CDATA[Blog posts on Emacs, GNU+Linux, etc.]]></description>
<language>en</language>
<lastBuildDate>Tue, 18 Nov 2025 13:15:28 -0500</lastBuildDate>
<generator>Emacs 30.1 org-publish-rss.el 0.8</generator>
<item>
<title>Building a Emacs Org-Mode Blog</title>
<link>https://taingram.org/blog/org-mode-blog.html</link>
<pubDate>Thu, 13 Jun 2019 00:00:00 -0400</pubDate>
<guid>https://taingram.org/blog/org-mode-blog.html</guid>
<description>
<![CDATA[<p>
As my WordPress website nears the end of its subscription, I've decided this
would be a perfect opportunity to build my own website using a pure <a href="https://gnu.org/s/emacs">Emacs</a> and
<a href="https://orgmode.org">Org mode</a> setup. While using WordPress I already composed my posts in Org mode
and published them using the <a href="https://github.com/org2blog/org2blog">org2blog</a> package. This works fine, but WordPress is
overkill as I don't the editor, themes, or plugins. A simpler solution would be
to utilize the HTML exporter built into Org mode. The result is a simple, fast
website, built entirely with Emacs.
</p>
<div id="outline-container-orgae27c34" class="outline-2">
<h2 id="orgae27c34"><span class="section-number-2">1.</span> Goals</h2>
<div class="outline-text-2" id="text-1">
<ol class="org-ol">
<li>A lightweight website with mobile scaling.</li>
<li>Easily rebuild my website and sync it to any web server.</li>
<li>Without adding any new software dependencies.</li>
</ol>
</div>
<div id="outline-container-org7f6a897" class="outline-3">
<h3 id="org7f6a897"><span class="section-number-3">1.1.</span> Tools</h3>
<div class="outline-text-3" id="text-1-1">
<table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">


<colgroup>
<col  class="org-left" />

<col  class="org-left" />
</colgroup>
<tbody>
<tr>
<td class="org-left"><b>Editor</b></td>
<td class="org-left">GNU Emacs</td>
</tr>

<tr>
<td class="org-left"><b>Markup Language</b></td>
<td class="org-left">Org mode</td>
</tr>

<tr>
<td class="org-left"><b>Site Generator</b></td>
<td class="org-left">Org mode ox-publish</td>
</tr>

<tr>
<td class="org-left"><b>Syncing</b></td>
<td class="org-left">tramp and ssh</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div id="outline-container-org98c159d" class="outline-2">
<h2 id="org98c159d"><span class="section-number-2">2.</span> Initial Setup</h2>
<div class="outline-text-2" id="text-2">
<p>
Out of the box Org mode provides many of different exporters for HTML, LaTeX,
even plain text. In addition to standard HTML exporting Org provides
<b>ox-publish</b> specifically for publishing Org projects as websites.
</p>

<p>
For my website, I use the following project structure:
</p>
<div class="org-src-container">
<pre class="src src-nil">~/taingram.org/
├── org/            # content to be exported
│   ├── blog/
│   │   └── example-post.org
│   ├── img/
│   ├── index.org
│   ├── robots.txt
│   └── style.css
├── html/            # temporary export directory
├── publish.el       # site sepecifc publishing config
└── Makefile         # for building the site outside of Emacs
</pre>
</div>

<p>
To explain this structure to Org publish we need to set the
<code>org-publish-project-alist</code> as follows
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp">(<span class="org-keyword">require</span> '<span class="org-constant">ox-publish</span>)

(<span class="org-keyword">setq</span> org-publish-project-alist
        `((<span class="org-string">"pages"</span>
           <span class="org-builtin">:base-directory</span> <span class="org-string">"~/taingram.org/org/"</span>
           <span class="org-builtin">:base-extension</span> <span class="org-string">"org"</span>
           <span class="org-builtin">:recursive</span> t
           <span class="org-builtin">:publishing-directory</span> <span class="org-string">"~/taingram.or/html/"</span>
           <span class="org-builtin">:publishing-function</span> org-html-publish-to-html)

          (<span class="org-string">"static"</span>
           <span class="org-builtin">:base-directory</span> <span class="org-string">"~/taingram.org/org/"</span>
           <span class="org-builtin">:base-extension</span> <span class="org-string">"css</span><span class="org-string"><span class="org-regexp-grouping-backslash">\\</span></span><span class="org-string"><span class="org-regexp-grouping-construct">|</span></span><span class="org-string">txt</span><span class="org-string"><span class="org-regexp-grouping-backslash">\\</span></span><span class="org-string"><span class="org-regexp-grouping-construct">|</span></span><span class="org-string">jpg</span><span class="org-string"><span class="org-regexp-grouping-backslash">\\</span></span><span class="org-string"><span class="org-regexp-grouping-construct">|</span></span><span class="org-string">gif</span><span class="org-string"><span class="org-regexp-grouping-backslash">\\</span></span><span class="org-string"><span class="org-regexp-grouping-construct">|</span></span><span class="org-string">png"</span>
           <span class="org-builtin">:recursive</span> t
           <span class="org-builtin">:publishing-directory</span>  <span class="org-string">"~/taingram.org/html/"</span>
           <span class="org-builtin">:publishing-function</span> org-publish-attachment)

          (<span class="org-string">"taingram.org"</span> <span class="org-builtin">:components</span> (<span class="org-string">"pages"</span> <span class="org-string">"static"</span>))))
</pre>
</div>

<p>
From the last line we can see "taingram.org" is broken down into the
components "pages" and "static". Each component handles a different part of
the website and has its own settings. The "pages" component handles org files
as specified by the <code>:base-extension</code> and exports the files to html as per the
<code>:publishing-function</code>. The "static" component handles copying over other
files like images and style sheets.
</p>

<p>
For each project component the following options should always be set:
</p>

<ul class="org-ul">
<li><code>:base-directory</code> &#x2014; where the source files are</li>
<li><code>:base-extension</code> &#x2014; what type of file (e.g. org) is being exported</li>
<li><code>:publishing-directory</code> &#x2014; where the exported files are going</li>
<li><code>:publishing-function</code> &#x2014; how the files are exported. Some options are:
<ul class="org-ul">
<li><code>org-html-publish-to-html</code> &#x2014; converts org files to HTML</li>
<li><code>org-publish-attachment</code> &#x2014; copies the files verbatim</li>
</ul></li>
</ul>
</div>
<div id="outline-container-org7846db6" class="outline-3">
<h3 id="org7846db6"><span class="section-number-3">2.1.</span> Exporting</h3>
<div class="outline-text-3" id="text-2-1">
<p>
Evaluating above code is enough to enable publishing. Open an org file within
your project and type <code>C</code>-<code>c</code> <code>C</code>-<code>e</code> to bring up the "Org Export
Dispatcher", type <code>P</code> for Publishing, and <code>a</code> to publish all. The site will
be generated and placed in the <code>html/</code> directory.
</p>

<p>
You can also publish the site from elisp by evaluating:
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp">(org-publish <span class="org-string">"taingram.org"</span> t)
</pre>
</div>

<p>
The <code>t</code> argument is optional and will force every file to be re-export, even
if that file has not changed. Useful if you are experimenting with project
settings without changing org files.
</p>
</div>
<div id="outline-container-orgbc8fc8b" class="outline-4">
<h4 id="orgbc8fc8b"><span class="section-number-4">2.1.1.</span> Testing your Website</h4>
<div class="outline-text-4" id="text-2-1-1">
<p>
To test out your website with working links you will need a web
server. Python includes one we can use, from the <code>html/</code> directory run
</p>

<div class="org-src-container">
<pre class="src src-bash">python3 -m http.server
</pre>
</div>

<p>
Open <a href="http://localhost:8000">http://localhost:8000</a> in a browser to see your new website.
</p>
</div>
</div>
</div>
</div>
<div id="outline-container-orgbf092eb" class="outline-2">
<h2 id="orgbf092eb"><span class="section-number-2">3.</span> Further Customization</h2>
<div class="outline-text-2" id="text-3">
<p>
Now that we have a basic website exporting we can start experimenting with
more advanced settings within Org publish.
</p>
</div>
<div id="outline-container-org31095b8" class="outline-3">
<h3 id="org31095b8"><span class="section-number-3">3.1.</span> Customize the &lt;Head&gt;</h3>
<div class="outline-text-3" id="text-3-1">
<p>
We can tweak the way HTML is exported with a number of <code>:html-*</code> options. I
prefer to use HTML5 and disable Org's default style sheet and scripts:
</p>
<div class="org-src-container">
<pre class="src src-emacs-lisp"><span class="org-comment-delimiter">; </span><span class="org-comment">HTML5
</span><span class="org-builtin">:html-doctype</span> <span class="org-string">"html5"</span>
<span class="org-builtin">:html-html5-fancy</span> t

<span class="org-comment-delimiter">; </span><span class="org-comment">Disable some Org's HTML defaults
</span><span class="org-builtin">:html-head-include-scripts</span> nil
<span class="org-builtin">:html-head-include-default-style</span> nil
</pre>
</div>
</div>
<div id="outline-container-orgaa1f377" class="outline-4">
<h4 id="orgaa1f377"><span class="section-number-4">3.1.1.</span> CSS</h4>
<div class="outline-text-4" id="text-3-1-1">
<p>
Org's HTML exporter makes it easy to create your own style sheet. The
exported HTML makes sensible use of standard tags as well as specifying
number of classes documented under <a href="https://orgmode.org/manual/CSS-support.html">CSS Support in the Org manual</a>. For my
site I wrote my own style sheet and linked it with:
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp"><span class="org-builtin">:html-head</span> <span class="org-string">"&lt;link rel=\"stylesheet\" href=\"/style.css\" type=\"text/css\"/&gt;"</span>
</pre>
</div>

<p>
The <code>:html-head</code> option lets you add any arbitrary HTML to the head tag.
</p>
</div>
</div>
</div>
<div id="outline-container-orgf180198" class="outline-3">
<h3 id="orgf180198"><span class="section-number-3">3.2.</span> Preamble and Postamble</h3>
<div class="outline-text-3" id="text-3-2">
<p>
Like <code>:html-head</code> Org Publish options for inserting extra HTML before and
after your post content using <code>:html-preamble</code> and <code>:html-postamble</code>.
</p>

<p>
You can add as much (or little) additional HTML as you would like. I used the
preamble to insert some navigation and when the page was updated. The
postamble has a footer with copyright information and site creation info.
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp"><span class="org-builtin">:html-preamble</span> <span class="org-string">"&lt;nav&gt;
  &lt;a href=\"/\"&gt;&amp;lt; Home&lt;/a&gt;
&lt;/nav&gt;
&lt;div id=\"updated\"&gt;Updated: %C&lt;/div&gt;"</span>

<span class="org-builtin">:html-postamble</span> <span class="org-string">"&lt;hr/&gt;
&lt;footer&gt;
  &lt;div class=\"copyright-container\"&gt;
    &lt;div class=\"copyright\"&gt;
      Copyright &amp;copy; 2017-2020 Thomas Ingram some rights reserved&lt;br/&gt;
         Content is available under
         &lt;a rel=\"license\" href=\"http://creativecommons.org/licenses/by-sa/4.0/\"&gt;
           CC-BY-SA 4.0
         &lt;/a&gt; unless otherwise noted
    &lt;/div&gt;
    &lt;div class=\"cc-badge\"&gt;
      &lt;a rel=\"license\" href=\"http://creativecommons.org/licenses/by-sa/4.0/\"&gt;
        &lt;img alt=\"Creative Commons License\"
             src=\"https://i.creativecommons.org/l/by-sa/4.0/88x31.png\" /&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;div class=\"generated\"&gt;
    Created with %c on &lt;a href=\"https://www.gnu.org\"&gt;GNU&lt;/a&gt;/&lt;a href=\"https://www.kernel.org/\"&gt;Linux&lt;/a&gt;
  &lt;/div&gt;
&lt;/footer&gt;"</span>
</pre>
</div>

<p>
Note the use of '%c' and '%C', these symbols will be expanded by Org's html
exporter. Their meaning is documented in the <code>org-html-preamble-format</code>
variable. Here is the complete list:
</p>
<table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">


<colgroup>
<col  class="org-left" />

<col  class="org-left" />
</colgroup>
<tbody>
<tr>
<td class="org-left">%t</td>
<td class="org-left">stands for the title.</td>
</tr>

<tr>
<td class="org-left">%s</td>
<td class="org-left">stands for the subtitle.</td>
</tr>

<tr>
<td class="org-left">%a</td>
<td class="org-left">stands for the author’s name.</td>
</tr>

<tr>
<td class="org-left">%e</td>
<td class="org-left">stands for the author’s email.</td>
</tr>

<tr>
<td class="org-left">%d</td>
<td class="org-left">stands for the date.</td>
</tr>

<tr>
<td class="org-left">%c</td>
<td class="org-left">will be replaced by ‘org-html-creator-string’.</td>
</tr>

<tr>
<td class="org-left">%v</td>
<td class="org-left">will be replaced by ‘org-html-validation-link’.</td>
</tr>

<tr>
<td class="org-left">%T</td>
<td class="org-left">will be replaced by the export time.</td>
</tr>

<tr>
<td class="org-left">%C</td>
<td class="org-left">will be replaced by the last modification time.</td>
</tr>
</tbody>
</table>
</div>
</div>
<div id="outline-container-org0e1549a" class="outline-3">
<h3 id="org0e1549a"><span class="section-number-3">3.3.</span> Sitemap</h3>
<div class="outline-text-3" id="text-3-3">
<p>
Org publish can generate a <a href="https://orgmode.org/manual/Site-map.html#Site-map">sitemap</a> for projects, essentially a site wide
table of contents with links and directory structure. For a global sitemap in
your website add the following to the "pages" project component:
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp"><span class="org-builtin">:auto-sitemap</span> t
<span class="org-builtin">:sitemap-filename</span> <span class="org-string">"sitemap.org"</span>
</pre>
</div>

<p>
For example, a global sitemap for taingram.org would appear as follows:
</p>

<ul class="org-ul">
<li><a href="https://taingram.org/blog/../fun-links.html">Interesting Links From Around the Web</a></li>
<li><a href="https://taingram.org/blog/../notes.html">Useful Tips and Tricks</a></li>
<li>blog
<ul class="org-ul">
<li><a href="https://taingram.org/blog/org-mode-blog.html">Building a Blog with Emacs Org-Mode</a></li>
<li><a href="https://taingram.org/blog/emacs-client.html">Emacsclient Setup with Desktop Integration</a></li>
<li><a href="https://taingram.org/blog/fix-xps-audio.html">Fixing Dell XPS 13 Audio</a></li>
</ul></li>
</ul>

<p>
Once the sitemap.org is generated you can include it from any other page with
</p>

<pre class="example">
#+INCLUDE: sitemap.org :lines "3-"
</pre>


<p>
The <code>:lines 3-</code> will only include the 3rd line on, skipping the <code>#+TITLE</code> tag
set in sitemap.org and grabbing only the list of pages as shown above.
</p>
</div>
<div id="outline-container-orgf9d4f22" class="outline-4">
<h4 id="orgf9d4f22"><span class="section-number-4">3.3.1.</span> Creating a List of Blog Posts</h4>
<div class="outline-text-4" id="text-3-3-1">
<p>
While a global sitemap can be useful, I want a greater distinction made
between blog posts and regular pages. This can be accomplish by separating
"pages" into two components: "pages" in the base directory and "blog" posts
under <code>org/blog/</code>
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp">(<span class="org-string">"pages"</span>
 <span class="org-builtin">:base-directory</span> <span class="org-string">"~/taingram.org/org/"</span>
 <span class="org-builtin">:base-extension</span> <span class="org-string">"org"</span>
 <span class="org-builtin">:recursive</span> nil                               <span class="org-comment-delimiter">; </span><span class="org-comment">avoid exporting blog twice
</span> <span class="org-builtin">:publishing-directory</span> <span class="org-string">"~/taingram.org/html/"</span>
 <span class="org-builtin">:publishing-function</span> org-html-publish-to-html)
(<span class="org-string">"blog"</span>
 <span class="org-builtin">:base-directory</span> <span class="org-string">"~/taingram.org/org/org/blog/"</span>
 <span class="org-builtin">:base-extension</span> <span class="org-string">"org"</span>
 <span class="org-builtin">:publishing-directory</span> <span class="org-string">"~/taingram.org/org/html/blog/"</span>
 <span class="org-builtin">:publishing-function</span> org-html-publish-to-html

 <span class="org-builtin">:auto-sitemap</span> t
 <span class="org-builtin">:sitemap-title</span> <span class="org-string">"Blog Posts"</span>
 <span class="org-builtin">:sitemap-filename</span> <span class="org-string">"index.org"</span>
 <span class="org-builtin">:sitemap-sort-files</span> anti-chronologically)
(<span class="org-string">"taingram.org"</span> <span class="org-builtin">:components</span> (<span class="org-string">"pages"</span> <span class="org-string">"blog"</span> <span class="org-string">"static"</span>))))
</pre>
</div>

<p>
With these settings "blog" will have a sitemap in <code>blog/index.org</code> that
contains a list of <b>only</b> blog posts. The option <code>:sitemap-sort-files
    anti-chronologically</code> will sort the posts from newest to oldest.
</p>

<p>
Now say you have written a homepage in <code>index.org</code> and would like to have
your list of recent blog posts, again include with
</p>

<pre class="example">
* Blog Posts
#+INCLUDE: blog/blog.org :lines "3-8"
[[file:blog/index.org][See more...]]
</pre>
</div>
</div>
<div id="outline-container-org49ea646" class="outline-4">
<h4 id="org49ea646"><span class="section-number-4">3.3.2.</span> Custom sitemap entries</h4>
<div class="outline-text-4" id="text-3-3-2">
<p>
To take this one step further, we can customize the entry format with a
<code>sitemap-format-entry</code> function. In my case I wanted to show the date inline
with the blog post listings:
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp">(<span class="org-keyword">defun</span> <span class="org-function-name">my/org-sitemap-date-entry-format</span> (entry style project)
  <span class="org-doc">"Format ENTRY in org-publish PROJECT Sitemap format ENTRY ENTRY STYLE format that includes date."</span>
  (<span class="org-keyword">let</span> ((filename (org-publish-find-title entry project)))
    (<span class="org-keyword">if</span> (= (length filename) 0)
        (format <span class="org-string">"*%s*"</span> entry)
      (format <span class="org-string">"{{{timestamp(%s)}}} [[file:%s][%s]]"</span>
              (format-time-string <span class="org-string">"%Y-%m-%d"</span>
                                  (org-publish-find-date entry project))
              entry
              filename))))
</pre>
</div>

<p>
Notice <code>(format "{{{timestamp(%s)}}} [[file:%s][%s]]")</code> inserts an <a href="https://orgmode.org/manual/Macro-Replacement.html">Org macro</a>
called timestamp, it is defined as follows:
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp">(<span class="org-keyword">setq</span> org-export-global-macros
            '((<span class="org-string">"timestamp"</span> . <span class="org-string">"@@html:&lt;span class=\"timestamp\"&gt;[$1]&lt;/span&gt;@@"</span>)))
</pre>
</div>

<p>
This macro adds some HTML around the timestamp for CSS styling, it has to be
done as a macro as otherwise Org escapes the HTML tags. The results are:
</p>

<ul class="org-ul">
<li><span class="timestamp">[2020-09-11]</span> <a href="https://taingram.org/blog/org-mode-blog.html">Building a Blog with Emacs Org-Mode</a></li>
<li><span class="timestamp">[2017-05-09]</span> <a href="https://taingram.org/blog/emacs-client.html">Emacsclient Setup with Desktop Integration</a></li>
<li><span class="timestamp">[2017-04-01]</span> <a href="https://taingram.org/blog/fix-xps-audio.html">Fixing Dell XPS 13 Audio Popping</a></li>
</ul>

<p>
Further styling is added on the homepage by wrapping the list in an
additional div class:
</p>

<pre class="example">
#+HTML: &lt;div class="blog-entries"&gt;
#+INCLUDE: "blog/index.org" :lines "3-"
#+HTML: &lt;/div&gt;
</pre>
</div>
</div>
</div>
</div>
<div id="outline-container-org7b62c2b" class="outline-2">
<h2 id="org7b62c2b"><span class="section-number-2">4.</span> Building and Publishing</h2>
<div class="outline-text-2" id="text-4">
<p>
Now that we have our website looking more professional we need to publish it
to the web server. A fast and simple way is to copy the <code>html/</code> directory with
rsync:
</p>

<div class="org-src-container">
<pre class="src src-bash">rsync -e ssh -uvr html/ thomas@taingram.org:/var/www/taingram.org/html/
</pre>
</div>
</div>
<div id="outline-container-org006c48b" class="outline-3">
<h3 id="org006c48b"><span class="section-number-3">4.1.</span> Publish Over Tramp</h3>
<div class="outline-text-3" id="text-4-1">
<p>
Another option is to publish directly to your web server using <a href="https://www.gnu.org/software/tramp/">TRAMP</a>. TRAMP
(Transparent Remote (file) Access, Multiple Protocol) is a tool built into
Emacs for accessing files on remote servers. The format for accessing a file
over TRAMP is <code>/method:user@host:/path/to/file</code> and can be used directly in
Emacs find file dialog.
</p>

<p>
We can simply replace our <code>:publishing-directory</code> with the tramp format:
</p>
<div class="org-src-container">
<pre class="src src-emacs-lisp"><span class="org-builtin">:publishing-directory</span> <span class="org-string">"/ssh:thomas@taingram.org:/var/www/taingram.org/html/"</span>
</pre>
</div>

<p>
Just like that when we publish our file they will be sent directly to our
server. Convenient for publishing individual files, but will be much slower
than the rsync solution.
</p>
</div>
</div>
<div id="outline-container-orgda4210d" class="outline-3">
<h3 id="orgda4210d"><span class="section-number-3">4.2.</span> Relative Directory Paths</h3>
<div class="outline-text-3" id="text-4-2">
<p>
If you intend to distribute the source code of your website (or
otherwise move the project directory) then you'll run into the
issue of breaking paths.  To get around this I keep my publishing
config in a file <code>publish.el</code> with the rest of my website's source
code.  From <code>publish.el</code> we can determine the complete project path
using:
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp">(<span class="org-keyword">defvar</span> <span class="org-variable-name">taingram--project-directory</span>
  (file-name-directory (<span class="org-keyword">or</span> load-file-name (buffer-file-name))))
</pre>
</div>

<p>
Now we can dynamically set our base directory to the full path:
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp"><span class="org-builtin">:base-directory</span> ,(concat taingram--project-directory <span class="org-string">"org/"</span>)
</pre>
</div>

<p>
<b>Note</b> for this to work your <code>org-publish-project-alist</code> should be started
with a ` (backquote) which enables code after a comma to be evaluated. See
<a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Backquote.html">backquote in the Emacs Lisp Manual</a>.
</p>
</div>
</div>
</div>
<div id="outline-container-org3f0d02a" class="outline-2">
<h2 id="org3f0d02a"><span class="section-number-2">5.</span> Thanks</h2>
<div class="outline-text-2" id="text-5">
<p>
I have always found the Emacs community to be full of extremely knowledgeable
and helpful individuals. I would like to thank Thibault Marin on the
<a href="https://orgmode.org/community.html">emacs-orgmode mailing list</a> for his <a href="https://lists.gnu.org/archive/html/emacs-orgmode/2019-07/msg00053.html">help fixing my custom sitemap function</a> with
the suggestion of using an Org mode macro.
</p>

<p>
Thanks to <a href="https://stackoverflow.com/a/26991675">Lindydancer on Stack Overflow</a> for the initial solution for
determining the path of an Emacs Lisp file, and thanks to <a href="https://www.reddit.com/r/emacs/comments/10hiuiz/comment/j59vrta/?utm_source=share&amp;utm_medium=web3x&amp;utm_name=web3xcss&amp;utm_term=1&amp;utm_content=share_button">u/nv-elisp
on reddit</a> for their improved solution.
</p>

<p>
Finally, thank you to all developers of Org mode for producing the best text
based organization system in existence. Specifically thanks to David O’Toole
who originally contributed Org Publish.
</p>
</div>
</div>
<div id="outline-container-orga111fc8" class="outline-2">
<h2 id="orga111fc8"><span class="section-number-2">6.</span> See Also</h2>
<div class="outline-text-2" id="text-6">
<ul class="org-ul">
<li><a href="https://orgmode.org/worg/org-tutorials/org-publish-html-tutorial.html">Publishing Org-mode files to HTML &#x2014; Worg</a></li>
</ul>
</div>
<div id="outline-container-org4b9502c" class="outline-3">
<h3 id="org4b9502c"><span class="section-number-3">6.1.</span> Other Org mode blogs</h3>
<div class="outline-text-3" id="text-6-1">
<ul class="org-ul">
<li><a href="https://nicolas.petton.fr/blog/blogging-with-org-mode.html">https://nicolas.petton.fr/blog/blogging-with-org-mode.html</a></li>
<li><a href="https://ogbe.net/">https://ogbe.net/</a></li>
<li><a href="https://bastibe.de/">https://bastibe.de/</a></li>
<li><a href="https://writepermission.com/">https://writepermission.com/</a></li>
<li><a href="https://staff.fnwi.uva.nl/p.vanormondt/index.html">https://staff.fnwi.uva.nl/p.vanormondt/index.html</a></li>
<li><a href="https://meganrenae21.github.io/Meg-in-Progress/index.html">https://meganrenae21.github.io/Meg-in-Progress/index.html</a></li>
<li><a href="http://professor.ufabc.edu.br/~m.sambinelli/">http://professor.ufabc.edu.br/~m.sambinelli/</a></li>
<li><a href="https://ochicken.net/">https://ochicken.net/</a></li>
</ul>
</div>
</div>
</div>
]]>
</description></item>
<item>
<title>Building Emacs 28.1 with Native Compilation on GNU/Linux</title>
<link>https://taingram.org/blog/emacs-native-comp.html</link>
<pubDate>Mon, 24 Jan 2022 00:00:00 -0500</pubDate>
<guid>https://taingram.org/blog/emacs-native-comp.html</guid>
<description>
<![CDATA[<p>
The recent release of Emacs version 28 brings the addition of a
just-in-time (JIT) native compiler for Emacs Lisp.  This will allow
for Emacs Lisp to seamlessly be compiled to machine code giving
programs a 2-5times speed increase.
</p>

<p>
The following guide will walk through how to build Emacs with native
compilation.  Anyone with a basic understanding of the command line
should be able to follow the steps.
</p>
<div id="outline-container-org8666f01" class="outline-2">
<h2 id="org8666f01"><span class="section-number-2">1.</span> Install the Build Dependencies</h2>
<div class="outline-text-2" id="text-1">
<p>
Since we are only focusing on native compilation we can just install
the default build dependencies as specified by the distros package
manager.  This will save us time hunting down all necessary
dependencies.
</p>
</div>
<div id="outline-container-orgd0ad651" class="outline-3">
<h3 id="orgd0ad651"><span class="section-number-3">1.1.</span> Debian, Trisquel, or Ubuntu</h3>
<div class="outline-text-3" id="text-1-1">
<p>
Install the libraries needed for building Emacs (build dependencies):
</p>

<div class="org-src-container">
<pre class="src src-sh">sudo apt-get build-dep emacs
</pre>
</div>

<p>
Verify your gcc version with <code>gcc --version</code>, example output:
</p>

<pre class="example" id="orgeaa5992">
gcc (Debian 10.2.1-6) 10.2.1 20210110
</pre>

<p>
Install the corresponding libgccjit of the same version.<sup><a id="fnr.1" class="footref" href="#fn.1" role="doc-backlink">1</a></sup>  This is the
JIT compiler used by Emacs:
</p>

<div class="org-src-container">
<pre class="src src-sh">sudo apt-get install libgccjit0 libgccjit-10-dev
</pre>
</div>
</div>
</div>
<div id="outline-container-orge49a785" class="outline-3">
<h3 id="orge49a785"><span class="section-number-3">1.2.</span> Fedora</h3>
<div class="outline-text-3" id="text-1-2">
<p>
Install the build dependencies for Emacs:
</p>

<div class="org-src-container">
<pre class="src src-sh">sudo dnf builddep emacs
</pre>
</div>

<p>
Install libgccjit, the native compiler used by Emacs:
</p>

<div class="org-src-container">
<pre class="src src-sh">sudo dnf install libgccjit libgccjit-devel
</pre>
</div>
</div>
</div>
</div>
<div id="outline-container-org8c86c0c" class="outline-2">
<h2 id="org8c86c0c"><span class="section-number-2">2.</span> Building Emacs</h2>
<div class="outline-text-2" id="text-2">
<p>
You can download the official Emacs 28.1 source code from the below link:
</p>

<ul class="org-ul">
<li><a href="https://ftpmirror.gnu.org/emacs/emacs-28.1.tar.xz">https://ftpmirror.gnu.org/emacs/emacs-28.1.tar.xz</a></li>
<li><a href="https://ftpmirror.gnu.org/emacs/emacs-28.1.tar.gz">https://ftpmirror.gnu.org/emacs/emacs-28.1.tar.gz</a></li>
</ul>

<p>
You can verify this file by following the instructions in the <a href="https://lists.gnu.org/archive/html/emacs-devel/2022-04/msg00093.html">official
release announcement</a>.  This will protect you from the file being
corrupt or modified.
</p>

<p>
Extract the archive:
</p>
<div class="org-src-container">
<pre class="src src-sh">tar -xvf emacs-28.1.tar.xz
</pre>
</div>

<p>
Move into the extracted directory and run the following build commands:
</p>

<div class="org-src-container">
<pre class="src src-sh"><span class="org-builtin">cd</span> emacs-28.1
./autogen.sh
./configure --with-native-compilation
</pre>
</div>

<p>
Verify the commands complete without errors otherwise you may be
missing a dependencies.  In addition, verify the below is output
otherwise libgccjit is not properly installed.
</p>

<pre class="example">
Does Emacs have native lisp compiler?   yes
</pre>


<p>
If the above has completed correctly, then build Emacs by running
<code>make</code>.
</p>

<div class="org-src-container">
<pre class="src src-sh">make
</pre>
</div>
</div>
</div>
<div id="outline-container-org31f23f2" class="outline-2">
<h2 id="org31f23f2"><span class="section-number-2">3.</span> Try it out!</h2>
<div class="outline-text-2" id="text-3">
<p>
Once completed you should have a working Emacs 28 binary.  You can run
it manually and try it out.
</p>

<div class="org-src-container">
<pre class="src src-sh">./src/emacs
</pre>
</div>

<p>
Run <code>M-x</code> <code>version</code> to check it is Emacs 28.  Evaluate the following elisp
to determine if you have native compilation setup correctly:
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp">(native-comp-available-p)
</pre>
</div>

<p>
That's it!  Emacs should automatically start natively compiling all
your installed packages in the background.  You may receive some
compiler warnings occasionally until this process has completed.
</p>
</div>
</div>
<div id="outline-container-orgbf802f9" class="outline-2">
<h2 id="orgbf802f9"><span class="section-number-2">4.</span> Installing</h2>
<div class="outline-text-2" id="text-4">
<p>
You can continue running it from the build directory or fully install
it using make:
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp">sudo make install
</pre>
</div>

<p>
If at any point you'd like to remove it you can run:
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp">sudo make uninstall
</pre>
</div>
</div>
</div>
<div id="footnotes">
<h2 class="footnotes">Footnotes: </h2>
<div id="text-footnotes">

<div class="footdef"><sup><a id="fn.1" class="footnum" href="#fnr.1" role="doc-backlink">1</a></sup> <div class="footpara" role="doc-footnote"><p class="footpara">
Thanks to Pascal Jaeger and Răzvan Birișan for this correction.
</p></div></div>


</div>
</div>]]>
</description></item>
<item>
<title>Emacsclient Setup with Desktop Integration</title>
<link>https://taingram.org/blog/emacs-client.html</link>
<pubDate>Tue, 02 May 2017 00:00:00 -0400</pubDate>
<guid>https://taingram.org/blog/emacs-client.html</guid>
<description>
<![CDATA[<p>
When using a typical text editor (e.g. gedit or vim) it is expected to be able
to quickly open and close files from your file manager or terminal. Emacs, while
a great editor, is not well suited for this workflow as typical users have long
configuration files that must be loaded slowing the start-up time. This is not a
problem if you start Emacs once and do everything inside of it, but if you are
frequently opening and closing windows you would be better off just starting
Emacs once and connect to it using the fast and lightweight <code>emacsclient</code>.
</p>
<div id="outline-container-org448c907" class="outline-2">
<h2 id="org448c907"><span class="section-number-2">1.</span> Running Emacs as a daemon</h2>
<div class="outline-text-2" id="text-1">
<div class="org-src-container">
<pre class="src src-bash">emacs --daemon
</pre>
</div>
<p>
This can be added to startup files that are sourced at login like your bash
profile (<code>~/.profile</code> or <code>~/.bash_profile</code>) to automatically start the daemon at
login.
</p>
</div>
<div id="outline-container-org9279265" class="outline-3">
<h3 id="org9279265"><span class="section-number-3">1.1.</span> Using a systemd service</h3>
<div class="outline-text-3" id="text-1-1">
<p>
Alternatively, as of <a href="https://lists.gnu.org/archive/html/emacs-devel/2018-05/msg00765.html">GNU Emacs 26.1 a systemd unit file is included</a>, using
systemd allows for convenient management commands through the familiar <code>systemctl</code>
utility as used with other services.
</p>

<table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">


<colgroup>
<col  class="org-left" />

<col  class="org-left" />
</colgroup>
<thead>
<tr>
<th scope="col" class="org-left">Systemctl commands</th>
<th scope="col" class="org-left">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="org-left">start</td>
<td class="org-left">Start (activate) one or more units</td>
</tr>

<tr>
<td class="org-left">stop</td>
<td class="org-left">Stop (deactivate) one or more units</td>
</tr>

<tr>
<td class="org-left">restart</td>
<td class="org-left">Start or restart one or more units</td>
</tr>

<tr>
<td class="org-left">enable</td>
<td class="org-left">Enable one or more unit files</td>
</tr>

<tr>
<td class="org-left">disable</td>
<td class="org-left">Disable one or more unit files</td>
</tr>
</tbody>
</table>

<p>
Emacs's unit file is a user service, meaning it doesn't require root access and
is started at login rather than boot. In order to control user services we must
preface our commands with <code>--user</code> flag.
</p>

<div class="org-src-container">
<pre class="src src-bash">systemctl --user start emacs.service   <span class="org-comment-delimiter"># </span><span class="org-comment">Start emacs for the current session
</span>systemctl --user enable emacs.service  <span class="org-comment-delimiter"># </span><span class="org-comment">Enable emacs to be started at login</span>
</pre>
</div>
</div>
</div>
</div>
<div id="outline-container-orgc3e2d2f" class="outline-2">
<h2 id="orgc3e2d2f"><span class="section-number-2">2.</span> Open files from your graphical file browser</h2>
<div class="outline-text-2" id="text-2">
<p>
Now like any other graphical editor you will need a desktop icon in order to
open files from your graphical file browser. To do so create a desktop file for
emacsclient and place it in <code>~/.local/share/applications/emacsclient.desktop</code><sup><a id="fnr.1" class="footref" href="#fn.1" role="doc-backlink">1</a></sup>
</p>

<div class="org-src-container">
<pre class="src src-conf" id="org9a05201">[<span class="org-type">Desktop Entry</span>]
<span class="org-variable-name">Name</span>=Emacs Client
<span class="org-variable-name">GenericName</span>=Text Editor
<span class="org-variable-name">Comment</span>=Edit text
<span class="org-variable-name">MimeType</span>=text/english;text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++;
<span class="org-variable-name">Exec</span>=emacsclient -c %f
<span class="org-variable-name">Icon</span>=emacs
<span class="org-variable-name">Type</span>=Application
<span class="org-variable-name">Terminal</span>=false
<span class="org-variable-name">Categories</span>=Utility;TextEditor;
</pre>
</div>

<p>
Note that some distributions ship with an Emacs client desktop icon by
default, like Debian, so this step may be unnecessary unless you want
to make use of the script below.
</p>
</div>
<div id="outline-container-orgc2f965f" class="outline-3">
<h3 id="orgc2f965f"><span class="section-number-3">2.1.</span> Open all files in one frame</h3>
<div class="outline-text-3" id="text-2-1">
<p>
This desktop file will result in each file being opened as a new Emacs frame (a
new window). This will clutter up your desktop if you open many files. A better
approach would be to open a new frame only if none exist otherwise open the file
as a new buffer in the existing frame. This is accomplished with the following
script <sup><a id="fnr.2" class="footref" href="#fn.2" role="doc-backlink">2</a></sup>
</p>

<div class="org-src-container">
<pre class="src src-bash" id="org661537b"><span class="org-comment-delimiter">#</span><span class="org-comment">!/bin/</span><span class="org-keyword">bash</span><span class="org-comment">
</span>
<span class="org-comment-delimiter"># </span><span class="org-comment">if no args open new frame
</span><span class="org-keyword">if</span> [ $<span class="org-variable-name">#</span> -eq 0 ]; <span class="org-keyword">then</span>
    emacsclient -c -n
    <span class="org-keyword">exit</span>
<span class="org-keyword">fi</span>

emacsclient -e <span class="org-string">"(frames-on-display-list \"$DISPLAY\")"</span> &amp;&gt;/dev/null

<span class="org-keyword">if</span> [ $<span class="org-variable-name">?</span> -eq 0 ]; <span class="org-keyword">then</span>
    emacsclient -n <span class="org-string">"$*"</span>
<span class="org-keyword">else</span>
    emacsclient -c -n <span class="org-string">"$*"</span>
<span class="org-keyword">fi</span>
</pre>
</div>

<div class="notice" id="org337f73d">
<p>
<b>Update <span class="timestamp-wrapper"><span class="timestamp">[2025-02-20 Thu]</span></span></b>:
</p>

<p>
Neftali Figueroa suggested using the X11 <a href="https://github.com/mkropat/jumpapp">jumpapp</a> tool to improve this
script.  <a href="https://gist.github.com/nefigcas/ab6b09b8eb730fcf24ad071167a1df9c">See their modified script here</a>.
</p>

</div>

<p>
Make the script executable:
</p>
<div class="org-src-container">
<pre class="src src-bash">chmod +x emacsclient-one-frame.sh
</pre>
</div>

<p>
And place it somewhere accessible from your <code>$PATH</code>. I use <code>~/bin</code> but if you would
like it hidden <code>~/.local/bin</code> is another option. Add both to your <code>$PATH</code> by adding
the following to your <code>~/.bashrc</code>:
</p>

<div class="org-src-container">
<pre class="src src-bash"><span class="org-variable-name">PATH</span>=<span class="org-string">"$HOME/.local/bin:$HOME/bin:$PATH"</span>
<span class="org-builtin">export</span> PATH
</pre>
</div>

<p>
Change the Exec line in the desktop file to the script.
</p>
<div class="org-src-container">
<pre class="src src-conf"><span class="org-variable-name">Exec</span>=emacsclient-one-frame.sh %f
</pre>
</div>
</div>
</div>
<div id="outline-container-org3e3a4ff" class="outline-3">
<h3 id="org3e3a4ff"><span class="section-number-3">2.2.</span> Set as default in Nautilus</h3>
<div class="outline-text-3" id="text-2-2">
<p>
In nautilus file browser find a text file type you wish to be
associated with Emacs client. Right click it, select properties, move
to the "Open With" tab choose Emacs Client and press "Set as
default".
</p>
</div>
</div>
</div>
<div id="outline-container-orgba3d09d" class="outline-2">
<h2 id="orgba3d09d"><span class="section-number-2">3.</span> Add a command alias</h2>
<div class="outline-text-2" id="text-3">
<p>
If you frequently start Emacs from the commandline you'll want to
start using emacsclient to speed up your startup time. In your
<code>~/.bashrc</code> consider adding one of the following aliases
</p>

<div class="org-src-container">
<pre class="src src-bash"><span class="org-builtin">alias</span> <span class="org-variable-name">emacs</span>=<span class="org-string">'emacsclient-one-frame.sh'</span>
<span class="org-builtin">alias</span> <span class="org-variable-name">ec</span>=<span class="org-string">'emacsclient -t'</span>                <span class="org-comment-delimiter"># </span><span class="org-comment">Opens emacs inside terminal</span>
</pre>
</div>
</div>
<div id="outline-container-org35564be" class="outline-3">
<h3 id="org35564be"><span class="section-number-3">3.1.</span> Set emacsclient as your default terminal  editor</h3>
<div class="outline-text-3" id="text-3-1">
<p>
In your <code>~/.profile</code> or <code>~/.bash_profile</code> add the following lines
</p>

<div class="org-src-container">
<pre class="src src-bash"><span class="org-variable-name">VISUAL</span>=<span class="org-string">'emacsclient -t'</span>
<span class="org-builtin">export</span> VISUAL
</pre>
</div>

<p>
<code>VISUAL</code> means  full-screen or <i>visual</i> editor, this variable should be used over
<code>EDITOR</code>. <code>EDITOR</code>  is a fallback used when full-screen editing features are not
available. <sup><a id="fnr.3" class="footref" href="#fn.3" role="doc-backlink">3</a></sup>
</p>
</div>
</div>
</div>
<div id="footnotes">
<h2 class="footnotes">Footnotes: </h2>
<div id="text-footnotes">

<div class="footdef"><sup><a id="fn.1" class="footnum" href="#fnr.1" role="doc-backlink">1</a></sup> <div class="footpara" role="doc-footnote"><p class="footpara">
<a href="https://developer.gnome.org/integration-guide/stable/desktop-files.html.en">GNOME Desktop file guide</a>
</p></div></div>

<div class="footdef"><sup><a id="fn.2" class="footnum" href="#fnr.2" role="doc-backlink">2</a></sup> <div class="footpara" role="doc-footnote"><p class="footpara">
<a href="http://stackoverflow.com/questions/25029877/using-emacs-as-a-server-and-opening-only-one-window-exactly-which-should-be-max#28015471">Shell script adapted from StackOverflow user mzuther</a>
</p></div></div>

<div class="footdef"><sup><a id="fn.3" class="footnum" href="#fnr.3" role="doc-backlink">3</a></sup> <div class="footpara" role="doc-footnote"><p class="footpara">
<a href="https://unix.stackexchange.com/questions/4859/visual-vs-editor-whats-the-difference">VISUAL versus EDITOR</a>
</p></div></div>


</div>
</div>]]>
</description></item>
<item>
<title>Useful Tips for the Sway Window Manager</title>
<link>https://taingram.org/blog/sway-tips.html</link>
<pubDate>Wed, 30 Nov 2022 00:00:00 -0500</pubDate>
<guid>https://taingram.org/blog/sway-tips.html</guid>
<description>
<![CDATA[<div id="table-of-contents" role="doc-toc">
<h2>Table of Contents</h2>
<div id="text-table-of-contents" role="doc-toc">
<ul>
<li><a href="#orgd7b1bf5">1. Set Caps Lock to be Control</a></li>
<li><a href="#orgaee2c19">2. Adjust Screen Brightness</a></li>
<li><a href="#org56b8b9e">3. Taking Screenshots</a></li>
<li><a href="#orgfb39704">4. Reduce Blue Light</a></li>
<li><a href="#org4cfc909">5. Hide Borders when Window is <i>'Maximized'</i></a></li>
<li><a href="#orgadb4b98">6. Keep Renamed Workspaces in Order</a></li>
<li><a href="#org49e6d52">7. Conclusion</a></li>
</ul>
</div>
</div>
<p>
For the past several months I've been using <a href="https://swaywm.org/">Sway window manager</a>, after
getting tired of how much GNOME was changing<sup><a id="fnr.1" class="footref" href="#fn.1" role="doc-backlink">1</a></sup>.  The switch has
been a very pleasant experience.  If I find a behavior I don't like
then a quick search of the <a href="https://manpages.debian.org/bullseye/sway/sway.5.en.html">manual</a> will usually have an option to
change it.  If there is a missing feature then it's a quick web search
to find the right tool for the job.  Most are already packaged in
Debian stable.  Overall whole sway ecosystem has gotten quite mature.
</p>

<p>
In this post I will summarize some useful settings and tools I've used
to get sway working the way I like.  Nothing groundbreaking, but
hopefully it will be useful.
</p>
<div id="outline-container-orgd7b1bf5" class="outline-2">
<h2 id="orgd7b1bf5"><span class="section-number-2">1.</span> Set Caps Lock to be Control</h2>
<div class="outline-text-2" id="text-1">
<p>
As an <a href="https://taingram.org/init.html">Emacs user</a> on a laptop I like to have the <code>Caps Lock</code> key
rebound to <code>Ctrl</code>.  In sway this can be done as follows:
</p>

<div class="org-src-container">
<pre class="src src-nil">input "1:1:AT_Translated_Set_2_keyboard" xkb_options ctrl:nocaps
</pre>
</div>
</div>
</div>
<div id="outline-container-orgaee2c19" class="outline-2">
<h2 id="orgaee2c19"><span class="section-number-2">2.</span> Adjust Screen Brightness</h2>
<div class="outline-text-2" id="text-2">
<p>
I use <a href="https://github.com/Hummer12007/brightnessctl">brightnessctl</a> to control this.
</p>

<div class="org-src-container">
<pre class="src src-conf"><span class="org-comment-delimiter"># </span><span class="org-comment">Brightness
</span>bindsym XF86MonBrightnessDown exec <span class="org-string">"brightnessctl -n set 5%-"</span>
bindsym XF86MonBrightnessUp   exec <span class="org-string">"brightnessctl set +5%"</span>
</pre>
</div>

<p>
Years ago I contributed the <code>-n</code> flag or <code>--min-value</code>.
This flag will prevent your brightness from falling to zero and
turning off your display.
</p>
</div>
</div>
<div id="outline-container-org56b8b9e" class="outline-2">
<h2 id="org56b8b9e"><span class="section-number-2">3.</span> Taking Screenshots</h2>
<div class="outline-text-2" id="text-3">
<dl class="org-dl">
<dt><a href="https://sr.ht/~emersion/grim/">grim</a></dt><dd>Very simple command line screenshot tool.</dd>
<dt><a href="https://github.com/swaywm/sway/blob/master/contrib/grimshot">grimshot</a></dt><dd>A small shell script around grim that provides easy
commands to capture a specific windows/regions using your mouse.</dd>
</dl>

<div class="org-src-container">
<pre class="src src-conf"><span class="org-comment-delimiter"># </span><span class="org-comment">Screenshot
</span>bindsym Print       exec <span class="org-string">"grimshot save screen"</span>
bindsym Mod1+Print  exec <span class="org-string">"grimshot save window"</span>
bindsym Shift+Print exec <span class="org-string">"grimshot save area"</span>
bindsym Mod4+Print  exec <span class="org-string">"grimshot copy area"</span>
</pre>
</div>

<p>
I based these shortcuts off the <a href="https://help.gnome.org/users/gnome-help/stable/screen-shot-record.html.en">ones used in GNOME</a>.
</p>

<p>
By default grim/grimshot will place files in the
<code>$XDG_SCREENSHOTS_DIR</code> (default <code>~/Pictures</code>).  This can be overridden
by setting <code>$XDG_SCREENSHOTS_DIR</code> if needed.
</p>
</div>
</div>
<div id="outline-container-orgfb39704" class="outline-2">
<h2 id="orgfb39704"><span class="section-number-2">4.</span> Reduce Blue Light</h2>
<div class="outline-text-2" id="text-4">
<p>
There is some research that shows blue light in the evening is not
good for you.  Regardless though it's nice to have the screen a bit
warmer when viewing in a dark room.
</p>

<p>
<a href="https://gitlab.com/chinstrap/gammastep">Gammastep</a> handles this in an extremely easy way.  Just set your
location (latitude:longitude) and add it to your config.  The color
temperature can be tweaked if needed.
</p>

<div class="org-src-container">
<pre class="src src-nil">exec gammastep -l 45.000:-80.000
</pre>
</div>
</div>
</div>
<div id="outline-container-org4cfc909" class="outline-2">
<h2 id="org4cfc909"><span class="section-number-2">5.</span> Hide Borders when Window is <i>'Maximized'</i></h2>
<div class="outline-text-2" id="text-5">
<p>
When there is only one window on the screen the borders are
unnecessary.  This is normally how "maximized" windows are handled in
most floating window desktops.  Smart border hiding does exactly that.
</p>

<div class="org-src-container">
<pre class="src src-conf">hide_edge_borders smart
</pre>
</div>
</div>
</div>
<div id="outline-container-orgadb4b98" class="outline-2">
<h2 id="orgadb4b98"><span class="section-number-2">6.</span> Keep Renamed Workspaces in Order</h2>
<div class="outline-text-2" id="text-6">
<p>
If you rename your workspaces to something other than numbers they may
not be ordered correctly in the sway bar.  This can be corrected by
adding a "number:" before the name.  The numbers can be removed by
adding the following to your sway bar settings:
</p>

<div class="org-src-container">
<pre class="src src-conf">strip_workspace_numbers yes
</pre>
</div>

<p>
Example using Japanese Kanji:
</p>
<div class="org-src-container">
<pre class="src src-conf"><span class="org-comment-delimiter"># </span><span class="org-comment">switch to workspace
</span>bindsym $mod+1 workspace 1:&#19968;
bindsym $mod+2 workspace 2:&#20108;
bindsym $mod+3 workspace 3:&#19977;
bindsym $mod+4 workspace 4:&#22235;
bindsym $mod+5 workspace 5:&#20116;
bindsym $mod+6 workspace 6:&#20845;
bindsym $mod+7 workspace 7:&#19971;
bindsym $mod+8 workspace 8:&#20843;
bindsym $mod+9 workspace 9:&#20061;
bindsym $mod+0 workspace 10:&#21313;
<span class="org-comment-delimiter"># </span><span class="org-comment">move focused container to workspace
</span>bindsym $mod+Shift+1 move container to workspace 1:&#19968;
bindsym $mod+Shift+2 move container to workspace 2:&#20108;
bindsym $mod+Shift+3 move container to workspace 3:&#19977;
bindsym $mod+Shift+4 move container to workspace 4:&#22235;
bindsym $mod+Shift+5 move container to workspace 5:&#20116;
bindsym $mod+Shift+6 move container to workspace 6:&#20845;
bindsym $mod+Shift+7 move container to workspace 7:&#19971;
bindsym $mod+Shift+8 move container to workspace 8:&#20843;
bindsym $mod+Shift+9 move container to workspace 9:&#20061;
bindsym $mod+Shift+0 move container to workspace 10:&#21313;
</pre>
</div>
</div>
</div>
<div id="outline-container-org49e6d52" class="outline-2">
<h2 id="org49e6d52"><span class="section-number-2">7.</span> Conclusion</h2>
<div class="outline-text-2" id="text-7">
<p>
I'm pretty happy with sway and I think I'll stick with it for a
while.  I love how every rough edge I smooth feels like a step towards
creating my perfect computer experience.
</p>

<p>
Still there are a few edges I still would like to address further.
Below are a just a few:
</p>

<ul class="org-ul">
<li><b>Launching Applications</b> &#x2014; I don't like how dmenu by default shows
all commands as many I will <i>never</i> need to run.</li>
<li><b>Audio Controls</b> &#x2014; I currently use amixer because that was already
included on Debian.  I've had some situations where it has behaved
inconsistently.</li>
<li><b>Customizing Swaybar</b> &#x2014; I currently use a pretty basic i3status
config.  It would be interesting to experiment with something
different.</li>
<li><b>Color Schemes</b> &#x2014; I currently use the default i3 colors,
and it would be nice to come up with something more me.</li>
</ul>
</div>
</div>
<div id="footnotes">
<h2 class="footnotes">Footnotes: </h2>
<div id="text-footnotes">

<div class="footdef"><sup><a id="fn.1" class="footnum" href="#fnr.1" role="doc-backlink">1</a></sup> <div class="footpara" role="doc-footnote"><p class="footpara">
The GNOME developers mean well and most decisions they make are
good for the average computer consumer.  However, as a pretty adept
user having your workflow change gets old.
</p></div></div>


</div>
</div>]]>
</description></item>
<item>
<title>Lightweight Emacs-like Editors</title>
<link>https://taingram.org/blog/lightweight-emacs-editors.html</link>
<pubDate>Tue, 18 Aug 2020 00:00:00 -0400</pubDate>
<guid>https://taingram.org/blog/lightweight-emacs-editors.html</guid>
<description>
<![CDATA[<p>
<b>Note</b>: Some information may be out of date.
</p>

<p>
GNU Emacs is an excellent editor thanks in large part to the power of lisp as an
extension language. It is the extensibility of Emacs that allows for total
customization and excellent packages like <a href="https://orgmode.org/">org mode</a>, <a href="https://magit.vc/">magit</a>, <a href="https://emacs-helm.github.io/helm/">helm</a>, and <a href="https://melpa.org/">many
more</a>. That power comes at a cost, slow start up times and a reasonable memory
footprint. You'll rarely find GNU Emacs pre-installed on most Linux distros,
especially not in low-resource environments.
</p>

<p>
What is an Emacs user to do, assuming you don't want to use vi, the best
option is to utilize Emacs editors with a lighter feel. So consider giving one
of these lightweight Emacs alternatives a try.
</p>

<table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">


<colgroup>
<col  class="org-left" />

<col  class="org-left" />

<col  class="org-left" />

<col  class="org-left" />

<col  class="org-left" />

<col  class="org-left" />

<col  class="org-left" />
</colgroup>
<thead>
<tr>
<th scope="col" class="org-left">Editor</th>
<th scope="col" class="org-left">Language</th>
<th scope="col" class="org-left">Config</th>
<th scope="col" class="org-left">UTF-8</th>
<th scope="col" class="org-left">Syntax</th>
<th scope="col" class="org-left">Size</th>
<th scope="col" class="org-left">License</th>
</tr>
</thead>
<tbody>
<tr>
<td class="org-left"><a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Directory-Variables.html">GNU Emacs</a></td>
<td class="org-left">C, elisp</td>
<td class="org-left">elisp</td>
<td class="org-left">Yes</td>
<td class="org-left">Yes</td>
<td class="org-left">130 M</td>
<td class="org-left">GPLv3</td>
</tr>

<tr>
<td class="org-left"><a href="https://www.jedsoft.org/jed/index.html">jed</a></td>
<td class="org-left">C, S-Lang</td>
<td class="org-left">S-Lang</td>
<td class="org-left">Yes</td>
<td class="org-left">Yes</td>
<td class="org-left">6.5 M</td>
<td class="org-left">GPLv2+</td>
</tr>

<tr>
<td class="org-left"><a href="https://joe-editor.sourceforge.io/">joe</a></td>
<td class="org-left">C</td>
<td class="org-left">text</td>
<td class="org-left">Yes</td>
<td class="org-left">Yes</td>
<td class="org-left">2.0 M</td>
<td class="org-left">GPLv2+</td>
</tr>

<tr>
<td class="org-left"><a href="https://www.gnu.org/software/zile/">zile</a></td>
<td class="org-left">C, Lua</td>
<td class="org-left">zlisp</td>
<td class="org-left">No</td>
<td class="org-left">No</td>
<td class="org-left">813 K</td>
<td class="org-left">GPLv3</td>
</tr>

<tr>
<td class="org-left"><a href="https://git.kernel.org/pub/scm/editors/uemacs/uemacs.git/">uemacs</a></td>
<td class="org-left">C</td>
<td class="org-left">&#xa0;</td>
<td class="org-left">Yes</td>
<td class="org-left">No</td>
<td class="org-left">639 K</td>
<td class="org-left">Source-available</td>
</tr>

<tr>
<td class="org-left"><a href="https://github.com/hboetes/mg">mg</a></td>
<td class="org-left">C</td>
<td class="org-left">text</td>
<td class="org-left">No</td>
<td class="org-left">No</td>
<td class="org-left">553 K</td>
<td class="org-left">Permissive</td>
</tr>

<tr>
<td class="org-left"><a href="https://sites.google.com/site/e3editor/">e3</a></td>
<td class="org-left">x86 assembly</td>
<td class="org-left">&#xa0;</td>
<td class="org-left">Yes</td>
<td class="org-left">No</td>
<td class="org-left">121 K</td>
<td class="org-left">GPLv2</td>
</tr>
</tbody>
</table>
<div id="outline-container-org58e6650" class="outline-2">
<h2 id="org58e6650"><span class="section-number-2">1.</span> JED</h2>
<div class="outline-text-2" id="text-1">

<div id="org5ec3bfa" class="figure">
<p><img src="https://taingram.org/blog/files/jed.png" alt="jed.png" />
</p>
<p><span class="figure-number">Figure 1: </span>JED showing off split windows, UTF-8 support, and syntax highlighting</p>
</div>
<ul class="org-ul">
<li><b>Website</b>: <a href="https://www.jedsoft.org/jed/index.html">https://www.jedsoft.org/jed/index.html</a></li>
<li><b>License</b>: GPLv2+</li>
<li><b>Depends on</b>: libc, slang, slsh, and libgpm</li>
</ul>

<p>
JED is a powerful editor in near competition with GNU Emacs. JED is written in
a combination of C and the S-Lang scripting language for which JED is the
flagship application. JED ships with <b>UTF-8 support</b> and <b>syntax highlighting</b>
along with language specific modes for many popular programming languages.
</p>

<p>
By default JED uses keybindings very similar to Emacs with extra commands
available from <code>M-x</code>. There are familiar extras like <code>compile</code>, <code>info</code>, and a
<code>shell</code>, there's even a mail reader. JED can be configured <b>and extended</b> with
S-Lang making it more flexible and Emacs-like than others on this list.
</p>

<p>
JED has not had a stable release in over ten years, however, JED is actively
developed and the <a href="https://www.jedsoft.org/snapshots/">latest development snapshot</a> is only a few months old.
</p>
</div>
</div>
<div id="outline-container-orgf3ad0a1" class="outline-2">
<h2 id="orgf3ad0a1"><span class="section-number-2">2.</span> JOE &#x2014; Joe's Own Editor</h2>
<div class="outline-text-2" id="text-2">

<div id="org05468a4" class="figure">
<p><img src="https://taingram.org/blog/files/joe-jmacs.png" alt="joe-jmacs.png" />
</p>
<p><span class="figure-number">Figure 2: </span>JOE's default jmacs config showing off syntax highlighting</p>
</div>

<ul class="org-ul">
<li><b>Website</b>: <a href="https://joe:editor.sourceforge.io/">https://joe:editor.sourceforge.io/</a></li>
<li><b>License</b>: GPLv2</li>
<li><b>Depends on</b>: libc, ncurses, terminfo</li>
</ul>

<blockquote>
<p>
JOE is a blending of MicroPro's venerable microcomputer word processor
WordStar and Richard Stallman's famous LISP based text editor GNU-EMACS [&#x2026;]:
most of the basic editing keys are the same as in WordStar as is the overall
feel of the editor. JOE also has some of the key bindings and many of the
powerful features of EMACS.
</p>
</blockquote>

<p>
The defaults of JOE may be closer to WordStar than Emacs, but that's no
problem as JOE provides a number of different configurations. One specifically
made to emulate the <i>feel</i> of Emacs is aliased to <code>jmacs</code>. This scheme matches
GNU Emacs keybindings with movement, find and replace, transpose, undo,
etc. all in their usual places.
</p>

<p>
In addition, JOE provides extra niceties like <b>syntax highlighting</b> and <b>UTF-8
support</b>. You can run a shell with <code>F3</code>, or compile and grep within JOE using
familiar <code>M-x</code> commands.
</p>

<p>
Read more about <a href="https://joe:editor.sourceforge.io/">JOE on its website</a> and its extensive <a href="https://joe-editor.sourceforge.io/4.6/man.html">manual page <code>joe(1)</code></a>.
</p>
</div>
</div>
<div id="outline-container-org6a32cc2" class="outline-2">
<h2 id="org6a32cc2"><span class="section-number-2">3.</span> GNU Zile &#x2014; Zile Implements Lua Editors</h2>
<div class="outline-text-2" id="text-3">

<div id="orgea0658e" class="figure">
<p><img src="https://taingram.org/blog/files/zile.png" alt="zile.png" />
</p>
<p><span class="figure-number">Figure 3: </span>Zile's default Zemacs editor opening a file in GNOME Terminal</p>
</div>

<ul class="org-ul">
<li><b>Website</b>: <a href="https://www.gnu.org/software/zile/">https://www.gnu.org/software/zile/</a></li>
<li><b>Repository</b>: <a href="https://savannah.gnu.org/projects/zile/">https://savannah.gnu.org/projects/zile/</a></li>
<li><b>License</b>: GPLv3</li>
<li><b>Depends on</b>: libc, libacl, libgc, ncurses, and terminfo</li>
</ul>

<p>
GNU Zile began as an attempt to make a lightweight Emacs editor (its original
acronym was "Zile Is Lossy Emacs"). It has expanded to be a toolkit for
implementing small editors with C and Lua. Regardless of this change of scope
its stock editor is still one of the better imitations of GNU Emacs available.
</p>

<blockquote>
<p>
[Zile] comes with an example implementation of a lightweight Emacs clone,
called Zemacs. Every Emacs user should feel at home with Zemacs. Zemacs is
aimed at small footprint systems and quick editing sessions (it starts up and
shuts down instantly).
</p>
</blockquote>

<p>
Zemacs looks and feels very similar to running GNU Emacs from the terminal,
even sporting the familiar modeline. The similarities go deeper as Zemacs is
self-documenting editor with help pages for commands, variables, and
keybindings that can be read with the usual Emacs commands (<code>C-h f</code>, <code>C-h v</code>,
and <code>C-h k</code>). Zemacs is configured in its own lisp with syntax like a stripped
down version of Emacs Lisp. You cannot define new functions, but you can set
variables and keybindings.
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp">(global-set-key <span class="org-string">"key"</span> 'func)

<span class="org-comment-delimiter">; </span><span class="org-comment">Column beyond which automatic line-wrapping should happen.
</span>(<span class="org-keyword">setq</span> fill-column 80)
</pre>
</div>

<p>
Out of the box Zemacs has most of the basic editing commands of GNU Emacs and
supports multiple buffers/windows. It lacks richer features like UTF-8, syntax
highlighting, or language modes other than fundamental. Zile acknowledges this
and recommends using Emacs or JED if you need those powerful features.
</p>

<p>
For more information check out <a href="https://www.gnu.org/software/zile/">Zile's website</a> and on your system look at
<code>zile(1)</code> and <code>/usr/share/doc/zile/</code>.
</p>
</div>
</div>
<div id="outline-container-org83b6433" class="outline-2">
<h2 id="org83b6433"><span class="section-number-2">4.</span> Mg &#x2014; Micro GNU/emacs</h2>
<div class="outline-text-2" id="text-4">

<div id="orgd47989a" class="figure">
<p><img src="https://taingram.org/blog/files/mg.png" alt="mg.png" />
</p>
<p><span class="figure-number">Figure 4: </span>Mg opening a file in GNOME Terminal</p>
</div>

<ul class="org-ul">
<li><b>Repository</b>:  <a href="https://github.com/hboetes/mg">https://github.com/hboetes/mg</a></li>
<li><b>License</b>:  Permissive</li>
<li><b>Depends on</b>: libc, libbsd, and terminfo</li>
</ul>

<p>
Mg is a lightweight Emacs-like editor maintained by OpenBSD developers and
included in their base operating system. Mg strives to specifically emulate
GNU Emacs, so users should feel particularly at home.
</p>

<blockquote>
<p>
This program is intended to be a small, fast, and portable editor for people
who can't (or don't want to) run real Emacs for one reason or another.  It is
compatible with GNU because there shouldn't be any reason to learn more than
one Emacs flavor. &#x2014; Mg's README
</p>
</blockquote>

<p>
Mg is extensively documented, like most OpenBSD tools, within its manual page
<code>mg(1)</code>. Keybindings with their assigned functions names are all listed and
every functions' behavior is documented in detail.  Mg supports a wide breadth
of Emacs editing commands, you can compile files within mg, and even view
directories with dired (a feature absent from other editors on this
list). There is only one specific language mode included, <code>c-mode</code>, which adds
some indenting help but no syntax highlighting. Mg also supports ctags and
cscope to help navigate through large code base.
</p>

<p>
Configuration for mg is done with a plain text file that looks like elisp but
with all the lispy elements stripped out. From this any key can be rebound and
settings can be adjusted (example taken from the mg manual):
</p>

<div class="org-src-container">
<pre class="src src-nil">global-set-key ")" self-insert-command
global-set-key "\^x\^f" find-file
global-set-key "\e[Z" backward-char
set-default-mode fill
set-fill-column 72
auto-execute *.c c-mode
</pre>
</div>

<p>
For the most part mg strikes a good balance between minimal and feeling close
to GNU Emacs. The most obvious downsides of mg is its lack of UTF-8 support.
</p>
</div>
</div>
<div id="outline-container-org519ddf9" class="outline-2">
<h2 id="org519ddf9"><span class="section-number-2">5.</span> e3</h2>
<div class="outline-text-2" id="text-5">

<div id="org912a34e" class="figure">
<p><img src="https://taingram.org/blog/files/e3em-help.png" alt="e3em-help.png" />
</p>
<p><span class="figure-number">Figure 5: </span>e3 running from the <code>e3em</code> command showing its help screen</p>
</div>
<ul class="org-ul">
<li><b>Website</b>: <a href="https://sites.google.com/site/e3editor/">https://sites.google.com/site/e3editor/</a></li>
<li><b>License</b>: GPLv2</li>
<li><b>Depends on</b>: (nothing)</li>
</ul>

<p>
e3 is perhaps the most lightweight editor on this list, it has the smallest
install size at 121 kilobytes, is written completely in x86 assembly, and has
absolutely has no dependencies (not even libc). Yet somehow e3 manages to pack
in an editor with 5 different keybinding schemes (e3em for Emacs), an inline
calculator, and even <b>UTF-8 support</b>! Each editor has a built in help page and
its own manual page containing a list of keybindings for each editor.
</p>

<p>
That being said the imitation the of Emacs only supports the basic Emacs
editing keybindings. E3 does not support any type of configuration file so you
have to work with what you're given unless you want to edit some assembly
code. The other downside of assembly means you are mostly limited to x86
architecture (e.g. no Raspberry Pi etc.). Still e3's feature set is extremely
impressive for its size.
</p>
</div>
</div>
<div id="outline-container-orgd5ab328" class="outline-2">
<h2 id="orgd5ab328"><span class="section-number-2">6.</span> uEmacs</h2>
<div class="outline-text-2" id="text-6">

<div id="org68e110f" class="figure">
<p><img src="https://taingram.org/blog/files/uemacs.png" alt="uemacs.png" />
</p>
<p><span class="figure-number">Figure 6: </span>uEmacs built from source running in GNOME Terminal</p>
</div>
<ul class="org-ul">
<li><b>Repository</b>: <a href="https://git.kernel.org/pub/scm/editors/uemacs/uemacs.git/">https://git.kernel.org/pub/scm/editors/uemacs/uemacs.git/</a></li>
<li><b>License</b>: Shared source with non-commercial redistribution only</li>
<li><b>Depends on</b>: libc, curses or termcap</li>
</ul>

<p>
uEmacs is the personal editor of Linus Torvalds, creator of Linux and Git. It
is a fork of <a href="https://en.wikipedia.org/wiki/MicroEMACS">MicroEmacs</a> 3.9e that Torvalds has added number of improvements to
over the years. Most notably the addition of <b>UTF-8 support</b>.
</p>

<p>
It's unlikely there are many users outside of Torvalds. Its existence is not
well advertised and the license restrictions impede uEmacs from be packaged by
most Linux distros. Despite that, uEmacs is actively maintained, very small,
and supports UTF-8, so for those who need international language support it
could be a viable option.
</p>
</div>
</div>
<div id="outline-container-org2e8c944" class="outline-2">
<h2 id="org2e8c944"><span class="section-number-2">7.</span> GNU Emacs</h2>
<div class="outline-text-2" id="text-7">

<div id="org1442797" class="figure">
<p><img src="https://taingram.org/blog/files/gnu-emacs-nw.png" alt="gnu-emacs-nw.png" />
</p>
<p><span class="figure-number">Figure 7: </span>GNU Emacs (<code>emacs -nw -q --execute '(menu-bar-mode 0)'</code>)</p>
</div>

<p>
Now that you have seen the many options available for lightweight Emacs
lookalikes, its time to ask yourself why are you looking for an Emacs
replacement? Is it simply because Emacs starts to slow or just <i>"feels too
heavy"</i> for a quick edit. If you don't have a hardware constraint then why
limit yourself to an inferior editing experience when good ol' GNU Emacs could
work for you.
</p>

<p>
The following options could help to make Emacs feel snappier for that quick
edit:
</p>

<ul class="org-ul">
<li>Run Emacs without a config: <code>emacs -Q</code></li>
<li>Run Emacs with a shorter config: <code>emacs -Q -l ~/.emacs.d/quick.el</code></li>
<li>Run Emacs as a background daemon and edit using: <code>emacsclient</code></li>
<li>Run Emacs within the terminal: <code>emacs -nw</code> or <code>emacsclient -nw</code></li>
</ul>

<p>
Using any of these options or a combination can make GNU Emacs <i>feel</i> as fast
a lightweight editor. Alias these options to an easy to use command like <code>qe</code>:
</p>

<div class="org-src-container">
<pre class="src src-bash"><span class="org-builtin">alias</span> <span class="org-variable-name">qe</span>=<span class="org-string">'emacs -Q -nw -l ~/.emacs.d/quick.el'</span>
<span class="org-builtin">alias</span> <span class="org-variable-name">ec</span>=<span class="org-string">'emacsclient -nw'</span>
</pre>
</div>

<p>
If you want to use these options from graphical apps like your file manager
you can create a .desktop file with these options.
</p>
</div>
<div id="outline-container-org84b5ed1" class="outline-3">
<h3 id="org84b5ed1"><span class="section-number-3">7.1.</span> Remote Editing</h3>
<div class="outline-text-3" id="text-7-1">
<p>
Spare yourself from needed to use an editor on a remote system by using <a href="https://www.gnu.org/software/tramp/">TRAMP</a>
to edit remote files from within your local Emacs session. You can open a
remote file like any other file in Emacs with this special format:
</p>

<div class="org-src-container">
<pre class="src src-nil">C-x C-f /ssh:username@example.com:~/Documents/somefile.txt
</pre>
</div>
</div>
</div>
</div>
<div id="outline-container-orgf19d391" class="outline-2">
<h2 id="orgf19d391"><span class="section-number-2">8.</span> See Also</h2>
<div class="outline-text-2" id="text-8">
<ul class="org-ul">
<li><a href="https://opensource.com/article/20/3/lightweight-emacs">Getting started with lightweight alternatives to GNU Emacs</a>. <i>OpenSource.com</i></li>
<li><a href="https://www.w3.org/2001/06/utf-8-test/UTF-8-demo.html">UTF-8 Demo</a>. <i>www.w3.org</i></li>
</ul>
</div>
</div>
]]>
</description></item>
<item>
<title>Using an Org-mode README on SourceHut</title>
<link>https://taingram.org/blog/sourcehut-org-readme.html</link>
<pubDate>Wed, 12 Mar 2025 00:00:00 -0400</pubDate>
<guid>https://taingram.org/blog/sourcehut-org-readme.html</guid>
<description>
<![CDATA[<p>
<a href="https://sourcehut.org/">Sourcehut</a> is a fantastic development platform for free software
hackers.  It's fun to use and works well with good 'ol tools like git
and email.  I'm a paying member and I have been very happy with the
services.  The only rough spot I have with sourcehut is the insistence
on markdown as the only available markup language.
</p>

<p>
For some reason I've never really liked markdown.  The syntax never
clicked with me so I generally avoid it.  When I found Org mode, I
thought "this just makes sense, this is how I want plain text markup to
be."  If you are reading this you probably feel similar, so let's look
at some ways to utilize an Org README on sourcehut.
</p>

<p>
For a non-markdown README sourcehut gives us three main options:
</p>

<ol class="org-ol">
<li>Display your file as plain text.</li>
<li>Export your file to markdown.</li>
<li>Export your file to HTML and set it using the custom README options.</li>
</ol>
<div id="outline-container-orgb0d3c80" class="outline-2">
<h2 id="orgb0d3c80"><span class="section-number-2">1.</span> Display README.org in plain text</h2>
<div class="outline-text-2" id="text-1">
<ol class="org-ol">
<li>Rename your Org README.org as README and it will be displayed as
plain text on the Summary tab.</li>
<li>To allow programs to detect the file as Org you can
<ul class="org-ul">
<li>create a symbolic link <code>ln -s README README.org</code>,</li>
<li>or for Emacs set a file local variable <code>-*- mode: org-mode -*-</code>
on the first line.</li>
</ul></li>
</ol>

<p>
For most projects this should be sufficient, <a href="https://git.sr.ht/~taingram/org-readme/blob/master/README.org">Org is extremely readable
without any special rendering</a>.  For best readability avoid embedding
links inside of text paragraphs.
</p>
</div>
</div>
<div id="outline-container-org501957f" class="outline-2">
<h2 id="org501957f"><span class="section-number-2">2.</span> Export README.org to README.md</h2>
<div class="outline-text-2" id="text-2">
<p>
To enable markdown in the export menu you will need to add it to the
org-export-backends list from the customize menu or with:
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp">(add-to-list 'org-export-backends 'md)
</pre>
</div>

<p>
Now while visiting an Org file we can export it to markdown with C-c
C-e m m.  This can be done from the commandline with:
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp">emacs README.org --batch --eval '(org-md-export-to-markdown)'
</pre>
</div>

<p>
Commit the README.md to your repo and you'll get a nicely rendered
markdown file on the Summary tab.  This gives us the CSS, syntax
highlighting, and headline linking sourcehut provides by default
without needing to write markdown.
</p>

<p>
I recommend using this as a way to write-up a file in Org and then
upload it once.  Write the readme in Org, export it, commit the
markdown file, then throw out the Org file.  Trying to maintain two
separate README formats seems like a hassle.  Even if you automate the
process it will likely confuse contributors.
</p>
</div>
</div>
<div id="outline-container-org8983c88" class="outline-2">
<h2 id="org8983c88"><span class="section-number-2">3.</span> Export README.org to HTML and apply a custom README</h2>
<div class="outline-text-2" id="text-3">
<p>
Sourcehut provides functionality for <a href="https://man.sr.ht/git.sr.ht/#setting-a-custom-readme">setting your Summary tab to any
arbitrary HTML</a>.  You can do this easily with the <a href="https://sr.ht/~xenrox/hut/">hut</a> command.
</p>

<div class="org-src-container">
<pre class="src src-nil">hut git update --readme readme.html --repo https://git.sr.ht/~foo/bar
</pre>
</div>

<p>
So a simple process for this would be to occasionally export your
README to HTML (C-c C-e h h) and then manually upload it with hut.
That would work well for a project where the README is updated only
occasionally, and keeps the git tree free of extra files.
</p>

<div class="org-src-container">
<pre class="src src-sh">emacs README.org -Q --batch --eval <span class="org-string">"(require 'ox-html) (org-html-export-to-html nil nil nil t)"</span>
</pre>
</div>
</div>
<div id="outline-container-orgd8f5293" class="outline-3">
<h3 id="orgd8f5293"><span class="section-number-3">3.1.</span> Automatically export README to HTML and apply it</h3>
<div class="outline-text-3" id="text-3-1">
<p>
This process can be triggered automatically using the sourcehut builds
service <a href="https://man.sr.ht/builds.sr.ht/">builds.sr.ht</a>.<sup><a id="fnr.1" class="footref" href="#fn.1" role="doc-backlink">1</a></sup> The builds are automatically triggered
after each commit.  If you don't want them to run then push with <code>git
push -o skip-ci</code>.
</p>

<p>
The build system looks for a <code>.build.yml</code> file, or any <code>.yml</code> files in
the <code>.builds/</code> folder, and runs the specified tasks after receiving
new commits.  <a href="https://git.sr.ht/~taingram/org-readme">This repository</a> contains a <code>.builds/org-readme.yml</code>
manifest that can be copied into any other project to render an Org
README.
</p>

<div class="org-src-container">
<pre class="src src-yaml"><span class="org-variable-name">image</span>: debian/testing
<span class="org-variable-name">oauth</span>: git.sr.ht/REPOSITORIES:RW git.sr.ht/PROFILE:RO
<span class="org-variable-name">packages</span>:
  - hut
  - emacs
<span class="org-variable-name">sources</span>:
  - https://git.sr.ht/~taingram/org-readme
<span class="org-variable-name">environment</span>:
  <span class="org-variable-name">README</span>: README.org
<span class="org-variable-name">tasks</span>:
  - <span class="org-variable-name">export-readme</span>: |
      <span class="org-string">cd org-readme</span>
<span class="org-string">      emacs -Q --batch \
        --eval='(setq vc-handled-backends nil)' \
        --eval '(setq org-startup-folded nil)' \
        --eval '(setq org-element-cache-persistent nil)' \
        --eval "(require 'ox-html)" \
        --eval "(find-file \"$README\")" \
        --eval '(org-html-export-to-html nil nil nil t)'
      hut git update --readme $(basename "$README" .org).html</span>
</pre>
</div>

<p>
When using this manifest file ensure the following information has
been updated:
</p>
<dl class="org-dl">
<dt>sources</dt><dd>Your repository URL.</dd>
<dt>README</dt><dd>Your Org file to be exported if it is not named README.org.</dd>
<dt>cd org-readme</dt><dd>Your repository's directory name.</dd>
</dl>

<p>
Copy the file to your <code>.builds/</code> folder and it should work
automatically.  Note that sourchut will only run <a href="https://man.sr.ht/builds.sr.ht/#gitsrht">4 build manifests max</a>
per project.  If you have existing builds you can add this as a
separate task.
</p>
</div>
</div>
<div id="outline-container-org7efdb64" class="outline-3">
<h3 id="org7efdb64"><span class="section-number-3">3.2.</span> Examples</h3>
<div class="outline-text-3" id="text-3-2">
<ul class="org-ul">
<li><a href="https://git.sr.ht/~taingram/org-readme">See this example README on sourcehut</a>.</li>
<li>For a large example Org file see <a href="https://git.sr.ht/~taingram/emacs-init">my emacs init repository</a>.</li>
</ul>
</div>
</div>
</div>
<div id="outline-container-org955f2a6" class="outline-2">
<h2 id="org955f2a6">Conclusion</h2>
<div class="outline-text-2" id="text-org955f2a6">
<p>
The flexibility of the sourcehut build system is really neat.  I
probably would not have used it this way if Org had been supported
natively, so that's kind of cool.  I could see this being really neat
to automatically publish a website or generate a book directly from
your git repo.  I'm definitely looking forward to experimenting with
it for other non-code projects.
</p>
</div>
</div>
<div id="outline-container-orga228bc8" class="outline-2">
<h2 id="orga228bc8">See also</h2>
<div class="outline-text-2" id="text-orga228bc8">
<ul class="org-ul">
<li><a href="https://breatheoutbreathe.in/blog/2024-12-10-sourcehut-org-mode-readme.html">Render README.org as HTML on Sourcehut</a></li>
<li><a href="https://man.sr.ht/git.sr.ht/#setting-a-custom-readme">Setting a custom README - git.sr.ht docs</a></li>
</ul>
</div>
</div>
<div id="footnotes">
<h2 class="footnotes">Footnotes: </h2>
<div id="text-footnotes">

<div class="footdef"><sup><a id="fn.1" class="footnum" href="#fnr.1" role="doc-backlink">1</a></sup> <div class="footpara" role="doc-footnote"><p class="footpara">
If you are concerned about wasting build server resources to
render a readme please note this is the solution <a href="https://lists.sr.ht/~sircmpwn/sr.ht-discuss/%3C87cyib79ad.fsf@%3E">Drew DeVault has
actively recommended</a>.
</p></div></div>


</div>
</div>]]>
</description></item>
<item>
<title>Emacs Auto-Insert Default Text in New Files</title>
<link>https://taingram.org/blog/emacs-auto-insert.html</link>
<pubDate>Wed, 11 Jun 2025 00:00:00 -0400</pubDate>
<guid>https://taingram.org/blog/emacs-auto-insert.html</guid>
<description>
<![CDATA[<p>
I recently blogged about <a href="https://taingram.org/blog/intro-to-emacs-tempo.html">Emacs tempo-mode</a> and in that post I created
an example way to generate the header text commonly used in Emacs
Lisp.  While looking into Tempo I noticed this manual section <a href="https://www.gnu.org/software/emacs/manual/html_mono/autotype.html#Autoinserting">5
Autoinserting Text in Empty Files</a>, but I had not taken the time to
read through that section since I assumed I would still need to setup
some kind of template.
</p>

<p>
It turns out I was underestimating Emacs, because <code>auto-insert-mode</code>
includes this exact functionality.  It is built in to Emacs and
completely setup by default.  All you need to do is enable the mode:
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp">(auto-insert-mode)
</pre>
</div>

<p>
Now opening new elisp files will prompt us for auto-insertion and
insert the standard boilerplate heading.  Great!
</p>

<p>
If you use vertico or something similar you may get stuck in the
keywords prompt.  It will continue prompting you for options until you
hit M-RET to close the prompt.
</p>
<div id="outline-container-org9cd0f2c" class="outline-2">
<h2 id="org9cd0f2c"><span class="section-number-2">1.</span> Adding Defaults for other File Types</h2>
<div class="outline-text-2" id="text-1">
<p>
<code>auto-insert-mode</code> includes several default templates you can view in
the <code>auto-insert-alist</code> variable.  Defaults are included for elisp,
C/C++, TeX, Makefile, and HTML.  These provide good examples to build
your own settings.
</p>
</div>
<div id="outline-container-orgc5c5cf3" class="outline-3">
<h3 id="orgc5c5cf3"><span class="section-number-3">1.1.</span> A Simple Example</h3>
<div class="outline-text-3" id="text-1-1">
<p>
Below is an example of adding an extremely simple JavaScript template
using a <a href="https://www.gnu.org/software/emacs/manual/html_mono/autotype.html#Skeleton-Language">skeleton template</a>:
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp">(define-auto-insert 'js-mode
  '(nil
    <span class="org-string">"// Copyright "</span>
    (format-time-string <span class="org-string">"%Y"</span>) <span class="org-string">" "</span>
    (<span class="org-keyword">progn</span> user-full-name) \n \n
    <span class="org-string">"'use strict';"</span> \n
    _))
</pre>
</div>

<p>
The first <code>define-auto-insert</code> argument is the condition needed to
apply the template.  This can be written as <code>'CONDITION</code> or
<code>'(CONDITION . DESCRIPTION)</code>.  So we could replace <code>'js-mode</code> with
<code>'(js-mode . "JavaScript Header")</code> to be more verbose.  That may be
more useful when the condition is a regex.  See the default C/C++
header condition:
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp">(<span class="org-string">"\\.</span><span class="org-string"><span class="org-regexp-grouping-backslash">\\</span></span><span class="org-string"><span class="org-regexp-grouping-construct">(</span></span><span class="org-string">[Hh]</span><span class="org-string"><span class="org-regexp-grouping-backslash">\\</span></span><span class="org-string"><span class="org-regexp-grouping-construct">|</span></span><span class="org-string">hh</span><span class="org-string"><span class="org-regexp-grouping-backslash">\\</span></span><span class="org-string"><span class="org-regexp-grouping-construct">|</span></span><span class="org-string">hpp</span><span class="org-string"><span class="org-regexp-grouping-backslash">\\</span></span><span class="org-string"><span class="org-regexp-grouping-construct">|</span></span><span class="org-string">hxx</span><span class="org-string"><span class="org-regexp-grouping-backslash">\\</span></span><span class="org-string"><span class="org-regexp-grouping-construct">|</span></span><span class="org-string">h\\+\\+</span><span class="org-string"><span class="org-regexp-grouping-backslash">\\</span></span><span class="org-string"><span class="org-regexp-grouping-construct">)</span></span><span class="org-string">\\'"</span> . <span class="org-string">"C / C++ header"</span>)
</pre>
</div>

<p>
The second argument is the template to be applied.  This is very
flexible as it can be a skeleton, filename, or a function.  In this
case it is a skeleton template, which is another templating system
built into emacs.
</p>

<p>
Note the first element of skeletons is what is called the
"interactor", which decides whether the template is interactive.  It
can be a text prompt like used in the default Emacs Lisp <code>"Short
description: "</code> auto-insert setting.  In my example I do not need
interactivity so I set the first parameter to <code>nil</code>.
</p>

<p>
For more details on emacs skeletons see the <a href="https://www.gnu.org/software/emacs/manual/html_mono/autotype.html#Skeleton-Language">manual section</a> and the
<code>skeleton-insert</code> function.
</p>
</div>
</div>
<div id="outline-container-orgbd99932" class="outline-3">
<h3 id="orgbd99932"><span class="section-number-3">1.2.</span> Using Tempo Templates</h3>
<div class="outline-text-3" id="text-1-2">
<p>
I find skeleton templates a little more confusing than tempo.  Since
tempo generates a function we can define a tempo template and use that
function instead.
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp">(tempo-define-template <span class="org-string">"js-header"</span>
                       `(<span class="org-string">"// Copyright "</span>
                         (format-time-string <span class="org-string">"%Y"</span>) <span class="org-string">" "</span> user-full-name n n
                        <span class="org-string">"'use strict';"</span> n n %)
                       nil
                       <span class="org-string">"Insert JavaScript header"</span>)
</pre>
</div>

<p>
This will generate the function <code>tempo-template-js-header</code> which we
can add as an auto-insert condition:
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp">(define-auto-insert 'js-mode  #'tempo-template-js-header)
</pre>
</div>
</div>
</div>
</div>
]]>
</description></item>
<item>
<title>Getting Started with Watchy</title>
<link>https://taingram.org/blog/getting-started-with-watchy.html</link>
<pubDate>Thu, 21 Oct 2021 00:00:00 -0400</pubDate>
<guid>https://taingram.org/blog/getting-started-with-watchy.html</guid>
<description>
<![CDATA[<p>
I've recently received my <a href="https://www.crowdsupply.com/sqfmi/watchy">Watchy</a>, an open source E-Ink watch, and have
just started to crack the surface of what can be done with the
device. This post outlines how to get going with Watchy from the
perspective of someone who has done very little with Arduino and
hardware programming.
</p>

<p>
Tested on Debian Sid, steps should be similar across
distributions. Recently moved to Fedora and will be testing shortly.
</p>
<div id="outline-container-orga95602e" class="outline-2">
<h2 id="orga95602e"><span class="section-number-2">1.</span> Setup</h2>
<div class="outline-text-2" id="text-1">
<p>
On Debian install the following:
</p>

<div class="org-src-container">
<pre class="src src-bash">sudo apt install arduino python3-pyserial
</pre>
</div>

<p>
To access the serial connection necessary for uploading to your device
you'll need to add yourself to the <code>dialout</code> group.
</p>

<div class="org-src-container">
<pre class="src src-sh">sudo adduser $<span class="org-variable-name">USER</span> dialout
</pre>
</div>

<p>
You will need to log out and back in for the change to take full
effect. You can check whether you are in the <code>dialout</code> group with:
</p>
<div class="org-src-container">
<pre class="src src-sh">groups $<span class="org-variable-name">USER</span>
</pre>
</div>
</div>
<div id="outline-container-org609dee8" class="outline-3">
<h3 id="org609dee8"><span class="section-number-3">1.1.</span> Arduino Setup</h3>
<div class="outline-text-3" id="text-1-1">
<p>
With Arduino IDE open there is some hardware setup and libraries that
still need to be setup.  The following steps are outlined in the
<a href="https://github.com/sqfmi/Watchy">Watchy README.md</a>.
</p>

<ol class="org-ol">
<li>Add <a href="https://github.com/espressif/arduino-esp32/blob/master/docs/arduino-ide/boards_manager.md">ESP32 Boards</a>
<ol class="org-ol">
<li><b>File</b> &gt;&gt; <b>Preferences</b></li>
<li>In <b>Additional Boards Manager URLs</b> paste in
<a href="https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json">https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json</a></li>
</ol></li>

<li>Import the Watchy Library
<ol class="org-ol">
<li><b>Tools</b> &gt;&gt; <b>Manage Libraries</b></li>
<li>Search Watchy click install
<img src="https://taingram.org/blog/files/arduino-watchy-library.png" alt="arduino-watchy-library.png" /></li>
</ol></li>

<li>Hardware Settings
<ol class="org-ol">
<li>Set Board to "ESP32 Dev Module"
<b>Tools</b> &gt;&gt; <b>Board</b> &gt;&gt; <b>ESP32 Arduino</b> &gt;&gt; <b>ESP32 Dev Module</b></li>

<li>Set Partition Scheme to "Minimal SPIFFS"
<b>Tools</b> &gt;&gt; <b>Partition Scheme</b> &gt;&gt; <b>Minimal SPIFFS</b></li>
</ol></li>
</ol>
</div>
</div>
</div>
<div id="outline-container-org193d275" class="outline-2">
<h2 id="org193d275"><span class="section-number-2">2.</span> Getting Started</h2>
<div class="outline-text-2" id="text-2">
<p>
With the setup complete you should be all set to get started working
on a watch face. The Watchy library provides a number of example faces
from which you can use as a basis for your own.  Open an example watch
face <b>File</b> &gt;&gt; <b>Watchy</b> &gt;&gt; <b>WatchFaces</b>.  So far I've found <code>7_SEG</code> to be a
good starter for learning, but you should feel free to try out all
options.
</p>

<p>
A basic change you can make to see if things are working is to swap
the <code>7_SEG</code> color scheme by changing line 3 of <code>Watchy_7_SEG.cpp</code> to
false.
</p>

<div class="org-src-container">
<pre class="src src-C"><span class="org-preprocessor">#define</span> <span class="org-variable-name">DARKMODE</span> <span class="org-constant">false</span>
</pre>
</div>

<p>
Then verify your project with the Check ✓ icon.  If it succeeds plug
in your Watchy to your computer via USB and click Upload.  You'll
likely need to confirm your device (something like <code>/dev/ttyUSB0</code> on
Linux), then after a few seconds you should see your watchface invert
colors.
</p>
</div>
</div>
<div id="outline-container-org0c5eb45" class="outline-2">
<h2 id="org0c5eb45"><span class="section-number-2">3.</span> Issues</h2>
<div class="outline-text-2" id="text-3">
<p>
I had an issue while building the watchface in Arduino where <code>python</code>
could not be found because Debian testing does not currently have a
<code>python</code> symlink. I had python3 installed so I added one as follows:
</p>

<div class="org-src-container">
<pre class="src src-bash">ln -s /bin/python3 ~/bin/python
</pre>
</div>

<p>
~/bin= the default location for user scripts in Debian's bash
<code>.profile</code>. It will automatically add this directory to the path if it
exists so no additional configuration is needed.  However, if you had
to create this directory you may need to log out and back in for it to
take full effect.
</p>

<p>
For other distros you may need to add <code>~/bin</code> to your <code>.profile</code> or
<code>.bash_profile</code>
</p>

<div class="org-src-container">
<pre class="src src-bash"><span class="org-comment-delimiter"># </span><span class="org-comment">set PATH so it includes user's private bin if it exists
</span><span class="org-keyword">if</span> [ -d <span class="org-string">"$HOME/bin"</span> ] ; <span class="org-keyword">then</span>
    <span class="org-variable-name">PATH</span>=<span class="org-string">"$HOME/bin:$PATH"</span>
<span class="org-keyword">fi</span>
</pre>
</div>
</div>
</div>
<div id="outline-container-org5544f57" class="outline-2">
<h2 id="org5544f57"><span class="section-number-2">4.</span> Updates</h2>
<div class="outline-text-2" id="text-4">
<p>
Watchy is a neat little toy and it's crazy you can pack this much
stuff in for $50 USD.  Although, I would have preferred something more
expensive if that meant it was a more polished product.  As someone
who is not <i>that</i> interested with tinkering with electronics I found
the overall package too clunky to actually use and wear.
</p>

<p>
The final nail in the coffin was when, within my first couple weeks of
use, I accidentally snapped one of the plastic buttons
(<a href="https://www.lcsc.com/product-detail/Tactile-Switches_Korean-Hroparts-Elec-K2-1114SA-A4SW-06_C136662.html">K2-1114SA-A4SW-06</a>).  I just don't have enough enthusiasm about the
device to go through the hassle of repairing that.
</p>
</div>
</div>
]]>
</description></item>
<item>
<title>Setup Emacs for JavaScript Development with LSP</title>
<link>https://taingram.org/blog/emacs-javascript-lsp.html</link>
<pubDate>Fri, 30 May 2025 00:00:00 -0400</pubDate>
<guid>https://taingram.org/blog/emacs-javascript-lsp.html</guid>
<description>
<![CDATA[<p>
Recently I've been toying with JavaScript so I wanted to see if I
could get a good development environment working inside Emacs.  The
adoption of the Language Server Protocol LSP has streamlined a lot of
this process in 2025.  What used to require lots of custom elisp code
(see js2-mode) can now be handled with generic Emacs packages and a
good Language Sever.
</p>
<div id="outline-container-org4cea520" class="outline-2">
<h2 id="org4cea520"><span class="section-number-2">1.</span> Installing a JavaScript Language Server (LSP)</h2>
<div class="outline-text-2" id="text-1">
<p>
According to the internet the best JavaScript language server is the
<a href="https://github.com/typescript-language-server/typescript-language-server">TypeScript Language Server</a>.  This language server can also be used for
vanilla JavaScript development as well.
</p>
</div>
<div id="outline-container-org1b43f7f" class="outline-3">
<h3 id="org1b43f7f"><span class="section-number-3">1.1.</span> Installing via NPM</h3>
<div class="outline-text-3" id="text-1-1">
<p>
Currently the TypeScript Language Server is not packaged in Debian so
you have to install it via the node package manager NPM.  I am not
that familiar with NPM, but online instructions told me I should use
<code>sudo npm install -g</code> to install it globally with root.  I think this
is a bad security practice, so I am just going to install it locally
in my home directory where it can do <i>less</i> damage.
</p>

<p>
<a href="https://yourlabs.org/posts/2020-02-05-npm-install-g-home-local/">This article by James Pic</a> provides a workaround that advises NPM to
install programs in your home directory instead.  All you have to do
is add the following variables to your <code>~/.bashrc</code>
</p>

<div class="org-src-container">
<pre class="src src-sh"><span class="org-builtin">export</span> <span class="org-variable-name">PATH</span>=$<span class="org-variable-name">HOME</span>/.local/bin:$<span class="org-variable-name">PATH</span>
<span class="org-builtin">export</span> <span class="org-variable-name">NODE_PATH</span>=$<span class="org-variable-name">HOME</span>/.local/lib/node_modules:$<span class="org-variable-name">NODE_PATH</span>
<span class="org-builtin">export</span> <span class="org-variable-name">npm_config_prefix</span>=$<span class="org-variable-name">HOME</span>/.local
</pre>
</div>

<p>
Apply those settings to your running shell with:
</p>

<div class="org-src-container">
<pre class="src src-sh"><span class="org-builtin">source</span> ~/.bashrc
</pre>
</div>

<p>
Now we can install the Typescript Language Server with:
</p>

<div class="org-src-container">
<pre class="src src-sh">npm install -g typescript-language-server typescript
</pre>
</div>

<p>
You may need to log out and back in for Emacs to recognize the
executable typescript-language-server is available in your path under
<code>~/.local/bin</code>.
</p>
</div>
</div>
</div>
<div id="outline-container-orgde6edcd" class="outline-2">
<h2 id="orgde6edcd"><span class="section-number-2">2.</span> Emacs Setup</h2>
<div class="outline-text-2" id="text-2">
<p>
Open a JavaScript file, run M-x <code>eglot</code>, and it should work out of the
box.  For some additional tweaks below is a minimal Emacs config.
Checkout my <a href="https://taingram.org/init.html">complete init file</a> to see my actual settings.
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp"><span class="org-comment-delimiter">;; </span><span class="org-comment">Emacs LSP Client (built into Emacs 29.1)
</span>(<span class="org-keyword">use-package</span> eglot
  <span class="org-builtin">:ensure</span> t)

<span class="org-comment-delimiter">;; </span><span class="org-comment">Optional, can run M-x eglot to start LSP manually
</span>(<span class="org-keyword">use-package</span> js-mode
  <span class="org-builtin">:hook</span> ((js-mode . subword-mode)
         (js-mode . electric-pair-mode)
         (js-mode . eglot-ensure)
         (js-mode . completion-preview-mode)))

<span class="org-comment-delimiter">;; </span><span class="org-comment">Drop-down completions
</span>(<span class="org-keyword">use-package</span> corfu
  <span class="org-builtin">:ensure</span> t
  <span class="org-builtin">:hook</span> ((prog-mode . corfu-mode)))

<span class="org-comment-delimiter">;; </span><span class="org-comment">Add bindings for navigating to next/previous error
</span>(<span class="org-keyword">use-package</span> flymake
  <span class="org-builtin">:bind</span> (<span class="org-builtin">:map</span> prog-mode-map
              (<span class="org-string">"M-n"</span> . flymake-goto-next-error)
              (<span class="org-string">"M-p"</span> . flymake-goto-prev-error)))
</pre>
</div>

<p>
<a href="https://github.com/minad/corfu">Corfu</a> is an optional package that will make completions appear as a
drop-down menu, similar to a programming integrated development
environment IDE.  Start typing something then type 'M-TAB' to trigger
the completion drop-down.  This can be triggered automatically but I
find that distracting.
</p>
</div>
</div>
<div id="outline-container-orgce627c4" class="outline-2">
<h2 id="orgce627c4"><span class="section-number-2">3.</span> Things I Still Need to Figure Out</h2>
<div class="outline-text-2" id="text-3">
<p>
This setup has given me the basic editing environment I wanted with
drop-down completions, error checking, and documentation at point.
Although there are still some additional enhancements I am hoping to
add.
</p>
</div>
<div id="outline-container-org3679934" class="outline-3">
<h3 id="org3679934"><span class="section-number-3">3.1.</span> <span class="todo TODO">TODO</span> Search for Documentation</h3>
<div class="outline-text-3" id="text-3-1">
<p>
Eldoc will show documentation for a function/variable when it is
written in full which is helpful.  The issue is I often don't know
exactly what I am looking for.  Ideally I need a way to search for
<i>potential matches</i> and review all their reference info.  The
documentation is in the server so I just need a way to get it out&#x2026;
</p>
</div>
</div>
<div id="outline-container-orgd071801" class="outline-3">
<h3 id="orgd071801"><span class="section-number-3">3.2.</span> <span class="todo TODO">TODO</span> Live Editing A Web Page</h3>
<div class="outline-text-3" id="text-3-2">
<p>
Right now I am editing scripts and refreshing the browser manually to
test.  I need to streamline that process.  I see there is an
interesting <a href="https://elpa.gnu.org/packages/firefox-javascript-repl.html">firefox-javascript-repl</a> package.
</p>
</div>
</div>
</div>
<div id="outline-container-org071bc34" class="outline-2">
<h2 id="org071bc34"><span class="section-number-2">4.</span> Conclusion</h2>
<div class="outline-text-2" id="text-4">
<p>
So far things are basically working as expected.  I am actually really
enjoying learning JavaScript.  The post ES6 language spec is pretty
fun to work with.  I highly recommend <a href="https://javascript.info/">javascript.info</a> to get up to
speed quickly on modern JavaScript.
</p>

<p>
Expect to see more posts about web development.  I am looking forward
to adding some interactivity to my website and working on some other
web-based projects.  Don't worry though, my website will always work
great without JavaScript.  It has to look good in <a href="https://www.gnu.org/software/emacs/manual/html_mono/eww.html">eww</a> after all.
</p>
</div>
</div>
<div id="outline-container-org6fda993" class="outline-2">
<h2 id="org6fda993"><span class="section-number-2">5.</span> See Also</h2>
<div class="outline-text-2" id="text-5">
<ul class="org-ul">
<li><a href="https://yourlabs.org/posts/2020-02-05-npm-install-g-home-local/">Use npm install -g in ~/.local non-root</a> by James Pic for
<i>yourlabs.org</i></li>
</ul>
</div>
<div id="outline-container-orgbbf71b8" class="outline-3">
<h3 id="orgbbf71b8"><span class="section-number-3">5.1.</span> JavaScript Learning Resources</h3>
<div class="outline-text-3" id="text-5-1">
<ul class="org-ul">
<li><a href="https://javascript.info/">The Modern JavaScript Tutorial</a> <i>javascript.info</i></li>
<li><a href="https://developer.mozilla.org/en-US/">Mozilla Developer Network MDN</a>  <i>developer.mozilla.org</i></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript">MDN JavaScript</a> <i>developer.mozilla.org</i></li>
</ul>
</div>
</div>
</div>
]]>
</description></item>
<item>
<title>Building Your Own Emacs IDE with LSP</title>
<link>https://taingram.org/blog/emacs-lsp-ide.html</link>
<pubDate>Thu, 17 Jun 2021 00:00:00 -0400</pubDate>
<guid>https://taingram.org/blog/emacs-lsp-ide.html</guid>
<description>
<![CDATA[<p>
When it comes to programming there is a lot of options around how you choose to
code. None is perhaps as personal as your <a href="https://en.wikipedia.org/wiki/Comparison_of_text_editors">choice of editor</a>. Among editors Emacs
is one that has stood the test of time and continued to grow in its capabilities
throughout the over 30 years it has existed. It is a tool that can last with you
for a <a href="https://www.youtube.com/watch?v=VADudzQGvU8">lifetime</a>. However, Emacs does have limitations when compared to the power
offered by a language specific integrated development environment (IDE). For
Emacs to be able to provide such language specific features requires an in-depth
understanding of every programming language it is working with. That means that
each programming language needs its own set of plugins, duplicating effort
across languages and also editors.
</p>
<div id="outline-container-org2abc43d" class="outline-2">
<h2 id="org2abc43d"><span class="section-number-2">1.</span> Enter the Language Protocol Server</h2>
<div class="outline-text-2" id="text-1">
<p>
The <a href="https://microsoft.github.io/language-server-protocol/">Language Server Protocol (LSP)</a> is an open standard that strives to solve
this redundancy. Developed by Microsoft for Visual Studio Code editor, it
works by creating a standard communication method for your editor to talk
directly with programming tools. Allowing for features like auto complete,
jump to definition, find all references, lookup documentation, and error
warnings. This reduces wasted work as an editor needs only to implement an LSP
plugin to support all programming languages.
</p>
</div>
<div id="outline-container-org7df731a" class="outline-3">
<h3 id="org7df731a"><span class="section-number-3">1.1.</span> LSP and Emacs</h3>
<div class="outline-text-3" id="text-1-1">
<p>
With Emacs being the <a href="https://www.gnu.org/software/emacs/">"extensible, customizable, free/libre text editor,"</a>
there have always been ways to get IDE-like features in Emacs. LSP
differentiates itself by requiring less heavy lifting from Emacs, and current
Emacs LSP implementation take advantage of many built-in features and well
established Emacs packages<sup><a id="fnr.1" class="footref" href="#fn.1" role="doc-backlink">1</a></sup>.
</p>

<table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">


<colgroup>
<col  class="org-left" />

<col  class="org-left" />

<col  class="org-left" />
</colgroup>
<thead>
<tr>
<th scope="col" class="org-left">Feature</th>
<th scope="col" class="org-left">Package</th>
<th scope="col" class="org-left">Issues in the past</th>
</tr>
</thead>
<tbody>
<tr>
<td class="org-left">syntax checking</td>
<td class="org-left">flymake</td>
<td class="org-left">limited language support</td>
</tr>

<tr>
<td class="org-left">jump to definition</td>
<td class="org-left">xref</td>
<td class="org-left">requires generating tags</td>
</tr>

<tr>
<td class="org-left">auto completion</td>
<td class="org-left">company*</td>
<td class="org-left">needs back-ends for every language</td>
</tr>

<tr>
<td class="org-left">argument suggestion</td>
<td class="org-left">eldoc</td>
<td class="org-left">needs packages for other languages</td>
</tr>
</tbody>
</table>

<p>
&lowast; = must be installed from ELPA (the official Emacs package repository).
</p>

<p>
The benefits of this is you can simplify your Emacs configuration and use
fewer external packages. In fact the development of the LSP has spurred on
development in several existing Emacs features like flymake and the built in
json decoder added in Emacs 27.
</p>
</div>
</div>
<div id="outline-container-orgb23c2b3" class="outline-3">
<h3 id="orgb23c2b3"><span class="section-number-3">1.2.</span> Emacs LSP Client Implementations</h3>
<div class="outline-text-3" id="text-1-2">
<p>
In LSP terms you have a language specific server that runs in the background
and a client that connects to it from your chosen editor. For Emacs LSP
clients there are two competing packages, both attempt to support as many LSP
features as possible.
</p>

<ul class="org-ul">
<li><b><a href="https://github.com/joaotavora/eglot">Eglot</a></b> has a focus on minimalism, performance, and has the added benefit
it <i>could</i> one day be included into Emacs<sup><a id="fnr.2" class="footref" href="#fn.2" role="doc-backlink">2</a></sup>. For that reason it is also
already included in the official Emacs package archive ELPA.</li>

<li><b><a href="https://github.com/emacs-lsp/lsp-mode">lsp-mode</a></b> targets universal support of as many additional features and
packages possible. There are a large number of lsp-mode extensions
providing additional features. Most packages beginning with "lsp-" are
lsp-mode specific and will not work with eglot. lsp-mode also has a
dap-mode package allowing it to work with debuggers that support the Debug
Adapter Protocol.</li>
</ul>

<p>
Today we will be using lsp-mode as it is slightly easier setup and is
currently has more active development.
</p>
</div>
</div>
</div>
<div id="outline-container-orgf6b3ab8" class="outline-2">
<h2 id="orgf6b3ab8"><span class="section-number-2">2.</span> Installation</h2>
<div class="outline-text-2" id="text-2">
<p>
The easiest way to install lsp-mode is through the built in Emacs package
manager. First we need to add <a href="https://melpa.org/">MELPA</a>, a community maintained Emacs package
repository, by adding the following to your <a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Init-File.html">init file</a>:
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp">(<span class="org-keyword">require</span> '<span class="org-constant">package</span>)
(add-to-list 'package-archives '(<span class="org-string">"melpa"</span> . <span class="org-string">"https://melpa.org/packages/"</span>))
(package-initialize)
</pre>
</div>

<p>
Then refresh your package list by typing<sup><a id="fnr.3" class="footref" href="#fn.3" role="doc-backlink">3</a></sup>:
</p>

<p>
<code>M</code>-<code>x</code> <code>package-refresh-contents</code>
</p>

<p>
Now we can install with:
</p>

<p>
<code>M</code>-<code>x</code> <code>package-install</code> <code>RET</code> <code>lsp-mode</code>
</p>

<p>
I wanted drop down auto-completion so I installed <a href="https://company-mode.github.io/">company</a> as well:
</p>

<p>
<code>M</code>-<code>x</code> <code>package-install</code> <code>RET</code> <code>company</code>
</p>
</div>
<div id="outline-container-orgc7a4dd8" class="outline-3">
<h3 id="orgc7a4dd8"><span class="section-number-3">2.1.</span> Configuration</h3>
<div class="outline-text-3" id="text-2-1">
<p>
Here is a very minimal configuration with lsp-mode with company, add it to
your init file as well:
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp">(<span class="org-keyword">require</span> '<span class="org-constant">lsp-mode</span>)

<span class="org-comment-delimiter">;; </span><span class="org-comment">Start lsp when you open a file for each langauge
</span>(add-hook 'python-mode-hook #'lsp)
(add-hook 'go-mode-hook     #'lsp)
<span class="org-comment-delimiter">;; </span><span class="org-comment">Add more languages as needed</span>
</pre>
</div>

<p>
lsp-mode will handle starting all the other <a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Minor-Modes.html">minor modes</a> necessary. One tweak
to the defaults I made is changing the amount of documentation lsp-mode shows
when your cursor rests on a function.
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp"><span class="org-comment-delimiter">;; </span><span class="org-comment">Show all documenttion
</span>(<span class="org-keyword">setq</span> lsp-eldoc-render-all t)
</pre>
</div>
</div>
<div id="outline-container-orge034eaf" class="outline-4">
<h4 id="orge034eaf"><span class="section-number-4">2.1.1.</span> use-package</h4>
<div class="outline-text-4" id="text-2-1-1">
<p>
If you are using <a href="https://github.com/jwiegley/use-package">use-package</a>, which can help simplify package configuration,
check out the <a href="https://github.com/emacs-lsp/lsp-mode/blob/master/README.org#use-package">example configuration listed in lsp-mode's readme</a>.
</p>
</div>
</div>
</div>
<div id="outline-container-org258a7d7" class="outline-3">
<h3 id="org258a7d7"><span class="section-number-3">2.2.</span> Installing Language Servers</h3>
<div class="outline-text-3" id="text-2-2">
<p>
A language server is the brains behind all of the LSP features we have
discussed, your experience will only be as good as the server you use. It is
important to highlight that the LSP is a relatively new technology and not
every programming language has a robust server implement just yet.
</p>

<p>
lsp-mode maintains <a href="https://github.com/emacs-lsp/lsp-mode#supported-languages">a list of supportted language servers</a> that should work
automatically. More language servers can be found on <a href="https://langserver.org/">langserver.org</a>. Two I
have experimented with are <a href="https://github.com/golang/tools/tree/master/gopls">gopls</a> and <a href="https://github.com/palantir/python-language-server">pyls</a> for GoLang and Python
respectively. A nice feature of these particular language servers is they can
be installed using their language specific package tools. For example, gopls
is installed with:
</p>

<div class="org-src-container">
<pre class="src src-bash">go get golang.org/x/tools/gopls@latest
</pre>
</div>

<p>
and pyls with:
</p>

<div class="org-src-container">
<pre class="src src-bash">pip install &#8216;python-language-server[all]&#8217;
</pre>
</div>

<p>
Make sure that wherever your language server is installed it is reachable
from your <b>$PATH</b>. You can test this by running the language server command,
for most servers it should run and do nothing. Just make sure you don't get
<code>bash: gopls: command not found...</code>
</p>
</div>
</div>
</div>
<div id="outline-container-org7e67eb9" class="outline-2">
<h2 id="org7e67eb9"><span class="section-number-2">3.</span> Using LSP</h2>
<div class="outline-text-2" id="text-3">
<p>
Once you've got your language server open any file on one of your projects and
you will be greeted with the following message:
</p>

<div class="org-src-container">
<pre class="src src-nil">foo.py is not part of any project. Select action:

i==&gt;Import project root /home/name/Projects/FooBar/.
I==&gt;Import project by selecting root directory interactively.
d==&gt;Do not ask for the current project by adding /home/name/Projects/FooBar/. to lsp-session-folders-blacklist.
D==&gt;Do not ask again for current project by selecting ignore path interactively.
n==&gt;Do nothing: ask again when opening other files from the current project.
</pre>
</div>

<p>
The options should be pretty self explanatory, use <b>i</b> if the given root is
correct, <b>I</b> if the root needs to be adjusted (e.g. you are in a
subdirectory). You should only use <b>d</b> and <b>D</b> for project you do not wish to
use lsp-mode's project management features.
</p>

<p>
Now you are good to code. lsp-mode will have automatically started the
necessary modes:
</p>

<ul class="org-ul">
<li><b>company</b> will provide auto complete suggestions,</li>
<li><b>flymake</b> will highlight warnings and errors,</li>
<li><b>xref</b> can find the definition of a function or variable, and</li>
<li><b>eldoc</b> will show function documentation in the <a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Minibuffer.html">minibuffer</a>.</li>
</ul>

<p>
By default <code>M</code>-<code>.</code> will jump to definition of a highlighted
function or variable.
</p>
</div>
<div id="outline-container-org24077b4" class="outline-3">
<h3 id="org24077b4"><span class="section-number-3">3.1.</span> Screenshots</h3>
<div class="outline-text-3" id="text-3-1">

<div id="orgca2d500" class="figure">
<p><img src="https://taingram.org/blog/files/eglot-company.png" alt="eglot-company.png" />
</p>
<p><span class="figure-number">Figure 1: </span>Showing company auto complete suggestions (actually eglot, but lsp-mode would look identical)</p>
</div>


<div id="org235b88c" class="figure">
<p><img src="https://taingram.org/blog/files/lsp-eldoc.gif" alt="lsp-eldoc.gif" />
</p>
<p><span class="figure-number">Figure 2: </span>Showing function documentation with eldoc</p>
</div>


<div id="org54863e4" class="figure">
<p><img src="https://taingram.org/blog/files/lsp-eldoc-hover.png" alt="lsp-eldoc-hover.png" />
</p>
<p><span class="figure-number">Figure 3: </span>Showing function documentation on mouse hover with eldoc</p>
</div>
</div>
</div>
</div>
<div id="outline-container-org96a6c60" class="outline-2">
<h2 id="org96a6c60"><span class="section-number-2">4.</span> Conclusion</h2>
<div class="outline-text-2" id="text-4">
<p>
Overall with this basic LSP setup and a few other packages (<a href="https://magit.vc/">magit</a>, <a href="https://github.com/joaotavora/yasnippet">yasnippets</a>,
<a href="https://github.com/Fuco1/smartparens">smartparens</a>, and <a href="https://emacs-helm.github.io/helm/">helm</a>) is enough for me to have a comfortable editing
experience with some niceties of an IDE. In the future I'd like to try out
Java development using <a href="https://github.com/eclipse/eclipse.jdt.ls">Eclipse's Java language server</a>, as well compare pyls
with the <a href="https://github.com/Microsoft/python-language-server">Microsoft Python language server</a>.
</p>

<p>
For someone that would like to take this idea further I would suggest you look
into some of the additional lsp-mode packages (<a href="https://github.com/emacs-lsp/lsp-ui">lsp-ui</a>, <a href="https://github.com/tigersoldier/company-lsp">company-lsp</a>,
<a href="https://github.com/emacs-lsp/lsp-treemacs">lsp-treemacs</a>, etc.). Also, you could explore making Emacs look more like a
modern editor with <a href="https://emacsthemes.com/">a nice theme</a>, <a href="https://github.com/milkypostman/powerline">powerline</a>, <a href="https://github.com/jaypei/emacs-neotree">NeoTree</a>, and <a href="https://github.com/domtronn/all-the-icons.el">all-the-icons.el</a>.
</p>
</div>
</div>
<div id="outline-container-org7d1070e" class="outline-2">
<h2 id="org7d1070e"><span class="section-number-2">5.</span> Possible Issues and Solutions</h2>
<div class="outline-text-2" id="text-5">
</div>
<div id="outline-container-org68727f5" class="outline-3">
<h3 id="org68727f5"><span class="section-number-3">5.1.</span> Performance</h3>
<div class="outline-text-3" id="text-5-1">
<p>
I have not had any issues with performance on my machine using GNU Emacs 26.3
with the default setting, however, if issues occur there are <a href="https://github.com/emacs-lsp/lsp-mode#performance">several steps
you can take to increase performance</a>.
</p>

<p>
Increasing memory limits for Emacs garbage collector and maximum data output
read from a process:
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp"><span class="org-comment-delimiter">;; </span><span class="org-comment">Increase garbage collector threshold
</span>(<span class="org-keyword">setq</span> gc-cons-threshold 100000000) <span class="org-comment-delimiter">;; </span><span class="org-comment">100 MB
</span>
<span class="org-comment-delimiter">;; </span><span class="org-comment">Increase amount of data read from a process
</span>(<span class="org-keyword">setq</span> read-process-output-max (* 1024 1024)) <span class="org-comment-delimiter">;; </span><span class="org-comment">1 MB</span>
</pre>
</div>

<p>
Using an up-to-date Emacs version can work wonders as Emacs 27 has a native
json parser which is reported to be "~15 times" faster than previous
versions.
</p>
</div>
</div>
<div id="outline-container-orgeb68576" class="outline-3">
<h3 id="orgeb68576"><span class="section-number-3">5.2.</span> flymake vs flycheck</h3>
<div class="outline-text-3" id="text-5-2">
<p>
Another issue you may be facing is with flymake, flymake is currently
undergoing a rewrite to better support modern things like the LSP. Some of
that rewrite has made it into Emacs 26 and some is still to come in 27. If
you are using an older Emacs version, or having other issues you could
install flycheck a popular third-party alternative to flymake.
</p>

<p>
If you are using flymake on the latest Emacs version consider <a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Bugs.html">filing a bug
report</a> to help with its development.
</p>
</div>
</div>
</div>
<div id="outline-container-org1c10324" class="outline-2">
<h2 id="org1c10324"><span class="section-number-2">6.</span> Full Configuration Example</h2>
<div class="outline-text-2" id="text-6">
<div class="org-src-container">
<pre class="src src-emacs-lisp"><span class="org-comment-delimiter">;;; </span><span class="org-comment">A minimal config for using lsp-mode
</span>
<span class="org-comment-delimiter">;; </span><span class="org-comment">Packages
</span>(<span class="org-keyword">require</span> '<span class="org-constant">package</span>)
(add-to-list 'package-archives '(<span class="org-string">"melpa"</span> . <span class="org-string">"https://melpa.org/packages/"</span>))
(package-initialize)

<span class="org-comment-delimiter">;; </span><span class="org-comment">LSP
</span>(<span class="org-keyword">setq</span> lsp-keymap-prefix <span class="org-string">"C-c l"</span>)

(<span class="org-keyword">require</span> '<span class="org-constant">lsp-mode</span>)
<span class="org-comment-delimiter">;; </span><span class="org-comment">Start lsp-mode with desired languages
</span>(add-hook 'python-mode-hook #'lsp)
(add-hook 'go-mode-hook     #'lsp)
<span class="org-comment-delimiter">;; </span><span class="org-comment">Add more as needed
</span>
(<span class="org-keyword">setq</span> lsp-eldoc-render-all t)

<span class="org-comment-delimiter">;; </span><span class="org-comment">Drop-down auto completion
</span>(<span class="org-keyword">require</span> '<span class="org-constant">company</span>)
(add-hook 'after-init-hook 'global-company-mode)
</pre>
</div>
</div>
</div>
<div id="footnotes">
<h2 class="footnotes">Footnotes: </h2>
<div id="text-footnotes">

<div class="footdef"><sup><a id="fn.1" class="footnum" href="#fnr.1" role="doc-backlink">1</a></sup> <div class="footpara" role="doc-footnote"><p class="footpara">
In Emacs a package is like a plugin in other editors.
</p></div></div>

<div class="footdef"><sup><a id="fn.2" class="footnum" href="#fnr.2" role="doc-backlink">2</a></sup> <div class="footpara" role="doc-footnote"><p class="footpara">
Emacs requires contributions to have copyright assignment given to the
FSF in order to be added, Eglot requires this for contributions
</p></div></div>

<div class="footdef"><sup><a id="fn.3" class="footnum" href="#fnr.3" role="doc-backlink">3</a></sup> <div class="footpara" role="doc-footnote"><p class="footpara">
In Emacs <code>M</code> is <code>Alt</code> so <code>M</code>-<code>x</code> is <code>Alt</code> + <code>x</code>, <code>C</code> is
<code>Ctrl</code>, and <code>RET</code> is <code>Enter</code>.
</p></div></div>


</div>
</div>]]>
</description></item>
<item>
<title>Open Emacs Eshell in the Current Directory</title>
<link>https://taingram.org/blog/open-eshell-current-dir.html</link>
<pubDate>Sun, 16 Nov 2025 00:00:00 -0500</pubDate>
<guid>https://taingram.org/blog/open-eshell-current-dir.html</guid>
<description>
<![CDATA[<p>
When working in Emacs I often want to swap from the current open file
to a terminal buffer in the same working directory.  If you are
opening an eshell buffer for the first time that is easy.  Eshell
opens the <code>default-directory</code> automatically.  However there is no easy
way to reuse an existing eshell buffer and move to the current
directory without manual input.
</p>

<p>
I want a way to save my current working directory, switch to eshell,
and change to that directory without losing any work.  Here's the
quick solution I came up with:
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp">(<span class="org-keyword">defun</span> <span class="org-function-name">eshell-current-directory</span> (<span class="org-type">&amp;optional</span> directory)
  <span class="org-doc">"Open eshell current `</span><span class="org-doc"><span class="org-constant">default-directory</span></span><span class="org-doc">' or DIRECTORY."</span>
  (<span class="org-keyword">interactive</span>)
  (<span class="org-keyword">let</span> ((current-dir (<span class="org-keyword">or</span> directory default-directory))
        (eshell-buffer (<span class="org-keyword">or</span> (get-buffer <span class="org-string">"*eshell*"</span>)
                    (eshell))))
    (switch-to-buffer eshell-buffer)
    (eshell/cd current-dir)
    (eshell-next-prompt)
    <span class="org-comment-delimiter">;; </span><span class="org-comment">Regenerate prompt to show current directory.
</span>    <span class="org-comment-delimiter">;; </span><span class="org-comment">Avoid sending any half written input commands
</span>    (<span class="org-keyword">if</span> (eobp)
        (eshell-send-input nil nil nil)
      (move-end-of-line nil)
      (eshell-kill-input)
      (eshell-send-input nil nil nil)
      (yank))))
</pre>
</div>

<p>
I've bound this to <code>C-x e</code> so whenever I am working on something I can
quickly open a terminal in the current directory.  If I don't want to
change directories then I can use <code>switch-to-buffer</code> instead.
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp">(global-set-key (kbd <span class="org-string">"C-x e"</span>) #'eshell-current-directory)
</pre>
</div>
<div id="outline-container-org39f8339" class="outline-3">
<h3 id="org39f8339"><span class="section-number-3">0.1.</span> Future Enhancement Ideas</h3>
<div class="outline-text-3" id="text-0-1">
<p>
I'd like to adapt this to work with <code>shell-mode</code>, which should be
pretty easy.  Then look at excluding some buffer types like <code>*Info*</code>,
<code>*scratch*</code>, and <code>*Help*</code> to avoid changing the working directory on
accident.  I never want to go to <code>/usr/share/info</code>.
</p>
</div>
</div>
<div id="outline-container-orgd5cd089" class="outline-2">
<h2 id="orgd5cd089"><span class="section-number-2">1.</span> Free Software Foundation 40th Anniversary Hackathon</h2>
<div class="outline-text-2" id="text-1">
<p>
I'm planning on participating in the <a href="https://www.fsf.org/events/fsf40-hackathon">FSF40 Anniversary Hackathon</a> next
weekend in support of Emacs <a href="https://orgmode.org/">Org-mode</a>.  I'll be participating with
<a href="https://thibaut.dev/">Thibaut</a> who has collaborated with me on org-publish-rss.
</p>

<p>
In the next week I plan to post a few short articles as I get myself
back into the rhythm of writing elisp.  Since September, my FOSS
contributions have slowed as I have started graduate school for my
MBA.  Unfortunately my current classes have very little overlap with
my Emacs usage.  My classmates would rather collaborate using Google
Docs than a git server&#x2026;
</p>
</div>
<div id="outline-container-orge61bcc1" class="outline-3">
<h3 id="orge61bcc1"><span class="section-number-3">1.1.</span> <a href="https://my.fsf.org/join">Donate to the Free Software Foundation!</a></h3>
<div class="outline-text-3" id="text-1-1">
<p>
The FSF is not a perfect institution (none are), but they have a
steadfast commitment to supporting software freedom.  It is important
we keep their message of software freedom alive for another 40 years.
It lends credibility to the <a href="https://en.wikipedia.org/wiki/Free_software_movement">free software movement</a> and gives <a href="https://www.gnu.org/">GNU</a>
projects a legal organization to work under.  Please consider
supporting them.
</p>

<p>
It is also worth noting that hosting costs for free software
organizations has <a href="https://github.com/magit/magit/issues/5472#issuecomment-3487310934">gone significantly up</a> in the past three years due to
AI scrapers.  It is importantly we keep these organizations alive and
well funded.
</p>

<p>
<a href="https://my.fsf.org/join">Donate to the FSF!</a>
</p>
</div>
</div>
</div>
]]>
</description></item>
<item>
<title>Minimal Debian 13 and LaTeX Install</title>
<link>https://taingram.org/blog/minimal-debian-texlive.html</link>
<pubDate>Fri, 05 Sep 2025 00:00:00 -0400</pubDate>
<guid>https://taingram.org/blog/minimal-debian-texlive.html</guid>
<description>
<![CDATA[<p>
In honor of the release of <a href="https://www.debian.org/News/2025/20250809">Debian 13 Trixie</a> I've treated myself to a
fresh install of Debian.  In the spirit of minimalism I've started
with a completely bare base-system, opting to skip all graphical
desktops for my initial install.  I enjoy the process of starting with
essentially a Linux server and only installing packages as I actually
need them.  Doing this highlights the applications I rely on, and in
turn the software those apps rely on.  In other words dependencies.
</p>

<p>
Now I'll admit this is mostly a fun exercise that appeals to my
brain in particular.  For the <i>most part</i> extra software is not a big
issue, and it is better to have a working computer than a few less
bytes on a hard drive.  I just find a minimal setup satisfying.  At
one point I was an <a href="https://archlinux.org/">Arch Linux</a> user, it is what it is.
</p>

<p>
The tradeoffs of software minimalism were highlighted for me when I
installed <a href="https://packages.debian.org/trixie/mpd"><code>mpd</code></a> (Music Player Daemon).  <code>mpd</code> has a lot of
dependencies and a few that I found unnecessary.  I will likely never
need to play Commodore 64 music files (<code>libsidplayfp6</code>), but that is
also what makes <code>mpd</code> great.  It is a flexible tool you can throw
anything at.  Still I was a little more annoyed to see JavaScript
libraries installed just to show the documentation pages (Sphinx).
</p>

<p>
If I was a python programmer I likely would have never noticed because
Sphinx is a dependency for nearly every <code>*python-doc</code> package.  For me
though <code>mpd</code> is the only package that requires these dependencies.
It's just a few extra bytes, I can live with it.  Perhaps someday I'll
be in the woods completely offline and need to consult a local copy of
the <code>mpd</code> docs.  In that moment I'll be so thankful.  I might not even
consider that Sphinx definitely has export options that does not
require JavaScript libraries.
</p>

<p>
Of course this is not a real deal breaker.  I could build <code>mpd</code>
myself, or build a custom deb package.  I could switch back to Arch
Linux.  Better yet I could switch to <a href="https://www.gentoo.org/">Gentoo</a> and spend all my days
compiling packages.  No, I use Debian because I <i>like</i> Debian.  I like
the philosophy, stability, and cooperative spirit of the project.
Debian maintainers are making sane choices that makes stuff work with
reasonable defaults that supports a huge range of use cases.
</p>

<p>
With all that in mind, lets talk about LaTeX.
</p>
<div id="outline-container-org1b6e737" class="outline-2">
<h2 id="org1b6e737"><span class="section-number-2">1.</span> Installing LaTeX on Debian</h2>
<div class="outline-text-2" id="text-1">
<p>
To build LaTeX documents we need to install the TeX Live distribution.
A full install of the <code>texlive</code> packages is huge and includes
thousands of TeX packages.  Majority of which I will never use and
don't want to install.  The problem is to compile Org-mode documents
we need several packages that are <i>only</i> included in the extensive
<code>texlive-latex-extra</code> and <code>texlive-pictures</code> packages.
</p>
</div>
<div id="outline-container-org2ea0cbc" class="outline-3">
<h3 id="org2ea0cbc"><span class="section-number-3">1.1.</span> Installing LaTeX the Normal Way</h3>
<div class="outline-text-3" id="text-1-1">
<div class="org-src-container">
<pre class="src src-sh">sudo apt install texlive texlive-latex-extra texlive-pictures texlive-science
</pre>
</div>

<p>
You can see the list of TeX packages each of these installs in the
package descriptions.  Run <code>apt info</code> to see the full list. The
<code>texlive-latex-extra</code> lists around 1,500 packages.  I need ~3.
</p>

<div class="org-src-container">
<pre class="src src-sh">apt info texlive-latex-extra
</pre>
</div>
</div>
</div>
<div id="outline-container-org7e15b3d" class="outline-3">
<h3 id="org7e15b3d"><span class="section-number-3">1.2.</span> Manual TeX Live Install</h3>
<div class="outline-text-3" id="text-1-2">
<p>
If you <i>really</i> want a minimal install the best option would be to
just manually install texlive and the packages you want.  You can do
that by following the instructions on <a href="https://tug.org/texlive/">tug.org/texlive/</a>, That is
probably the <b>right way</b> to circumvent installing every Debian texlive
package.  Once installed you'll be able to manage your whole texlive
install with the included package manager <code>tlmgr</code> (TeX Live Manager).
</p>
</div>
</div>
<div id="outline-container-org454687b" class="outline-3">
<h3 id="org454687b"><span class="section-number-3">1.3.</span> Mixed Install with <code>apt</code> and <code>tlmgr</code></h3>
<div class="outline-text-3" id="text-1-3">
<p>
The method I used was a little more chaotic.  I installed the base
<a href="https://packages.debian.org/trixie/texlive">texlive</a> system via <code>apt</code>.  This gives us all the critical stuff for
building basic documents (pdflatex, tlmgr) with minimal effort.
</p>

<div class="org-src-container">
<pre class="src src-sh">apt install texlive
</pre>
</div>

<p>
After that I go to my documents and start trying to build them.  Even
for a basic Org to LaTeX document there are several TeX packages that
will be missing.  The compile warning will call out the missing
package <code>*.sty</code> and then I can install it with <code>tlmgr</code>.
</p>

<pre class="example" id="org5878326">
ERROR: LaTeX Error: File `wrapfig.sty' not found.

--- TeX said ---
./test.tex:9:  ==&gt; Fatal error occurred, no output PDF file produced!
</pre>

<p>
On Debian the texlive package manager <code>tlmgr</code> is included with the
base <code>texlive</code> install.  The Debian maintainers have explicitly
recommend not to use this tool<sup><a id="fnr.1" class="footref" href="#fn.1" role="doc-backlink">1</a></sup>, because it may install TeX
packages are incompatible with the deb package versions.  So please
<span class="underline">do this at your own risk and do <b>NOT</b> pester Debian volunteers if
your TeX install breaks!</span>
</p>

<p>
One benefit of this mixed setup is the <code>tlmgr</code> tool is forced into
<code>--user</code> mode.  This means all packages are installed locally in your
home directory.  For my use case that is perfect.  If something breaks
I can always delete the directory and fall back to an <code>apt</code> install.
By default packages are stored in <code>~/texmf/</code>, and can be changed by
setting the <code>TEXMFHOME</code> environment variable.  In my <code>~/.bashrc</code> I
have this set:
</p>

<div class="org-src-container">
<pre class="src src-sh"><span class="org-builtin">export</span> <span class="org-variable-name">TEXMFHOME</span>=$<span class="org-variable-name">HOME</span>/.config/texlive/
</pre>
</div>

<p>
Then initialize our <code>tlmgr</code> folder with:
</p>

<div class="org-src-container">
<pre class="src src-sh"><span class="org-builtin">source</span> ~/.bashrc    <span class="org-comment-delimiter"># </span><span class="org-comment">Ensure your $TEXMFHOME is set
</span><span class="org-builtin">echo</span> $<span class="org-variable-name">TEXMFHOME</span>
tlmgr init-usertree
</pre>
</div>

<p>
Now we can install the couple missing dependences needed for Org LaTeX
export via <code>tlmgr</code>.  Once you've installed all the packages reported
in your LaTeX compile errors you should be all set going forward.
</p>

<div class="org-src-container">
<pre class="src src-sh">tlmgr install warpfig rotating ulem capt-of
</pre>
</div>

<p>
Again this is a hack-y solution, but currently I only have ~10
packages manually installed.  That is in comparison to the hundreds of
packages included in all of texlive.  This solution may become more
fragile over time as Debian stable drifts further out of date with
current TeX Live releases.  Although I suspect most popular TeX
packages are pretty stable and slow moving.
</p>
</div>
</div>
</div>
<div id="footnotes">
<h2 class="footnotes">Footnotes: </h2>
<div id="text-footnotes">

<div class="footdef"><sup><a id="fn.1" class="footnum" href="#fnr.1" role="doc-backlink">1</a></sup> <div class="footpara" role="doc-footnote"><p class="footpara">
See <code>/usr/share/doc/texlive-base/README.tlmgr-on-Debian.md</code>
</p></div></div>


</div>
</div>]]>
</description></item>
<item>
<title>Introduction to Emacs Tempo Code Templates</title>
<link>https://taingram.org/blog/intro-to-emacs-tempo.html</link>
<pubDate>Sat, 12 Apr 2025 00:00:00 -0400</pubDate>
<guid>https://taingram.org/blog/intro-to-emacs-tempo.html</guid>
<description>
<![CDATA[<p>
Recently I removed <a href="https://github.com/joaotavora/yasnippet">yasnippets</a> from my Emacs config as I rarely used
the most of the snippets.  Probably my own fault, when I started using
yasnippets I downloaded a large repo of premade snippet definitions
which meant I suddenly had a ton of keywords.  Over the years I
deleted many of ones I triggered by accident and found myself only
using a handful of templates regularly.
</p>

<p>
When I learned Emacs has a built in template system, tempo, I figured
this was a good time to try it out.  I've been porting my few snippets
over to tempo.el.
</p>

<p>
Since tempo is included with Emacs all you need to do is require it to
enable it.
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp">(<span class="org-keyword">require</span> '<span class="org-constant">tempo</span>)
(<span class="org-keyword">setq</span> tempo-interactive t) <span class="org-comment-delimiter">; </span><span class="org-comment">Enable interactive prompts etc</span>
</pre>
</div>

<p>
The package is really cool, although it is not documented very well by
Emacs standards.  The explanation in the <a href="https://www.gnu.org/software/emacs/manual/html_node/autotype/Tempo.html">Emacs manual</a> barely gives you
any idea where to start.  You need to dig around the <code>tempo.el</code> source
file to read the commentary section and docstrings.  From there I
discovered there is a partially complete info manual available on
<a href="https://www.lysator.liu.se/~davidk/elisp/">David Kågedal's website</a>.
</p>

<p>
I found the <a href="https://www.emacswiki.org/emacs/TempoMode">examples on the Emacs Wiki</a> the most helpful.  Along with
that and the <code>tempo-define-template</code> docstring I was able to start
building some templates.  A basic template definition looks like this:
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp">(tempo-define-template <span class="org-string">"insert-lambda"</span>
                       '(<span class="org-string">"(lambda ("</span> (p <span class="org-string">"Arguments: "</span>) <span class="org-string">")"</span> n&gt; p <span class="org-string">")"</span> n)
                       <span class="org-string">"lambda"</span>
                       <span class="org-string">"Insert a lambda function."</span>)
</pre>
</div>

<p>
Going line by line this means
</p>

<ol class="org-ol">
<li>Template name.</li>
<li>Template definition, tempo defines several default keywords that
can be interpreted to do different things.
<ul class="org-ul">
<li><code>p</code> &#x2014; prompt user for input.</li>
<li><code>n</code> &#x2014; insert new line</li>
<li><code>n&gt;</code> &#x2014; insert new line  and indent</li>
</ul></li>
<li>Template keyword.</li>
<li>Template docstring explanation.</li>
</ol>

<p>
For every tempo template defined an interactive function is
automatically generated named "tempo-template" + "your-template-name".
So you can run M-x <code>tempo-template-insert-lambda</code> and it will insert
the template into your current buffer.  This is really nice since I
can use vertico to look-up my templates quickly without remembering a
keyword.
</p>

<p>
If you want automatic expansion of the keywords like yasnippets that
can be enabled by calling the function in an abbrev definition.  Just
make sure you have abbrev-mode on in the mode you are using.
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp">(define-abbrev emacs-lisp-mode-abbrev-table <span class="org-string">"lambda"</span> <span class="org-string">""</span>
  'tempo-template-insert-lambda)
</pre>
</div>

<p>
Note the empty string <code>""</code> which is required since this is not expanding
to a normal word.
</p>
<div id="outline-container-org76675e0" class="outline-2">
<h2 id="org76675e0"><span class="section-number-2">1.</span> Dynamic Example</h2>
<div class="outline-text-2" id="text-1">
<p>
Anything tempo cannot identify in the template definition it
interprets as raw elisp code.  It will insert the final expression
output as a string.  So we can use this to get variables and run
functions.  For example I created this template to generate a elisp
file header.
</p>

<div class="org-src-container">
<pre class="src src-emacs-lisp">  (tempo-define-template <span class="org-string">"elisp-header"</span>
    '(<span class="org-string">";;; "</span> (file-name-nondirectory (<span class="org-keyword">or</span> buffer-file-name <span class="org-string">""</span>)) <span class="org-string">" --- "</span>
      (p <span class="org-string">"Short Description: "</span>)<span class="org-string">" -*- lexical-binding: t -*-

;; Copyright (C) 2025 Thomas Ingram

;; Author: Thomas Ingram <a href="mailto:thomas%40taingram.org">&lt;thomas@taingram.org&gt;</a>
;; Version: 0.1
;; Package-Requires: ((emacs \"30.1\"))
;; Homepage: https://git.sr.ht/~taingram/
;; Keywords:

;; This file is NOT part of GNU Emacs

;; This file is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; For a full copy of the GNU General Public License
;; see <a href="http://www.gnu.org/licenses/">&lt;http://www.gnu.org/licenses/&gt;</a>.

;;; Commentary:

;;; Code:

(provide '"</span> (file-name-base (<span class="org-keyword">or</span> buffer-file-name <span class="org-string">""</span>)) <span class="org-string">")

;;; "</span> (file-name-with-extension (<span class="org-keyword">or</span> buffer-file-name <span class="org-string">""</span>)) <span class="org-string">" ends here"</span>)
    nil
    <span class="org-string">"Insert documentation header for a Emacs Lisp file."</span>)
</pre>
</div>

<p>
Note this is just an example definition, repetitive file headers are
better entered using <a href="https://www.gnu.org/software/emacs/manual/html_mono/autotype.html#Autoinserting">auto-insert-mode</a>. Another really cool package
built into Emacs.
</p>
</div>
</div>
<div id="outline-container-org98b767b" class="outline-2">
<h2 id="org98b767b"><span class="section-number-2">2.</span> Conclusion</h2>
<div class="outline-text-2" id="text-2">
<p>
Once I got my head wrapped around the setup I'm really impressed with
how easy tempo is to use.  I also like that I can create templates and
just call them as a function.  The extra setup needed with abbrev does
not bother me as I rarely want expandable keywords anyways for my
workflow.
</p>
</div>
</div>
<div id="outline-container-orgc6c85c1" class="outline-2">
<h2 id="orgc6c85c1"><span class="section-number-2">3.</span> See Also</h2>
<div class="outline-text-2" id="text-3">
<ul class="org-ul">
<li><a href="https://www.lysator.liu.se/~davidk/elisp/">Tempo Author David Kågedal's website</a></li>
<li><a href="https://www.emacswiki.org/emacs/TempoMode">Tempo Mode - EmacsWiki</a></li>
<li><a href="https://github.com/minad/tempel">tempel.el &#x2014; Daniel Mendler's modern take on Tempo</a></li>
</ul>
</div>
</div>
]]>
</description></item>
<item>
<title>Creating a Desktop Launcher for Emacs Calc</title>
<link>https://taingram.org/blog/emacs-calc-desktop-entry.html</link>
<pubDate>Tue, 18 Nov 2025 00:00:00 -0500</pubDate>
<guid>https://taingram.org/blog/emacs-calc-desktop-entry.html</guid>
<description>
<![CDATA[<p>
<a href="https://www.gnu.org/software/emacs/manual/html_mono/calc.html#Top">Calc</a> is one of Emacs my favorite packages.  It is an excellent
calculator with <a href="https://www.youtube.com/watch?v=993dmoDdybs">a bunch of neat features</a>.  For me, the only downside
is I need to swap to Emacs to use it.  When I'm working in spreadsheet
or browsing the web I'll often need to make some quick calculations
and want open a real calculator.  By creating a custom desktop
launcher for calc we can open it as easily as the standard desktop
calculator.
</p>
<div id="outline-container-orgcb49137" class="outline-2">
<h2 id="orgcb49137"><span class="section-number-2">1.</span> Creating a Desktop Launcher</h2>
<div class="outline-text-2" id="text-1">
<p>
On most Linux desktop environments you can create a launcher entry by
adding a <a href="https://specifications.freedesktop.org/desktop-entry/latest/">desktop file</a> in <code>~/.local/share/applications/</code>.  Once added
the app icon will appear in your applications list.  Here is the
<code>calc.desktop</code> file I created:
</p>

<div class="org-src-container">
<pre class="src src-conf">[<span class="org-type">Desktop Entry</span>]
<span class="org-variable-name">Name</span>=Calc (Emacs)
<span class="org-variable-name">GenericName</span>=Calculator
<span class="org-variable-name">Comment</span>=Emacs Calculator
<span class="org-variable-name">Exec</span>=emacs -Q --eval <span class="org-string">"(full-calc)"</span> -l <span class="org-string">"~/.config/emacs/early-init.el"</span>
<span class="org-variable-name">Icon</span>=emacs
<span class="org-variable-name">Type</span>=Application
<span class="org-variable-name">Terminal</span>=false
<span class="org-variable-name">Categories</span>=Utility;
</pre>
</div>

<p>
To make sure it launches quickly I'm skipping my full init file with
<code>-Q</code> and manually loading my <code>early-init.el</code> to hide the tool-bar
etc..  See <a href="https://manpages.debian.org/trixie/emacs-gtk/emacs.1.en.html">emacs(1)</a> for all options.
</p>

<p>
This solution should work automatically in most mainstream Linux/BSD
desktop environments.  Although you may need to log out and back in to
refresh your applications list.  If you use a window manager like <a href="https://i3wm.org/">i3</a>
or <a href="https://swaywm.org/">sway</a> you can using a custom launcher that supports desktop files,
or a script like <a href="https://github.com/enkore/j4-dmenu-desktop">j4-dmenu-desktop</a>.  I use the latter in conjunction
with wmenu on sway to launch applications.
</p>

<div class="org-src-container">
<pre class="src src-conf"><span class="org-comment-delimiter"># </span><span class="org-comment">Simple Application Launcher for Sway
</span><span class="org-variable-name">bindsym $mod+space exec j4-dmenu-desktop --no-generic --dmenu</span>=<span class="org-string">"wmenu -b -f 'Monospace 16' -i"</span> | xargs swaymsg exec --
</pre>
</div>
</div>
</div>
<div id="outline-container-org322dbcd" class="outline-2">
<h2 id="org322dbcd"><span class="section-number-2">2.</span> Launching Calc in an Emacs Client</h2>
<div class="outline-text-2" id="text-2">
<p>
If you run emacs as a daemon then you can launch calc directly into an
emacsclient frame instead.  This has the added benefit of maintaining
your calc history and current emacs theme.  For further discussion of
emacsclient see my <a href="https://taingram.org/blog/emacs-client.html">earlier blog post</a>.
</p>

<pre class="example" id="org853b50d">
[Desktop Entry]
Name=Calc (Emacs Client)
GenericName=Calculator
Comment=Emacs Calculator
Exec=emacsclient -c --eval "(full-calc)"
Icon=emacs
Type=Application
Terminal=false
Categories=Utility;
</pre>
</div>
</div>
<div id="outline-container-orga38ca24" class="outline-2">
<h2 id="orga38ca24"><span class="section-number-2">3.</span> See Also</h2>
<div class="outline-text-2" id="text-3">
<ul class="org-ul">
<li><a href="https://www.gnu.org/software/emacs/manual/html_mono/calc.html#Top">Calc Manual</a> <i>gnu.org</i> Emacs Advance Desktop Calculator</li>
<li><a href="https://github.com/enkore/j4-dmenu-desktop">j4-dmenu-desktop</a> <i>github.com</i> created by enkore et. al.</li>
<li><a href="https://specifications.freedesktop.org/desktop-entry/latest/">Desktop File Specification</a> <i>freedesktop.org</i></li>
</ul>
</div>
</div>
]]>
</description></item>
<item>
<title>Fixing Dell XPS 13 Audio Popping</title>
<link>https://taingram.org/blog/fix-xps-audio.html</link>
<pubDate>Sat, 01 Apr 2017 16:40:00 -0400</pubDate>
<guid>https://taingram.org/blog/fix-xps-audio.html</guid>
<description>
<![CDATA[<p>
The Dell XPS 13 has been my primary computer for the past couple
months. It has worked great but recently I noticed some audio
crackling when starting/stopping playback.
</p>
<div id="outline-container-orga9c426b" class="outline-2">
<h2 id="orga9c426b"><span class="section-number-2">1.</span> Solution</h2>
<div class="outline-text-2" id="text-1">
<p>
I <a href="http://en.community.dell.com/support-forums/laptop/f/3517/t/20006160">found the problem</a> was an issue with <code>tlp</code>, a fantastic tool that helps
save power on Linux laptops. Issue was it was cutting power to my
audio jack when not in use which caused the loud crackling when it was
turned on and off.
</p>
</div>
<div id="outline-container-org770172a" class="outline-3">
<h3 id="org770172a"><span class="section-number-3">1.1.</span> Check if tlp is running</h3>
<div class="outline-text-3" id="text-1-1">
<div class="org-src-container">
<pre class="src src-bash">systemctl status tlp
</pre>
</div>

<p>
Example output:
</p>
<pre class="example" id="org7249975">
● tlp.service - TLP system startup/shutdown
   Loaded: loaded (/usr/lib/systemd/system/tlp.service; enabled; vendor preset: enabled)
   Active: active (exited) since Fri 2017-05-12 00:27:00 EDT; 59min ago
     Docs: http://linrunner.de/tlp
  Process: 1574 ExecStart=/usr/sbin/tlp init start (code=exited, status=0/SUCCESS)
 Main PID: 1574 (code=exited, status=0/SUCCESS)
    Tasks: 0 (limit: 4915)
   CGroup: /system.slice/tlp.service

May 12 00:27:00 XPS systemd[1]: Starting TLP system startup/shutdown...
May 12 00:27:00 XPS tlp[1574]: Applying power save settings...done.
May 12 00:27:00 XPS tlp[1574]: Setting battery charge thresholds...done.
May 12 00:27:00 XPS systemd[1]: Started TLP system startup/shutdown.
</pre>

<p>
In the output you should see the 3rd line "<code>Active: active</code>" if <code>tlp</code>
is running. Otherwise this solution likely won't fix your problem.
</p>
</div>
</div>
<div id="outline-container-orgf554cde" class="outline-3">
<h3 id="orgf554cde"><span class="section-number-3">1.2.</span> Edit your tlp config</h3>
<div class="outline-text-3" id="text-1-2">
<p>
To solve this edit <code>/etc/default/tlp</code> (for beginners use "<code>gksudo
gedit /etc/default/tlp</code>" or "<code>sudo nano /etc/default/tlp</code>").
</p>

<p>
Change lines:
</p>
<div class="org-src-container">
<pre class="src src-conf"><span class="org-variable-name">SOUND_POWER_SAVE_ON_AC</span>=0
<span class="org-variable-name">SOUND_POWER_SAVE_ON_BAT</span>=1
</pre>
</div>
<p>
To this:
</p>
<div class="org-src-container">
<pre class="src src-conf"><span class="org-variable-name">SOUND_POWER_SAVE_ON_AC</span>=0
<span class="org-variable-name">SOUND_POWER_SAVE_ON_BAT</span>=0
</pre>
</div>
<p>
Then restart your computer.
</p>

<p>
That will stop <code>tlp</code> from turning your audio on and off when audio
stops playing. You may loose some slight power savings, but I haven't
noticed anything significant. So it's worth doing just to ditch the
annoying crackling!
</p>
</div>
</div>
</div>
<div id="outline-container-org11aba25" class="outline-2">
<h2 id="org11aba25"><span class="section-number-2">2.</span> Update: Headphone Audio Whining</h2>
<div class="outline-text-2" id="text-2">
<p>
Recently I have noticed a constant whining when using headphones. The <a href="https://wiki.archlinux.org/index.php/Dell_XPS_13_(9350)#Sound%5D%5D">Arch
Wiki provides a solution</a> that seems to work:
</p>

<div class="org-src-container">
<pre class="src src-bash">amixer -c 0 cset <span class="org-string">'numid=10'</span> 1
</pre>
</div>
</div>
</div>
]]>
</description></item>
<item>
<title>How to Stay Sane within the Trump 2.0 News Cycle</title>
<link>https://taingram.org/blog/staying-sane-under-trump.html</link>
<pubDate>Fri, 07 Feb 2025 00:00:00 -0500</pubDate>
<guid>https://taingram.org/blog/staying-sane-under-trump.html</guid>
<description>
<![CDATA[<p>
Donald Trump has been in office for less than a month and life already
feels extremely chaotic.  The daily new cycle feels fast and insane,
that being their intentional "flood the zone" political strategy.  To
implement as much as possible as quickly as possible to overwhelm any
opposition.  If you have been avoiding the news, or reading this from
the future, this article summarizes the first couple weeks well:
</p>

<p>
<a href="https://www.cjr.org/the_media_today/trump_flood_zone_transparency_secrecy_musk.php">Columbia Journalism Review - Is Trump Flooding or Draining the Zone?  Yes. [Feb 3, 2025]​</a>
</p>

<p>
Under this atmosphere it is easy to get overwhelmed by the shear
volume of news and apparent chaos.  In this regard I hope to provide
some recommendations on how I personally am trying to handle life and
stay sane.
</p>
<div id="outline-container-orgec1aecc" class="outline-2">
<h2 id="orgec1aecc"><span class="section-number-2">1.</span> Rest &amp; Reset from the 24-hour News Cycle</h2>
<div class="outline-text-2" id="text-1">
<p>
It is critical to remember reading the news (and social media) is
<span class="underline">not</span> activism.  You personally staying constantly updated will not
make any positive impact on its own.  The urge to stay plugged in is
just draining your mental stamina and feeding the algorithms.
</p>

<p>
Set limits on when you can access the news and social media.  I
personally check the news throughout my morning and workday.  I check
BlueSky when I get off work, then I try to completely get
off my phone by 7 PM.  I have been trying especially not to check the
social media before bed.
</p>

<p>
As much as possible your free time should be recharging and living life.
Be with the people you love.  Work on your hobbies, create things!  Do
things that you enjoy, go hiking, get into <a href="https://play.google.com/store/apps/developer?id=SQUARE+ENIX+Co.,Ltd.&amp;hl=en-US">100+ hour long JRPGs</a>.
Whatever you need to do.  Do not mindlessly doom scroll.
</p>

<p>
Beyond that make sure you are getting enough sleep.  Everything is
worse and harder when you are exhausted.  This is something I actively
have to manage as someone who has problems falling asleep and
desperately needs 8+ hours of it.  Limit screens before bed.  I like
to unwind with a book, or at least a very chill game like Dragon
Quest.
</p>
</div>
</div>
<div id="outline-container-org8b7c521" class="outline-2">
<h2 id="org8b7c521"><span class="section-number-2">2.</span> Can Social Media Outrage Actually Do Anything?</h2>
<div class="outline-text-2" id="text-2">
<p>
Trump has shown he does respond to extremely bad press, economic
shifts, and approval ratings.  If it shown on TV news or negatively
impacts support from his base he has pivoted.  So there is some value
to outrage news, especially if it can generate negative opinion across
the right wing.
</p>

<p>
Talk to people in your direct life about what is going on and why it
matters.  Especially if they are center or right-leaning.  Their news
media may be completely ignoring or spinning news stories out of
context.  That type of small advocacy can be helpful.
</p>

<p>
Keep in mind our House Representatives are much more easily swayed by
bad press and polling.  Their elections are coming fast and we need to
make them aware that we are paying attention to their actions.  Find
your House Representative and let them know when you disagree with
their action.  Further let people in your area know what they are
doing.
</p>

<p>
<a href="https://www.house.gov/representatives/find-your-representative">Find Your Representative - U.S. House of Representatives</a>
</p>
</div>
</div>
<div id="outline-container-orge8e2d69" class="outline-2">
<h2 id="orge8e2d69"><span class="section-number-2">3.</span> Disclaimer, I'm just some guy</h2>
<div class="outline-text-2" id="text-3">
<p>
I want to keep the scope of this post limited to news and social media
consumption, as that is something I personally can speak to.  I don't
know how to fix politics in this country.  I am also privileged that I
likely will not be significantly disadvantaged by Trump's policies
(unless he starts a recession or war).  Regardless of your politics
please try to be conscious and empathetic towards the people being
negatively affected by our government's actions.  Consider further if
this is an administration you wish to support.
</p>

<p>
Please consider contributing to organizations assisting people being
harmed domestically and abroad.  If you know of good organizations
that need support please let me know.
</p>

<ul class="org-ul">
<li><a href="https://www.aclu.org/">https://www.aclu.org/</a></li>
<li><a href="https://www.rescue.org/">https://www.rescue.org/</a></li>
</ul>
</div>
</div>
]]>
</description></item>
</channel>
</rss>
