<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/atom.xsl" type="text/xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-GB">
  <title>Flother
    
  </title>
  
  <subtitle>Flother is the online home of Matt Riggott, a programmer and map-maker living in Reykjavík, Iceland.</subtitle>
  
  <link href="https://www.flother.is/atom.xml" rel="self" type="application/atom+xml"/>
  <link href="
      
        https://www.flother.is
      
    "/>
  <updated>2025-08-26T00:00:00+00:00</updated>
  <id>https://www.flother.is/atom.xml</id>
  
  <entry xml:lang="en-GB">
    <title>How to get quick access to dictionary definitions using Spotlight on MacOS</title>
    <published>2025-08-26T00:00:00+00:00</published>
    <updated>2025-08-26T00:00:00+00:00</updated>
    <link href="https://www.flother.is/til/macos-spotlight-dictionary-definitions/" type="text/html"/>
    <id>https://www.flother.is/til/macos-spotlight-dictionary-definitions/</id>
    
    <content type="html">&lt;p&gt;It’s 2014 and I want to check the spelling of a word. I’m on my MacBook, so I can simply hit &lt;kbd&gt;Command&lt;&#x2F;kbd&gt;-&lt;kbd&gt;Space&lt;&#x2F;kbd&gt; and search for the word with Spotlight. Because I’ve configured dictionary definitions to appear at the top of Spotlight results (using the &lt;a href=&quot;https:&#x2F;&#x2F;www.macworld.com&#x2F;article&#x2F;225198&#x2F;choosing-the-right-keyboard-based-launcher-utility.html#get-used-to-keyboard-commands&quot;&gt;UI shown here&lt;&#x2F;a&gt;), the word appears right at the top of the list. I love computers!&lt;&#x2F;p&gt;
&lt;p&gt;It’s 2015 and Apple have released El Capitan (aka OS X 10.11). I want to check the spelling of a word. I’m on my MacBook, so I hit &lt;kbd&gt;Command&lt;&#x2F;kbd&gt;-&lt;kbd&gt;Space&lt;&#x2F;kbd&gt; and search for the word with Spotlight. Unfortunately, I’m no longer allowed to configure the order of Spotlight search results, so instead I scroll through results for web pages, documents, photos, emails, system preferences, and more, before finally finding the dictionary definition. I hate computers!&lt;&#x2F;p&gt;
&lt;p&gt;It’s 2025 and I’m &lt;em&gt;still annoyed&lt;&#x2F;em&gt; that Apple won’t let me put dictionary definitions at the top of Spotlight search results anymore. It’s been a decade and I miss it every day. Finally, 3,650 days later, I looked for a solution.&lt;&#x2F;p&gt;
&lt;p&gt;And found one! It’s not quite as simple as it used to be, but there are a couple of keyboard shortcuts that make Spotlight search results marginally less frustrating:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;kbd&gt;Command&lt;&#x2F;kbd&gt;-&lt;kbd&gt;L&lt;&#x2F;kbd&gt;: Jump straight to the dictionary definition in the results list&lt;&#x2F;li&gt;
&lt;li&gt;&lt;kbd&gt;Command&lt;&#x2F;kbd&gt;-&lt;kbd&gt;D&lt;&#x2F;kbd&gt;: Launch the Dictionary app with the definition open immediately&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Apple maintains documentation on &lt;a href=&quot;https:&#x2F;&#x2F;support.apple.com&#x2F;en-gb&#x2F;guide&#x2F;mac-help&#x2F;mh26783&#x2F;mac&quot;&gt;Spotlight keyboard shortcuts on Mac&lt;&#x2F;a&gt; but, naturally, neither of these shortcuts are listed there. They &lt;em&gt;are&lt;&#x2F;em&gt; listed in an answer to this &lt;a href=&quot;https:&#x2F;&#x2F;superuser.com&#x2F;questions&#x2F;1591978&quot;&gt;SuperUser thread&lt;&#x2F;a&gt;, and the source for that, a &lt;a href=&quot;https:&#x2F;&#x2F;www.flother.is&#x2F;til&#x2F;macos-spotlight-dictionary-definitions&#x2F;(https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;OSXElCapitan&#x2F;comments&#x2F;3lf3tj&#x2F;comment&#x2F;cxw7wgv&#x2F;)&quot;&gt;Reddit post&lt;&#x2F;a&gt; by a now-deleted user, lists another undocumented shortcut: &lt;kbd&gt;Command&lt;&#x2F;kbd&gt;-&lt;kbd&gt;B&lt;&#x2F;kbd&gt; to search for the term in your browser. There’s at least one other longstanding undocumented shortcut too: &lt;kbd&gt;Command&lt;&#x2F;kbd&gt;-&lt;kbd&gt;I&lt;&#x2F;kbd&gt; to show the Get Info dialogue for files and folders (I discovered this in &lt;a href=&quot;https:&#x2F;&#x2F;osxdaily.com&#x2F;2012&#x2F;03&#x2F;09&#x2F;spotlight-keyboard-shortcuts&#x2F;&quot;&gt;this OSXDaily post from 2012&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;The broader issue here is symptomatic of modern Apple: removing power-user features in favour of what they think most people want, then hiding the remaining functionality behind undocumented keyboard shortcuts. But at least I can get fast access to dictionary definitions. For now.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;PS. The SuperUser thread also mentions a solution to reorder Spotlight results by editing a &lt;code&gt;.plist&lt;&#x2F;code&gt; file. I tried this but couldn’t get it to work. So keyboard shortcuts it is.&lt;&#x2F;p&gt;
</content>
  </entry>
  
  <entry xml:lang="en-GB">
    <title>How to automatically format acronyms according to The Economist’s style guide in Typst</title>
    <published>2025-05-29T00:00:00+00:00</published>
    <updated>2025-05-29T00:00:00+00:00</updated>
    <link href="https://www.flother.is/til/typst-acronyms-economist-style/" type="text/html"/>
    <id>https://www.flother.is/til/typst-acronyms-economist-style/</id>
    
    <content type="html">&lt;p&gt;I &lt;em&gt;love&lt;&#x2F;em&gt; &lt;a href=&quot;https:&#x2F;&#x2F;typst.app&#x2F;docs&#x2F;&quot;&gt;Typst&lt;&#x2F;a&gt;. It’s a markup-based typesetting system that has the readability of Markdown with the power of LaTeX. I enjoy writing in it, and its PDF output is excellent. For my academic writing, Typst has replaced a homemade system of Markdown, Pandoc, and LaTeX that always felt clunky and brittle.&lt;&#x2F;p&gt;
