frog orbits2023-12-30T04:46:46Zhttps://www.frogorbits.com/frogorbits.com authorship juntaActually understanding Typst2023-12-30T04:46:46Zurn:uuid:17cc1a84-fd98-40ff-9414-ffa5da2a02c1<p>I’ve been working with <a href="https://typst.app/">Typst</a> a little bit recently and one of the problems I’ve had is when to use what construct for modifying things, and how to combine them however I want.</p>
<p>Here’s how I built up the knowledge to understand what was going on. This page is mostly a restatement of the Typst docs, but the order and emphasis is a little different.</p>
<h1>Functions</h1>
<p>Typst has functions.</p>
<p>Interestingly enough, <code>page</code>, <code>text</code>, <code>heading</code>, <code>par</code>, <code>raw</code>, and other identifiers that you use to mark different types of text are functions. These are known as <dfn>element functions</dfn>.</p>
<h1><code>set</code> rules</h1>
<p><code>set</code> rules…</p>
<ul>
<li>are written as a function call to an element function</li>
<li>only configure basic properties of elements</li>
<li>only let you fill in optional parameters (the mandatory parameters tend to be the actual text to style)</li>
<li>take effect until the end of the document or the block</li>
</ul>
<p>Examples:</p>
<pre tabindex="0"><code class="language-typst" data-lang="typst">#set text(
font: "Concourse"
)
Only this list is affected: #[
#set list(marker: [--])
- Dash
]
</code></pre><h1><code>show</code> rules</h1>
<p>The most basic of these is a show-set rule:</p>
<pre tabindex="0"><code class="language-typst" data-lang="typst">#show «selector»: set «element function»(·)
</code></pre><p>More concretely:</p>
<pre tabindex="0"><code class="language-typst" data-lang="typst">#let usualLeading = 0.65em
#show par: set block(spacing: 1.0em - (1.0em - usualLeading));
</code></pre><p>For full power, write a <a href="https://typst.app/docs/reference/styling/#show-rules">show rule</a>:</p>
<pre tabindex="0"><code class="language-typst" data-lang="typst">#set heading(numbering: "(I)")
#show heading: it => [
#set align(center)
#set text(font: "Inria Serif")
\~ #emph(it.body)
#counter(heading).display() \~
]
</code></pre><p>In the above anonymous function, <code>it</code> is a variable containing the contents of whatever was passed into that function. For example, if you didn’t want to italicize anything in your heading, you would write:</p>
<pre tabindex="0"><code class="language-typst" data-lang="typst">#show heading: it => [
#set align(center)
#set text(font: "Inria Serif")
#it
]
</code></pre><h1>Defining your own functions</h1>
<p>This is a thing you can do.</p>
<pre tabindex="0"><code class="language-typst" data-lang="typst">#let task(body, critical: false) = {
set text(red) if critical
[- #body]
}
#task(critical: true)[Food today?]
#task(critical: false)[Work deadline]
</code></pre><p>I’m not sure why this uses braces when normally I would expect brackets (for a block).</p>
Styling code in Typst2023-04-09T08:29:33Z2023-04-09T07:37:54Zurn:uuid:1a0dbac8-292a-4c5b-9fac-bda6d19515a1<p><a href="https://typst.app/">Typst</a> showed up in Homebrew the other day, and I’ve been playing around with it a little bit. I like it.</p>
<p>It took me a bit to figure out how to style code blocks, though. <a href="https://typst.app/docs/reference/text/raw/">Raw</a> text in Typst come in two types:</p>
<ul>
<li>not-block, which is what you get if you use single backticks (`) as delimiters</li>
<li>block, which is what you get if you use triple backticks (```) as delimiters</li>
</ul>
<p>Changing style for all text is easy:</p>
<pre tabindex="0"><code class="language-typst" data-lang="typst">#set text(
font: "Seravek", size: 18pt
)
</code></pre><p>Changing style for all headings is a bit more complicated:</p>
<pre tabindex="0"><code class="language-typst" data-lang="typst">#show heading: (it) => block[
#set text(font: "Recent Grotesk")
#block(it.body)
]
</code></pre><p>For raw text, though, you’ll want to handle the block and not-block styles separately:</p>
<pre tabindex="0"><code class="language-typst" data-lang="typst">#show raw.where(block: false): (it) => text[
#set text(font: "Cascadia Code")
#text(it.text)
]
#show raw.where(block: true): (it) => block[
#set text(font: "Cascadia Code")
#block(it.text)
]
</code></pre><p>If you neglect to put in the <code>.where(…)</code> clause and duplicate everything for the other style, like I did at first, you’ll end up forcing all your raw text to be either block or not-block, depending on whether you put <code>text</code> or <code>block</code> right after the arrow.</p>
<p>Finally, you could do something even simpler, and dispose of the redundant <code>block</code>/<code>text</code> bits and consolidate into one <a href="https://typst.app/docs/reference/styling/#show-rules">show rule</a> with a function:</p>
<pre tabindex="0"><code class="language-typst" data-lang="typst">#show raw: (it) => [
#set text(font: "Cascadia Code")
#it
]
</code></pre>The globe as a keyboard-shortcut character2021-10-05T00:00:00Z2021-09-22T00:00:00Zurn:uuid:9adba4ad-1f1b-4509-8d3d-fbaea459c8ea<p>Now that iPadOS 15 is out, people are starting to use 🌐︎ as a keyboard-shortcut icon in addition to the usual
<span title='command'>⌘</span>,
<span title='option'>⌥</span>,
<span title='control'>⌃</span>, and
<span title='shift'>⇧</span><sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>.
However, 🌐︎ also works as an emoji, and if you just put a raw <code>U+1F310</code> in your document, you might get an emoji-looking 🌐️ in your document instead of a colorless text one. While Safari in macOS defaults to text presentation (🌐︎), Safari in iOS and iPadOS defaults to emoji presentation (🌐️). On other platforms, I’m not sure what they all do. I don’t see these things often when I’m on Windows or a Linux distribution.</p>
<p>If you want to do what you can to ensure that visitors to your site don’t see the emoji version, you’ll want to have not just the raw <code>U+1F310</code>, but also a <a href="https://en.wikipedia.org/wiki/Variation_Selectors_%28Unicode_block%29">VARIATION SELECTOR</a>-15 (<code>U+FE0E</code>) after it.</p>
<p>Since you’re already viewing this page, the easiest way to get this particular variation selector right after a globe is to copy and paste one that’s already after a globe character. Here’s a nice large globe paired with a variation selector 15 right after it:</p>
<div style='font-size: 3rem; text-align: center;'>🌐︎</div>
<p>If you’d like to be able to type variation selectors yourself in macOS, read on.</p>
<h1>Typing a variation selector 15</h1>
<p>First, pull up the macOS character picker by pressing
<span title='control command space'>⌃⌘␣</span>.
You’ll see something like this:</p>
<figure>
<picture>
<source
srcset='default-picker-dark.webp'
media='(prefers-color-scheme: dark)'
type='image/webp'>
<source
srcset='default-picker-light.webp'
media='(prefers-color-scheme: light)'
type='image/webp'>
<source
srcset='default-picker-light.png'
media='(prefers-color-scheme: light)'
type='image/png'>
<img src='default-picker-dark.png' alt='Default character picker for macOS 11.6 Big Sur'>
</picture>
<figcaption></figcaption>
</figure>
<p>At the top of the picker, on the right, next to the search box, there’s a button. Click on it. You’ll see something like this:</p>
<figure>
<picture>
<source
srcset='extended-picker-dark.webp'
media='(prefers-color-scheme: dark)'
type='image/webp'>
<source
srcset='extended-picker-light.webp'
media='(prefers-color-scheme: light)'
type='image/webp'>
<source
srcset='extended-picker-light.png'
media='(prefers-color-scheme: light)'
type='image/png'>
<img src='extended-picker-dark.png' alt='Extended character picker for macOS 11.6 Big Sur'>
</picture>
<figcaption></figcaption>
</figure>
<p>Then, type “variation” into the search box in the top right. You’ll see something like this:</p>
<figure>
<picture>
<source
srcset='extended-picker-search-dark.webp'
media='(prefers-color-scheme: dark)'
type='image/webp'>
<source
srcset='extended-picker-search-light.webp'
media='(prefers-color-scheme: light)'
type='image/webp'>
<source
srcset='extended-picker-search-light.png'
media='(prefers-color-scheme: light)'
type='image/png'>
<img
src='extended-picker-search-dark.png'
alt='What you see when you type “variation” in the character-picker search box'
title='“‘Jehovah’ begins with a J…”'>
</picture>
<figcaption></figcaption>
</figure>
<p>Now, what you need to do is single-click on the completely blank square for VARIATION SELECTOR-15. Yes, you’ll have to guess and check; hovering your mouse pointer won’t tell you anything. My first guess ends up being in the mid-20s, usually. Make sure to not accidentally double-click prematurely, otherwise you’ll get some <em>other</em> variation selector instead and the “text presentation, please” message won’t be communicated.</p>
<p>Yes, picking characters you can’t see is character picking on hard mode.</p>
<p>Once you’ve single-clicked on the right space, your picker will look like this:</p>
<figure>
<picture>
<source
srcset='variation-15-dark.webp'
media='(prefers-color-scheme: dark)'
type='image/webp'>
<source
srcset='variation-15-light.webp'
media='(prefers-color-scheme: light)'
type='image/webp'>
<source
srcset='variation-15-light.png'
media='(prefers-color-scheme: light)'
type='image/png'>
<img src='variation-15-dark.png' alt='What you see when you type “variation” in the character-picker search box and then successfully click on the space for VARIATION SELECTOR-15'>
</picture>
<figcaption></figcaption>
</figure>
<p>At this point, just double-click on the square you’ve highlighted to insert a VARIATION SELECTOR-15.</p>
<h1>Using VARIATON SELECTOR-15s with glyphs other than 🌐︎</h1>
<p>A “text, please” variation selector is handy for more than just globes. “↩︎︎” is a common arrow to use for “return to the part of the text where this footnote is from”, but this character gets emoji presentation by default on iOS and iPadOS. You might not want that.</p>
<h1>Forcing <em>emoji</em> presentation</h1>
<p>If for some reason you want to ask for emoji presentation specifically, put a <code>VARIATON SELECTOR-16</code> after the character. I did that above to get 🌐️ to show up as an emoji, even on macOS.</p>
<h1>A note about character order</h1>
<p>I haven’t seen a lot of globe shortcuts on iPadOS, but the canonical printed order for globe shortcuts seems to be the same as for the command symbol:
<span title='control option shift globe'>⌃⌥⇧🌐︎</span>,
just like
<span title='control option shift command'>⌃⌥⇧⌘</span>.
That said, <a href="https://atp.fm/369"><em>spoken</em> order</a> moves “shift” first, so you’d read these shortcuts aloud as “shift control option globe”.</p>
<p>I haven’t seen any 🌐︎-and-⌘ shortcuts yet.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Not sure what these funny-looking icons mean? Hover your mouse pointer over them and you’ll get them written out, in words, in a tooltip. <a href="#fnref:1" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>
</ol>
</div>
Abstract bases in BEM2020-08-07T00:00:00Zurn:uuid:7b5fdccc-498e-4a1d-9343-d2f7051cc510<p>(Consider skipping to the <a href="./example.html">live example</a>.)</p>
<p>You’re probably familiar with abstract base classes in object-oriented languages. In a nutshell, abstract base classes let you set up some expectations of what a derived class must do, but nobody can actually instantiate instances of the base class. One needs to create a derived class, <em>then</em> create objects that are instances of that derived class.</p>
<p>A similar idea came to me while I was working in <a href="http://getbem.com/">BEM</a>.</p>
<p>I was working on something that I called a “spotlight” block that you may remember <a href="../peribreakpoints/">from earlier</a>. Here’s what they look like in the HTML source:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">'spotlight'</span><span class="p">></span>
</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">'spotlight__image'</span><span class="p">></</span><span class="nt">div</span><span class="p">></span>
</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">'spotlight__verbiage'</span><span class="p">></span>Mmm, meat.<span class="p"></</span><span class="nt">div</span><span class="p">></span>
</span></span><span class="line"><span class="cl"><span class="p"></</span><span class="nt">div</span><span class="p">></span>
</span></span></code></pre></div><p><code>.spotlight__image</code>’s background is supposed to be a flavor image. <code>.spotlight__verbiage</code>, as shown, is supposed to have text in it.</p>
<p>I wanted to be able to have both image-on-left and image-on-right <code>spotlight</code>s, but I <em>also</em> wanted to be able to keep the source order the same for both.</p>
<p>On very narrow viewports, my plan was to shrink the width of <code>.spotlight__image</code> to just a tiny sliver, so I wasn’t concerned with rotating the block 90° to put the image on top.</p>
<p>The obvious way to do this sort of thing would be to have two main styles:</p>
<ul>
<li><code>.spotlight</code> (implicitly puts the image on the left)</li>
<li><code>.spotlight--image-last</code> (flips the text/image order)</li>
</ul>
<p>With this arrangement, I ended up setting most style adjustments (padding, etc.) on <code>spotlight</code> and undoing them on <code>.spotlight--image-last</code>. The undoing parts of <code>.spotlight--image-last</code> turned out to be my, um, undoing; order flips using flexbox tend to be weirdly asymmetrical.</p>
<p>Eventually, I settled on requiring users of <code>.spotlight</code> to explicitly pick an order. A user could use either:</p>
<ul>
<li><code><div class='spotlight spotlight--image-first'></code></li>
<li><code><div class='spotlight spotlight--image-last'></code></li>
</ul>
<p>but I wouldn’t make any guarantees on what it should look like if there were no with-modifier (the part after the <code>--</code>) class on the element.</p>
<p>A worked example would be worth at least a thousand words at this point, so go see a <a href="./example.html">live example</a> of this in action. Beats being remotely tempted to undo things with <code>:not()</code> and similar.</p>
Peribreakpoints: breakpoints near breakpoints2020-06-29T00:00:00Z2020-07-28T00:00:00Zurn:uuid:2b3a75cf-4ec1-4ee4-a2fb-a45c07552a5f<p>Have you considered having more breakpoints than you have breakpoints?</p>
<p>Let me explain.</p>
<p>When people say “breakpoint”, they’re usually referring to one of two definitions:</p>
<dl>
<dt>breakpoint₁
<dd>A viewport width that has a <code>@media (max-width: …)</code> or <code>@media (min-width: …)</code> somewhere in a site’s CSS.
<dt>breakpoint₂
<dd>A viewport width at which you rejigger your site’s layout so it looks good, if different, at widths wider than this width and at widths narrower than this width.
</dl>
<p>These two definitions aren’t quite the same.</p>
<p>In particular, you might benefit from having a couple of <code>@media (min-width: …)</code> blocks in your site’s CSS that you don’t think of as a proper breakpoint. I call these <dfn>peribreakpoints</dfn>.</p>
<h1>Peribreakpoints: why they’re useful</h1>
<p>You’re used to using breakpoints to rejigger your site’s layout when the current design doesn’t work well below — or above — a range of viewport widths. You’ve seen — or perhaps made — layouts like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">body</span><span class="p">></span>
</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"everything"</span><span class="p">></span>
</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"spotlight"</span><span class="p">></span>
</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"spotlight__image"</span><span class="p">></</span><span class="nt">div</span><span class="p">></span>
</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"spotlight__verbiage"</span><span class="p">></span>…<span class="p"></</span><span class="nt">div</span><span class="p">></span>
</span></span><span class="line"><span class="cl"> <span class="p"></</span><span class="nt">div</span><span class="p">></span>
</span></span><span class="line"><span class="cl"> <span class="p"></</span><span class="nt">div</span><span class="p">></span>
</span></span><span class="line"><span class="cl"><span class="p"></</span><span class="nt">body</span><span class="p">></span>
</span></span></code></pre></div><p>that are styled with this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="o">*</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">margin</span><span class="p">:</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="k">padding</span><span class="p">:</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">.</span><span class="nc">everything</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="c">/* any wider and line lengths
</span></span></span><span class="line"><span class="cl"><span class="c"> * get too long to read
</span></span></span><span class="line"><span class="cl"><span class="c"> */</span>
</span></span><span class="line"><span class="cl"> <span class="k">max-width</span><span class="p">:</span> <span class="mi">40</span><span class="kt">rem</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="k">margin</span><span class="p">:</span> <span class="mi">0</span> <span class="kc">auto</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">.</span><span class="nc">spotlight</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="c">/* has text on one side and an
</span></span></span><span class="line"><span class="cl"><span class="c"> * image on the other */</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="c">/* … */</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>This looks fine when the viewport is noticeably wider than <code>40rem</code>, but at viewport widths of <code>40rem</code> and below, normal text will be flush against the viewport edge. In general, we don’t want this. The obvious fix is to add a breakpoint at <code>40em</code> and, below this width, have some extra space:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="p">@</span><span class="k">media</span> <span class="o">(</span><span class="nt">max-width</span><span class="o">:</span> <span class="nt">40em</span><span class="o">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="nc">everything</span> <span class="p">.</span><span class="nc">spotlight</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">margin</span><span class="p">:</span> <span class="mi">0</span> <span class="mf">0.5</span><span class="kt">rem</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>But what if the viewport width is just a little bit wider than <code>40em</code>? It still looks bad:</p>
<figure>
<a href='before.html'>
<picture>
<source srcset='peribreakpoints-before-dark.webp'
media='(prefers-color-scheme: dark)'
type='image/webp'>
<source srcset='peribreakpoints-before-light.webp'
media='(prefers-color-scheme: light)'
type='image/webp'>
<source srcset='peribreakpoints-before-light.png'
media='(prefers-color-scheme: light)'
type='image/png'>
<img src='peribreakpoints-before-dark.png' alt='A screenshot of a browser displaying the need for a peribreakpoint'>
</picture>
</a>
<figcaption>
<p>
This looks like the author forgot to put margins around the text that’s flush against the edge of the viewport.
</p>
<p>
You can also view <a href='before.html'>this “before” example live</a> and play around with your window’s width yourself.
</p>
</figcaption>
</figure>
<p>The solution, then, is to make up a peribreakpoint — a breakpoint <em>near</em> a more important breakpoint.</p>
<h1>Applying peribreakpoints</h1>
<p>This is as simple as it sounds. Make up a new breakpoint that’s close to the more-important <code>40em</code> breakpoint. Since we want the text to be pinched in no matter whether the viewport width is <code>40.1em</code> or <code>39.9em</code>, let’s set the <code>max-width</code> peribreakpoint at <code>41em</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="p">@</span><span class="k">media</span> <span class="o">(</span><span class="nt">max-width</span><span class="o">:</span> <span class="nt">41em</span><span class="o">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="p">.</span><span class="nc">everything</span> <span class="p">.</span><span class="nc">spotlight</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">margin</span><span class="p">:</span> <span class="mi">0</span> <span class="mf">0.5</span><span class="kt">rem</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>This is what it looks like <a href="after.html">afterwards</a>.</p>
<figure>
<a href='after.html'>
<picture>
<source srcset='peribreakpoints-after-dark.webp'
media='(prefers-color-scheme: dark)'
type='image/webp'>
<source srcset='peribreakpoints-after-light.webp'
media='(prefers-color-scheme: light)'
type='image/webp'>
<source srcset='peribreakpoints-after-light.png'
media='(prefers-color-scheme: light)'
type='image/png'>
<img src='peribreakpoints-after-dark.png' alt='A screenshot of a browser using a peribreakpoint in its design'>
</picture>
</a>
<figcaption>
This looks better. As before, you can view <a href='after.html'>this “after” example live</a> and play around with it.
</figcaption>
</figure>
<h2>Relative peribreakpoints in CSS preprocessors</h2>
<p>All that said, what should you call these peribreakpoints? Quite honestly, I don’t have great advice, at least not yet. Here’s what I did in <a href="http://lesscss.org/">less</a> a few weeks back:</p>
<pre tabindex="0"><code class="language-less" data-lang="less">@maximum-defined-width: 100ch;
@narrower-than-maximum: ~'(max-width: @{maximum-defined-width})';
@side-spacing: 10ch;
@maximum-defined-width-plus-spacing: @maximum-defined-width + @side-spacing;
@narrower-than-maximum-plus-spacing: ~'(max-width: @{maximum-defined-width-plus-spacing})';
// …
.spotlight__verbiage--on-left {
@media @narrower-than-maximum-plus-spacing {
padding-left: 1rem;
}
}
</code></pre><p>These are long names (the last definition is 92 columns if I don’t break it manually), but at least the media queries’ names are obvious.</p>
Using git with syncing folders, sort of2019-09-21T00:00:00Zurn:uuid:9c81ff57-a344-4841-be08-b365eb88d2ef<p>One of the limitations of folder-sync software like <a href="https://www.dropbox.com/">Dropbox</a> and <a href="https://www.syncthing.net/">Syncthing</a> is that it’s a bad idea to put <a href="https://git-scm.com/">git</a> repositories in synced folders. In short, if there’s a sync conflict in a file, the conflicting files will be duplicated and the user will have to sort out which is the right file to use. Annoying, but tolerable if it happens only occasionally. However, if one of the conflicting files is somewhere in <code>.git/objects/</code>, then the repository could get unfixably corrupted.</p>
<p>Of course, if all you want from Git is a history of your changes, you don’t need to keep the git repo in your sync folder at all. You can keep your files in a synced folder, sync back and forth between all your computers, and then, periodically copy those files to an un-synced Git repository on one of your computers. Those copied files will look like changes to Git, and you can commit those changes as you see fit.</p>
<h1>In practice</h1>
<p>Let me show you how it works.</p>
<p>I have a web thing (I hate to call it a “website” since it’s not published anywhere) called Cool Dot Com Domain. It’s a <a href="https://gohugo.io/">Hugo</a>-based site with a handful of opinions about things and a development diary for all my projects. When I started it, I wanted to be able to work on it from either my desktop or laptop without having to go through the formal steps of committing and pushing and pulling. As such, I put it in <code>~/Sync/Sites/cooldotcomdomain</code>, where <code>~/Sync</code> is synced by Syncthing.</p>
<p>Eventually I wanted to be able to dig through the site’s history in case I tried out, used, and abandoned a particularly cool CSS or Hugo-augmented Go template construct. I ended up making <code>~/Projects/Attic/Synced Elsewhere/cooldotcomdomain</code> and added this to <code>~/Sync/Sites/cooldotcomdomain/Makefile</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-make" data-lang="make"><span class="line"><span class="cl"><span class="nv">ELSEWHERE</span> <span class="o">=</span> <span class="si">${</span><span class="nv">HOME</span><span class="si">}</span>/Projects/Attic/Synced Elsewhere/cooldotcomdomain
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">.PHONY</span><span class="o">:</span> <span class="n">backup</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">backup</span><span class="o">:</span>
</span></span><span class="line"><span class="cl"> rsync -rdhPc --perms --delete --delete-excluded <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span> --filter<span class="o">=</span><span class="s2">"P .git"</span> --filter<span class="o">=</span><span class="s2">"P .gitignore"</span> --filter<span class="o">=</span><span class="s2">"- .src/"</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span> -- . <span class="s2">"</span><span class="si">${</span><span class="nv">ELSEWHERE</span><span class="si">}</span><span class="s2">"</span>
</span></span></code></pre></div><p>Not familiar with <a href="https://rsync.samba.org/">rsync</a> flags? In a nutshell, this copies everything to the Git repository while ensuring that <code>.git/</code> and <code>.gitignore</code> are left alone. It also ensures that the <a href="http://www.catb.org/esr/src/">src</a> directories aren’t copied at all.</p>
<p>Now, when I want a backup of what’s in the site-slash-diary and I’m on my iMac, I just run <code>make backup</code> and <code>rsync</code> copies the site contents to the Git repo, where I can make the commits as fine- or coarse-grained as I please, without the commit cycle getting in the way of writing and changing things.</p>
<h1>Limitations</h1>
<ul>
<li>
<p>If I’m ever away with my laptop and need to access the history of Cool Dot Com Domain, I’m going to have to retrieve it from my cloud-backup site. This would be unpleasant, but so far it hasn’t been an issue.</p>
</li>
<li>
<p>If I ever want to restore files as they were from the Git history into <code>~/Sync/Sites/cooldotcomdomain</code>, I’m going to have to do some manual copying or define a Makefile target to copy everything in the other direction.</p>
</li>
</ul>
<h1>Wrapup</h1>
<p>Hopefully this’ll be useful to you if you like easy sync for some of your projects yet still want a Git repository keeping track of changes. While I certainly don’t use this technique for all of my Git repos, it’s handy for less-formal setups where you don’t expect to have to <code>git pull</code> anything ever.</p>
Nonintrusive fzf with fish2019-08-26T00:00:00Zurn:uuid:6cf595c5-bd2f-45e2-8c9f-57b88ee56b56<p>I’ve been getting into <a href="https://github.com/junegunn/fzf">fzf</a> recently. In case what it does isn’t immediately obvious to you (it wasn’t to me), here’s what it does:</p>
<ol>
<li>You send a bunch of things to <code>fzf</code>, one per line.</li>
<li><code>fzf</code> lets you pick one (or more!) of the things that was sent to it.</li>
<li><code>fzf</code> prints, to standard output, that thing or those things that you picked.</li>
</ol>
<p>This has a couple obvious use cases:</p>
<ul>
<li>“I want to <code>cd</code> to a directory, but I only want to type the unique end of the path, not the entire path from here to there.”</li>
<li>“I want to <code>ssh</code> into this one server again, but <code>history | grep ssh | grep horse.example</code> is more typing <code>grep</code> than I want to do.”</li>
</ul>
<p>If you install <code>fzf</code> by hand, you’ll get an opportunity to let it install its own things into your shell’s configuration. If you let it, it’ll set up C-t, C-r, and M-c so that they run a “file widget”, “history widget”, and a “<code>cd</code> widget”, respectively. Pretty handy, but:</p>
<ul>
<li>This installation process puts a symlink from your <a href="https://fishshell.com/">fish</a>-config directory (likely <code>~/.config/fish/</code>) to <code>/usr/local/something/fzf/key-bindings.fish</code>. What’s worse, that <code>something</code> could vary depending on your OS. This might not be an issue for most fish users, but I use the same <code>fish</code> configuration on both macOS and FreeBSD computers. If the <code>key-bindings.fish</code> file is in different places on both macOS and FreeBSD, I was gonna have a bad time.</li>
<li>My primary OS is macOS. While the Meta key may be easily used on every other OS, the only hardware Meta key I have is the Option key, and it’s being used to make curly quotes and ellipses, even in Terminal.app. Sure, I <em>can</em> press Escape and then press C, it’s not nearly as pleasant as pressing Alt-C.</li>
</ul>
<p>I then tried to see if I could get 95% of what I wanted with 0% of the invasive code in my <code>~/.config/fish/</code>.</p>
<h1>Searching through history</h1>
<p>Normally, when I want to search through my history, I run <code>hgrep foo</code>, where <code>hgrep</code> is short for <code>history | grep</code>.</p>
<p>I ended up with this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fish" data-lang="fish"><span class="line"><span class="cl"><span class="k">function</span> <span class="nf">hfzf</span>
</span></span><span class="line"><span class="cl"> <span class="k">set</span> <span class="na">-l</span> <span class="nv">to_run</span> <span class="o">(</span><span class="nb">history</span> <span class="o">|</span> <span class="nf">fzf</span><span class="o">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="k">test</span> <span class="na">-n</span> <span class="s2">"</span><span class="nv">$to_run</span><span class="s2">"</span>
</span></span><span class="line"><span class="cl"> <span class="k">echo</span> <span class="s2">"</span><span class="nv">$to_run</span><span class="s2">"</span>
</span></span><span class="line"><span class="cl"> <span class="nb">eval</span> <span class="s2">"</span><span class="nv">$to_run</span><span class="s2">"</span>
</span></span><span class="line"><span class="cl"> <span class="k">end</span>
</span></span><span class="line"><span class="cl"><span class="k">end</span>
</span></span></code></pre></div><p>Note that <code>fish</code> won’t let you just run <code>(history | fzf)</code>. It’ll give you an error of <code>fish: Command substitutions not allowed</code>. I’m not sure, but I think this is to keep <code>fish</code> users from shooting themselves in the foot. However, if you explicitly set that command to a variable and then run <code>eval</code> on it, <code>fish</code> will let you do what you want.</p>
<p>The <code>echo</code> line is there because it feels weird to run a command that hasn’t been printed to the console in some form. <code>bash</code> will print out lines that have had command-substitution magic (!!, etc.) applied to them; I wanted the same thing in <code>fish</code> with <code>fzf</code>.</p>
<p>Running it is easy. I just type <code>hfzf</code>, pick the history item from the list, and then hit Enter to run it.</p>
<h1>Changing directories</h1>
<p><code>fish</code> already has <code>cdh</code> for “change to a recently-visited directory”, so what about <code>cdf</code> for “fuzzy cd”?</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fish" data-lang="fish"><span class="line"><span class="cl"><span class="k">function</span> <span class="nf">cdf</span>
</span></span><span class="line"><span class="cl"> <span class="k">set</span> <span class="na">-l</span> <span class="nv">whither</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nb">command</span> <span class="na">-sq</span> fd
</span></span><span class="line"><span class="cl"> <span class="k">set</span> <span class="nv">whither</span> <span class="o">(</span><span class="nf">fd</span> <span class="na">--type</span> d <span class="o">|</span> <span class="nf">fzf</span><span class="o">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">else</span>
</span></span><span class="line"><span class="cl"> <span class="k">set</span> <span class="nv">whither</span> <span class="o">(</span><span class="nf">find</span> . <span class="na">-type</span> d <span class="o">|</span> <span class="nf">fzf</span><span class="o">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">end</span>
</span></span><span class="line"><span class="cl"> <span class="k">test</span> <span class="na">-n</span> <span class="s2">"</span><span class="nv">$whither</span><span class="s2">"</span><span class="p">;</span> <span class="k">and</span> <span class="k">cd</span> <span class="s2">"</span><span class="nv">$whither</span><span class="s2">"</span>
</span></span><span class="line"><span class="cl"><span class="k">end</span>
</span></span></code></pre></div><p>After declaring a local variable, this tests to see if <a href="https://github.com/sharkdp/fd">fd</a> is installed. <code>fd</code> is a Rust-based reimplementation of <code>find</code>. Most importantly, it ignores hidden files by default, so it won’t waste time and disk reads by trawling through <code>.git/objects/</code> directories looking for directories to change to.</p>
<p>I don’t have <code>fd</code> installed on all my machines, so I have a fallback case that uses <code>find</code>.</p>
<p>The final interesting line tests to make sure <code>$whither</code> actually has something in it before changing directories. If I quit out of fzf without picking anything, I don’t want to run <code>cd</code> with no arguments. That’ll just drag me back to my home directory, which likely isn’t what I want.</p>
<h1>Wrapup</h1>
<p>Two functions in two files gives me most of what I want out of <code>fzf</code> without deeply integrating it into my shell configuration in weird ways. If you dislike it when your utilities get their hooks into your shell, maybe you’ll find all this useful.</p>
fish: just a little bit nicer2021-08-29T00:00:00Z2019-08-03T00:00:00Zurn:uuid:fa77bfc0-c068-44b6-bcf0-a5680079ad33<p>I’ve been trying <a href="https://fishshell.com/"><code>fish</code></a>, however briefly, for a few years now. This time, I finally stuck with it. If you’re interested in seeing what the initial adjustment period is like, have a look at <a href="../fish-initial-adjustment/">fish: the inital adjustment period</a>.</p>
<p>Previously, I’d try <code>fish</code> only to discover that it didn’t support changing the title of Terminal.app or that <code>fish</code> sessions wouldn’t restore properly<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>. By <code>fish</code> 3.0.2, both of these problems were fixed and I was able to give <code>fish</code> a fair try.</p>
<p>After a bit I ended up liking it. <code>fish</code> bills itself as “the friendly interactive shell”. I’d describe <code>fish</code> as “just a little bit nicer”.</p>
<p>You can browse the <a href="https://fishshell.com/"><code>fish</code></a> site to get an idea of some of its feature set and what makes it better than other shells. This page lists some of the reasons why <strong>I</strong> like <code>fish</code> more than <code>bash</code> 3.2.57, the version that ships with macOS 10.14:</p>
<h1>Configuration goes in <code>~/.config/fish/</code>, making it easier to version-control</h1>
<p><code>bash</code> configuration tends to be sprawled at the top level of one’s home directory. In order to properly version-control <code>bash</code> dotfiles, one needs to either:</p>
<ol>
<li>put them in a version-controlled directory elsewhere and symlink to them from <code>~</code></li>
<li>use a version-control system that doesn’t try to version-control everything in <code>~</code>, like <a href="http://www.catb.org/esr/src/">src</a>.</li>
</ol>
<p>I like <code>src</code>, but I can’t use it to sync changes between my desktop and laptop through a service like GitHub. <code>~/.config/fish/</code>, however, is easily synced with a <code>git push</code> on one machine and a <code>git pull</code> on the other.</p>
<h1>No profile/rc split</h1>
<p><code>bash</code> has both <code>~/.bashrc</code> and <code>~/.bash_profile</code>. I never really did understand when each gets loaded up. When I was first bitten by this split, I decided to write both such that they both sourced <code>~/.globalbashrc</code> and that was the end of it. Later on, as I moved to Macs mostly full-time and stopped bouncing between terminals both inside and outside the X Window system, I got less defensive with my <code>bash</code> configuration and moved to sourcing <code>~/.bashrc</code> from my <code>~/.bash_profile</code>, although I couldn’t tell you why I did it this way and not the other way. At any rate, I have my <code>$PS1</code>-prompt twiddling and alias setup in <code>~/.bashrc</code> and my <code>$PATH</code> prepending in <code>~/.bash_profile</code>, although I couldn’t tell you why.</p>
<p><code>fish</code>, mercifully, is much simpler, or at least it’s easier to understand where to put things.</p>
<ul>
<li>Settings that <code>fish</code> likes setting itself (colors, etc.) go in <code>~/.config/fish/fish_variables</code>. (The convenience of <a href="https://fishshell.com/docs/current/tutorial.html#universal-variables">universal variables</a> is nice, but reading <code>fish_variables</code> with its <code>\x1e</code> and similar escapes is a bit of a chore for long variables.)</li>
<li><code>~/.config/fish/functions/</code> for, well, all functions. One file per function. (fish uses functions for the sorts of things one would use an alias for in <code>bash</code>.)</li>
<li><code>~/.config/fish/config.fish</code> for everything else, including building up <code>$PATH</code> and <code>$EXA_COLORS</code> over multiple lines apiece.</li>
</ul>
<h1><code>?</code> doesn’t glob</h1>
<p>This is a small thing, but dagnabbit, I like it.</p>
<p>I use <a href="https://ytdl-org.github.io/youtube-dl/">youtube-dl</a> a fair amount. If I’m downloading a URL like <code>https://www.youtube.com/watch?v=dQw4w9WgXcQ</code>, I need to quote it with single quotes in <code>bash</code>. I don’t need to bother typing the quotes in <code>fish</code> if I’ve done <code>set -U fish_features stderr-nocaret qmark-noglob</code> first.</p>
<p>Why also <code>stderr-nocaret</code>? It disables an old annoyance that I ran into. <code>^</code> isn’t anything special in <code>bash</code>, but it is in <code>fish</code>. <code>git diff HEAD^ HEAD</code> works just fine in <code>bash</code>, but you’ll want to enable <code>stderr-nocaret</code> in <code>fish</code> to keep git and regex annoyances to a minimum.</p>
<h1>Tab-completable makefile targets</h1>
<p>I use simple <a href="https://en.wikipedia.org/wiki/Make_(software)">makefiles</a> in most of my projects. Not only do makefiles reduce the amount of typing you have to do, but they’re a useful memory aid when you return to a project after a spell and wonder “how do I make it go, again?”. Previously, in order to view makefile targets, I’d have to <code>cat</code> the file to see what targets were in the makefile. With <code>fish</code>, though, all I need to do is type <code>make</code>, a space, and then hit the tab-key twice.</p>
<h1>More-accessible history</h1>
<p>This is the feature that I end up using the most, it seems.</p>
<p><code>fish</code> history autocompletes. Press → or C-f to complete the current suggestion. It’s a bit weird to see your old Git commit messages autocomplete when you type <code>git commit -am</code>, but seeing <code>cd Projects/Go/src</code> after just typing <code>cd</code> gets handy. I wouldn’t bother searching through my history and typing <code>!234</code> for something like that.</p>
<p>If you want to keep a few commands out of your history, <code>fish -P</code> <a href="https://fishshell.com/docs/current/interactive.html#private-mode">starts <code>fish</code> in private mode</a>. I’ve used this for a screencast or two.</p>
<hr>
<p>If these features sound neat, head on over to <a href="https://fishshell.com/">the fish website</a> to find out more. If you’re wondering whether switching is a pain (it was for me, if only for a few days), have a look at <a href="../fish-initial-adjustment/">my page on the initial adjustment period</a>.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Frequently, I have four different Terminal windows open to four different paths. Back when <code>fish</code> didn’t support session restoration, each terminal would get reset to my home directory instead of wherever its current working directory was before I quit Terminal. This was more than enough to switch back to <code>bash</code>. <a href="#fnref:1" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>
</ol>
</div>
fish: the initial adjustment period2019-08-02T00:00:00Z2019-08-03T00:00:00Zurn:uuid:f81f5109-c485-4e27-96d9-6eef08a30826<p>A while ago, I switched from <a href="https://en.wikipedia.org/wiki/Bash_(Unix_shell)"><code>bash</code></a> to <a href="https://fishshell.com/"><code>fish</code></a>. This time, I stuck with it. After reading this, you should have a better idea of the hassles involved with switching to a new shell.</p>
<p>(I’m going to assume that you know what a shell is. While I don’t expect you to have used anything other than <code>bash</code>, I assume you’ve heard of other shells like <a href="https://en.wikipedia.org/wiki/Z_shell"><code>zsh</code></a> and <a href="https://en.wikipedia.org/wiki/Tcsh"><code>tcsh</code></a>.)</p>
<hr>
<h1>Even an old version of <code>bash</code> is good enough</h1>
<p>Let’s get this out of the way: <code>bash</code> ain’t half bad. <code>command.com</code>, used for both DOS and Windows, didn’t even do command tab completion. <code>cmd.exe</code>, used in Windows NT up through Windows 10, only started doing command completion by manually changing a setting. <code>bash</code> does this out of the box. Furthermore, even an old version of <code>bash</code>, like the 3.2 that ships with macOS 10.14 Mojave, does all this. (Every so often I check <code>bash</code>’s NEWS file; none of the additions seem memorable enough to justify switching to a new version.)</p>
<p><code>bash</code> also has nifty-keen substitution parameters like <code>!!</code> and <code>!$</code>. They’re handy.</p>
<h1>Initially everything is just a little bit wrong</h1>
<p>As you might expect, a fresh <code>fish</code> shell is way different from my moderately-customized <code>bash</code> settings. <code>fish</code> color settings aren’t too important, but I’m used to my style of prompt and I didn’t want much, if anything, to change about it. The biggest annoyance? <code>fish</code> automatically shortens paths in prompts. That is, <code>~/Pictures/Funny/Autocorrect Failures</code> would get shortened to <code>~/P/F/Autocorrect Failures</code> and I’d have to type <code>pwd</code> to reorient myself in the file system hierarchy. Piecing together different prompts and their writing styles, I eventually settled on this <code>functions/fish_prompt.fish</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fish" data-lang="fish"><span class="line"><span class="cl"><span class="k">function</span> <span class="nb">fish_prompt</span> <span class="na">--description</span> <span class="s1">'Write out the prompt'</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="k">set</span> <span class="na">-l</span> <span class="nv">last_status</span> <span class="nv">$status</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="c"># `set -U ARROW_ONLY yes` and `set -eU ARROW_ONLY` to toggle
</span></span></span><span class="line"><span class="cl"><span class="c"></span> <span class="c"># good for presentations
</span></span></span><span class="line"><span class="cl"><span class="c"></span> <span class="k">if</span> <span class="k">test</span> <span class="na">-n</span> <span class="s2">"</span><span class="nv">$ARROW_ONLY</span><span class="s2">"</span>
</span></span><span class="line"><span class="cl"> <span class="k">echo</span> <span class="s1">'> '</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span>
</span></span><span class="line"><span class="cl"> <span class="k">end</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="k">test</span> <span class="nv">$last_status</span> <span class="na">-ne</span> <span class="m">0</span>
</span></span><span class="line"><span class="cl"> <span class="nb">printf</span> <span class="s2">"%s(%d)%s "</span> <span class="o">(</span><span class="nb">set_color </span>red <span class="na">--bold</span><span class="o">)</span> <span class="nv">$last_status</span> <span class="o">(</span><span class="nb">set_color </span>normal<span class="o">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">end</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="k">set</span> <span class="na">-l</span> <span class="nv">color_cwd</span>
</span></span><span class="line"><span class="cl"> <span class="k">set</span> <span class="na">-l</span> <span class="nv">suffix</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="k">switch</span> <span class="s2">"</span><span class="nv">$USER</span><span class="s2">"</span>
</span></span><span class="line"><span class="cl"> <span class="k">case</span> root toor
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="k">set</span> <span class="na">-q</span> <span class="nv">fish_color_cwd_root</span>
</span></span><span class="line"><span class="cl"> <span class="k">set</span> <span class="nv">color_cwd</span> <span class="nv">$fish_color_cwd_root</span>
</span></span><span class="line"><span class="cl"> <span class="k">else</span>
</span></span><span class="line"><span class="cl"> <span class="k">set</span> <span class="nv">color_cwd</span> <span class="nv">$fish_color_cwd</span>
</span></span><span class="line"><span class="cl"> <span class="k">end</span>
</span></span><span class="line"><span class="cl"> <span class="k">set</span> <span class="nv">suffix</span> <span class="s1">'#'</span>
</span></span><span class="line"><span class="cl"> <span class="k">case</span> <span class="s1">'*'</span>
</span></span><span class="line"><span class="cl"> <span class="k">set</span> <span class="nv">color_cwd</span> <span class="nv">$fish_color_cwd</span>
</span></span><span class="line"><span class="cl"> <span class="k">set</span> <span class="nv">suffix</span> <span class="s1">'>'</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="k">set</span> <span class="na">-q</span> <span class="nv">fish_private_mode</span>
</span></span><span class="line"><span class="cl"> <span class="k">set</span> <span class="nv">suffix</span> <span class="s1">'»'</span>
</span></span><span class="line"><span class="cl"> <span class="k">end</span>
</span></span><span class="line"><span class="cl"> <span class="k">end</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="c"># set $fish_prompt_pwd_dir_length to 0 to disable shortening in prompt_pwd
</span></span></span><span class="line"><span class="cl"><span class="c"></span> <span class="k">echo</span> <span class="na">-n</span> <span class="na">-s</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span> <span class="o">(</span><span class="nb">set_color</span> <span class="na">--bold</span> <span class="nv">$fish_color_user</span><span class="o">)</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span> <span class="s2">"</span><span class="nv">$USER</span><span class="s2">"</span> @ <span class="o">(</span><span class="nf">prompt_hostname</span><span class="o">)</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span> <span class="s1">' '</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span> <span class="o">(</span><span class="nb">set_color</span> <span class="na">--bold</span> <span class="nv">$color_cwd</span><span class="o">)</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span> <span class="o">(</span><span class="nb">prompt_pwd</span><span class="o">)</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span> <span class="o">(</span><span class="nb">set_color </span>normal<span class="o">)</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span> <span class="s2">" </span><span class="nv">$suffix</span><span class="s2"> "</span>
</span></span><span class="line"><span class="cl"><span class="k">end</span>
</span></span></code></pre></div><p>It’s a bit fancier than my old <code>$PS1</code>, but it’s still reasonably clear to read for a novice like me. While the documentation for <code>$fish_prompt_pwd_dir_length</code> wasn’t easy to find, everything else was. This was a refreshing change compared to what I remember of <code>bash</code> documentation. With <code>bash</code>’s web-based <a href="https://en.wikipedia.org/wiki/Info_(Unix)">info</a> pages, I never seemed to be able to find how to do anything I wanted and had to rely on other sites to explain <code>bash</code>’s feature set to me.</p>
<h1>Settling in</h1>
<p>The <code>fish</code> documentation talks about universal variables. At first blush, variables that are shared between all instances of a shell sounded like a useful idea. Every so often I’ve wanted to change something about <code>bash</code> and had to paste-and-run <code>source ~/.bashrc</code> in all my running <code>bash</code> instances. This is an annoyance, if an infrequent one. Unfortunately, I found it’s much more useful to be able to put my variable settings — and especially additions — in <code>config.fish</code>, the <code>.bashrc</code>/<code>.bash_profile</code> equivalent. To see why, have a look at a snippet of my <code>fish_variables</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fish" data-lang="fish"><span class="line"><span class="cl"><span class="c"># This file contains fish universal variable definitions.
</span></span></span><span class="line"><span class="cl"><span class="c"># VERSION: 3.0
</span></span></span><span class="line"><span class="cl"><span class="c"></span><span class="nf">SETUVAR</span> __fish_init_2_39_8:<span class="se">\x</span>1d
</span></span><span class="line"><span class="cl"><span class="nf">SETUVAR</span> __fish_init_2_3_0:<span class="se">\x</span>1d
</span></span><span class="line"><span class="cl"><span class="nf">SETUVAR</span> __fish_init_3_x:<span class="se">\x</span>1d
</span></span><span class="line"><span class="cl"><span class="nf">SETUVAR</span> fish_color_autosuggestion:BD93F9
</span></span><span class="line"><span class="cl"><span class="nf">SETUVAR</span> fish_color_cancel:<span class="se">\x</span>2dr
</span></span><span class="line"><span class="cl"><span class="nf">SETUVAR</span> fish_color_command:normal
</span></span><span class="line"><span class="cl"><span class="c"># …
</span></span></span><span class="line"><span class="cl"><span class="c"></span><span class="nf">SETUVAR</span> fish_pager_color_prefix:white<span class="se">\x</span>1e<span class="se">\x</span>2d<span class="se">\x</span>2dbold<span class="se">\x</span>1e<span class="se">\x</span>2d<span class="se">\x</span>2dunderline
</span></span><span class="line"><span class="cl"><span class="nf">SETUVAR</span> fish_pager_color_progress:brwhite<span class="se">\x</span>1e<span class="se">\x</span>2d<span class="se">\x</span>2dbackground<span class="se">\x</span>3dcyan
</span></span><span class="line"><span class="cl"><span class="nf">SETUVAR</span> fish_prompt_pwd_dir_length:<span class="m">0</span>
</span></span></code></pre></div><p>Now imagine trying to edit your <code>$PATH</code> if it were separated by not just colons, but backslash-escaped UTF-8 byte sequences of <a href="https://en.wikipedia.org/wiki/Private_Use_Areas">Private Use Area</a> code points. Ick. Meanwhile, the old-fashioned way preserves the ability to logically group similar path adjustments:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fish" data-lang="fish"><span class="line"><span class="cl"><span class="k">set</span> <span class="na">-x</span> <span class="nv">PATH</span> <span class="nv">$HOME</span>/Library/Python/<span class="m">2</span>.<span class="m">7</span>/bin <span class="nv">$PATH</span>
</span></span><span class="line"><span class="cl"><span class="k">set</span> <span class="na">-x</span> <span class="nv">PATH</span> /Library/Frameworks/Python.framework/Versions/<span class="m">2</span>.<span class="m">7</span>/bin <span class="nv">$PATH</span>
</span></span><span class="line"><span class="cl"><span class="k">set</span> <span class="na">-x</span> <span class="nv">PATH</span> /Library/Frameworks/Python.framework/Versions/<span class="m">3</span>.<span class="m">5</span>/bin <span class="nv">$PATH</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">set</span> <span class="na">-x</span> <span class="nv">GOPATH</span> <span class="nv">$HOME</span>/Projects/Go
</span></span><span class="line"><span class="cl"><span class="k">set</span> <span class="na">-x</span> <span class="nv">PATH</span> <span class="nv">$HOME</span>/Projects/Go/bin <span class="nv">$PATH</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">set</span> <span class="na">-x</span> <span class="nv">PATH</span> <span class="nv">$HOME</span>/bin <span class="nv">$PATH</span>
</span></span></code></pre></div><p>This is doubly important for anything that needs to be documented on a per-chunk basis:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fish" data-lang="fish"><span class="line"><span class="cl"><span class="c"># for xterm-256color:
</span></span></span><span class="line"><span class="cl"><span class="c">#
</span></span></span><span class="line"><span class="cl"><span class="c"># - 38;5 — next number sets text color
</span></span></span><span class="line"><span class="cl"><span class="c"># - 48;5 — next number sets background color
</span></span></span><span class="line"><span class="cl"><span class="c">#
</span></span></span><span class="line"><span class="cl"><span class="c"># (colors at, say, <https://i.stack.imgur.com/UQVe5.png>)
</span></span></span><span class="line"><span class="cl"><span class="c"></span><span class="k">set</span> <span class="na">-x</span> <span class="nv">EXA_COLORS</span>
</span></span><span class="line"><span class="cl"><span class="k">set</span> <span class="na">-a</span> <span class="nv">EXA_COLORS</span> <span class="s2">"di=38;5;69"</span> <span class="c"># directories
</span></span></span><span class="line"><span class="cl"><span class="c"></span><span class="k">set</span> <span class="na">-a</span> <span class="nv">EXA_COLORS</span> <span class="s2">"da=38;5;195"</span> <span class="c"># times
</span></span></span><span class="line"><span class="cl"><span class="c"></span>
</span></span><span class="line"><span class="cl"><span class="k">set</span> <span class="nv">EXA_COLORS</span> <span class="o">(</span><span class="nb">string </span>join <span class="s2">":"</span> <span class="nv">$EXA_COLORS</span><span class="o">)</span>
</span></span></code></pre></div><p>While it’d be neat to have <a href="https://the.exa.website" title="an ls(1) replacement">exa</a> colors propagate instantly, editing its <code>fish_variables</code> entry would be as fun as editing a 120-column, one-line regular expression.</p>
<h1>Yes, this is a lot of busywork</h1>
<p>If all this sounds like I’m doing lots of work to merely get my <code>fish</code> setup to be as good as my <code>bash</code> setup, you’re right. What’s more, I hadn’t really seen any of the benefits of <code>fish</code> yet.</p>
<p>Eventually, I <a href="../fish-benefits/">found a lot of things to like about <code>fish</code></a> that made me glad I switched.</p>
Widespread adoption of dark mode will help people sleep better2019-06-10T18:02:26-07:002019-06-02T23:41:18-07:00urn:uuid:cf7d1f23-9dae-4138-a4f5-b3f52dbbbf75<p>People like reading in bed right before bed. Unfortunately, the best thing to read is frequently a phone or tablet. This appears to be bad, but this will be less bad in the future once websites start supporting automatic dark modes. You can help your visitors get to sleep faster, rest more, and be closer their fullest selves if you keep your website’s lights to a minimum when they’re browsing your site at night.</p>
<p>Not yet convinced? Read on.</p>
<h1 id="melatonin">Melatonin helps you get to sleep</h1>
<p>There are many things that one can do to ensure that his ability to fall asleep isn’t impaired. One of the general strategies that turns up in getting-to-sleep advice is <em>don’t let anything interfere with your body’s melatonin production</em>.</p>
<p>Melatonin times sleep onset<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> and it’s naturally generated by your body once you stop seeing high-energy light. What sort of light is high-energy? Sunlight and light shifted toward the violet/blue end of the spectrum. What sort of light is lower-energy? Light that’s redder and more like candlelight. What can you do to see less high-energy light in the evening? Well, you could…</p>
<ul>
<li>wear blue-blocking glasses (they look yellow)</li>
<li>use lower-color-temperature light bulbs and turn your daytime-simulating bluer bulbs off</li>
<li>put <a href="https://www.amazon.com/LightDims-Original-Strength-Electronics-Appliances/dp/B009WSJNCW">Light Dims</a> on LEDs, <em>especially</em> those annoying bright blue LEDs and white LEDs that are all the rage these days</li>
<li>not look at any blue-light-emitting screens in the evening</li>
</ul>
<p>That last one on the list is kind of hard to do for most people. Luckily, there’s something able to help with that.</p>
<h1 id="flux">F.lux and friends</h1>
<p>Back in February of 2009, <a href="https://en.wikipedia.org/wiki/F.lux">f.lux</a> was released. It shifted everything on your monitor toward the red end of the spectrum and did so automatically based on your location and time of day, as sunrise and sunset depend on both the time of year and how far away from the equator you are. While f.lux is a fine piece of software, its core feature has been incorporated into almost all the major consumer operating systems: macOS, iOS, and Windows. These days, you can get just about everything red-shifted in the evenings, especially since I’m pretty sure there are third-party f.lux clones for current versions of Android as well.</p>
<p>Of course, there is still more that could be done. A screen that’s mostly reddish white is still more disruptive than a screen that’s mostly black. My book-reading app supports light text on a dark background, but what about everything else?</p>
<h1 id="dark-mode">Exit light, enter night</h1>
<p>One solution is to take all the UI changes that Books uses and build support for that sort of thing into the operating system. The OS will tell an application “the system is in light mode” or “the system is in dark mode”, much like it communicates “the user prefers high-contrast UI”. Any app that supports dark mode, for lack of a better word, will switch to mostly-light text on a mostly-dark background. This is much, <em>much</em> more pleasant at night than having your eyeballs bleached by white-background web pages surrounded by light-gray browser buttons and address bars.</p>
<p>What’s more, web pages can get in on the dark-mode action. <a href="https://webkit.org/blog/8840/dark-mode-support-in-webkit/">Safari</a> for macOS supports it, Safari for iOS will support it later this fall, and Firefox supports it on (at least) both macOS and Windows. As of this writing, it’s in the “intent to ship” state <a href="https://bugs.chromium.org/p/chromium/issues/detail?id=889087#c59">in the Chromium bug tracker</a>, so it should be coming to a browser near you if it hasn’t already.</p>
<h1 id="darkening">How much work is involved?</h1>
<p>Eh, it depends. Possibly a lot if you’ve got a lot of images and/or diagrams.</p>
<p>Andy Clarke’s <a href="https://stuffandnonsense.co.uk/blog/redesigning-your-product-and-website-for-dark-mode">page on designing for dark mode</a> is fairly helpful if you’re looking for how to choose colors and override them properly inside a <code>@media (prefers-color-scheme: dark) { }</code> block. On the other hand, dealing with images isn’t always easy or fast. If you use SVG icons or icon fonts for UI elements, some of them might look funny until a new version of Font Awesome is released with re-drawn designs that look good on a dark background. <a href="https://developer.apple.com/design/human-interface-guidelines/macos/visual-design/dark-mode/">Apple points out</a> that icons that look good as an outline in light mode often look better as a solid shape in dark mode.</p>
<p>User-chosen colors are another pain point that crops up and I don’t have any good answers for how to handle this. If you can manage to restrict your users’ color choices to a smallish palette, you can improve your odds of having nice-looking colors in either mode. However, any given user has a decent chance of picking colors that only look good in his preferred color scheme, making others squint to figure out what his nickname is or what a label says. Apple’s solution for their operating systems is to have a handful of predefined color names that subtly change in dark mode. For example, their <code>.teal</code> is a darker teal in dark mode than it is in light mode. This may be a bit more work if you support 55 different user-selectable colors (as <a href="https://timingapp.com/">Timing</a> does), or impossible if you support 16½ million (as Twitch does for Prime and Turbo members).</p>
<p>Third-party visualization libraries are also another source of headaches. I’ve been having trouble getting <a href="https://www.chartjs.org/">chart.js</a> to respond properly to color-scheme toggles. Its developers will probably figure out something, but if you want background-color-agnostic charts, you’re not going to be able to just set a color as a string and call it a day.</p>
<h1 id="why">Why do all this work?</h1>
<p>Late at night, dark things are pleasant to read. Light things are painful to read. You don’t want your website to be painful to read, do you? If your website is pleasant and soothing in a darkened room, your site will be more likely to be one of the last things on your visitors’ minds before they go to sleep. Sure, dark-mode changes are quite a bit of work to implement, but do you want to cede the opportunity to be the last thing your viewer reads right before nodding off?</p>
<p>What’s more, as more sites have dark modes available, people will have a little less trouble going to bed at a proper hour. Sure, there will still be loud cars and hungry babies and filled bladders and gnawing fears, but more people will get a better night’s sleep more often if the late-night high-energy photon blast is kept to a bare minimum. I’m happy to help other people sleep a little bit better, and you will too.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>This and other factoids about sleep are from Matthew Walker’s <em>Why We Sleep: Unlocking the Power of Sleep and Dreams</em>. You should buy his book. <a href="#fnref:1" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>
</ol>
</div>