<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>emacs on
A Scripter's Notes</title><link>https://scripter.co/categories/emacs/</link><description>Recent content in emacs
on A Scripter's Notes</description><language>en-us</language><managingEditor>kaushal.modi@gmail.com (Kaushal Modi)</managingEditor><webMaster>kaushal.modi@gmail.com (Kaushal Modi)</webMaster><lastBuildDate>Wed, 22 Apr 2026 08:24:58 -0400</lastBuildDate><generator>Hugo -- gohugo.io</generator><docs>https://validator.w3.org/feed/docs/rss2.html</docs><atom:link href="https://scripter.co/categories/emacs/index.xml" rel="self" type="application/rss+xml"/><item><title>Using Git Delta with Magit</title><link>https://scripter.co/using-git-delta-with-magit/</link><description>&lt;blockquote>&lt;em>Git Delta&lt;/em> is a command line utility that beautifies git diffs in the
terminal. But did you know that it can do the same in Magit too?&lt;/blockquote>&lt;div class="ox-hugo-toc toc">
&lt;div class="heading">Table of Contents&lt;/div>
&lt;ul>
&lt;li>&lt;a href="#installing-delta">Installing &lt;code>delta&lt;/code>&lt;/a>&lt;/li>
&lt;li>&lt;a href="#installing-magit-delta">Installing &lt;code>magit-delta&lt;/code>&lt;/a>&lt;/li>
&lt;li>&lt;a href="#configuring-delta">Configuring &lt;code>delta&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;/div>
&lt;!--endtoc-->
&lt;p>&lt;a href="https://github.com/dandavison/delta">Delta&lt;/a> is a highly configurable
&lt;span class="sidenote-number">&lt;small class="sidenote">
I am not kidding. Check out the output of &lt;a href="https://dandavison.github.io/delta/full---help-output.html">&lt;code>delta --help&lt;/code>&lt;/a>.
&lt;/small>&lt;/span>
command line utility that makes the git diffs look better, while also
syntax-highlighting
&lt;span class="sidenote-number">&lt;small class="sidenote">
&lt;a href="https://github.com/Wilfred/difftastic/">Difftastic&lt;/a> is another popular diff tool which compares files based on
their syntax. I like reviewing &lt;em>git diffs&lt;/em> from within Emacs
(Magit). But &lt;em>difftastic&lt;/em> &lt;a href="https://github.com/Wilfred/difftastic/issues/251">does not support Magit&lt;/a>.
&lt;/small>&lt;/span>
the code in the diffs.&lt;/p>
&lt;p>When I first heard of &amp;ldquo;syntax highlighted diffs&amp;rdquo;, I wasn&amp;rsquo;t sure what
that meant. If you are in the same boat, here&amp;rsquo;s a screenshot that
shows that.&lt;/p>
&lt;p>&lt;a id="figure--git-delta-example">&lt;/a>&lt;/p>
&lt;figure>
&lt;a href="delta-example.png">
&lt;img src="https://scripter.co/using-git-delta-with-magit/delta-example.png" alt="Figure 1: Example of how delta renders a git diff for an ox-hugo commit"/> &lt;/a>&lt;figcaption>
&lt;p>
&lt;span class="figure-number">Figure 1: &lt;/span>Example of how &lt;code>delta&lt;/code> renders a &lt;em>git diff&lt;/em> for an &lt;code>ox-hugo&lt;/code> commit
&lt;/p>
&lt;/figcaption>&lt;/figure>
&lt;p>But I do most of my git operations including viewing of diffs from
within Emacs, using &lt;a href="https://magit.vc">Magit&lt;/a>.&lt;/p>
&lt;div class="verse">
&lt;p>        .. and thankfully &lt;em>delta&lt;/em> &lt;a href="https://dandavison.github.io/delta/using-delta-with-magit.html">works with Magit&lt;/a>!&lt;br />&lt;/p>
&lt;/div>
&lt;p>Below screenshot shows how the same diff looks like in Magit.&lt;/p>
&lt;p>&lt;a id="figure--git-magit-delta-example">&lt;/a>&lt;/p>
&lt;figure>
&lt;a href="magit-delta-example.png">
&lt;img src="https://scripter.co/using-git-delta-with-magit/magit-delta-example.png" alt="Figure 2: Example of how magit-delta renders a git diff for an ox-hugo commit"/> &lt;/a>&lt;figcaption>
&lt;p>
&lt;span class="figure-number">Figure 2: &lt;/span>Example of how &lt;code>magit-delta&lt;/code> renders a &lt;em>git diff&lt;/em> for an &lt;code>ox-hugo&lt;/code> commit
&lt;/p>
&lt;/figcaption>&lt;/figure>
&lt;p>The &lt;a href="https://github.com/dandavison/magit-delta">&lt;code>magit-delta&lt;/code>&lt;/a> Emacs package makes this possible, which is also
developed by the &lt;code>delta&lt;/code> author Dan Davison.&lt;/p>
&lt;dl>
&lt;dt>Caveat&lt;/dt>
&lt;dd>If the line numbers are enabled in &lt;code>delta&lt;/code>, they mess up
the interactive expanding and collapsing of diffs in Magit. See
&lt;a href="https://github.com/dandavison/magit-delta/issues/13#issuecomment-949820122">Magit Delta Issue # 13&lt;/a> for more details.&lt;/dd>
&lt;/dl>
&lt;p>Now, I am alright with not seeing the line numbers in Magit. But I
really liked to see the line numbers in the side-by-side view in the
terminal. Luckily, if disabled the &lt;code>line-numbers&lt;/code> feature but enabled
the &lt;code>side-by-side&lt;/code> view, I got what I wanted!&lt;/p>
&lt;ol>
&lt;li>Line numbers are disabled in Magit and expanding/collapsing of
diffs works correctly. &lt;em>I am also really glad that I don&amp;rsquo;t see the
side-by-side view in Magit diffs even when I enable that feature in
&lt;code>delta&lt;/code>, because I like to have my Emacs buffers only about 90
characters wide.&lt;/em>&lt;/li>
&lt;li>Line numbers &lt;strong>and&lt;/strong> side-by-side view are enabled in the terminal.&lt;/li>
&lt;/ol>
&lt;p>I&amp;rsquo;ll end this post with pointers to installing &lt;code>delta&lt;/code> and
&lt;code>magit-delta&lt;/code> and how to configure them.&lt;/p>
&lt;h2 id="installing-delta">Installing &lt;code>delta&lt;/code>&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#installing-delta">#&lt;/a>&lt;/h2>
&lt;p>You can install &lt;code>delta&lt;/code> (it&amp;rsquo;s called &lt;code>git-delta&lt;/code> in some package
managers) using one of the methods listed &lt;a href="https://dandavison.github.io/delta/installation.html">in its manual&lt;/a>, or you can
download → extract its statically compiled binary for your OS from its
&lt;a href="https://github.com/dandavison/delta/releases">GitHub Releases&lt;/a> page.&lt;/p>
&lt;h2 id="installing-magit-delta">Installing &lt;code>magit-delta&lt;/code>&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#installing-magit-delta">#&lt;/a>&lt;/h2>
&lt;p>Once you put this snippet in your Emacs config and evaluate it, it
will install this package and enable the &lt;code>magit-delta-mode&lt;/code> in the
Magit buffers.&lt;/p>
&lt;p>&lt;a id="code-snippet--enabling-magit-delta">&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-emacs-lisp" data-lang="emacs-lisp">&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="nb">use-package&lt;/span> &lt;span class="nv">magit-delta&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">:ensure&lt;/span> &lt;span class="no">t&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">:hook&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nv">magit-mode&lt;/span> &lt;span class="o">.&lt;/span> &lt;span class="nv">magit-delta-mode&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="src-block-caption">
&lt;span class="src-block-number">&lt;a href="#code-snippet--enabling-magit-delta">Code Snippet 1&lt;/a>:&lt;/span>
Installing and enabling &lt;code>magit-delta&lt;/code> using &lt;code>use-package&lt;/code>
&lt;/div>
&lt;h2 id="configuring-delta">Configuring &lt;code>delta&lt;/code>&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#configuring-delta">#&lt;/a>&lt;/h2>
&lt;p>Here&amp;rsquo;s a snippet for &lt;code>delta&lt;/code> configuration from my &lt;code>.gitconfig&lt;/code>. It&amp;rsquo;s
mostly the same as the one in &lt;em>delta&lt;/em>&amp;rsquo;s the &lt;a href="https://github.com/dandavison/delta#get-started">Getting Started&lt;/a> guide. The
main difference in my workaround for the &lt;code>magit-delta&lt;/code> issue.&lt;/p>
&lt;p>&lt;a id="code-snippet--delta-gitconfig">&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-sh" data-lang="sh">&lt;span class="line">&lt;span class="cl">&lt;span class="o">[&lt;/span>core&lt;span class="o">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">pager&lt;/span> &lt;span class="o">=&lt;/span> delta
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">[&lt;/span>interactive&lt;span class="o">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">diffFilter&lt;/span> &lt;span class="o">=&lt;/span> delta --color-only
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">[&lt;/span>add.interactive&lt;span class="o">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">useBuiltin&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">false&lt;/span> &lt;span class="c1"># required for git 2.37.0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">[&lt;/span>diff&lt;span class="o">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">colorMoved&lt;/span> &lt;span class="o">=&lt;/span> default
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">[&lt;/span>delta&lt;span class="o">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># https://github.com/dandavison/magit-delta/issues/13&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># line-numbers = true # Don&amp;#39;t do this.. messes up diffs in magit&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">#&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> side-by-side &lt;span class="o">=&lt;/span> &lt;span class="nb">true&lt;/span> &lt;span class="c1"># Display a side-by-side diff view instead of the traditional view&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># navigate = true # Activate diff navigation: use n to jump forwards and N to jump backwards&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> relative-paths &lt;span class="o">=&lt;/span> &lt;span class="nb">true&lt;/span> &lt;span class="c1"># Output all file paths relative to the current directory&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> file-style &lt;span class="o">=&lt;/span> yellow
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> hunk-header-style &lt;span class="o">=&lt;/span> line-number syntax
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="src-block-caption">
&lt;span class="src-block-number">&lt;a href="#code-snippet--delta-gitconfig">Code Snippet 2&lt;/a>:&lt;/span>
My configuration for &lt;code>delta&lt;/code> in &lt;code>.gitconfig&lt;/code>
&lt;/div></description><author>Kaushal.Modi@fakeEmailToMakeValidatorHappy.com (Kaushal Modi)</author><category domain="https://scripter.co/categories/emacs">emacs</category><category domain="https://scripter.co/tags/git">git</category><category domain="https://scripter.co/tags/100daystooffload">100DaysToOffload</category><category domain="https://scripter.co/tags/magit">magit</category><category domain="https://scripter.co/tags/diff">diff</category><guid>https://scripter.co/using-git-delta-with-magit/</guid><pubDate>Wed, 06 Jul 2022 22:04:00 -0400</pubDate></item><item><title>Gujarati Transliteration</title><link>https://scripter.co/gujarati-transliteration/</link><description>&lt;blockquote>You can phonetically write a non-English language on an English
keyword in Emacs, and that transforms into that non-English
script. This is called &lt;a href="https://en.wikipedia.org/wiki/Transliteration">&lt;em>transliteration&lt;/em>&lt;/a>, and I demonstrate that for
the Gujarati language in this post.&lt;/blockquote>&lt;div class="ox-hugo-toc toc">
&lt;div class="heading">Table of Contents&lt;/div>
&lt;ul>
&lt;li>&lt;a href="#enabling-transliteration">Enabling transliteration&lt;/a>&lt;/li>
&lt;li>&lt;a href="#toggling-the-input-method">Toggling the input method&lt;/a>&lt;/li>
&lt;li>&lt;a href="#caveats-with-gujarati-and-other-indic-language-transliteration">Caveats with Gujarati and other Indic language transliteration&lt;/a>&lt;/li>
&lt;li>&lt;a href="#input-method-cheat-sheet">&amp;ldquo;Input method&amp;rdquo; cheat sheet&lt;/a>&lt;/li>
&lt;li>&lt;a href="#closing">Closing&lt;/a>&lt;/li>
&lt;li>&lt;a href="#gujarati-transliteration-references">References&lt;/a>&lt;/li>
&lt;/ul>
&lt;/div>
&lt;!--endtoc-->
&lt;p>Emacs provides the transliteration feature using the
&lt;strong>set-input-method&lt;/strong> command. I&amp;rsquo;ll introduce that and few related
functions in this post to get to help get started with transliteration
quickly.&lt;/p>
&lt;h2 id="enabling-transliteration">Enabling transliteration&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#enabling-transliteration">#&lt;/a>&lt;/h2>
&lt;p>Emacs uses the &amp;ldquo;input method&amp;rdquo; feature to do character conversion from
ASCII to the target language or script. The &amp;ldquo;input method&amp;rdquo;, stored in
&lt;code>current-input-method&lt;/code>, is &lt;em>nil&lt;/em> by default. In this state, you see
the exact ASCII in Emacs buffer, that you typed on the
keyboard&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>.&lt;/p>
&lt;p>In this post, my target non-English language is &lt;a href="https://en.wikipedia.org/wiki/Gujarati_language">Gujarati&lt;/a>. So I want to
type on my English keyboard and have Gujarati script letters show up
in the buffer.&lt;/p>
&lt;p>Emacs provides the &lt;code>set-input-method&lt;/code> command to change the &lt;em>current
input method&lt;/em>. This command is bound to &lt;kbd>C-x&lt;/kbd> &lt;kbd>RET&lt;/kbd>
&lt;kbd>C-\&lt;/kbd> by default. Pick the new input method after calling
that command.&lt;/p>
&lt;div class="note">
&lt;p>To see the available input methods, do &lt;code>M-x list-input-methods&lt;/code>.&lt;/p>
&lt;/div>
&lt;p>As I want to do Gujarati transliteration, I pick the &lt;code>gujarati-itrans&lt;/code>
method.&lt;/p>
&lt;p>If you don&amp;rsquo;t know Gujarati, don&amp;rsquo;t fret! The commands shown here will
work when transliterating to other languages too &amp;mdash; only the
Gujarati-specific &lt;em>input method&lt;/em> &lt;code>gujarati-itrans&lt;/code> will change to the
input method of your choice.&lt;/p>
&lt;h2 id="toggling-the-input-method">Toggling the input method&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#toggling-the-input-method">#&lt;/a>&lt;/h2>
&lt;p>I often need to switch between the Gujarati and English languages in
the same document. You can see me doing that in this post next section
onwards. The &lt;code>toggle-input-method&lt;/code> command bound by default to
&lt;kbd>C-\&lt;/kbd> is helpful here.&lt;/p>
&lt;p>So if I am already in the &amp;ldquo;Gujarati transliteration mode&amp;rdquo; calling this
command will set &lt;code>current-input-method&lt;/code> back to &lt;em>nil&lt;/em>. Repeating that
same call will again set &lt;code>current-input-method&lt;/code> to &lt;code>gujarati-itrans&lt;/code>,
and I will once again be in the &amp;ldquo;Gujarati transliteration mode&amp;rdquo;.&lt;/p>
&lt;h2 id="caveats-with-gujarati-and-other-indic-language-transliteration">Caveats with Gujarati and other Indic language transliteration&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#caveats-with-gujarati-and-other-indic-language-transliteration">#&lt;/a>&lt;/h2>
&lt;p>Apologies, but this section is meaningful only if you know how to read
Gujarati. So you can safely skip to the next section.&lt;/p>
&lt;p>Below table is a quick glimpse of some nuances in Gujarati
transliteration. I will save my explanation and instead show some of
the mistakes I made in transliteration using examples.&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>ASCII input&lt;/th>
&lt;th>Gujarati Transliteration&lt;/th>
&lt;th>Rough Translation&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;em>ram&lt;/em>&lt;/td>
&lt;td>રમ્&lt;/td>
&lt;td>(incorrect spelling, no meaning)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;em>rama&lt;/em>&lt;/td>
&lt;td>રમ&lt;/td>
&lt;td>play&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;em>raama&lt;/em>&lt;/td>
&lt;td>રામ&lt;/td>
&lt;td>a popular name Raama (as in Lord Raama)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;em>angreji&lt;/em>&lt;/td>
&lt;td>અન્ગ્રેજિ&lt;/td>
&lt;td>(incorrect spelling)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;em>hu.n&lt;/em>&lt;/td>
&lt;td>હું&lt;/td>
&lt;td>I&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;em>chhu.n&lt;/em>&lt;/td>
&lt;td>છું&lt;/td>
&lt;td>am&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;em>a.ngrejii&lt;/em>&lt;/td>
&lt;td>અંગ્રેજી&lt;sup id="fnref:2">&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref">2&lt;/a>&lt;/sup>&lt;/td>
&lt;td>English (language)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;em>Ime.cksa&lt;/em>&lt;/td>
&lt;td>ઈમૅક્સ&lt;/td>
&lt;td>this literally reads &amp;ldquo;Emacs&amp;rdquo;&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="input-method-cheat-sheet">&amp;ldquo;Input method&amp;rdquo; cheat sheet&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#input-method-cheat-sheet">#&lt;/a>&lt;/h2>
&lt;p>Thankfully Emacs provides full help through the
&lt;code>describe-input-method&lt;/code> command bound to &lt;kbd>C-h&lt;/kbd>
&lt;kbd>C-\&lt;/kbd>
&lt;span class="sidenote-number">&lt;small class="sidenote">
If you haven&amp;rsquo;t already noticed the consistency in these bindings, the
default bindings with &lt;kbd>C-\&lt;/kbd> in them are related to &amp;ldquo;input
method&amp;rdquo; commands.
&lt;/small>&lt;/span>
by default.&lt;/p>
&lt;p>For example, &lt;code>M-x describe-input-method gujarati-itrans&lt;/code> gives this:&lt;/p>
&lt;p>&lt;a id="figure--gujarati-itrans-help">&lt;/a>&lt;/p>
&lt;figure>
&lt;a href="gujarati-itrans-help.png">
&lt;img src="https://scripter.co/gujarati-transliteration/gujarati-itrans-help.png" alt="Figure 1: Partial screen capture of Gujarati transliteration cheat sheet C-h C- gujarati-itrans"/> &lt;/a>&lt;figcaption>
&lt;p>
&lt;span class="figure-number">Figure 1: &lt;/span>Partial screen capture of Gujarati transliteration cheat sheet &lt;code>C-h C- gujarati-itrans&lt;/code>
&lt;/p>
&lt;/figcaption>&lt;/figure>
&lt;p>The ∗Help∗ that shows up looks formidable at the first glance. Though,
I found comfort in the fact that roughly half of the key sequences
were obvious and roughly half resulted in Gujarati characters that I
have never found the need of! 😃&lt;/p>
&lt;h2 id="closing">Closing&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#closing">#&lt;/a>&lt;/h2>
&lt;p>Typing this in the &amp;ldquo;transliteration mode&amp;rdquo;:&lt;/p>
&lt;blockquote>
&lt;p>maaru naama kaushala chhe. mane e jaaNii ne aana.nda thaaya chhe ke
hu.n aa sahelaaI thI lakhI shaku chhu.n. (joDanI-bhula maapha.)&lt;/p>
&lt;/blockquote>
&lt;p>will result in:&lt;/p>
&lt;p>મારુ નામ કૌશલ છે. મને એ જાણી ને આનંદ થાય છે કે હું આ સહેલાઈ થી લખી શકુ
છું. (જોડણી-ભુલ માફ.)&lt;/p>
&lt;p>&lt;em>Translation: My name is Kaushal. I am happy knowing that I can write
this easily.&lt;/em>&lt;/p>
&lt;h2 id="gujarati-transliteration-references">References&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#gujarati-transliteration-references">#&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Input-Methods.html" title="Emacs Lisp: (info &amp;quot;(emacs) Input Methods&amp;quot;)">Emacs Info: Input Methods&lt;/a>
&lt;ul>
&lt;li>&lt;a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Select-Input-Method.html" title="Emacs Lisp: (info &amp;quot;(emacs) Select Input Method&amp;quot;)">Emacs Info: Select Input Method&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;code>M-x describe-input-method gujarati-itrans&lt;/code>&lt;/li>
&lt;/ul>
&lt;div class="footnotes" role="doc-endnotes">
&lt;hr>
&lt;ol>
&lt;li id="fn:1">
&lt;p>I am assuming an English keyboard here.&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:2">
&lt;p>This spelling might still render incorrectly on your browser
depending on the unicode character set available for Gujarati on your
system.&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;/div></description><author>Kaushal.Modi@fakeEmailToMakeValidatorHappy.com (Kaushal Modi)</author><category domain="https://scripter.co/categories/emacs">emacs</category><category domain="https://scripter.co/series/gujarati-in-emacs">Gujarati in Emacs</category><category domain="https://scripter.co/tags/gujarati">gujarati</category><category domain="https://scripter.co/tags/transliteration">transliteration</category><category domain="https://scripter.co/tags/100daystooffload">100DaysToOffload</category><guid>https://scripter.co/gujarati-transliteration/</guid><pubDate>Mon, 27 Jun 2022 18:43:00 -0400</pubDate></item><item><title>View GitHub Pull Requests in Magit</title><link>https://scripter.co/view-github-pull-requests-in-magit/</link><description>&lt;blockquote>How to view GitHub Pull Request branches locally in the cloned repo,
and more importantly, how to do that automatically from within Emacs.&lt;/blockquote>&lt;div class="ox-hugo-toc toc">
&lt;div class="heading">Table of Contents&lt;/div>
&lt;ul>
&lt;li>&lt;a href="#locally-creating-a-branch-for-a-pr">Locally creating a branch for a PR&lt;/a>&lt;/li>
&lt;li>&lt;a href="#getting-references-to-all-pull-requests">Getting references to all Pull Requests&lt;/a>&lt;/li>
&lt;li>&lt;a href="#automatically-adding-pr-refs">Automatically adding PR refs&lt;/a>&lt;/li>
&lt;li>&lt;a href="#summary">Summary&lt;/a>&lt;/li>
&lt;li>&lt;a href="#references">References&lt;/a>&lt;/li>
&lt;/ul>
&lt;/div>
&lt;!--endtoc-->
&lt;p>I have a few public projects in git repos, but I don&amp;rsquo;t get that much
traffic in &lt;em>Pull Requests (PR)&lt;/em>
&lt;span class="sidenote-number">&lt;small class="sidenote">
Gitlab calls these &lt;em>Merge Requests&lt;/em> or MRs.
&lt;/small>&lt;/span>
. So when I need to add additional commits to a PR, I would just add
the PR author&amp;rsquo;s &lt;em>remote&lt;/em> to my local repo, &lt;em>check out&lt;/em> their PR
branch, add my own commits and then merge that to my project&amp;rsquo;s &lt;em>main&lt;/em>
branch.&lt;/p>
&lt;p>As these occurrences were few and far apart, I didn&amp;rsquo;t have a need to
view the &lt;em>PR branches&lt;/em> directly from within Emacs/Magit. Though, I
somehow knew that each GitHub Pull Request&amp;rsquo;s &lt;em>HEAD&lt;/em> got assigned a &lt;a href="https://git-scm.com/book/en/v2/Git-Internals-Git-References">git
&lt;strong>reference&lt;/strong>&lt;/a>. But I didn&amp;rsquo;t need to use that knowledge until today
😃.&lt;/p>
&lt;p>Today, when discussing &lt;a href="https://github.com/protesilaos/denote/pull/20">PR # 20&lt;/a> on &lt;a href="https://protesilaos.com/">Prot&amp;rsquo;s&lt;/a> &lt;a href="https://protesilaos.com/emacs/denote">Denote&lt;/a> package&amp;rsquo;s GitHub
mirror
&lt;span class="sidenote-number">&lt;small class="sidenote">
Prot uses &lt;a href="https://git.sr.ht/~protesilaos/denote">SourceHut&lt;/a> as the primary git forge for his Emacs
packages. But I am glad that he doesn&amp;rsquo;t mind the activity in Issues
and Pull Requests on the GitHub mirror.
&lt;/small>&lt;/span>
, he wrote &lt;a href="https://github.com/protesilaos/denote/pull/20#issuecomment-1164676013">this comment&lt;/a>:&lt;/p>
&lt;blockquote>
&lt;p>Now I just need to figure out how best to incorporate your changes
into the &lt;code>org-id&lt;/code> branch so I can add the final bits. I am not too
familiar with the PR workflow &amp;hellip;&lt;/p>
&lt;/blockquote>
&lt;p>.. and that inspired this post today.&lt;/p>
&lt;h2 id="locally-creating-a-branch-for-a-pr">Locally creating a branch for a PR&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#locally-creating-a-branch-for-a-pr">#&lt;/a>&lt;/h2>
&lt;p>From the &lt;a href="https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/checking-out-pull-requests-locally">GitHub docs&lt;/a>, the &lt;code>git&lt;/code> command to create a local branch for a
PR is this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">git fetch origin pull/ID/head:BRANCHNAME
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>I have the &lt;code>denote&lt;/code> package cloned from its GitHub mirror. So the
&lt;strong>origin&lt;/strong> remote&amp;rsquo;s &lt;strong>url&lt;/strong> is &lt;code>https://github.com/protesilaos/denote&lt;/code>.&lt;/p>
&lt;div class="note">
&lt;p>Make sure that the remote name used in this command is pointing to a
GitHub repo, and not a mirror forge like GitLab or SourceHut.&lt;/p>
&lt;/div>
&lt;p>When I ran the below command, I got a new branch &lt;strong>pr-20&lt;/strong> pointing to
the latest commit of that PR:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">git fetch origin pull/20/head:pr-20
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Awesome!&lt;/p>
&lt;div class="verse">
&lt;p>.. But that wasn&amp;rsquo;t good enough&lt;br />
    .. Now I wanted more&lt;br />
        .. I didn&amp;rsquo;t want to manually create a branch for each PR.&lt;br />&lt;/p>
&lt;/div>
&lt;h2 id="getting-references-to-all-pull-requests">Getting references to all Pull Requests&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#getting-references-to-all-pull-requests">#&lt;/a>&lt;/h2>
&lt;p>Now that I was on that quest of &amp;ldquo;I want more&amp;rdquo;, it didn&amp;rsquo;t take me long
to re-discover &lt;a href="https://oremacs.com/2015/03/11/git-tricks/#illusion-2-quickly-get-github-pull-requests-on-your-system">this 7-year old nugget&lt;/a> by &lt;a href="https://oremacs.com">Oleh Krehel&lt;/a>. Here are the
relevant bits from that post:&lt;/p>
&lt;ol>
&lt;li>Open the local repo&amp;rsquo;s &lt;code>.git/config&lt;/code> file.&lt;/li>
&lt;li>Find the &lt;code>[remote &amp;quot;origin&amp;quot;]&lt;/code> section&lt;/li>
&lt;li>Modify it by adding this one line with &lt;strong>pull&lt;/strong> refs. &lt;em>This is the
same for all GitHub repositories.&lt;/em>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-cfg" data-lang="cfg">&lt;span class="line">&lt;span class="cl">&lt;span class="k">[remote &amp;#34;origin&amp;#34;]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">https://github.com/USER/REPO.git
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> fetch = +refs/heads/*:refs/remotes/origin/*
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line hl">&lt;span class="cl">&lt;span class="s"> fetch = +refs/pull/*/head:refs/pull/origin/*&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ol>
&lt;p>With that edit in place, when I did &lt;kbd>l&lt;/kbd> &lt;kbd>a&lt;/kbd> (show
the log for all git references), followed by &lt;kbd>f&lt;/kbd> &lt;kbd>a&lt;/kbd>
(fetch all the remotes) in the Magit, I could see the references to
the &lt;code>denote&lt;/code> repo&amp;rsquo;s PRs!&lt;/p>
&lt;p>&lt;a id="figure--magit-denote-pr-refs">&lt;/a>&lt;/p>
&lt;figure>
&lt;img src="https://scripter.co/view-github-pull-requests-in-magit/pr-20-ref.png" alt="Figure 1: Viewing PR references from denote package&amp;rsquo;s GitHub repo"/> &lt;figcaption>
&lt;p>
&lt;span class="figure-number">Figure 1: &lt;/span>Viewing PR references from &lt;code>denote&lt;/code> package&amp;rsquo;s GitHub repo
&lt;/p>
&lt;/figcaption>&lt;/figure>
&lt;div class="verse">
&lt;p>.. But that still wasn&amp;rsquo;t good enough&lt;br />
    .. I didn&amp;rsquo;t want to manually edit the &lt;code>.git/config&lt;/code> in each repo.&lt;br />&lt;/p>
&lt;/div>
&lt;h2 id="automatically-adding-pr-refs">Automatically adding PR refs&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#automatically-adding-pr-refs">#&lt;/a>&lt;/h2>
&lt;p>Of course, I wasn&amp;rsquo;t the first one to think of this!&lt;/p>
&lt;p>Another Emacs veteran &lt;a href="https://endlessparentheses.com/">Artur Malabarba&lt;/a> had already had this covered
also around &lt;a href="https://endlessparentheses.com/automatically-configure-magit-to-access-github-prs.html">7 years back&lt;/a>. Coincidentally, that post was written as a
response to that same blog post by Oleh where he shared the above
&lt;code>.git/config&lt;/code> tip.&lt;/p>
&lt;p>In that post, Artur shares an Emacs Lisp function that uses Magit
functions like &lt;code>magit-get&lt;/code>, &lt;code>magit-get-all&lt;/code> and &lt;code>magit-git-string&lt;/code> to
auto-add the &lt;code>fetch = +refs/pull/*/head:refs/pull/origin/*&lt;/code> line in
the &lt;code>.git/config&lt;/code>. This magic happens after checking that the &lt;strong>origin&lt;/strong>
remote points to a GitHub repo, and if that line doesn&amp;rsquo;t already
exist.&lt;/p>
&lt;p>Here, I am lightly modifying the function shared in that post so that
the &lt;strong>origin&lt;/strong> remote name is not hard-coded
&lt;span class="sidenote-number">&lt;small class="sidenote">
The reason is that sometimes, I name the original remote as &lt;strong>upstream&lt;/strong>
and my fork as &lt;strong>fork&lt;/strong>, and I might have no remote named &lt;strong>origin&lt;/strong>.
&lt;/small>&lt;/span>
. Credit for the main logic in this code still goes to Artur.&lt;/p>
&lt;p>&lt;a id="code-snippet--add-PR-fetch-ref">&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-emacs-lisp" data-lang="emacs-lisp">&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="nb">defun&lt;/span> &lt;span class="nv">modi/add-PR-fetch-ref&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kp">&amp;amp;optional&lt;/span> &lt;span class="nv">remote-name&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;If refs/pull is not defined on a GH repo, define it.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">If REMOTE-NAME is not specified, it defaults to the &lt;/span>&lt;span class="ss">`remote&amp;#39;&lt;/span>&lt;span class="s"> set
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">for the \&amp;#34;main\&amp;#34; or \&amp;#34;master\&amp;#34; branch.&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">let*&lt;/span> &lt;span class="p">((&lt;/span>&lt;span class="nv">remote-name&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nb">or&lt;/span> &lt;span class="nv">remote-name&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">magit-get&lt;/span> &lt;span class="s">&amp;#34;branch&amp;#34;&lt;/span> &lt;span class="s">&amp;#34;main&amp;#34;&lt;/span> &lt;span class="s">&amp;#34;remote&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">magit-get&lt;/span> &lt;span class="s">&amp;#34;branch&amp;#34;&lt;/span> &lt;span class="s">&amp;#34;master&amp;#34;&lt;/span> &lt;span class="s">&amp;#34;remote&amp;#34;&lt;/span>&lt;span class="p">)))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">remote-url&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nv">magit-get&lt;/span> &lt;span class="s">&amp;#34;remote&amp;#34;&lt;/span> &lt;span class="nv">remote-name&lt;/span> &lt;span class="s">&amp;#34;url&amp;#34;&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">fetch-refs&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nb">and&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">stringp&lt;/span> &lt;span class="nv">remote-url&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nf">string-match&lt;/span> &lt;span class="s">&amp;#34;github&amp;#34;&lt;/span> &lt;span class="nv">remote-url&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">magit-get-all&lt;/span> &lt;span class="s">&amp;#34;remote&amp;#34;&lt;/span> &lt;span class="nv">remote-name&lt;/span> &lt;span class="s">&amp;#34;fetch&amp;#34;&lt;/span>&lt;span class="p">)))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">;; https://oremacs.com/2015/03/11/git-tricks/&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">fetch-address&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">format&lt;/span> &lt;span class="s">&amp;#34;+refs/pull/*/head:refs/pull/%s/*&amp;#34;&lt;/span> &lt;span class="nv">remote-name&lt;/span>&lt;span class="p">)))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">when&lt;/span> &lt;span class="nv">fetch-refs&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">unless&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">member&lt;/span> &lt;span class="nv">fetch-address&lt;/span> &lt;span class="nv">fetch-refs&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">magit-git-string&lt;/span> &lt;span class="s">&amp;#34;config&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;--add&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nf">format&lt;/span> &lt;span class="s">&amp;#34;remote.%s.fetch&amp;#34;&lt;/span> &lt;span class="nv">remote-name&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">fetch-address&lt;/span>&lt;span class="p">)))))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="nv">add-hook&lt;/span> &lt;span class="ss">&amp;#39;magit-mode-hook&lt;/span> &lt;span class="nf">#&amp;#39;&lt;/span>&lt;span class="nv">modi/add-PR-fetch-ref&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="src-block-caption">
&lt;span class="src-block-number">&lt;a href="#code-snippet--add-PR-fetch-ref">Code Snippet 1&lt;/a>:&lt;/span>
Function to auto-add GitHub PR references to the repo's &lt;code>.git/config&lt;/code>
&lt;/div>
&lt;h2 id="summary">Summary&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#summary">#&lt;/a>&lt;/h2>
&lt;p>With the above snippet added to your Emacs config and evaluated, each
time you visit a repo cloned from GitHub in the Magit Status buffer
(&lt;code>M-x magit-status&lt;/code>), the PR refs will get auto-added to that repo&amp;rsquo;s
&lt;code>.git/config&lt;/code> if needed.&lt;/p>
&lt;p>After that, you can easily view the commits from all the PRs by doing
&lt;kbd>l&lt;/kbd> &lt;kbd>a&lt;/kbd> &lt;kbd>f&lt;/kbd> &lt;kbd>a&lt;/kbd>.&lt;/p>
&lt;h2 id="references">References&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#references">#&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://oremacs.com/2015/03/11/git-tricks/#illusion-2-quickly-get-github-pull-requests-on-your-system">oremacs &amp;ndash; Some git/magit/github tricks&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://endlessparentheses.com/automatically-configure-magit-to-access-github-prs.html">endlessparentheses &amp;ndash; Automatically configure Magit to access Github PRs&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/checking-out-pull-requests-locally">GitHub &amp;ndash; Checking out PR branches locally&lt;/a>&lt;/li>
&lt;/ul></description><author>Kaushal.Modi@fakeEmailToMakeValidatorHappy.com (Kaushal Modi)</author><category domain="https://scripter.co/categories/emacs">emacs</category><category domain="https://scripter.co/categories/elisp">elisp</category><category domain="https://scripter.co/tags/git">git</category><category domain="https://scripter.co/tags/magit">magit</category><category domain="https://scripter.co/tags/100daystooffload">100DaysToOffload</category><category domain="https://scripter.co/tags/github">github</category><category domain="https://scripter.co/tags/git-reference">git-reference</category><guid>https://scripter.co/view-github-pull-requests-in-magit/</guid><pubDate>Thu, 23 Jun 2022 17:51:00 -0400</pubDate></item><item><title>Gujarati fonts in Emacs</title><link>https://scripter.co/gujarati-fonts-in-emacs/</link><description>&lt;blockquote>Setting a different font for a specific script or language in Emacs.&lt;/blockquote>&lt;div class="ox-hugo-toc toc">
&lt;div class="heading">Table of Contents&lt;/div>
&lt;ul>
&lt;li>&lt;a href="#setting-a-fontset-font">Setting a &amp;ldquo;fontset&amp;rdquo; font&lt;/a>&lt;/li>
&lt;li>&lt;a href="#gujarati-fonts">Gujarati fonts&lt;/a>&lt;/li>
&lt;/ul>
&lt;/div>
&lt;!--endtoc-->
&lt;p>All Emacs versions ship with a nifty &lt;strong>HELLO&lt;/strong> file that you can quickly
open using &lt;code>M-x view-hello-file&lt;/code> or its default binding &lt;code>C-h h&lt;/code>. This
file lists &amp;ldquo;Hello&amp;rdquo; written in dozens of languages to demonstrate some
of the character sets supported by Emacs.&lt;/p>
&lt;p>&lt;a id="figure--hello-buffer">&lt;/a>&lt;/p>
&lt;figure>
&lt;a href="hello.png">
&lt;img src="https://scripter.co/gujarati-fonts-in-emacs/hello.png" alt="Figure 1: &amp;ldquo;Hello&amp;rdquo; buffer in Emacs"/> &lt;/a>&lt;figcaption>
&lt;p>
&lt;span class="figure-number">Figure 1: &lt;/span>&amp;ldquo;Hello&amp;rdquo; buffer in Emacs
&lt;/p>
&lt;/figcaption>&lt;/figure>
&lt;p>Born and raised in the Gujarat state in India, I grew up
speaking the &lt;a href="https://en.wikipedia.org/wiki/Gujarati_language">Gujarati (ગુજરાતી)&lt;/a> language
&lt;span class="sidenote-number">&lt;small class="sidenote">
India officially recognizes &lt;a href="https://en.wikipedia.org/wiki/Languages_of_India">22 languages&lt;/a> (as of &lt;span class="timestamp-wrapper">&lt;span class="timestamp">&amp;lt;2022-06-19 Sun&amp;gt;&lt;/span>&lt;/span>) and
Gujarati is one of them.
&lt;/small>&lt;/span>
and so it&amp;rsquo;s also the language closest to my heart. So I was pleasantly
surprised to see a representation of Gujarati in the &amp;ldquo;Hello&amp;rdquo; buffer!
In the above screenshot, in the &amp;ldquo;South Asia&amp;rdquo; section, the script after
the yellow cursor is Gujarati, and it reads &lt;em>namaste&lt;/em>.&lt;/p>
&lt;h2 id="setting-a-fontset-font">Setting a &amp;ldquo;fontset&amp;rdquo; font&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#setting-a-fontset-font">#&lt;/a>&lt;/h2>
&lt;p>It was on &lt;span class="timestamp-wrapper">&lt;span class="timestamp">&amp;lt;2018-08-13 Mon&amp;gt; &lt;/span>&lt;/span> that I discovered the presence of Gujarati
script in that &amp;ldquo;Hello&amp;rdquo; buffer, and the reason I know that exact date
is because I had &lt;a href="https://lists.gnu.org/r/help-gnu-emacs/2018-08/msg00033.html">asked a question&lt;/a> regarding that on the
&lt;em>help-gnu-emacs&lt;/em> mailing list 😃.&lt;/p>
&lt;p>This was the time when Emacs was using the &lt;a href="https://www.nongnu.org/m17n/">m17n&lt;/a> library for
multi-lingual font rendering by default. The question was regarding a
font rendering issue I was seeing. As I learn later in that thread, it
was because I didn&amp;rsquo;t have the m17n database installed on my machine
&lt;span class="sidenote-number">&lt;small class="sidenote">
At least in 2022, the &lt;a href="https://github.com/harfbuzz/harfbuzz">harfbuzz&lt;/a> library is the recommended library for
text shaping and font rendering. Someone please correct me if that&amp;rsquo;s
wrong. In any case, I have switched to using &lt;em>harfbuzz&lt;/em> instead of
&lt;em>m17n&lt;/em> for a while now and haven&amp;rsquo;t found any font-rendering issues
with non-English scripts.
&lt;/small>&lt;/span>
. But it&amp;rsquo;s in that support thread that, thanks to &lt;em>Andy Moreton&lt;/em>, I
learned that you can change the font for the Gujarati script using
&lt;code>set-fontset-font&lt;/code>.&lt;/p>
&lt;p>This applies in general to any script. You can read more details about
this function in &lt;a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Modifying-Fontsets.html" title="Emacs Lisp: (info &amp;quot;(emacs) Modifying Fontsets&amp;quot;)">Emacs Info: Modifying Fontsets&lt;/a>, but here&amp;rsquo;s the gist:&lt;/p>
&lt;p>&lt;a id="code-snippet--gujarati-set-fontset-font">&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-emacs-lisp" data-lang="emacs-lisp">&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="nf">set-fontset-font&lt;/span> &lt;span class="s">&amp;#34;fontset-default&amp;#34;&lt;/span> &lt;span class="ss">&amp;#39;gujarati&lt;/span> &lt;span class="s">&amp;#34;&amp;lt;FONT NAME&amp;gt;&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="src-block-caption">
&lt;span class="src-block-number">&lt;a href="#code-snippet--gujarati-set-fontset-font">Code Snippet 1&lt;/a>:&lt;/span>
Setting default font for Gujarati script using &lt;code>set-fontset-font&lt;/code>
&lt;/div>
&lt;p>That led me down the path of exploring the available Gujarati fonts
out there ..&lt;/p>
&lt;h2 id="gujarati-fonts">Gujarati fonts&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#gujarati-fonts">#&lt;/a>&lt;/h2>
&lt;p>After looking around for a bit, I found a wonderful &lt;a href="https://github.com/samyakbhuta/chhapkaam/wiki/%E0%AA%97%E0%AB%81%E0%AA%9C%E0%AA%B0%E0%AA%BE%E0%AA%A4%E0%AB%80-%E0%AA%AF%E0%AB%81%E0%AA%A8%E0%AA%BF%E0%AA%95%E0%AB%8B%E0%AA%A1-%E0%AA%AB%E0%AB%8B%E0%AA%A8%E0%AB%8D%E0%AA%9F-%E0%AA%B8%E0%AB%82%E0%AA%9A%E0%AB%80---List-of-Gujarati-Unicode-Fonts">collection of
Gujarati fonts&lt;/a> in this GitHub repository:
&lt;a href="https://github.com/samyakbhuta/chhapkaam">github.com/samyakbhuta/chhapkaam&lt;/a>
&lt;span class="sidenote-number">&lt;small class="sidenote">
The repo name is &lt;em>chhapkaam&lt;/em> (I
would have spelled it as &lt;em>chhaapkaam&lt;/em>) which is the Gujarati word
છાપકામ, meaning &amp;ldquo;printing&amp;rdquo;.
&lt;/small>&lt;/span>
.&lt;/p>
&lt;p>Below is my further curated list of fonts from the above list:&lt;/p>
&lt;p>&lt;a id="table--gujarati-fonts">&lt;/a>&lt;/p>
&lt;div class="table-caption">
&lt;span class="table-number">&lt;a href="#table--gujarati-fonts">Table 1&lt;/a>:&lt;/span>
Gujarati Fonts
&lt;/div>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Font Name&lt;/th>
&lt;th>&lt;em>Namaste&lt;/em>&lt;/th>
&lt;th>Category&lt;/th>
&lt;th>Homepage&lt;/th>
&lt;th>Download&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>Shruti&lt;/strong>&lt;/td>
&lt;td>&lt;img src="namaste_shruti.png" alt="">&lt;/td>
&lt;td>serif&lt;/td>
&lt;td>&lt;/td>
&lt;td>&lt;a href="https://www.wfonts.com/font/shruti">wfonts.com&lt;/a>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Mukta Vaani&lt;/strong>&lt;/td>
&lt;td>&lt;img src="namaste_mukta_vaani.png" alt="">&lt;/td>
&lt;td>serif&lt;/td>
&lt;td>&lt;a href="https://ektype.in/scripts/gujarati/mukta-vaani.html">Ek Type &amp;ndash; Mukta Vaani&lt;/a>&lt;/td>
&lt;td>&lt;a href="https://github.com/EkType/Mukta/releases">GitHub&lt;/a>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Lohit Gujarati&lt;/strong>&lt;/td>
&lt;td>&lt;img src="namaste_lohit.png" alt="">&lt;/td>
&lt;td>sans serif&lt;/td>
&lt;td>&lt;a href="https://pagure.io/lohit">Pagure &amp;ndash; Lohit&lt;/a>&lt;/td>
&lt;td>&lt;a href="https://releases.pagure.org/lohit/">pagure releases&lt;/a>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>To use these fonts, after downloading and installing them on your
system, evaluate &lt;a href="#code-snippet--gujarati-set-fontset-font">Code Snippet 1&lt;/a> above with the
correct &amp;ldquo;FONT NAME&amp;rdquo;. For example, to set the Gujarati text to use the
&lt;em>Shruti&lt;/em> font, evaluate &lt;code class="code-inline language-emacs-lisp">&lt;span class="p">(&lt;/span>&lt;span class="nf">set-fontset-font&lt;/span> &lt;span class="s">&amp;#34;fontset-default&amp;#34;&lt;/span> &lt;span class="ss">&amp;#39;gujarati&lt;/span> &lt;span class="s">&amp;#34;Shruti&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;/code>.&lt;/p>
&lt;p>Thanks for reading (વાંચવા બદલ આભાર) 🙏!&lt;/p></description><author>Kaushal.Modi@fakeEmailToMakeValidatorHappy.com (Kaushal Modi)</author><category domain="https://scripter.co/categories/emacs">emacs</category><category domain="https://scripter.co/series/gujarati-in-emacs">Gujarati in Emacs</category><category domain="https://scripter.co/tags/gujarati">gujarati</category><category domain="https://scripter.co/tags/font">font</category><category domain="https://scripter.co/tags/100daystooffload">100DaysToOffload</category><guid>https://scripter.co/gujarati-fonts-in-emacs/</guid><pubDate>Sun, 19 Jun 2022 01:31:00 -0400</pubDate></item><item><title>Emacs Lisp: Advice Combinators</title><link>https://scripter.co/emacs-lisp-advice-combinators/</link><description>&lt;blockquote>My diagrammatic take on summarizing all the Emacs advice combinators.&lt;/blockquote>&lt;div class="ox-hugo-toc toc">
&lt;div class="heading">Table of Contents&lt;/div>
&lt;ul>
&lt;li>&lt;a href="#overview-on-using-advices">Overview on using advices&lt;/a>&lt;/li>
&lt;li>&lt;a href="#advice-combinators--before">&lt;span class="section-num">1&lt;/span> &lt;code>:before&lt;/code>&lt;/a>&lt;/li>
&lt;li>&lt;a href="#advice-combinators--after">&lt;span class="section-num">2&lt;/span> &lt;code>:after&lt;/code>&lt;/a>&lt;/li>
&lt;li>&lt;a href="#advice-combinators--override">&lt;span class="section-num">3&lt;/span> &lt;code>:override&lt;/code>&lt;/a>&lt;/li>
&lt;li>&lt;a href="#advice-combinators--around">&lt;span class="section-num">4&lt;/span> &lt;code>:around&lt;/code>&lt;/a>&lt;/li>
&lt;li>&lt;a href="#advice-combinators--before-while">&lt;span class="section-num">5&lt;/span> &lt;code>:before-while&lt;/code>&lt;/a>&lt;/li>
&lt;li>&lt;a href="#advice-combinators--before-until">&lt;span class="section-num">6&lt;/span> &lt;code>:before-until&lt;/code>&lt;/a>&lt;/li>
&lt;li>&lt;a href="#advice-combinators--after-while">&lt;span class="section-num">7&lt;/span> &lt;code>:after-while&lt;/code>&lt;/a>&lt;/li>
&lt;li>&lt;a href="#advice-combinators--after-until">&lt;span class="section-num">8&lt;/span> &lt;code>:after-until&lt;/code>&lt;/a>&lt;/li>
&lt;li>&lt;a href="#advice-combinators--filter-args">&lt;span class="section-num">9&lt;/span> &lt;code>:filter-args&lt;/code>&lt;/a>&lt;/li>
&lt;li>&lt;a href="#advice-combinators--filter-return">&lt;span class="section-num">10&lt;/span> &lt;code>:filter-return&lt;/code>&lt;/a>&lt;/li>
&lt;li>&lt;a href="#summary">Summary&lt;/a>&lt;/li>
&lt;li>&lt;a href="#advice-combinators--references">References&lt;/a>&lt;/li>
&lt;/ul>
&lt;/div>
&lt;!--endtoc-->
&lt;p>If you have read some of my earlier posts, you would know that I
really enjoy using the Emacs Advice system 😃.&lt;/p>
&lt;p>The &amp;ldquo;advice&amp;rdquo; feature lets you add to the existing definition of a
function, by &lt;em>advising the function&lt;/em>. This is a cleaner method than
redefining the whole function, because it&amp;rsquo;s easier to debug and if you
don&amp;rsquo;t need it, you can just &lt;em>remove&lt;/em> the advice.&lt;/p>
&lt;div class="note">
&lt;p>You can jump to the &lt;a href="#advice-combinators--references">References section&lt;/a> below if you need to look at
the related sections in the Emacs Lisp Manual.&lt;/p>
&lt;/div>
&lt;h2 id="overview-on-using-advices">Overview on using advices&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#overview-on-using-advices">#&lt;/a>&lt;/h2>
&lt;p>I do not plan to write a tutorial on how to write advices in
Emacs-Lisp, but here&amp;rsquo;s a 3-second primer:&lt;/p>
&lt;dl>
&lt;dt>To add an advice&lt;/dt>
&lt;dd>&lt;code class="code-inline language-emacs-lisp">&lt;span class="p">(&lt;/span>&lt;span class="nv">advice-add&lt;/span> &lt;span class="ss">&amp;#39;original-fn&lt;/span> &lt;span class="nv">&amp;lt;combinator&amp;gt;&lt;/span> &lt;span class="nf">#&amp;#39;&lt;/span>&lt;span class="nv">advising-fn&lt;/span>&lt;span class="p">)&lt;/span>&lt;/code>&lt;/dd>
&lt;dt>To remove an advice&lt;/dt>
&lt;dd>&lt;code class="code-inline language-emacs-lisp">&lt;span class="p">(&lt;/span>&lt;span class="nv">advice-remove&lt;/span> &lt;span class="ss">&amp;#39;original-fn&lt;/span> &lt;span class="nf">#&amp;#39;&lt;/span>&lt;span class="nv">advising-fn&lt;/span>&lt;span class="p">)&lt;/span>&lt;/code>&lt;/dd>
&lt;/dl>
&lt;p>This article attempts to briefly describe different ways of advising a
function, using 10 different &lt;em>combinators&lt;/em>. If you have never used
advices in your Emacs config, don&amp;rsquo;t worry. I am hopeful that the
diagrams in this post and the examples linked for some of the
combinators in the Summary section makes this concept a bit easier to
assimilate.&lt;/p>
&lt;dl>
&lt;dt>Diagram Legend&lt;/dt>
&lt;dd>&lt;ul>
&lt;li>Initial black circle: Original Fn input arguments&lt;/li>
&lt;li>Yellow box: Original Fn&lt;/li>
&lt;li>Gray box: Advising Fn&lt;/li>
&lt;li>Black circle inside a white circle: Return values&lt;/li>
&lt;/ul>
&lt;/dd>
&lt;/dl>
&lt;h2 id="advice-combinators--before">&lt;span class="section-num">1&lt;/span> &lt;code>:before&lt;/code>&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#advice-combinators--before">#&lt;/a>&lt;/h2>
&lt;p>&lt;a id="figure--advice-combinators-before">&lt;/a>&lt;/p>
&lt;figure>
&lt;img src="https://scripter.co/emacs-lisp-advice-combinators/before.svg" alt="Figure 1: :before advice"/> &lt;figcaption>
&lt;p>
&lt;span class="figure-number">Figure 1: &lt;/span>&lt;strong>:before&lt;/strong> advice
&lt;/p>
&lt;/figcaption>&lt;/figure>
&lt;h2 id="advice-combinators--after">&lt;span class="section-num">2&lt;/span> &lt;code>:after&lt;/code>&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#advice-combinators--after">#&lt;/a>&lt;/h2>
&lt;p>&lt;a id="figure--advice-combinators-after">&lt;/a>&lt;/p>
&lt;figure>
&lt;img src="https://scripter.co/emacs-lisp-advice-combinators/after.svg" alt="Figure 2: :after advice"/> &lt;figcaption>
&lt;p>
&lt;span class="figure-number">Figure 2: &lt;/span>&lt;strong>:after&lt;/strong> advice
&lt;/p>
&lt;/figcaption>&lt;/figure>
&lt;h2 id="advice-combinators--override">&lt;span class="section-num">3&lt;/span> &lt;code>:override&lt;/code>&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#advice-combinators--override">#&lt;/a>&lt;/h2>
&lt;p>&lt;a id="figure--advice-combinators-override">&lt;/a>&lt;/p>
&lt;figure>
&lt;img src="https://scripter.co/emacs-lisp-advice-combinators/override.svg" alt="Figure 3: :override advice"/> &lt;figcaption>
&lt;p>
&lt;span class="figure-number">Figure 3: &lt;/span>&lt;strong>:override&lt;/strong> advice
&lt;/p>
&lt;/figcaption>&lt;/figure>
&lt;h2 id="advice-combinators--around">&lt;span class="section-num">4&lt;/span> &lt;code>:around&lt;/code>&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#advice-combinators--around">#&lt;/a>&lt;/h2>
&lt;p>&lt;a id="figure--advice-combinators-around">&lt;/a>&lt;/p>
&lt;figure>
&lt;img src="https://scripter.co/emacs-lisp-advice-combinators/around.svg" alt="Figure 4: :around advice"/> &lt;figcaption>
&lt;p>
&lt;span class="figure-number">Figure 4: &lt;/span>&lt;strong>:around&lt;/strong> advice
&lt;/p>
&lt;/figcaption>&lt;/figure>
&lt;h2 id="advice-combinators--before-while">&lt;span class="section-num">5&lt;/span> &lt;code>:before-while&lt;/code>&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#advice-combinators--before-while">#&lt;/a>&lt;/h2>
&lt;p>&lt;a id="figure--advice-combinators-before-while">&lt;/a>&lt;/p>
&lt;figure>
&lt;img src="https://scripter.co/emacs-lisp-advice-combinators/before-while.svg" alt="Figure 5: :before-while advice"/> &lt;figcaption>
&lt;p>
&lt;span class="figure-number">Figure 5: &lt;/span>&lt;strong>:before-while&lt;/strong> advice
&lt;/p>
&lt;/figcaption>&lt;/figure>
&lt;h2 id="advice-combinators--before-until">&lt;span class="section-num">6&lt;/span> &lt;code>:before-until&lt;/code>&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#advice-combinators--before-until">#&lt;/a>&lt;/h2>
&lt;p>&lt;a id="figure--advice-combinators-before-until">&lt;/a>&lt;/p>
&lt;figure>
&lt;img src="https://scripter.co/emacs-lisp-advice-combinators/before-until.svg" alt="Figure 6: :before-until advice"/> &lt;figcaption>
&lt;p>
&lt;span class="figure-number">Figure 6: &lt;/span>&lt;strong>:before-until&lt;/strong> advice
&lt;/p>
&lt;/figcaption>&lt;/figure>
&lt;h2 id="advice-combinators--after-while">&lt;span class="section-num">7&lt;/span> &lt;code>:after-while&lt;/code>&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#advice-combinators--after-while">#&lt;/a>&lt;/h2>
&lt;p>&lt;a id="figure--advice-combinators-after-while">&lt;/a>&lt;/p>
&lt;figure>
&lt;img src="https://scripter.co/emacs-lisp-advice-combinators/after-while.svg" alt="Figure 7: :after-while advice"/> &lt;figcaption>
&lt;p>
&lt;span class="figure-number">Figure 7: &lt;/span>&lt;strong>:after-while&lt;/strong> advice
&lt;/p>
&lt;/figcaption>&lt;/figure>
&lt;h2 id="advice-combinators--after-until">&lt;span class="section-num">8&lt;/span> &lt;code>:after-until&lt;/code>&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#advice-combinators--after-until">#&lt;/a>&lt;/h2>
&lt;p>&lt;a id="figure--advice-combinators-after-until">&lt;/a>&lt;/p>
&lt;figure>
&lt;img src="https://scripter.co/emacs-lisp-advice-combinators/after-until.svg" alt="Figure 8: :after-until advice"/> &lt;figcaption>
&lt;p>
&lt;span class="figure-number">Figure 8: &lt;/span>&lt;strong>:after-until&lt;/strong> advice
&lt;/p>
&lt;/figcaption>&lt;/figure>
&lt;h2 id="advice-combinators--filter-args">&lt;span class="section-num">9&lt;/span> &lt;code>:filter-args&lt;/code>&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#advice-combinators--filter-args">#&lt;/a>&lt;/h2>
&lt;p>&lt;a id="figure--advice-combinators-filter-args">&lt;/a>&lt;/p>
&lt;figure>
&lt;img src="https://scripter.co/emacs-lisp-advice-combinators/filter-args.svg" alt="Figure 9: :filter-args advice"/> &lt;figcaption>
&lt;p>
&lt;span class="figure-number">Figure 9: &lt;/span>&lt;strong>:filter-args&lt;/strong> advice
&lt;/p>
&lt;/figcaption>&lt;/figure>
&lt;h2 id="advice-combinators--filter-return">&lt;span class="section-num">10&lt;/span> &lt;code>:filter-return&lt;/code>&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#advice-combinators--filter-return">#&lt;/a>&lt;/h2>
&lt;p>&lt;a id="figure--advice-combinators-filter-return">&lt;/a>&lt;/p>
&lt;figure>
&lt;img src="https://scripter.co/emacs-lisp-advice-combinators/filter-return.svg" alt="Figure 10: :filter-return advice"/> &lt;figcaption>
&lt;p>
&lt;span class="figure-number">Figure 10: &lt;/span>&lt;strong>:filter-return&lt;/strong> advice
&lt;/p>
&lt;/figcaption>&lt;/figure>
&lt;h2 id="summary">Summary&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#summary">#&lt;/a>&lt;/h2>
&lt;p>Here&amp;rsquo;s a concise summary of what each advice combinator does. For
brevity, the &lt;em>advising function&lt;/em> is called &lt;em>A&lt;/em> and the &lt;em>original
function&lt;/em> is called &lt;em>O&lt;/em>.&lt;/p>
&lt;div class="note">
&lt;p>Once you click on any of the example posts, search for &lt;code>advice-add&lt;/code> on
that page to find the code example.&lt;/p>
&lt;/div>
&lt;p>&lt;a id="table--advice-combinator-summary">&lt;/a>&lt;/p>
&lt;div class="table-caption">
&lt;span class="table-number">&lt;a href="#table--advice-combinator-summary">Table 1&lt;/a>:&lt;/span>
Summary of what each advice combinator means
&lt;/div>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Combinator&lt;/th>
&lt;th>Description&lt;/th>
&lt;th>Example&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>:before&lt;/code>&lt;/td>
&lt;td>&lt;em>A&lt;/em> is called before &lt;em>O&lt;/em>. &lt;em>O&lt;/em> args and return values are not modified.&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>:after&lt;/code>&lt;/td>
&lt;td>&lt;em>A&lt;/em> is called after &lt;em>O&lt;/em>. &lt;em>O&lt;/em> args and return values are not modified.&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>:override&lt;/code>&lt;/td>
&lt;td>&lt;em>A&lt;/em> is called in lieu of &lt;em>O&lt;/em>. &lt;em>A&lt;/em> gets the same args as &lt;em>O&lt;/em>.&lt;/td>
&lt;td>&lt;a href="https://scripter.co/zero-html-validation-errors/">Zero HTML Validation Errors!&lt;/a>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>:around&lt;/code>&lt;/td>
&lt;td>&lt;em>A&lt;/em> is called in lieu of &lt;em>O&lt;/em>. &lt;em>A&lt;/em> gets &lt;em>O&lt;/em> fn + &lt;em>O&lt;/em> args as args.&lt;/td>
&lt;td>&lt;a href="https://scripter.co/using-emacs-advice-to-silence-messages-from-functions/">Using Emacs advice to silence messages from functions&lt;/a>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>:before-while&lt;/code>&lt;/td>
&lt;td>&lt;em>A&lt;/em> is called first. If it returns non-nil, &lt;em>O&lt;/em> is called.&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>:before-until&lt;/code>&lt;/td>
&lt;td>&lt;em>A&lt;/em> is called first. If it returns nil, &lt;em>O&lt;/em> is called.&lt;/td>
&lt;td>&lt;a href="https://scripter.co/org-show-only-post-subtree-headings/">Org: Show only Post subtree headings&lt;/a>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>:after-while&lt;/code>&lt;/td>
&lt;td>&lt;em>O&lt;/em> is called first. If it returns non-nil, &lt;em>A&lt;/em> is called.&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>:after-until&lt;/code>&lt;/td>
&lt;td>&lt;em>O&lt;/em> is called first. If it returns nil, &lt;em>A&lt;/em> is called.&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>:filter-args&lt;/code>&lt;/td>
&lt;td>&lt;em>A&lt;/em> is called first. &lt;em>O&lt;/em> is called next with return value from &lt;em>A&lt;/em> as input.&lt;/td>
&lt;td>&lt;a href="https://scripter.co/narrowing-the-author-column-in-magit/">Narrowing the Author column in Magit&lt;/a>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>:filter-return&lt;/code>&lt;/td>
&lt;td>&lt;em>O&lt;/em> is called first. &lt;em>A&lt;/em> is called next with return value from &lt;em>O&lt;/em> as input.&lt;/td>
&lt;td>&lt;a href="https://scripter.co/zero-html-validation-errors/">Zero HTML Validation Errors!&lt;/a>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>If you have any feedback on how these diagrams can be made easier to
understand, please let me know.&lt;/p>
&lt;h2 id="advice-combinators--references">References&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#advice-combinators--references">#&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Advising-Functions.html" title="Emacs Lisp: (info &amp;quot;(elisp) Advising Functions&amp;quot;)">Elisp Info: Advising Functions&lt;/a>
&lt;ul>
&lt;li>&lt;a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Advice-Combinators.html" title="Emacs Lisp: (info &amp;quot;(elisp) Advice Combinators&amp;quot;)">Elisp Info: Advice Combinators&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul></description><author>Kaushal.Modi@fakeEmailToMakeValidatorHappy.com (Kaushal Modi)</author><category domain="https://scripter.co/categories/emacs">emacs</category><category domain="https://scripter.co/categories/elisp">elisp</category><category domain="https://scripter.co/tags/100daystooffload">100DaysToOffload</category><category domain="https://scripter.co/tags/advice">advice</category><category domain="https://scripter.co/tags/plantuml">plantuml</category><guid>https://scripter.co/emacs-lisp-advice-combinators/</guid><pubDate>Fri, 17 Jun 2022 21:30:00 -0400</pubDate></item><item><title>Org: Show only Post subtree headings</title><link>https://scripter.co/org-show-only-post-subtree-headings/</link><description>&lt;blockquote>How to define a custom &lt;code>org-global-cycle&lt;/code>-like command that collapses
only the Org subtrees with specific properties.&lt;/blockquote>&lt;div class="ox-hugo-toc toc">
&lt;div class="heading">Table of Contents&lt;/div>
&lt;ul>
&lt;li>&lt;a href="#org-global-cycle">Org Global Cycle&lt;/a>&lt;/li>
&lt;li>&lt;a href="#skeleton-of-only-post-headings">Skeleton of only Post headings&lt;/a>&lt;/li>
&lt;li>&lt;a href="#the-collapse-all-posts-function">The &amp;ldquo;Collapse All Posts&amp;rdquo; function&lt;/a>&lt;/li>
&lt;li>&lt;a href="#binding-with-c-u-c-c-tab">Binding with &lt;code>C-u C-c TAB&lt;/code>&lt;/a>&lt;/li>
&lt;li>&lt;a href="#result">Result&lt;/a>&lt;/li>
&lt;/ul>
&lt;/div>
&lt;!--endtoc-->
&lt;p>I start this post by introducing what the Org mode global cycling
command does, what kind of subtree folding I actually need, and then
share the solution with code snippets.&lt;/p>
&lt;h2 id="org-global-cycle">Org Global Cycle&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#org-global-cycle">#&lt;/a>&lt;/h2>
&lt;p>Org mode has a built-in &lt;code>org-global-cycle&lt;/code> command that you might be
familiar with. It&amp;rsquo;s bound by default to the &lt;code>S-TAB&lt;/code> key. Each time
this command is called, the Org buffer will cycle through these
states:&lt;/p>
&lt;ol>
&lt;li>Overview: Show only the Level 1 headings and collapse everything
underneath.&lt;/li>
&lt;li>Contents: Show only the Org headings and collapse all the content.&lt;/li>
&lt;li>Show All: Expand all the headings and show their contents too.&lt;/li>
&lt;/ol>
&lt;p>If a numeric prefix &lt;em>N&lt;/em> is used with this command, it will show only
the Org headings up to Level &lt;em>N&lt;/em>. For example, &lt;code>C-2 S-TAB&lt;/code> will show
only the headings up to Level 2.&lt;/p>
&lt;p>This is a really helpful command, but I needed something different ..&lt;/p>
&lt;h2 id="skeleton-of-only-post-headings">Skeleton of only Post headings&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#skeleton-of-only-post-headings">#&lt;/a>&lt;/h2>
&lt;p>I maintain most of this website&amp;rsquo;s content in a single Org file. I have
dozens of blog posts organized in Org subtrees, which I further
organize under &amp;ldquo;category&amp;rdquo; headings .. It kind of looks like the below
mock-up:
&lt;span class="sidenote-number">&lt;small class="sidenote">
It&amp;rsquo;s amazing how many features PlantUML has. If you are interested in
creating diagrams like these, check out the &lt;a href="https://plantuml.com/salt">PlantUML Salt&lt;/a> syntax.
&lt;/small>&lt;/span>&lt;/p>
&lt;p>&lt;a id="figure--post-subtrees-collapsed-mockup">&lt;/a>&lt;/p>
&lt;figure>
&lt;img src="https://scripter.co/org-show-only-post-subtree-headings/post-subtrees.svg" alt="Figure 1: Post Subtrees at arbitrary heading levels"/> &lt;figcaption>
&lt;p>
&lt;span class="figure-number">Figure 1: &lt;/span>Post Subtrees at arbitrary heading levels
&lt;/p>
&lt;/figcaption>&lt;/figure>
&lt;p>As we can see,&lt;/p>
&lt;ul>
&lt;li>All the post subtrees are not at Level 1 headings.&lt;/li>
&lt;li>They are also not at a fixed Level &lt;em>N&lt;/em>.&lt;/li>
&lt;li>The heading level of the post depends on how many parent categories
that post has (and that will also change over time).&lt;/li>
&lt;/ul>
&lt;p>I needed to basically show everything leading up to a post subtree
heading, and then collapse all the content under that post; even the
sub-headings.&lt;/p>
&lt;h2 id="the-collapse-all-posts-function">The &amp;ldquo;Collapse All Posts&amp;rdquo; function&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#the-collapse-all-posts-function">#&lt;/a>&lt;/h2>
&lt;p>The &lt;code>modi/org-hugo-collapse-all-posts&lt;/code> function defined below meets
the above requirement:&lt;/p>
&lt;ol>
&lt;li>It first widens the whole buffer and expands all the headings.&lt;/li>
&lt;li>Then it loops through all the headings and collapses all the &lt;em>post
subtrees&lt;/em> i.e. all the subtrees that have the &lt;code>EXPORT_FILE_NAME&lt;/code>
property set. This is where I use the &lt;a href="https://scripter.co/looping-through-org-mode-headings/">&lt;code>org-map-entries&lt;/code>&lt;/a> magic.&lt;/li>
&lt;li>Finally it looks for Org headings that begin with &amp;ldquo;Footnotes&amp;rdquo; or
&amp;ldquo;COMMENT&amp;rdquo; and collapses them as well.&lt;/li>
&lt;/ol>
&lt;p>I am using the development version of Org mode (version 9.6, yet to be
released as of &lt;span class="timestamp-wrapper">&lt;span class="timestamp">&amp;lt;2022-06-15 Wed&amp;gt;&lt;/span>&lt;/span>) which has the new &lt;code>org-fold&lt;/code>
library. This library obsoletes the use of &lt;code>outline.el&lt;/code> library and
other &lt;em>code-folding&lt;/em> related functions in Org mode. So &lt;code>cl-flet&lt;/code> is
used to create function symbol aliases that use the &lt;code>org-fold-*&lt;/code>
functions if available, otherwise they fall back to the legacy
functions.&lt;/p>
&lt;p>&lt;a id="code-snippet--collapse-all-posts-fn">&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="hl">&lt;span class="lnt">19
&lt;/span>&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="hl">&lt;span class="lnt">23
&lt;/span>&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-emacs-lisp" data-lang="emacs-lisp">&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="nb">defun&lt;/span> &lt;span class="nv">modi/org-hugo-collapse-all-posts&lt;/span> &lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;Collapse all post subtrees in the current buffer.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">Also collapse the Footnotes subtree and COMMENT subtrees if
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">present.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">A post subtree is one that has the EXPORT_FILE_NAME property
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">set.&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">interactive&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">cl-flet&lt;/span> &lt;span class="p">((&lt;/span>&lt;span class="nv">show-all&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nb">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">fboundp&lt;/span> &lt;span class="ss">&amp;#39;org-fold-show-all&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">#&amp;#39;&lt;/span>&lt;span class="nv">org-fold-show-all&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">#&amp;#39;&lt;/span>&lt;span class="nv">org-show-all&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">hide-subtree&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nb">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">fboundp&lt;/span> &lt;span class="ss">&amp;#39;org-fold-hide-subtree&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">#&amp;#39;&lt;/span>&lt;span class="nv">org-fold-hide-subtree&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">#&amp;#39;&lt;/span>&lt;span class="nv">outline-hide-subtree&lt;/span>&lt;span class="p">)))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nf">widen&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">show-all&lt;/span> &lt;span class="o">&amp;#39;&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nv">headings&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">;; Collapse all the post subtrees (ones with EXPORT_FILE_NAME&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">;; property set).&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line hl">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">org-map-entries&lt;/span> &lt;span class="nf">#&amp;#39;&lt;/span>&lt;span class="nv">hide-subtree&lt;/span> &lt;span class="s">&amp;#34;EXPORT_FILE_NAME&amp;lt;&amp;gt;\&amp;#34;\&amp;#34;&amp;#34;&lt;/span> &lt;span class="ss">&amp;#39;file&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">;; Also hide Footnotes and comments.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">save-excursion&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nf">goto-char&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">point-min&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line hl">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">while&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">re-search-forward&lt;/span> &lt;span class="s">&amp;#34;^\\(\\* Footnotes\\|\\*+ COMMENT\\)&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="no">nil&lt;/span> &lt;span class="nb">:noerror&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">hide-subtree&lt;/span>&lt;span class="p">)))))&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="src-block-caption">
&lt;span class="src-block-number">&lt;a href="#code-snippet--collapse-all-posts-fn">Code Snippet 1&lt;/a>:&lt;/span>
Function that collapses all the post subtrees in the current buffer
&lt;/div>
&lt;h2 id="binding-with-c-u-c-c-tab">Binding with &lt;code>C-u C-c TAB&lt;/code>&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#binding-with-c-u-c-c-tab">#&lt;/a>&lt;/h2>
&lt;p>The function is ready, but let&amp;rsquo;s now add a bit of convenience to it.&lt;/p>
&lt;p>If a point is under a subtree, &lt;code>C-c TAB&lt;/code> will collapse that subtree
while showing only Level 1 headings, and if a numeric prefix is used,
it will show only those many levels of headings. I decided to bind the
above function to &lt;code>C-u C-c TAB&lt;/code> because,&lt;/p>
&lt;ol>
&lt;li>The behavior of &lt;code>modi/org-hugo-collapse-all-posts&lt;/code> falls in the
same category as that of &lt;code>C-c TAB&lt;/code>.&lt;/li>
&lt;li>The &lt;code>C-u C-c ..&lt;/code> binding rolls off the fingers pretty
nicely 😃.&lt;/li>
&lt;/ol>
&lt;p>This &lt;em>binding&lt;/em> is achieved using one of my favorite Emacs features
.. the &lt;strong>advice&lt;/strong> system. The &lt;code>:before-until&lt;/code> &lt;a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Advice-Combinators.html" title="Emacs Lisp: (info &amp;quot;(elisp) Advice Combinators&amp;quot;)">Advice Combinator&lt;/a> is used
here, which means that if the &lt;em>advising&lt;/em> function (below) returns a
&lt;em>nil&lt;/em>, the &lt;em>advised&lt;/em> or the original function &lt;code>org-ctrl-c-tab&lt;/code> is not
called.&lt;/p>
&lt;p>The &lt;em>advising&lt;/em> function below detects if the &lt;code>C-u&lt;/code> prefix argument is
used. If it is, the &lt;code>modi/org-hugo-collapse-all-posts&lt;/code> function is
called, otherwise the original &lt;code>org-ctrl-c-tab&lt;/code> function is called.&lt;/p>
&lt;p>&lt;a id="code-snippet--collapse-all-posts-binding">&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="hl">&lt;span class="lnt">4
&lt;/span>&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-emacs-lisp" data-lang="emacs-lisp">&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="nb">defun&lt;/span> &lt;span class="nv">modi/org-ctrl-c-tab-advice&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kp">&amp;amp;rest&lt;/span> &lt;span class="nv">args&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;Run &lt;/span>&lt;span class="ss">`modi/org-hugo-collapse-all-posts&amp;#39;&lt;/span>&lt;span class="s"> when
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">doing \\[universal-argument] \\[org-ctrl-c-tab].&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line hl">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">let&lt;/span> &lt;span class="p">((&lt;/span>&lt;span class="nv">do-not-run-orig-fn&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">equal&lt;/span> &lt;span class="o">&amp;#39;&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">4&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="nv">current-prefix-arg&lt;/span>&lt;span class="p">)))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">when&lt;/span> &lt;span class="nv">do-not-run-orig-fn&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">modi/org-hugo-collapse-all-posts&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">do-not-run-orig-fn&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="nv">advice-add&lt;/span> &lt;span class="ss">&amp;#39;org-ctrl-c-tab&lt;/span> &lt;span class="nb">:before-until&lt;/span> &lt;span class="nf">#&amp;#39;&lt;/span>&lt;span class="nv">modi/org-ctrl-c-tab-advice&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="src-block-caption">
&lt;span class="src-block-number">&lt;a href="#code-snippet--collapse-all-posts-binding">Code Snippet 2&lt;/a>:&lt;/span>
Bind &lt;code>C-u C-c TAB&lt;/code> to call &lt;code>modi/org-hugo-collapse-all-posts&lt;/code>
&lt;/div>
&lt;h2 id="result">Result&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#result">#&lt;/a>&lt;/h2>
&lt;p>After evaluating the above two snippets, when I do &lt;code>C-u C-c TAB&lt;/code> in
my &amp;ldquo;blog posts&amp;rdquo; Org buffer, I see this:&lt;/p>
&lt;p>&lt;a id="figure--post-subtrees-collapsed">&lt;/a>&lt;/p>
&lt;figure>
&lt;a href="post-subtrees-collapsed.png">
&lt;img src="https://scripter.co/org-show-only-post-subtree-headings/post-subtrees-collapsed.png" alt="Figure 2: My &amp;ldquo;blog posts&amp;rdquo; Org buffer showing only the Post subtree headings"/> &lt;/a>&lt;figcaption>
&lt;p>
&lt;span class="figure-number">Figure 2: &lt;/span>My &amp;ldquo;blog posts&amp;rdquo; Org buffer showing only the Post subtree headings
&lt;/p>
&lt;/figcaption>&lt;/figure>
&lt;p>It matches &lt;a href="#figure--post-subtrees-collapsed-mockup">that earlier mockup&lt;/a> &amp;mdash; Mission accomplished! 💯&lt;/p></description><author>Kaushal.Modi@fakeEmailToMakeValidatorHappy.com (Kaushal Modi)</author><category domain="https://scripter.co/categories/emacs">emacs</category><category domain="https://scripter.co/categories/org">org</category><category domain="https://scripter.co/categories/elisp">elisp</category><category domain="https://scripter.co/tags/100daystooffload">100DaysToOffload</category><category domain="https://scripter.co/tags/subtree">subtree</category><category domain="https://scripter.co/tags/looping">looping</category><category domain="https://scripter.co/tags/advice">advice</category><guid>https://scripter.co/org-show-only-post-subtree-headings/</guid><pubDate>Thu, 16 Jun 2022 00:21:00 -0400</pubDate></item><item><title>Zero HTML Validation Errors!</title><link>https://scripter.co/zero-html-validation-errors/</link><description>&lt;blockquote>How I fixed my site content and went down from 46 HTML validations
errors down to 0!&lt;/blockquote>&lt;div class="ox-hugo-toc toc">
&lt;div class="heading">Table of Contents&lt;/div>
&lt;ul>
&lt;li>&lt;a href="#avoid-duplicate-heading-id-attributes">&lt;span class="section-num">1&lt;/span> Avoid duplicate heading &lt;code>id&lt;/code> attributes&lt;/a>&lt;/li>
&lt;li>&lt;a href="#remove-inline-style-elements">&lt;span class="section-num">2&lt;/span> Remove inline &lt;code>&amp;lt;style&amp;gt;&lt;/code> elements&lt;/a>&lt;/li>
&lt;li>&lt;a href="#ensure-that-all-images-have-captions-or-alt-attributes">&lt;span class="section-num">3&lt;/span> Ensure that all images have captions or &lt;code>alt&lt;/code> attributes&lt;/a>&lt;/li>
&lt;li>&lt;a href="#do-not-have-hyperlinks-in-headings">&lt;span class="section-num">4&lt;/span> Do not have hyperlinks in headings&lt;/a>&lt;/li>
&lt;li>&lt;a href="#validation-ignores">Validation Ignores&lt;/a>
&lt;ul>
&lt;li>&lt;a href="#ignore-errors-due-to-hyperlinks-in-inline-svg">&lt;span class="section-num">5&lt;/span> Ignore errors due to hyperlinks in inline SVG&lt;/a>&lt;/li>
&lt;li>&lt;a href="#ignore-files-not-expected-to-serve-html-content">&lt;span class="section-num">6&lt;/span> Ignore files not expected to serve HTML content&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;a href="#summary">Summary&lt;/a>&lt;/li>
&lt;/ul>
&lt;/div>
&lt;!--endtoc-->
&lt;p>In my &lt;a href="https://scripter.co/offline-html5-validator/">previous HTML5 Validator post&lt;/a>, I mentioned:&lt;/p>
&lt;blockquote>
&lt;p>I was a bit disappointed to see validation errors on my site, but then
it wasn&amp;rsquo;t too bad .. 46 errors.&lt;/p>
&lt;/blockquote>
&lt;p>But they truly say ..&lt;/p>
&lt;div class="org-center">
&lt;p>Ignorance is bliss.&lt;/p>
&lt;/div>
&lt;p>So .. once I realized that my site had 46 validation errors, I lost
that &lt;em>bliss&lt;/em> .. and I couldn&amp;rsquo;t rest easy &amp;mdash; I had to fix them all
😁.&lt;/p>
&lt;p>This post summarizes the categories of those errors and how I fixed
&lt;span class="sidenote-number">&lt;small class="sidenote">
The fixes mentioned in this post refer to changes in Org mode
content. But you should be able to derive equivalent fixes for
Markdown too.
&lt;/small>&lt;/span>
them all.&lt;/p>
&lt;h2 id="avoid-duplicate-heading-id-attributes">&lt;span class="section-num">1&lt;/span> Avoid duplicate heading &lt;code>id&lt;/code> attributes&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#avoid-duplicate-heading-id-attributes">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/notes/​string-fns-nim-vs-python/index.html&amp;#34;:636.34-636.46: error: Duplicate ID &amp;#34;notes&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/notes/​nim-fmt/index.html&amp;#34;:300.34-300.52: error: Duplicate ID &amp;#34;older-issue&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/notes/​nim-fmt/index.html&amp;#34;:306.20-306.33: error: Duplicate ID &amp;#34;floats&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/page/6/index.html&amp;#34;:29.39-29.54: error: Duplicate ID &amp;#34;fnref:1&amp;#34;.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Errors with above kind of signatures were fixed by,&lt;/p>
&lt;ol>
&lt;li>
&lt;p>Converting headings to description lists&lt;/p>
&lt;p>I had a bunch of generic headings like &amp;ldquo;Notes&amp;rdquo; and &amp;ldquo;Older Issue&amp;rdquo; in
some of my posts. After taking a second look at those, it made more
sense to convert those to description lists. So in Org mode, I
converted headings like &lt;code class="code-inline language-org">&lt;span class="gh">*&lt;/span>&lt;span class="gs"> Notes&lt;/span>&lt;/code> to
description lists &lt;code class="code-inline language-org">&lt;span class="k">- &lt;/span>Notes ::&lt;/code>.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Setting &lt;code>CUSTOM_ID&lt;/code> heading property&lt;/p>
&lt;p>For the cases, where the headings needed to be left as so, their
IDs were uniquified by setting their &lt;code>CUSTOM_ID&lt;/code> property. For
example, below fixed the &lt;em>Duplicate ID &amp;ldquo;floats&amp;rdquo;&lt;/em> errors.
&lt;a id="code-snippet--using-custom-id-to-uniquify-heading-id">&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-diff" data-lang="diff">&lt;span class="line">&lt;span class="cl"> ** Precision
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ..
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> *** Floats
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">+:PROPERTIES:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">+:CUSTOM_ID: precision-floats
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">+:END:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">&lt;/span> ..
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ** Type (only for numbers)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ..
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> *** Floats
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">+:PROPERTIES:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">+:CUSTOM_ID: type-floats
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">+:END:
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="src-block-caption">
&lt;span class="src-block-number">&lt;a href="#code-snippet--using-custom-id-to-uniquify-heading-id">Code Snippet 1&lt;/a>:&lt;/span>
Using &lt;code>CUSTOM_ID&lt;/code> property to uniquify heading ID's
&lt;/div>
&lt;/li>
&lt;li>
&lt;p>Prevent footnote links in post summaries&lt;/p>
&lt;p>This issue was due to me not being conscious about how the footnote
references work in a post &lt;em>versus&lt;/em> on a page outside that post&amp;rsquo;s
context. The issue was caused by footnote references getting into
the post summaries parsed by Hugo, which will then show up on the
list pages.&lt;/p>
&lt;p>The fix was simple &amp;mdash; Edit the post summaries so that they don&amp;rsquo;t
contain any footnote references.&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h2 id="remove-inline-style-elements">&lt;span class="section-num">2&lt;/span> Remove inline &lt;code>&amp;lt;style&amp;gt;&lt;/code> elements&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#remove-inline-style-elements">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/​grep-po/index.html&amp;#34;:51.139-51.145: error: Element &amp;#34;style&amp;#34; not allowed as child of element &amp;#34;div&amp;#34; in this context. (Suppressing further errors from this subtree.)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/​how-do-i-write-org-mode/index.html&amp;#34;:23.194-23.200: error: Element &amp;#34;style&amp;#34; not allowed as child of element &amp;#34;div&amp;#34; in this context. (Suppressing further errors from this subtree.)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Errors with above kind of signatures were fixed by,&lt;/p>
&lt;ol>
&lt;li>
&lt;p>Avoiding export of raw &lt;code>&amp;lt;style&amp;gt;&lt;/code> elements in the Markdown content&lt;/p>
&lt;p>I figured out which functions were responsible for injecting
&lt;code>&amp;lt;style&amp;gt;&lt;/code> elements in Markdown content and then advised them to
stop that. After applying these advises, I lost the in-content
rules for CSS classes &lt;code>.org-center&lt;/code> and &lt;code>.csl-entry&lt;/code>. So I put
those rules directly in this website&amp;rsquo;s CSS.
&lt;a id="code-snippet--advices-to-prevent-style-elem-in-exports">&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-emacs-lisp" data-lang="emacs-lisp">&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="nb">defun&lt;/span> &lt;span class="nv">modi/org-blackfriday-center-block&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nv">_center-block&lt;/span> &lt;span class="nv">contents&lt;/span> &lt;span class="nv">info&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">let*&lt;/span> &lt;span class="p">((&lt;/span>&lt;span class="nv">class&lt;/span> &lt;span class="s">&amp;#34;org-center&amp;#34;&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nf">format&lt;/span> &lt;span class="s">&amp;#34;&amp;lt;div class=\&amp;#34;%s\&amp;#34;&amp;gt;%s\n\n%s\n&amp;lt;/div&amp;gt;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">class&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nv">org-blackfriday--extra-div-hack&lt;/span> &lt;span class="nv">info&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="nv">contents&lt;/span>&lt;span class="p">)))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="nv">advice-add&lt;/span> &lt;span class="ss">&amp;#39;org-blackfriday-center-block&lt;/span> &lt;span class="nb">:override&lt;/span> &lt;span class="nf">#&amp;#39;&lt;/span>&lt;span class="nv">modi/org-blackfriday-center-block&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="nb">defun&lt;/span> &lt;span class="nv">modi/org-cite-csl-render-bibliography&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nv">bib-str&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">replace-regexp-in-string&lt;/span> &lt;span class="s">&amp;#34;&amp;lt;style&amp;gt;\\.csl-entry[^&amp;lt;]+&amp;lt;/style&amp;gt;&amp;#34;&lt;/span> &lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="nv">bib-str&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="nv">advice-add&lt;/span> &lt;span class="ss">&amp;#39;org-cite-csl-render-bibliography&lt;/span> &lt;span class="nb">:filter-return&lt;/span> &lt;span class="nf">#&amp;#39;&lt;/span>&lt;span class="nv">modi/org-cite-csl-render-bibliography&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="src-block-caption">
&lt;span class="src-block-number">&lt;a href="#code-snippet--advices-to-prevent-style-elem-in-exports">Code Snippet 2&lt;/a>:&lt;/span>
Emacs-Lisp advices to prevent &lt;code>&amp;lt;style&amp;gt;&lt;/code> elements in exports
&lt;/div>
&lt;/li>
&lt;li>
&lt;p>Removing unnecessary micro-styling&lt;/p>
&lt;p>I found a single case, where an inline CSS rule was defined in
content for CSS class &lt;code>.repr-type&lt;/code> for a table. I just removed that
without affecting the looks of that rendered table too much.&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h2 id="ensure-that-all-images-have-captions-or-alt-attributes">&lt;span class="section-num">3&lt;/span> Ensure that all images have captions or &lt;code>alt&lt;/code> attributes&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#ensure-that-all-images-have-captions-or-alt-attributes">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/​hugo-use-goat-code-blocks-for-ascii-diagrams/index.html&amp;#34;:24.130-24.255: error: An &amp;#34;img&amp;#34; element must have an &amp;#34;alt&amp;#34; attribute, except under certain conditions. For details, consult guidance on providing text alternatives for images.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Errors with above kind of signatures were easily fixed by ensuring
that all images had captions
&lt;span class="sidenote-number">&lt;small class="sidenote">
Thankfully, there were only two images that were missing captions.
&lt;/small>&lt;/span>
. The Hugo &lt;code>figure&lt;/code> shortcode adds the caption to the &lt;code>alt&lt;/code> attribute if
the &lt;code>alt&lt;/code> is not specified separately.&lt;/p>
&lt;p>As an example, here&amp;rsquo;s how I fixed the above error:&lt;/p>
&lt;p>&lt;a id="code-snippet--adding-a-caption-to-an-image">&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-diff" data-lang="diff">&lt;span class="line">&lt;span class="cl">&lt;span class="gi">+ #+name: fig__disproportionate_box_drawing
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">+ #+caption: Disproportionate box drawing characters
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">&lt;/span>[[file:images/​hugo-use-goat-code-blocks-for-ascii-diagrams/ascii-diagram-rendered-in-plain-text-code-block.png]]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="src-block-caption">
&lt;span class="src-block-number">&lt;a href="#code-snippet--adding-a-caption-to-an-image">Code Snippet 3&lt;/a>:&lt;/span>
A &lt;code>git diff&lt;/code> showing addition of caption to an image
&lt;/div>
&lt;h2 id="do-not-have-hyperlinks-in-headings">&lt;span class="section-num">4&lt;/span> Do not have hyperlinks in headings&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#do-not-have-hyperlinks-in-headings">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/​using-emacs-advice-to-silence-messages-from-functions/index.html&amp;#34;:151.687-151.732: error: Start tag &amp;#34;a&amp;#34; seen but an element of the same type was already open.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/​using-emacs-advice-to-silence-messages-from-functions/index.html&amp;#34;:151.748-151.751: error: Stray end tag &amp;#34;a&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/​auto-count-100daystooffload-posts/index.html&amp;#34;:114.446-114.475: error: Start tag &amp;#34;a&amp;#34; seen but an element of the same type was already open.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/​auto-count-100daystooffload-posts/index.html&amp;#34;:114.446-114.475: error: End tag &amp;#34;a&amp;#34; violates nesting rules.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/​auto-count-100daystooffload-posts/index.html&amp;#34;:114.526-114.529: error: Stray end tag &amp;#34;a&amp;#34;.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>While the hyperlinks in headings work well, they created invalid HTML
in the Hugo-generated TOC. So while these errors were created
technically because of a bug in Hugo
&lt;span class="sidenote-number">&lt;small class="sidenote">
It&amp;rsquo;s really cool when you end up finding a bug in an upstream project
while trying to fix the errors in your own thing 😎.
&lt;/small>&lt;/span>
, I wanted to fix these errors on my end as soon as I can.&lt;/p>
&lt;p>I reviewed the errors, and this is all it took to get rid of them all:&lt;/p>
&lt;ol>
&lt;li>
&lt;p>Remove manually inserting hyperlinks in headings
&lt;a id="code-snippet--removing-hyperlink-from-a-heading">&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-diff" data-lang="diff">&lt;span class="line">&lt;span class="cl"> show two methods of finding sources of any printed messages.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gd">-***** Using plain-old /grep/ or [[https://github.com/BurntSushi/ripgrep][/rg/]]
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gd">&lt;/span>&lt;span class="gi">+***** Using plain-old /grep/ or /ripgrep (rg)/
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">&lt;/span> This method is pretty easy (but not robust) to use if the search
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ..
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Org source directory and search for the /&amp;#34;org-babel-exp process ..&amp;#34;/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gd">-string ..
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gd">&lt;/span>&lt;span class="gi">+string using [[https://github.com/BurntSushi/ripgrep][~rg~]] ..
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="src-block-caption">
&lt;span class="src-block-number">&lt;a href="#code-snippet--removing-hyperlink-from-a-heading">Code Snippet 4&lt;/a>:&lt;/span>
Removing hyperlink from a heading
&lt;/div>
&lt;/li>
&lt;li>
&lt;p>Remove Org Radio links that created links in headings&lt;/p>
&lt;p>Here, a Org heading happened to contain the string &amp;ldquo;Day count&amp;rdquo;,
which was also an &lt;a href="https://orgmode.org/manual/Radio-Targets.html" title="Emacs Lisp: (info &amp;quot;(org) Radio Targets&amp;quot;)">an Org Radio link&lt;/a> in that post. While ideally
that shouldn&amp;rsquo;t have mattered, I removed that radio link to get
around this Hugo bug.
&lt;a id="code-snippet--removing-an-org-radio-link">&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-diff" data-lang="diff">&lt;span class="line">&lt;span class="cl"> .. /Just may be/. But regardless, I am already enjoying writing once
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gd">-again, and it&amp;#39;s great to see the &amp;lt;&amp;lt;&amp;lt;Day count&amp;gt;&amp;gt;&amp;gt; (counting up to 100)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gd">&lt;/span>&lt;span class="gi">+again, and it&amp;#39;s great to see the Day count (counting up to 100)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">&lt;/span> increase with each new post!
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="src-block-caption">
&lt;span class="src-block-number">&lt;a href="#code-snippet--removing-an-org-radio-link">Code Snippet 5&lt;/a>:&lt;/span>
Removing an Org Radio link
&lt;/div>
&lt;/li>
&lt;/ol>
&lt;h2 id="validation-ignores">Validation Ignores&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#validation-ignores">#&lt;/a>&lt;/h2>
&lt;p>Above fixes fixed 43 out of 46 errors, but the remaining 3 were unfixable.&lt;/p>
&lt;h3 id="ignore-errors-due-to-hyperlinks-in-inline-svg">&lt;span class="section-num">5&lt;/span> Ignore errors due to hyperlinks in inline SVG&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#ignore-errors-due-to-hyperlinks-in-inline-svg">#&lt;/a>&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/notes/​plantuml/index.html&amp;#34;:114.474-114.678: error: Attribute &amp;#34;title&amp;#34; not allowed on element &amp;#34;a&amp;#34; at this point.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This error was caused by hyperlinks in inline SVG elements. These SVG
elements are created by &lt;a href="https://plantuml.com/">PlantUML&lt;/a>. The &lt;em>hyperlinks in SVG&lt;/em> feature
works great, and as these are generated by PlantUML, I chose to just
ignore these errors.&lt;/p>
&lt;p>I ignored this error by adding the &lt;code>--ignore-re 'notes/plantuml.*Attribute.*title.*not allowed'&lt;/code> switch to the
&lt;code>html5validator&lt;/code> command.&lt;/p>
&lt;h3 id="ignore-files-not-expected-to-serve-html-content">&lt;span class="section-num">6&lt;/span> Ignore files not expected to serve HTML content&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#ignore-files-not-expected-to-serve-html-content">#&lt;/a>&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/googleFOO.html&amp;#34;:1.1-1.52: error: Non-space characters found without seeing a doctype first. Expected &amp;#34;&amp;lt;!DOCTYPE html&amp;gt;&amp;#34;.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The &lt;code>googleFOO.html&lt;/code> file here is not a valid HTML file. It&amp;rsquo;s a just a
&lt;em>cookie&lt;/em> file that was used by Google to verify that I own this
domain.&lt;/p>
&lt;p>This error was masked by adding the &lt;code>--ignore 'googleFOO'&lt;/code> switch to
the &lt;code>html5validator&lt;/code> command.&lt;/p>
&lt;h2 id="summary">Summary&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#summary">#&lt;/a>&lt;/h2>
&lt;p>Once I fixed the 43 errors by tweaking the Org mode content, and added
those two ignores, I had &lt;strong>zero validation errors&lt;/strong>! 🎉&lt;/p>
&lt;p>If you are interested in the fix details, &lt;a href="https://gitlab.com/kaushalmodi/kaushalmodi.gitlab.io/-/compare/a7cac5dd1293442a51fd5020a3bcef8da7f75fdc...42d6c72d533c337b5c67fa09207f68e45efe6e6c">here are the commits&lt;/a>.&lt;/p></description><author>Kaushal.Modi@fakeEmailToMakeValidatorHappy.com (Kaushal Modi)</author><category domain="https://scripter.co/categories/emacs">emacs</category><category domain="https://scripter.co/categories/web">web</category><category domain="https://scripter.co/categories/org">org</category><category domain="https://scripter.co/series/html5-validator">HTML5 Validator</category><category domain="https://scripter.co/tags/html">html</category><category domain="https://scripter.co/tags/validator">validator</category><category domain="https://scripter.co/tags/100daystooffload">100DaysToOffload</category><guid>https://scripter.co/zero-html-validation-errors/</guid><pubDate>Sun, 05 Jun 2022 17:58:00 -0400</pubDate></item><item><title>Looping through Org mode headings</title><link>https://scripter.co/looping-through-org-mode-headings/</link><description>&lt;blockquote>Using the &lt;code>org-map-entries&lt;/code> API to loop through selected or all
headings in an Org file.&lt;/blockquote>&lt;div class="ox-hugo-toc toc">
&lt;div class="heading">Table of Contents&lt;/div>
&lt;ul>
&lt;li>&lt;a href="#org-map-entries-api">&lt;code>org-map-entries&lt;/code> API&lt;/a>
&lt;ul>
&lt;li>&lt;a href="#match-strings">&lt;em>MATCH&lt;/em> strings&lt;/a>&lt;/li>
&lt;li>&lt;a href="#comparison-types">Comparison Types&lt;/a>&lt;/li>
&lt;li>&lt;a href="#other-notes">Other notes&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;a href="#example-modifying-a-property-in-all-headings">Example: Modifying a property in all headings&lt;/a>&lt;/li>
&lt;li>&lt;a href="#org-map-entries-references">&lt;code>org-map-entries&lt;/code> References&lt;/a>&lt;/li>
&lt;/ul>
&lt;/div>
&lt;!--endtoc-->
&lt;p>&lt;a href="https://framapiaf.org/@postroutine/108313152514542145">Below question&lt;/a> on Mastodon by the user &lt;a href="https://framapiaf.org/@postroutine">@postroutine&lt;/a> inspired me to
write this post:&lt;/p>
&lt;blockquote>
&lt;p>I got a lot of Org-Mode headings and I want to modify their properties
(add, remove, edit). Is there a function to do the same modifications
on each heading?&lt;/p>
&lt;/blockquote>
&lt;p>I think that the best solution to that question is using the
&lt;strong>org-map-entries&lt;/strong> function.&lt;/p>
&lt;p>But somehow when replying to that question then, that wasn&amp;rsquo;t what
first came to my mind! .. when ironically that function is the &lt;a href="https://github.com/kaushalmodi/ox-hugo/blob/2b169e5e83d608e80f4faee9d681b98d87041f58/ox-hugo.el#L4781-L4788">main
function&lt;/a> that enables my preferred &lt;em>subtree-based flow&lt;/em> in &lt;code>ox-hugo&lt;/code>
😆. So I am writing this post to better ingrain the following
concept in myself ..&lt;/p>
&lt;div class="note">
&lt;p>If you need to loop through headings in an Org buffer, and especially
if you &lt;strong>need to modify that buffer&lt;/strong> in the process, use
&lt;strong>org-map-entries&lt;/strong>&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>.&lt;/p>
&lt;/div>
&lt;p>Next,&lt;/p>
&lt;ol>
&lt;li>I will give a give introduction to the &lt;code>org-map-entries&lt;/code> API.&lt;/li>
&lt;li>Then provide a super-short solution to the above question.&lt;/li>
&lt;/ol>
&lt;h2 id="org-map-entries-api">&lt;code>org-map-entries&lt;/code> API&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#org-map-entries-api">#&lt;/a>&lt;/h2>
&lt;p>I will give only a broad level overview on how to use this function. I
would encourage the reader to refer to the resources at the end of
this post to learn more about it.&lt;/p>
&lt;p>So let&amp;rsquo;s start by looking at this function&amp;rsquo;s signature:&lt;/p>
&lt;p>&lt;a id="code-snippet--org-map-entries-signature">&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-emacs-lisp" data-lang="emacs-lisp">&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="nv">org-map-entries&lt;/span> &lt;span class="nv">FUNC&lt;/span> &lt;span class="kp">&amp;amp;optional&lt;/span> &lt;span class="nv">MATCH&lt;/span> &lt;span class="nv">SCOPE&lt;/span> &lt;span class="kp">&amp;amp;rest&lt;/span> &lt;span class="nv">SKIP&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="src-block-caption">
&lt;span class="src-block-number">&lt;a href="#code-snippet--org-map-entries-signature">Code Snippet 1&lt;/a>:&lt;/span>
Signature of the &lt;code>org-map-entries&lt;/code> function
&lt;/div>
&lt;p>The &lt;code>org-map-entries&lt;/code> function iterates through all the headings
meeting the &lt;em>MATCH&lt;/em> criteria in the determined &lt;em>SCOPE&lt;/em>, and then calls
the specified function &lt;em>FUNC&lt;/em> at each of those headings.&lt;/p>
&lt;ul>
&lt;li>The &lt;code>FUNC&lt;/code> function accepts &lt;strong>no&lt;/strong> arguments and is called at the
beginning of each Org heading.&lt;/li>
&lt;li>The optional second argument &lt;em>MATCH&lt;/em> is either &lt;em>nil&lt;/em>, &lt;code>t&lt;/code> or a
&lt;em>search string&lt;/em>.
&lt;ul>
&lt;li>If &lt;em>MATCH&lt;/em> is &lt;em>nil&lt;/em> or &lt;code>t&lt;/code>, &lt;strong>all&lt;/strong> headings will be visited by the
iteration and &lt;em>FUNC&lt;/em> will be called on all of them.&lt;/li>
&lt;li>But if &lt;em>MATCH&lt;/em> is a string, the headings will first be filtered
based on that string and then the &lt;em>FUNC&lt;/em> will be called on only
those.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>For explanations on the optional &lt;em>SCOPE&lt;/em> and &lt;em>SKIP&lt;/em> arguments, see
&lt;a href="https://orgmode.org/manual/Using-the-Mapping-API.html" title="Emacs Lisp: (info &amp;quot;(org) Using the Mapping API&amp;quot;)">Org Info: Using the Mapping API&lt;/a> or &lt;kbd>C-h&lt;/kbd> &lt;kbd>f&lt;/kbd> &lt;code>org-map-entries&lt;/code> from
within Emacs.&lt;/li>
&lt;/ul>
&lt;p>Here&amp;rsquo;s a typical &lt;code>org-map-entries&lt;/code> call that loops through &lt;strong>all&lt;/strong> the
headings in the &lt;strong>visible&lt;/strong> buffer: &lt;code class="code-inline language-emacs-lisp">&lt;span class="p">(&lt;/span>&lt;span class="nv">org-map-entries&lt;/span> &lt;span class="nf">#&amp;#39;&lt;/span>&lt;span class="nv">some-function&lt;/span>&lt;span class="p">)&lt;/span>&lt;/code> where all the optional
argument values are &lt;em>nil&lt;/em>. Next, we&amp;rsquo;ll see some examples of
string-type &lt;em>MATCH&lt;/em> arguments used for filtering the headings.&lt;/p>
&lt;h3 id="match-strings">&lt;em>MATCH&lt;/em> strings&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#match-strings">#&lt;/a>&lt;/h3>
&lt;p>Below table shows few examples of match string patterns.&lt;/p>
&lt;p>&lt;a id="table--org-map-entries-search-strings">&lt;/a>&lt;/p>
&lt;div class="table-caption">
&lt;span class="table-number">&lt;a href="#table--org-map-entries-search-strings">Table 1&lt;/a>:&lt;/span>
String-type &lt;i>MATCH&lt;/i> argument examples for &lt;code>org-map-entries&lt;/code>
&lt;/div>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Search string&lt;/th>
&lt;th>Description&lt;/th>
&lt;th>Example&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>&lt;code>&amp;quot;TAG&amp;quot;&lt;/code>&lt;/strong>&lt;/td>
&lt;td>Tag name&lt;/td>
&lt;td>&lt;code>&amp;quot;foo&amp;quot;&lt;/code> matches all headings with that tag&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>&lt;code>&amp;quot;{TAG REGEXP}&amp;quot;&lt;/code>&lt;/strong>&lt;/td>
&lt;td>Regexp matching tags&lt;/td>
&lt;td>&lt;code>&amp;quot;{f.*}&amp;quot;&lt;/code> matches all headings whose tags match that regexp&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>&lt;code>&amp;quot;TAG1+TAG2+..&amp;quot;&lt;/code>&lt;/strong>&lt;/td>
&lt;td>Tag set intersection&lt;/td>
&lt;td>&lt;code>&amp;quot;foo+bar&amp;quot;&lt;/code> matches all headings with both of those tags&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>&lt;code>&amp;quot;TAG1-TAG2+..&amp;quot;&lt;/code>&lt;/strong>&lt;/td>
&lt;td>Tag set difference&lt;/td>
&lt;td>&lt;code>&amp;quot;foo-bar&amp;quot;&lt;/code> matches all headings with &lt;code>foo&lt;/code> tag but without &lt;code>bar&lt;/code> tag&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>&lt;code>&amp;quot;TAG1&lt;/code>|​&lt;code>TAG2&lt;/code>|​&lt;code>..&amp;quot;&lt;/code>&lt;/strong>&lt;/td>
&lt;td>Tag set union or boolean &lt;em>OR&lt;/em>&lt;/td>
&lt;td>&lt;code>&amp;quot;foo&lt;/code>​|​&lt;code>bar&amp;quot;&lt;/code> matches all headings with either of those tags&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>&lt;code>&amp;quot;TAG1&amp;amp;TAG2&amp;amp;..&amp;quot;&lt;/code>&lt;/strong>&lt;/td>
&lt;td>Tag set intersection or boolean &lt;em>AND&lt;/em>&lt;/td>
&lt;td>&lt;code>&amp;quot;foo&amp;amp;bar&amp;quot;&lt;/code> is same as &lt;code>&amp;quot;foo+bar&amp;quot;&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>&lt;code>&amp;quot;PROP&lt;/code>​=​&lt;code>\&amp;quot;STRVAL\&amp;quot;&amp;quot;&lt;/code>&lt;/strong>&lt;/td>
&lt;td>Specified property value matching a string&lt;/td>
&lt;td>&lt;code>&amp;quot;color&lt;/code>​=​&lt;code>\&amp;quot;blue\&amp;quot;&amp;quot;&lt;/code> matches all headings where &lt;code>color&lt;/code> property is &lt;code>blue&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>&lt;code>&amp;quot;PROP&amp;lt;&amp;gt;\&amp;quot;STRVAL\&amp;quot;&amp;quot;&lt;/code>&lt;/strong>&lt;/td>
&lt;td>Specified property value not matching a string&lt;/td>
&lt;td>&lt;code>&amp;quot;color&amp;lt;&amp;gt;\&amp;quot;blue\&amp;quot;&amp;quot;&lt;/code> matches all headings where &lt;code>color&lt;/code> property is not &lt;code>blue&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>&lt;code>&amp;quot;PROP&lt;/code>​=​&lt;code>{VAL REGEXP}&amp;quot;&lt;/code>&lt;/strong>&lt;/td>
&lt;td>Specified property value matching a regexp&lt;/td>
&lt;td>&lt;code>&amp;quot;color={b.*}&amp;quot;&lt;/code> matches all headings where &lt;code>color&lt;/code> property value matches &amp;lsquo;&lt;code>b.*&lt;/code>&amp;rsquo; regexp&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>&lt;code>&amp;quot;PROP[OP]NUMVAL&amp;quot;&lt;/code>&lt;/strong>&lt;/td>
&lt;td>Specified property value compared with a numeric value&lt;/td>
&lt;td>&lt;code>&amp;quot;some_num&lt;/code>​&amp;gt;=​&lt;code>10&amp;quot;&lt;/code> matches all headings where &lt;code>some_num&lt;/code> property is &amp;gt;=10&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>&lt;code>&amp;quot;LEVEL[OP]VAL&amp;quot;&lt;/code>&lt;/strong>&lt;/td>
&lt;td>Check value of headline&amp;rsquo;s special property &lt;em>LEVEL&lt;/em>&lt;/td>
&lt;td>&lt;code>&amp;quot;level&amp;gt;2&amp;quot;&lt;/code> matches all headlines at levels greater than 2&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>&lt;code>&amp;quot;TODO[OP]\&amp;quot;STRVAL\&amp;quot;&amp;quot;&lt;/code>&lt;/strong>&lt;/td>
&lt;td>Check value of headline&amp;rsquo;s &lt;em>TODO&lt;/em> state&lt;/td>
&lt;td>&lt;code>&amp;quot;TODO&lt;/code>​=​&lt;code>\&amp;quot;DONE\&amp;quot;&amp;quot;&lt;/code> matches all headlines with &lt;em>TODO&lt;/em> state set to &amp;lsquo;DONE&amp;rsquo;&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="comparison-types">Comparison Types&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#comparison-types">#&lt;/a>&lt;/h3>
&lt;ul>
&lt;li>If the comparison value is a plain number, a numerical comparison is
done, and the allowed operators are &amp;lsquo;&amp;lt;&amp;rsquo;, &amp;lsquo;=​&amp;rsquo;, &amp;lsquo;&amp;gt;&amp;rsquo;, &amp;lsquo;&amp;lt;=​&amp;rsquo;, &amp;lsquo;&amp;gt;=​&amp;rsquo;,
and &amp;lsquo;&amp;lt;&amp;gt;&amp;rsquo;.&lt;/li>
&lt;li>If the comparison value is enclosed in double quotes, a string
comparison is done, and the same operators are allowed.&lt;/li>
&lt;li>If the comparison value is enclosed in curly braces, a regexp match
is performed. For this comparison, only &amp;lsquo;=​&amp;rsquo; (regexp matches) and
&amp;lsquo;&amp;lt;&amp;gt;&amp;rsquo; (regexp does not match) operators are allowed.&lt;/li>
&lt;li>Comparison with dates and &lt;a href="https://orgmode.org/manual/Tag-Hierarchy.html" title="Emacs Lisp: (info &amp;quot;(org) Tag Hierarchy&amp;quot;)">Group Tags&lt;/a> is also possible. See
&lt;a href="https://orgmode.org/manual/Matching-tags-and-properties.html" title="Emacs Lisp: (info &amp;quot;(org) Matching tags and properties&amp;quot;)">Org Info: Matching tags and properties&lt;/a> for more details.&lt;/li>
&lt;/ul>
&lt;h3 id="other-notes">Other notes&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#other-notes">#&lt;/a>&lt;/h3>
&lt;ul>
&lt;li>The property names are case-insensitive. So these all work the
same: &lt;code>&amp;quot;COLOR&amp;lt;&amp;gt;\&amp;quot;blue\&amp;quot;&amp;quot;&lt;/code>, &lt;code>&amp;quot;color&amp;lt;&amp;gt;\&amp;quot;blue\&amp;quot;&amp;quot;&lt;/code>,
&lt;code>&amp;quot;Color&amp;lt;&amp;gt;\&amp;quot;blue\&amp;quot;&amp;quot;&lt;/code>.&lt;/li>
&lt;li>The &amp;ldquo;tag&amp;rdquo; and &amp;ldquo;property&amp;rdquo; matches can be mixed up using the boolean
&amp;lsquo;&lt;code>&amp;amp;&lt;/code>&amp;rsquo;, &amp;lsquo;&lt;code>|&lt;/code>&amp;rsquo;, &amp;lsquo;&lt;code>+&lt;/code>&amp;rsquo; and &amp;lsquo;&lt;code>-&lt;/code>​&amp;rsquo; operators. So searching
&amp;lsquo;&lt;code>+LEVEL=3+boss-TODO​=&amp;quot;DONE&amp;quot;&lt;/code>&amp;rsquo; lists all level three headlines
that have the tag &amp;lsquo;boss&amp;rsquo; and are &lt;span class="underline">not&lt;/span> marked with the TODO
keyword &amp;lsquo;DONE&amp;rsquo;.&lt;/li>
&lt;li>&amp;lsquo;&lt;code>&amp;amp;&lt;/code>&amp;rsquo; binds more strongly than &amp;lsquo;&lt;code>|&lt;/code>&amp;rsquo;.&lt;/li>
&lt;li>Grouping of match expressions using parentheses is not
supported.&lt;/li>
&lt;/ul>
&lt;h2 id="example-modifying-a-property-in-all-headings">Example: Modifying a property in all headings&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#example-modifying-a-property-in-all-headings">#&lt;/a>&lt;/h2>
&lt;p>Below is an example solution to the &lt;a href="https://framapiaf.org/@postroutine/108313152514542145">Mastoson question&lt;/a> that I
referenced in the beginning of this post.&lt;/p>
&lt;p>&lt;a id="code-snippet--set-props-all-headings">&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-emacs-lisp" data-lang="emacs-lisp">&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="nb">defun&lt;/span> &lt;span class="nv">test/set-property-at-heading&lt;/span> &lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;Function to be called at the beginning of an Org heading.&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">let&lt;/span> &lt;span class="p">((&lt;/span>&lt;span class="nv">el&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nv">org-element-at-point&lt;/span>&lt;span class="p">)))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">org-set-property&lt;/span> &lt;span class="s">&amp;#34;foo&amp;#34;&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nv">org-element-property&lt;/span> &lt;span class="nb">:title&lt;/span> &lt;span class="nv">el&lt;/span>&lt;span class="p">))))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="nv">org-map-entries&lt;/span> &lt;span class="nf">#&amp;#39;&lt;/span>&lt;span class="nv">test/set-property-at-heading&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="src-block-caption">
&lt;span class="src-block-number">&lt;a href="#code-snippet--set-props-all-headings">Code Snippet 2&lt;/a>:&lt;/span>
Dummy example showing how to set a property for all Org headings using &lt;code>org-map-entries&lt;/code>
&lt;/div>
&lt;ul>
&lt;li>It defines a function that parses the Org element at point using
&lt;code>org-element-at-point&lt;/code>, gets the &lt;code>title&lt;/code> property of the element
&lt;span class="sidenote-number">&lt;small class="sidenote">
This function is designed to be called by &lt;code>org-map-entries&lt;/code> and so
the point at the time of calling this function will always be on a
heading.
&lt;/small>&lt;/span>
, and sets that to the &lt;em>headline&lt;/em> element&amp;rsquo;s &lt;code>foo&lt;/code> property.&lt;/li>
&lt;li>The &lt;code>org-map-entries&lt;/code> call now simply calls this function on each
heading in the visible scope of the Org buffer.&lt;/li>
&lt;/ul>
&lt;h2 id="org-map-entries-references">&lt;code>org-map-entries&lt;/code> References&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#org-map-entries-references">#&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>&lt;kbd>C-h&lt;/kbd> &lt;kbd>f&lt;/kbd> &lt;code>org-map-entries&lt;/code>&lt;/li>
&lt;li>&lt;a href="https://orgmode.org/manual/Using-the-Mapping-API.html" title="Emacs Lisp: (info &amp;quot;(org) Using the Mapping API&amp;quot;)">Org Info: Using the Mapping API&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://orgmode.org/manual/Matching-tags-and-properties.html" title="Emacs Lisp: (info &amp;quot;(org) Matching tags and properties&amp;quot;)">Org Info: Matching tags and properties&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="footnotes" role="doc-endnotes">
&lt;hr>
&lt;ol>
&lt;li id="fn:1">
&lt;p>Org mode has another popular mapping/looping API function
&lt;strong>org-element-map&lt;/strong>. I won&amp;rsquo;t go into much detail about that in this post
&amp;mdash; I&amp;rsquo;ll just mention that &lt;code>org-element-map&lt;/code> is not the best choice if
you need to modify the original Org buffer. It&amp;rsquo;s main use is to loop
through a parsed &lt;abbr aria-label="Abstract Syntax Tree" tabindex=0>AST&lt;/abbr> of an Org buffer
and optional modify those elements &lt;em>in memory&lt;/em>.&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;/div></description><author>Kaushal.Modi@fakeEmailToMakeValidatorHappy.com (Kaushal Modi)</author><category domain="https://scripter.co/categories/emacs">emacs</category><category domain="https://scripter.co/categories/org">org</category><category domain="https://scripter.co/categories/elisp">elisp</category><category domain="https://scripter.co/tags/looping">looping</category><category domain="https://scripter.co/tags/100daystooffload">100DaysToOffload</category><guid>https://scripter.co/looping-through-org-mode-headings/</guid><pubDate>Wed, 18 May 2022 23:29:00 -0400</pubDate></item><item><title>Using Org Logbook Notes to record blog post updates</title><link>https://scripter.co/using-org-logbook-notes-to-record-blog-post-updates/</link><description>&lt;blockquote>Quick introduction to Org mode&amp;rsquo;s &lt;code>:LOGBOOK:&lt;/code> feature and how I use it
to record time-stamped notes for blog post updates.&lt;/blockquote>&lt;div class="ox-hugo-toc toc">
&lt;div class="heading">Table of Contents&lt;/div>
&lt;ul>
&lt;li>&lt;a href="#prior-forms-of-adding-post-updates">Prior forms of adding post updates&lt;/a>&lt;/li>
&lt;li>&lt;a href="#introducing-logbook">Introducing &lt;code>:LOGBOOK:&lt;/code>&lt;/a>&lt;/li>
&lt;li>&lt;a href="#adding-notes-to-logbook">Adding notes to &lt;code>:LOGBOOK:&lt;/code>&lt;/a>&lt;/li>
&lt;li>&lt;a href="#logbook-notes-example">&lt;code>:LOGBOOK:&lt;/code> Notes Example&lt;/a>&lt;/li>
&lt;li>&lt;a href="#references">References&lt;/a>&lt;/li>
&lt;/ul>
&lt;/div>
&lt;!--endtoc-->
&lt;p>Most of my blog posts are mainly to serve as documentation for my
future self
&lt;span class="sidenote-number">&lt;small class="sidenote">
This post will serve to remind me how to get the &lt;code>:LOGBOOK:&lt;/code> notes
working once again in case I end up with some issue there.
&lt;/small>&lt;/span>
. So when I get a chance, I try to fix outdated stuff in
my old blog posts. And along with the act of updating things, adding
brief notes describing those updates comes naturally to me.&lt;/p>
&lt;h2 id="prior-forms-of-adding-post-updates">Prior forms of adding post updates&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#prior-forms-of-adding-post-updates">#&lt;/a>&lt;/h2>
&lt;p>As I author my posts in Org mode, I can easy enter a date stamp using
the &lt;code>org-time-stamp&lt;/code> command (bound by default to &lt;kbd>C-c&lt;/kbd> &lt;kbd>.&lt;/kbd> &lt;kbd>RET&lt;/kbd>) and
follow that by the update note.&lt;/p>
&lt;p>While that worked, that approach bothered me because those notes
didn&amp;rsquo;t have consistent format across multiple posts. For example, I
might type the update as &amp;ldquo;&lt;code class="code-inline language-org">&lt;span class="gs">*Update (&amp;lt;time stamp&amp;gt;)*&lt;/span>: &amp;lt;&lt;span class="s">note&lt;/span>&amp;gt;&lt;/code>&amp;rdquo; in one post, while I might type the same in a
&lt;em>description list&lt;/em> form in another: &amp;ldquo;&lt;code class="code-inline language-org">&lt;span class="k">- &lt;/span>&amp;lt;&lt;span class="s">time stamp&lt;/span>&amp;gt;) :: &amp;lt;&lt;span class="s">note&lt;/span>&amp;gt;&lt;/code>&amp;rdquo;.&lt;/p>
&lt;p>To solve the consistency problem, I came up with this Org macro:&lt;/p>
&lt;p>&lt;a id="code-snippet--update-org-macro">&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-org" data-lang="org">&lt;span class="line">&lt;span class="cl">&lt;span class="cs">#+macro&lt;/span>&lt;span class="c">: update - $1 :: $2&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="src-block-caption">
&lt;span class="src-block-number">&lt;a href="#code-snippet--update-org-macro">Code Snippet 1&lt;/a>:&lt;/span>
&lt;code>{{{update(..)}}}&lt;/code> Org Macro
&lt;/div>
&lt;p>This worked mostly &amp;hellip; except when the update text needed to be a bit
longer, like a paragraph. It didn&amp;rsquo;t look elegant in that case. Also,
if the text had a &lt;em>comma&lt;/em> character in there, it needed to be escaped
with a backslash (&lt;code>\&lt;/code>).&lt;/p>
&lt;h2 id="introducing-logbook">Introducing &lt;code>:LOGBOOK:&lt;/code>&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#introducing-logbook">#&lt;/a>&lt;/h2>
&lt;p>So when I learned
&lt;span class="sidenote-number">&lt;small class="sidenote">
A little bit of history .. I learned about the &lt;code>:LOGBOOK:&lt;/code> drawer when
Adam Porter mentioned it in &lt;a href="https://github.com/kaushalmodi/ox-hugo/issues/203">&lt;code>ox-hugo&lt;/code> Issue # 203&lt;/a> back in
September 2018. I wanted to use that feature, but I didn&amp;rsquo;t have time
and/or know-how on how exactly I would parse those Org Drawers in
&lt;code>ox-hugo&lt;/code> until very recently (May 2022)!
&lt;/small>&lt;/span>
about the Org &lt;code>:LOGBOOK:&lt;/code> drawer, it solved all those problems: (i)
consistency in adding notes (ii) easy to add update notes &amp;ndash; in fact
much easier (iii) easy to type long form notes (iv) no comma escaping
needed.&lt;/p>
&lt;p>Org Drawers look like this:&lt;/p>
&lt;p>&lt;a id="code-snippet--code-org-drawers">&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-org" data-lang="org">&lt;span class="line">&lt;span class="cl">Content before the drawer
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">:DRAWERNAME:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="cs">Content inside the drawer
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cs">&lt;/span>&lt;span class="c">:END:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Content after the drawer
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="src-block-caption">
&lt;span class="src-block-number">&lt;a href="#code-snippet--code-org-drawers">Code Snippet 2&lt;/a>:&lt;/span>
Org Drawers
&lt;/div>
&lt;p>and they can be inserted anywhere in your Org content using the
&lt;code>org-insert-drawer&lt;/code> command (bound by default to &lt;kbd>C-c&lt;/kbd> &lt;kbd>C-x&lt;/kbd> &lt;kbd>d&lt;/kbd>).&lt;/p>
&lt;p>&lt;code>:LOGBOOK:&lt;/code> is a special kind of drawer that&amp;rsquo;s auto-inserted by Org
mode when certain actions are detected, like changing the TODO state
of a subtree, or
&lt;mark>adding a note&lt;/mark> . That latter action is what this blog post is about.&lt;/p>
&lt;h2 id="adding-notes-to-logbook">Adding notes to &lt;code>:LOGBOOK:&lt;/code>&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#adding-notes-to-logbook">#&lt;/a>&lt;/h2>
&lt;p>You need to enable this feature using one of these methods:&lt;/p>
&lt;ol>
&lt;li>Set the &lt;code>org-log-into-drawer&lt;/code> variable to a non-nil value
(typically &lt;code>t&lt;/code>) in your Emacs config, or as a file-local variable,
or in your project&amp;rsquo;s &lt;strong>&lt;code>.dir-locals.el&lt;/code>&lt;/strong> (⭐ my preference).&lt;/li>
&lt;li>Set &lt;code>#+startup: logdrawer&lt;/code> to enable this for the whole Org file.&lt;/li>
&lt;li>To enable this feature for only selected subtrees, set the
&lt;code>:LOG_INTO_DRAWER: t&lt;/code> property in the subtree (or one of its parent
subtrees).&lt;/li>
&lt;/ol>
&lt;p>Once this is set, call the &lt;code>org-add-note&lt;/code> command (bound by default to
&lt;kbd>C-c&lt;/kbd> &lt;kbd>C-z&lt;/kbd>). That will open a window with ∗Org Note∗ buffer where-in
you will type your post update and then &lt;kbd>C-c&lt;/kbd> &lt;kbd>C-c&lt;/kbd> to save it to the
subtree&amp;rsquo;s &lt;code>:LOGBOOK:&lt;/code> drawer. If that drawer didn&amp;rsquo;t exist already, it
will be created directly under the subtree&amp;rsquo;s heading.&lt;/p>
&lt;p>The note will get recorded in this format by default under the current
subtree:&lt;/p>
&lt;p>&lt;a id="code-snippet--logbook-default-format">&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-org" data-lang="org">&lt;span class="line">&lt;span class="cl">&lt;span class="gh">*&lt;/span>&lt;span class="gs"> Subtree title&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">:LOGBOOK:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="cs">- Note taken on &amp;lt;current date and time&amp;gt; \\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cs"> &amp;lt;note text&amp;gt;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cs">&lt;/span>&lt;span class="c">:END:&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="src-block-caption">
&lt;span class="src-block-number">&lt;a href="#code-snippet--logbook-default-format">Code Snippet 3&lt;/a>:&lt;/span>
Default format of a &lt;code>:LOGBOOK:&lt;/code> note
&lt;/div>
&lt;p>As you see, you only type the note text, and the time-stamp is
inserted automatically.&lt;/p>
&lt;h2 id="logbook-notes-example">&lt;code>:LOGBOOK:&lt;/code> Notes Example&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#logbook-notes-example">#&lt;/a>&lt;/h2>
&lt;p>Here are the update notes from one of my posts:&lt;/p>
&lt;p>&lt;a id="code-snippet--logbook-example">&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-org" data-lang="org">&lt;span class="line">&lt;span class="cl">&lt;span class="c">:LOGBOOK:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="cs">- Note taken on &amp;lt;2018-08-26 Sun&amp;gt; \\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cs"> Mention =org-babel-demarcate-block=, tweak the =org-meta-return= advice.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cs">- Note taken on &amp;lt;2018-08-23 Thu&amp;gt; \\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cs"> Use ~M-return~ instead of ~C-return~ for splitting blocks and
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cs"> support upper-case blocks (though I [[* Converting Org keywords to lower-case][don&amp;#39;t prefer those]]!).
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cs">&lt;/span>&lt;span class="c">:END:&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="src-block-caption">
&lt;span class="src-block-number">&lt;a href="#code-snippet--logbook-example">Code Snippet 4&lt;/a>:&lt;/span>
Examples of post update notes added to the &lt;code>:LOGBOOK:&lt;/code> drawer
&lt;/div>
&lt;p>You can see how they rendered at the top of the &lt;a href="https://scripter.co/splitting-an-org-block-into-two/">Splitting an Org block into two&lt;/a> post.&lt;/p>
&lt;p>If you are an &lt;code>ox-hugo&lt;/code> user following the &lt;em>subtree-based export
flow&lt;/em>, and would like to export &lt;code>:LOGBOOK:&lt;/code> notes in a similar
fashion, check out the &lt;a href="https://ox-hugo.scripter.co/doc/drawers/">&lt;code>ox-hugo&lt;/code> Manual: Drawers&lt;/a> page for details.&lt;/p>
&lt;h2 id="references">References&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#references">#&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://orgmode.org/manual/Drawers.html" title="Emacs Lisp: (info &amp;quot;(org) Drawers&amp;quot;)">Org Info: Drawers&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://orgmode.org/manual/Tracking-TODO-state-changes.html" title="Emacs Lisp: (info &amp;quot;(org) Tracking TODO state changes&amp;quot;)">Org Info: Tracking TODO state changes&lt;/a>&lt;/li>
&lt;/ul></description><author>Kaushal.Modi@fakeEmailToMakeValidatorHappy.com (Kaushal Modi)</author><category domain="https://scripter.co/categories/emacs">emacs</category><category domain="https://scripter.co/categories/org">org</category><category domain="https://scripter.co/tags/100daystooffload">100DaysToOffload</category><category domain="https://scripter.co/tags/logbook">logbook</category><guid>https://scripter.co/using-org-logbook-notes-to-record-blog-post-updates/</guid><pubDate>Mon, 16 May 2022 00:59:00 -0400</pubDate></item><item><title>Building Org Development version (2022)</title><link>https://scripter.co/building-org-development-version/</link><description>&lt;blockquote>A guide on how to build Org mode from its &lt;strong>main&lt;/strong> branch and load in
Emacs without any path &lt;em>shadowing&lt;/em>.&lt;/blockquote>&lt;div class="ox-hugo-toc toc">
&lt;div class="heading">Table of Contents&lt;/div>
&lt;ul>
&lt;li>&lt;a href="#clone-the-org-repo">&lt;span class="section-num">1&lt;/span> Clone the Org repo&lt;/a>&lt;/li>
&lt;li>&lt;a href="#build-setup">&lt;span class="section-num">2&lt;/span> Build Setup&lt;/a>
&lt;ul>
&lt;li>&lt;a href="#customizing-local-dot-mk--optional">Customizing &lt;code>local.mk&lt;/code> (Optional)&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;a href="#build">&lt;span class="section-num">3&lt;/span> Build&lt;/a>&lt;/li>
&lt;li>&lt;a href="#set-the-correct-paths-in-your-emacs-config">&lt;span class="section-num">4&lt;/span> Set the correct paths in your Emacs config&lt;/a>&lt;/li>
&lt;li>&lt;a href="#testing-that-the-right-org-version-got-loaded">&lt;span class="section-num">5&lt;/span> Testing that the right Org version got loaded&lt;/a>&lt;/li>
&lt;li>&lt;a href="#future-org-development-version-updates">Future Org development version updates&lt;/a>&lt;/li>
&lt;li>&lt;a href="#references">References&lt;/a>&lt;/li>
&lt;/ul>
&lt;/div>
&lt;!--endtoc-->
&lt;div class="note">
&lt;p>This post is a re-write of &lt;a href="https://scripter.co/building-org-development-version-2017/">an earlier &amp;ldquo;Building Org Development
version&amp;rdquo; post&lt;/a> but minus all the outdated stuff.&lt;/p>
&lt;/div>
&lt;p>I am assuming that you already know what &lt;a href="https://orgmode.org/">Org mode&lt;/a> is and that&amp;rsquo;s why
you are here 😃.&lt;/p>
&lt;p>You would want to build Org from its development branch (&lt;a href="https://git.savannah.gnu.org/cgit/emacs/org-mode.git/log/?h=main">&lt;strong>main&lt;/strong>
branch&lt;/a>) to get the latest and greatest goodies &lt;em>plus&lt;/em> bug fixes! Go
through the &lt;a href="https://git.savannah.gnu.org/cgit/emacs/org-mode.git/tree/etc/ORG-NEWS?h=main">&lt;code>ORG-NEWS&lt;/code>&lt;/a> file to read about what&amp;rsquo;s new in the &lt;strong>main&lt;/strong>
branch.&lt;/p>
&lt;p>If you like what you see there, here are the steps for installing the
development version of Org.&lt;/p>
&lt;h2 id="clone-the-org-repo">&lt;span class="section-num">1&lt;/span> Clone the Org repo&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#clone-the-org-repo">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">git clone https://git.savannah.gnu.org/git/emacs/org-mode.git
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>
&lt;h2 id="build-setup">&lt;span class="section-num">2&lt;/span> Build Setup&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#build-setup">#&lt;/a>&lt;/h2>
&lt;ol>
&lt;li>Copy &lt;code>&amp;lt;REPO_ROOT&amp;gt;/mk/default.mk&lt;/code> to &lt;code>&amp;lt;REPO_ROOT&amp;gt;/local.mk&lt;/code>&lt;/li>
&lt;li>Tweak &lt;code>local.mk&lt;/code> (optional)&lt;/li>
&lt;/ol>
&lt;h3 id="customizing-local-dot-mk--optional">Customizing &lt;code>local.mk&lt;/code> (Optional)&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#customizing-local-dot-mk--optional">#&lt;/a>&lt;/h3>
&lt;p>Here are few variables that you might like to change in the &lt;code>local.mk&lt;/code>:&lt;/p>
&lt;dl>
&lt;dt>&lt;code>prefix&lt;/code>&lt;/dt>
&lt;dd>Org installation directory
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-makefile" data-lang="makefile">&lt;span class="line">&lt;span class="cl">&lt;span class="nv">prefix&lt;/span> &lt;span class="o">=&lt;/span> /dir/where/you/want/to/install/org &lt;span class="c1"># Default: /usr/share&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The &lt;code>.el&lt;/code> files will go to &lt;code>$(prefix)/emacs/site-lisp/org&lt;/code> by
default. If you&amp;rsquo;d like to change that, change the &lt;code>lispdir&lt;/code>
variable too.&lt;/p>
&lt;/dd>
&lt;dt>&lt;code>infodir&lt;/code>&lt;/dt>
&lt;dd>Org Info installation directory. I like to keep the
Info file for development version of Org in a separate directory.
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-makefile" data-lang="makefile">&lt;span class="line">&lt;span class="cl">&lt;span class="nv">infodir&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">$(&lt;/span>prefix&lt;span class="k">)&lt;/span>/org/info &lt;span class="c1"># Default: $(prefix)/info&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/dd>
&lt;dt>&lt;code>ORG_MAKE_DOC&lt;/code>&lt;/dt>
&lt;dd>Types of Org documentation you&amp;rsquo;d like to build by
default. Setting below generates only the Org Info manual.
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-makefile" data-lang="makefile">&lt;span class="line">&lt;span class="cl">&lt;span class="nv">ORG_MAKE_DOC&lt;/span> &lt;span class="o">=&lt;/span> info &lt;span class="c1"># Default: html pdf&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/dd>
&lt;/dl>
&lt;h2 id="build">&lt;span class="section-num">3&lt;/span> Build&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#build">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">make autoloads
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">make
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">make doc
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">make install
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Type &lt;code>make help&lt;/code> for help on the Org &lt;code>Makefile&lt;/code>. Type &lt;code>make helpall&lt;/code>
to get a detailed help, or see the &lt;a href="https://orgmode.org/worg/dev/org-build-system.html">Org build system help&lt;/a>.&lt;/p>
&lt;h2 id="set-the-correct-paths-in-your-emacs-config">&lt;span class="section-num">4&lt;/span> Set the correct paths in your Emacs config&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#set-the-correct-paths-in-your-emacs-config">#&lt;/a>&lt;/h2>
&lt;ol>
&lt;li>Update &lt;code>load-path&lt;/code> to remove the Org version that ships with
Emacs. Do the same if you have Org installed via GNU ELPA
&lt;span class="sidenote-number">&lt;small class="sidenote">
If you need the latest stable version of Org mode, install it from
GNU ELPA.
&lt;/small>&lt;/span>
too.&lt;/li>
&lt;li>Also remove the associated old Org mode Info manuals from
&lt;code>Info-directory-list&lt;/code>.&lt;/li>
&lt;li>Update the &lt;code>load-path&lt;/code> and &lt;code>Info-directory-list&lt;/code> variables to point
to the Org mode source code and Info manual built using the &lt;strong>main&lt;/strong>
branch.&lt;/li>
&lt;/ol>
&lt;p>&lt;a href="#code-snippet--org-load-path-info-update">Below code&lt;/a> does all that but
&lt;mark>make sure this code is executed &lt;strong>after&lt;/strong> you do &lt;code>(package-initialize)&lt;/code>,
but &lt;strong>before&lt;/strong> you &lt;code>require&lt;/code> the &lt;code>org&lt;/code> package&lt;/mark> . You can use &lt;a href="https://github.com/jwiegley/use-package">&lt;code>use-package&lt;/code>&lt;/a> and make sure that this order of code
evaluation is always correct &amp;mdash; Just put the code from
&lt;a href="#code-snippet--org-load-path-info-update">Code Snippet 2&lt;/a> where &lt;code>&amp;lt;HERE&amp;gt;&lt;/code> is shown in the below
snippet:&lt;/p>
&lt;p>&lt;a id="code-snippet--use-package-org">&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-emacs-lisp" data-lang="emacs-lisp">&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="nb">use-package&lt;/span> &lt;span class="nv">org&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">:preface&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">&amp;lt;HERE&amp;gt;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="src-block-caption">
&lt;span class="src-block-number">&lt;a href="#code-snippet--use-package-org">Code Snippet 1&lt;/a>:&lt;/span>
Update &lt;code>load-path&lt;/code> and &lt;code>Info-directory-list&lt;/code> in &lt;code>use-package&lt;/code> &lt;code>:preface&lt;/code>
&lt;/div>
&lt;p>&lt;a id="code-snippet--org-load-path-info-update">&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-emacs-lisp" data-lang="emacs-lisp">&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="nb">defvar&lt;/span> &lt;span class="nv">modi/org-version-select&lt;/span> &lt;span class="ss">&amp;#39;dev&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;Variable to choose the version of Org to be loaded.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">Valid values are &lt;/span>&lt;span class="ss">`dev&amp;#39;&lt;/span>&lt;span class="s">, &lt;/span>&lt;span class="ss">`elpa&amp;#39;&lt;/span>&lt;span class="s"> and &lt;/span>&lt;span class="ss">`emacs&amp;#39;&lt;/span>&lt;span class="s">.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">When set to &lt;/span>&lt;span class="ss">`dev&amp;#39;&lt;/span>&lt;span class="s">, the development version of Org built locally
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">is loaded.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">When set to &lt;/span>&lt;span class="ss">`elpa&amp;#39;&lt;/span>&lt;span class="s">, Org is installed and loaded from GNU ELPA.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">When set to &lt;/span>&lt;span class="ss">`emacs&amp;#39;&lt;/span>&lt;span class="s">, the Org version shipped with Emacs is used.&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="nb">defvar&lt;/span> &lt;span class="nv">modi/default-lisp-directory&lt;/span> &lt;span class="s">&amp;#34;/your/emacs/share/dir/version/lisp/&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;Directory containing lisp files for the Emacs installation.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">This value must match the path to the lisp/ directory of your
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">Emacs installation.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">If Emacs is installed using --prefix=\&amp;#34;${PREFIX_DIR}\&amp;#34; this value
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">would typically be
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">\&amp;#34;${PREFIX_DIR}/share/emacs/&amp;lt;VERSION&amp;gt;/lisp/\&amp;#34;.&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="nb">defvar&lt;/span> &lt;span class="nv">org-dev-lisp-directory&lt;/span> &lt;span class="s">&amp;#34;/value/of/lispdir/in/local.mk&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;Directory containing lisp files for dev version of Org.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">This value must match the &lt;/span>&lt;span class="ss">`lispdir&amp;#39;&lt;/span>&lt;span class="s"> variable in the Org local.mk.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">By default the value is \&amp;#34;$prefix/emacs/site-lisp/org\&amp;#34;, where
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">&lt;/span>&lt;span class="ss">`prefix&amp;#39;&lt;/span>&lt;span class="s"> must match that in local.mk too.&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="nb">defvar&lt;/span> &lt;span class="nv">org-dev-info-directory&lt;/span> &lt;span class="s">&amp;#34;/value/of/infodir/in/local.mk&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;Directory containing Info manual file for dev version of Org.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">This value must match the &lt;/span>&lt;span class="ss">`infodir&amp;#39;&lt;/span>&lt;span class="s"> variable in the Org local.mk.&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="nb">when&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nb">and&lt;/span> &lt;span class="nv">org-dev-lisp-directory&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">org-dev-info-directory&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">with-eval-after-load&lt;/span> &lt;span class="ss">&amp;#39;package&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">;; If `modi/org-version-select&amp;#39; is *not* `emacs&amp;#39;, remove the Emacs&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">;; version of Org from the `load-path&amp;#39;.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">unless&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">eq&lt;/span> &lt;span class="nv">modi/org-version-select&lt;/span> &lt;span class="ss">&amp;#39;emacs&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">;; Remove Org that ships with Emacs from the `load-path&amp;#39;.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">let&lt;/span> &lt;span class="p">((&lt;/span>&lt;span class="nv">default-org-path&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">expand-file-name&lt;/span> &lt;span class="s">&amp;#34;org&amp;#34;&lt;/span> &lt;span class="nv">modi/default-lisp-directory&lt;/span>&lt;span class="p">)))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">setq&lt;/span> &lt;span class="nv">load-path&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">delete&lt;/span> &lt;span class="nv">default-org-path&lt;/span> &lt;span class="nv">load-path&lt;/span>&lt;span class="p">))))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">;; If `modi/org-version-select&amp;#39; is *not* `elpa&amp;#39;, remove the Elpa&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">;; version of Org from the `load-path&amp;#39;.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">unless&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">eq&lt;/span> &lt;span class="nv">modi/org-version-select&lt;/span> &lt;span class="ss">&amp;#39;elpa&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">dolist&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nv">org-elpa-install-path&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nv">directory-files-recursively&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">package-user-dir&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;\\`org-[0-9.]+\\&amp;#39;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">:include-directories&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">setq&lt;/span> &lt;span class="nv">load-path&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">delete&lt;/span> &lt;span class="nv">org-elpa-install-path&lt;/span> &lt;span class="nv">load-path&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">;; Also ensure that the associated path is removed from Info&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">;; search list.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">setq&lt;/span> &lt;span class="nv">Info-directory-list&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">delete&lt;/span> &lt;span class="nv">org-elpa-install-path&lt;/span> &lt;span class="nv">Info-directory-list&lt;/span>&lt;span class="p">))))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">let&lt;/span> &lt;span class="p">((&lt;/span>&lt;span class="nv">dev-org-path&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">directory-file-name&lt;/span> &lt;span class="nv">org-dev-lisp-directory&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">dev-org-info&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">directory-file-name&lt;/span> &lt;span class="nv">org-dev-info-directory&lt;/span>&lt;span class="p">)))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">eq&lt;/span> &lt;span class="nv">modi/org-version-select&lt;/span> &lt;span class="ss">&amp;#39;dev&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">progn&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">add-to-list&lt;/span> &lt;span class="ss">&amp;#39;load-path&lt;/span> &lt;span class="nv">dev-org-path&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">;; It&amp;#39;s possible that `org-dev-info-directory&amp;#39; is set to&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">;; an unconventional value, in which case, it will not be&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">;; automatically added to `Info-directory-alist&amp;#39;. So add&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">;; it to `Info-directory-alist&amp;#39; manually.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">add-to-list&lt;/span> &lt;span class="ss">&amp;#39;Info-directory-list&lt;/span> &lt;span class="nv">dev-org-info&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">;; If `modi/org-version-select&amp;#39; is *not* `dev&amp;#39;, remove the&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">;; development version of Org from the `load-path&amp;#39;, and its&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">;; Info from the Info search list.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">setq&lt;/span> &lt;span class="nv">load-path&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">delete&lt;/span> &lt;span class="nv">dev-org-path&lt;/span> &lt;span class="nv">load-path&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">with-eval-after-load&lt;/span> &lt;span class="ss">&amp;#39;info&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">setq&lt;/span> &lt;span class="nv">Info-directory-list&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">delete&lt;/span> &lt;span class="nv">dev-org-info&lt;/span> &lt;span class="nv">Info-directory-list&lt;/span>&lt;span class="p">)))))))&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="src-block-caption">
&lt;span class="src-block-number">&lt;a href="#code-snippet--org-load-path-info-update">Code Snippet 2&lt;/a>:&lt;/span>
Emacs config snippet to ensure that &lt;code>load-path&lt;/code> and &lt;code>Info-directory-list&lt;/code> use the right Org version
&lt;/div>
&lt;dl>
&lt;dt>Note&lt;/dt>
&lt;dd>Remember that you need to correctly set the values of these
3 variables in the above snippet:
&lt;ul>
&lt;li>&lt;code>modi/default-lisp-directory&lt;/code>&lt;/li>
&lt;li>&lt;code>org-dev-lisp-directory&lt;/code>&lt;/li>
&lt;li>&lt;code>org-dev-info-directory&lt;/code>&lt;/li>
&lt;/ul>
&lt;/dd>
&lt;/dl>
&lt;h2 id="testing-that-the-right-org-version-got-loaded">&lt;span class="section-num">5&lt;/span> Testing that the right Org version got loaded&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#testing-that-the-right-org-version-got-loaded">#&lt;/a>&lt;/h2>
&lt;ol>
&lt;li>&lt;strong>Restart Emacs&lt;/strong> (&lt;em>Don&amp;rsquo;t be lazy &amp;mdash; do it!&lt;/em>)&lt;/li>
&lt;li>&lt;code>M-x org-version&lt;/code> &amp;ndash; That should show something like this in the
echo area:
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">Org mode version 9.5.3 (release_9.5.3-482-gd5a52b @ /home/kmodi/usr_local/apps/7/emacs/emacs-28/share/emacs/site-lisp/org/)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>This message format is broken down as:
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">Org mode version &amp;lt;ORG-VERSION&amp;gt; (release_&amp;lt;ORG-VERSION&amp;gt;-NNN-g&amp;lt;GIT-HASH&amp;gt; @ &amp;lt;PREFIX&amp;gt;/emacs/site-lisp/org/)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ol>
&lt;p>If the &lt;code>GIT-HASH&lt;/code> and &lt;code>PREFIX&lt;/code> above are what you expect,
congratulations! You did it! 🎉&lt;/p>
&lt;p>Else, let me know in comments if I can help you.&lt;/p>
&lt;h2 id="future-org-development-version-updates">Future Org development version updates&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#future-org-development-version-updates">#&lt;/a>&lt;/h2>
&lt;ol>
&lt;li>Below will do &lt;code>git pull&lt;/code> and build Org.
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">make update
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>Restart Emacs.&lt;/li>
&lt;/ol>
&lt;h2 id="references">References&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#references">#&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://github.com/kaushalmodi/.emacs.d/blob/master/setup-files/setup-org.el">&lt;code>setup-org.el&lt;/code> in my Emacs config&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/kaushalmodi/.emacs.d/blob/master/setup-packages.el">&lt;code>setup-packages.el&lt;/code> in my Emacs config&lt;/a>&lt;/li>
&lt;/ul></description><author>Kaushal.Modi@fakeEmailToMakeValidatorHappy.com (Kaushal Modi)</author><category domain="https://scripter.co/categories/emacs">emacs</category><category domain="https://scripter.co/categories/org">org</category><category domain="https://scripter.co/tags/development">development</category><category domain="https://scripter.co/tags/100daystooffload">100DaysToOffload</category><guid>https://scripter.co/building-org-development-version/</guid><pubDate>Fri, 13 May 2022 17:01:00 -0400</pubDate></item><item><title>Creating a patch file using Magit</title><link>https://scripter.co/creating-a-patch-file-using-magit/</link><description>&lt;blockquote>Quick tip on how to create &lt;em>git&lt;/em> patch files in Emacs using Magit.&lt;/blockquote>&lt;div class="ox-hugo-toc toc">
&lt;div class="heading">Table of Contents&lt;/div>
&lt;ul>
&lt;li>&lt;a href="#single-file-patch">Single-file patch&lt;/a>&lt;/li>
&lt;li>&lt;a href="#multi-file-patch">Multi-file patch&lt;/a>&lt;/li>
&lt;li>&lt;a href="#more-resources">More Resources&lt;/a>&lt;/li>
&lt;/ul>
&lt;/div>
&lt;!--endtoc-->
&lt;p>Recently I came across few instances where people were asking
questions related to creating patches for contributions to Emacs and
Org mode repos &lt;a href="https://www.reddit.com/r/emacs/comments/udjk8l/how_do_you_actually_send_pull_requests_in/">here&lt;/a> and then &lt;a href="https://github.com/kaushalmodi/ox-hugo/discussions/618#discussioncomment-2690410">here&lt;/a>. I was in the same shoes back then
when I was about to make my first contribution to Emacs. And so I
thought of sharing this tip on how to use Magit to create patch files.&lt;/p>
&lt;p>If you have been using both Emacs and git, you might have already
heard about the awesome &lt;a href="https://magit.vc/">Magit&lt;/a> package. If you haven&amp;rsquo;t 😲,
check out &lt;a href="https://emacsair.me/2017/09/01/magit-walk-through/">this screenshot-annotated review of what Magit is&lt;/a>. With that
out of the way, and assuming that you already have it installed
&lt;span class="sidenote-number">&lt;small class="sidenote">
&lt;code class="code-inline language-emacs-lisp">&lt;span class="p">(&lt;/span>&lt;span class="nb">use-package&lt;/span> &lt;span class="nv">magit&lt;/span> &lt;span class="nb">:ensure&lt;/span> &lt;span class="no">t&lt;/span>&lt;span class="p">)&lt;/span>&lt;/code>
&lt;/small>&lt;/span>
, here&amp;rsquo;s how to create a patch file using Magit ..&lt;/p>
&lt;h2 id="single-file-patch">Single-file patch&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#single-file-patch">#&lt;/a>&lt;/h2>
&lt;ol>
&lt;li>Commit your changes to the git repo first.&lt;/li>
&lt;li>Bring up the &lt;strong>Magit Log&lt;/strong> view. From the Magit status buffer, you
would type &lt;kbd>l&lt;/kbd> &lt;kbd>l&lt;/kbd> to show the log of the current branch.&lt;/li>
&lt;li>Move the point to the commit that you want to send as a patch file,
and hit &lt;kbd>W&lt;/kbd> &lt;kbd>c&lt;/kbd> &lt;kbd>c&lt;/kbd> &lt;kbd>RET&lt;/kbd>.
&lt;ul>
&lt;li>The last &lt;kbd>RET&lt;/kbd> selects the commit the point is on, in the
∗magit-log∗ buffer.&lt;/li>
&lt;li>If the first line of the commit log of the selected commit is
&amp;ldquo;Update docstrings for shortdoc.el&amp;rdquo;, you&amp;rsquo;ll see a patch file
named &lt;code>0001-Update-docstrings-for-shortdoc.el.patch&lt;/code> created in
your git repo root.&lt;/li>
&lt;li>You can now email this patch file
&lt;mark>as an attachment&lt;/mark> to &lt;a href="mailto:bug-gnu-emacs@gnu.org">bug-gnu-emacs@gnu.org&lt;/a> (if contributing to Emacs) or to
&lt;a href="mailto:emacs-orgmode@gnu.org">emacs-orgmode@gnu.org&lt;/a> (if contributing to Org mode).&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;h2 id="multi-file-patch">Multi-file patch&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#multi-file-patch">#&lt;/a>&lt;/h2>
&lt;p>If you need to create a multi-file patch i.e. patch files for a series
of commits, select those commits in the ∗magit-log∗ buffer
&lt;span class="sidenote-number">&lt;small class="sidenote">
The commit selection process is the same as how you would select
text in any Emacs buffer. For example, if I want to create a series
of 5 patches, I would go to the latest commit in the series, hit
&lt;kbd>C-SPC&lt;/kbd> and then &lt;kbd>C-n&lt;/kbd> 4 times to select 5 rows of commits.
&lt;/small>&lt;/span>
, and then use the same &lt;kbd>W&lt;/kbd> &lt;kbd>c&lt;/kbd> &lt;kbd>c&lt;/kbd> binding.&lt;/p>
&lt;h2 id="more-resources">More Resources&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#more-resources">#&lt;/a>&lt;/h2>
&lt;p>Here are the official contribution guides for Emacs and Org mode:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://git.savannah.gnu.org/cgit/emacs.git/tree/CONTRIBUTE">How to contribute to Emacs &amp;ndash; Emacs CONTRIBUTE document&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://orgmode.org/worg/org-contribute.html">How to contribute to Org &amp;ndash; Worg&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>Here are some more resources that got shared in the &lt;em>Emacsverse&lt;/em>
recently (within the past year as of writing this):&lt;/p>
&lt;ol>
&lt;li>&lt;span class="timestamp-wrapper">&lt;span class="timestamp">&amp;lt;2022-04-23 Sat&amp;gt; &lt;/span>&lt;/span> &lt;a href="https://lists.gnu.org/r/emacs-orgmode/2022-04/orgYGCOr0hBKH.org">Contributing patches to Org &amp;ndash; Ihor Radchenko&lt;/a>&lt;/li>
&lt;li>&lt;span class="timestamp-wrapper">&lt;span class="timestamp">&amp;lt;2022-04-09 Sat&amp;gt; &lt;/span>&lt;/span> &lt;a href="https://protesilaos.com/codelog/2022-04-09-simple-guide-git-patches-emacs/">Primer on formatting Git patches with Emacs (Magit) &amp;ndash; Protesilaos Stavrou&lt;/a>&lt;/li>
&lt;li>&lt;span class="timestamp-wrapper">&lt;span class="timestamp">&amp;lt;2021-08-17 Tue&amp;gt; &lt;/span>&lt;/span> &lt;a href="https://www.fosskers.ca/en/blog/contributing-to-emacs">Contributing to Emacs &amp;ndash; Colin Woodbury&lt;/a>&lt;/li>
&lt;/ol></description><author>Kaushal.Modi@fakeEmailToMakeValidatorHappy.com (Kaushal Modi)</author><category domain="https://scripter.co/categories/emacs">emacs</category><category domain="https://scripter.co/tags/git">git</category><category domain="https://scripter.co/tags/magit">magit</category><category domain="https://scripter.co/tags/100daystooffload">100DaysToOffload</category><guid>https://scripter.co/creating-a-patch-file-using-magit/</guid><pubDate>Sun, 08 May 2022 08:48:00 -0400</pubDate></item><item><title>Presenting tomelr!</title><link>https://scripter.co/presenting-tomelr/</link><description>&lt;blockquote>In this post, I introduce a little library I created for &lt;code>ox-hugo&lt;/code> to
have a robust mechanism for generating TOML from any Lisp expression.&lt;/blockquote>&lt;div class="ox-hugo-toc toc">
&lt;div class="heading">Table of Contents&lt;/div>
&lt;ul>
&lt;li>&lt;a href="#my-flow-for-creating-this-library">My flow for creating this library&lt;/a>&lt;/li>
&lt;li>&lt;a href="#adapting-the-library-to-fit-ox-hugo">Adapting the library to fit &lt;code>ox-hugo&lt;/code>&lt;/a>&lt;/li>
&lt;li>&lt;a href="#changes-in-ox-hugo-tests">Changes in &lt;code>ox-hugo&lt;/code> tests&lt;/a>&lt;/li>
&lt;li>&lt;a href="#what-s-next">What&amp;rsquo;s next?&lt;/a>
&lt;ul>
&lt;li>&lt;a href="#unblocking-some-future-ox-hugo-improvements">Unblocking some future &lt;code>ox-hugo&lt;/code> improvements&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/div>
&lt;!--endtoc-->
&lt;p>In my previous post &lt;a href="https://scripter.co/defining-tomelr/">Defining &lt;em>tomelr&lt;/em>&lt;/a>, I started toying with the idea
of creating a library that would help convert any Lisp expression to a
TOML config, and I share my vision (specification) of what this
library would look like.&lt;/p>
&lt;p>I wasn&amp;rsquo;t even sure if I would be able to make the &lt;a href="https://github.com/kaushalmodi/tomelr">&lt;strong>tomelr&lt;/strong>&lt;/a> library
feature-complete at least to the extent of what &lt;code>ox-hugo&lt;/code> was already
doing! But to my surprise, the library development snowballed to a
completion much earlier than I thought, and additionally it helped fix
some inconsistencies that the older TOML generation code had in
&lt;code>ox-hugo&lt;/code>.&lt;/p>
&lt;p>In this post, I start by (i) giving a broad overview of how the
development of &lt;code>tomelr&lt;/code> happened, then (ii) briefly describe how it
got integrated into &lt;code>ox-hugo&lt;/code>, and finally (iii) how the use of this
library will unblock the path to addition of some cool features to
&lt;code>ox-hugo&lt;/code>.&lt;/p>
&lt;h2 id="my-flow-for-creating-this-library">My flow for creating this library&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#my-flow-for-creating-this-library">#&lt;/a>&lt;/h2>
&lt;ol>
&lt;li>Write the spec for the library.
&lt;ul>
&lt;li>List all the formats of Lisp data I would expect it to process.&lt;/li>
&lt;li>List the corresponding TOML data I would expect it to generate.&lt;/li>
&lt;li>Ensure that I am not inventing my &lt;em>own lisp syntax&lt;/em> by confirming
that the expected TOML output matches the JSON generated from
that same lisp form (using the Emacs built-in &lt;code>json.el&lt;/code> library).&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>That helped me write the tests first! &amp;ndash; &lt;a href="https://en.wikipedia.org/wiki/Test-driven_development">Test Driven Development
(TDD)&lt;/a>.&lt;/li>
&lt;li>I started with writing tests for TOML booleans and then
implementing that (because that was the simplest and easiest). Of
course, I used &lt;a href="https://scripter.co/quick-intro-to-emacs-lisp-regression-testing/">ert&lt;/a> for this! &lt;code>ert&lt;/code> helped me quickly create small
modular tests
&lt;span class="sidenote-number">&lt;small class="sidenote">
&lt;a href="https://github.com/kaushalmodi/tomelr/blob/867c82c9e230309c748de59bf8c0937b10d6fc64/test/tscalar.el#L31-L43">Here&amp;rsquo;s&lt;/a> the &lt;em>ert&lt;/em> test for booleans as an example.
&lt;/small>&lt;/span>
and efficiently iterate through modifications in the library code
until I got the tests to pass.&lt;/li>
&lt;li>Once that got working, I set up a continuous integration system
using &lt;a href="https://docs.github.com/en/actions">GitHub Actions (GHA)&lt;/a>. I used GHA because I host my library on
GitHub. Also I already have a tried and tested setup that I could
get up and going in a matter of few seconds. In general, this
concept would apply to any &lt;em>Continuous Integration system&lt;/em>. The CI
setup step should come early in the development of any project so
that incremental feature additions don&amp;rsquo;t start breaking previously
added features 😃.&lt;/li>
&lt;li>The library development just snowballed after this point .. added
support for integers, floats, regular strings, multi-line strings,
arrays, TOML tables, arrays of TOML tables. By this time, the
library was about 80% finished.&lt;/li>
&lt;li>Then came the difficult part .. stabilizing the library to support
all the varieties of Lisp data I can think of. I must have put in
double the time spent so far to finish the remaining 20% of the
planned features for this library 👉 &lt;a href="https://github.com/kaushalmodi/tomelr/tree/main/test">&lt;strong>tomelr test suite&lt;/strong>&lt;/a>&lt;/li>
&lt;li>Once I had the test suite complete and passing, it was time to do
some code cleanup:
&lt;ul>
&lt;li>Remove duplicate code and break them off into smaller helper
functions.&lt;/li>
&lt;li>See if the function defined in this library is already defined
somewhere else (in this case, I was able to use &lt;code>json-plist-p&lt;/code>
directly from &lt;code>json.el&lt;/code>).&lt;/li>
&lt;li>Proof read the code.&lt;/li>
&lt;li>Proof read the docstrings and run &lt;code>M-x checkdoc&lt;/code> to fix their
formatting.&lt;/li>
&lt;li>Ensure that the code compiles without any warnings.&lt;/li>
&lt;li>Remove unnecessary customization options and case statements from
the library (while continuously ensuring that the &lt;em>ert&lt;/em> tests
still pass).&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;h2 id="adapting-the-library-to-fit-ox-hugo">Adapting the library to fit &lt;code>ox-hugo&lt;/code>&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#adapting-the-library-to-fit-ox-hugo">#&lt;/a>&lt;/h2>
&lt;p>After polishing the library by its stand-alone testing, I decided to
use it with &lt;code>ox-hugo&lt;/code> and see how the test suite in that repo fared.&lt;/p>
&lt;p>Of course I saw that a lot of tests failed now 😁.&lt;/p>
&lt;p>The main issue was that &lt;code>tomelr&lt;/code> was constructing multi-line strings
such that the spaces translated exactly from Lisp data to TOML. So
&lt;code class="code-inline language-emacs-lisp">&lt;span class="p">(&lt;/span>&lt;span class="nv">tomelr-encode&lt;/span> &lt;span class="o">&amp;#39;&lt;/span>&lt;span class="p">((&lt;/span>&lt;span class="nv">foo&lt;/span> &lt;span class="o">.&lt;/span> &lt;span class="s">&amp;#34;line1\nline2&amp;#34;&lt;/span>&lt;span class="p">)))&lt;/span>&lt;/code> would generate:&lt;/p>
&lt;p>&lt;a id="code-snippet--tomelr-mls-no-extra-ws">&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-toml" data-lang="toml">&lt;span class="line">&lt;span class="cl">&lt;span class="nx">foo&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">line1
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">line2&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="src-block-caption">
&lt;span class="src-block-number">&lt;a href="#code-snippet--tomelr-mls-no-extra-ws">Code Snippet 1&lt;/a>:&lt;/span>
Multi-line string with same white-space as in original data.. but not that "pretty"
&lt;/div>
&lt;p>whereas &lt;code>ox-hugo&lt;/code> expected the same TOML to look like:&lt;/p>
&lt;p>&lt;a id="code-snippet--tomelr-pretty-mls">&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-toml" data-lang="toml">&lt;span class="line">&lt;span class="cl">&lt;span class="nx">foo&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> line1
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> line2
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="src-block-caption">
&lt;span class="src-block-number">&lt;a href="#code-snippet--tomelr-pretty-mls">Code Snippet 2&lt;/a>:&lt;/span>
Pretty multi-line string, but with extra white-space
&lt;/div>
&lt;p>I had intentionally decided for &lt;code>ox-hugo&lt;/code> to have this latter format
for multi-line strings because (i) it made it more readable with the
&lt;em>triple-quotes&lt;/em> out of the way on their own lines, (ii) the indented
lines prevented the multi-line string from getting mixed with
surrounding TOML parameters, and &lt;strong>most importantly&lt;/strong> (iii) these
strings were processed by the Hugo Markdown parser, and so it wasn&amp;rsquo;t
sensitive to horizontal spaces.&lt;/p>
&lt;p>And so the &lt;code>tomelr-indent-multi-line-strings&lt;/code> feature was born
(&lt;a href="https://github.com/kaushalmodi/tomelr/commit/3362213172237f40ff0d9aa3ddf12b4bb00a3564">commit&lt;/a>) which optionally made &lt;code>tomelr&lt;/code> export multi-line strings as
expected by &lt;code>ox-hugo&lt;/code> 😎.&lt;/p>
&lt;h2 id="changes-in-ox-hugo-tests">Changes in &lt;code>ox-hugo&lt;/code> tests&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#changes-in-ox-hugo-tests">#&lt;/a>&lt;/h2>
&lt;p>Once I had finalized the integration of &lt;code>tomelr&lt;/code> into &lt;code>ox-hugo&lt;/code>, I had
only about 30 tests change out of roughly 400 tests. These changes
were welcome as they fixed all the inconsistencies in the older TOML
generation code in &lt;code>ox-hugo&lt;/code>. If interested, you can see &lt;a href="https://github.com/kaushalmodi/ox-hugo/commit/c24ea792484598ffd2f8e786fadb823d48c8ec12">this commit&lt;/a>
for the diff and details, but here&amp;rsquo;s the gist:&lt;/p>
&lt;ol>
&lt;li>Now &lt;em>nil&lt;/em> value of a key in Lisp consistently implies that the key
should not be exported to TOML. So &lt;code class="code-inline language-emacs-lisp">&lt;span class="o">&amp;#39;&lt;/span>&lt;span class="p">((&lt;/span>&lt;span class="nv">foo&lt;/span> &lt;span class="o">.&lt;/span> &lt;span class="no">nil&lt;/span>&lt;span class="p">))&lt;/span>&lt;/code> will result in &lt;code>foo&lt;/code> &lt;strong>not&lt;/strong> getting exported
to TOML, whether that&amp;rsquo;s a top-level key or a key in a nested TOML
map or array. If you need to set a key to a boolean &lt;em>false&lt;/em>, use
&lt;code>&amp;quot;false&amp;quot;&lt;/code> or any value from &lt;code>tomelr-false&lt;/code>.&lt;/li>
&lt;li>Earlier &lt;em>empty string&lt;/em> value as in &lt;code class="code-inline language-emacs-lisp">&lt;span class="o">&amp;#39;&lt;/span>&lt;span class="p">((&lt;/span>&lt;span class="nv">foo&lt;/span> &lt;span class="o">.&lt;/span> &lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">))&lt;/span>&lt;/code> behaved like the current &lt;em>nil&lt;/em>
implementation. That&amp;rsquo;s not the case any more. Now that empty string
will export as &lt;code class="code-inline language-toml">&lt;span class="nx">foo&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;/code> in TOML.&lt;/li>
&lt;li>Now if a string has a quote character (&lt;code>&amp;quot;&lt;/code>) in it, that value will
auto-export as TOML multi-line string. I like the readability of
this more than that of backslash-escaped double-quotes.&lt;/li>
&lt;li>Now the nested tables like &lt;code class="code-inline language-toml">&lt;span class="p">[&lt;/span>&lt;span class="nx">menu&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="s2">&amp;#34;nested menu&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;/code> export with their parent table keys like &lt;code class="code-inline language-toml">&lt;span class="p">[&lt;/span>&lt;span class="nx">menu&lt;/span>&lt;span class="p">]&lt;/span>&lt;/code>. As per the TOML spec, this is not required. But now
that &lt;code>tomelr&lt;/code> has added a generic support for any TOML table, this
change happens as a result of consistency 💯.&lt;/li>
&lt;/ol>
&lt;p>In summary, the changes in &lt;code>ox-hugo&lt;/code> TOML front-matter exports were
mostly cosmetic, and if they were not cosmetic, they were consistency
fixes.&lt;/p>
&lt;h2 id="what-s-next">What&amp;rsquo;s next?&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#what-s-next">#&lt;/a>&lt;/h2>
&lt;dl>
&lt;dt>tomelr&lt;/dt>
&lt;dd>The library is pretty much feature complete ✨ as
many of the examples from &lt;a href="https://toml.io/en/v1.0.0">TOML v1.0.0 spec&lt;/a> have been added to its
test suite, and .. it is supporting all the &lt;code>ox-hugo&lt;/code> use cases.
&lt;p>The library though has &lt;a href="https://github.com/kaushalmodi/tomelr#limitations">one limitation&lt;/a> that I&amp;rsquo;d like to resolve at
some point &amp;mdash; Right now, we require the Lisp data to first list all
the scalar keys and then list the TOML tables and arrays of
tables. But at the moment, I don&amp;rsquo;t know how to fix that, and also
&lt;code>ox-hugo&lt;/code> is not affected by that (because it already populates the
front-matter alist in the correct order). So fixing this is not
urgent, but of course, if someone can help me out with that, I&amp;rsquo;d
welcome that! 🙏.&lt;/p>
&lt;/dd>
&lt;dt>ox-hugo&lt;/dt>
&lt;dd>Given that &lt;code>tomelr&lt;/code> allows robustly exporting any Lisp
data expression to TOML, I do not see any value in continuing with
YAML generation support using the old custom code.
&lt;p>📢 In near future, I plan to get rid of the
&lt;code>org-hugo-front-matter-format&lt;/code> customization variable from &lt;code>ox-hugo&lt;/code>
&amp;mdash; thus deprecating YAML export support
&lt;span class="sidenote-number">&lt;small class="sidenote">
This change should not functionally affect the YAML front-matter
fans out there because the front-matter that &lt;code>ox-hugo&lt;/code> is exporting
is mainly for Hugo&amp;rsquo;s consumption. The only scenario where I see that
this change can be breaking is if the user is using YAML format
&lt;em>extra front-matter&lt;/em> blocks. If so, unfortunately, they will need to
convert those to TOML manually.
&lt;/small>&lt;/span>
and sticking with using just TOML for the front-matter.&lt;/p>
&lt;/dd>
&lt;/dl>
&lt;h3 id="unblocking-some-future-ox-hugo-improvements">Unblocking some future &lt;code>ox-hugo&lt;/code> improvements&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#unblocking-some-future-ox-hugo-improvements">#&lt;/a>&lt;/h3>
&lt;p>This decision will open up the doors to add more features to &lt;code>ox-hugo&lt;/code>
like:&lt;/p>
&lt;ol>
&lt;li>
&lt;p>Exporting Org &lt;code>:LOGBOOK:&lt;/code> drawers to TOML front-matter (&lt;a href="https://github.com/kaushalmodi/ox-hugo/pull/504">ox-hugo #
&lt;strong>504&lt;/strong>&lt;/a>)&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Exporting Org Special Blocks to user-configurable front-matter
(&lt;a href="https://github.com/kaushalmodi/ox-hugo/pull/627">ox-hugo # &lt;strong>627&lt;/strong>&lt;/a>)&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Supporting more complex data in Lisp form using
&lt;code>:EXPORT_HUGO_CUSTOM_FRONT_MATTER:&lt;/code> which could translate to nested
TOML tables or arrays of TOML tables.&lt;/p>
&lt;p>Finally, there won&amp;rsquo;t be a need to use the &lt;a href="https://ox-hugo.scripter.co/doc/custom-front-matter/#front-matter-extra">&amp;ldquo;Extra front-matter&amp;rdquo;&lt;/a>
workaround. For example, it would be possible to represent the data
in that first example on that page as &lt;code class="code-inline language-emacs-lisp">&lt;span class="nb">:foo&lt;/span> &lt;span class="p">((&lt;/span>&lt;span class="nb">:bar&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="nb">:zoo&lt;/span> &lt;span class="s">&amp;#34;abc&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nb">:bar&lt;/span> &lt;span class="mi">2&lt;/span> &lt;span class="nb">:zoo&lt;/span> &lt;span class="s">&amp;#34;def&amp;#34;&lt;/span>&lt;span class="p">))&lt;/span>&lt;/code> in the
&lt;code>:EXPORT_HUGO_CUSTOM_FRONT_MATTER:&lt;/code> property.&lt;/p>
&lt;/li>
&lt;/ol></description><author>Kaushal.Modi@fakeEmailToMakeValidatorHappy.com (Kaushal Modi)</author><category domain="https://scripter.co/categories/web">web</category><category domain="https://scripter.co/categories/org">org</category><category domain="https://scripter.co/categories/hugo">hugo</category><category domain="https://scripter.co/categories/emacs">emacs</category><category domain="https://scripter.co/categories/elisp">elisp</category><category domain="https://scripter.co/tags/ox-hugo">ox-hugo</category><category domain="https://scripter.co/tags/toml">toml</category><category domain="https://scripter.co/tags/100daystooffload">100DaysToOffload</category><guid>https://scripter.co/presenting-tomelr/</guid><pubDate>Wed, 04 May 2022 01:03:00 -0400</pubDate></item><item><title>Defining tomelr – A library for converting Lisp expressions to TOML</title><link>https://scripter.co/defining-tomelr/</link><description>&lt;blockquote>Creating a specification for an Emacs-Lisp library to convert Lisp
data expressions into easy-to-read TOML strings.&lt;/blockquote>&lt;div class="ox-hugo-toc toc">
&lt;div class="heading">Table of Contents&lt;/div>
&lt;ul>
&lt;li>&lt;a href="#using-json-encode-as-reference">Using &lt;code>json-encode&lt;/code> as reference&lt;/a>&lt;/li>
&lt;li>&lt;a href="#mapping-scalar-data-to-toml">Mapping scalar data to TOML&lt;/a>
&lt;ul>
&lt;li>&lt;a href="#about-false">About &lt;code>:false&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;a href="#mapping-lists-to-toml">Mapping lists to TOML&lt;/a>&lt;/li>
&lt;li>&lt;a href="#mapping-lists-of-lists-to-toml">Mapping lists of lists to TOML&lt;/a>&lt;/li>
&lt;li>&lt;a href="#mapping-other-object-types">Mapping other object types&lt;/a>&lt;/li>
&lt;li>&lt;a href="#closing">Closing&lt;/a>&lt;/li>
&lt;/ul>
&lt;/div>
&lt;!--endtoc-->
&lt;p>&lt;code>ox-hugo&lt;/code> has some custom code that generates &lt;a href="https://toml.io/en/">TOML&lt;/a>
&lt;span class="sidenote-number">&lt;small class="sidenote">
I ❤️ TOML. As the makers of this config format put it.. &amp;ldquo;it&amp;rsquo;s a
format &lt;em>for humans&lt;/em>&amp;rdquo;! &amp;mdash; No need to deal with indentations, weird
syntax for multi-line strings, no prohibition on adding comments to
the config, or dealing with careful placement of commas and braces.
&lt;/small>&lt;/span>
for &lt;a href="https://gohugo.io/">Hugo&lt;/a> front-matter, based on the Org keywords and other meta-data
that the user sets in their Org file. But this TOML generation code is
not generic enough for any TOML object type.&lt;/p>
&lt;p>As I am &lt;a href="https://github.com/kaushalmodi/ox-hugo/pull/504#issuecomment-1093592230">writing up a definition&lt;/a> on how to export &lt;code>:LOGBOOK:&lt;/code> &lt;a href="https://orgmode.org/manual/Drawers.html" title="Emacs Lisp: (info &amp;quot;(org) Drawers&amp;quot;)">drawers&lt;/a>,
I felt it&amp;rsquo;s a good time to polish the whole &lt;strong>Lisp data → TOML&lt;/strong>
conversion code, and may be package that into a separate library.&lt;/p>
&lt;div class="verse">
&lt;p>        It&amp;rsquo;s kind of an ambitious project &amp;mdash; I am calling it &lt;a href="https://github.com/kaushalmodi/tomelr">tom​&lt;strong>el&lt;/strong>​r&lt;/a> ✨&lt;br />&lt;/p>
&lt;/div>
&lt;p>It&amp;rsquo;s a big undertaking to create a generic library for this kind of
data format conversion. But even before I start coding or think if I
can complete this project, I need to &lt;em>spec&lt;/em>
&lt;span class="sidenote-number">&lt;small class="sidenote">
I am not sure if it&amp;rsquo;s a widely used verb, but &lt;em>to spec&lt;/em> means &lt;em>to
write a specification for something&lt;/em>.
&lt;/small>&lt;/span>
it. I need to understand early-on how the &lt;em>S-exp&lt;/em> (Symbolic lisp
expression) would needed to look for each kind of generated TOML
object &amp;mdash; scalars, lists, lists of lists, maps, lists of maps, etc.&lt;/p>
&lt;h2 id="using-json-encode-as-reference">Using &lt;code>json-encode&lt;/code> as reference&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#using-json-encode-as-reference">#&lt;/a>&lt;/h2>
&lt;p>The aim of the &lt;code>tomelr&lt;/code> library is to take some &lt;code>(lisp data)&lt;/code> and
convert that TOML. But I did not want to invent my own &lt;em>lisp data
convention&lt;/em> for this! So I decided to stick with the lisp expression
conventions understood by the &lt;code>json-encode&lt;/code> function from the Emacs
core library &lt;code>json.el&lt;/code>.&lt;/p>
&lt;p>Credit for the &lt;code>json.el&lt;/code> idea goes to &lt;a href="https://twitter.com/pdcawley/status/1519007598896369664">this tweet&lt;/a> by &lt;a href="https://twitter.com/pdcawley">Piers Cawley&lt;/a>:&lt;/p>
&lt;blockquote>
&lt;p>I&amp;rsquo;d suggest that
&lt;span class="sidenote-number">&lt;small class="sidenote">
By &amp;ldquo;that&amp;rdquo;, he&amp;rsquo;s referring to adding support for exporting front-matter
to JSON in &lt;code>ox-hugo&lt;/code>.
&lt;/small>&lt;/span>
, since emacs has built in JSON support these days, you
don&amp;rsquo;t really have to worry about the commas and braces, just build the
s-exp you want and export, but it&amp;rsquo;s you that&amp;rsquo;s writing the code and
I&amp;rsquo;m just delighted that it exists.&lt;/p>
&lt;p>Thank you for your efforts.&lt;/p>
&lt;/blockquote>
&lt;p>I am not sold on adding support of yet another front-matter format to
&lt;code>ox-hugo&lt;/code>. I might not use &lt;code>json.el&lt;/code> for that, but it definitely
helped me a lot with coming up with this library&amp;rsquo;s spec 😆.&lt;/p>
&lt;h2 id="mapping-scalar-data-to-toml">Mapping scalar data to TOML&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#mapping-scalar-data-to-toml">#&lt;/a>&lt;/h2>
&lt;p>Figuring out the Lisp representation for scalar (plain key-value
pairs) TOML objects was easy. &lt;code>json.el&lt;/code> helped figure out how to deal
with &lt;em>nil&lt;/em> and &lt;em>false&lt;/em> values.&lt;/p>
&lt;p>&lt;a id="table--mapping-scalar-lisp-to-toml">&lt;/a>&lt;/p>
&lt;div class="table-caption">
&lt;span class="table-number">&lt;a href="#table--mapping-scalar-lisp-to-toml">Table 1&lt;/a>:&lt;/span>
Mapping of &lt;i>scalar&lt;/i> Lisp data to TOML
&lt;/div>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Lisp S-exp&lt;/th>
&lt;th>TOML&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>'((int_key . 123))&lt;/code>&lt;/td>
&lt;td>&lt;code>int_key = 123&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>'((float_key . 1.23))&lt;/code>&lt;/td>
&lt;td>&lt;code>float_key = 1.23&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>'((date_key . 2022-04-27))&lt;/code>&lt;/td>
&lt;td>&lt;code>date_key = 2022-04-27&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>'((bool_key . t))&lt;/code>&lt;/td>
&lt;td>&lt;code>bool_key = true&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>'((any_key . nil))&lt;/code>&lt;/td>
&lt;td>&lt;em>(key removed in TOML)&lt;/em>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>'((bool_key . :false))&lt;/code>&lt;/td>
&lt;td>&lt;code>bool_key = false&lt;/code>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="about-false">About &lt;code>:false&lt;/code>&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#about-false">#&lt;/a>&lt;/h3>
&lt;p>&lt;code>json.el&lt;/code> defines a variable &lt;code>json-false&lt;/code> that&amp;rsquo;s set to the value
&lt;code>:json-false&lt;/code>. This is because in JSON, the &lt;em>null&lt;/em> value is different
from the boolean &lt;code>false&lt;/code> value.&lt;/p>
&lt;ul>
&lt;li>&lt;em>nil&lt;/em> in Lisp → &lt;em>null&lt;/em> in JSON&lt;/li>
&lt;li>&lt;code>:json-false&lt;/code> in Lisp → &lt;code>false&lt;/code> in JSON&lt;/li>
&lt;/ul>
&lt;p>Inspired by that decision of &lt;code>json.el&lt;/code>, I am thinking of using
&lt;code>:false&lt;/code> as the special value that will set the equivalent TOML value
to boolean &lt;code>false&lt;/code>.&lt;/p>
&lt;div class="note">
&lt;p>TOML does not define a &lt;em>null&lt;/em> value, but if the Lisp value is &lt;em>nil&lt;/em>,
that key will simply not be translated to TOML.&lt;/p>
&lt;/div>
&lt;h2 id="mapping-lists-to-toml">Mapping lists to TOML&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#mapping-lists-to-toml">#&lt;/a>&lt;/h2>
&lt;p>Mapping lists was simple.. because in Lisp, a list value of course
looks like &lt;code class="code-inline language-emacs-lisp">&lt;span class="o">&amp;#39;&lt;/span>&lt;span class="p">((&lt;/span>&lt;span class="nv">foo&lt;/span> &lt;span class="o">.&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span> &lt;span class="mi">2&lt;/span> &lt;span class="mi">3&lt;/span> &lt;span class="mi">4&lt;/span> &lt;span class="mi">5&lt;/span>&lt;span class="p">)))&lt;/span>&lt;/code>
😃.&lt;/p>
&lt;p>&lt;a id="table--mapping-list-lisp-to-toml">&lt;/a>&lt;/p>
&lt;div class="table-caption">
&lt;span class="table-number">&lt;a href="#table--mapping-list-lisp-to-toml">Table 2&lt;/a>:&lt;/span>
Mapping of &lt;i>list&lt;/i> Lisp data to TOML
&lt;/div>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Lisp S-exp&lt;/th>
&lt;th>TOML&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>'((list_key1 . (1 2 3)))&lt;/code>&lt;/td>
&lt;td>&lt;code>list_key1 = [1, 2, 3]&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>'((list_key2 . (&amp;quot;a&amp;quot; &amp;quot;b&amp;quot; &amp;quot;c&amp;quot;)))&lt;/code>&lt;/td>
&lt;td>&lt;code>list_key2 = [&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, &amp;quot;c&amp;quot;]&lt;/code>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="mapping-lists-of-lists-to-toml">Mapping lists of lists to TOML&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#mapping-lists-of-lists-to-toml">#&lt;/a>&lt;/h2>
&lt;p>&lt;a id="table--mapping-list-of-list-lisp-to-toml">&lt;/a>&lt;/p>
&lt;div class="table-caption">
&lt;span class="table-number">&lt;a href="#table--mapping-list-of-list-lisp-to-toml">Table 3&lt;/a>:&lt;/span>
Mapping of &lt;i>list of list&lt;/i> Lisp data to TOML
&lt;/div>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Lisp S-exp&lt;/th>
&lt;th>TOML&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>'((lol_key . [(1 2) (3 4)]))&lt;/code>&lt;/td>
&lt;td>&lt;code>lol_key = [ [1, 2], [3, 4] ]&lt;/code>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>I was going to use &lt;code class="code-inline language-emacs-lisp">&lt;span class="o">&amp;#39;&lt;/span>&lt;span class="p">((&lt;/span>&lt;span class="nv">lol_key&lt;/span> &lt;span class="o">.&lt;/span> &lt;span class="p">((&lt;/span>&lt;span class="mi">1&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="mi">3&lt;/span> &lt;span class="mi">4&lt;/span>&lt;span class="p">))))&lt;/span>&lt;/code> as the reference Lisp expression for &lt;code class="code-inline language-toml">&lt;span class="nx">lol_key&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="p">[&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">],&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">4&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="p">]&lt;/span>&lt;/code>. But I found out that
&lt;code>json-encode&lt;/code> throws an error if you pass it that expression! I don&amp;rsquo;t
understand the reason for that error, and so I have &lt;a href="https://lists.gnu.org/r/help-gnu-emacs/2022-04/msg00240.html">asked for help&lt;/a> on
the &lt;em>help-gnu-emacs&lt;/em> mailing list.&lt;/p>
&lt;p>But while that question gets resolved, I wanted to move forward with
the spec definition. After some trial-and-error and
reverse-engineering &lt;code>json.el&lt;/code>
&lt;span class="sidenote-number">&lt;small class="sidenote">
I knew how I wanted TOML to look. So I used &lt;a href="https://toolkit.site/format.html">an online JSON/TOML
converter&lt;/a> to convert that TOML snippet to JSON, and then used
&lt;code>json-read&lt;/code> to convert JSON to Lisp expression.
&lt;/small>&lt;/span>
, I learned that &lt;em>list of list&lt;/em> data needs to be represented using a &lt;a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Vector-Type.html" title="Emacs Lisp: (info &amp;quot;(elisp) Vector Type&amp;quot;)">Vector type&lt;/a>, and so &lt;code class="code-inline language-emacs-lisp">&lt;span class="o">&amp;#39;&lt;/span>&lt;span class="p">((&lt;/span>&lt;span class="nv">lol_key&lt;/span> &lt;span class="o">.&lt;/span> &lt;span class="p">[(&lt;/span>&lt;span class="mi">1&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="mi">3&lt;/span> &lt;span class="mi">4&lt;/span>&lt;span class="p">)]))&lt;/span>&lt;/code> would be the correct expression &amp;ndash; &lt;em>Notice the use
of square brackets instead of parentheses for the outer vector&lt;/em>.&lt;/p>
&lt;h2 id="mapping-other-object-types">Mapping other object types&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#mapping-other-object-types">#&lt;/a>&lt;/h2>
&lt;p>Once I figured out how to map the above data types, mapping Lisp data
to &lt;em>TOML Tables&lt;/em> aka &lt;em>dictionaries&lt;/em> and &lt;em>arrays of Tables&lt;/em> was a
breeze
&lt;span class="sidenote-number">&lt;small class="sidenote">
Of course, the &lt;em>breeze&lt;/em> is referring to the ease of writing the spec
for these 😆. Implementation-wise, the &lt;em>tables&lt;/em>, &lt;em>arrays of
tables&lt;/em>, and the especially &lt;strong>nested&lt;/strong> variants of those are going to be
the most challenging.
&lt;/small>&lt;/span>
.&lt;/p>
&lt;h2 id="closing">Closing&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#closing">#&lt;/a>&lt;/h2>
&lt;p>It was fun coming up with an initial draft of the specification for
this library. My next steps would be to gradually add TOML generator
functions (as I find time) to this library, along with &lt;a href="https://scripter.co/quick-intro-to-emacs-lisp-regression-testing/">ERT tests&lt;/a>!
Eventually, I will remove the existing TOML generation code from
&lt;code>ox-hugo&lt;/code> and depend on this library.&lt;/p>
&lt;p>Getting back to &lt;a href="https://github.com/kaushalmodi/ox-hugo/pull/504#issuecomment-1093592230">my plan&lt;/a> for exporting &lt;code>:LOGBOOK:&lt;/code> drawers in
&lt;code>ox-hugo&lt;/code>, based on this spec, I will need to construct this date in
Emacs-Lisp:&lt;/p>
&lt;p>&lt;a id="code-snippet--org-logbook-lisp">&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-emacs-lisp" data-lang="emacs-lisp">&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="nv">org_logbook&lt;/span> &lt;span class="o">.&lt;/span> &lt;span class="p">(((&lt;/span>&lt;span class="nv">timestamp&lt;/span> &lt;span class="o">.&lt;/span> &lt;span class="nv">2022-04-08T14:53:00-04:00&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">note&lt;/span> &lt;span class="o">.&lt;/span> &lt;span class="s">&amp;#34;This note addition prompt shows up on typing the `C-c C-z` binding.\nSee [org#Drawers](https://www.gnu.org/software/emacs/manual/html_mono/org.html#Drawers).&amp;#34;&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">((&lt;/span>&lt;span class="nv">timestamp&lt;/span> &lt;span class="o">.&lt;/span> &lt;span class="nv">2018-09-06T11:45:00-04:00&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">note&lt;/span> &lt;span class="o">.&lt;/span> &lt;span class="s">&amp;#34;Another note **bold** _italics_.&amp;#34;&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">((&lt;/span>&lt;span class="nv">timestamp&lt;/span> &lt;span class="o">.&lt;/span> &lt;span class="nv">2018-09-06T11:37:00-04:00&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">note&lt;/span> &lt;span class="o">.&lt;/span> &lt;span class="s">&amp;#34;A note `mono`.&amp;#34;&lt;/span>&lt;span class="p">))))&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="src-block-caption">
&lt;span class="src-block-number">&lt;a href="#code-snippet--org-logbook-lisp">Code Snippet 1&lt;/a>:&lt;/span>
Example data from a &lt;code>:LOGBOOK:&lt;/code> drawer in Lisp format
&lt;/div>
&lt;p>.. will translate to this in TOML:&lt;/p>
&lt;p>&lt;a id="code-snippet--org-logbook-toml">&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-toml" data-lang="toml">&lt;span class="line">&lt;span class="cl">&lt;span class="p">[[&lt;/span>&lt;span class="nx">org_logbook&lt;/span>&lt;span class="p">]]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">timestamp&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="ld">2022-04-08T14:53:00-04:00&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">note&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;This note addition prompt shows up on typing the `C-c C-z` binding.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">See [org#Drawers](https://www.gnu.org/software/emacs/manual/html_mono/org.html#Drawers).&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">[[&lt;/span>&lt;span class="nx">org_logbook&lt;/span>&lt;span class="p">]]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">timestamp&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="ld">2018-09-06T11:45:00-04:00&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">note&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;Another note **bold** _italics_.&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">[[&lt;/span>&lt;span class="nx">org_logbook&lt;/span>&lt;span class="p">]]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">timestamp&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="ld">2018-09-06T11:37:00-04:00&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">note&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;A note `mono`.&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="src-block-caption">
&lt;span class="src-block-number">&lt;a href="#code-snippet--org-logbook-toml">Code Snippet 2&lt;/a>:&lt;/span>
Same example data from the &lt;code>:LOGBOOK:&lt;/code> drawer translated to TOML format
&lt;/div>
&lt;hr>
&lt;p>Check out the below link where I have documented the equivalent
expressions between Lisp, TOML and JSON for all the object types.&lt;/p>
&lt;p>👉 &lt;a href="https://github.com/kaushalmodi/tomelr/blob/main/README.org">tom​&lt;strong>el&lt;/strong>​r Specification&lt;/a>&lt;/p></description><author>Kaushal.Modi@fakeEmailToMakeValidatorHappy.com (Kaushal Modi)</author><category domain="https://scripter.co/categories/emacs">emacs</category><category domain="https://scripter.co/categories/elisp">elisp</category><category domain="https://scripter.co/tags/toml">toml</category><category domain="https://scripter.co/tags/100daystooffload">100DaysToOffload</category><guid>https://scripter.co/defining-tomelr/</guid><pubDate>Thu, 28 Apr 2022 00:08:00 -0400</pubDate></item><item><title> Improving ox-hugo exported Org "info:" links</title><link>https://scripter.co/improving-ox-hugo-exported-org-info-links/</link><description>&lt;blockquote>In my previous post, I talked about how &lt;code>info:&lt;/code> Org link export
support got added to &lt;code>ox-hugo&lt;/code>. This post is about making those
exported links a tiny 🤏 bit better.&lt;/blockquote>&lt;div class="ox-hugo-toc toc">
&lt;div class="heading">Table of Contents&lt;/div>
&lt;ul>
&lt;li>&lt;a href="#flexed-biceps-1-exported-links-now-point-to-separate-pages-in-the-manual">💪1: Exported links now point to separate pages in the manual&lt;/a>&lt;/li>
&lt;li>&lt;a href="#flexed-biceps-2-export-org-manual-links-to-orgmode-dot-org-urls">💪 2: Export Org manual links to &lt;code>orgmode.org&lt;/code> URLs&lt;/a>&lt;/li>
&lt;li>&lt;a href="#flexed-biceps-3-link-hover-text-shows-the-elisp-code-for-accessing-the-info-node">💪 3: Link hover text shows the &lt;em>elisp&lt;/em> code for accessing the Info node&lt;/a>&lt;/li>
&lt;li>&lt;a href="#final-code-in-ox-hugo-that-exports-the-info-links">Final code in &lt;code>ox-hugo&lt;/code> that exports the &lt;code>info:&lt;/code> links&lt;/a>&lt;/li>
&lt;/ul>
&lt;/div>
&lt;!--endtoc-->
&lt;p>After writing my &lt;a href="https://scripter.co/linking-and-exporting-org-info-links/">previous post&lt;/a>, I had shared its link on the Org mode
mailing list
&lt;span class="sidenote-number">&lt;small class="sidenote">
For folks who don&amp;rsquo;t know, you can email the Org mode mailing list
(&lt;code>emacs-orgmode@gnu.org&lt;/code>) about pretty much anything Org mode related:
any help you want, a bug you want to report, a patch you want to
submit, or just share your positive or negative experiences with Org
mode or thank someone for their awesome work.
&lt;/small>&lt;/span>
&lt;a href="https://lists.gnu.org/r/emacs-orgmode/2022-04/msg00162.html">here&lt;/a>, and received some helpful feedback from Max Nikulin.&lt;/p>
&lt;div class="verse">
&lt;p>        &lt;em>Thank you Max!&lt;/em>&lt;br />&lt;/p>
&lt;/div>
&lt;p>This post is a response to his feedback, and it also describes a few
improvements made for &lt;code>info:&lt;/code> link exports in &lt;code>ox-hugo&lt;/code> based on that.&lt;/p>
&lt;div class="note">
&lt;p>The commits for this &lt;code>info:&lt;/code> link export improvements can be found in
&lt;code>ox-hugo&lt;/code> &lt;a href="https://github.com/kaushalmodi/ox-hugo/pull/620">PR # 620&lt;/a>.&lt;/p>
&lt;/div>
&lt;h2 id="flexed-biceps-1-exported-links-now-point-to-separate-pages-in-the-manual">💪&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup> 1: Exported links now point to separate pages in the manual&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#flexed-biceps-1-exported-links-now-point-to-separate-pages-in-the-manual">#&lt;/a>&lt;/h2>
&lt;dl>
&lt;dt>Feedback&lt;/dt>
&lt;dd>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl"> For &amp;lt;info:emacs#Browse-URL&amp;gt; export to html produces the following link:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> https://www.gnu.org/software/emacs/manual/html_mono/emacs.html#Browse_002dURL
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> I think, a better variant is
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> https://www.gnu.org/software/emacs/manual/html_node/emacs/Browse_002dURL.html
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> even though for the Org manual I often prefer single-page HTML version.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/dd>
&lt;/dl>
&lt;p>I really liked this suggestion!&lt;/p>
&lt;ul>
&lt;li>Earlier, the Info node references were exporting to an &lt;span class="underline">anchor&lt;/span> on a
huge single-page HTML manual e.g. &lt;code>emacs.html#Browse_002dURL&lt;/code>&lt;/li>
&lt;li>After implementing this fix, the exported link points to a &lt;span class="underline">separate
HTML page&lt;/span> for that node e.g. &lt;code>emacs/Browse_002dURL.html&lt;/code>.&lt;/li>
&lt;/ul>
&lt;p>Now, &lt;code class="code-inline language-org">[[&lt;span class="na">info:emacs#Screen&lt;/span>]]&lt;/code> exports and renders to
&lt;a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Screen.html" title="Emacs Lisp: (info &amp;quot;(emacs) Screen&amp;quot;)">Emacs Info: Screen&lt;/a>, and a Top level node like &lt;code class="code-inline language-org">[[&lt;span class="na">info:emacs#Top&lt;/span>]]&lt;/code> exports and renders to &lt;a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/index.html" title="Emacs Lisp: (info &amp;quot;(emacs) Top&amp;quot;)">Emacs Info&lt;/a>.&lt;/p>
&lt;p>For consistency, all &lt;code>info:&lt;/code> links will now be exported to URLs
pointing to the separate node HTML pages, even for Org manual links.&lt;/p>
&lt;h2 id="flexed-biceps-2-export-org-manual-links-to-orgmode-dot-org-urls">💪 2: Export Org manual links to &lt;code>orgmode.org&lt;/code> URLs&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#flexed-biceps-2-export-org-manual-links-to-orgmode-dot-org-urls">#&lt;/a>&lt;/h2>
&lt;dl>
&lt;dt>Feedback&lt;/dt>
&lt;dd>(About an example &lt;code>info:&lt;/code> link pointing to Org manual:
&lt;code class="code-inline language-org">[[&lt;span class="na">info:org#Top&lt;/span>]]&lt;/code>)
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">And the link target ideally should be https://orgmode.org/manual/index.html
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/dd>
&lt;/dl>
&lt;p>This was another great suggestion!&lt;/p>
&lt;p>By default, the Org manual &lt;code>info:&lt;/code> links will export to URLs pointing
to the &lt;a href="https://www.gnu.org/software/emacs/manual/html_node/org/index.html">Org manual shipped with Emacs&lt;/a>. That manual will be associated
with the Org mode version that shipped with the last stable version of
Emacs. &lt;em>So depending on how long it has been since the last Emacs
release, you could be referring to quite an older version of the Org
manual.&lt;/em>&lt;/p>
&lt;p>If you install Org from GNU Elpa, you can get an
&lt;mark>update of the latest stable Org version every week&lt;/mark> !
&lt;span class="sidenote-number">&lt;small class="sidenote">
There&amp;rsquo;s a related post on &lt;a href="https://scripter.co/org-contribution-flowchart/">Org mode&amp;rsquo;s Release Flow&lt;/a> that might interest
you.
&lt;/small>&lt;/span>
And the manual hosted on &lt;a href="https://orgmode.org">https://orgmode.org&lt;/a> gets updated every week
as well. I would like to always refer to the latest Org manual with
the latest fixes and documentation improvements, and so I agree with
Max&amp;rsquo;s suggestion above.&lt;/p>
&lt;p>Now &lt;code class="code-inline language-org">[[&lt;span class="na">info:org#Top&lt;/span>]]&lt;/code> exports and renders as
&lt;a href="https://orgmode.org/manual/index.html" title="Emacs Lisp: (info &amp;quot;(org) Top&amp;quot;)">Org Info&lt;/a> and the Org manual nodes like &lt;code class="code-inline language-org">[[&lt;span class="na">info:org#Working with Source Code&lt;/span>]]&lt;/code> also export as a link to a
page in that manual: &lt;span class="org-target" id="org-target--improving-info-link-exports--last-link">&lt;/span>
&lt;a href="https://orgmode.org/manual/Working-with-Source-Code.html" title="Emacs Lisp: (info &amp;quot;(org) Working with Source Code&amp;quot;)">Org Info: Working with Source Code&lt;/a>.&lt;/p>
&lt;h2 id="flexed-biceps-3-link-hover-text-shows-the-elisp-code-for-accessing-the-info-node">💪 3: Link hover text shows the &lt;em>elisp&lt;/em> code for accessing the Info node&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#flexed-biceps-3-link-hover-text-shows-the-elisp-code-for-accessing-the-info-node">#&lt;/a>&lt;/h2>
&lt;dl>
&lt;dt>Feedback&lt;/dt>
&lt;dd>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl"> I would prefer
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> info &amp;#34;(org) Top&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> to
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Org Info: Top
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> since the former may be pasted to M-x : or to shell command prompt.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/dd>
&lt;/dl>
&lt;p>I wanted the link descriptions in the exported markdown to be more
&amp;ldquo;English&amp;rdquo; and understandable to people not familiar with the Emacs
Info interface. So I decided to keep this &lt;em>mostly&lt;/em> unchanged ..&lt;/p>
&lt;p>I did not change the link &lt;em>description&lt;/em>, but I did add a new HTML
&lt;strong>title&lt;/strong> attribute to the link. This attribute contains the Emacs Lisp
code needed to access the Info manual from Emacs. The user will see
the text from this attribute when they hover the mouse over the
links. If you haven&amp;rsquo;t already discovered this feature, try hovering
the mouse over &lt;a href="#org-target--improving-info-link-exports--last-link">that last link above&lt;/a> and you should see this 😃 :&lt;/p>
&lt;p>&lt;a id="figure--info-link-title-attribute">&lt;/a>&lt;/p>
&lt;figure>
&lt;img src="https://scripter.co/improving-ox-hugo-exported-org-info-links/info-link-title-attribute.png" alt="Figure 1: Hovering the mouse over the exported info: links will show the Emacs Lisp code for accessing the same node from Emacs"/> &lt;figcaption>
&lt;p>
&lt;span class="figure-number">Figure 1: &lt;/span>Hovering the mouse over the exported &lt;code>info:&lt;/code> links will show the Emacs Lisp code for accessing the same node from Emacs
&lt;/p>
&lt;/figcaption>&lt;/figure>
&lt;p>Of course, the user will still not be able to copy that text and paste
in Emacs. But it will still provide them enough hint on how to access
Info nodes in Emacs.&lt;/p>
&lt;h2 id="final-code-in-ox-hugo-that-exports-the-info-links">Final code in &lt;code>ox-hugo&lt;/code> that exports the &lt;code>info:&lt;/code> links&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#final-code-in-ox-hugo-that-exports-the-info-links">#&lt;/a>&lt;/h2>
&lt;p>Here&amp;rsquo;s the version of the &lt;code>org-hugo--org-info-export&lt;/code> function that
handles the exports of &lt;code>info:&lt;/code> links as of today (&lt;span class="timestamp-wrapper">&lt;span class="timestamp">&amp;lt;2022-04-15 Fri&amp;gt;&lt;/span>&lt;/span>):&lt;/p>
&lt;details title="Click to expand">
&lt;summary>&lt;code>org-hugo--org-info-export&lt;/code> function from &lt;code>ox-hugo&lt;/code>&lt;/summary>
&lt;div class="details">
&lt;p>&lt;a id="code-snippet--org-hugo--org-info-export">&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">888
&lt;/span>&lt;span class="lnt">889
&lt;/span>&lt;span class="lnt">890
&lt;/span>&lt;span class="lnt">891
&lt;/span>&lt;span class="lnt">892
&lt;/span>&lt;span class="lnt">893
&lt;/span>&lt;span class="lnt">894
&lt;/span>&lt;span class="lnt">895
&lt;/span>&lt;span class="lnt">896
&lt;/span>&lt;span class="lnt">897
&lt;/span>&lt;span class="lnt">898
&lt;/span>&lt;span class="lnt">899
&lt;/span>&lt;span class="lnt">900
&lt;/span>&lt;span class="lnt">901
&lt;/span>&lt;span class="lnt">902
&lt;/span>&lt;span class="lnt">903
&lt;/span>&lt;span class="lnt">904
&lt;/span>&lt;span class="lnt">905
&lt;/span>&lt;span class="lnt">906
&lt;/span>&lt;span class="lnt">907
&lt;/span>&lt;span class="lnt">908
&lt;/span>&lt;span class="lnt">909
&lt;/span>&lt;span class="lnt">910
&lt;/span>&lt;span class="lnt">911
&lt;/span>&lt;span class="lnt">912
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-emacs-lisp" data-lang="emacs-lisp">&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="nb">defun&lt;/span> &lt;span class="nv">org-hugo--org-info-export&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nv">path&lt;/span> &lt;span class="nv">desc&lt;/span> &lt;span class="nf">format&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;Add support for exporting [[info:..]] links for &lt;/span>&lt;span class="ss">`hugo&amp;#39;&lt;/span>&lt;span class="s"> format.&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">let*&lt;/span> &lt;span class="p">((&lt;/span>&lt;span class="nv">parts&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nv">split-string&lt;/span> &lt;span class="nv">path&lt;/span> &lt;span class="s">&amp;#34;#\\|::&amp;#34;&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">manual&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">car&lt;/span> &lt;span class="nv">parts&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">node&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nb">or&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">nth&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="nv">parts&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="s">&amp;#34;Top&amp;#34;&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">title&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">format&lt;/span> &lt;span class="s">&amp;#34;Emacs Lisp: (info \\\&amp;#34;(%s) %s\\\&amp;#34;)&amp;#34;&lt;/span> &lt;span class="nv">manual&lt;/span> &lt;span class="nv">node&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">desc&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nb">or&lt;/span> &lt;span class="nv">desc&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nv">string=&lt;/span> &lt;span class="nv">node&lt;/span> &lt;span class="s">&amp;#34;Top&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nf">format&lt;/span> &lt;span class="s">&amp;#34;%s Info&amp;#34;&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">capitalize&lt;/span> &lt;span class="nv">manual&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nf">format&lt;/span> &lt;span class="s">&amp;#34;%s Info: %s&amp;#34;&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">capitalize&lt;/span> &lt;span class="nv">manual&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="nv">node&lt;/span>&lt;span class="p">))))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">;; `link&amp;#39; below is mostly derived from the code in&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">;; `org-info-map-html-url&amp;#39;.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">link&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nb">cond&lt;/span> &lt;span class="p">((&lt;/span>&lt;span class="nf">member&lt;/span> &lt;span class="nv">manual&lt;/span> &lt;span class="nv">org-info-emacs-documents&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">let&lt;/span> &lt;span class="p">((&lt;/span>&lt;span class="nv">manual-url&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nb">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nv">string=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">downcase&lt;/span> &lt;span class="nv">manual&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="s">&amp;#34;org&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;https://orgmode.org/manual&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nf">format&lt;/span> &lt;span class="s">&amp;#34;https://www.gnu.org/software/emacs/manual/html_node/%s&amp;#34;&lt;/span> &lt;span class="nv">manual&lt;/span>&lt;span class="p">)))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">node-url&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nb">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nv">string=&lt;/span> &lt;span class="nv">node&lt;/span> &lt;span class="s">&amp;#34;Top&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;index.html&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nf">concat&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nv">org-info--expand-node-name&lt;/span> &lt;span class="nv">node&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="s">&amp;#34;.html&amp;#34;&lt;/span>&lt;span class="p">))))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nf">format&lt;/span> &lt;span class="s">&amp;#34;%s/%s&amp;#34;&lt;/span> &lt;span class="nv">manual-url&lt;/span> &lt;span class="nv">node-url&lt;/span>&lt;span class="p">)))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">((&lt;/span>&lt;span class="nf">cdr&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">assoc&lt;/span> &lt;span class="nv">manual&lt;/span> &lt;span class="nv">org-info-other-documents&lt;/span>&lt;span class="p">)))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="no">t&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nf">concat&lt;/span> &lt;span class="nv">manual&lt;/span> &lt;span class="s">&amp;#34;.html&amp;#34;&lt;/span>&lt;span class="p">)))))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">when&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">member&lt;/span> &lt;span class="nf">format&lt;/span> &lt;span class="o">&amp;#39;&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nv">md&lt;/span> &lt;span class="nv">hugo&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nf">format&lt;/span> &lt;span class="s">&amp;#34;[%s](%s \&amp;#34;%s\&amp;#34;)&amp;#34;&lt;/span> &lt;span class="nv">desc&lt;/span> &lt;span class="nv">link&lt;/span> &lt;span class="nv">title&lt;/span>&lt;span class="p">))))&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="src-block-caption">
&lt;span class="src-block-number">&lt;a href="#code-snippet--org-hugo--org-info-export">Code Snippet 1&lt;/a>:&lt;/span>
&lt;code>ox-hugo&lt;/code>'s version of &lt;code>org-info-export&lt;/code> (&lt;code>ol-info.el&lt;/code>) function
&lt;/div>
&lt;/div>
&lt;/details>
&lt;p>&lt;a href="https://github.com/kaushalmodi/ox-hugo/blob/5b3a0d8a7da49f602785aa20486bbbbeb35ebb36/ox-hugo.el#L888-L912">Link to code in the repo&lt;/a>&lt;/p>
&lt;p>I will leave it as an exercise for the reader to map the lines in
above code snippet to the features described in this post
🍀.&lt;/p>
&lt;div class="footnotes" role="doc-endnotes">
&lt;hr>
&lt;ol>
&lt;li id="fn:1">
&lt;p>Just for giggles, I am using 💪 as a replacement
for &amp;ldquo;Improvement&amp;rdquo;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;/div></description><author>Kaushal.Modi@fakeEmailToMakeValidatorHappy.com (Kaushal Modi)</author><category domain="https://scripter.co/categories/web">web</category><category domain="https://scripter.co/categories/hugo">hugo</category><category domain="https://scripter.co/categories/emacs">emacs</category><category domain="https://scripter.co/categories/org">org</category><category domain="https://scripter.co/tags/100daystooffload">100DaysToOffload</category><category domain="https://scripter.co/tags/info">info</category><category domain="https://scripter.co/tags/ox-hugo">ox-hugo</category><guid>https://scripter.co/improving-ox-hugo-exported-org-info-links/</guid><pubDate>Fri, 15 Apr 2022 22:50:00 -0400</pubDate></item><item><title> Linking and Exporting Org "info:" links</title><link>https://scripter.co/linking-and-exporting-org-info-links/</link><description>&lt;blockquote>Journey of Org links from copying (storing) them, inserting them in
Org documents and exporting them. The focus of this post is on the
&lt;code>info:&lt;/code> type Org links, but the same concept would apply to any Org
link type.&lt;/blockquote>&lt;div class="ox-hugo-toc toc">
&lt;div class="heading">Table of Contents&lt;/div>
&lt;ul>
&lt;li>&lt;a href="#storing-links-to-info-nodes">&lt;span class="section-num">1&lt;/span> Storing links to Info nodes&lt;/a>&lt;/li>
&lt;li>&lt;a href="#inserting-stored-links">&lt;span class="section-num">2&lt;/span> Inserting stored links&lt;/a>
&lt;ul>
&lt;li>&lt;a href="#org-link-library-for-info-links--ol-info">Org Link library for &lt;code>info:&lt;/code> links (&lt;code>ol-info&lt;/code>)&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;a href="#exporting-info-dot-dot-links-using-ox-hugo">&lt;span class="section-num">3&lt;/span> Exporting &lt;code>[[info:..]]&lt;/code> links using &lt;code>ox-hugo&lt;/code>&lt;/a>&lt;/li>
&lt;li>&lt;a href="#summary">Summary&lt;/a>&lt;/li>
&lt;/ul>
&lt;/div>
&lt;!--endtoc-->
&lt;p>This post was inspired out of the exercise of support &lt;code>info:&lt;/code> Org link
exports in &lt;code>ox-hugo&lt;/code>.&lt;/p>
&lt;p>There are 3 steps:&lt;/p>
&lt;ol>
&lt;li>Storing a link from any buffer that you want to later document in
an Org file.&lt;/li>
&lt;li>Inserting that link that you stored earlier.&lt;/li>
&lt;li>Exporting the Org document.&lt;/li>
&lt;/ol>
&lt;p>I am focusing on the &lt;code>info:&lt;/code> Org links in this post, they these steps
apply to &lt;a href="https://orgmode.org/manual/External-Links.html" title="Emacs Lisp: (info &amp;quot;(org) External Links&amp;quot;)">any&lt;/a> Org link type.&lt;/p>
&lt;h2 id="storing-links-to-info-nodes">&lt;span class="section-num">1&lt;/span> Storing links to Info nodes&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#storing-links-to-info-nodes">#&lt;/a>&lt;/h2>
&lt;p>If you follow the instructions on &lt;a href="https://orgmode.org/manual/Activation.html" title="Emacs Lisp: (info &amp;quot;(org) Activation&amp;quot;)">Org Info: Activation&lt;/a>, you&amp;rsquo;ll see that
it is recommended
&lt;span class="sidenote-number">&lt;small class="sidenote">
This post assumes that you have actually set this binding. If you
haven&amp;rsquo;t yet, go do it already! &lt;code>(global-set-key (kbd &amp;quot;C-c l&amp;quot;) #'org-store-link)&lt;/code>
&lt;/small>&lt;/span>
to bind the &lt;code>org-store-link&lt;/code> command to &lt;kbd>C-c&lt;/kbd> &lt;kbd>l&lt;/kbd> in your Emacs
&lt;em>global map&lt;/em>.&lt;/p>
&lt;p>&lt;code>org-store-link&lt;/code> stores an Org Mode compatible link based on the
context i.e. type of buffer where the point is. Org supports a
variety of links as documented in &lt;a href="https://orgmode.org/manual/External-Links.html" title="Emacs Lisp: (info &amp;quot;(org) External Links&amp;quot;)">Org Info: External Links&lt;/a>.&lt;/p>
&lt;p>If the point is in an ∗Info∗ buffer and &lt;code>org-store-link&lt;/code> is called, it
stores an &lt;code>info:&lt;/code> type link that will lead back to the same node where
the point was.&lt;/p>
&lt;p>Let&amp;rsquo;s say you have opened the Org Info manual and you hit &lt;kbd>C-c&lt;/kbd>
&lt;kbd>l&lt;/kbd>. You should then see this in the &lt;em>Echo Area&lt;/em>:&lt;/p>
&lt;blockquote>
&lt;p>Stored: org#Top&lt;/p>
&lt;/blockquote>
&lt;p>The link to Org manual&amp;rsquo;s &lt;em>Top&lt;/em> node is &lt;em>stored&lt;/em> by that command, but
only temporarily &amp;ndash; it isn&amp;rsquo;t yet saved anywhere.&lt;/p>
&lt;h2 id="inserting-stored-links">&lt;span class="section-num">2&lt;/span> Inserting stored links&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#inserting-stored-links">#&lt;/a>&lt;/h2>
&lt;p>These stored links can now be saved in an Org file. To do that,&lt;/p>
&lt;ul>
&lt;li>Visit an Org file or a buffer and call &lt;kbd>M-x&lt;/kbd> &lt;kbd>org-insert-link&lt;/kbd>
(bound to &lt;kbd>C-c&lt;/kbd> &lt;kbd>C-l&lt;/kbd> by default) and follow the prompts.&lt;/li>
&lt;li>An immediate &lt;kbd>RET&lt;/kbd> after the prompt will select the last stored link
to be inserted.&lt;/li>
&lt;li>The second prompt allows you to change the link description, and
then the link will be inserted.&lt;/li>
&lt;/ul>
&lt;p>If I insert the &lt;code>org#Top&lt;/code> Info link that I stored earlier over here,
and accept the default link description, it will paste as
&lt;code class="code-inline language-org">[[&lt;span class="na">info:org#Top&lt;/span>][&lt;span class="nt">org#Top&lt;/span>]]&lt;/code>.&lt;/p>
&lt;p>But .. how did the link description become &amp;ldquo;&lt;code>org#Top&lt;/code>&amp;rdquo; by default?&lt;/p>
&lt;div class="verse">
&lt;p>        The &lt;a href="https://git.savannah.gnu.org/cgit/emacs/org-mode.git/tree/lisp/ol-info.el">&lt;code>ol-info.el&lt;/code>&lt;/a> library did that.&lt;br />&lt;/p>
&lt;/div>
&lt;h3 id="org-link-library-for-info-links--ol-info">Org Link library for &lt;code>info:&lt;/code> links (&lt;code>ol-info&lt;/code>)&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#org-link-library-for-info-links--ol-info">#&lt;/a>&lt;/h3>
&lt;p>The default description for &lt;code>info:&lt;/code> type links was set at the time of
storing those links, with the help of the &lt;a href="https://git.savannah.gnu.org/cgit/emacs/org-mode.git/tree/lisp/ol-info.el?id=f6813dbea9ef0c6be19bf68b4d9227ceb64c9449#n49">&lt;code>org-info-store-link&lt;/code>&lt;/a>
function in &lt;code>ol-info.el&lt;/code>. That same description is then suggested at
the time of inserting that link.&lt;/p>
&lt;p>This library defines these &amp;ldquo;actions&amp;rdquo; for &lt;code>[[info:..]]&lt;/code> type of links:&lt;/p>
&lt;dl>
&lt;dt>:store&lt;/dt>
&lt;dd>Defines when (in which buffer, major mode, etc.) the
&amp;ldquo;store&amp;rdquo; operation should store to an &lt;code>info:&lt;/code> type link, and what
metadata should be stored. Some of the stored metadata are: the Info
file name, node name, link string and description string.&lt;/dd>
&lt;dt>:follow&lt;/dt>
&lt;dd>Defines what action to perform when &lt;code>org-open-at-point&lt;/code>
(&lt;kbd>C-c&lt;/kbd> &lt;kbd>C-o&lt;/kbd>) is called with point on the link. Hitting this
binding with point on an &lt;code>info:&lt;/code> link will open or switch to that
∗Info∗ node.&lt;/dd>
&lt;dt>:export&lt;/dt>
&lt;dd>Defines how the link should be exported for various
backends. &lt;em>&lt;code>ol-info&lt;/code> defines how the &lt;code>info:&lt;/code> links should be
exported, but only for &lt;code>html&lt;/code> and &lt;code>texinfo&lt;/code> backends.&lt;/em>&lt;/dd>
&lt;/dl>
&lt;h2 id="exporting-info-dot-dot-links-using-ox-hugo">&lt;span class="section-num">3&lt;/span> Exporting &lt;code>[[info:..]]&lt;/code> links using &lt;code>ox-hugo&lt;/code>&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#exporting-info-dot-dot-links-using-ox-hugo">#&lt;/a>&lt;/h2>
&lt;p>&lt;code>ol-info.el&lt;/code> defines the &lt;code>:export&lt;/code> &amp;ldquo;action&amp;rdquo; such that &lt;code>info:&lt;/code> links
get converted to hyperlinks pointing to online Org manual pages, when
exporting using &lt;code>ox-html&lt;/code>.&lt;/p>
&lt;p>But it didn&amp;rsquo;t do the same when exporting using &lt;code>ox-hugo&lt;/code>. That feature
got added recently in &lt;a href="https://github.com/kaushalmodi/ox-hugo/blob/d3d4c57444f03898e78d2ae11e97fdb94a4655c5/ox-hugo.el#L888-L899">this &lt;code>ox-hugo&lt;/code> commit&lt;/a>. Now &lt;code>ox-hugo&lt;/code> exports
&lt;code class="code-inline language-org">[[&lt;span class="na">info:org#Top&lt;/span>][&lt;span class="nt">org#Top&lt;/span>]]&lt;/code> to &lt;a href="https://orgmode.org/manual/index.html" title="Emacs Lisp: (info &amp;quot;(org) Top&amp;quot;)">org#Top&lt;/a>.&lt;/p>
&lt;p>I didn&amp;rsquo;t like the &lt;code>#&lt;/code> that &lt;code>org-info-store-link&lt;/code> added to the default
description (notice that previous link). So I added a tiny little
feature to the &lt;code>info:&lt;/code> export behavior 😁 &amp;mdash; If you leave the
&lt;code>info:&lt;/code> link descriptions empty when inserting the links, &lt;code>ox-hugo&lt;/code>
injects its own &amp;ldquo;auto description&amp;rdquo; which are better (in my
opinion).&lt;/p>
&lt;p>Now when that same Info link is inserted description-less as
&lt;code class="code-inline language-org">[[&lt;span class="na">info:org#Top&lt;/span>]]&lt;/code>, it renders to: &lt;a href="https://orgmode.org/manual/index.html" title="Emacs Lisp: (info &amp;quot;(org) Top&amp;quot;)">Org Info&lt;/a>.&lt;/p>
&lt;h2 id="summary">Summary&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#summary">#&lt;/a>&lt;/h2>
&lt;ol>
&lt;li>Store link (from anywhere in Emacs) : &lt;kbd>C-c&lt;/kbd> &lt;kbd>l&lt;/kbd>&lt;/li>
&lt;li>Insert link (in an Org file) : &lt;kbd>C-c&lt;/kbd> &lt;kbd>C-l&lt;/kbd>&lt;/li>
&lt;li>Export the Org file as usual.&lt;/li>
&lt;/ol></description><author>Kaushal.Modi@fakeEmailToMakeValidatorHappy.com (Kaushal Modi)</author><category domain="https://scripter.co/categories/web">web</category><category domain="https://scripter.co/categories/hugo">hugo</category><category domain="https://scripter.co/categories/emacs">emacs</category><category domain="https://scripter.co/categories/org">org</category><category domain="https://scripter.co/tags/100daystooffload">100DaysToOffload</category><category domain="https://scripter.co/tags/info">info</category><category domain="https://scripter.co/tags/ox-hugo">ox-hugo</category><guid>https://scripter.co/linking-and-exporting-org-info-links/</guid><pubDate>Tue, 12 Apr 2022 13:51:00 -0400</pubDate></item></channel></rss>