&lt;p&gt;When I’m writing in Typst I try to follow The Economist’s style guide. It’s a well-regarded set of rules that can help produce readable prose in a formal style. One thing the style guide insists on, for example, is for acronyms to be typeset in small caps — so HTML becomes &lt;span aria-label=&quot;HTML&quot;&gt;ʜᴛᴍʟ&lt;&#x2F;span&gt; and NATO becomes &lt;span aria-label=&quot;NATO&quot;&gt;ɴᴀᴛᴏ&lt;&#x2F;span&gt;. This creates a more refined appearance on the page, preventing acronyms from appearing prominent in body text. However, there are two important exceptions: chemical formulae like H&lt;sub&gt;2&lt;&#x2F;sub&gt;O shouldn’t use small caps (probably because chemical notation is a precise symbolic language), and acronyms in headings should remain in full capitals (probably to maintain proper hierarchy, but also because it looks odd).&lt;&#x2F;p&gt;
&lt;p&gt;The challenge was implementing these rules in Typst without littering documents with &lt;code&gt;#smallcaps&lt;&#x2F;code&gt; function calls everywhere. Nobody wants to write &lt;code&gt;#smallcaps[HTML]&lt;&#x2F;code&gt; repeatedly throughout a document — it makes a document hard to write and its source hard to read.&lt;&#x2F;p&gt;
&lt;p&gt;The solution involves using Typst’s &lt;a href=&quot;https:&#x2F;&#x2F;typst.app&#x2F;docs&#x2F;reference&#x2F;introspection&#x2F;state&#x2F;&quot;&gt;state management&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;typst.app&#x2F;docs&#x2F;tutorial&#x2F;formatting&#x2F;#show-rules&quot;&gt;show rules&lt;&#x2F;a&gt; to create an automatic formatting system. A boolean state called &lt;code&gt;acOK&lt;&#x2F;code&gt; tracks whether acronyms should be converted to small caps. By default, it’s enabled, but it gets temporarily disabled within headings and can be manually disabled using a &lt;code&gt;noac()&lt;&#x2F;code&gt; wrapper function for chemical formulae.&lt;&#x2F;p&gt;
&lt;p&gt;The magic happens with a regex pattern that matches words made up of a capital letter followed by one or more capital letters and digits (&lt;code&gt;\b[A-Z][A-Z\d]+\b&lt;&#x2F;code&gt;). When this pattern is found in a document, Typst checks the current state and either applies small caps formatting or leaves the text unchanged.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;typst&quot; class=&quot;language-typst z-code&quot;&gt;&lt;code class=&quot;language-typst&quot; data-lang=&quot;typst&quot;&gt;&lt;span class=&quot;z-text z-typst&quot;&gt;&lt;span class=&quot;z-meta z-expression z-typst&quot;&gt;&lt;span class=&quot;z-keyword z-other z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-expression z-typst&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-declaration z-typst&quot;&gt;let&lt;&#x2F;span&gt; acOK &lt;span class=&quot;z-keyword z-operator z-typst&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-arguments z-typst&quot;&gt;&lt;span class=&quot;z-support z-function z-typst&quot;&gt;state&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-typst&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-typst&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;acOK&lt;span class=&quot;z-punctuation z-definition z-string z-end z-typst&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-typst&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-boolean z-typst&quot;&gt;true&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-typst&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-typst&quot;&gt;&lt;span class=&quot;z-meta z-expression z-typst&quot;&gt;&lt;span class=&quot;z-keyword z-other z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-expression z-typst&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-declaration z-typst&quot;&gt;let&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-arguments z-typst&quot;&gt;&lt;span class=&quot;z-support z-function z-typst&quot;&gt;noac&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-typst&quot;&gt;(&lt;&#x2F;span&gt;content&lt;span class=&quot;z-punctuation z-section z-group z-end z-typst&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-typst&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-section z-group z-begin z-typst&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-typst&quot;&gt;&lt;span class=&quot;z-meta z-expression z-typst&quot;&gt;  acOK&lt;span class=&quot;z-meta z-function-call z-arguments z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-typst&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-typst&quot;&gt;update&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-typst&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language z-boolean z-typst&quot;&gt;false&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-typst&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-typst&quot;&gt;&lt;span class=&quot;z-meta z-expression z-typst&quot;&gt;  content
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-typst&quot;&gt;&lt;span class=&quot;z-meta z-expression z-typst&quot;&gt;  acOK&lt;span class=&quot;z-meta z-function-call z-arguments z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-typst&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-typst&quot;&gt;update&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-typst&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language z-boolean z-typst&quot;&gt;true&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-typst&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-typst&quot;&gt;&lt;span class=&quot;z-meta z-expression z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-typst&quot;&gt;}&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-typst&quot;&gt;&lt;span class=&quot;z-meta z-expression z-typst&quot;&gt;&lt;span class=&quot;z-keyword z-other z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-expression z-typst&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-declaration z-typst&quot;&gt;show&lt;&#x2F;span&gt; heading&lt;span class=&quot;z-punctuation z-separator z-key-value z-typst&quot;&gt;:&lt;&#x2F;span&gt; it &lt;span class=&quot;z-keyword z-operator z-typst&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-section z-group z-begin z-typst&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-typst&quot;&gt;&lt;span class=&quot;z-meta z-expression z-typst&quot;&gt;  acOK&lt;span class=&quot;z-meta z-function-call z-arguments z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-typst&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-typst&quot;&gt;update&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-typst&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language z-boolean z-typst&quot;&gt;false&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-typst&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-typst&quot;&gt;&lt;span class=&quot;z-meta z-expression z-typst&quot;&gt;  it
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-typst&quot;&gt;&lt;span class=&quot;z-meta z-expression z-typst&quot;&gt;  acOK&lt;span class=&quot;z-meta z-function-call z-arguments z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-typst&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-typst&quot;&gt;update&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-typst&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language z-boolean z-typst&quot;&gt;true&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-typst&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-typst&quot;&gt;&lt;span class=&quot;z-meta z-expression z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-typst&quot;&gt;}&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-typst&quot;&gt;&lt;span class=&quot;z-meta z-expression z-typst&quot;&gt;&lt;span class=&quot;z-keyword z-other z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-expression z-typst&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-declaration z-typst&quot;&gt;show&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-arguments z-typst&quot;&gt;&lt;span class=&quot;z-support z-function z-typst&quot;&gt;regex&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-typst&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-typst&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-typst&quot;&gt;&lt;span class=&quot;z-string z-regexp z-typst&quot;&gt;\b[A-Z][A-Z\d]+\b&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-typst&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-typst&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-typst&quot;&gt;:&lt;&#x2F;span&gt; acronym &lt;span class=&quot;z-keyword z-operator z-typst&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-declaration z-typst&quot;&gt;context&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-section z-group z-begin z-typst&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-expression z-typst&quot;&gt;&lt;span class=&quot;z-keyword z-other z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-expression z-typst&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control z-typst&quot;&gt;if&lt;&#x2F;span&gt; acOK&lt;span class=&quot;z-meta z-function-call z-arguments z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-typst&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-typst&quot;&gt;get&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-typst&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-typst&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-section z-group z-begin z-typst&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-typst&quot;&gt;&lt;span class=&quot;z-support z-function z-typst&quot;&gt;smallcaps&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-typst&quot;&gt;(&lt;&#x2F;span&gt;acronym&lt;span class=&quot;z-punctuation z-separator z-typst&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-typst&quot;&gt;all&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-parameter z-typst&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-boolean z-typst&quot;&gt;true&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-typst&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-typst&quot;&gt;}&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-typst&quot;&gt;else&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-section z-group z-begin z-typst&quot;&gt;{&lt;&#x2F;span&gt;acronym&lt;span class=&quot;z-punctuation z-section z-group z-end z-typst&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-typst&quot;&gt;]&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This combination of Typst features lets me write clean, readable documents while automatically applying The Economist’s style rules — I can focus on writing rather than formatting. Acronyms in body text are typeset in small caps, headings remain unaffected, and chemical formulae can be wrapped in &lt;code&gt;noac()&lt;&#x2F;code&gt; when needed. It’s a perfect example of the power of the Typst language: beautiful output from readable sources.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;example&quot;&gt;Example&lt;&#x2F;h3&gt;
&lt;p&gt;Here’s a complete example document:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;typst&quot; class=&quot;language-typst z-code&quot;&gt;&lt;code class=&quot;language-typst&quot; data-lang=&quot;typst&quot;&gt;&lt;span class=&quot;z-text z-typst&quot;&gt;&lt;span class=&quot;z-meta z-expression z-typst&quot;&gt;&lt;span class=&quot;z-keyword z-other z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-expression z-typst&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-declaration z-typst&quot;&gt;set&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-arguments z-typst&quot;&gt;&lt;span class=&quot;z-support z-function z-typst&quot;&gt;page&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-typst&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-typst&quot;&gt;paper&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-parameter z-typst&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-typst&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;a6&lt;span class=&quot;z-punctuation z-definition z-string z-end z-typst&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-typst&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-typst&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-typst&quot;&gt;&lt;span class=&quot;z-meta z-expression z-typst&quot;&gt;&lt;span class=&quot;z-keyword z-other z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-expression z-typst&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-declaration z-typst&quot;&gt;let&lt;&#x2F;span&gt; acOK &lt;span class=&quot;z-keyword z-operator z-typst&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-arguments z-typst&quot;&gt;&lt;span class=&quot;z-support z-function z-typst&quot;&gt;state&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-typst&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-typst&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;acOK&lt;span class=&quot;z-punctuation z-definition z-string z-end z-typst&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-typst&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-boolean z-typst&quot;&gt;true&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-typst&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-typst&quot;&gt;&lt;span class=&quot;z-meta z-expression z-typst&quot;&gt;&lt;span class=&quot;z-keyword z-other z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-expression z-typst&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-declaration z-typst&quot;&gt;show&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-typst&quot;&gt;&amp;quot;&lt;&#x2F;span&gt; — &lt;span class=&quot;z-punctuation z-definition z-string z-end z-typst&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-typst&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-section z-group z-begin z-typst&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-backslash z-typst&quot;&gt;\&lt;&#x2F;span&gt;u{202F}&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-expression z-typst&quot;&gt;&lt;span class=&quot;z-constant z-other z-symbol z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-typst&quot;&gt;#&lt;&#x2F;span&gt;sym.dash&lt;span class=&quot;z-punctuation z-accessor z-typst&quot;&gt;.&lt;&#x2F;span&gt;em&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-backslash z-typst&quot;&gt;\&lt;&#x2F;span&gt;u{202F}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-typst&quot;&gt;]&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-typst&quot;&gt;&lt;span class=&quot;z-meta z-expression z-typst&quot;&gt;&lt;span class=&quot;z-keyword z-other z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-expression z-typst&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-declaration z-typst&quot;&gt;let&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-arguments z-typst&quot;&gt;&lt;span class=&quot;z-support z-function z-typst&quot;&gt;noac&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-typst&quot;&gt;(&lt;&#x2F;span&gt;content&lt;span class=&quot;z-punctuation z-section z-group z-end z-typst&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-typst&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-section z-group z-begin z-typst&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-typst&quot;&gt;&lt;span class=&quot;z-meta z-expression z-typst&quot;&gt;  acOK&lt;span class=&quot;z-meta z-function-call z-arguments z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-typst&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-typst&quot;&gt;update&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-typst&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language z-boolean z-typst&quot;&gt;false&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-typst&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-typst&quot;&gt;&lt;span class=&quot;z-meta z-expression z-typst&quot;&gt;  content
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-typst&quot;&gt;&lt;span class=&quot;z-meta z-expression z-typst&quot;&gt;  acOK&lt;span class=&quot;z-meta z-function-call z-arguments z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-typst&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-typst&quot;&gt;update&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-typst&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language z-boolean z-typst&quot;&gt;true&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-typst&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-typst&quot;&gt;&lt;span class=&quot;z-meta z-expression z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-typst&quot;&gt;}&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-typst&quot;&gt;&lt;span class=&quot;z-meta z-expression z-typst&quot;&gt;&lt;span class=&quot;z-keyword z-other z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-expression z-typst&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-declaration z-typst&quot;&gt;show&lt;&#x2F;span&gt; heading&lt;span class=&quot;z-punctuation z-separator z-key-value z-typst&quot;&gt;:&lt;&#x2F;span&gt; it &lt;span class=&quot;z-keyword z-operator z-typst&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-section z-group z-begin z-typst&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-typst&quot;&gt;&lt;span class=&quot;z-meta z-expression z-typst&quot;&gt;  acOK&lt;span class=&quot;z-meta z-function-call z-arguments z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-typst&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-typst&quot;&gt;update&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-typst&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language z-boolean z-typst&quot;&gt;false&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-typst&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-typst&quot;&gt;&lt;span class=&quot;z-meta z-expression z-typst&quot;&gt;  it
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-typst&quot;&gt;&lt;span class=&quot;z-meta z-expression z-typst&quot;&gt;  acOK&lt;span class=&quot;z-meta z-function-call z-arguments z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-typst&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-typst&quot;&gt;update&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-typst&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language z-boolean z-typst&quot;&gt;true&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-typst&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-typst&quot;&gt;&lt;span class=&quot;z-meta z-expression z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-typst&quot;&gt;}&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-typst&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-typst&quot;&gt;&lt;span class=&quot;z-meta z-expression z-typst&quot;&gt;&lt;span class=&quot;z-keyword z-other z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-expression z-typst&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-declaration z-typst&quot;&gt;show&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-arguments z-typst&quot;&gt;&lt;span class=&quot;z-support z-function z-typst&quot;&gt;regex&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-typst&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-typst&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-typst&quot;&gt;&lt;span class=&quot;z-string z-regexp z-typst&quot;&gt;\b[A-Z\d]{2,}\b&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-typst&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-typst&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-typst&quot;&gt;:&lt;&#x2F;span&gt; acronym &lt;span class=&quot;z-keyword z-operator z-typst&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-declaration z-typst&quot;&gt;context&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-section z-group z-begin z-typst&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-expression z-typst&quot;&gt;&lt;span class=&quot;z-keyword z-other z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-expression z-typst&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control z-typst&quot;&gt;if&lt;&#x2F;span&gt; acOK&lt;span class=&quot;z-meta z-function-call z-arguments z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-typst&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-typst&quot;&gt;get&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-typst&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-typst&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-section z-group z-begin z-typst&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-typst&quot;&gt;&lt;span class=&quot;z-support z-function z-typst&quot;&gt;smallcaps&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-typst&quot;&gt;(&lt;&#x2F;span&gt;acronym&lt;span class=&quot;z-punctuation z-separator z-typst&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-typst&quot;&gt;all&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-parameter z-typst&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-boolean z-typst&quot;&gt;true&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-typst&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-typst&quot;&gt;}&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-typst&quot;&gt;else&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-section z-group z-begin z-typst&quot;&gt;{&lt;&#x2F;span&gt;acronym&lt;span class=&quot;z-punctuation z-section z-group z-end z-typst&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-typst&quot;&gt;]&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-typst&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-typst&quot;&gt;&lt;span class=&quot;z-markup z-heading z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-heading z-begin z-typst&quot;&gt;=&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-heading z-typst&quot;&gt;&lt;span class=&quot;z-entity z-name z-section z-typst&quot;&gt;What is HTML?&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-whitespace z-newline z-typst&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-typst&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-typst&quot;&gt;HTML is one of the three basic building block of all web pages,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-typst&quot;&gt;the others being CSS and JavaScript.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-typst&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-typst&quot;&gt;On an analogue clock, the number 4 is often written as
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-typst&quot;&gt;&lt;span class=&quot;z-meta z-expression z-typst&quot;&gt;&lt;span class=&quot;z-support z-other z-typst&quot;&gt;&lt;span class=&quot;z-variable z-function z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-expression z-typst&quot;&gt;#&lt;&#x2F;span&gt;noac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-typst&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-typst&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;IIII&lt;span class=&quot;z-punctuation z-definition z-string z-end z-typst&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-typst&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; rather than &lt;span class=&quot;z-meta z-expression z-typst&quot;&gt;&lt;span class=&quot;z-support z-other z-typst&quot;&gt;&lt;span class=&quot;z-variable z-function z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-expression z-typst&quot;&gt;#&lt;&#x2F;span&gt;noac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-typst&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-typst&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;IV&lt;span class=&quot;z-punctuation z-definition z-string z-end z-typst&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-typst&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And its output:&lt;&#x2F;p&gt;

    
    
  
  &lt;figure&gt;
  
  &lt;img alt=&quot;Output of the Typst code&quot; src=&quot;https:&amp;#x2F;&amp;#x2F;www.flother.is&amp;#x2F;processed_images&amp;#x2F;output.fe9c777fc7159532.png&quot; srcset=&quot;https:&amp;#x2F;&amp;#x2F;www.flother.is&amp;#x2F;processed_images&amp;#x2F;output.c1292b8755c17526.png 2x&quot; height=&quot;294&quot; width=&quot;608&quot; loading=&quot;lazy&quot;&gt;
  
  
