<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Small Sharp Tools</title>
    <link>https://pulpme.sh/~sample2</link>
    <description>One command at a time, with the output pasted in</description>
    <language>en</language>
    <atom:link href="https://pulpme.sh/~sample2/rss.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>The shell prompt is a lie</title>
      <link>https://pulpme.sh/~sample2/the-shell-prompt-is-a-lie.html</link>
      <guid isPermaLink="true">https://pulpme.sh/~sample2/the-shell-prompt-is-a-lie.html</guid>
      <pubDate>Sat, 21 Mar 2026 00:00:00 +0000</pubDate>
      <category>shell</category>
      <category>writing</category>
      <description><![CDATA[
<p>Every shell session in every blog post has been edited. Mine included.</p>

<h2 id="what-gets-cut">What gets cut</h2>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>./build/bin/pulpmesh build ~/Sites/notes <span class="nt">--out=/tmp/site</span>
wrote 12 pages
</code></pre></div></div>

<p>What actually happened was a typo, a missing directory, a rebuild, and then<br />
that. Nobody wants the first three, so out they go. Fine. But two habits keep<br />
the edit honest.</p>

<h2 id="habit-one-paste-real-output">Habit one: paste real output</h2>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>./build/bin/pulpmesh build ~/Sites/notes <span class="nt">--out=/tmp/site</span>
pulpmesh: no base_url <span class="k">in </span>_readme.md<span class="p">;</span> skipping rss.xml
wrote 12 pages
</code></pre></div></div>

<p>The warning is real, it is what a reader will see, and cutting it means the<br />
first thing they experience is a surprise.</p>

<h2 id="habit-two-show-the-failure-too">Habit two: show the failure too</h2>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>./build/bin/pulpmesh build ~/Sites/notes
pulpmesh: two files publish to frontier-model.html
  0010-frontier-model.md
  2026-06-20-frontier-model.md
<span class="nv">$ </span><span class="nb">echo</span> <span class="nv">$</span>?
1
</code></pre></div></div>

<p>An error message with an exit code is more useful than three paragraphs about<br />
what could go wrong.</p>

<h2 id="habit-three-mark-the-elisions">Habit three: mark the elisions</h2>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">ls </span>_site | <span class="nb">head</span> <span class="nt">-4</span>
404.html
index.html
frontier-model.html
rss.xml
...
</code></pre></div></div>

<p><code>head</code> and a trailing <code>...</code> are honest. Silently deleting the middle of a<br />
listing is not.</p>

<h2 id="the-one-i-break">The one I break</h2>

<p>I still align output columns by hand when the paste comes out ragged. I have<br />
made my peace with it.</p>
]]></description>
    </item>
    <item>
      <title>Backticks all the way down</title>
      <link>https://pulpme.sh/~sample2/backticks-all-the-way-down.html</link>
      <guid isPermaLink="true">https://pulpme.sh/~sample2/backticks-all-the-way-down.html</guid>
      <pubDate>Mon, 02 Mar 2026 00:00:00 +0000</pubDate>
      <category>markdown</category>
      <category>inline code</category>
      <description><![CDATA[
<p>Writing documentation about markdown means writing code spans that contain<br />
backticks, which means counting.</p>

<h2 id="the-rule">The rule</h2>

<p>A run of n backticks opens a code span, and it closes on the next run of<br />
exactly n. So a single backtick inside a span needs a double-backtick fence:<br />
<code> ` </code>. Two backticks inside need three: <code> `` </code>.</p>

<h2 id="nothing-is-markup-inside-a-span">Nothing is markup inside a span</h2>

<p>Inside a span, <code>*this*</code> is asterisks, <code>_that_</code> is underscores, <code>[a](b)</code> is a<br />
link that never happens, and <code>&lt;b&gt;</code> is an angle bracket, a letter and another<br />
angle bracket. That is the whole point of a span.</p>

<h2 id="padding">Padding</h2>

<p>A span whose content begins or ends with a backtick needs a space of padding<br />
so the fences do not run together. The space is part of the syntax, not the<br />
content: <code> `code` </code> renders without the outer spaces.</p>

<h2 id="where-it-goes-wrong">Where it goes wrong</h2>

<p>The failure mode is an unclosed run. <code> `three ``` </code> opens a run of one and<br />
finds a run of three, which does not match, so the backtick stays literal text<br />
and the rest of the paragraph reads normally. That is the behaviour you want:<br />
a typo degrades to text, never to a swallowed paragraph.</p>

<h2 id="in-fences">In fences</h2>

<p>Inside a fenced block none of this applies. A fence ends on a line whose first<br />
non-space characters are the closing run, so a lone backtick in the middle of<br />
a line is just a character:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">echo</span> <span class="s2">"a ` b"</span>
a ` b
</code></pre></div></div>
]]></description>
    </item>
    <item>
      <title>A config in a language nobody parses</title>
      <link>https://pulpme.sh/~sample2/a-config-in-a-language-nobody-parses.html</link>
      <guid isPermaLink="true">https://pulpme.sh/~sample2/a-config-in-a-language-nobody-parses.html</guid>
      <pubDate>Wed, 11 Feb 2026 00:00:00 +0000</pubDate>
      <category>config</category>
      <category>toml</category>
      <category>highlighting</category>
      <description><![CDATA[
<p>Every generator eventually meets a code fence whose language tag it does not<br />
recognise. The right behaviour is to escape the contents, label the block, and<br />
get out of the way.</p>

<h2 id="toml">TOML</h2>

<pre><code class="language-toml">[package]
name = "pulpmesh"
version = "0.4.0"

[build]
target = "wasm32-wasi"
flags = ["-Os", "--strip"]
</code></pre>

<h2 id="an-ini-file">An .ini file</h2>

<pre><code class="language-ini">[core]
	editor = vim
	pager = less -FRX

[alias]
	lg = log --graph --oneline
</code></pre>

<h2 id="something-invented-on-the-spot">Something invented on the spot</h2>

<pre><code class="language-pulpmesh-manifest">site  slab-and-serif
posts 12
draft 3
feed  rss.xml
</code></pre>

<h2 id="plain-with-no-tag-at-all">Plain, with no tag at all</h2>

<pre><code>Every character in here is literal.
Even *this*, and `this`, and &lt;this&gt;.
</code></pre>

<h2 id="why-this-matters">Why this matters</h2>

<p>An unknown language must not become a parse error, a swallowed block, or a<br />
paragraph. It becomes a <code>&lt;pre&gt;</code> with a class naming the language, so a<br />
stylesheet or a future highlighter can pick it up later without the content<br />
having to change.</p>
]]></description>
    </item>
    <item>
      <title>Reading Ruby blocks</title>
      <link>https://pulpme.sh/~sample2/reading-ruby-blocks.html</link>
      <guid isPermaLink="true">https://pulpme.sh/~sample2/reading-ruby-blocks.html</guid>
      <pubDate>Sat, 24 Jan 2026 00:00:00 +0000</pubDate>
      <category>ruby</category>
      <category>blocks</category>
      <description><![CDATA[
<p>A block is not an object until you ask for it to be one. That single fact<br />
explains most of the syntax.</p>

<h2 id="yield">Yield</h2>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">each_pair</span>
  <span class="k">yield</span> <span class="ss">:name</span><span class="p">,</span> <span class="s2">"pulpmesh"</span>
  <span class="k">yield</span> <span class="ss">:kind</span><span class="p">,</span> <span class="s2">"generator"</span>
<span class="k">end</span>

each_pair <span class="p">{</span> <span class="o">|</span>key<span class="p">,</span> value<span class="o">|</span> <span class="nb">puts</span> <span class="s2">"</span><span class="si">#{</span>key<span class="si">}</span><span class="s2">=</span><span class="si">#{</span>value<span class="si">}</span><span class="s2">"</span> <span class="p">}</span>
</code></pre></div></div>

<p>No parameter in the signature, no allocation, and <code>block_given?</code> tells you<br />
whether anyone passed one.</p>

<h2 id="the-captured-block">The captured block</h2>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">with_retries</span><span class="p">(</span>attempts<span class="p">,</span> <span class="o">&amp;</span>block<span class="p">)</span>
  tries <span class="o">=</span> <span class="mi">0</span>
  <span class="k">begin</span>
    tries <span class="o">+=</span> <span class="mi">1</span>
    block<span class="p">.</span>call<span class="p">(</span>tries<span class="p">)</span>
  <span class="k">rescue</span> <span class="no">StandardError</span>
    <span class="k">retry</span> <span class="k">if</span> tries <span class="o">&lt;</span> attempts
    <span class="k">raise</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<p>The ampersand converts the block into a <code>Proc</code> so it can be stored, passed on,<br />
or called later. That conversion is the cost.</p>

<h2 id="passing-it-through">Passing it through</h2>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">each_post</span><span class="p">(</span><span class="o">&amp;</span>block<span class="p">)</span>
  posts<span class="p">.</span>each<span class="p">(</span><span class="o">&amp;</span>block<span class="p">)</span>
<span class="k">end</span>
</code></pre></div></div>

<p>Capturing only to hand it straight on is the one case where a plain <code>yield</code><br />
inside <code>posts.each { |post| yield post }</code> is both faster and clearer.</p>

<h2 id="return-break-next">Return, break, next</h2>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">].</span>each <span class="k">do</span> <span class="o">|</span>number<span class="o">|</span>
  <span class="k">next</span> <span class="k">if</span> number<span class="p">.</span>even?
  <span class="k">break</span> number <span class="k">if</span> number <span class="o">&gt;</span> <span class="mi">2</span>
<span class="k">end</span>
</code></pre></div></div>

<ul>
  <li><code>next</code> ends this iteration</li>
  <li><code>break</code> ends the method that yielded</li>
  <li><code>return</code> inside a block returns from the enclosing method, which is why a<br />
<code>return</code> inside a <code>Proc</code> created at the top level raises</li>
</ul>

<h2 id="arity-is-looser-than-you-think">Arity is looser than you think</h2>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pair <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">]</span>
<span class="p">[</span>pair<span class="p">].</span>each <span class="p">{</span> <span class="o">|</span>a<span class="p">,</span> b<span class="o">|</span> <span class="nb">puts</span> <span class="s2">"</span><span class="si">#{</span>a<span class="si">}</span><span class="s2"> </span><span class="si">#{</span>b<span class="si">}</span><span class="s2">"</span> <span class="p">}</span>   <span class="c1"># 1 2</span>
<span class="p">[</span>pair<span class="p">].</span>each <span class="p">{</span> <span class="o">|</span>a<span class="o">|</span> <span class="nb">puts</span> a<span class="p">.</span>inspect <span class="p">}</span>        <span class="c1"># [1, 2]</span>
</code></pre></div></div>

<p>Blocks destructure. Lambdas do not. If an arity mismatch should be an error,<br />
you wanted a lambda.</p>
]]></description>
    </item>
    <item>
      <title>find without tears</title>
      <link>https://pulpme.sh/~sample2/find-without-tears.html</link>
      <guid isPermaLink="true">https://pulpme.sh/~sample2/find-without-tears.html</guid>
      <pubDate>Mon, 05 Jan 2026 00:00:00 +0000</pubDate>
      <category>shell</category>
      <category>find</category>
      <description><![CDATA[
<p><code>find</code> has a reputation for being unmemorable. It is not: there are four<br />
shapes, and everything else is a variation on one of them.</p>

<h2 id="files-by-name-under-one-directory">Files by name, under one directory</h2>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>find lib <span class="nt">-name</span> <span class="s1">'*.rb'</span>
lib/pulpmesh.rb
lib/pulpmesh/post.rb
lib/pulpmesh/site.rb
</code></pre></div></div>

<p>Quote the pattern. Unquoted, the shell expands <code>*.rb</code> against the current<br />
directory first and <code>find</code> receives whatever that happened to match.</p>

<h2 id="files-newer-than-a-reference">Files newer than a reference</h2>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">touch</span> <span class="nt">-d</span> <span class="s1">'2026-01-01'</span> /tmp/cutoff
<span class="nv">$ </span>find src <span class="nt">-type</span> f <span class="nt">-newer</span> /tmp/cutoff
src/parser.c
src/parser.h
</code></pre></div></div>

<p>There is no <code>-newerthan '2026-01-01'</code>. A reference file is the interface.</p>

<h2 id="prune-a-subtree">Prune a subtree</h2>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>find . <span class="nt">-name</span> node_modules <span class="nt">-prune</span> <span class="nt">-o</span> <span class="nt">-name</span> <span class="s1">'*.json'</span> <span class="nt">-print</span>
./package.json
./config/tsconfig.json
</code></pre></div></div>

<p>The <code>-o</code> is doing real work. Without <code>-print</code> on the right side, the default<br />
print applies to both branches and the prune is decorative.</p>

<h2 id="hand-the-results-to-something-else">Hand the results to something else</h2>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>find . <span class="nt">-name</span> <span class="s1">'*.log'</span> <span class="nt">-print0</span> | xargs <span class="nt">-0</span> <span class="nb">wc</span> <span class="nt">-l</span>
   1204 ./build.log
    318 ./serve.log
   1522 total
</code></pre></div></div>

<p><code>-print0</code> and <code>-xargs -0</code> travel together. Any pipeline that omits them is one<br />
filename with a space away from doing something surprising.</p>

<h2 id="what-i-still-look-up">What I still look up</h2>

<p>Every single time: <code>-mindepth</code>, <code>-maxdepth</code>, and which order they have to<br />
appear in relative to the tests. The answer is that they are options, not<br />
tests, so put them first.</p>
]]></description>
    </item>
  </channel>
</rss>