&lt;&#x2F;figure&gt;
</content>
  </entry>
  
  <entry xml:lang="en-GB">
    <title>How to customise the styling of em-dashes in Typst</title>
    <published>2025-03-01T00:00:00+00:00</published>
    <updated>2025-03-01T00:00:00+00:00</updated>
    <link href="https://www.flother.is/til/typst-em-dash-show-rule/" type="text/html"/>
    <id>https://www.flother.is/til/typst-em-dash-show-rule/</id>
    
    <content type="html">&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;typst.app&#x2F;&quot;&gt;Typst&lt;&#x2F;a&gt; is a modern, markup-based typesetting system designed as a successor to LaTeX. If you need to produce PDFs — particularly for academic or technical writing — then it’s an invaluable tool.&lt;&#x2F;p&gt;
&lt;p&gt;Writing in Typst is much like writing in Markdown: you write primarily in plain-text, adding lightweight markup only when you need it — _italics_, *bold text*, that sort of thing. It stays out of your way when you just want to write.&lt;&#x2F;p&gt;
&lt;p&gt;I am, however, quite particular about formatting. Take em-dashes, for example. I prefer them flanked by narrow non-breaking spaces. Narrow, so they don’t butt up directly against surrounding words, yet aren’t surrounded by oceans of whitespace. Non-breaking, so they don’t end up orphaned at the end of a line.&lt;&#x2F;p&gt;
&lt;p&gt;The problem? Typing this needs markup, which takes me out of the flow of writing. To produce the following sentence:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The food — which was delicious — reminded me of Morocco&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I’d need to write each em-dash as:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;typst&quot; class=&quot;language-typst z-code&quot;&gt;&lt;code class=&quot;language-typst&quot; data-lang=&quot;typst&quot;&gt;&lt;span class=&quot;z-text z-typst&quot;&gt;&lt;span class=&quot;z-constant z-character z-escape z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-backslash z-typst&quot;&gt;\&lt;&#x2F;span&gt;u{202F}&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-expression z-typst&quot;&gt;&lt;span class=&quot;z-constant z-other z-symbol z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-typst&quot;&gt;#&lt;&#x2F;span&gt;sym.dash&lt;span class=&quot;z-punctuation z-accessor z-typst&quot;&gt;.&lt;&#x2F;span&gt;em&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-backslash z-typst&quot;&gt;\&lt;&#x2F;span&gt;u{202F}&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Which is unreadable, tedious, and prone to mistakes. What I really want is to write it in a way that allows me to keep typing without thinking about typesetting. Typst has a shortcut for an em-dash (three hyphens, &lt;code&gt;---&lt;&#x2F;code&gt;). I want to type that but get my surrounding narrow-width non-breaking spaces too. I want to type this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;The food --- which was delicious --- reminded me of Morocco
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And have it render as:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;The food\u{202F}#sym.dash.em\u{202F}which was delicious\u{202F}#sym.dash.em\u{202F}reminded me of Morocco
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Yesterday, I had a eureka moment: I realised I can use Typst’s &lt;a href=&quot;https:&#x2F;&#x2F;typst.app&#x2F;docs&#x2F;reference&#x2F;styling#show-rules&quot;&gt;show rules&lt;&#x2F;a&gt; to do exactly that. Below is a show rule with a text selector, &lt;code&gt;&quot; — &quot;&lt;&#x2F;code&gt; (space, em-dash, space), that replaces that text with an em-dash surrounded by narrow non-breaking spaces:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;typst&quot; class=&quot;language-typst z-code&quot;&gt;&lt;code class=&quot;language-typst&quot; data-lang=&quot;typst&quot;&gt;&lt;span class=&quot;z-text z-typst&quot;&gt;&lt;span class=&quot;z-meta z-expression z-typst&quot;&gt;&lt;span class=&quot;z-keyword z-other z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-expression z-typst&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-declaration z-typst&quot;&gt;show&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-typst&quot;&gt;&amp;quot;&lt;&#x2F;span&gt; — &lt;span class=&quot;z-punctuation z-definition z-string z-end z-typst&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-typst&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-section z-group z-begin z-typst&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-backslash z-typst&quot;&gt;\&lt;&#x2F;span&gt;u{202F}&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-expression z-typst&quot;&gt;&lt;span class=&quot;z-constant z-other z-symbol z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-typst&quot;&gt;#&lt;&#x2F;span&gt;sym.dash&lt;span class=&quot;z-punctuation z-accessor z-typst&quot;&gt;.&lt;&#x2F;span&gt;em&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape z-typst&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-backslash z-typst&quot;&gt;\&lt;&#x2F;span&gt;u{202F}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-typst&quot;&gt;]&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The trick is that the text selector, &lt;code&gt;&quot; — &quot;&lt;&#x2F;code&gt;, should match the &lt;em&gt;rendered&lt;&#x2F;em&gt; text (an em-dash character) and not the &lt;em&gt;written&lt;&#x2F;em&gt; text (&lt;code&gt;---&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;Typst’s show rules are incredibly powerful. With &lt;code&gt;show regex(&quot;...&quot;)&lt;&#x2F;code&gt; I should also be able to render acronyms and initialisms in small-caps without having to wrap each instance in &lt;code&gt;smallcaps()&lt;&#x2F;code&gt;. That’s next on my to-do list. &lt;em&gt;[Edit: &lt;a href=&quot;https:&#x2F;&#x2F;www.flother.is&#x2F;til&#x2F;typst-acronyms-economist-style&#x2F;&quot; title=&quot;Automatically formatting acronyms in Typst&quot;&gt;done!&lt;&#x2F;a&gt;]&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</content>
  </entry>
  
  <entry xml:lang="en-GB">
    <title>How Leicester City failed to reach 100 points</title>
    <published>2024-06-05T00:00:00+00:00</published>
    <updated>2024-06-05T00:00:00+00:00</updated>
    <link href="https://www.flother.is/blog/leicester-city-championship-106-points/" type="text/html"/>
    <id>https://www.flother.is/blog/leicester-city-championship-106-points/</id>
    
    <content type="html">&lt;p&gt;It was a season of emotional highs and baffling lows for Leicester City Football Club. From the heartbreak of Premier League relegation to the euphoria of clinching the Championship title, the Foxes’ 2023&#x2F;24 campaign had it all. While their charge for the title seemed destined to break records, an unexpected slump dashed those dreams, leaving them nine points shy of the all-time Championship high. As Leicester City fans celebrate promotion and a fresh managerial search begins, let’s explore how close — and how far — they came to making history.&lt;&#x2F;p&gt;
&lt;p&gt;At one stage, it appeared Leicester City would &lt;a href=&quot;https:&#x2F;&#x2F;www.bbc.com&#x2F;sport&#x2F;football&#x2F;67818350&quot;&gt;march effortlessly to the title&lt;&#x2F;a&gt;, poised to shatter the points record in the process. But a poor run of form saw them finish with 97 points, far short of Reading’s 2005&#x2F;06 record of 106 points.&lt;&#x2F;p&gt;
&lt;p&gt;Five teams have won the Championship&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; with more than 100 points: record-holders Reading, Sunderland in 1998&#x2F;99 (105 pts), Newcastle United in 2009&#x2F;10 (102 pts), Leicester City themselves in 2013&#x2F;14 (102 pts), and Fulham in 2000&#x2F;01 (101 pts). Comparing this season’s Foxes to these teams, it becomes clear where Leicester fell short.&lt;&#x2F;p&gt;
&lt;div id=&quot;viz-100-points&quot;&gt;
  &lt;em&gt;
    [You’ll need to enable JavaScript to view this data visualisation.]
  &lt;&#x2F;em&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Leicester City were neck-and-neck with Reading for the first two-thirds of the season. But things started to go wrong on matchday 33, when they hit a rough patch, losing four of their next six games. In their final 14 games they managed just 19 points — a meagre 1.36 points per game. In contrast, Reading maintained an average of 1.93 points per game. Although they won the league, the Foxes’ season fizzled out, culminating in the &lt;a href=&quot;https:&#x2F;&#x2F;www.theguardian.com&#x2F;football&#x2F;article&#x2F;2024&#x2F;jun&#x2F;03&#x2F;chelsea-confirm-enzo-maresca-appointment-head-coach&quot;&gt;departure of manager Enzo Maresca&lt;&#x2F;a&gt; after just twelve months, as he took the job at Chelsea (&lt;a href=&quot;https:&#x2F;&#x2F;www.theguardian.com&#x2F;football&#x2F;article&#x2F;2024&#x2F;may&#x2F;28&#x2F;todd-boehly-chelsea-enzo-maresca&quot;&gt;lol&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;In fact, if we look at how many points Leicester City won per game, using a five-game rolling average, we can see they had more than one dip along the way.&lt;&#x2F;p&gt;
&lt;div id=&quot;viz-rolling-points&quot;&gt;
  &lt;em&gt;
    [You’ll need to enable JavaScript to view this data visualisation.]
  &lt;&#x2F;em&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Title-winning form was 2.1 points per game (equal to 97 points over 46 games). Using the five-game rolling average, Leicester droped below this level three times, in October, December, and February. Playoff form was 1.6 points per game (equal to sixth-placed Norwich’s 73 points), and Leicester dropped below this level in November and February. Worst of all, Leicester even fell into relegation form (1.1 points per game, equal to 22nd-placed Birmingham City’s 50 points) in March. They eventually recovered, but it was too late to break the 100-point barrier.&lt;&#x2F;p&gt;
&lt;p&gt;Despite all that, City finish champions and will be back in the Premier League next season. Yes, alright, so the search is on for a new manager, and a points deduction is likely, but the promised land of the Premier League awaits. Roll on 2024&#x2F;25.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;I’m using ‘Championship’ as shorthand for the second tier of English football that’s existed since the 1992&#x2F;93 season. Since then it’s consistently had 24 teams and a win has counted for three points. (Honestly, the English football divisions have nonsense names only a marketing guru could love. The top tier is the Premier League, below that is the Championship, and then comes the third tier known, inexplicably, as League One.)&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
  </entry>
  
  <entry xml:lang="en-GB">
    <title>Election fever in Iceland: a presidential race too close to call</title>
    <published>2024-05-24T00:00:00+00:00</published>
    <updated>2024-05-24T00:00:00+00:00</updated>
    <link href="https://www.flother.is/blog/iceland-presidential-election/" type="text/html"/>
    <id>https://www.flother.is/blog/iceland-presidential-election/</id>
    
    <content type="html">&lt;p&gt;On 1 June Icelanders will go to the polls to elect their next president. The contest feels fresh but familiar at the same time: while the incumbent, Guðni Th, said in January he wouldn’t stand for a third term, most of the candidates are household names. Katrín Jakobsdóttir was, until a few weeks ago, prime minister; Jón Gnarr is a former mayor of Reykjavik; Ástþór Magnússon is attempting to take office at the fifth attempt.&lt;&#x2F;p&gt;
&lt;p&gt;Several polling companies are tracking the contest: Maskína, Prósent, and Gallup are releasing opinion polls roughly once a week. But while they may know how to conduct a poll, the pollsters (and journalists) are generally poor at presenting the data. Some examples: &lt;a href=&quot;https:&#x2F;&#x2F;www.ruv.is&#x2F;frettir&#x2F;innlent&#x2F;2024-05-17-katrin-og-halla-hrund-laekka-en-halla-tomasdottir-haekkar-mest-i-nyjum-thjodarpuls-413006&quot;&gt;obnoxious animations&lt;&#x2F;a&gt;, a &lt;a href=&quot;https:&#x2F;&#x2F;www.ruv.is&#x2F;frettir&#x2F;innlent&#x2F;2024-05-10-katrin-og-halla-hrund-maelast-hnifjafnar-412431&quot;&gt;lack of interest in communicating standard error&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;www.visir.is&#x2F;g&#x2F;20242567866d&#x2F;halla-hrund-a-fram-efst&quot;&gt;unreadable charts&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;www.visir.is&#x2F;g&#x2F;20242562589d&#x2F;halla-hrund-maelist-med-mest-fylgi-allra-fram-bjod-enda&quot;&gt;terrible x-axes&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;www.ruv.is&#x2F;frettir&#x2F;innlent&#x2F;2024-04-12-litlu-munar-a-milli-katrinar-og-baldurs-i-nyjustu-konnun-gallup-410122&quot;&gt;throwing too much information in&lt;&#x2F;a&gt;, and &lt;a href=&quot;https:&#x2F;&#x2F;www.ruv.is&#x2F;frettir&#x2F;innlent&#x2F;2024-05-21-i-fyrsta-skipti-sem-prosent-maelir-katrinu-efsta-413249&quot;&gt;only showing the latest data&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;That was all the excuse I needed to track the contest myself. My goals were to use all the polling data to visualise the trends over time, and to understand how close the race really is.&lt;&#x2F;p&gt;

    
    
  
  &lt;figure&gt;
  
  &lt;img alt=&quot;Line chart showing voting intention for Iceland’s presidential election in 2024. It depicts a tight four-way race between five candidates who can claim more than 10% support&quot; src=&quot;https:&amp;#x2F;&amp;#x2F;www.flother.is&amp;#x2F;processed_images&amp;#x2F;poll-of-polls.a86fc2698e546fef.png&quot; srcset=&quot;https:&amp;#x2F;&amp;#x2F;www.flother.is&amp;#x2F;processed_images&amp;#x2F;poll-of-polls.0e0e00a5822b7a57.png 2x&quot; height=&quot;600&quot; width=&quot;800&quot; loading=&quot;lazy&quot;&gt;
  
  
&lt;&#x2F;figure&gt;
&lt;p&gt;Baldur was the early favourite, commanding 35% support in late March, but his support steadily declined once other candidates entered the fray. Halla Hrund, initially polling in the single digits, surged to 30% in early May, but has faded since. Halla T, who began May with just 5% support, has seen her numbers quadruple and has jumped into second place. Katrín, meanwhile, has seen a drop in her support overall but looks to be the frontrunner in a close race.&lt;&#x2F;p&gt;
&lt;p&gt;The semi-transparent areas around the chart’s lines show how uncertain we are about the data. The central line confidently states that Katrín is at 25%, but the area around it shows us that really — given the spread and sparsity of the polling data — she could be as high as 32% or as low as 17%. That’s the difference between winning and being an also-ran. In order to see how close the race is right now, we should take a look at the latest polling averages.&lt;&#x2F;p&gt;

    
    
  
  &lt;figure&gt;
  
  &lt;img alt=&quot;Bar chart showing the latest polling averages for the six major candidates in Iceland’s presidential race. Each candidate has a horizontal bar representing their polling range, with a point indicating their average support percentage. Katrín Jakobsdóttir leads with a range close to 25%, followed by Halla Tómasdóttir and Baldur Þórhallsson around 15%, Halla Hrund Logadóttir and Jón Gnarr around 10%, and Arnar Þór Jónsson close to 5%.&quot; src=&quot;https:&amp;#x2F;&amp;#x2F;www.flother.is&amp;#x2F;processed_images&amp;#x2F;polling-averages.1e1f6f6ab157f279.png&quot; srcset=&quot;https:&amp;#x2F;&amp;#x2F;www.flother.is&amp;#x2F;processed_images&amp;#x2F;polling-averages.98414e1b4c1ce5ff.png 2x&quot; height=&quot;600&quot; width=&quot;800&quot; loading=&quot;lazy&quot;&gt;
  
  
&lt;&#x2F;figure&gt;
&lt;p&gt;It’s fair to say Katrín has a substantial lead. But the range of uncertainty around her support should give her pause for concern. Halla T, Baldur, and Halla Hrund are virtually neck-and-neck, and all close enough to Katrín to make this a four-way race. With just a week to go then, the only prediction I would make it that the outcome is unpredictable. It may all come down to Halla T’s recent surge in support. Can she catch Katrín? We’ll find out in a few short days.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;update-31-may-2024&quot;&gt;Update, 31 May 2024&lt;&#x2F;h3&gt;
&lt;p&gt;The charts above are a snapshot of the race as it was on 24 May, but of course polls have continued to be published since. Here are updated charts with the latest polling data on the eve of the election. The race has got &lt;em&gt;even&lt;&#x2F;em&gt; tighter! It’s a three-way race now: Halla T has &lt;em&gt;just&lt;&#x2F;em&gt; pipped Katrín to first place, but it’s neck-and-neck. Halla Hrund is still just about keeping up with them.&lt;&#x2F;p&gt;

    
    
  
  &lt;figure&gt;
  
  &lt;img alt=&quot;Line chart showing voting intention for Iceland’s presidential election as of 31 May 2024. It shows a tight three-way race between the top candidates&quot; src=&quot;https:&amp;#x2F;&amp;#x2F;www.flother.is&amp;#x2F;processed_images&amp;#x2F;poll-of-all-polls.3e8d17b5cabf6230.png&quot; srcset=&quot;https:&amp;#x2F;&amp;#x2F;www.flother.is&amp;#x2F;processed_images&amp;#x2F;poll-of-all-polls.f37ff7a8676aecf7.png 2x&quot; height=&quot;600&quot; width=&quot;800&quot; loading=&quot;lazy&quot;&gt;
  
  
&lt;&#x2F;figure&gt;

    
    
  
  &lt;figure&gt;
  
  &lt;img alt=&quot;Bar chart showing polling averages as of 31 May 2024. Katrín leads, followed closely by Halla T and Halla Hrund&quot; src=&quot;https:&amp;#x2F;&amp;#x2F;www.flother.is&amp;#x2F;processed_images&amp;#x2F;polling-averages-final.3bebd788877e17d0.png&quot; srcset=&quot;https:&amp;#x2F;&amp;#x2F;www.flother.is&amp;#x2F;processed_images&amp;#x2F;polling-averages-final.206ee2518e203ce0.png 2x&quot; height=&quot;600&quot; width=&quot;800&quot; loading=&quot;lazy&quot;&gt;
  
  
&lt;&#x2F;figure&gt;
&lt;h3 id=&quot;update-4-june-2024&quot;&gt;Update, 4 June 2024&lt;&#x2F;h3&gt;
&lt;p&gt;Well, the results are in and it was a resounding win for Halla Tómasdóttir. She collected over 34% of the vote — nine percentage points ahead of second place — and she surpassed the expectations of opinion polls, even those published closest to the vote.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;alastaircampbell.org&quot;&gt;Alastair Campbell&lt;&#x2F;a&gt; likes to call opinion polls ‘the junk food of journalism’, but I think they had a spectacular and direct effect on this election. Halla T won this election in large part &lt;em&gt;because&lt;&#x2F;em&gt; of the opinion polls. People love to back a winner, and on top of that there was a &lt;a href=&quot;https:&#x2F;&#x2F;www.icelandreview.com&#x2F;news&#x2F;new-presidential-poll-takes-a-different-angle&#x2F;&quot;&gt;substantial group that didn’t want Katrín to be president&lt;&#x2F;a&gt;. That meant that when the polls showed Halla T to be on an upward trend and the candidate best-placed to beat Katrín, people decided to back her instead of their preferred candidate (largely, by the looks of things, Halla Hrund and Baldur). I don’t think Halla T’s surge would have been possible without the opinion polls. So, although they got it wrong, I think the opinion polls were decisive in this election.&lt;&#x2F;p&gt;

    
    
  
  &lt;figure&gt;
  
  &lt;img alt=&quot;&quot; src=&quot;https:&amp;#x2F;&amp;#x2F;www.flother.is&amp;#x2F;processed_images&amp;#x2F;polls-vs-votes.8f3b6d58c61b8a17.png&quot; srcset=&quot;https:&amp;#x2F;&amp;#x2F;www.flother.is&amp;#x2F;processed_images&amp;#x2F;polls-vs-votes.5555aa5dd5ce9688.png 2x&quot; height=&quot;600&quot; width=&quot;800&quot; loading=&quot;lazy&quot;&gt;
  
  
&lt;&#x2F;figure&gt;
</content>
  </entry>
  
  <entry xml:lang="en-GB">
    <title>How to use DuckDB’s ST_Read function to read and convert zipped shapefiles</title>
    <published>2024-04-04T00:00:00+00:00</published>
    <updated>2024-04-04T00:00:00+00:00</updated>
    <link href="https://www.flother.is/til/duckdb-st-read/" type="text/html"/>
    <id>https://www.flother.is/til/duckdb-st-read/</id>
    
    <content type="html">&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;duckdb.org&#x2F;&quot;&gt;DuckDB&lt;&#x2F;a&gt; is a (relatively) new RDBMS designed for in-process analytical queries, but really it’s useful for all kinds of things. As a database it’s most similar to SQLite, but DuckDB’s killer feature for me is that it comes with a &lt;a href=&quot;https:&#x2F;&#x2F;duckdb.org&#x2F;docs&#x2F;extensions&#x2F;spatial.html&quot;&gt;spatial extension&lt;&#x2F;a&gt;. That makes it really approachable for geospatial data processing — think PostgreSQL + PostGIS but without the hassle of running a server.&lt;&#x2F;p&gt;
&lt;p&gt;DuckDB’s spatial extension provides an &lt;a href=&quot;https:&#x2F;&#x2F;duckdb.org&#x2F;docs&#x2F;extensions&#x2F;spatial.html#st_read--read-spatial-data-from-files&quot;&gt;&lt;code&gt;ST_Read&lt;&#x2F;code&gt; function&lt;&#x2F;a&gt; that lets you read spatial data from various file formats as if they were database tables. All that’s need to query a GeoJSON file named &lt;code&gt;source.geojson&lt;&#x2F;code&gt; is:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sql&quot; class=&quot;language-sql z-code&quot;&gt;&lt;code class=&quot;language-sql&quot; data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;z-source z-sql&quot;&gt;INSTALL spatial; &lt;span class=&quot;z-comment z-line z-double-dash z-sql&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-sql&quot;&gt;--&lt;&#x2F;span&gt; You only need to install it once.
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-sql&quot;&gt;LOAD spatial;    &lt;span class=&quot;z-comment z-line z-double-dash z-sql&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-sql&quot;&gt;--&lt;&#x2F;span&gt; But you need to load it each session.
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-sql&quot;&gt;&lt;span class=&quot;z-keyword z-other z-DML z-sql&quot;&gt;SELECT&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-language z-star z-sql&quot;&gt;*&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-other z-DML z-sql&quot;&gt;FROM&lt;&#x2F;span&gt; ST_Read(&lt;span class=&quot;z-string z-quoted z-single z-sql&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-sql&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;source.geojson&lt;span class=&quot;z-punctuation z-definition z-string z-end z-sql&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Under the hood, &lt;code&gt;ST_Read&lt;&#x2F;code&gt; uses &lt;a href=&quot;https:&#x2F;&#x2F;gdal.org&#x2F;&quot;&gt;GDAL&lt;&#x2F;a&gt;, which means DuckDB supports a huge number of &lt;a href=&quot;https:&#x2F;&#x2F;gdal.org&#x2F;drivers&#x2F;vector&#x2F;index.html&quot;&gt;vector file formats&lt;&#x2F;a&gt;. It also means that DuckDB supports GDAL’s more esoteric features, such as &lt;a href=&quot;https:&#x2F;&#x2F;gdal.org&#x2F;user&#x2F;virtual_file_systems.html&quot;&gt;virtual file systems&lt;&#x2F;a&gt;. The &lt;a href=&quot;https:&#x2F;&#x2F;gdal.org&#x2F;user&#x2F;virtual_file_systems.html#vsizip-zip-archives&quot;&gt;&lt;code&gt;&#x2F;vsizip&#x2F;&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; prefix, for example, lets you &lt;code&gt;SELECT&lt;&#x2F;code&gt; from a file within a ZIP file, decompressing it on-the-fly. Shapefiles are often distributed as ZIP files (because a ‘shapefile’ is usually several files), and it can be annoying to need two steps to get to the file. But using &lt;code&gt;&#x2F;vsizip&#x2F;&lt;&#x2F;code&gt; lets you query geospatial data directly from a ZIP file. Here’s how you could query a shapefile named &lt;code&gt;bar.shp&lt;&#x2F;code&gt; within a ZIP file named &lt;code&gt;foo.zip&lt;&#x2F;code&gt;, removing any features that don’t cover a point in Australia:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sql&quot; class=&quot;language-sql z-code&quot;&gt;&lt;code class=&quot;language-sql&quot; data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;z-source z-sql&quot;&gt;&lt;span class=&quot;z-keyword z-other z-DML z-sql&quot;&gt;SELECT&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-sql&quot;&gt;    &lt;span class=&quot;z-variable z-language z-star z-sql&quot;&gt;*&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-sql&quot;&gt;&lt;span class=&quot;z-keyword z-other z-DML z-sql&quot;&gt;FROM&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-sql&quot;&gt;    ST_Read(&lt;span class=&quot;z-string z-quoted z-single z-sql&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-sql&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&#x2F;vsizip&#x2F;foo.zip&#x2F;bar.shp&lt;span class=&quot;z-punctuation z-definition z-string z-end z-sql&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-sql&quot;&gt;&lt;span class=&quot;z-keyword z-other z-DML z-sql&quot;&gt;WHERE&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-sql&quot;&gt;    ST_Covers(geom, ST_Point(&lt;span class=&quot;z-constant z-numeric z-sql&quot;&gt;128&lt;&#x2F;span&gt;.&lt;span class=&quot;z-constant z-numeric z-sql&quot;&gt;28&lt;&#x2F;span&gt;, &lt;span class=&quot;z-keyword z-operator z-math z-sql&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-sql&quot;&gt;21&lt;&#x2F;span&gt;.&lt;span class=&quot;z-constant z-numeric z-sql&quot;&gt;69&lt;&#x2F;span&gt;));
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;DuckDB’s spatial extension includes a &lt;a href=&quot;https:&#x2F;&#x2F;duckdb.org&#x2F;docs&#x2F;extensions&#x2F;spatial.html#spatial-copy-functions&quot;&gt;&lt;code&gt;COPY&lt;&#x2F;code&gt; function&lt;&#x2F;a&gt; to export geospatial tables to different formats. This works on &lt;code&gt;ST_Read&lt;&#x2F;code&gt; virtual tables, which means you can convert a zipped shapefile to, for example, a GeoJSON file in a single query:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sql&quot; class=&quot;language-sql z-code&quot;&gt;&lt;code class=&quot;language-sql&quot; data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;z-source z-sql&quot;&gt;COPY ⟨
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-sql&quot;&gt;    &lt;span class=&quot;z-keyword z-other z-DML z-sql&quot;&gt;SELECT&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-language z-star z-sql&quot;&gt;*&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-other z-DML z-sql&quot;&gt;FROM&lt;&#x2F;span&gt; ST_Read(&lt;span class=&quot;z-string z-quoted z-single z-sql&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-sql&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&#x2F;vsizip&#x2F;foo.zip&#x2F;bar.shp&lt;span class=&quot;z-punctuation z-definition z-string z-end z-sql&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-sql&quot;&gt;⟩
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-sql&quot;&gt;TO &lt;span class=&quot;z-string z-quoted z-single z-sql&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-sql&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;some_file.geojson&lt;span class=&quot;z-punctuation z-definition z-string z-end z-sql&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-sql&quot;&gt;&lt;span class=&quot;z-keyword z-other z-DML z-sql&quot;&gt;WITH&lt;&#x2F;span&gt; (FORMAT GDAL, DRIVER &lt;span class=&quot;z-string z-quoted z-single z-sql&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-sql&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;GeoJSON&lt;span class=&quot;z-punctuation z-definition z-string z-end z-sql&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And of course the &lt;code&gt;SELECT&lt;&#x2F;code&gt; sub-query can be as complicated as you need it to be, filtering out data as you go.&lt;&#x2F;p&gt;
</content>
  </entry>
  
  <entry xml:lang="en-GB">
    <title>What audio formats are supported by Raylib?</title>
    <published>2023-09-20T00:00:00+00:00</published>
    <updated>2023-09-20T00:00:00+00:00</updated>
    <link href="https://www.flother.is/til/raylib-audio-files/" type="text/html"/>
    <id>https://www.flother.is/til/raylib-audio-files/</id>
    
    <content type="html">&lt;p&gt;A couple of weeks ago &lt;a href=&quot;http:&#x2F;&#x2F;borgar.net&#x2F;&quot;&gt;a friend&lt;&#x2F;a&gt; convinced me, without much difficulty as it happens, that making games in &lt;a href=&quot;https:&#x2F;&#x2F;go.dev&#x2F;&quot;&gt;Go&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;www.raylib.com&#x2F;&quot;&gt;Raylib&lt;&#x2F;a&gt; is an enjoyable way to spend your free time. I started off by recreating that stalwart of the 1970s, &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Pong&quot;&gt;Pong&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Raylib’s documentation is as minimal as it gets. There’s a dense &lt;a href=&quot;https:&#x2F;&#x2F;www.raylib.com&#x2F;cheatsheet&#x2F;cheatsheet.html&quot;&gt;cheatsheet&lt;&#x2F;a&gt; and a suggestion that if you want to learn you should read &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;raysan5&#x2F;raylib&quot;&gt;the code&lt;&#x2F;a&gt;. And so, when I wanted to add some sound to the game, these were the first places I went to find out which audio formats are supported. The cheatsheet wasn’t much use: it simply tells you that you can load sound from a file using &lt;code&gt;LoadSound&lt;&#x2F;code&gt;, or load wave data from &lt;code&gt;LoadSoundFromWave&lt;&#x2F;code&gt;. So off to GitHub I went.&lt;&#x2F;p&gt;
&lt;p&gt;From there it was pretty easy to discover what’s available. In &lt;code&gt;src&#x2F;config.h&lt;&#x2F;code&gt; there are &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;raysan5&#x2F;raylib&#x2F;blob&#x2F;c9020ece5da5dcb4760b32080fdeddbba96d885c&#x2F;src&#x2F;config.h#L218-L225&quot;&gt;some configuration flags&lt;&#x2F;a&gt; that hint at the supported audio formats:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;WAV&quot;&gt;Waveform Audio File Format&lt;&#x2F;a&gt; (&lt;code&gt;.wav&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;xiph.org&#x2F;vorbis&#x2F;&quot;&gt;Ogg Vorbis&lt;&#x2F;a&gt; (&lt;code&gt;.ogg&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;MP3&quot;&gt;MP3&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;qoaformat.org&#x2F;&quot;&gt;Quite OK Audio&lt;&#x2F;a&gt; (&lt;code&gt;.qoa&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;XM_(file_format)&quot;&gt;XM&lt;&#x2F;a&gt; (&lt;code&gt;.xm&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;MOD_(file_format)&quot;&gt;MOD music&lt;&#x2F;a&gt; (&lt;code&gt;.mod&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;xiph.org&#x2F;flac&#x2F;&quot;&gt;Free Lossless Audio Codec&lt;&#x2F;a&gt; (FLAC, &lt;code&gt;.flac&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Raylib supports the first six by default, but support for FLAC isn’t included unless you compile it in yourself. If you want it, you’ll need a customised build with the &lt;code&gt;SUPPORT_FILEFORMAT_FLAC&lt;&#x2F;code&gt; flag turned on. Try to play a FLAC file without it and Raylib will log an error:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;WARNING: WAVE: Data format not supported
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Of course, after all that I discovered that this is briefly &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;raysan5&#x2F;raylib&#x2F;blob&#x2F;master&#x2F;FAQ.md#what-file-formats-are-supported-by-raylib&quot;&gt;documented in the FAQ&lt;&#x2F;a&gt; and in the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;raysan5&#x2F;raudio&#x2F;blob&#x2F;master&#x2F;README.md&quot;&gt;&lt;code&gt;raudio&lt;&#x2F;code&gt; module README&lt;&#x2F;a&gt;. Today I learnt that if someone promises minimal documentation, you shouldn’t take their word for it.&lt;&#x2F;p&gt;
</content>
  </entry>
  
  <entry xml:lang="en-GB">
    <title>When was Red Dwarf at its best?</title>
    <published>2023-08-31T00:00:00+00:00</published>
    <updated>2023-08-31T00:00:00+00:00</updated>
    <link href="https://www.flother.is/blog/red-dwarf/" type="text/html"/>
    <id>https://www.flother.is/blog/red-dwarf/</id>
    
    <content type="html">&lt;p&gt;The cult BBC sitcom &lt;a href=&quot;https:&#x2F;&#x2F;reddwarf.co.uk&#x2F;guide&#x2F;&quot;&gt;Red Dwarf&lt;&#x2F;a&gt; played a large part in my teenage years. I watched every episode over and over on VHS, quoted the best lines, read the books. But the long gap between series VI (1993) and series VII (1997) meant that eventually I ended up moving on to other obsessions.&lt;&#x2F;p&gt;
&lt;p&gt;Recently I discovered that, although I gave up on it after series VI, they carried on and made a lot more episodes. All the way up to series XIII&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; in fact. Turns out I’ve only seen around half of Red Dwarf, which was all the excuse I needed to a) wallow in nostalgia and watch the old episodes, and b) catch up with the new.&lt;&#x2F;p&gt;
&lt;p&gt;The first six series were as good as I remembered: dated, but still good fun. The seventh series seemed like a stark drop in quality though. And that made me wonder, was it just the nostalgia that made the early episodes the best? Did everyone feel the same as me? Would it get better after the series VII lull?&lt;&#x2F;p&gt;
&lt;p&gt;Time to make some data viz&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, lickety-split.&lt;&#x2F;p&gt;
&lt;div id=&quot;viz&quot;&gt;&lt;em&gt;[You’ll need to enable JavaScript to view this data visualisation.]&lt;&#x2F;em&gt;&lt;&#x2F;div&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.imdb.com&#x2F;title&#x2F;tt0094535&#x2F;&quot; title=&quot;Red Dwarf on IMDb&quot;&gt;IMDb&lt;&#x2F;a&gt; has crowd-sourced ratings for each episode. In the chart above you can see the ratings grouped by series, along with the mean average rating for each series and Red Dwarf as a whole&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#3&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. It seems the users of IMDb agree with me: the ratings suggest that after finding its feet in series I, Red Dwarf hits its long and consistent peak in series II-VI. Series VII sees the start of a decline that hits its nadir in ‘Back to Earth’ (aka series IX). After that series X regains some of the show’s mojo, and then fades slightly over time — although not before hitting the high of series XII episode 6, ‘Skipper’, IMDb’s joint-tenth favourite episode.&lt;&#x2F;p&gt;
&lt;p&gt;And the highest rated episode? That would be series V’s ‘Back to Reality’ from 1992 (although personally I have a soft spot for series I’s ‘Me²’, which really lays bare Rimmer’s self-hatred).&lt;&#x2F;p&gt;
&lt;p&gt;So it seems that the crowd-sourced story is that Red Dwarf was indeed at its peak in the late 80s and early 90s and, apart from the odd episode here and there, hasn’t reached that high again. But then perhaps we’re all just sentimental and longing for days past, our memories muddied by nostalgia. I haven’t yet watched any of series IX–XIII, so I’ll try and keep an open mind.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;top-ten-episodes-of-red-dwarf-according-to-imdb&quot;&gt;Top ten episodes of Red Dwarf (according to IMDb)&lt;&#x2F;h2&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: right&quot;&gt;&lt;&#x2F;th&gt;&lt;th&gt;Episode&lt;&#x2F;th&gt;&lt;th&gt;Title&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Rating&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: right&quot;&gt;1&lt;&#x2F;td&gt;&lt;td&gt;S05 E06&lt;&#x2F;td&gt;&lt;td&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.bbc.co.uk&#x2F;iplayer&#x2F;episode&#x2F;p00bplb0&#x2F;red-dwarf-v-6-back-to-reality&quot;&gt;Back to Reality&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;9.2&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: right&quot;&gt;2&lt;&#x2F;td&gt;&lt;td&gt;S05 E04&lt;&#x2F;td&gt;&lt;td&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.bbc.co.uk&#x2F;iplayer&#x2F;episode&#x2F;p00bpl70&#x2F;red-dwarf-v-4-quarantine&quot;&gt;Quarantine&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;8.9&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: right&quot;&gt;3&lt;&#x2F;td&gt;&lt;td&gt;S03 E03&lt;&#x2F;td&gt;&lt;td&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.bbc.co.uk&#x2F;iplayer&#x2F;episode&#x2F;p00bp2y3&#x2F;red-dwarf-iii-3-polymorph&quot;&gt;Polymorph&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;8.8&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: right&quot;&gt;4&lt;&#x2F;td&gt;&lt;td&gt;S02 E05&lt;&#x2F;td&gt;&lt;td&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.bbc.co.uk&#x2F;iplayer&#x2F;episode&#x2F;p00bp2lz&#x2F;red-dwarf-ii-5-queeg&quot;&gt;Queeg&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;8.7&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: right&quot;&gt;-&lt;&#x2F;td&gt;&lt;td&gt;S06 E02&lt;&#x2F;td&gt;&lt;td&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.bbc.co.uk&#x2F;iplayer&#x2F;episode&#x2F;p00bplf6&#x2F;red-dwarf-vi-2-legion&quot;&gt;Legion&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;8.7&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: right&quot;&gt;6&lt;&#x2F;td&gt;&lt;td&gt;S04 E05&lt;&#x2F;td&gt;&lt;td&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.bbc.co.uk&#x2F;iplayer&#x2F;episode&#x2F;p00bp2rm&#x2F;red-dwarf-iv-5-dimension-jump&quot;&gt;Dimension Jump&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;8.6&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: right&quot;&gt;-&lt;&#x2F;td&gt;&lt;td&gt;S06 E03&lt;&#x2F;td&gt;&lt;td&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.bbc.co.uk&#x2F;iplayer&#x2F;episode&#x2F;p00bplhd&#x2F;red-dwarf-vi-3-gunmen-of-the-apocalypse&quot;&gt;Gunmen of the Apocalypse&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;8.6&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: right&quot;&gt;8&lt;&#x2F;td&gt;&lt;td&gt;S03 E01&lt;&#x2F;td&gt;&lt;td&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.bbc.co.uk&#x2F;iplayer&#x2F;episode&#x2F;p00bp2vg&#x2F;red-dwarf-iii-1-backwards&quot;&gt;Backwards&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;8.5&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: right&quot;&gt;-&lt;&#x2F;td&gt;&lt;td&gt;S04 E03&lt;&#x2F;td&gt;&lt;td&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.bbc.co.uk&#x2F;iplayer&#x2F;episode&#x2F;p00bp2p7&#x2F;red-dwarf-iv-3-justice&quot;&gt;Justice&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;8.5&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: right&quot;&gt;10&lt;&#x2F;td&gt;&lt;td&gt;S02 E02&lt;&#x2F;td&gt;&lt;td&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.bbc.co.uk&#x2F;iplayer&#x2F;episode&#x2F;p00bp2hb&#x2F;red-dwarf-ii-2-better-than-life&quot;&gt;Better than Life&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;8.4&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: right&quot;&gt;-&lt;&#x2F;td&gt;&lt;td&gt;S03 E02&lt;&#x2F;td&gt;&lt;td&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.bbc.co.uk&#x2F;iplayer&#x2F;episode&#x2F;b0077s1y&#x2F;red-dwarf-iii-2-marooned&quot;&gt;Marooned&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;8.4&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: right&quot;&gt;-&lt;&#x2F;td&gt;&lt;td&gt;S04 E04&lt;&#x2F;td&gt;&lt;td&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.bbc.co.uk&#x2F;iplayer&#x2F;episode&#x2F;p00bp2qk&#x2F;red-dwarf-iv-4-white-hole&quot;&gt;White Hole&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;8.4&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: right&quot;&gt;-&lt;&#x2F;td&gt;&lt;td&gt;S12 E06&lt;&#x2F;td&gt;&lt;td&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.bbc.co.uk&#x2F;iplayer&#x2F;episode&#x2F;p090v3vq&#x2F;red-dwarf-xii-6-skipper&quot;&gt;Skipper&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;8.4&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;The Roman numerals aren’t my affectation, they’ve long been used to number Red Dwarf series.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;This is the first visualisation I’ve published here using &lt;a href=&quot;https:&#x2F;&#x2F;observablehq.com&#x2F;plot&#x2F;&quot;&gt;Observable Plot&lt;&#x2F;a&gt;, a JavaScript library for visualising tabular data. Usually I make my charts in R and &lt;a href=&quot;https:&#x2F;&#x2F;ggplot2.tidyverse.org&quot;&gt;ggplot2&lt;&#x2F;a&gt;, but this time I thought I’d try something different. Both have their pros and cons, but I think Observable Plot is more suitable to this kind of one-off Web-based vector visualisation.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;3&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;The ratings were collected on the 30th of August 2023. Who knows how they’ve changed since. I mean, you can’t predict the future, can you? Can you, Cassandra?&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
  </entry>
  
  <entry xml:lang="en-GB">
    <title>How to use JSDoc to add type contraints to generic function arguments</title>
    <published>2023-03-23T00:00:00+00:00</published>
    <updated>2023-03-23T00:00:00+00:00</updated>
    <link href="https://www.flother.is/til/typescript-jsdoc-generics/" type="text/html"/>
    <id>https://www.flother.is/til/typescript-jsdoc-generics/</id>
    
    <content type="html">&lt;p&gt;The other day, while working on a Typescript&#x2F;Javascript codebase, I found myself writing a function that took a single argument. That argument might be one of two types, and the function would return an array of the same type. For example, if the function was passed a string, it would return an array of strings. But if the function was passed a number, it would return an array of numbers. I had most of the function written; all that was missing was the type information.&lt;&#x2F;p&gt;
&lt;p&gt;Adding the necessary types would have been no problem in Typescript, where a sprinkling of &lt;a href=&quot;https:&#x2F;&#x2F;www.typescriptlang.org&#x2F;docs&#x2F;handbook&#x2F;2&#x2F;generics.html&quot;&gt;generics&lt;&#x2F;a&gt; would provide the information needed. If we name the function &lt;code&gt;foo&lt;&#x2F;code&gt; and simplify the code it contained, we end up with something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;typescript&quot; class=&quot;language-typescript z-code&quot;&gt;&lt;code class=&quot;language-typescript&quot; data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-type z-declaration z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-type z-ts&quot;&gt;type&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-type z-alias z-ts&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-typeparameters z-begin z-ts&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-ts&quot;&gt;T&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-typeparameters z-end z-ts&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-type z-ts&quot;&gt;T&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-modifier z-ts&quot;&gt;extends&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-type z-primitive z-ts&quot;&gt;string&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-ternary z-ts&quot;&gt;?&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-type z-primitive z-ts&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-tuple z-ts&quot;&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-ternary z-ts&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-type z-primitive z-ts&quot;&gt;number&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-tuple z-ts&quot;&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-ts&quot;&gt;function&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-definition z-function z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;foo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-typeparameters z-begin z-ts&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-ts&quot;&gt;T&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-modifier z-ts&quot;&gt;extends&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-type z-primitive z-ts&quot;&gt;string&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-type z-ts&quot;&gt;|&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-type z-primitive z-ts&quot;&gt;number&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-typeparameters z-end z-ts&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-begin z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;bar&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-annotation z-ts&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-type z-annotation z-ts&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-type z-ts&quot;&gt;T&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-end z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-return z-type z-ts&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-type z-annotation z-ts&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-type z-ts&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-typeparameters z-begin z-ts&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-ts&quot;&gt;T&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-typeparameters z-end z-ts&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-keyword z-control z-conditional z-ts&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-expression z-typeof z-ts&quot;&gt;typeof&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;bar&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-comparison z-ts&quot;&gt;===&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;string&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-flow z-ts&quot;&gt;return&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-array z-literal z-ts&quot;&gt; &lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;a&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;b&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-as z-ts&quot;&gt;as&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-type z-ts&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-typeparameters z-begin z-ts&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-ts&quot;&gt;T&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-typeparameters z-end z-ts&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-conditional z-ts&quot;&gt;else&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-flow z-ts&quot;&gt;return&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-array z-literal z-ts&quot;&gt; &lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-decimal z-ts&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-decimal z-ts&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-as z-ts&quot;&gt;as&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-type z-ts&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-typeparameters z-begin z-ts&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-ts&quot;&gt;T&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-type z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-typeparameters z-end z-ts&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With this code, when I pass a string Typescript would know the result is guaranteed to be an array of strings. And when I pass a number, Typescript would know the result would be an array of numbers.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;typescript&quot; class=&quot;language-typescript z-code&quot;&gt;&lt;code class=&quot;language-typescript&quot; data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;result1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;foo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Hello!&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt; &lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-ts&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt; result1 is a string[]&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;result2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;foo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-decimal z-ts&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt; &lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-ts&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt; result2 is a number[]&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The problem I had was that the function was in a &lt;em&gt;Javascript&lt;&#x2F;em&gt; file, not a &lt;em&gt;Typescript&lt;&#x2F;em&gt; file, and so I needed to type the function using &lt;a href=&quot;https:&#x2F;&#x2F;www.typescriptlang.org&#x2F;docs&#x2F;handbook&#x2F;jsdoc-supported-types.html&quot;&gt;Typescript’s flavour of JSDoc&lt;&#x2F;a&gt;. While this syntax has a lot in common with Typescript, it’s all added above the function in a comment rather than being inline. How exactly should I structure that comment?&lt;&#x2F;p&gt;
&lt;p&gt;I completely failed to find the answer online and instead worked it out by trial and error. Delightfully, the answer ended up being more succinct than the Typescript version:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;js&quot; class=&quot;language-js z-code&quot;&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-comment z-block z-documentation z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-ts&quot;&gt;&#x2F;**&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-comment z-block z-documentation z-ts&quot;&gt; * &lt;span class=&quot;z-storage z-type z-class z-jsdoc&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-tag z-jsdoc&quot;&gt;@&lt;&#x2F;span&gt;template&lt;&#x2F;span&gt; {string | number} T
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-comment z-block z-documentation z-ts&quot;&gt; *
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-comment z-block z-documentation z-ts&quot;&gt; * &lt;span class=&quot;z-storage z-type z-class z-jsdoc&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-tag z-jsdoc&quot;&gt;@&lt;&#x2F;span&gt;param&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-type z-instance z-jsdoc&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-bracket z-curly z-begin z-jsdoc&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-instance z-jsdoc&quot;&gt;T&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-instance z-jsdoc&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-bracket z-curly z-end z-jsdoc&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-jsdoc&quot;&gt;bar&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-comment z-block z-documentation z-ts&quot;&gt; * &lt;span class=&quot;z-storage z-type z-class z-jsdoc&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-tag z-jsdoc&quot;&gt;@&lt;&#x2F;span&gt;returns&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-type z-instance z-jsdoc&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-bracket z-curly z-begin z-jsdoc&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-instance z-jsdoc&quot;&gt;T extends string ? string[] : number[]&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-instance z-jsdoc&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-bracket z-curly z-end z-jsdoc&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-comment z-block z-documentation z-ts&quot;&gt; &lt;span class=&quot;z-punctuation z-definition z-comment z-ts&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-ts&quot;&gt;function&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-definition z-function z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;foo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-begin z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;bar&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-end z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-keyword z-control z-conditional z-ts&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-expression z-typeof z-ts&quot;&gt;typeof&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;bar&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-comparison z-ts&quot;&gt;===&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;string&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-flow z-ts&quot;&gt;return&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-array z-literal z-ts&quot;&gt; &lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;a&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;b&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-conditional z-ts&quot;&gt;else&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-flow z-ts&quot;&gt;return&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-array z-literal z-ts&quot;&gt; &lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-decimal z-ts&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-decimal z-ts&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The constraint on the Typescript function — &lt;code&gt;&amp;lt;T extends string | number&amp;gt;&lt;&#x2F;code&gt; — was replaced by using a &lt;a href=&quot;https:&#x2F;&#x2F;www.typescriptlang.org&#x2F;docs&#x2F;handbook&#x2F;jsdoc-supported-types.html#template&quot;&gt;&lt;code&gt;@template&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; tag, the &lt;code&gt;bar&lt;&#x2F;code&gt; argument was typed using &lt;a href=&quot;https:&#x2F;&#x2F;jsdoc.app&#x2F;tags-param.html&quot;&gt;&lt;code&gt;@param&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, and the return type was just declared directly rather than needing to use a defined type. That in turn removed the need to coerce the return values (&lt;code&gt;return ... as Result&amp;lt;T&amp;gt;&lt;&#x2F;code&gt;). All in all, quite an elegant solution.&lt;&#x2F;p&gt;
</content>
  </entry>
  
  <entry xml:lang="en-GB">
    <title>How to search a GitHub repo using regular expressions or case-sensitive matching</title>
    <published>2023-03-18T00:00:00+00:00</published>
    <updated>2023-03-18T00:00:00+00:00</updated>
    <link href="https://www.flother.is/til/github-repo-regex-case-insensitive-search/" type="text/html"/>
    <id>https://www.flother.is/til/github-repo-regex-case-insensitive-search/</id>
    
    <content type="html">&lt;p&gt;Here’s a little hack I’ve discovered. You’ll need to be logged in to GitHub for this to work, but it’s possible to search a repo using case-sensitive string matching — or even a regular expression — from GitHub’s website.&lt;&#x2F;p&gt;
&lt;p&gt;Here’s a hypothetical (and slightly contrived) example: let’s say you’re browsing through a repo online at &lt;code&gt;https:&#x2F;&#x2F;github.com&#x2F;example&#x2F;foo&lt;&#x2F;code&gt;. There’s a class called &lt;code&gt;Bar&lt;&#x2F;code&gt;, and somewhere in the repo an array of &lt;code&gt;Bar&lt;&#x2F;code&gt; is instantiated. You can’t remember if that array is called &lt;code&gt;bar&lt;&#x2F;code&gt; or &lt;code&gt;bars&lt;&#x2F;code&gt;. The &lt;code&gt;Bar&lt;&#x2F;code&gt; class is used throughout the code so there are a lot of results if you simply search for ‘bar’. You need case-sensitive regex search, but GitHub’s search doesn’t support that.&lt;&#x2F;p&gt;
&lt;p&gt;What you can do, though, is press &lt;code&gt;.&lt;&#x2F;code&gt; (aka full-stop or period) while &lt;code&gt;https:&#x2F;&#x2F;github.com&#x2F;example&#x2F;foo&lt;&#x2F;code&gt; is open in your browser. If you’re logged in this will actually open &lt;code&gt;https:&#x2F;&#x2F;github.dev&#x2F;example&#x2F;foo&lt;&#x2F;code&gt; — that is, &lt;code&gt;github.dev&lt;&#x2F;code&gt; not &lt;code&gt;github.com&lt;&#x2F;code&gt; — and set up Visual Studio Code in your browser. Once that’s ready you can open up VS Code’s &lt;a href=&quot;https:&#x2F;&#x2F;code.visualstudio.com&#x2F;docs&#x2F;editor&#x2F;codebasics#_search-across-files&quot;&gt;search sidebar&lt;&#x2F;a&gt;, turn on case-sensitive matching and regexes, and type &lt;code&gt;bars?&lt;&#x2F;code&gt; into the search box. And &lt;em&gt;voilà&lt;&#x2F;em&gt;, only code that matches &lt;code&gt;bar&lt;&#x2F;code&gt; or &lt;code&gt;bars&lt;&#x2F;code&gt; (in lowercase) will appear in the results.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;update-20th-september-2023&quot;&gt;Update, 20th September 2023&lt;&#x2F;h3&gt;
&lt;p&gt;A few months after I posted this, in May 2023, &lt;a href=&quot;https:&#x2F;&#x2F;github.blog&#x2F;2023-05-08-github-code-search-is-generally-available&#x2F;&quot;&gt;GitHub updated their code search&lt;&#x2F;a&gt; so you can search using a regex directly on github.com. Here’s the &lt;a href=&quot;https:&#x2F;&#x2F;docs.github.com&#x2F;en&#x2F;search-github&#x2F;github-code-search&#x2F;understanding-github-code-search-syntax#using-regular-expressions&quot;&gt;brief documentation&lt;&#x2F;a&gt;. So there’s no need for this hack any more — using the example above you can simply search your repo for &lt;code&gt;&#x2F;bars?&#x2F;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;One glitch in their current implementation is that regexes are &lt;em&gt;only&lt;&#x2F;em&gt; supported in the code search, so you’ll get zero matching results for issues, PRs, wiki pages, etc.&lt;&#x2F;p&gt;
</content>
  </entry>
  
</feed>
