<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Hang Out With J. B. Rainsberger</title>
    <description>Missing Documentation: Help Pages I wish they&apos;d written</description>
    <link>http://jb.rainsberger.ca/</link>
    <atom:link href="http://jb.rainsberger.ca/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Wed, 13 May 2026 18:11:24 +0000</pubDate>
    <lastBuildDate>Wed, 13 May 2026 18:11:24 +0000</lastBuildDate>
    <generator>Jekyll v4.4.1</generator>
    
      <item>
        <title>Why My Webcam Image Is So Damn Red!</title>
        <description>&lt;p&gt;After a brief absence from home, I had a Zoom meeting, so I turned on my webcam and, much to my surprise, everything looked shifted far towards the red! I didn’t find anything in my OBS Studio settings nor in Zoom, but I was late for the meeting, so I had to switch back to my crappy internal webcam until I could sit down to figure out just what happened.&lt;/p&gt;
&lt;h1 id=&quot;just-what-happened&quot;&gt;Just What Happened&lt;/h1&gt;
&lt;p&gt;I used &lt;code&gt;guvcview&lt;/code&gt; to look at the settings of the camera. Fortunately, I have another camera, so I could do some basic A/B testing to isolate the problem. The other camera looked fine. The difference lay in a single setting: Saturation. On the “faulty” camera, it was set to 100; on the “working” camera, it was set to 50.&lt;/p&gt;
&lt;p&gt;I don’t know how that setting was changed. The problem is solved!&lt;/p&gt;
&lt;h1 id=&quot;a-neat-feature&quot;&gt;A Neat Feature&lt;/h1&gt;
&lt;p&gt;The utility &lt;code&gt;guvcview&lt;/code&gt; has the feature to save a profile to a plain text file, so I could save the settings on both cameras, then compare them with &lt;code&gt;meld&lt;/code&gt;. Both cameras have the same settings now, so presumably they behave the same now. Great! I can even put these profiles into a version control repository as a baseline for the next time my camera does something strange.&lt;/p&gt;
&lt;h1 id=&quot;details&quot;&gt;Details&lt;/h1&gt;
&lt;p&gt;The cameras involved are Anker PowerConf C200 cameras and I experienced this problem on Pop!_OS 24.04. I also found a project that threatens to have CLI tools for PowerConf cameras: &lt;a href=&quot;https://github.com/erans/anker-powerconf-c200-linux-tools&quot; class=&quot;uri&quot;&gt;https://github.com/erans/anker-powerconf-c200-linux-tools&lt;/a&gt;. This project bears examining, but I haven’t done that yet.&lt;/p&gt;
</description>
        <pubDate>Wed, 29 Apr 2026 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/why-my-webcam-image-is-so-damn-red</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/why-my-webcam-image-is-so-damn-red</guid>
        
        
      </item>
    
      <item>
        <title>Byobu Session Name in Terminal Window Title</title>
        <description>&lt;p&gt;I started using multiple &lt;code&gt;byobu&lt;/code&gt; windows to organize my projects, but in the process, something annoying happened: I began to lose track of which window was which. When switching windows, I couldn’t tell from the window title which &lt;code&gt;byobu&lt;/code&gt; window to switch to.&lt;/p&gt;
&lt;figure&gt;
&lt;p&gt;
&lt;img src=&quot;/img/set-window-title-in-byobu/windows-look-the-same.png&quot;
style=&quot;width:80.0%&quot; /&gt;
&lt;/p&gt;
&lt;figcaption&gt;
&lt;p&gt;
“Uhh… which one?”
&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Fortunately, I use &lt;code&gt;tmux&lt;/code&gt; as the terminal back-end for &lt;code&gt;byobu&lt;/code&gt;, so I some very elementary &lt;code&gt;tmux&lt;/code&gt; configuration was enable to solve the problem.&lt;/p&gt;
&lt;h1 id=&quot;turn-titles-on-in-tmux&quot;&gt;Turn Titles On in &lt;code&gt;tmux&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;In a &lt;code&gt;tmux&lt;/code&gt; window:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;&lt;p&gt;Press &lt;code&gt;F12&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Type &lt;code&gt;:set -g set-titles on&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Type &lt;code&gt;:set -g set-titles-string &quot;#{session_name} @ #{host_short}:#{pane_current_path}&quot;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;When you reopen the terminal window, you’ll see that the &lt;code&gt;byobu&lt;/code&gt; session name is now at the beginning of the terminal window title, making it easier to see when switching windows.&lt;/p&gt;
&lt;figure&gt;
&lt;p&gt;
&lt;img src=&quot;/img/set-window-title-in-byobu/i-can-find-my-window.png&quot;
style=&quot;width:80.0%&quot; /&gt;
&lt;/p&gt;
&lt;figcaption&gt;
&lt;p&gt;
“A little busy, but good enough for now.”
&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h1 id=&quot;remember-these-settings-forever&quot;&gt;Remember These Settings Forever&lt;/h1&gt;
&lt;p&gt;Edit the &lt;code&gt;.tmux.conf&lt;/code&gt; configuration file. I found mine at &lt;code&gt;$HOME/.config/byobu/.tmux.conf&lt;/code&gt;. Add these lines:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;set -g set-titles on
set -g set-titles-string &amp;quot;#{session_name} @ #{host_short}:#{pane_current_path}&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When you reopen the terminal window, you’ll see that these settings have become yours to keep forever.&lt;/p&gt;
&lt;h1 id=&quot;further-reading&quot;&gt;Further Reading&lt;/h1&gt;
&lt;p&gt;Nothing beats the &lt;code&gt;man&lt;/code&gt; page.&lt;/p&gt;
</description>
        <pubDate>Tue, 17 Mar 2026 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/byobu-session-name-in-terminal-window-title</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/byobu-session-name-in-terminal-window-title</guid>
        
        
      </item>
    
      <item>
        <title>Viewing HEIC (HEIF) Images on Pop! OS 22.04</title>
        <description>&lt;p&gt;Today I was blindsided by the existence of HEIC images, because I don’t often receive images from iPhone/iPad users. Since Pop!_OS is still running Ubuntu 22.04, I not only didn’t have the library I needed to view these images, but when I found the library I needed, the standard package manager had an out-of-date version for the images I was trying to view. It took an hour of stumbling around to track down a solution.&lt;/p&gt;
&lt;h1 id=&quot;the-solution&quot;&gt;The Solution&lt;/h1&gt;
&lt;p&gt;Install the latest version of the &lt;code&gt;libheif&lt;/code&gt; package from the Ubuntu PPA.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ sudo add-apt-repository ppa:strukturag/libheif
$ sudo nala install libheif1 heif-gdk-pixbuf heif-thumbnailer&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&quot;the-symptom&quot;&gt;The Symptom&lt;/h1&gt;
&lt;p&gt;I couldn’t open the HEIC images using &lt;code&gt;eog&lt;/code&gt;, but I &lt;em&gt;could&lt;/em&gt; open them using GIMP. I wanted to convert the images in bulk to JPG, so I didn’t stop at using GIMP to convert the images one by one using the UI.&lt;/p&gt;
&lt;h2 id=&quot;attempt-1&quot;&gt;Attempt 1&lt;/h2&gt;
&lt;p&gt;I tried to install &lt;code&gt;heif-gdk-pixbuf&lt;/code&gt;, but then neither &lt;code&gt;magick&lt;/code&gt; nor &lt;code&gt;eog&lt;/code&gt; could read the image. I got this error message:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Could not read HEIF/AVIF file: Invalid input: Unspecified: Metadata not correctly assigned to image&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is how I learned that the version (1.12) of &lt;code&gt;libheif&lt;/code&gt; that ships (as of the date of writing this) in the Ubuntu package manager can’t read HEIC images taken on iOS 18. I needed to install the latest version (1.19.8) from the Ubuntu PPA listed in the solution.&lt;/p&gt;
&lt;p&gt;Now I can receive images from my friends who use iOS 18 and, so far, all the image tools I use can read the images without issue.&lt;/p&gt;
</description>
        <pubDate>Tue, 14 Oct 2025 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/viewing-heic-images-on-popos</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/viewing-heic-images-on-popos</guid>
        
        
      </item>
    
      <item>
        <title>Video Gradually and Increasingly Falling Behind: Don&apos;t Use Buffering</title>
        <description>&lt;p&gt;I noticed in early 2025 that, when I used my USB external webcam together with OBS Studio for video sessions, that the video signal was falling gradually and increasingly behind my audio signal and, indeed, real time. Sometimes it took 10 minutes, sometimes it took an hour, but eventually, my video would become so far out of sync with my audio that it became too distracting to continue. Restarting OBS Studio brought the camera back in sync with my microphone.&lt;/p&gt;
&lt;p&gt;The problem lay in &lt;strong&gt;buffering&lt;/strong&gt;, so I turned it off, and now all seems well.&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;In OBS Studio, open the &lt;strong&gt;Properties&lt;/strong&gt; for your &lt;strong&gt;V4L2 Video Source&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Look for the option &lt;strong&gt;Use buffering&lt;/strong&gt; and unselect it. In OBS Studio 31, this is a checkbox, so uncheck it.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I don’t know whether you &lt;em&gt;need&lt;/em&gt; to restart OBS Studio for this change to take effect, but you might.&lt;/p&gt;
&lt;p&gt;With buffering off, my webcam has not (yet) fallen behind noticeably, even after over 90 minutes of continuous use on my laptop. If the symptom remains, it is much much much less noticeable.&lt;/p&gt;
&lt;h1 id=&quot;a-fix&quot;&gt;A Fix?&lt;/h1&gt;
&lt;p&gt;The nice folks in the OBS Studio community &lt;a href=&quot;https://github.com/obsproject/obs-studio/pull/12431&quot;&gt;are working on a fix&lt;/a&gt; as of July 25, 2025.&lt;/p&gt;
&lt;h1 id=&quot;key-references&quot;&gt;Key References&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/obsproject/obs-studio/discussions/11142&quot;&gt;A Github conversation about whether buffered video sources are a good idea&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://obsproject.com/forum/threads/video-gradually-falling-behind-audio-where-can-i-start-investigating.187021&quot;&gt;The OBS Studio Forum thread where I beg for help&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&quot;some-details&quot;&gt;Some Details&lt;/h1&gt;
&lt;p&gt;First, the ingredients that led to the symptom:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;OBS Studio 31.0.4 running on Flatpak&lt;/li&gt;
&lt;li&gt;Anker PowerConf C200 external USB webcam connected by USB-A&lt;/li&gt;
&lt;li&gt;Røde lapel microphone connected to an audio-to-USB adapter connected to an external (powered) USB hub connected by USB-A&lt;/li&gt;
&lt;li&gt;The Zoom client for Linux&lt;/li&gt;
&lt;li&gt;Pop!_OS 22.04&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The symptom: the video signal echoed through OBS Studio and transmitted over Zoom gradually and increasingly fell behind real time, although my audio signal stayed very close (close enough!) to real time for me not to notice the difference. Video fell more and more out of sync with audio (and real time) without a clear pattern for when it would happen nor how much. I only knew that it happened increasingly, so that choosing a fixed audio offset would not solve the problem.&lt;/p&gt;
&lt;p&gt;With all these variables, you can imagine how many permutations I had to test to gather information. Sometimes I could run my camera for 30 minutes and not notice a difference and sometimes I could run my camera 10 minutes and start seeing my video fall noticeably behind. As I was thinking about what could be happening, I was ruling ingredients out, such as Flatpak, the USB hub, the microphone, the webcam (my laptop’s internal webcam seemed fine), the Zoom client, the Zoom web app on Chrome, the current version of OBS Studio… it took weeks to gather enough information to be able to ask for help in a meaningful way.&lt;/p&gt;
&lt;p&gt;Why not just use my internal webcam? Because on it I look pink like a lobster… part of the time. I like this external USB webcam precisely because it provides a nicer and more consistent picture.&lt;/p&gt;
&lt;p&gt;Finally, I managed to point the finger quite strongly at OBS Studio, which led me to ask on the forum. It took nearly two weeks, but someone replied not only with a helpful idea, but with a very likely explanation for all the behavior I was seeing: OBS Studio was buffering the frames and insisting on displaying “out of date” frames rather than jumping forward to the front of the queue. When the computer was under heavier load, the frame queue kept expanding and OBS Studio kept insisting on displaying frames in sequence, rather than jumping forward. The issue seems to revolve around the difficult question of which timestamps to trust coming from which clocks.&lt;/p&gt;
&lt;p&gt;Very well, then: turn buffering off, which results in perhaps dropping more frames, but eliminates the problem of never catching up to the front of the frame queue.&lt;/p&gt;
&lt;p&gt;Presumably this buffering also affects my laptop’s internal webcam, but I presume that external webcams connected by an external USB port are more likely to be affected by variations in the computer’s workload. I suppose if I kept OBS Studio open for 24 hours and kept my laptop busy from time to time, even a buffered internal webcam video source might fall behind real time.&lt;/p&gt;
&lt;p&gt;So there it is. I don’t know whether I will ever regret turning buffering off, but at least for now, my voice and my face are reunited, which is plenty good enough for today.&lt;/p&gt;
</description>
        <pubDate>Wed, 16 Jul 2025 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/video-gradually-lagging-behind</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/video-gradually-lagging-behind</guid>
        
        
      </item>
    
      <item>
        <title>Upgrading Discourse When You Totally Have Enough Disk Space</title>
        <description>&lt;p&gt;I run some forums with Discourse and I upgrade them. Sometimes, when I upgrade them, I end up in an infinite loop of sadness. There is an easy way out that doesn’t require more disk space, because sometimes, you know, you already have enough disk space.&lt;/p&gt;
&lt;h1 id=&quot;the-symptom&quot;&gt;The Symptom&lt;/h1&gt;
&lt;p&gt;Try to upgrade and you get a message telling you to free up disk space, but when you try to free up disk space by deleting unused containers, and then you have something like 7.5 GiB free, you get that message again. But… I have enough disk space!&lt;/p&gt;
&lt;h1 id=&quot;a-workaround&quot;&gt;A Workaround&lt;/h1&gt;
&lt;p&gt;According to &lt;a href=&quot;https://meta.discourse.org/t/less-than-5gb-of-free-space-not-true/224517/6?u=jbrains&quot;&gt;this post at the Discourse Discourse&lt;/a&gt;, you can tell the upgrade script not to check for free space, but just go ahead. And it often works!&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;# ./launcher rebuild app --skip-prereqs&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If this doesn’t work, then you actually need to free some disk space or increase the disk capacity.&lt;/p&gt;
&lt;h1 id=&quot;why&quot;&gt;Why?!&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;You have 7.1GB free &lt;em&gt;before&lt;/em&gt; downloading the discourse container image but less than 5gb &lt;em&gt;after&lt;/em&gt; downloading it when we perform the check.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now you know.&lt;/p&gt;
</description>
        <pubDate>Tue, 21 May 2024 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/upgrading-discourse-when-you-totally-have-enough-disk-space</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/upgrading-discourse-when-you-totally-have-enough-disk-space</guid>
        
        
      </item>
    
      <item>
        <title>unWise Arithmetic</title>
        <description>&lt;p&gt;My company and I bank with Wise and today, while doing a routine check of exchange rates, Wise’s UI scared the hell out of me. Fortunately, they were able to explain why it looked like their web site was bothering to throwing away the paltry sum of $10 on a currency conversion. They weren’t. It’s fine; it’s just a questionable user experience.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Please note&lt;/strong&gt;: I have notified Wise customer support about this. Maybe they’ll do something to make it better. I’m guessing that they’ve had non-trivial internal discussion about the tension between a cleaner UI and a more-transparent UI. The ball is firmly in their court now.&lt;/p&gt;
&lt;h1 id=&quot;the-symptom&quot;&gt;The Symptom&lt;/h1&gt;
&lt;p&gt;I visited Wise’s “Convert Money” feature to see what they would give me in CAD for all the USD in my account. Their UI helpfully shows the conversion like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;USD amount
- our fees
x exchange rate
= the CAD we would deposit into your account&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I really like how clearly they present their calculation. There was only one problem: &lt;strong&gt;the CAD amount didn’t match the calculation&lt;/strong&gt;. It was a difference of about $10, which is not a large amount, but is enough to look like a hidden fee, rather than a computation error. Wise’s brand is fee transparency as well as keeping fees low.&lt;/p&gt;
&lt;h1 id=&quot;the-impact&quot;&gt;The Impact&lt;/h1&gt;
&lt;p&gt;Was there some hidden fee I didn’t know about?! Did Wise forget how to do arithmetic?! I expect them to get it right to the penny. Every. Single Time. It’s what I pay every bank for. Whatever the explanation, there is some part of my psyche that now trusts them less. I can’t be the only person.&lt;/p&gt;
&lt;h1 id=&quot;the-problem&quot;&gt;The Problem&lt;/h1&gt;
&lt;p&gt;Wise reports the exchange rate rounded to four decimal places, however, they apply a more-precise exchange rate. When the amount to convert is large enough, a difference of 0.00005 becomes noticeable, and when they round up, it looks like I’m not getting all my money, even though I am.&lt;/p&gt;
&lt;h1 id=&quot;the-solution&quot;&gt;The Solution&lt;/h1&gt;
&lt;p&gt;I told Wise customer support what psychological effect this experience had on me, notably on my perception of their brand. Now it’s on me to remember this for the future as well as on them to decide whether a slightly cleaner UI is worth scaring a segment of their customer base. It has become a business decision for them. I did my duty and reported the issue; I also did my best to present my opinion without undue drama.&lt;/p&gt;
&lt;p&gt;And I believe my heart rate is all the way back to normal.&lt;/p&gt;
</description>
        <pubDate>Mon, 08 Apr 2024 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/unwise-arithmetic</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/unwise-arithmetic</guid>
        
        
      </item>
    
      <item>
        <title>strptime: a Beginner&apos;s Mistake</title>
        <description>&lt;p&gt;I’m using &lt;code&gt;jq&lt;/code&gt; to process CSV files to use in a Plain Text Accounting environment, specifically using &lt;code&gt;hledger&lt;/code&gt;. I mention all this, not because it’s salient, but purely to make it easier for you to find this article by a web search.&lt;/p&gt;
&lt;h1 id=&quot;the-symptom&quot;&gt;The Symptom&lt;/h1&gt;
&lt;pre&gt;&lt;code&gt;$ jq -n &amp;#39;&amp;quot;8/4/2023&amp;quot; | strptime(&amp;quot;%D&amp;quot;)&amp;#39;
jq: error (at &amp;lt;unknown&amp;gt;): date &amp;quot;8/4/2023&amp;quot; does not match format &amp;quot;%D&amp;quot;

$ jq -n &amp;#39;&amp;quot;8/4/2023&amp;quot; | strptime(&amp;quot;%m/%d/%y&amp;quot;)&amp;#39;
jq: error (at &amp;lt;unknown&amp;gt;): date &amp;quot;8/4/2023&amp;quot; does not match format &amp;quot;%m/%d/%y&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;WAT?!&lt;/p&gt;
&lt;h1 id=&quot;the-problem&quot;&gt;The Problem&lt;/h1&gt;
&lt;p&gt;The &lt;code&gt;strptime&lt;/code&gt; pattern &lt;code&gt;%y&lt;/code&gt; matches the string &lt;code&gt;23&lt;/code&gt;, but not the string &lt;code&gt;2023&lt;/code&gt;. It’s pretty clear in the &lt;code&gt;man&lt;/code&gt; page, if a little unexpected.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;%y     The  year  within  century  (0–99).   When a century is not otherwise specified, values in the range 69–99 refer to years in the
      twentieth century (1969–1999); values in the range 00–68 refer to years in the twenty-first century (2000–2068).

%Y     The year, including century (for example, 1991).&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&quot;the-solution&quot;&gt;The Solution&lt;/h1&gt;
&lt;pre&gt;&lt;code&gt;$ jq -n &amp;#39;&amp;quot;8/4/2023&amp;quot; | strptime(&amp;quot;%m/%d/%Y&amp;quot;)&amp;#39;
[
  2023,
  7,
  4,
  0,
  0,
  0,
  5,
  215
]&lt;/code&gt;&lt;/pre&gt;
</description>
        <pubDate>Thu, 14 Mar 2024 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/strptime-a-beginner_s-mistake</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/strptime-a-beginner_s-mistake</guid>
        
        
      </item>
    
      <item>
        <title>Remove a Password from a PDF Document on Linux the Super-Easy Way</title>
        <description>&lt;p&gt;My accountants sensibly send me PDFs of returns and authorization forms with password protection enabled. Sadly, this makes it difficult for me to add text and sign the document digitally, at least with my preferred PDF editor on Linux, Master PDF Editor. Every year I fail to remember how to work around this problem, so I’m writing this article, hoping that my web search will find it next year.&lt;/p&gt;
&lt;h1 id=&quot;the-symptom&quot;&gt;The Symptom&lt;/h1&gt;
&lt;p&gt;My PDF document is password protected, so I can’t do anything with it, including adding text and signing it digitally.&lt;/p&gt;
&lt;h1 id=&quot;the-problem&quot;&gt;The Problem&lt;/h1&gt;
&lt;p&gt;Web searches for this topic return many many many irrelevant articles. It’s worse than searching the web for recipes.&lt;/p&gt;
&lt;h1 id=&quot;the-solution&quot;&gt;The Solution&lt;/h1&gt;
&lt;p&gt;Use &lt;code&gt;evince&lt;/code&gt; to print a new copy of the PDF document to file. This removes the passwodrd protection by default.&lt;/p&gt;
</description>
        <pubDate>Mon, 19 Feb 2024 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/remove-the-password-from-a-pdf-the-super-easy-way</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/remove-the-password-from-a-pdf-the-super-easy-way</guid>
        
        
      </item>
    
      <item>
        <title>The Mysterious Extra Quotes that `jc` Put In My JSON</title>
        <description>&lt;h1 id=&quot;the-symptom&quot;&gt;The Symptom&lt;/h1&gt;
&lt;p&gt;I try to use &lt;a href=&quot;https://github.com/kellyjonbrazil/jc&quot;&gt;&lt;code&gt;jc&lt;/code&gt;&lt;/a&gt; to convert a CSV file to JSON for further processing with &lt;a href=&quot;https://github.com/jqlang/jq&quot;&gt;&lt;code&gt;jq&lt;/code&gt;&lt;/a&gt;. When I try to process the JSON document with &lt;code&gt;jq&lt;/code&gt;, it fails, unable to find a value for the first cell of the first row.&lt;/p&gt;
&lt;p&gt;When I look at the JSON document, the JSON object key corresponding the first column name in the CSV document has extra quotes around it: instead of &lt;code&gt;&quot;Date&quot;&lt;/code&gt;, the key is &lt;code&gt;&quot;\&quot;Date\&quot;&quot;&lt;/code&gt;. Only this key has been changed; the others are exactly as I expect them.&lt;/p&gt;
&lt;p&gt;It seems that &lt;code&gt;jc&lt;/code&gt; has put extraneous quotes (or extra quotation marks&lt;a href=&quot;#fn1&quot; class=&quot;footnote-ref&quot; id=&quot;fnref1&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; ) around a CSV column header name.&lt;/p&gt;
&lt;h1 id=&quot;the-cause&quot;&gt;The Cause&lt;/h1&gt;
&lt;p&gt;The CSV file has a Byte Order Mark (BOM) at the beginning, which is unprintable, so I didn’t notice it. These unprintable characters become part of the name of the first CSV column, which then becomes a key in the resulting JSON objects that &lt;code&gt;jc --csv&lt;/code&gt; parses.&lt;/p&gt;
&lt;p&gt;Since &lt;code&gt;&quot;\&quot;Date\&quot;&quot;&lt;/code&gt; is not equal to &lt;code&gt;&quot;Date&quot;&lt;/code&gt;, chaos reigns.&lt;/p&gt;
&lt;h1 id=&quot;the-solution&quot;&gt;The Solution&lt;/h1&gt;
&lt;p&gt;Upgrade &lt;code&gt;jc&lt;/code&gt; to at least version 1.22.2, at least according to &lt;a href=&quot;https://github.com/kellyjonbrazil/jc/issues/307&quot;&gt;this issue&lt;/a&gt;. I was using… 1.20.4. How embarrassing.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode zsh&quot;&gt;&lt;code class=&quot;sourceCode zsh&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;$ pip3 install jc&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;$ jc --version&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;#cb1-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;jc version:  1.25.0&lt;/span&gt;
&lt;span id=&quot;cb1-4&quot;&gt;&lt;a href=&quot;#cb1-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;python interpreter version:  3.11.2&lt;/span&gt;
&lt;span id=&quot;cb1-5&quot;&gt;&lt;a href=&quot;#cb1-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;python path:  /home/jbrains/ThirdParty/python-3.11.2/bin/python3&lt;/span&gt;
&lt;span id=&quot;cb1-6&quot;&gt;&lt;a href=&quot;#cb1-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-7&quot;&gt;&lt;a href=&quot;#cb1-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;https://github.com/kellyjonbrazil/jc&lt;/span&gt;
&lt;span id=&quot;cb1-8&quot;&gt;&lt;a href=&quot;#cb1-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;© 2019-2024 Kelly Brazil&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h1 id=&quot;the-gory-details&quot;&gt;The Gory Details&lt;/h1&gt;
&lt;p&gt;I reproduce these details in order to give the next poor soul a chance to make it here by reading a single web page. Here are the steps that led me here.&lt;/p&gt;
&lt;p&gt;I downloaded a CSV file of transactions from PayPal. (I use them against my will.)&lt;/p&gt;
&lt;p&gt;I tried to process the CSV file with &lt;code&gt;jc --csv | jq &apos;.[&quot;Date&quot;] | parse_paypal_date&apos;&lt;/code&gt;, because I’ve written a &lt;code&gt;jq&lt;/code&gt; function to parse PayPal’s annoying date format of &lt;code&gt;dd/mm/yyyy&lt;/code&gt;. (If I got to pass one law, it’d require ISO 8601 for all dates all the time everywhere.)&lt;/p&gt;
&lt;p&gt;My processing command failed with&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;jq: error (at &amp;lt;stdin&amp;gt;:1): strptime/1 requires string inputs and arguments&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I checked the CSV file and I saw a column named &lt;code&gt;Date&lt;/code&gt; with obvious string values, starting with &lt;code&gt;&quot;02/11/2022&quot;&lt;/code&gt;, which is, of course, 2022-11-02 to people with taste.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/the-mysterious-extra-quotes-that-jc-put-in-my-json/the_date_is_right_there.jpg&quot; /&gt;&lt;/p&gt;
&lt;p&gt;After a few iterations of disbelief and confusion, I checked the JSON document.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre class=&quot;sourceCode json&quot;&gt;&lt;code class=&quot;sourceCode json&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;[&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-2&quot;&gt;&lt;a href=&quot;#cb3-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;fu&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-3&quot;&gt;&lt;a href=&quot;#cb3-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;&amp;quot;﻿&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;fu&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;02/11/2022&amp;quot;&lt;/span&gt;&lt;span class=&quot;fu&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Extra quotes?!&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;And, BTW, when I paste the JSON output into Typora to write this article, Typora clearly shows me that there’s an unprintable character at the beginning of that key.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I’ve never seen this before, so let me check another, very similar CSV file from a different source. &lt;strong&gt;Was this always broken?!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Nope. Everything looks good from another CSV document that also has &lt;code&gt;&quot;Date&quot;&lt;/code&gt; as the first column name.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb4&quot;&gt;&lt;pre class=&quot;sourceCode json&quot;&gt;&lt;code class=&quot;sourceCode json&quot;&gt;&lt;span id=&quot;cb4-1&quot;&gt;&lt;a href=&quot;#cb4-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;[&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-2&quot;&gt;&lt;a href=&quot;#cb4-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;fu&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-3&quot;&gt;&lt;a href=&quot;#cb4-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;&amp;quot;Date&amp;quot;&lt;/span&gt;&lt;span class=&quot;fu&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;11/01/2022&amp;quot;&lt;/span&gt;&lt;span class=&quot;fu&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;spot-the-difference&quot;&gt;Spot the Difference!&lt;/h2&gt;
&lt;p&gt;At least now I can compare these two CSV documents and ignore the rest of the world. That makes diagnosis much simpler.&lt;/p&gt;
&lt;p&gt;Since I can’t see a difference in the first column name between these two files, &lt;strong&gt;there must be an unprintable difference&lt;/strong&gt;. How do I see the unprintable characters in a text file on the typical Linux distribution?&lt;/p&gt;
&lt;p&gt;Today I Learned about &lt;code&gt;cat -A&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb5&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb5-1&quot;&gt;&lt;a href=&quot;#cb5-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; cat &lt;span class=&quot;at&quot;&gt;-A&lt;/span&gt; /path/to/annoying/paypal.csv &lt;span class=&quot;kw&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;at&quot;&gt;-n&lt;/span&gt; 1    &lt;/span&gt;
&lt;span id=&quot;cb5-2&quot;&gt;&lt;a href=&quot;#cb5-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;M-oM-&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;M-?&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Date&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Time&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;TimeZone&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Name&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Type&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Status&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Currency&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Gross&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Fee&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Net&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;From Email Address&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;To Email Address&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Transaction ID&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Shipping Address&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Address Status&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Item Title&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Item ID&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Shipping and Handling Amount&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Insurance Amount&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Sales Tax&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Option 1 Name&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Option 1 Value&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Option 2 Name&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Option 2 Value&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Reference Txn ID&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Invoice Number&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Custom Number&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Quantity&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Receipt ID&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Balance&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Address Line 1&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Address Line 2/District/Neighborhood&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Town/City&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;State/Province/Region/County/Territory/Prefecture/Republic&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Zip/Postal Code&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Country&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Contact Phone Number&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Subject&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Note&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Country Code&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Balance Impact&amp;quot;&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;img src=&quot;/img/the-mysterious-extra-quotes-that-jc-put-in-my-json/unprintable_characters.jpg&quot; /&gt;&lt;/p&gt;
&lt;h2 id=&quot;til-byte-order-marks&quot;&gt;TIL: Byte Order Marks&lt;/h2&gt;
&lt;p&gt;I inhaled quickly, then exhaled slowly.&lt;/p&gt;
&lt;p&gt;I searched the web for &lt;code&gt;&quot;M-oM-;M-?&quot;&lt;/code&gt; and found a non-trivial number of resuilts, which led me to learn about Byte Order Marks (BOM), thanks first to &lt;a href=&quot;https://stackoverflow.com/a/57282281/253921&quot;&gt;a Stack Overflow answer&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I don’t know much about Byte Order Marks, except that now I have better search keywords.&lt;/p&gt;
&lt;p&gt;I searched the web for &lt;code&gt;remove &quot;BOM&quot; from csv file&lt;/code&gt; and found a non-trivial number of results, including the authoritative-sounding &lt;a href=&quot;https://csv.thephpleague.com/7.0/bom/&quot;&gt;“CSV and BOM character”&lt;/a&gt;. Unfortunately, I’m not writing PHP code using LeagueCSV, so that helps me a bit less to work around the problem. Even so, it gives me confidence that there exists some body of prior art on this subject, so I don’t need to figure this all out on my own.&lt;/p&gt;
&lt;h2 id=&quot;i-cant-be-the-first&quot;&gt;I Can’t Be the First!&lt;/h2&gt;
&lt;p&gt;I went back to &lt;code&gt;jc&lt;/code&gt;, hoping to find an issue about this, before I went charging off on my own to &lt;del&gt;fix&lt;/del&gt; work around the problem. And that’s when I found &lt;a href=&quot;https://github.com/kellyjonbrazil/jc/issues/307&quot;&gt;this issue&lt;/a&gt;. And that’s when I discovered that I’m using an outdated version of &lt;code&gt;jc&lt;/code&gt; and that upgrading might fix the problem.&lt;/p&gt;
&lt;p&gt;And that’s when I wrote all this, while it was fresh in my mind.&lt;/p&gt;
&lt;section class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot; role=&quot;doc-endnote&quot;&gt;&lt;p&gt;I add synonyms here, not for clarity, but to attract more hits in web searches.&lt;a href=&quot;#fnref1&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
        <pubDate>Tue, 06 Feb 2024 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/the-mysterious-extra-quotes-that-jc-put-in-my-json</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/the-mysterious-extra-quotes-that-jc-put-in-my-json</guid>
        
        
      </item>
    
      <item>
        <title>Ducking in Screenflow</title>
        <description>&lt;h1 id=&quot;the-problem&quot;&gt;The Problem&lt;/h1&gt;
&lt;p&gt;I don’t remember how to do ducking correctly in Screenflow. I can’t figure it out by just doing what I think makes sense. Everyone wants to provide help as a video instead of as searchable text. I’m impatient.&lt;/p&gt;
&lt;h1 id=&quot;the-solution&quot;&gt;The Solution&lt;/h1&gt;
&lt;p&gt;Leave the music bed track, the one under the voiceover, alone. Enable ducking on the voiceover track. Adjust until happy.&lt;/p&gt;
</description>
        <pubDate>Sat, 26 Aug 2023 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/ducking-in-screenflow</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/ducking-in-screenflow</guid>
        
        
      </item>
    
      <item>
        <title>LibreOffice Calc, Headers, Footers, and Every Page!</title>
        <description>&lt;p&gt;I prepare expense reports using LibreOffice Calc, because nothing seems to handle multiple currencies the way my company wants to do it. The details don’t matter, but it’s enough to know that I print a workbook to PDF as part of my workflow. This workbook has many worksheets. I want headers and footers on each page in order to easily see which document I’m looking at.&lt;/p&gt;
&lt;p&gt;Suddenly, without warning, I started to see out-of-date headers on page 2 of my document. Several minutes of checking page styles and header settings didn’t change anything. I couldn’t find the magic keywords to search the web to find the problem. And then, finally, I noticed the issue: a new feature in LibreOffice 7.&lt;/p&gt;
&lt;h1 id=&quot;the-problem&quot;&gt;The Problem&lt;/h1&gt;
&lt;p&gt;Somebody wanted to be able to use different headers on the first page from the headers on remaining pages within a single sheet page style. They added that feature. They even made it possible to keep the previous behavior of using the same headers on every page. Sadly, they didn’t make the old behavior the default choice, so it changed without my consent.&lt;/p&gt;
&lt;p&gt;Moreover, they named the option in a way that makes sense to programmers, but not to normal, everyday humans. I didn’t notice it even after looking directly at it a handful of times.&lt;/p&gt;
&lt;h1 id=&quot;the-solution&quot;&gt;The Solution&lt;/h1&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Open the Styles panel and locate your page style.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Modify…&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Choose the tab &lt;strong&gt;Header&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Locate the new option “&lt;strong&gt;Same content on first page&lt;/strong&gt;”. It’s probably disabled, so enable it!&lt;/li&gt;
&lt;li&gt;Press &lt;strong&gt;Edit…&lt;/strong&gt;. Notice that now there only one tab for the header.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;LibreOffice Calc will now use this one header on every page of your PDF document.&lt;/p&gt;
&lt;p&gt;If you’d like to see the difference, disable the option &lt;strong&gt;Same content on first page&lt;/strong&gt;, then edit the headers again. Now notice that there are two settings tabs: one for the first page and one for the rest of the pages.&lt;/p&gt;
&lt;p&gt;Now check your &lt;strong&gt;Footer&lt;/strong&gt; settings.&lt;/p&gt;
&lt;h1 id=&quot;a-ux-suggestion-for-everyone&quot;&gt;A UX Suggestion For Everyone&lt;/h1&gt;
&lt;p&gt;When you add a new feature with configuration settings, give those settings default values that match the previous behavior, so that you don’t confuse users. Thanks.&lt;/p&gt;
</description>
        <pubDate>Wed, 17 May 2023 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/libreoffice-calc-headers</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/libreoffice-calc-headers</guid>
        
        
      </item>
    
      <item>
        <title>How Pandoc and Ranger Froze My Laptop</title>
        <description>&lt;p&gt;I use &lt;code&gt;ranger&lt;/code&gt; to manage files from my shell, because it gives me vim-style navigation&lt;a href=&quot;#fn1&quot; class=&quot;footnote-ref&quot; id=&quot;fnref1&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; and search features that help me navigate my file system very quickly.&lt;/p&gt;
&lt;p&gt;I use LibreOffice for all my spreadsheet needs because, well, Numbers.app is not available on Linux.&lt;/p&gt;
&lt;p&gt;I use &lt;code&gt;pandoc&lt;/code&gt; for a variety of reasons, including converting blog posts into PDFs.&lt;/p&gt;
&lt;p&gt;When we put those three together, however, my laptop fan started blowing at top speed and wouldn’t stop. My laptop froze—or at least went very very slowly—and I had to reboot a few times and explore a little in order to discover the problem.&lt;/p&gt;
&lt;h1 id=&quot;the-problem&quot;&gt;The Problem&lt;/h1&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;&lt;code&gt;ranger&lt;/code&gt; can create previews of files as you navigate through the file system.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ranger&lt;/code&gt; uses &lt;code&gt;pandoc&lt;/code&gt; to create previews of certain kinds of files, rendering the text from some kinds of non-text files. This makes it possible to preview a PDF, for example, by extracting the text instead of rendering a 1/4-size image of the file that only very young eyes could possibly read.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pandoc&lt;/code&gt; (at least version 2.18, which I have installed) becomes stuck when it tries to process an Open Document Spreadsheet (&lt;code&gt;*.ods&lt;/code&gt;). According to the project’s lead maintainer, &lt;a href=&quot;https://github.com/jgm/pandoc/issues/8596#issuecomment-1412744130&quot;&gt;&lt;code&gt;pandoc&lt;/code&gt; doesn’t support that format so whatever happens, happens&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;When I navigate to a directory in &lt;code&gt;ranger&lt;/code&gt; and that directory contains Open Document Spreadsheet files… &lt;code&gt;pandoc&lt;/code&gt; tries very hard to render the spreadsheet, leaks memory, spins forever at top speed, and begins eating CPUs.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Users of &lt;code&gt;pandoc&lt;/code&gt; should not expect this problem to be resolved any time soon. Garbage in, garbage out, it seems. And yes: a binary file is garbage to a Markdown parser.&lt;/p&gt;
&lt;h1 id=&quot;the-solution&quot;&gt;The Solution&lt;/h1&gt;
&lt;p&gt;Install a version of &lt;code&gt;ranger&lt;/code&gt; that doesn’t try to render previews for Open Document Spreadsheet files. Sadly, &lt;code&gt;ranger&lt;/code&gt; doesn’t release new versions very often, which makes this slightly more complicated than installing the latest version from your Linux distribution’s package manager.&lt;/p&gt;
&lt;p&gt;It appears that &lt;code&gt;ranger&lt;/code&gt; fixed the problem &lt;a href=&quot;https://github.com/ranger/ranger/commit/9da2b4c79323a3f34da8d54198364d549a29ff00&quot;&gt;in commit 9da2b4c79323a3f34da8d54198364d549a29ff00&lt;/a&gt;. &lt;a href=&quot;https://github.com/ranger/ranger#installing-from-a-clone&quot;&gt;I built &lt;code&gt;ranger&lt;/code&gt; from source&lt;/a&gt; with the latest version of the main branch of the project as of 2023-04-20. This version worked for me. Building from source didn’t seem intimidating to me and it just worked the first time.&lt;/p&gt;
&lt;p&gt;I hope you have a similarly smooth experience fixing the problem.&lt;/p&gt;
&lt;section class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot; role=&quot;doc-endnote&quot;&gt;&lt;p&gt;I would prefer &lt;em&gt;kakoune&lt;/em&gt;-style navigation, but I can settle for vim.&lt;a href=&quot;#fnref1&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
        <pubDate>Thu, 20 Apr 2023 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/why-did-my-laptop-suddenly-become-frozen-pandoc</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/why-did-my-laptop-suddenly-become-frozen-pandoc</guid>
        
        
      </item>
    
      <item>
        <title>Installing hledger</title>
        <description>&lt;p&gt;I became interested in &lt;a href=&quot;https://plaintextaccounting.org/&quot;&gt;Plain Text Accounting&lt;/a&gt; and decided to install &lt;a href=&quot;https://hledger.org/install.html&quot;&gt;hledger&lt;/a&gt; to see how to start using it. I failed to install it the first time due to this message:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ stack install --resolver=lts-19 hledger-lib-1.28 hledger-1.28 hledger-ui-1.28 hledger-web-1.28
Selected resolver: lts-19.33

Error: While constructing the build plan, the following exceptions were encountered:

In the dependencies for hledger-ui-1.28:
    brick-0.68.1 from stack configuration does not match &amp;gt;=1.5  (latest matching version is 1.6)
    fsnotify-0.3.0.1 from stack configuration does not match &amp;gt;=0.4 &amp;amp;&amp;amp; &amp;lt;0.5  (latest matching version is 0.4.1.0)
needed since hledger-ui is a build target.

Some different approaches to resolving this:

  * Set &amp;#39;allow-newer: true&amp;#39; in /home/jbrains/.stack/config.yaml to ignore all version constraints and build anyway.

  * Recommended action: try adding the following to your extra-deps in /home/jbrains/.stack/global-project/stack.yaml:

- brick-1.6@sha256:4a94b18be68d2d27da9e84eff7f8b4dc8bfa3a40d28d536fb737828d73a0e3eb,18899
- fsnotify-0.4.1.0@sha256:44540beabea36aeeef930aa4d5f28091d431904bc9923b6ac4d358831c651235,2854

Plan construction failed.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since I don’t know &lt;code&gt;ghcup&lt;/code&gt; at all, I was stuck. I managed to piece together an answer: &lt;strong&gt;specify the additional packages in the command&lt;/strong&gt;, so that &lt;code&gt;stack&lt;/code&gt; would install them.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ stack install --resolver=lts-20.8 hledger-lib-1.28 hledger-1.28 hledger-ui-1.28 hledger-web-1.28 brick-1.5 fsnotify-0.4.0.0&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This installed &lt;code&gt;hledger&lt;/code&gt; and now I have a new task to spend a few hours figuring out what I can do with it.&lt;/p&gt;
&lt;p&gt;Notice the version numbers of the various packages, which don’t exactly match the installation documentation nor the “Recommended action” in the installation failure message.&lt;/p&gt;
&lt;h1 id=&quot;how-i-knew&quot;&gt;How I Knew…&lt;/h1&gt;
&lt;p&gt;I couldn’t figure out how to specify the additional packages simply. I didn’t want to change a magic global configuration file, so I inferred that there must be a way to specify the extra packages as part of the &lt;code&gt;stack install&lt;/code&gt; command.&lt;/p&gt;
&lt;p&gt;I read the section of the install documentation entitled “Build with hledger-install”, which directed me to read the installation script. When I did this, I noticed some helpful-looking package version numbers.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# the oldest version of stack that might possibly work: perhaps 2.5.1
STACK_MIN_VERSION=2.5.1

# stackage snapshot to use when installing with stack.
# You can try specifying a different stackage version here, or
# commenting out this line to use your current global resolver,
# to avoid unnecessary building.
STACK_RESOLVER=&amp;quot;--resolver=lts-20.8&amp;quot;

# Dependencies we require that aren&amp;#39;t in the above stackage snapshot.
# (Also requested when using cabal, but that&amp;#39;s harmless.)
STACK_EXTRA_DEPS=&amp;quot;\
brick-1.5 \
fsnotify-0.4.0.0 \
&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This suggested to me that I ought to try a different resolver version (&lt;code&gt;lts-20.8&lt;/code&gt; instead of &lt;code&gt;lts-19&lt;/code&gt;) and these particular package versions for &lt;code&gt;brick&lt;/code&gt; and &lt;code&gt;fsnotify&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;After reading through the installation script, I realized—and felt mildly stupid about this—that I needed merely to specify the additional packages with their version numbers as packages to install. (I had kept looking for some “extra dependencies” command-line argument and couldn’t find it!) That led me to the winning command.&lt;/p&gt;
&lt;p&gt;As of today, these versions of the various tools worked for me on Pop!_OS 22.04.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ghc 9.2.5&lt;/li&gt;
&lt;li&gt;stack 2.9.1
&lt;ul&gt;
&lt;li&gt;resolver lts-20.8&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;hledger-* 1.28&lt;/li&gt;
&lt;li&gt;brick-1.5&lt;/li&gt;
&lt;li&gt;fsnotify-0.4.0.0&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I have no idea how long this information will remain relevant and accurate.&lt;/p&gt;
</description>
        <pubDate>Tue, 31 Jan 2023 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/installing-hledger</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/installing-hledger</guid>
        
        
      </item>
    
      <item>
        <title>Pop! OS Won&apos;t Mount Any External USB Disk</title>
        <description>&lt;p&gt;I use Pop!_OS 22.04 and today I encountered a nasty surprise: I couldn’t mount the portable USB disk that I use to back up my &lt;a href=&quot;https://bitwarden.com&quot;&gt;Bitwarden&lt;/a&gt; vault, which contains passwords and secure notes.&lt;a href=&quot;#fn1&quot; class=&quot;footnote-ref&quot; id=&quot;fnref1&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; Fortunately, it only took a few seconds of web searching to find someone who encountered the same problem.&lt;/p&gt;
&lt;h1 id=&quot;solution&quot;&gt;Solution&lt;/h1&gt;
&lt;p&gt;Reboot, then mounting the USB disks worked as expected.&lt;/p&gt;
&lt;h1 id=&quot;why&quot;&gt;Why?&lt;/h1&gt;
&lt;p&gt;During an operating system package upgrade, I evidently upgraded the Linux kernel from version 5.x to version 6.x. This seems to have caused the &lt;code&gt;usb_storage&lt;/code&gt; kernel module to stop working. This meant that I couldn’t mount &lt;em&gt;any&lt;/em&gt; external USB disk, no matter which port (USB-C or USB-A). I infer that this kernel module changed in a non-backwards-compatible way and reloading it seems to have solved the problem.&lt;/p&gt;
&lt;p&gt;I did not try reloading the kernel module with &lt;code&gt;modprobe&lt;/code&gt;, so maybe that would have worked.&lt;/p&gt;
&lt;h1 id=&quot;how-did-we-get-here&quot;&gt;How Did We Get Here?&lt;/h1&gt;
&lt;p&gt;I connected a USB disk (call this “Disk A”) to my System76 Lemur Pro’s USB-C port. It did not mount.&lt;/p&gt;
&lt;p&gt;I connected Disk A into my Galaxy Tab. It mounted. I inferred that Disk A works.&lt;/p&gt;
&lt;p&gt;I found another USB disk (call this “Disk B”) and connected it to one of my Lemur Pro’s USB-A ports. It did not mount. I inferred that this is a software problem instead of a hardware problem, because what are the chances that both ports are dead at once?&lt;/p&gt;
&lt;p&gt;I searched the web: &lt;code&gt;lemur pro usb-c port doesn&apos;t work&lt;/code&gt;. I found a comment suggesting to check &lt;code&gt;dmesg&lt;/code&gt; for related log messages.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode zsh&quot;&gt;&lt;code class=&quot;sourceCode zsh&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;$ sudo dmesg &lt;span class=&quot;kw&quot;&gt;|&lt;/span&gt; rga -i &lt;span class=&quot;st&quot;&gt;&amp;quot;usb&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;[...a bunch of stuff...]&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;#cb1-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;failed to validate module [usb_storage] BTF: -22&lt;/span&gt;
&lt;span id=&quot;cb1-4&quot;&gt;&lt;a href=&quot;#cb1-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;[...a bunch of stuff...]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That seemed like a sign of trouble, so I searched the web: &lt;code&gt;&quot;failed to validate module&quot; usb_storage&lt;/code&gt;. I found &lt;a href=&quot;https://forum.proxmox.com/threads/usb-storage-can-not-be-mounted.100480/&quot; class=&quot;uri&quot;&gt;https://forum.proxmox.com/threads/usb-storage-can-not-be-mounted.100480/&lt;/a&gt;. This is how I learned about &lt;code&gt;journalctl -f&lt;/code&gt; for monitoring the system logs in real time. I connnected and disconnected the USB disks and watched the messages in real time, confirming the symptom I’d seen. The person who asked the question in this thread reported&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I tested again yesterday after a restart. Now everything is working as expected.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I didn’t love trying a magic solution, but I happened to use the command &lt;code&gt;uname -r&lt;/code&gt; and noticed that I’d upgraded the kernel to a new major version, namely 6.0.x. That gave me the idea that maybe a kernel module had breaking changes and needed to be reloaded, then suddenly “reboot” didn’t sound like a magic solution any more, but rather made perfect sense to me.&lt;/p&gt;
&lt;p&gt;I rebooted. Now all my USB disks mount as expected.&lt;/p&gt;
&lt;section class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot; role=&quot;doc-endnote&quot;&gt;&lt;p&gt;Yes, I deleted my Lastpass account after the breach reported in late December 2022. Thank you for your concern. I hope my master password was strong enough.&lt;a href=&quot;#fnref1&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
        <pubDate>Sat, 24 Dec 2022 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/popos-wont-mount-any-external-usb-disk</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/popos-wont-mount-any-external-usb-disk</guid>
        
        
      </item>
    
      <item>
        <title>Why My Spreadsheet File is So Big</title>
        <description>&lt;p&gt;Today I noticed that a spreadsheet I use had a file size significantly higher than I’d expect: 2 worksheets, maybe 100 rows, but somehow 31.2 MB. (I’m using LibreOffice.)&lt;/p&gt;
&lt;p&gt;Fortunately, it didn’t take long for me to find the problem: embedded fonts.&lt;/p&gt;
&lt;h1 id=&quot;solution&quot;&gt;Solution&lt;/h1&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Open the file in LibreOffice Calc.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;File &amp;gt; Properties…&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Go to the &lt;strong&gt;Font&lt;/strong&gt; tab.&lt;/li&gt;
&lt;li&gt;Uncheck the various settings for embedding fonts in the document.&lt;/li&gt;
&lt;li&gt;Save the file and watch the file size decrease.&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id=&quot;how-i-got-here&quot;&gt;How I Got Here&lt;/h1&gt;
&lt;p&gt;I installed &lt;a href=&quot;https://www.7-zip.org/&quot;&gt;7-Zip&lt;/a&gt; and listed the contents of the spreadsheet file (&lt;code&gt;7zz l $FILENAME&lt;/code&gt;). I noticed font files. I inferred that LibreOffice had embedded the font files in the spreadsheet file. I searched the web and learned how to stop doing that.&lt;/p&gt;
&lt;p&gt;What’s odd is that I don’t remember embedding fonts in this document, so maybe I did it by accident. I also couldn’t find any kind of sticky preference in LibreOffice that would embed fonts in new documents by default. This means that I have no idea how this happened; I presume that information is lost to time.&lt;/p&gt;
</description>
        <pubDate>Thu, 22 Dec 2022 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/why-my-is-spreadsheet-file-so-big</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/why-my-is-spreadsheet-file-so-big</guid>
        
        
      </item>
    
      <item>
        <title>When Your Site Can&apos;t Find Its Discourse Comments</title>
        <description>&lt;p&gt;It’s November 2022 and I insist on having comments on my professional blogs, even though nobody really cares. In 2021 I began migrating comments away from Disqus (which I dislike for various reasons) towards Discourse. With Discourse, I embed a topic into each blog post, so that each post corresponds to a Discourse topic. Discourse creates a topic for each post and the comment thread of the topic becomes the comment thread of the post. Nice.&lt;/p&gt;
&lt;h1 id=&quot;symptom&quot;&gt;Symptom&lt;/h1&gt;
&lt;p&gt;Today I was rudely greeted with an HTTP/404 response in the spot on a blog post where comments should appear. In my browser, that showed up as a sad face.&lt;/p&gt;
&lt;h1 id=&quot;problem&quot;&gt;Problem&lt;/h1&gt;
&lt;p&gt;Discourse did not allow embedding from the domain I was visiting.&lt;/p&gt;
&lt;h1 id=&quot;solution&quot;&gt;Solution&lt;/h1&gt;
&lt;p&gt;Tell Discourse to allow embedding from &lt;em&gt;all&lt;/em&gt; the domains that you use for your site/blog/whatever.&lt;/p&gt;
&lt;p&gt;As of November 2022, you’ll find the setting in Discourse under &lt;strong&gt;Admin &amp;gt; Customize &amp;gt; Embedding&lt;/strong&gt;. If you need more details, search the &lt;a href=&quot;https://meta.discourse.org&quot;&gt;Discourse Forum about Discourse&lt;/a&gt;, just as I do every time I need to look something up about Discourse.&lt;/p&gt;
&lt;h1 id=&quot;why-the-problem-was-a-problem&quot;&gt;Why the Problem Was a Problem&lt;/h1&gt;
&lt;p&gt;My &lt;a href=&quot;https://blog.thecodewhisperer.com&quot;&gt;programming-focused blog&lt;/a&gt; can be found at &lt;a href=&quot;https://blog.thecodewhisperer.com&quot; class=&quot;uri&quot;&gt;https://blog.thecodewhisperer.com&lt;/a&gt;, but also at &lt;a href=&quot;https://www.thecodewhisperer.com&quot; class=&quot;uri&quot;&gt;https://www.thecodewhisperer.com&lt;/a&gt; and even at &lt;a href=&quot;https://thecodewhisperer.com&quot; class=&quot;uri&quot;&gt;https://thecodewhisperer.com&lt;/a&gt;. I need to do one of two things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Change the HTTP redirect response code to &lt;em&gt;forward&lt;/em&gt; the requester (change the address in the browser’s address bar) on to the canonical subdomain &lt;code&gt;blog.&lt;/code&gt; &lt;strong&gt;or&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Add all these domains to the “allow list” for embedding (with the same settinngs).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I chose the latter, even though I don’t love the duplication. I would be thrilled if Discourse added the feature of applying the same “embed allow list” settings to a colletion of domains, but I don’t have the energy to do that today.&lt;/p&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;
</description>
        <pubDate>Sun, 06 Nov 2022 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/when-your-site-cant-find-discourse-comments</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/when-your-site-cant-find-discourse-comments</guid>
        
        
      </item>
    
      <item>
        <title>Fix the Automatic Time Zone on Pop! OS</title>
        <description>&lt;p&gt;Somewhere along the way, my System 76 laptop stopped automatically updating the time zone based on its location. This annoyed me for a few months, but only today did I finally take some time to explore what was happening and how to fix it.&lt;/p&gt;
&lt;h1 id=&quot;the-short-version&quot;&gt;The Short Version&lt;/h1&gt;
&lt;p&gt;It seems to matter the sequence of enabling the two relevant settings: Location Services and Automatic Time Zone.&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Turn both Location Services and Automatic Time Zone off.&lt;/li&gt;
&lt;li&gt;Breathe for 10 seconds.&lt;/li&gt;
&lt;li&gt;First, turn Location Services on.&lt;/li&gt;
&lt;li&gt;Breathe for 10 seconds.&lt;/li&gt;
&lt;li&gt;Next, turn Automatic Time Zone on.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This changed my time zone to the one I find myself in right now, which is not my home time zone. Problem solved.&lt;/p&gt;
&lt;h1 id=&quot;how-i-got-here&quot;&gt;How I Got Here&lt;/h1&gt;
&lt;p&gt;Somewhere along the way I turned off Location Services in Pop!_OS 22.04 settings, presumably for privacy reasons. Unfortunately, I had also turned on the Automatic Time Zone setting, not knowing that it needed Location Services to do its work. There was no way to get the correct location in order to find the correct current time zone. I consider this a UI defect, but at least I can make sense of it.&lt;/p&gt;
&lt;p&gt;Sadly, when I turned Location Services on, nothing changed. I looked for ways to force the Time Synchronization service to, you know, synchronize the time, but nothing worked. I learned a little about &lt;code&gt;timedatectl&lt;/code&gt; along the way. The system time never changed, but neither did I find any error messages in the &lt;code&gt;systemd&lt;/code&gt; journal for the &lt;code&gt;systemd-timesyncd&lt;/code&gt; service. I couldn’t find any sign that anything was wrong. I infer now that the operating system was trying to ask for the current time zone, didn’t have access to Location Services, and quietly failed to even ask the question. As a result, my laptop remained stuck in Atlantic Daylight Time when I was clearly sitting in Eastern Daylight Time.&lt;/p&gt;
&lt;p&gt;And then I thought of something.&lt;/p&gt;
&lt;p&gt;My computer programmer mind told me that &lt;strong&gt;there was probably some silly dependency between the services&lt;/strong&gt;, so it probably mattered in which sequence I turned these two services on.&lt;/p&gt;
&lt;p&gt;Bingo.&lt;/p&gt;
&lt;p&gt;Related: &lt;a href=&quot;https://youtu.be/Jtq1EBMe1gQ?t=96&quot; class=&quot;uri&quot;&gt;https://youtu.be/Jtq1EBMe1gQ?t=96&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Do you know how I could have reliably discovered this problem, rather than guessing and getting lucky? Please tell me; otherwise, this seems like two defects to me:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the settings UI doesn’t signal the dependency between these two services&lt;/li&gt;
&lt;li&gt;the “synchronize time” command doesn’t signal that since Location Services is disabled, it doesn’t know which current location to use to ask for the time zone&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Mon, 22 Aug 2022 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/fix-automatic-time-zone-popos</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/fix-automatic-time-zone-popos</guid>
        
        
      </item>
    
      <item>
        <title>Remap Keys on System76 Less Painfully</title>
        <description>&lt;p&gt;If you search the web for “remap keys ubuntu”, you’ll find a dizzying collection of contradictory articles on the subject. This is one of those simple questions that seems to have a complicated answer, because of the long legacy of remapping keys on various distributions of Linux over the decades. I found many many ways to do it, not all equivalent, and with a complicated variety of consequences, most of which I do not understand yet. This makes it easy to find answers, but difficult to find answers that fit you well. It seems like one needs to get a Ph. D. in Linux to find an answer that you’ll feel comfortable with.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Of course, if you want to learn more about the boundaries between the operating system and your desktop environment, remapping keys provides an effective way to learn some part of that. I do not—at least not today.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And if you’re like me, you’ll forget about how you remapped your keys, then you’ll wake up one morning after a software update, your keyboard layout will have been reset, and you won’t remember how to fix it.&lt;/p&gt;
&lt;h1 id=&quot;my-primary-goal&quot;&gt;My Primary Goal&lt;/h1&gt;
&lt;p&gt;I wanted a solution that allowed me to put my keyboard configuration in version control, so that I knew exactly how to reapply my keyboard mapping any time it changed on me. I wanted the ability to do this quickly and easily.&lt;/p&gt;
&lt;p&gt;Rather than wade through all the options available to me, I asked System 76 support what they recommended to me, and I really like their recommendation, at least for now, as of late 2022.&lt;/p&gt;
&lt;h1 id=&quot;my-current-solution&quot;&gt;My Current Solution&lt;/h1&gt;
&lt;p&gt;I use the package &lt;code&gt;system76-keyboard-configurator&lt;/code&gt;, which provides two things that I like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a GUI to remap the keys, so that I can see what I’m doing&lt;/li&gt;
&lt;li&gt;an import/export feature, so that I can store my configuration in a text file (JSON format) that I can put in version control (git).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The whole exercise took about 1 minute.&lt;/p&gt;
&lt;p&gt;This software changes the keymap at the firmware level, which I infer means that these changes apply &lt;em&gt;before&lt;/em&gt; any changes I’ve made in Gnome, whether using the keyboard settings or Gnome Tweaks. I’ll keep an eye out for whether this causes any problems.&lt;/p&gt;
&lt;p&gt;If anything behaves strangely, I’ll probably prefer to move the keyboard mappings out of Gnome and into the firmware. For example, I want my &lt;code&gt;Caps Lock&lt;/code&gt; key to behave like &lt;code&gt;Control&lt;/code&gt; all the time, and not only when I’m running Gnome.&lt;/p&gt;
&lt;p&gt;Of course, I’ll need to look for a different solution when I’m working on a Linux machine that doesn’t come from System76, but the only reason I need this is that my Lemur Pro 10 laptop keyboard has a &lt;code&gt;Prt Sc&lt;/code&gt; key and no &lt;code&gt;Insert&lt;/code&gt; key, but I am used to using the keystroke &lt;code&gt;Alt+Insert&lt;/code&gt; quite often in IntelliJ IDEA. In an emergency, I can always change the keystroke in IDEA; in general, I don’t need &lt;code&gt;Prt Sc&lt;/code&gt;, because I use a screenshot tool such as Spectacle.&lt;/p&gt;
&lt;h2 id=&quot;the-steps&quot;&gt;The Steps&lt;/h2&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode zsh&quot;&gt;&lt;code class=&quot;sourceCode zsh&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;$ sudo apt-get install system76-keyboard-configurator&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;$ system76-keyboard-configurator&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This launches the GUI.&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Press “Configure Keyboard”.&lt;/li&gt;
&lt;li&gt;Remap the keys, as you like.&lt;/li&gt;
&lt;li&gt;From the menu, choose “Export Layout”.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This produces a JSON format text file that you can store anywhere you like. I put mine in my &lt;code&gt;dotfiles&lt;/code&gt; repository, even though it’s not &lt;em&gt;really&lt;/em&gt; a dotfile.&lt;/p&gt;
&lt;p&gt;As a test, I used the application to reset my keymap, then import my custom layout. This worked great!&lt;/p&gt;
&lt;h1 id=&quot;references&quot;&gt;References&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/pop-os/keyboard-configurator&quot; class=&quot;uri&quot;&gt;https://github.com/pop-os/keyboard-configurator&lt;/a&gt; I installed the release published into &lt;code&gt;apt&lt;/code&gt;, but it looks pretty easy to run this application directly from source, if you prefer.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://support.system76.com/articles/launch-keyboard/#keyboard-configurator&quot;&gt;“Configuring your new Launch keyboard”&lt;/a&gt;. I didn’t figure this out myself, mostly because this article doesn’t make it easy to notice that I can use the Keyboard Configurator on my laptop’s keyboard. When I skimmed this article, I assumed that one would use this tool only with a Launch keyboard, which I don’t have.&lt;/p&gt;
</description>
        <pubDate>Tue, 26 Jul 2022 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/remap-keys-on-system76-less-painfully</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/remap-keys-on-system76-less-painfully</guid>
        
        
      </item>
    
      <item>
        <title>Fixing Your Virtual Camera On Microsoft Teams for Linux</title>
        <description>&lt;p&gt;I host client meetings, I like OBS Studio, and I run Linux. Sometimes, the pieces don’t talk together nicely. This is the case when my client prefers to use Microsoft Teams. (I typically use Zoom. I know the risks. We are where we are.)&lt;/p&gt;
&lt;p&gt;When I tried to use my OBS Studio Virtual Camera device in Microsoft Teams on Linux, I got only a black screen/empty image. No video. (Audio worked fine.)&lt;/p&gt;
&lt;p&gt;After some digging, I discovered that this is a known limitation of Microsoft Teams for Linux.&lt;/p&gt;
&lt;h2 id=&quot;the-workaround&quot;&gt;The Workaround&lt;/h2&gt;
&lt;p&gt;In OBS Studio, set the overall video output resolution to 720p. That’s it. You might need to restart both OBS Studio and Teams.&lt;/p&gt;
&lt;h2 id=&quot;the-consequences&quot;&gt;The Consequences&lt;/h2&gt;
&lt;p&gt;You will need to resize the various windows and backgrounds you use in your scenes. It’s probably wise to have two OBS Studio configuration directories, so that you can switch back and forth. I’m doing that and it helps.&lt;/p&gt;
</description>
        <pubDate>Tue, 26 Apr 2022 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/microsoft-teams-obs-virtual-camera-linux</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/microsoft-teams-obs-virtual-camera-linux</guid>
        
        
      </item>
    
      <item>
        <title>Exclude Big Files From Your restic Backup</title>
        <description>&lt;p&gt;I use &lt;a href=&quot;restic.readthedocs.io/&quot;&gt;restic&lt;/a&gt; for backups on Linux. After a cappuccino scare, I turned my attention back to automating a local backup of my everyday laptop. After a few days, I noticed that each quasi-daily backup was adding 200-500 MB of data, which seems excessive. I presumed that I should exclude more files from this automated backup, but I didn’t know which ones. I guessed that I should look for &lt;em&gt;big&lt;/em&gt; files or &lt;em&gt;big&lt;/em&gt; directories. But how do I get that information?&lt;/p&gt;
&lt;p&gt;It turns out to be a combination of &lt;code&gt;restic&lt;/code&gt;, &lt;code&gt;stat&lt;/code&gt;, and &lt;code&gt;awk&lt;/code&gt;.&lt;/p&gt;
&lt;h1 id=&quot;a-solution&quot;&gt;A Solution&lt;/h1&gt;
&lt;p&gt;Please note that this solution works on &lt;code&gt;zsh&lt;/code&gt; and apparently not on &lt;code&gt;bash&lt;/code&gt;. I don’t know enough details to rewrite this in &lt;code&gt;bash&lt;/code&gt;, so I can’t help you do that.&lt;/p&gt;
&lt;p&gt;Also please note that I use &lt;code&gt;rga&lt;/code&gt;, but regular &lt;code&gt;grep&lt;/code&gt; would suffice.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode zsh&quot;&gt;&lt;code class=&quot;sourceCode zsh&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;restic &lt;span class=&quot;ot&quot;&gt;$BACKUP_CONNECTION_DETAILS&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    diff &lt;span class=&quot;ot&quot;&gt;$BEFORE_SNAPSHOT_ID&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;$AFTER_SNAPSHOT_ID&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;#cb1-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;|&lt;/span&gt; rga &lt;span class=&quot;st&quot;&gt;&amp;quot;^(?:M|\+)&amp;quot;&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;|&lt;/span&gt; awk &lt;span class=&quot;st&quot;&gt;&amp;#39;{print $2}&amp;#39;&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-4&quot;&gt;&lt;a href=&quot;#cb1-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;f&lt;/span&gt;; &lt;span class=&quot;kw&quot;&gt;do&lt;/span&gt;; &lt;span class=&quot;kw&quot;&gt;(stat&lt;/span&gt; -t &lt;span class=&quot;ot&quot;&gt;$f&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;|&lt;/span&gt; awk &lt;span class=&quot;st&quot;&gt;&amp;#39;{print $2 , $1}&amp;#39;&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;)&lt;/span&gt;; &lt;span class=&quot;kw&quot;&gt;done&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-5&quot;&gt;&lt;a href=&quot;#cb1-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;2&amp;gt;&lt;/span&gt; /dev/null &lt;span class=&quot;kw&quot;&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-6&quot;&gt;&lt;a href=&quot;#cb1-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;|&lt;/span&gt; sort -n&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Your &lt;code&gt;$BACKUP_CONNECTION_DETAILS&lt;/code&gt; includes your repository address and password file.&lt;/li&gt;
&lt;li&gt;The snapshot IDs are the ones to compare. I compared the most recent two, but just as a start.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;stat -t&lt;/code&gt; reports files it can’t find to &lt;code&gt;stderr&lt;/code&gt;, so I remove them. It shouldn’t be needed, but it’s there just in case.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This command lists the files modified and added to the backup, along with their sizes, sorted with largest files at the bottom. It gave me some clear ideas which directories to exclude from this backup.&lt;/p&gt;
&lt;p&gt;The most recent backup added only 8 MB of data to the repository. That’s more like it.&lt;/p&gt;
&lt;p&gt;What did I exclude? &lt;code&gt;$HOME/.config/Slack&lt;/code&gt; and &lt;code&gt;$HOME/.local/share/flatpak&lt;/code&gt;. I’m sure I should exclude more, but I don’t need to figure that out right now. If this becomes a bottleneck again, I’ll look into it.&lt;/p&gt;
&lt;p&gt;I will also eventually forget old snapshots and prune the repository, which will remove the large files that I should never have bothered backing up in the first place. There is no rush.&lt;/p&gt;
</description>
        <pubDate>Fri, 04 Feb 2022 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/find-big-files-in-restic-backups</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/find-big-files-in-restic-backups</guid>
        
        
      </item>
    
      <item>
        <title>Get Push Notifications for Rate Alerts at wise.com</title>
        <description>&lt;p&gt;Wise (aka Transferwise) offers push notifications for foreign currency exchange rate alerts, but I had trouble creating them. I could easily create email alerts, but I wanted push notifications as well. Although it’s possible, it’s not obvious.&lt;/p&gt;
&lt;h1 id=&quot;the-solution&quot;&gt;The Solution&lt;/h1&gt;
&lt;p&gt;When you create a rate alert, &lt;strong&gt;subscribe with an email address associated with a Wise account&lt;/strong&gt;. When you do this, the final confirmation page will offer you options for email and push notifications. If you use an email address not associated with a Wise account, you will only see confirmation that you’ll receive rate alerts by email with no evidence that receiving push notifications was ever possible.&lt;/p&gt;
&lt;p&gt;As of January 2022, here is the complete flow.&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Visit &lt;a href=&quot;https://wi.se/rate_tracker&quot;&gt;https://wi.se/rate_tracker&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Create a rate alert and subscribe by email using &lt;strong&gt;the exact email address&lt;/strong&gt; associated with your Wise account. (I haven’t tried email addresses with &lt;code&gt;+&lt;/code&gt; in them, but I assume they won’t match, even though that would be helpful.)&lt;/li&gt;
&lt;li&gt;Wait to receive the email to activate your rate alert by confirming your email address. Visit the link in the email to confirm your email address.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This last page includes checkboxes for both email and push notification, as well as a button to unsubscribe.&lt;/p&gt;
&lt;h1 id=&quot;why-did-this-confuse-me&quot;&gt;Why Did This Confuse Me?&lt;/h1&gt;
&lt;p&gt;I wanted to receive rate alerts by push notification. Their Rate Tracker page claimed it was possible to do this by downloading their app. I already had their app installed on my phone, so I looked for the feature in the app. As of January 2022, it isn’t in the app. This was the first point of confusion.&lt;/p&gt;
&lt;p&gt;I returned to the Rate Tracker page, where it suggested to “Join Wise” in order to get push notifications. I already have a Wise account, so I tried logging in, believing that they would serve a different Rate Tracker page to logged-in users than to anonymous browsers. This changed nothing. This was the second point of confusion.&lt;/p&gt;
&lt;p&gt;I decided to try again by subscribing by email, in case that offered a clue about what was happening. I chose an email address that makes it convenient to filter incoming messages, because that lets me add a filter that would give me an email notification. This was not the email address associated with my Wise account, because nothing on any of these pages suggested that that was needed. Nowhere did I see anything in these repeated attempts that even &lt;em&gt;hinted&lt;/em&gt; at being able to get push notifications. This was the third point of confusion.&lt;/p&gt;
&lt;p&gt;I wanted to receive rate alerts by push notification, but I had to subscribe by email first. This is just not how I was thinking at the moment. I didn’t want email alerts; I wanted push notifications in the app. &lt;strong&gt;There were no words on any page that I encountered that promised push notifications at the end of the “subscribe by email” flow&lt;/strong&gt;, so I didn’t know that I needed to do that, let alone subscribe to a rate alert with exactly the One True email address that Wise was expecting me to use.&lt;/p&gt;
&lt;p&gt;I have asked Wise to improve the flow, which would make this article obsolete.&lt;/p&gt;
</description>
        <pubDate>Thu, 27 Jan 2022 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/get-push-notifications-on-rate-alerts-at-wise</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/get-push-notifications-on-rate-alerts-at-wise</guid>
        
        
      </item>
    
      <item>
        <title>Stop Using My Microphone As a Speaker!</title>
        <description>&lt;p&gt;When I connect my microphone over USB to my Pop!_OS machine, the OS insists on choosing the microphone both as &lt;em&gt;input device&lt;/em&gt; (yes!) and &lt;em&gt;output device&lt;/em&gt; (why?!?!). This forces me to switch the output device to my headphones, earbuds, or even merely the built-in speakers. Yes, there are ways to make that easier, but I’d rather not need to do it at all.&lt;/p&gt;
&lt;h1 id=&quot;a-solution&quot;&gt;A Solution&lt;/h1&gt;
&lt;p&gt;Use &lt;code&gt;pavucontrol&lt;/code&gt; (PulseAudio Volume Control) to configure the device as only an &lt;em&gt;input device&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;You might not even have this installed, so you might need to install it.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; sudo apt-get install pavucontrol&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;[Evidence&lt;/span&gt; that the OS is installing it...]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Run &lt;code&gt;pavucontrol&lt;/code&gt; and go to the Configuration tab.&lt;/li&gt;
&lt;li&gt;Connect the microphone. See the microphone show up on this tab. It’s probably using the “Analog Stereo Duplex” Profile.&lt;/li&gt;
&lt;li&gt;Select the “Analog Stereo Input” Profile.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That’s it! Now, when you connect the microphone next time, only the “Input Device” changes. The “Output Device” stays as it was. Victory!&lt;/p&gt;
</description>
        <pubDate>Thu, 20 Jan 2022 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/stop-using-my-microphone-as-a-speaker</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/stop-using-my-microphone-as-a-speaker</guid>
        
        
      </item>
    
      <item>
        <title>Install Microsoft Office 365 Inside Virtualbox</title>
        <description>&lt;p&gt;First things first: &lt;strong&gt;I did not want to do this at all&lt;/strong&gt;. I hadn’t touched Windows at all since Windows 7 and for good reasons. This experience merely affirmed that decision, but I digress.&lt;/p&gt;
&lt;h1 id=&quot;the-symptom&quot;&gt;The Symptom&lt;/h1&gt;
&lt;p&gt;When I tried to install Microsoft Office 365 applications in Windows 10 within Virtualbox, the installer got stuck at “We’re getting things ready…”. It got stuck at not always exactly the same spot. To recover, I would have to kill Virtualbox and try again.&lt;/p&gt;
&lt;h1 id=&quot;a-solution&quot;&gt;A Solution&lt;/h1&gt;
&lt;p&gt;I managed to get past this by doing the following:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Download the offline installer for Microsoft Office 365. (Maybe this isn’t necessary, but it worked.) This is shipped as a disk image. You’ll find this under “Other options” when you download the installer.&lt;/li&gt;
&lt;li&gt;Mount the disk image.&lt;/li&gt;
&lt;li&gt;Browse inside the disk image using File Explorer.&lt;/li&gt;
&lt;li&gt;Ignore the installer program (called “Setup”) at the root of the disk image. (It’s a trap.)&lt;/li&gt;
&lt;li&gt;Enter the folder called “Office”. There are two installers in this folder: a 32-bit one and a 64-bit one.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Do not yet run the 64-bit installer by merely double-clicking on it&lt;/strong&gt;. It’s called “System64”. Instead, run this installer in “Windows 8 Compatibility Mode” and “Run as administrator”. You’ll find Compatibility Mode inside the installer’s Properties. You’ll find “Run as administrator” by right-clicking the installer.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This seemed to work.&lt;/p&gt;
&lt;h1 id=&quot;why&quot;&gt;Why?!&lt;/h1&gt;
&lt;p&gt;Due to various accidents of history, I have a QuickBooks backup file. Microsoft Excel alleges that it can import the backup file so that I can work with the data. Why QuickBooks? Because I ran Windows in 2001 when I opened my company and that’s what my then-bookkeeper used.&lt;/p&gt;
&lt;h1 id=&quot;references&quot;&gt;References&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://ilmubersama.com/2019/07/29/office-365-installing-stuck-at-were-getting-things-ready/&quot; class=&quot;uri&quot;&gt;https://ilmubersama.com/2019/07/29/office-365-installing-stuck-at-were-getting-things-ready/&lt;/a&gt;. It’s in Indonesian, but it gave me the hint of running the installer in Windows 8 Compatbility Mode and as Administrator.&lt;/p&gt;
</description>
        <pubDate>Sun, 29 Aug 2021 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/install-microsoft-office-365-inside-virtualbox</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/install-microsoft-office-365-inside-virtualbox</guid>
        
        
      </item>
    
      <item>
        <title>Your git log output as CSV</title>
        <description>&lt;p&gt;I use &lt;code&gt;git&lt;/code&gt; to track cash expenses. (Don’t you?)&lt;/p&gt;
&lt;p&gt;No, really. I track cash expenses using my phone by adding empty commits to a &lt;code&gt;git&lt;/code&gt; repository, then pushing. (That’s my “sync” feature.) I still haven’t found a better way to automatically timestamp a bunch of simple one-line text entries that I can quickly sync off site. I use &lt;code&gt;git&lt;/code&gt; with Gitlab.&lt;/p&gt;
&lt;p&gt;When I want to collect that information to process it, I need the output in a more convenient format than the default &lt;code&gt;git log&lt;/code&gt; format. For that, I combine &lt;code&gt;git log&lt;/code&gt; with &lt;code&gt;jq&lt;/code&gt; to make magic happen.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode zsh&quot;&gt;&lt;code class=&quot;sourceCode zsh&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;$ git &lt;span class=&quot;kw&quot;&gt;log&lt;/span&gt; master...offsite-backup/master --format=&lt;span class=&quot;st&quot;&gt;&amp;#39;{&amp;quot;date&amp;quot;: &amp;quot;%aI&amp;quot;,&amp;quot;transaction&amp;quot;: &amp;quot;%s&amp;quot;}&amp;#39;&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;|&lt;/span&gt; jq --slurp &lt;span class=&quot;st&quot;&gt;&amp;#39;. | sort_by(.date)&amp;#39;&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;|&lt;/span&gt; jq -r &lt;span class=&quot;st&quot;&gt;&amp;#39;. [] | [.date, .transaction] | @csv&amp;#39;&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;&amp;gt;&lt;/span&gt; ~/Downloads/cash-transactions.csv&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I can make that easier to read.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode zsh&quot;&gt;&lt;code class=&quot;sourceCode zsh&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;$ git &lt;span class=&quot;kw&quot;&gt;log&lt;/span&gt; master...offsite-backup/master &lt;span class=&quot;kw&quot;&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    --format=&lt;span class=&quot;st&quot;&gt;&amp;#39;{&amp;quot;date&amp;quot;: &amp;quot;%aI&amp;quot;,&amp;quot;transaction&amp;quot;: &amp;quot;%s&amp;quot;}&amp;#39;&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a href=&quot;#cb2-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;|&lt;/span&gt; jq --slurp &lt;span class=&quot;st&quot;&gt;&amp;#39;. | sort_by(.date)&amp;#39;&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-4&quot;&gt;&lt;a href=&quot;#cb2-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;|&lt;/span&gt; jq -r &lt;span class=&quot;st&quot;&gt;&amp;#39;. [] | [.date, .transaction] | @csv&amp;#39;&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-5&quot;&gt;&lt;a href=&quot;#cb2-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;$HOME&lt;/span&gt;/Downloads/cash-transactions.csv&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In case not all this feels familiar to you yet:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Give me all the commit comments from my offsite backup. Before this, I did &lt;code&gt;git fetch offsite-backup&lt;/code&gt; to download the transactions.&lt;/li&gt;
&lt;li&gt;Format the commits as a stream of JSON objects (in preparation for &lt;code&gt;jq&lt;/code&gt; to process them), with the date in ISO 8601 format (&lt;a href=&quot;https://xkcd.com/1179/&quot;&gt;is there any other format?&lt;/a&gt;) and using the entire commit comment as the transaction’s description.&lt;/li&gt;
&lt;li&gt;Slurp the stream of items into a JSON array, then sort them by date (ascending, by default). Maybe I could have asked &lt;code&gt;git log&lt;/code&gt; to sort the commits in ascending order by commit date, but I didn’t try. That would eliminate a step.&lt;/li&gt;
&lt;li&gt;Grab the JSON output again, this time in “raw” mode, so that I can format it as CSV. (I don’t know why yet; I’m just doing it.) First, map the JSON array back into a stream of rows, then map each object into an array of values, then format as CSV. In order to format as CSV, &lt;code&gt;jq&lt;/code&gt; wants a stream of rows, each row as an array of values.&lt;/li&gt;
&lt;li&gt;Pipe the output to a CSV file so that I can more-easily import that into Libreoffice Calc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There you have a very tiny introduction to &lt;code&gt;jq&lt;/code&gt;! I find it &lt;em&gt;very&lt;/em&gt; handy and it helps me do things that I used to do by writing little Ruby programs. It’s my go-to tool for processing structured data and I love it especially for how it turns unstructured output from standard &lt;code&gt;bash&lt;/code&gt; tools into structured data more suitable for complicated processing.&lt;/p&gt;
&lt;p&gt;So… &lt;a href=&quot;https://stedolan.github.io/jq/manual/&quot;&gt;go learn about &lt;code&gt;jq&lt;/code&gt;&lt;/a&gt;! Set aside an hour. You’ll be glad you did.&lt;/p&gt;
</description>
        <pubDate>Wed, 11 Aug 2021 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/git-log-to-csv</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/git-log-to-csv</guid>
        
        
      </item>
    
      <item>
        <title>Roll back a branch at Github</title>
        <description>&lt;p&gt;This is one of those things that’s obvious once you see it, but perhaps not obvious when you’re looking for it.&lt;/p&gt;
&lt;p&gt;Let’s say you find yourself in an environment where you don’t have easy access to a shell, such as working on a project using Code Sandbox, Codepen, or some other in-the-browser cloud-based Javascript programming environment. It’s common in these environments to be able to commit changes to a Git repository—indeed, that might be the only way to publish and test changes to your project.&lt;/p&gt;
&lt;p&gt;Now imagine you’ve spent two hours trying to figure out why something’s not working and you’ve given up for today. Now you have 38 extra commits that you’d like to delete, but you only have access to your programming environment and &lt;a href=&quot;https://github.com&quot; class=&quot;uri&quot;&gt;https://github.com&lt;/a&gt;. What do you do?&lt;/p&gt;
&lt;p&gt;If you had a shell, you’d type something like &lt;code&gt;git reset --hard HEAD~38&lt;/code&gt; and be done with it, but you can’t do that in Code Sandbox nor at Github. What now?!&lt;/p&gt;
&lt;h2 id=&quot;a-solution&quot;&gt;A Solution&lt;/h2&gt;
&lt;p&gt;Refactor your Git branches at Github. No, really.&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Visit Github, specifically the &lt;strong&gt;Branches&lt;/strong&gt; in your project.&lt;/li&gt;
&lt;li&gt;For safety, create a branch level with your current working branch (which I’ll call &lt;strong&gt;main&lt;/strong&gt;). I’ll call the newly-created branch &lt;strong&gt;old-main-delete-me&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;If &lt;strong&gt;main&lt;/strong&gt; is the default branch, and it often is, then change the default branch to &lt;strong&gt;old-main-delete-me&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Now that &lt;strong&gt;main&lt;/strong&gt; is not the default branch, delete branch &lt;strong&gt;main&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Return to your project’s code, then visit the &lt;strong&gt;Commits&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Select the commit you’d like to roll back to, which I’ll call the “target commit”. In our example, that’s 38 commits before &lt;strong&gt;old-main-delete-me&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Create a branch called &lt;strong&gt;main&lt;/strong&gt; at the target commit.&lt;/li&gt;
&lt;li&gt;Change the default branch back to &lt;strong&gt;main&lt;/strong&gt;. Now is a good time to verify that &lt;strong&gt;main&lt;/strong&gt; correctly points to the target commit.&lt;/li&gt;
&lt;li&gt;Delete the branch &lt;strong&gt;old-main-delete-me&lt;/strong&gt;. Wait for Github to throw away your abandoned commits, whenever it gets around to doing garbage collection in your repository.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And now &lt;strong&gt;main&lt;/strong&gt; points 38 commits earlier than it used to. Enjoy!&lt;/p&gt;
</description>
        <pubDate>Thu, 01 Jul 2021 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/git-reset-commit-at-github</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/git-reset-commit-at-github</guid>
        
        
      </item>
    
      <item>
        <title>Change the Default Font in Master PDF Editor</title>
        <description>&lt;p&gt;If you use &lt;a href=&quot;https://code-industry.net/free-pdf-editor/&quot;&gt;Master PDF Editor&lt;/a&gt; on Linux, then don’t use Noto Sans as the font for Typewriter comments/annotations, because the font will sometimes render incorrectly. This isn’t just a rendering problem in the viewer, but a font problem in the document itself. (I see the same disfigured text when I view the document in Zathura.) Changing the default font is not obvious from the Settings UI, so do this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Open &lt;strong&gt;Tools &amp;gt; Settings&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;From the menu of option categories, choose &lt;strong&gt;Comments&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;In the unnamed drop-down box, choose &lt;strong&gt;Typewriter&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Under the settings for &lt;strong&gt;Text&lt;/strong&gt;, choose a different font. I like “Inter”, but that font just happens to work.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You know that you have this problem if you enter a Typewriter comment that contains the character sequence “fi”. I infer that there is some font ligature rendering problem with the default font Noto Sans in Master PDF Editor.&lt;/p&gt;
&lt;h2 id=&quot;the-details&quot;&gt;The Details&lt;/h2&gt;
&lt;p&gt;When I switched from Mac OS to Pop!_OS, I worried about how I would replace the venerable &lt;a href=&quot;https://pdfpen.com/pdfpen/&quot;&gt;PDF Pen&lt;/a&gt;. I &lt;em&gt;love&lt;/em&gt; PDF Pen. Since PDFs lie at the center of my company’s record-keeping system, I needed a solid and quick-to-use alternative. When I learned about Master PDF Editor, I felt encouraged. It seemed to have all the features I needed and I learned fairly quickly how to use it. It has the typical user experience quirks that one expects from Linux software, but it performs very well and has done everything I’ve needed it to do.&lt;/p&gt;
&lt;p&gt;Imagine my chagrin recently, when I noticed a &lt;strong&gt;font rendering problem&lt;/strong&gt; when I added a text annotation to a document. It took me a few weeks to notice a pattern: it happened whenever I wrote a word that contained the sequence “fi”. Ah, yes! I presume that this is a font ligature problem. (I don’t &lt;em&gt;know&lt;/em&gt; that it’s a font ligature problem, but it seems like a reasonable explanation.) After a few months of noticing this problem and working around it (by restricting myself to words without “fi” in them!), I finally figured out that this problem lies in the default font that Master PDF Editor uses for such annotations: “Noto Sans”. And maybe in other fonts. I haven’t tested extensively.&lt;/p&gt;
&lt;p&gt;It’s important to know this: I don’t know fonts. I am no expert in fonts. I don’t know &lt;em&gt;exactly&lt;/em&gt; where the problem lies. I don’t know whether to blame Master PDF Editor or the font or some strange interaction between the two. I only know this: when I type a word containing “fi” in a Typewriter comment in Master PDF Editor using the font Noto Sans, I get something that looks like this:&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;/img/change-the-default-font-in-master-pdf-editor/noto-sans-font-ligature-problem.jpg&quot; alt=&quot;Noto Sans does not work in Master PDF Editor on my machine&quot; /&gt;&lt;figcaption aria-hidden=&quot;true&quot;&gt;Noto Sans does not work in Master PDF Editor on my machine&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Those alternating “fi” strings should all look the same and, you know, &lt;em&gt;sensible&lt;/em&gt;. And this isn’t just a rendering problem when I view the document in Master PDF Editor, but the problem lies in the document. When I open that document in another PDF viewer, I see the same ugly text.&lt;/p&gt;
&lt;p&gt;I have notified the nice folks who produce Master PDF Editor and they have told me that they intend to fix the problem, likely by choosing a different default font for Typewriter comments. I also asked them to improve the Settings UI to add some kind of label or explanation for that unnamed drop-down box.&lt;/p&gt;
&lt;p&gt;Do you understand what’s going on here? Do you have the energy to figure it out? If you do, then feel free to let me know. I’m not burning to understand it, but I would probably find an explanation amusing.&lt;/p&gt;
</description>
        <pubDate>Thu, 01 Apr 2021 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/change-the-default-font-in-master-pdf-editor</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/change-the-default-font-in-master-pdf-editor</guid>
        
        
      </item>
    
      <item>
        <title>Linux Sound and USB Microphones</title>
        <description>&lt;p&gt;A few weeks ago, I was minding my own business, furiously trying to get ready for a Zoom meeting. I was moving USB sound devices around when, suddenly, without warning, Pop!_OS &lt;strong&gt;no longer detected my USB microphone&lt;/strong&gt;. No sound.&lt;/p&gt;
&lt;p&gt;Great.&lt;/p&gt;
&lt;p&gt;Unplug from the USB hub, then plug into the computer directly. No. Unplug from the left-side USB port and plug into the right-side USB port. No. Plug into each and every port in the USB hub. No.&lt;/p&gt;
&lt;p&gt;Great.&lt;/p&gt;
&lt;p&gt;Reboot.&lt;/p&gt;
&lt;p&gt;Plug in the microphone directly into the computer on the inconvenient-for-my-setup right-side USB port.&lt;/p&gt;
&lt;p&gt;Yes! Sound!&lt;/p&gt;
&lt;p&gt;I had my meeting over Zoom. All was well.&lt;/p&gt;
&lt;p&gt;But what had happened?!&lt;/p&gt;
&lt;h2 id=&quot;recreating-the-problem&quot;&gt;Recreating the Problem&lt;/h2&gt;
&lt;p&gt;Recreating the problem took a couple of weeks. I noticed this problem intermittently. My favorite! Eventually I looked straight at the error message in &lt;code&gt;syslog&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;D:&lt;/span&gt; [pulseaudio] module-udev-detect.c: /dev/snd/controlC1 is accessible: yes                                                             &lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;D:&lt;/span&gt; [pulseaudio] module-udev-detect.c: /devices/pci0000:00/0000:00:14.0/usb1/1-7/1-7:1.0/sound/card1 is busy: no                         &lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;#cb1-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;D:&lt;/span&gt; [pulseaudio] module-udev-detect.c: Loading module-alsa-card with arguments &lt;span class=&quot;st&quot;&gt;&amp;#39;device_id=&amp;quot;1&amp;quot; name=&amp;quot;usb-Blue_Microphones_Yeti_Stereo_Microphone-00&amp;quot; card_name=&amp;quot;alsa_card.usb-Blue_Microphones_Yeti_Stereo_Microphone-00&amp;quot; namereg_fail=false tsched=yes fixed_latency_range=no ignore_dB=no deferred_volume=yes use_ucm=yes avoid_resampling=no card_properties=&amp;quot;module-udev-detect.discovered=1&amp;quot;&amp;#39;&lt;/span&gt;                        &lt;/span&gt;
&lt;span id=&quot;cb1-4&quot;&gt;&lt;a href=&quot;#cb1-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;D:&lt;/span&gt; [pulseaudio] reserve-wrap.c: Device &lt;span class=&quot;st&quot;&gt;&amp;#39;Audio1&amp;#39;&lt;/span&gt; already locked.&lt;/span&gt;
&lt;span id=&quot;cb1-5&quot;&gt;&lt;a href=&quot;#cb1-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;E:&lt;/span&gt; [pulseaudio] module.c: Failed to load module &lt;span class=&quot;st&quot;&gt;&amp;quot;module-alsa-card&amp;quot;&lt;/span&gt; &lt;span class=&quot;er&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;argument:&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;device_id=&amp;quot;&lt;/span&gt;1&lt;span class=&quot;st&quot;&gt;&amp;quot; name=&amp;quot;&lt;/span&gt;usb-Blue_Microphones_Yeti_Stereo_Microphone-00&lt;span class=&quot;st&quot;&gt;&amp;quot; card_name=&amp;quot;&lt;/span&gt;alsa_card.usb-Blue_Microphones_Yeti_Stereo_Microphone-00&lt;span class=&quot;st&quot;&gt;&amp;quot; namereg_fail=false tsched=yes fixed_latency_range=no ignore_dB=no deferred_volume=yes use_ucm=yes avoid_resampling=no card_properties=&amp;quot;&lt;/span&gt;module-udev-detect.discovered=1&lt;span class=&quot;st&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;bu&quot;&gt;:&lt;/span&gt; initialization failed.&lt;/span&gt;
&lt;span id=&quot;cb1-6&quot;&gt;&lt;a href=&quot;#cb1-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;I:&lt;/span&gt; [pulseaudio] module-udev-detect.c: Card /devices/pci0000:00/0000:00:14.0/usb1/1-7/1-7:1.0/sound/card1 &lt;span class=&quot;er&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;alsa_card.usb-Blue_Microphones_Yeti_Stereo_Microphone-00&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ex&quot;&gt;failed&lt;/span&gt; to load module.&lt;/span&gt;
&lt;span id=&quot;cb1-7&quot;&gt;&lt;a href=&quot;#cb1-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;I:&lt;/span&gt; [pulseaudio] client.c: Created 3 &lt;span class=&quot;st&quot;&gt;&amp;quot;Native client (UNIX socket client)&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;OK. “Device X already locked.” This looks like a problem. “Failed to load module.” This looks like a problem. Fine.&lt;/p&gt;
&lt;p&gt;Search the web.&lt;/p&gt;
&lt;p&gt;Nothing useful.&lt;/p&gt;
&lt;p&gt;OK.&lt;/p&gt;
&lt;p&gt;After a few days, &lt;strong&gt;I could reproduce the problem reliably and I could work around the problem by rebooting&lt;/strong&gt;. I didn’t even care about &lt;em&gt;fixing&lt;/em&gt; the problem so much as finding a workaround that didn’t require rebooting. I wasn’t asking much.&lt;/p&gt;
&lt;h2 id=&quot;ask-the-right-question&quot;&gt;Ask the Right Question&lt;/h2&gt;
&lt;p&gt;I asked on &lt;code&gt;askubuntu&lt;/code&gt;, but they told me that I was in the wrong place, because I have Pop!_OS, which is essentially Ubuntu, but not &lt;em&gt;exactly&lt;/em&gt; Ubuntu. Fine. I moved my question to a better place.&lt;/p&gt;
&lt;p&gt;Here is the question: &lt;a href=&quot;https://unix.stackexchange.com/q/635813/256763&quot; class=&quot;uri&quot;&gt;https://unix.stackexchange.com/q/635813/256763&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And fortunately, &lt;em&gt;beautifully&lt;/em&gt;, I received a useful answer one day later.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stop Pipewire. Restart pulseaudio.&lt;/strong&gt; Gather wood. Check the traps.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; systemctl &lt;span class=&quot;at&quot;&gt;--user&lt;/span&gt; stop pipewire.service&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; systemctl &lt;span class=&quot;at&quot;&gt;--user&lt;/span&gt; restart pulseaudio&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;According to Paul Medynski:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It appears to be a race between pipewire and pulseaudio. I don’t know anything about pipewire, but it sometimes seems to grab a lock on the USB audio device before pulseaudio can access it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Fine.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; systemctl &lt;span class=&quot;at&quot;&gt;--user&lt;/span&gt; disable pipewire.service&lt;/span&gt;
&lt;span id=&quot;cb3-2&quot;&gt;&lt;a href=&quot;#cb3-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; systemctl &lt;span class=&quot;at&quot;&gt;--user&lt;/span&gt; disable pipewire.socket&lt;/span&gt;
&lt;span id=&quot;cb3-3&quot;&gt;&lt;a href=&quot;#cb3-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; systemctl &lt;span class=&quot;at&quot;&gt;--user&lt;/span&gt; restart pulseaudio&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And now all is well. I just tested by unplugging then plugging in my Blue Yeti microphone 6 times in 30 seconds. All is well.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;I have sound.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Thank you, Paul. I appreciate you for taking the time to answer my question.&lt;/p&gt;
</description>
        <pubDate>Wed, 10 Mar 2021 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/linux-sound-and-usb-microphones</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/linux-sound-and-usb-microphones</guid>
        
        
      </item>
    
      <item>
        <title>A Puzzle about HTML: &amp;lt;details&amp;gt; and flexbox</title>
        <description>&lt;p&gt;This is a puzzle, rather than a solution. I publish this here in hopes that a web search engine crawls this article, someone finds it, knows the answer, and takes a moment to tell me. Will you please be that person?&lt;/p&gt;
&lt;h1 id=&quot;problem&quot;&gt;Problem&lt;/h1&gt;
&lt;p&gt;I have recently become enamored by the HTML 5 &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt; element. I like that it allows me to elide certain details on a page until the reader wants to read them. I use it to make my pages more easily skimmed, hoping that that confers some benefit to the reader. I’m trying to be nice &lt;em&gt;and&lt;/em&gt; hoping that it helps convert some readers into customers. (I have to feed my family.)&lt;/p&gt;
&lt;p&gt;The structure of a &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt; element is this:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode html&quot;&gt;&lt;code class=&quot;sourceCode html&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;&amp;lt;details&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;A summary that readers always see.&lt;span class=&quot;kw&quot;&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;#cb1-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  [... various HTML elements that the reader doesn&amp;#39;t see until they click on the summary, such as &lt;span class=&quot;kw&quot;&gt;&amp;lt;p&amp;gt;&lt;/span&gt;s ...]&lt;/span&gt;
&lt;span id=&quot;cb1-4&quot;&gt;&lt;a href=&quot;#cb1-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;&amp;lt;/details&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As you can imagine, I think of the content inside the &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt; element as text like any other on the page, so I’d like to style it similarly. Routinely, I use Flexbox’s &lt;code&gt;gap&lt;/code&gt; property to create interparagraph vertical spacing throughout the document. This works as I’d expect in general, but not inside a &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt; element.&lt;/p&gt;
&lt;p&gt;If I style the &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt; element as &lt;code&gt;flex&lt;/code&gt;, then the &lt;code&gt;gap&lt;/code&gt; property doesn’t apply to the children of this element. Instead, I have to do this:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode html&quot;&gt;&lt;code class=&quot;sourceCode html&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;&amp;lt;details&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;A summary that readers always see.&lt;span class=&quot;kw&quot;&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a href=&quot;#cb2-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;&amp;lt;section&lt;/span&gt; &lt;span class=&quot;er&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;the-details&amp;quot;&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-4&quot;&gt;&lt;a href=&quot;#cb2-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      [... various HTML elements that the reader doesn&amp;#39;t see until they click on the summary, such as &lt;span class=&quot;kw&quot;&gt;&amp;lt;p&amp;gt;&lt;/span&gt;s ...]&lt;/span&gt;
&lt;span id=&quot;cb2-5&quot;&gt;&lt;a href=&quot;#cb2-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-6&quot;&gt;&lt;a href=&quot;#cb2-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;&amp;lt;/details&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If I style &lt;code&gt;section.the-details&lt;/code&gt; as &lt;code&gt;flex&lt;/code&gt;, then the &lt;code&gt;gap&lt;/code&gt; property applies to its children as I’d expect.&lt;/p&gt;
&lt;p&gt;Why?&lt;/p&gt;
&lt;p&gt;I’ve provided &lt;a href=&quot;https://codepen.io/jbrains/pen/OJbmzoB&quot;&gt;an example with Codepen&lt;/a&gt; that illustrates the problem.&lt;/p&gt;
&lt;p&gt;If you know why this happens, then please tell me. Scroll down to see various ways to contact me.&lt;/p&gt;
&lt;p&gt;Many thanks.&lt;/p&gt;
</description>
        <pubDate>Mon, 01 Mar 2021 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/a-puzzle-about-html-details-and-flexbox</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/a-puzzle-about-html-details-and-flexbox</guid>
        
        
      </item>
    
      <item>
        <title>I Want To Listen With My Headphones, Not My Microphone!</title>
        <description>&lt;p&gt;I love my &lt;a href=&quot;https://www.amazon.com/Blue-Yeti-USB-Microphone-Blackout/dp/B00N1YPXW2?&amp;amp;linkCode=ll1&amp;amp;tag=jbrains.ca-20&amp;amp;linkId=ff47db37b788dcf048c505d0efdf017c&amp;amp;language=en_US&amp;amp;ref_=as_li_ss_tl&quot;&gt;Blue Yeti Microphone&lt;/a&gt;, but it creates problems for me when I connect my audio devices to my laptop for video conferencing. I often have to fiddle with the Linux sound settings after I connect everything in order to fix the interesting assumptions that Pop!_OS has made about which audio devices perform which jobs.&lt;/p&gt;
&lt;p&gt;If I don’t pay attention, then I can’t hear anything through my Bluetooth headset, which annoys me at the best of times, but embarrasses me (just a little) when my client sees me fumbling at the beginning of a session.&lt;/p&gt;
&lt;h1 id=&quot;solution&quot;&gt;Solution&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Remember that the last connected device wins&lt;/strong&gt;. This means connecting the devices in this sequence:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Blue Yeti Microphone&lt;/li&gt;
&lt;li&gt;Bluetooth headset (&lt;a href=&quot;https://www.amazon.com/Bluetooth-Retractable-Headphones-Sweatproof-Earphones/dp/B088FYPRKK?&amp;amp;linkCode=ll1&amp;amp;tag=jbrains.ca-20&amp;amp;linkId=7e35891565a77072c091ceed493edf2a&amp;amp;language=en_US&amp;amp;ref_=as_li_ss_tl&quot;&gt;SX-991&lt;/a&gt;, in case you wondered)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That’s it. If I connect them in the other sequence, then I get no audio through my Bluetooth headset.&lt;/p&gt;
&lt;h1 id=&quot;explanation&quot;&gt;Explanation&lt;/h1&gt;
&lt;p&gt;The Blue Yeti Microphone also acts as an output device (speaker, headphones), because it contains a built-in monitor for the microphone. I can connect wired headphones to the microphone to hear how I sound through the microphone while I’m speaking. I don’t use this feature, but I have it available. Accordingly, the Blue Yeti Microphone advertises itself to the operating system as both an input and output device, so Pop!_OS chooses it as an output device when I connect the microphone by USB.&lt;/p&gt;
&lt;p&gt;Worse, sadly, Linux doesn’t &lt;em&gt;always&lt;/em&gt; detect the microphone correctly, leading to other problems. Evidently, &lt;strong&gt;audio on Linux is hard&lt;/strong&gt;. I accept it as it is and I forgive it.&lt;/p&gt;
</description>
        <pubDate>Tue, 23 Feb 2021 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/i-want-to-listen-with-my-headphones-not-my-microphone</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/i-want-to-listen-with-my-headphones-not-my-microphone</guid>
        
        
      </item>
    
      <item>
        <title>How To Resize A Comment Box In LibreOffice Calc</title>
        <description>&lt;p&gt;I did not expect this to stymie me today.&lt;/p&gt;
&lt;video controls width=&quot;70%&quot;&gt;
&lt;source src=&quot;/img/how-to-resize-a-comment-in-libreoffice-calc/fail-to-resize-comment.webm&quot; type=&quot;video/webm&quot;&gt;
Sorry, your browser doesn’t support embedded videos.
&lt;/source&gt;
&lt;/video&gt;
&lt;p&gt;No matter how much I try to drag, I can’t resize the comment. What?!&lt;/p&gt;
&lt;h1 id=&quot;solution&quot;&gt;Solution&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Show the comment&lt;/strong&gt;. Really. After I show the comment, I can resize it. I can’t resize the comment while I’m editing it, but I can resize the comment while I’m merely looking it.&lt;/p&gt;
&lt;p&gt;Annoying. I’m going to forget this. When I’m editing the comment, the icon suggests to me that I will be able to resize the comment box.&lt;/p&gt;
&lt;p&gt;As usual, I published this so that I would find it when later I have the same problem.&lt;/p&gt;
&lt;h1 id=&quot;reference&quot;&gt;Reference&lt;/h1&gt;
&lt;p&gt;OpenOffice forum, &lt;a href=&quot;https://forum.openoffice.org/en/forum/viewtopic.php?f=9&amp;amp;t=63642&quot; class=&quot;uri&quot;&gt;https://forum.openoffice.org/en/forum/viewtopic.php?f=9&amp;amp;t=63642&lt;/a&gt;. It looks like LibreOffice has the same behavior.&lt;/p&gt;
</description>
        <pubDate>Mon, 08 Feb 2021 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/resizing-a-comment-box-in-libreoffice-calc</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/resizing-a-comment-box-in-libreoffice-calc</guid>
        
        
      </item>
    
      <item>
        <title>Print Sensibly to PDF in Firefox</title>
        <description>&lt;p&gt;I use HTML and CSS as my word processor. No, really. I started doing this about two years ago and I really like the simplicity of writing in Markdown, processing that as HTML, then producing documents that I can distribute either as web pages or as PDF. I could even dump them into a Leanpub book if I wanted to. I compose in Typora, do power editing in Kakoune, use Jekyll and pandoc for production, then Firefox to preview. Finally, I can use Firefox to print to PDF. I spent hours crafting a print CSS stylesheet that I can feel good about.&lt;/p&gt;
&lt;p&gt;Today, however, I ran into trouble: the header were suddenly flush with the edge of the page. This image illustrates what I wanted compared to what I got.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;/img/firefox-print-margins/Firefox-print-margins.png&quot; alt=&quot;What I wanted compared to what I got.&quot; /&gt;&lt;figcaption aria-hidden=&quot;true&quot;&gt;What I wanted compared to what I got.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;My “word processor” produces the document, but Firefox adds the header and footer. Setting the margins for the document was easy. Setting the margins for the header was… not obvious.&lt;/p&gt;
&lt;p&gt;No options in the Print Preview. No options in the Print… dialog. Nothing. Srsly!&lt;/p&gt;
&lt;h1 id=&quot;the-solution&quot;&gt;The Solution&lt;/h1&gt;
&lt;p&gt;Evidently, one must change configuration settings deep in the bowels of Firefox. You can read more at &lt;a href=&quot;https://support.mozilla.org/en-US/questions/1061569&quot; class=&quot;uri&quot;&gt;https://support.mozilla.org/en-US/questions/1061569&lt;/a&gt;.&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;In Firefox, visit &lt;code&gt;about:config&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Accept the risk of changing the complicated and scary configuration settings.&lt;/li&gt;
&lt;li&gt;Search for preferences matching the text &lt;code&gt;print.Mozilla_Save_to_PDF&lt;/code&gt;, since Mozilla recently (in mid-January 2021) changed the name of this device from “Print to File” to “Mozilla Save to PDF”, at least on Linux.&lt;/li&gt;
&lt;li&gt;Look for four configuration settings whose names match the pattern &lt;code&gt;print.Mozilla_Save_to_PDF.print_edge_&amp;lt;where&amp;gt;&lt;/code&gt;, for the four areas of the page: bottom, left, right, top.&lt;/li&gt;
&lt;li&gt;Set values for each of these to match the desired margins. (See the next section for details.)&lt;/li&gt;
&lt;li&gt;Close any print preview and open it again. Yay!&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;the-print-edge-margin-units&quot;&gt;The Print Edge Margin Units&lt;/h2&gt;
&lt;p&gt;If your paper measurement system is Colonial/Imperial/Archaic, such as “Letter (8.5 inches by 11 inches)”, then enter a margin as a multiple of 0.01 inch. For example, for a 0.5-inch margin, enter 50, and for a 0.25-inch margin, enter 25.&lt;/p&gt;
&lt;p&gt;If you measure paper using Modern/Sensible/Metric designations, such as “A4”, then enter a margin in millimetres, like a functioning adult.&lt;/p&gt;
&lt;p&gt;I live in Canada. Sadly, we are Colonial. Hundredths of an inch it is.&lt;/p&gt;
&lt;p&gt;I chose left and right margins of 50/100 inch as well as top and bottom margins of 25/100 inch. Excellent! You can see the great results in the image near the beginning of this article.&lt;/p&gt;
&lt;p&gt;Now &lt;strong&gt;I simply have to remember to check this if I ever need to print an article onto physical sheets of paper&lt;/strong&gt;.&lt;/p&gt;
&lt;section class=&quot;video&quot;&gt;
&lt;iframe src=&quot;https://www.youtube.com/embed/WQ4lDJs8skg?start=153&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen&gt;
&lt;/iframe&gt;
&lt;/section&gt;
&lt;h2 id=&quot;changes-in-mid-january-2021&quot;&gt;Changes in Mid-January 2021&lt;/h2&gt;
&lt;p&gt;Recently I noticed that my header and footer moved back to the edge of the page. This happened at the same time that the print dialog changed, at least on Linux. I hunted through the configuration properties and found the new properties &lt;code&gt;print.print_edge_bottom&lt;/code&gt; (and so on for the four edges of the page) which &lt;em&gt;seem&lt;/em&gt; to do nothing, because when I changed those values, nothing changed.&lt;/p&gt;
&lt;p&gt;I did, however, after a while, notice another batch of “print edge” configuration settings named &lt;code&gt;print.print_Mozilla_Save_to_PDF.print_edge_bottom&lt;/code&gt; and so on. When I changed these values, then opened a new print preview, the header and footer moved to the expected spot on the page. Success!&lt;/p&gt;
&lt;p&gt;Since I feel lucky, I reset the properties &lt;code&gt;print.print_edge_*&lt;/code&gt; to their default values and &lt;em&gt;deleted&lt;/em&gt; the properties &lt;code&gt;print.printer_Print_to_File.print_edge_*&lt;/code&gt;, since these last ones seem now obsolete. I will update this article if, in the future, these settings cause any problems.&lt;/p&gt;
</description>
        <pubDate>Fri, 08 Jan 2021 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/print-sensibly-to-pdf-in-firefox</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/print-sensibly-to-pdf-in-firefox</guid>
        
        
      </item>
    
      <item>
        <title>Rename a Bunch of Files</title>
        <description>&lt;p&gt;A reader asked me simply “How to rename a bunch of files?” but left a clearly fake email address, so I couldn’t reply directly to them. Instead, I’ll reply to you, dear readers.&lt;/p&gt;
&lt;p&gt;One can rename a bunch of files in myriad ways, using plain &lt;code&gt;bash&lt;/code&gt; scripts, software like A Better Finder Rename (Mac OS), and tools like &lt;code&gt;zmv&lt;/code&gt;. Most people &lt;em&gt;satisfice&lt;/em&gt; here: they learn one way to do it that works well enough that they can perform effortlessly enough, then they just use it. I learned another way to do it in the past year and this has become my current favorite: using the &lt;code&gt;bulkrename&lt;/code&gt; command in &lt;code&gt;ranger&lt;/code&gt;, &lt;a href=&quot;https://github.com/ranger/ranger&quot;&gt;a file manager that feels like &lt;code&gt;vim&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&quot;my-solution&quot;&gt;My Solution&lt;/h1&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Open &lt;code&gt;ranger&lt;/code&gt; on a folder.&lt;/li&gt;
&lt;li&gt;Mark the files to rename.&lt;/li&gt;
&lt;li&gt;Enter the command &lt;code&gt;:bulkrename&lt;/code&gt;. This opens an editor with each file name on a separate line.&lt;/li&gt;
&lt;li&gt;Edit the file. The first line becomes the new name of the first file, the second line becomes the new name of the second file, and so on.&lt;/li&gt;
&lt;li&gt;Save the file and exit the editor. This opens and editor with a summary of the rename commands that correspond to the changes I made to the filenames.&lt;/li&gt;
&lt;li&gt;Save the file and exit the editor once more. This renames the files.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This allows me to bring the full power of my editor to renaming files: creating sequence numbers, matching regular expressions, whatever I need. I can even use some general algorithm to rename 90% of the files then patch the other 10% by hand. I &lt;em&gt;love&lt;/em&gt; the flexibility of it and you might, too.&lt;/p&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;
&lt;h1 id=&quot;would-you-rather-watch&quot;&gt;Would You Rather Watch?&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://asciinema.org/a/347181&quot;&gt;&lt;img src=&quot;https://asciinema.org/a/347181.svg&quot; alt=&quot;asciicast&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Mon, 13 Jul 2020 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/rename-a-bunch-of-files</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/rename-a-bunch-of-files</guid>
        
        
      </item>
    
      <item>
        <title>TuneIn Radio Stops Streaming After a Minute Or So</title>
        <description>&lt;p&gt;I had to convince my Android phone that it had permission to let TuneIn Radio continue to stream music even after my screen went dark from inactivity. I don’t know what changed recently that caused me to need to do this, but I needed to do it.&lt;/p&gt;
&lt;h1 id=&quot;my-solution&quot;&gt;My Solution&lt;/h1&gt;
&lt;p&gt;Right now, my Galaxy Note 8 runs Android 9, so these instructions might have become out of date by the time you read this. I hope they still help you.&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Open Android settings.&lt;/li&gt;
&lt;li&gt;Choose &lt;strong&gt;Apps&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Choose the app TuneIn Radio.&lt;/li&gt;
&lt;li&gt;In the &lt;strong&gt;Usage&lt;/strong&gt; section, choose &lt;strong&gt;Battery&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Notice that the option &lt;strong&gt;Allow background activity&lt;/strong&gt; is &lt;em&gt;disabled&lt;/em&gt;. Enable it.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That’s it! Now TuneIn Radio continues to run in the background, even when I lock my device.&lt;/p&gt;
</description>
        <pubDate>Sun, 23 Feb 2020 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/tunein-radio-stops-streaming-after-a-minute-or-so</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/tunein-radio-stops-streaming-after-a-minute-or-so</guid>
        
        
      </item>
    
      <item>
        <title>Linux, snap, and Mysterious File Permission Errors</title>
        <description>&lt;p&gt;I figured this out, but it took me about 2 hours to think of it. I hope that by writing this, you will not need 2 hours to figure it out.&lt;/p&gt;
&lt;h2 id=&quot;the-symptom&quot;&gt;The Symptom&lt;/h2&gt;
&lt;p&gt;I installed a &lt;a href=&quot;https://snapcraft.io&quot;&gt;&lt;strong&gt;snap&lt;/strong&gt;&lt;/a&gt; package. I tried to run it. I saw this:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;PermissionError:&lt;/span&gt; [Errno 13] Permission denied: &lt;span class=&quot;st&quot;&gt;&amp;#39;/path/to/the/file/in/question.blah&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;File permission error. Fine!&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; chmod &lt;span class=&quot;at&quot;&gt;-R&lt;/span&gt; 777 /path/to/the/file/&lt;span class=&quot;pp&quot;&gt;**&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Try again… and &lt;code&gt;Permission denied&lt;/code&gt; again.&lt;/p&gt;
&lt;p&gt;I checked the ownership and permissions of &lt;em&gt;every&lt;/em&gt; directory in the path of this file. The correct user owned them all; they all allowed read, write, and execute. (Of course, I kept track of all the directories and files for which I did this, because I wanted to undo all that once I figured out what was happening!)&lt;/p&gt;
&lt;h2 id=&quot;the-problem&quot;&gt;The Problem&lt;/h2&gt;
&lt;p&gt;I had to give the &lt;strong&gt;snap&lt;/strong&gt; package explicit authority to touch the files on my removable media devices, because…&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I have two physical drives in my laptop: one for booting and the other for extra storage.&lt;/li&gt;
&lt;li&gt;I have symbolic links from my boot drive (where &lt;code&gt;/home&lt;/code&gt; is located) to most of my data (on &lt;code&gt;/mnt/extra-space&lt;/code&gt;), including the files that this &lt;strong&gt;snap&lt;/strong&gt; package was trying to operate on.&lt;/li&gt;
&lt;li&gt;I installed the tool in question as a &lt;strong&gt;snap&lt;/strong&gt; instead of as a conventional Linux package (or whatever one correctly calls a “non-&lt;strong&gt;snap&lt;/strong&gt;” package).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Even though all the file permissions looked correct on &lt;code&gt;zsh&lt;/code&gt;/&lt;code&gt;bash&lt;/code&gt;, the &lt;strong&gt;snap&lt;/strong&gt; was not allowed to touch those files, and the resulting &lt;code&gt;Permission denied&lt;/code&gt; error looks the same in both cases. Great!&lt;/p&gt;
&lt;h2 id=&quot;the-solution&quot;&gt;The Solution&lt;/h2&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; sudo snap connect &lt;span class=&quot;va&quot;&gt;$SNAP_NAME&lt;/span&gt;:removable-media&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I read this as “Please allow the &lt;strong&gt;snap&lt;/strong&gt; named &lt;code&gt;$SNAP_NAME&lt;/code&gt; to talk to &lt;code&gt;removable-media&lt;/code&gt;”. I consider the word “connect” as out of place here. If I’d known the technical terms involved, then I’d have had better keywords to search for and I’d have spent less than 2 hours figuring all this out.&lt;/p&gt;
&lt;h3 id=&quot;why-sudo&quot;&gt;Why &lt;code&gt;sudo&lt;/code&gt;?&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;This is because you need to prove you have system snap modification rights on your machine. You can put your user in the ultra restricted circle of snap administrators on your system by logging in.&lt;/p&gt;
&lt;p&gt;For this, just create a snap account if you don’t have one already on &lt;a href=&quot;https://login.ubuntu.com/&quot; class=&quot;uri&quot;&gt;https://login.ubuntu.com/&lt;/a&gt;. Take the time to do this, we’ll wait!&lt;/p&gt;
&lt;p&gt;—&lt;a href=&quot;https://tutorials.ubuntu.com/tutorial/advanced-snap-usage#1&quot;&gt;“Advanced snap usage”&lt;/a&gt;, a tutorial from Ubuntu.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;No, thanks. This feels weird to me: authenticating with some server outside my machine in order to establish that I have permission to do something on my machine. Surely I should be able to give myself the necessary authorization without creating an account on some web site somewhere!&lt;/p&gt;
&lt;h3 id=&quot;devmode-i-wouldnt.&quot;&gt;&lt;code&gt;devmode&lt;/code&gt;! I wouldn’t.&lt;/h3&gt;
&lt;p&gt;You could install the &lt;strong&gt;snap&lt;/strong&gt; in &lt;code&gt;devmode&lt;/code&gt; and move on with your life, but it &lt;em&gt;always&lt;/em&gt; makes me nervous when I give a tool more permission than it needs, &lt;strong&gt;particularly when I don’t really know what I’m doing&lt;/strong&gt;. Unintended consequences and all that.&lt;/p&gt;
&lt;h2 id=&quot;an-explanation&quot;&gt;An Explanation&lt;/h2&gt;
&lt;p&gt;By default, &lt;strong&gt;snap&lt;/strong&gt; &lt;em&gt;confines&lt;/em&gt; its packages to only touch your &lt;code&gt;$HOME&lt;/code&gt; directory. The &lt;strong&gt;snap&lt;/strong&gt; packages operate by default in a &lt;em&gt;sandbox&lt;/em&gt; environment designed to limit damage to your system. I really like this! Since I want this particular &lt;strong&gt;snap&lt;/strong&gt; to write to a directory on my secondary drive, which is mounted somewhere on &lt;code&gt;/mnt&lt;/code&gt;, I need to give that &lt;strong&gt;snap&lt;/strong&gt; explicit permission to &lt;em&gt;connect&lt;/em&gt; to the &lt;code&gt;removable-media&lt;/code&gt; &lt;em&gt;slot&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;If you’re not sure which permissions/connections your &lt;strong&gt;snap&lt;/strong&gt; has, then list them this way:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb4&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb4-1&quot;&gt;&lt;a href=&quot;#cb4-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; snap connections &lt;span class=&quot;va&quot;&gt;$SNAP_NAME&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;strong&gt;snap&lt;/strong&gt; environment connects to some slots automatically, then marks as &lt;code&gt;manual&lt;/code&gt; the connections that you create yourself. Clear enough.&lt;/p&gt;
&lt;p&gt;I hope this helps you get past your immediate obstacle.&lt;/p&gt;
&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;
&lt;p&gt;Read more at &lt;a href=&quot;https://ubuntu.com/blog/a-guide-to-snap-permissions-and-interfaces&quot; class=&quot;uri&quot;&gt;https://ubuntu.com/blog/a-guide-to-snap-permissions-and-interfaces&lt;/a&gt; if you have the combination of interest and energy. This guide is slightly out of date already (&lt;em&gt;interfaces&lt;/em&gt; have been renamed as &lt;em&gt;connections&lt;/em&gt;), but I understood enough.&lt;/p&gt;
&lt;p&gt;I found a tutorial that explains more about &lt;em&gt;connections&lt;/em&gt; at &lt;a href=&quot;https://tutorials.ubuntu.com/tutorial/advanced-snap-usage&quot; class=&quot;uri&quot;&gt;https://tutorials.ubuntu.com/tutorial/advanced-snap-usage&lt;/a&gt;, which I’m reading now. I seem to understand what it tries to explain to me, which makes me feel encouraged. Sadly, this tutorial also refers to &lt;em&gt;interfaces&lt;/em&gt; rather than the modern name &lt;em&gt;connections&lt;/em&gt;, but the information seems accurate, at least as far as I can tell as a novice.&lt;/p&gt;
</description>
        <pubDate>Wed, 30 Oct 2019 11:03:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/Linux-snap-file-permissions</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/Linux-snap-file-permissions</guid>
        
        
      </item>
    
      <item>
        <title>Linux, Firefox, Google Hangouts, and &apos;Camera Not Found&apos;</title>
        <description>&lt;p&gt;I tried to join a Google Hangouts meeting and my laptop’s webcam didn’t turn on. The settings in Hangouts didn’t let me choose a camera, instead reading “Camera Not Found”. This happened in Firefox, so I tried Chrome, with the same result.&lt;/p&gt;
&lt;p&gt;Was the problem with Firefox? Chrome? Linux? Hardware?!&lt;/p&gt;
&lt;p&gt;Fortunately, &lt;strong&gt;I found a straightforward solution&lt;/strong&gt;: I had accidentally deactivated my webcam. Stupid me. Press &lt;code&gt;Fn+F10&lt;/code&gt; to reactivate it.&lt;/p&gt;
&lt;p&gt;On my laptop’s keyboard, if I press &lt;code&gt;Fn+F10&lt;/code&gt;, this toggles the webcam on/off. I presume that this makes it easy to cut the webcam very quickly. I like the feature, but I had never paid attention to it, and since &lt;code&gt;F10&lt;/code&gt; sits beside &lt;code&gt;F9&lt;/code&gt;, and &lt;code&gt;F9&lt;/code&gt; is “increase brightness”, &lt;strong&gt;I probably accidentally grazed &lt;code&gt;F10&lt;/code&gt; and got no visible feedback that I had done it&lt;/strong&gt;, and then I’d forgot about it until I tried to use the camera.&lt;/p&gt;
&lt;p&gt;I looked around for commands to help me detect that I had pressed &lt;code&gt;Fn+F10&lt;/code&gt;, but I couldn’t find any. Please tweet me if you know how to do that! Not &lt;code&gt;modprobe [-r] uvcvideo&lt;/code&gt;, which seems to provide another layer of activate/deactivate. If I press &lt;code&gt;Fn+F10&lt;/code&gt;, then &lt;code&gt;lsmod&lt;/code&gt; still lists the webcam device, so that doesn’t help me. Maybe the &lt;code&gt;Fn+F10&lt;/code&gt; key combination is a hardware switch in the laptop somewhere? I’d like to learn more.&lt;/p&gt;
</description>
        <pubDate>Thu, 20 Jun 2019 16:30:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/Linux-Firefox-Google-Hangouts-and-Camera-Not-Found</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/Linux-Firefox-Google-Hangouts-and-Camera-Not-Found</guid>
        
        
      </item>
    
      <item>
        <title>Copy/Paste, Byobu, Scrollback Mode</title>
        <description>&lt;p&gt;I hope that you find this article when you have the same trouble that I had figuring out how to copy text to the system clipboard on Linux in Byobu’s scrollback mode.&lt;/p&gt;
&lt;h1 id=&quot;what-to-do&quot;&gt;What To Do&lt;/h1&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Enter &lt;strong&gt;Scrollback mode&lt;/strong&gt; by pressing &lt;code&gt;F7&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Scroll until you can see the text that you’d like to copy.&lt;/li&gt;
&lt;li&gt;Turn &lt;strong&gt;Mouse mode&lt;/strong&gt; to &lt;strong&gt;on&lt;/strong&gt; by pressing &lt;code&gt;Alt+F12&lt;/code&gt;. You’ll see “Mouse: ON”&lt;/li&gt;
&lt;li&gt;Hold &lt;code&gt;Shift&lt;/code&gt; and use the mouse/trackpad to select the text that you’d like to copy. You’ll see the selected text highlighted. Press &lt;code&gt;Shift+Ctrl+c&lt;/code&gt; to copy. If you have a system clipboard viewer, then verify that the selected text has reached the clipboard.&lt;/li&gt;
&lt;li&gt;Turn &lt;strong&gt;Mouse mode&lt;/strong&gt; back to &lt;strong&gt;off&lt;/strong&gt; by pressing &lt;code&gt;Alt+F12&lt;/code&gt; again. You’ll see “Mouse: OFF”&lt;/li&gt;
&lt;li&gt;Leave &lt;strong&gt;Scrollback mode&lt;/strong&gt; by pressing &lt;code&gt;Ctrl+c&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Yay!&lt;/p&gt;
&lt;p&gt;Holding &lt;code&gt;Shift&lt;/code&gt; while selecting the text seems to be the critical part. Without &lt;code&gt;Shift&lt;/code&gt;, Byobu (screen?) pastes the text immediately then discards it, rather than pasting it into the system clipboard. You can imagine how frustrating that was for me.&lt;/p&gt;
&lt;h1 id=&quot;reference&quot;&gt;Reference&lt;/h1&gt;
&lt;p&gt;Stack Overflow, &lt;a href=&quot;https://stackoverflow.com/questions/54021367/straightforward-way-of-copying-text-from-byobu-to-system-clipboard&quot;&gt;“Straightforward way of copying text from byobu to system clipboard?”&lt;/a&gt;. Thank you to user &lt;code&gt;gcuendet&lt;/code&gt;. This told me that we need &lt;code&gt;Shift&lt;/code&gt; when selecting the text to copy.&lt;/p&gt;
</description>
        <pubDate>Mon, 17 Jun 2019 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/copy-paste-byobu-scrollback-mode</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/copy-paste-byobu-scrollback-mode</guid>
        
        
      </item>
    
      <item>
        <title>Use a Fujitsu ScanSnap Scanner With Linux</title>
        <description>&lt;p&gt;I used to rely heavily for my Fujitsu ScanSnap S510M scanner, but by 2023, I almost never use it. I use scanning apps on my Android phone to scan documents, and since I don’t scan &lt;em&gt;long&lt;/em&gt; documents (more than a few pages), this suffices for my needs. As a result, I was surprised when I received an email from a concerned reader who told me that they couldn’t follow these instructions to install XSane. I hadn’t used XSane for about two years, but I remembered using it and it worked fine.&lt;/p&gt;
&lt;h2 id=&quot;what-happened&quot;&gt;What Happened?&lt;/h2&gt;
&lt;p&gt;I don’t know. It appears that XSane has entered some kind of in-between state as a project.&lt;/p&gt;
&lt;p&gt;If you don’t know—and I &lt;em&gt;barely&lt;/em&gt; know—XSane provides a graphical application for using the &lt;code&gt;sane&lt;/code&gt; libraries to drive scanners, such as the S510M. In typical programmer style, the community refers to these applications as “front ends”, so if you see that term, simply substitute the term “applications” (or even “apps”) that typical, everyday people would tend to understand. It’s enough to know that computers use &lt;code&gt;sane&lt;/code&gt; to talk to your scanner and that applications such as XSane make it easier for humans to use &lt;code&gt;sane&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Somewhere along the way, &lt;a href=&quot;https://xsane.org&quot;&gt;XSane’s web site&lt;/a&gt; began to refer to a German-language site at &lt;a href=&quot;https://wiki.ubuntuusers.de/XSane/&quot;&gt;ubuntuusers.de&lt;/a&gt;’s Wiki. Fortunately, I read just enough German not to be frightened by this, and when I scrolled down to the bottom of the page, I found a link to &lt;a href=&quot;http://www.fifi.org/doc/xsane/html/sane-xsane-doc.html&quot;&gt;an English-language snapshot of the documentation&lt;/a&gt; along with the simple comment “The original site is no longer online”. I also found a link to the source code, which shows no new commits for approximately 1 year. From what I’ve been able to understand so far, XSane continues to work, but there are no more friendly instructions for installing it.&lt;/p&gt;
&lt;p&gt;Maybe this means that the following instructions are the only English-friendly ones on the web right now. How nice! And as far as I can tell, they still work, so if you try them, please let me know if you notice anything that I need to change in what follows.&lt;/p&gt;
&lt;p&gt;The biggest difference in my own practice is that I use &lt;code&gt;nala&lt;/code&gt; instead of &lt;code&gt;apt&lt;/code&gt; as my day-to-day package manager on Pop!__OS; otherwise, if I reinstalled XSane now, I’d expect it to go something like…&lt;/p&gt;
&lt;h1 id=&quot;the-original-instructions-from-2019&quot;&gt;The Original Instructions from 2019&lt;/h1&gt;
&lt;p&gt;I love my Fujitsu ScanSnap S510M scanner, mostly because it just always works. It almost never jams. I find it very easy to operate. It makes scanning longer documents very easy. Even though I always have the backup option of photographing pages and processing them with Mobile Doc Scanner for Android, I still occasionally receive full-page mail and the ScanSnap scanner makes processing those pages really easy.&lt;/p&gt;
&lt;p&gt;I originally bought the S510M to work with my MacOS machines, but now that I’m trying to move entirely off MacOS, I’d like to make my scanner work on Linux. After some light web searching, this seems possible with some combination of the built-in SANE scanning software and with a custom package called VueScan (not FOSS). How do we get these things to work?&lt;/p&gt;
&lt;h1 id=&quot;software-included-in-pop_osubuntu&quot;&gt;Software Included In Pop!_OS/Ubuntu&lt;/h1&gt;
&lt;p&gt;I start at &lt;a href=&quot;https://help.ubuntu.com/community/Scanners&quot; class=&quot;uri&quot;&gt;https://help.ubuntu.com/community/Scanners&lt;/a&gt; and look at the scanners that SANE (Scanner Access Now Easy) supports. According to &lt;a href=&quot;http://www.sane-project.org/sane-mfgs.html&quot; class=&quot;uri&quot;&gt;http://www.sane-project.org/sane-mfgs.html&lt;/a&gt;, SANE supports the Fujitsu ScanSnap S510M “completely” (I don’t yet know how they’re judging “completeness” here, but it sounds promising). This table provides some information that I will need later, so I make a note of it:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;USB ID: 0x04c5/0x116f&lt;/li&gt;
&lt;li&gt;Backend: fujitsu (133)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now, how do I try this?&lt;/p&gt;
&lt;h2 id=&quot;basic-setup&quot;&gt;Basic Setup&lt;/h2&gt;
&lt;p&gt;I follow the instructions at &lt;a href=&quot;https://help.ubuntu.com/community/sane&quot; class=&quot;uri&quot;&gt;https://help.ubuntu.com/community/sane&lt;/a&gt; and do the following.&lt;/p&gt;
&lt;h3 id=&quot;interlude-something-is-wrong-as-of-june-2023&quot;&gt;Interlude: Something is Wrong as of June 2023&lt;/h3&gt;
&lt;p&gt;The instructions above don’t work, because they suggest installing the package &lt;code&gt;libsane-extras&lt;/code&gt;, which is not found in the standard Ubuntu/Pop!_OS package repository. &lt;a href=&quot;https://unix.stackexchange.com/questions/748778/package-libsane-extras-not-found-is-this-a-problem-or-should-the-instructions-c&quot;&gt;I’ve posted a question at the Unix &amp;amp; Linux StackExchange&lt;/a&gt;, hoping for a useful suggestion. Maybe you’ll find a useful answer by now!&lt;/p&gt;
&lt;h2 id=&quot;returning-to-basic-setup&quot;&gt;Returning to Basic Setup&lt;/h2&gt;
&lt;p&gt;[As of June 2023, this command fails, because the package &lt;code&gt;libsane-extras&lt;/code&gt; is not found. I don’t know how to fix this problem. Good luck.]&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; sudo apt-get install sane sane-utils libsane-extras xsane&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;a-detour-into-gimp-configuration-files&quot;&gt;A Detour Into Gimp Configuration Files&lt;/h3&gt;
&lt;p&gt;When installing these packages, &lt;code&gt;apt&lt;/code&gt; asks me about changing some configuration files related to Gimp. Since I don’t qualify as a Gimp power user, I probably don’t care too much about the contents of these configuration files, but I might learn something by reviewing these changes, so I look at them one by one. This also gives me a chance to learn a little bit more about the details of installing packages with &lt;code&gt;apt&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;First, comes the configuration file &lt;code&gt;/etc/gimp/2.0/controllerrc&lt;/code&gt;. All the changes in this file appear to relate to keyboard shortcuts that I don’t rely on, so I feel safe in accepting the changes. I have no muscle memory with Gimp to interfere with.&lt;/p&gt;
&lt;h4 id=&quot;etcgimp2.0controllerrc&quot;&gt;&lt;code&gt;/etc/gimp/2.0/controllerrc&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;&lt;/code&gt; represents the configuration file “as is” and &lt;code&gt;&amp;gt;&lt;/code&gt; represents the proposed changes to the configuration file. I’m no expert in Lisp, but even &lt;em&gt;I&lt;/em&gt; can read this.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode diff&quot;&gt;&lt;code class=&quot;sourceCode diff&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;8,17c8,17&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;&amp;lt;         (map &amp;quot;scroll-up-alt&amp;quot;                 &amp;quot;tools-value-1-increase-skip&amp;quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a href=&quot;#cb2-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;&amp;lt;         (map &amp;quot;scroll-down-alt&amp;quot;               &amp;quot;tools-value-1-decrease-skip&amp;quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-4&quot;&gt;&lt;a href=&quot;#cb2-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;&amp;lt;         (map &amp;quot;scroll-up-control-alt&amp;quot;         &amp;quot;context-gradient-select-next&amp;quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-5&quot;&gt;&lt;a href=&quot;#cb2-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;&amp;lt;         (map &amp;quot;scroll-down-control-alt&amp;quot;       &amp;quot;context-gradient-select-previous&amp;quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-6&quot;&gt;&lt;a href=&quot;#cb2-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;&amp;lt;         (map &amp;quot;scroll-up-shift-alt&amp;quot;           &amp;quot;context-pattern-select-next&amp;quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-7&quot;&gt;&lt;a href=&quot;#cb2-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;&amp;lt;         (map &amp;quot;scroll-down-shift-alt&amp;quot;         &amp;quot;context-pattern-select-previous&amp;quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-8&quot;&gt;&lt;a href=&quot;#cb2-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;&amp;lt;         (map &amp;quot;scroll-up-shift-control&amp;quot;       &amp;quot;context-brush-select-next&amp;quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-9&quot;&gt;&lt;a href=&quot;#cb2-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;&amp;lt;         (map &amp;quot;scroll-down-shift-control&amp;quot;     &amp;quot;context-brush-select-previous&amp;quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-10&quot;&gt;&lt;a href=&quot;#cb2-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;&amp;lt;         (map &amp;quot;scroll-up-shift-control-alt&amp;quot;   &amp;quot;context-font-select-next&amp;quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-11&quot;&gt;&lt;a href=&quot;#cb2-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;&amp;lt;         (map &amp;quot;scroll-down-shift-control-alt&amp;quot; &amp;quot;context-font-select-previous&amp;quot;)))&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-12&quot;&gt;&lt;a href=&quot;#cb2-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;---&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-13&quot;&gt;&lt;a href=&quot;#cb2-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt;         (map &amp;quot;scroll-up-alt&amp;quot;                 &amp;quot;tools-opacity-increase&amp;quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-14&quot;&gt;&lt;a href=&quot;#cb2-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt;         (map &amp;quot;scroll-down-alt&amp;quot;               &amp;quot;tools-opacity-decrease&amp;quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-15&quot;&gt;&lt;a href=&quot;#cb2-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt;         (map &amp;quot;scroll-up-shift-primary&amp;quot;       &amp;quot;tools-aspect-increase&amp;quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-16&quot;&gt;&lt;a href=&quot;#cb2-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt;         (map &amp;quot;scroll-down-shift-primary&amp;quot;     &amp;quot;tools-aspect-decrease&amp;quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-17&quot;&gt;&lt;a href=&quot;#cb2-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt;         (map &amp;quot;scroll-up-shift-alt&amp;quot;           &amp;quot;tools-angle-increase&amp;quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-18&quot;&gt;&lt;a href=&quot;#cb2-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt;         (map &amp;quot;scroll-down-shift-alt&amp;quot;         &amp;quot;tools-angle-decrease&amp;quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-19&quot;&gt;&lt;a href=&quot;#cb2-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt;         (map &amp;quot;scroll-up-primary-alt&amp;quot;         &amp;quot;tools-size-increase&amp;quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-20&quot;&gt;&lt;a href=&quot;#cb2-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt;         (map &amp;quot;scroll-down-primary-alt&amp;quot;       &amp;quot;tools-size-decrease&amp;quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-21&quot;&gt;&lt;a href=&quot;#cb2-21&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt;         (map &amp;quot;scroll-up-shift-primary-alt&amp;quot;   &amp;quot;tools-spacing-increase&amp;quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-22&quot;&gt;&lt;a href=&quot;#cb2-22&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt;         (map &amp;quot;scroll-down-shift-primary-alt&amp;quot; &amp;quot;tools-spacing-decrease&amp;quot;)))&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-23&quot;&gt;&lt;a href=&quot;#cb2-23&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;28,35c28,35&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-24&quot;&gt;&lt;a href=&quot;#cb2-24&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;&amp;lt;         (map &amp;quot;cursor-up-control&amp;quot;    &amp;quot;view-scroll-top-border&amp;quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-25&quot;&gt;&lt;a href=&quot;#cb2-25&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;&amp;lt;         (map &amp;quot;cursor-down-control&amp;quot;  &amp;quot;view-scroll-bottom-border&amp;quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-26&quot;&gt;&lt;a href=&quot;#cb2-26&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;&amp;lt;         (map &amp;quot;cursor-left-control&amp;quot;  &amp;quot;view-scroll-left-border&amp;quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-27&quot;&gt;&lt;a href=&quot;#cb2-27&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;&amp;lt;         (map &amp;quot;cursor-right-control&amp;quot; &amp;quot;view-scroll-right-border&amp;quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-28&quot;&gt;&lt;a href=&quot;#cb2-28&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;&amp;lt;         (map &amp;quot;cursor-up-alt&amp;quot;        &amp;quot;tools-value-1-increase-skip&amp;quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-29&quot;&gt;&lt;a href=&quot;#cb2-29&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;&amp;lt;         (map &amp;quot;cursor-down-alt&amp;quot;      &amp;quot;tools-value-1-decrease-skip&amp;quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-30&quot;&gt;&lt;a href=&quot;#cb2-30&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;&amp;lt;         (map &amp;quot;cursor-left-alt&amp;quot;      &amp;quot;tools-value-1-decrease&amp;quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-31&quot;&gt;&lt;a href=&quot;#cb2-31&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;&amp;lt;         (map &amp;quot;cursor-right-alt&amp;quot;     &amp;quot;tools-value-1-increase&amp;quot;)))&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-32&quot;&gt;&lt;a href=&quot;#cb2-32&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;---&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-33&quot;&gt;&lt;a href=&quot;#cb2-33&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt;         (map &amp;quot;cursor-up-primary&amp;quot;    &amp;quot;view-scroll-top-border&amp;quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-34&quot;&gt;&lt;a href=&quot;#cb2-34&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt;         (map &amp;quot;cursor-down-primary&amp;quot;  &amp;quot;view-scroll-bottom-border&amp;quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-35&quot;&gt;&lt;a href=&quot;#cb2-35&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt;         (map &amp;quot;cursor-left-primary&amp;quot;  &amp;quot;view-scroll-left-border&amp;quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-36&quot;&gt;&lt;a href=&quot;#cb2-36&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt;         (map &amp;quot;cursor-right-primary&amp;quot; &amp;quot;view-scroll-right-border&amp;quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-37&quot;&gt;&lt;a href=&quot;#cb2-37&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt;         (map &amp;quot;cursor-up-alt&amp;quot;        &amp;quot;tools-size-increase-skip&amp;quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-38&quot;&gt;&lt;a href=&quot;#cb2-38&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt;         (map &amp;quot;cursor-down-alt&amp;quot;      &amp;quot;tools-size-decrease-skip&amp;quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-39&quot;&gt;&lt;a href=&quot;#cb2-39&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt;         (map &amp;quot;cursor-left-alt&amp;quot;      &amp;quot;tools-size-decrease&amp;quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-40&quot;&gt;&lt;a href=&quot;#cb2-40&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt;         (map &amp;quot;cursor-right-alt&amp;quot;     &amp;quot;tools-size-increase&amp;quot;)))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Back to my terminal session:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;Configuration&lt;/span&gt; file &lt;span class=&quot;st&quot;&gt;&amp;#39;/etc/gimp/2.0/controllerrc&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-2&quot;&gt;&lt;a href=&quot;#cb3-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt; &lt;span class=&quot;ex&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt; File on system created by you or by a script.&lt;/span&gt;
&lt;span id=&quot;cb3-3&quot;&gt;&lt;a href=&quot;#cb3-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt; &lt;span class=&quot;ex&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt; File also in package provided by package maintainer.&lt;/span&gt;
&lt;span id=&quot;cb3-4&quot;&gt;&lt;a href=&quot;#cb3-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;   &lt;span class=&quot;ex&quot;&gt;What&lt;/span&gt; would you like to do about it &lt;span class=&quot;pp&quot;&gt;?&lt;/span&gt;  Your options are:&lt;/span&gt;
&lt;span id=&quot;cb3-5&quot;&gt;&lt;a href=&quot;#cb3-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ex&quot;&gt;Y&lt;/span&gt; or I  : install the package maintainer&lt;span class=&quot;st&quot;&gt;&amp;#39;s version&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-6&quot;&gt;&lt;a href=&quot;#cb3-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;    N or O  : keep your currently-installed version&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-7&quot;&gt;&lt;a href=&quot;#cb3-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;      D     : show the differences between the versions&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-8&quot;&gt;&lt;a href=&quot;#cb3-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;      Z     : start a shell to examine the situation&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-9&quot;&gt;&lt;a href=&quot;#cb3-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt; The default action is to keep your current version.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-10&quot;&gt;&lt;a href=&quot;#cb3-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;*** controllerrc (Y/I/N/O/D/Z) [default=N] ? Y&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now the same for &lt;code&gt;/etc/gimp/2.0/gimprc&lt;/code&gt;. I see &lt;em&gt;a large number&lt;/em&gt; of changes, but every single one involves a comment, so I see no harm in accepting the new version, so I do that by answering “Y” again.&lt;/p&gt;
&lt;p&gt;Next, &lt;code&gt;/etc/gimp/2.0/sessionrc&lt;/code&gt;. By reading the preamble comment, I feel comfortable just accepting the new version, so I do that by answering “Y” again.&lt;/p&gt;
&lt;h4 id=&quot;etcgimp2.0sessionrc&quot;&gt;&lt;code&gt;/etc/gimp/2.0/sessionrc&lt;/code&gt;&lt;/h4&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb4&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb4-1&quot;&gt;&lt;a href=&quot;#cb4-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;# GIMP sessionrc&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-2&quot;&gt;&lt;a href=&quot;#cb4-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;# &lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-3&quot;&gt;&lt;a href=&quot;#cb4-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;# This file takes session-specific info (that is info, you want to keep&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-4&quot;&gt;&lt;a href=&quot;#cb4-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;# between two GIMP sessions). You are not supposed to edit it manually, but&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-5&quot;&gt;&lt;a href=&quot;#cb4-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;# of course you can do. The sessionrc will be entirely rewritten every time&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-6&quot;&gt;&lt;a href=&quot;#cb4-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;# you quit GIMP. If this file isn&amp;#39;t found, defaults are used.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-7&quot;&gt;&lt;a href=&quot;#cb4-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;[...&lt;/span&gt; session settings that you don&lt;span class=&quot;st&quot;&gt;&amp;#39;t need to see here...]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Next, &lt;code&gt;/etc/gimp/2.0/templaterc&lt;/code&gt;. This appears to have a list of templates of some kind. Since I don’t use Gimp templates (yet?), I see no harm in accepting the new version.&lt;/p&gt;
&lt;p&gt;This appears to conclude the configuration-file surgery portion of this installation.&lt;/p&gt;
&lt;h2 id=&quot;back-to-installing-sane&quot;&gt;Back To Installing SANE&lt;/h2&gt;
&lt;p&gt;When installing completes, I see evidence that &lt;code&gt;apt&lt;/code&gt; has installed all the packages, as well as that &lt;code&gt;etckeeper&lt;/code&gt; has committed and pushed the changes to &lt;code&gt;/etc&lt;/code&gt;. Unfortunately, then I see this:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb5&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb5-1&quot;&gt;&lt;a href=&quot;#cb5-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;W:&lt;/span&gt; Operation was interrupted before it could finish&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;After reading a few Stack Overflow answers and forum posts, &lt;code&gt;W&lt;/code&gt; means “warning” and the message seems likely harmless. Just to check, I re-install the packages, and this operates without any warnings. I wonder whether, somehow, my exploring the configuration file differences resulted in this warning. I suppose I’ll never know.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;All this merely completed step 1&lt;/strong&gt; at &lt;a href=&quot;https://help.ubuntu.com/community/sane&quot; class=&quot;uri&quot;&gt;https://help.ubuntu.com/community/sane&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;On to step 2: I connect my scanner by USB, then launch XSane, and XSane detects the scanner as “ScanSnap S510M”! This might just work!&lt;/p&gt;
&lt;h2 id=&quot;scanning-a-page&quot;&gt;Scanning A Page&lt;/h2&gt;
&lt;p&gt;I put a page into the scanner, then press the button &lt;strong&gt;Acquire preview&lt;/strong&gt; on XSane. I haven’t changed any configuration settings yet. XSane scans the page and I see a preview image, which doesn’t look &lt;em&gt;great&lt;/em&gt;, but shows evidence that I can scan a page. Unfortunately, when I try to press the &lt;strong&gt;Scan&lt;/strong&gt; button on the main XSane window, I get an error: “Failed to start scanner: Invalid argument”.&lt;/p&gt;
&lt;p&gt;So I can acquire a preview image, but I can’t scan a page “for real”? What does that even mean?!&lt;/p&gt;
&lt;h2 id=&quot;when-in-doubt-try-it-again&quot;&gt;When In Doubt, Try It Again&lt;/h2&gt;
&lt;p&gt;I put the page back into the scanner, then pressed &lt;strong&gt;Acquire preview&lt;/strong&gt; again. After that, I pressed &lt;strong&gt;Scan&lt;/strong&gt; and got a different error telling me that the document feeder was out of pages, so I put the page back into the scanner, then pressed &lt;strong&gt;Scan&lt;/strong&gt;, then &lt;em&gt;I get a scanned document as PDF!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Well… sort of. When I open the PDF, it looks awful. It definitely doesn’t look like the crisp, sharp scans that I’d grown accustomed to when scanning a page on MacOS. Clearly, I have change some settings in order to improve the scan quality, but of course, I don’t know which settings to change, so I get to learn more about scanning quality than I ever wanted to know.&lt;/p&gt;
&lt;h2 id=&quot;changing-scanning-settings&quot;&gt;Changing Scanning Settings&lt;/h2&gt;
&lt;p&gt;I see that the &lt;em&gt;scan resolution&lt;/em&gt; is set to 50. I assume that’s 50 dots per inch (DPI). That seems &lt;em&gt;really&lt;/em&gt; low. I look at the resulting PDF file, which has a size of 82 kB, and these two observations together seem to match. Let me try 300 DPI, which seems like overkill, but at least would show me a stark difference between the two scans, if it behaved as I expect. I set the scan resolution to 300, then scan again.&lt;/p&gt;
&lt;p&gt;When I scan the page at 300 DPI, I notice two things:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;XSane shows me “2550*3300*8 (8.0 MB)”, which I interpret as 2550 pixels by 3300 pixels by 8 bits of color for a total page size of about 8.0 MB. This sounds like overkill and &lt;em&gt;should&lt;/em&gt; look much sharper.&lt;/li&gt;
&lt;li&gt;When I scan the page, it takes a lot longer to scan. This seems to correspond to the ScanSnap Manager’s various scanning settings of “Better, Best, Fastest” and so on. This setting seems to correspond to something like “Better” or even “Best”.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The resulting PDF has a size of 2.2 MB, and not 8.0 MB, but that seems like it would look sharper. When I open it in my PDF viewer, it indeed looks very sharp! I imagine that I could now just resample it to lower resolution if I wanted to. Perhaps it has become time to learn how to use Gimp “for real”.&lt;/p&gt;
&lt;h2 id=&quot;save-the-settings&quot;&gt;Save The Settings!&lt;/h2&gt;
&lt;p&gt;Before I play around with the various scan settings to find what I really want, I save the device settings so that I don’t lose them, using the XSane menu &lt;strong&gt;Preferences &amp;gt; Settings&lt;/strong&gt; (&lt;code&gt;Ctrl+P&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Now I can safely play around with the scanning settings and save them as various profiles. Nice!&lt;/p&gt;
</description>
        <pubDate>Thu, 17 Jan 2019 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/use-scansnap-with-linux</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/use-scansnap-with-linux</guid>
        
        
        <category>Tutorials</category>
        
      </item>
    
      <item>
        <title>Fixed: I Couldn&apos;t Open A Terminal Window!</title>
        <description>&lt;p&gt;I just had quite a nice scare: I was installing some packages on &lt;a href=&quot;https://system76.com/pop&quot;&gt;Pop!_OS 18.10&lt;/a&gt; (Ubuntu), and I unknowingly caused my trackpad to stop working and I couldn’t even open a &lt;strong&gt;Terminal&lt;/strong&gt; window to see what was happening.&lt;/p&gt;
&lt;h1 id=&quot;the-symptoms&quot;&gt;The Symptoms&lt;/h1&gt;
&lt;p&gt;I had been installing some packages with &lt;code&gt;apt&lt;/code&gt;. At one point, when I tried to take the next step, I tried to open a new window in Byobu Terminal. I pressed &lt;code&gt;F2&lt;/code&gt; and nothing happened. I tried again, and nothing happened. I couldn’t open a new window. I tried &lt;code&gt;Alt+F2&lt;/code&gt; and &lt;code&gt;Ctrl+F2&lt;/code&gt;, but neither of these key combinations did anything. I closed my Byobu Terminal session and tried to open a new one, but launching Byobu did nothing. No window opened.&lt;/p&gt;
&lt;p&gt;Oops.&lt;/p&gt;
&lt;p&gt;Next, I tried launching the regular &lt;strong&gt;Terminal&lt;/strong&gt; application. Again, no window. Nothing. I tried &lt;strong&gt;XTerm&lt;/strong&gt;. Nothing. I couldn’t open a Terminal session at all! How the hell was I going to even get information to help me diagnose the problem?&lt;/p&gt;
&lt;p&gt;I tried logging out, then logging in again. I couldn’t open any Terminal windows and, worse, I couldn’t use my trackpad! My trackpad didn’t move my cursor at all. This would make figuring out the problem &lt;em&gt;very&lt;/em&gt; difficult.&lt;/p&gt;
&lt;p&gt;I tried restarting the computer. No change: I couldn’t open a Terminal window and I couldn’t use my trackpad.&lt;/p&gt;
&lt;h1 id=&quot;getting-information&quot;&gt;Getting Information&lt;/h1&gt;
&lt;p&gt;I couldn’t see any output from trying to start a Terminal session, so I had no idea how to even guess at the symptoms, let alone the cause. How could I start a shell and see the result of trying to start one? And how do I get around my windowing environment without a trackpad?&lt;/p&gt;
&lt;p&gt;Fortunately, I had a USB mouse nearby, so I plugged that in and it just worked. This meant that I could at least browse the web on this computer to figure out what else to do. &lt;a href=&quot;https://duckduckgo.com/?q=terminal+doesn%27t+open+ubuntu&amp;amp;t=canonical&amp;amp;ia=web&quot;&gt;I searched the web&lt;/a&gt; and tried using &lt;code&gt;Alt+F2&lt;/code&gt; to run an arbitrary command (in Gnrome 3), so I ran &lt;code&gt;gnome-terminal&lt;/code&gt;. This didn’t open a Terminal session and it showed me no output, so I didn’t learn anything about the problem.&lt;/p&gt;
&lt;h2 id=&quot;a-trick&quot;&gt;A Trick&lt;/h2&gt;
&lt;p&gt;In desperation, I launched &lt;strong&gt;GVim&lt;/strong&gt;, then tried using the &lt;code&gt;:!&lt;/code&gt; command to run a shell. This finally gave me a clue:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;error&lt;/span&gt; while loading shared libraries: libtinfo.so.5: cannot open shared object file: No such file or directory&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Aha! &lt;code&gt;apt&lt;/code&gt; fooled me.&lt;/p&gt;
&lt;h1 id=&quot;the-trouble-with-autoremove&quot;&gt;The Trouble With &lt;code&gt;autoremove&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;I had been trying to install some printer-related packages, and in the process of uninstalling them (they didn’t do what I needed), &lt;code&gt;apt&lt;/code&gt; told me that it could &lt;code&gt;autoremove&lt;/code&gt; these packages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;libncursesw5&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;libtinfo5&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Since I didn’t know any better, I executed &lt;code&gt;apt autoremove&lt;/code&gt;, which removed these packages, and my problems started there.&lt;/p&gt;
&lt;h1 id=&quot;thank-you-etckeeper&quot;&gt;Thank You, &lt;code&gt;etckeeper&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;Fortunately, &lt;code&gt;etckeeper&lt;/code&gt; made it relatively easy both to recover and to document what went wrong. I could see a commit from when I removed the printer-related packages that I’d installed, and then a second commit from executing &lt;code&gt;apt autoremove&lt;/code&gt;. This helped me connect the error message above with the packages that I’d removed. This gave me the idea that I could simply reinstall those packages and return everything to normal.&lt;/p&gt;
&lt;h1 id=&quot;opening-a-shell-any-shell&quot;&gt;Opening A Shell… Any Shell&lt;/h1&gt;
&lt;p&gt;I couldn’t open my normal shell (&lt;code&gt;zsh&lt;/code&gt;) to fix the problem, but could I open &lt;em&gt;any&lt;/em&gt; shell? I opened the Preferences for the &lt;strong&gt;Terminal&lt;/strong&gt; application, then cloned my Pop! profile in order to change the shell command that the terminal runs to &lt;code&gt;/bin/bash&lt;/code&gt;. I set the new profile—I called it “Recovery”—as the default profile for the &lt;strong&gt;Terminal&lt;/strong&gt; application, then launched it. Yes! I got a &lt;code&gt;bash&lt;/code&gt; shell. Now I could try my idea for fixing the problem.&lt;/p&gt;
&lt;h3 id=&quot;even-better&quot;&gt;Even Better!&lt;/h3&gt;
&lt;p&gt;After reading &lt;a href=&quot;https://askubuntu.com/a/809058/839487&quot; class=&quot;uri&quot;&gt;https://askubuntu.com/a/809058/839487&lt;/a&gt; I saw that I could have started &lt;code&gt;gnome-terminal&lt;/code&gt; using &lt;code&gt;bash&lt;/code&gt; instead of my shell by pressing &lt;code&gt;Alt+F2&lt;/code&gt; then running the command &lt;code&gt;gnome-terminal -x bash&lt;/code&gt;. I hope I can remember this next time!&lt;/p&gt;
&lt;h1 id=&quot;fixing-the-problem&quot;&gt;Fixing The Problem&lt;/h1&gt;
&lt;p&gt;I fixed the problem (some of it—keep reading) by reinstalling the packages that &lt;code&gt;apt autoremove&lt;/code&gt; had removed.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; sudo apt-get install libncursesw5 libtinfo5&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;[Evidence&lt;/span&gt; of installing various packages...]&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a href=&quot;#cb2-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; sudo apt list &lt;span class=&quot;at&quot;&gt;--upgradable&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-4&quot;&gt;&lt;a href=&quot;#cb2-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;[Nothing.&lt;/span&gt; Good.]&lt;/span&gt;
&lt;span id=&quot;cb2-5&quot;&gt;&lt;a href=&quot;#cb2-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; zsh&lt;/span&gt;
&lt;span id=&quot;cb2-6&quot;&gt;&lt;a href=&quot;#cb2-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;[The&lt;/span&gt; zsh prompt.]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I could open a shell again. Maybe everything had returned to normal. Before I did anything else, I documented what I learned where I might one day stumble upon it again: in the &lt;code&gt;git&lt;/code&gt; log for &lt;code&gt;/etc&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;documenting-the-problem&quot;&gt;Documenting The Problem&lt;/h2&gt;
&lt;p&gt;I amended the relevant &lt;code&gt;etckeeper&lt;/code&gt; commits, adding detail about what happened, as well as making it easier for the eye to notice that something interesting had happened. First, I decorated the one-line commit messages.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; cd /etc&lt;/span&gt;
&lt;span id=&quot;cb3-2&quot;&gt;&lt;a href=&quot;#cb3-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; sudo git log &lt;span class=&quot;at&quot;&gt;--graph&lt;/span&gt; &lt;span class=&quot;at&quot;&gt;--all&lt;/span&gt; &lt;span class=&quot;at&quot;&gt;--oneline&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-3&quot;&gt;&lt;a href=&quot;#cb3-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;*&lt;/span&gt; c2efaa2 &lt;span class=&quot;er&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;HEAD&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ex&quot;&gt;[FIX]&lt;/span&gt; committing changes in /etc after apt run&lt;/span&gt;
&lt;span id=&quot;cb3-4&quot;&gt;&lt;a href=&quot;#cb3-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;*&lt;/span&gt; 8866206 [MISTAKE] committing changes in /etc after apt run&lt;/span&gt;
&lt;span id=&quot;cb3-5&quot;&gt;&lt;a href=&quot;#cb3-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;ex&quot;&gt;*&lt;/span&gt; 4c984ec &lt;span class=&quot;er&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;offsite-backup/master,&lt;/span&gt; master&lt;span class=&quot;kw&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ex&quot;&gt;committing&lt;/span&gt; changes in /etc after apt run&lt;/span&gt;
&lt;span id=&quot;cb3-6&quot;&gt;&lt;a href=&quot;#cb3-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;ex&quot;&gt;*&lt;/span&gt; 984c8eb committing changes in /etc after apt run&lt;/span&gt;
&lt;span id=&quot;cb3-7&quot;&gt;&lt;a href=&quot;#cb3-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;/&lt;/span&gt;  &lt;/span&gt;
&lt;span id=&quot;cb3-8&quot;&gt;&lt;a href=&quot;#cb3-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;*&lt;/span&gt; 2945f32 committing changes in /etc after apt run&lt;/span&gt;
&lt;span id=&quot;cb3-9&quot;&gt;&lt;a href=&quot;#cb3-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;*&lt;/span&gt; 81410e8 saving uncommitted changes in /etc prior to apt run&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The last two commits contained the mistake (&lt;code&gt;apt autoremove&lt;/code&gt; and the fix &lt;code&gt;apt-get install...&lt;/code&gt;). I added simple text tags to make it easier to spot them. I also added some detail to the log messages.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb4&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb4-1&quot;&gt;&lt;a href=&quot;#cb4-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; sudo git log &lt;span class=&quot;at&quot;&gt;--all&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-2&quot;&gt;&lt;a href=&quot;#cb4-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;commit&lt;/span&gt; c2efaa27381fa9a3afcb5426c44a7577a6cc01de &lt;span class=&quot;er&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;HEAD&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-3&quot;&gt;&lt;a href=&quot;#cb4-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;Author:&lt;/span&gt; J. B. Rainsberger &lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;me@jbrains.ca&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-4&quot;&gt;&lt;a href=&quot;#cb4-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;Date:&lt;/span&gt;   Thu Jan 17 10:33:36 2019 &lt;span class=&quot;at&quot;&gt;-0400&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-5&quot;&gt;&lt;a href=&quot;#cb4-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-6&quot;&gt;&lt;a href=&quot;#cb4-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ex&quot;&gt;[FIX]&lt;/span&gt; committing changes in /etc after apt run&lt;/span&gt;
&lt;span id=&quot;cb4-7&quot;&gt;&lt;a href=&quot;#cb4-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id=&quot;cb4-8&quot;&gt;&lt;a href=&quot;#cb4-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ex&quot;&gt;Reinstalling&lt;/span&gt; these packages fixes the previous action&lt;/span&gt;
&lt;span id=&quot;cb4-9&quot;&gt;&lt;a href=&quot;#cb4-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;apt&lt;/span&gt; autoremove&lt;span class=&quot;kw&quot;&gt;`&lt;/span&gt;.&lt;/span&gt;
&lt;span id=&quot;cb4-10&quot;&gt;&lt;a href=&quot;#cb4-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id=&quot;cb4-11&quot;&gt;&lt;a href=&quot;#cb4-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ex&quot;&gt;Package&lt;/span&gt; changes:&lt;/span&gt;
&lt;span id=&quot;cb4-12&quot;&gt;&lt;a href=&quot;#cb4-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ex&quot;&gt;+libncursesw5&lt;/span&gt; 6.1+20180210-4ubuntu1 amd64&lt;/span&gt;
&lt;span id=&quot;cb4-13&quot;&gt;&lt;a href=&quot;#cb4-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ex&quot;&gt;+libtinfo5&lt;/span&gt; 6.1+20180210-4ubuntu1 amd64&lt;/span&gt;
&lt;span id=&quot;cb4-14&quot;&gt;&lt;a href=&quot;#cb4-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-15&quot;&gt;&lt;a href=&quot;#cb4-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;commit&lt;/span&gt; 8866206fa2b6ff42a10d0d05e83da2eefaf44424&lt;/span&gt;
&lt;span id=&quot;cb4-16&quot;&gt;&lt;a href=&quot;#cb4-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;Author:&lt;/span&gt; J. B. Rainsberger &lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;me@jbrains.ca&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-17&quot;&gt;&lt;a href=&quot;#cb4-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;Date:&lt;/span&gt;   Thu Jan 17 10:16:53 2019 &lt;span class=&quot;at&quot;&gt;-0400&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-18&quot;&gt;&lt;a href=&quot;#cb4-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-19&quot;&gt;&lt;a href=&quot;#cb4-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ex&quot;&gt;[MISTAKE]&lt;/span&gt; committing changes in /etc after apt run&lt;/span&gt;
&lt;span id=&quot;cb4-20&quot;&gt;&lt;a href=&quot;#cb4-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id=&quot;cb4-21&quot;&gt;&lt;a href=&quot;#cb4-21&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;apt&lt;/span&gt; autoremove&lt;span class=&quot;kw&quot;&gt;`&lt;/span&gt; removed these packages, but after I did that,&lt;/span&gt;
&lt;span id=&quot;cb4-22&quot;&gt;&lt;a href=&quot;#cb4-22&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ex&quot;&gt;I&lt;/span&gt; could no longer open my shell &lt;span class=&quot;er&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;fu&quot;&gt;zsh&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;,&lt;/span&gt; even though I could open&lt;/span&gt;
&lt;span id=&quot;cb4-23&quot;&gt;&lt;a href=&quot;#cb4-23&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ex&quot;&gt;bash.&lt;/span&gt; Trying to launch zsh resulting in an error, unable to&lt;/span&gt;
&lt;span id=&quot;cb4-24&quot;&gt;&lt;a href=&quot;#cb4-24&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;fu&quot;&gt;find&lt;/span&gt; libtinfo.so.5.&lt;/span&gt;
&lt;span id=&quot;cb4-25&quot;&gt;&lt;a href=&quot;#cb4-25&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id=&quot;cb4-26&quot;&gt;&lt;a href=&quot;#cb4-26&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ex&quot;&gt;I&lt;/span&gt; don&lt;span class=&quot;st&quot;&gt;&amp;#39;t know why this happened, but reinstalling these two&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-27&quot;&gt;&lt;a href=&quot;#cb4-27&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;    packages seemed to fix the problem.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-28&quot;&gt;&lt;a href=&quot;#cb4-28&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-29&quot;&gt;&lt;a href=&quot;#cb4-29&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;    Package changes:&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-30&quot;&gt;&lt;a href=&quot;#cb4-30&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;    -libncursesw5 6.1+20180210-4ubuntu1 amd64&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-31&quot;&gt;&lt;a href=&quot;#cb4-31&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;    -libtinfo5 6.1+20180210-4ubuntu1 amd64&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I had documented my adventures for myself and could safely breathe, then begin describing my adventures for you, in case you should ever get yourself into a similar situation.&lt;/p&gt;
&lt;h2 id=&quot;verifying-the-fix&quot;&gt;Verifying The Fix&lt;/h2&gt;
&lt;p&gt;I could start my shell again, but my trackpad still didn’t work, so I got all this information out of my head, then I tried to see whether my trackpad would work again, first by logging out, then by rebooting in case logging it didn’t suffice.&lt;/p&gt;
&lt;p&gt;Curiously, when I logged &lt;em&gt;out&lt;/em&gt;, my trackpad started to work again, but when I logged &lt;em&gt;in&lt;/em&gt;, it stopped working. Moreover, each time I tried this, the cursor jumped to the same spot near the bottom-right corner of my display. I didn’t know what that meant yet, but it made me think that I had some configuration setting somewhere that needed to change. I hoped that rebooting would fix the problem, so I rebooted.&lt;/p&gt;
&lt;p&gt;Sadly, that didn’t fix the entire problem. Good news: I can start my shell and Byobu. Bad news: my trackpad only works when I’m logged out. This points pretty clearly to a user-level configuration problem, which I can probably diagnose (and maybe fix) by looking at the &lt;em&gt;changes&lt;/em&gt; to &lt;code&gt;/etc&lt;/code&gt; or to my &lt;code&gt;dotfiles&lt;/code&gt; when I reinstalled these packages. Fortunately, in the meantime, a USB mouse works, so I don’t have to fix this problem &lt;em&gt;right now&lt;/em&gt;, even though I’ll want to fix it very soon.&lt;/p&gt;
&lt;h2 id=&quot;post-script-fixing-the-touchpad&quot;&gt;Post Script: Fixing the Touchpad&lt;/h2&gt;
&lt;p&gt;I guess Linux calls it a “touchpad” and not a “trackpad”. Old habits die hard.&lt;/p&gt;
&lt;p&gt;I don’t know how it happened, but somehow, in the middle of removing and reinstalling packages, the “on/off” toggle for the touchpad in Gnome switched to “off”. That’s all. I switched it back “on” through the &lt;strong&gt;Mouse &amp;amp; Touchpad&lt;/strong&gt; settings, and the touchpad just started working again. Yay.&lt;/p&gt;
</description>
        <pubDate>Thu, 17 Jan 2019 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/fixed-i-couldnt-open-a-terminal-window</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/fixed-i-couldnt-open-a-terminal-window</guid>
        
        
        <category>Tutorials</category>
        
      </item>
    
      <item>
        <title>rvm and byobu</title>
        <description>&lt;p&gt;I use &lt;code&gt;rvm&lt;/code&gt; and I like &lt;code&gt;byobu&lt;/code&gt; terminal, so I want to use them together. Today, when I tried to write an article at &lt;a href=&quot;https://blog.thecodewhisperer.com&quot; class=&quot;uri&quot;&gt;https://blog.thecodewhisperer.com&lt;/a&gt;, I saw this:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; rvm use 2.4.3&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;#cb1-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;RVM&lt;/span&gt; is not a function, selecting rubies with &lt;span class=&quot;st&quot;&gt;&amp;#39;rvm use ...&amp;#39;&lt;/span&gt; will not work.&lt;/span&gt;
&lt;span id=&quot;cb1-4&quot;&gt;&lt;a href=&quot;#cb1-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;/span&gt;
&lt;span id=&quot;cb1-5&quot;&gt;&lt;a href=&quot;#cb1-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;You&lt;/span&gt; need to change your terminal emulator preferences to allow login shell.&lt;/span&gt;
&lt;span id=&quot;cb1-6&quot;&gt;&lt;a href=&quot;#cb1-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;Sometimes&lt;/span&gt; it is required to use &lt;span class=&quot;kw&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;/bin/bash&lt;/span&gt; &lt;span class=&quot;at&quot;&gt;--login&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;`&lt;/span&gt; as the command.&lt;/span&gt;
&lt;span id=&quot;cb1-7&quot;&gt;&lt;a href=&quot;#cb1-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;Please&lt;/span&gt; visit https://rvm.io/integration/gnome-terminal/ for a example.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I run Gnome 3 on Pop!_OS 18, so I visited &lt;a href=&quot;https://rvm.io/integration/gnome-terminal&quot; class=&quot;uri&quot;&gt;https://rvm.io/integration/gnome-terminal&lt;/a&gt; and followed the instructions there. I opened the &lt;strong&gt;Preferences&lt;/strong&gt; for my terminal application and verified that “Run command as a login shell” is &lt;strong&gt;enabled&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;That did not seem to help.&lt;/p&gt;
&lt;h1 id=&quot;workaround&quot;&gt;Workaround&lt;/h1&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;# In a byobu session...&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;# Load the script your own self!&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a href=&quot;#cb2-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; source &lt;span class=&quot;va&quot;&gt;$HOME&lt;/span&gt;/.rvm/scripts/rvm&lt;/span&gt;
&lt;span id=&quot;cb2-4&quot;&gt;&lt;a href=&quot;#cb2-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; rvm use 2.4.3&lt;/span&gt;
&lt;span id=&quot;cb2-5&quot;&gt;&lt;a href=&quot;#cb2-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;Using&lt;/span&gt; /home/jbrains/.rvm/gems/ruby-2.4.3&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h1 id=&quot;solution&quot;&gt;Solution?&lt;/h1&gt;
&lt;p&gt;I don’t know. I suppose I get to learn about various profile scripts and how the shell loads them. I assume that one of the various profile scripts doesn’t load (“&lt;code&gt;source&lt;/code&gt;”) the &lt;code&gt;rvm&lt;/code&gt; script, but it should. If you know how to figure that out, then please use the contact links below to tell me or tweet a mention to be about it. I’d appreciate it.&lt;/p&gt;
</description>
        <pubDate>Sun, 11 Nov 2018 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/rvm-and-byobu</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/rvm-and-byobu</guid>
        
        
      </item>
    
      <item>
        <title>Using git When the Firewall Says, &quot;No&quot;</title>
        <description>&lt;p&gt;If you find yourself on a network that blocks SSH (port 22), but you want to push some code to your favorite hosted &lt;code&gt;git&lt;/code&gt; repository, you can probably do it. Github, Gitlab, and Bitbucket all provide an alternative &lt;code&gt;git&lt;/code&gt; server so that you can connect over HTTPS (port 443), which such networks can’t really afford to block.&lt;/p&gt;
&lt;p&gt;Good news: you can use an alternative SSH configuration to connect without adding different remotes to your local repository. Bad news: every tutorial I read suggests changing your global/per-user SSH configuration settings, usually in &lt;code&gt;$HOME/.ssh/config&lt;/code&gt;. &lt;strong&gt;How likely do you think you’ll remember to change this back when you return to a nicer network?&lt;/strong&gt; Exactly.&lt;/p&gt;
&lt;p&gt;I think like a programmer. I prefer to configure systems as narrowly as possible: at the user level instead of system-wide; for an individual session instead of at the user level; for an individual request instead of for the entire session. You get the idea. I know that I can tell &lt;code&gt;ssh&lt;/code&gt; which configuration file to use for each request. I would like to do that for &lt;code&gt;git&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I can &lt;em&gt;almost&lt;/em&gt; do this, otherwise I wouldn’t write this article.&lt;/p&gt;
&lt;h2 id=&quot;using-git-with-an-alternate-ssh-configuration&quot;&gt;Using &lt;code&gt;git&lt;/code&gt; with an alternate SSH configuration&lt;/h2&gt;
&lt;p&gt;I created an alternative SSH configuration file, then taught &lt;code&gt;git&lt;/code&gt; how to use that configuration file when connecting to SSH. This way, I don’t have to change the configuration for all SSH sessions by my user, but only the ones to the &lt;code&gt;git&lt;/code&gt; hosting services’ servers.&lt;/p&gt;
&lt;h3 id=&quot;step-by-step-instructions&quot;&gt;Step by Step Instructions&lt;/h3&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Look up the HTTPS connection information from your git repository hosting service. I had to search for while, but I found that information for &lt;code&gt;gitlab.com&lt;/code&gt; and you’ll find it in the references below.&lt;/li&gt;
&lt;li&gt;Test that you can connect to their alternate server with &lt;code&gt;ssh -T -p 443 $server_name&lt;/code&gt;. For Gitlab, I use &lt;code&gt;altssh.gitlab.com&lt;/code&gt; as the server name. If you can’t connect, then I imagine you have a bigger problem and these instructions won’t help you.&lt;/li&gt;
&lt;li&gt;Create an alternative SSH configuration file at &lt;code&gt;$HOME/.ssh/config-blocked-ssh&lt;/code&gt; to use in situations like this.&lt;/li&gt;
&lt;li&gt;Paste into &lt;code&gt;config-blocked-ssh&lt;/code&gt; the connection information from your git repository hosting service. (See the &lt;a href=&quot;#references&quot;&gt;References&lt;/a&gt; section.)&lt;/li&gt;
&lt;li&gt;Now try to connect with &lt;code&gt;ssh -T @server_name&lt;/code&gt;. With luck, your git repository hosting service will tell you that you connected, even if they don’t give you shell access.&lt;/li&gt;
&lt;li&gt;In a terminal session, tell &lt;code&gt;git&lt;/code&gt; to use a different SSH command with &lt;code&gt;GIT_SSH_COMMAND=&quot;ssh -F $HOME/.ssh/config-blocked-ssh&quot;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Now try pushing or showing a specific remote. That should just work!&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Now, I can move this command into a script with a nice name that I’ll remember for the next time I find myself in this situation.&lt;/p&gt;
&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;
&lt;p&gt;Stack Overflow, &lt;a href=&quot;https://stackoverflow.com/a/41219960/253921&quot;&gt;“Tell git which SSH config file to use”&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Achilleas Pipinellis, &lt;a href=&quot;https://about.gitlab.com/2016/02/18/gitlab-dot-com-now-supports-an-alternate-git-plus-ssh-port/&quot;&gt;“Gitlab.com Now Supports an Alternate git+ssh Port”&lt;/a&gt;. The connection information for Gitlab. Your git repository hosting service likely offers something similar.&lt;/p&gt;
</description>
        <pubDate>Thu, 25 Oct 2018 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/using-git-when-the-firewall-says-no</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/using-git-when-the-firewall-says-no</guid>
        
        
      </item>
    
      <item>
        <title>Installing amp, a text editor</title>
        <description>&lt;p&gt;Recently I learned about &lt;code&gt;amp&lt;/code&gt;, a text editor that might lure me away from &lt;code&gt;vim&lt;/code&gt;. Intrigued by the idea, I tried to install it. I really tried, but I couldn’t manage it. I learned that I had some kind of dependency problem that I could solve by using the most recent tools for the Rust programming language.&lt;/p&gt;
&lt;p&gt;I don’t want to learn Rust (yet), but I’d like to try &lt;code&gt;amp&lt;/code&gt; as a potential new go-to text editor. I wasn’t in the mood to learn enough about Rust tools to resolve the problem myself, so &lt;a href=&quot;https://github.com/jmacdonald/amp/issues/108#issuecomment-422650417&quot;&gt;I posted an issue to github&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Fortunately, nice people gave me reasonable-sounding instructions, so I’m trying them. (Spoiler: they worked on my machine. Read on.)&lt;/p&gt;
&lt;h1 id=&quot;the-sitch&quot;&gt;The Sitch&lt;/h1&gt;
&lt;p&gt;I’m on Pop!_OS 18.04, which is mostly Ubuntu 18.04. I tried to follow &lt;a href=&quot;https://github.com/jmacdonald/amp/issues/108#issuecomment-422650417&quot;&gt;these instructions&lt;/a&gt;, and I ended up with a compile error that seems to relate to a dependency version mismatch with &lt;code&gt;libssh2-sys-0.2.11&lt;/code&gt;. And I literally have no idea what that signifies. I understand the individual words, but not the significance of the sentence as a whole.&lt;/p&gt;
&lt;p&gt;According to &lt;a href=&quot;https://github.com/rust-osdev/bootimage/issues/12&quot;&gt;this Rust-related issue&lt;/a&gt;, this might signal an out-of-date version of Rust. I assume that whatever version of Rust I have came when I installed &lt;code&gt;cargo&lt;/code&gt; and that puts me out of rocks. I just started using &lt;code&gt;cargo&lt;/code&gt; minutes earlier, so I don’t know how it installs a Rust compiler nor how to change it nor whether somehow, magically, at some point in the past I accidentally installed some out-of-date version of the Rust development environment….&lt;/p&gt;
&lt;p&gt;Evidently, since I’d tried to install &lt;code&gt;cargo&lt;/code&gt; through the Ubuntu package manager &lt;code&gt;apt&lt;/code&gt;, I probably got an out-of-date version, which led me to this dependency mismatch. I suppose this illustrates the down side of using package managers with rapidly-evolving software. Since then, I have removed &lt;code&gt;cargo&lt;/code&gt; from my system in the hopes of returning it to its previous state. With luck, I have nothing hanging around that will interfere with installing &lt;code&gt;amp&lt;/code&gt; in the future.&lt;/p&gt;
&lt;h1 id=&quot;some-hope&quot;&gt;Some Hope&lt;/h1&gt;
&lt;p&gt;I have gleaned from the comments on my &lt;code&gt;amp&lt;/code&gt; issue the following instructions:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Install a stable version of Rust using &lt;code&gt;rustup&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Install &lt;code&gt;cargo&lt;/code&gt;, and presumably it will use the stable version of Rust that I would have just installed.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;cargo install --git https://github.com/jmacdonald/amp&lt;/code&gt;, which I’d tried earlier, and which led me to this mess and to writing these words.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So let me try.&lt;/p&gt;
&lt;h1 id=&quot;let-me-try&quot;&gt;Let Me Try&lt;/h1&gt;
&lt;p&gt;I follow the instructions at &lt;a href=&quot;https://www.rust-lang.org/en-US/install.html&quot; class=&quot;uri&quot;&gt;https://www.rust-lang.org/en-US/install.html&lt;/a&gt; to install &lt;code&gt;rustup&lt;/code&gt;, which seems to be like &lt;code&gt;sdkman&lt;/code&gt; in the Java world, &lt;code&gt;rvm&lt;/code&gt; for Ruby, and so on.&lt;/p&gt;
&lt;p&gt;I see a version of Rust from literally 8 days ago. I feel very bleeding-edge.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; curl https://sh.rustup.rs &lt;span class=&quot;at&quot;&gt;-sSf&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;sh&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;[Many&lt;/span&gt; instructions, some of which provide evidence of installing up-to-date rust and cargo.]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So I seem to get two for the price of one. I will need to move &lt;code&gt;$HOME/.cargo&lt;/code&gt; to where I store my dotfiles in a git repository and then &lt;code&gt;stow&lt;/code&gt; it. No problem. I will also need to commit changes to my shell profile scripts, so before I continue, let me check that my &lt;code&gt;dotfiles&lt;/code&gt; repository is clean.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;# In another shell&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; cd &lt;span class=&quot;va&quot;&gt;$DOTFILES_PROJECT_ROOT&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a href=&quot;#cb2-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; git status &lt;span class=&quot;at&quot;&gt;-s&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-4&quot;&gt;&lt;a href=&quot;#cb2-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;[No&lt;/span&gt; uncommitted changes.]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Since my dotfiles are clean, I can continue. I can uninstall any time with &lt;code&gt;rustup self uninstall&lt;/code&gt;, so I note that command here in this article so that I might remember where to look for it later.&lt;/p&gt;
&lt;p&gt;I continue with the installation using the default options, because—and I can’t stress this enough—I don’t know what I’m doing.&lt;/p&gt;
&lt;p&gt;Back in the first shell window, where I’m installing &lt;code&gt;rustup&lt;/code&gt;, I choose &lt;strong&gt;Proceed with installation (default)&lt;/strong&gt; because it is the &lt;strong&gt;default&lt;/strong&gt;, then I see evidence of installing something.&lt;/p&gt;
&lt;h2 id=&quot;rust-is-installed-now.-great&quot;&gt;Rust is installed now. Great!&lt;/h2&gt;
&lt;p&gt;Before I go anywhere and do anything, I commit changes to my dotfiles.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; cd &lt;span class=&quot;va&quot;&gt;$DOTFILES_PROJECT_ROOT&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-2&quot;&gt;&lt;a href=&quot;#cb3-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; git status &lt;span class=&quot;at&quot;&gt;-s&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-3&quot;&gt;&lt;a href=&quot;#cb3-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;[I&lt;/span&gt; see changes to .profile and .bash_profile, but strangely not .zprofile, so I guess I don&lt;span class=&quot;st&quot;&gt;&amp;#39;t have one. I still don&amp;#39;&lt;/span&gt;t understand the difference between the profile files and the env files and the rc files.]&lt;/span&gt;
&lt;span id=&quot;cb3-4&quot;&gt;&lt;a href=&quot;#cb3-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; git add &lt;span class=&quot;at&quot;&gt;-A&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-5&quot;&gt;&lt;a href=&quot;#cb3-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; git commit &lt;span class=&quot;at&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;Installed Rust and Cargo with rustup.&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-6&quot;&gt;&lt;a href=&quot;#cb3-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; git push offsite-backup&lt;/span&gt;
&lt;span id=&quot;cb3-7&quot;&gt;&lt;a href=&quot;#cb3-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; popd&lt;/span&gt;
&lt;span id=&quot;cb3-8&quot;&gt;&lt;a href=&quot;#cb3-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;# I have `cd` aliased to `pushd`, so every `cd` is just a `pushd`. I like it.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Next, I add &lt;code&gt;cargo&lt;/code&gt; to my system path.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb4&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb4-1&quot;&gt;&lt;a href=&quot;#cb4-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; source &lt;span class=&quot;va&quot;&gt;$HOME&lt;/span&gt;/.cargo/env&lt;/span&gt;
&lt;span id=&quot;cb4-2&quot;&gt;&lt;a href=&quot;#cb4-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; env &lt;span class=&quot;kw&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;at&quot;&gt;-i&lt;/span&gt; cargo&lt;/span&gt;
&lt;span id=&quot;cb4-3&quot;&gt;&lt;a href=&quot;#cb4-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;PATH&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;=&lt;/span&gt;/home/jbrains/.cargo/bin:[the &lt;span class=&quot;ex&quot;&gt;rest&lt;/span&gt; of my PATH variable]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Next, I move &lt;code&gt;.cargo&lt;/code&gt; to where I track my dotfiles, then &lt;code&gt;stow&lt;/code&gt; it.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb5&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb5-1&quot;&gt;&lt;a href=&quot;#cb5-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; mkdir &lt;span class=&quot;at&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;va&quot;&gt;$DOTFILES_PROJECT_ROOT&lt;/span&gt;/system76-laptop/cargo&lt;/span&gt;
&lt;span id=&quot;cb5-2&quot;&gt;&lt;a href=&quot;#cb5-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; mv &lt;span class=&quot;va&quot;&gt;$HOME&lt;/span&gt;/.cargo &lt;span class=&quot;va&quot;&gt;$DOTFILES_PROJECT_ROOT&lt;/span&gt;/system76-laptop/cargo&lt;/span&gt;
&lt;span id=&quot;cb5-3&quot;&gt;&lt;a href=&quot;#cb5-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; stow &lt;span class=&quot;at&quot;&gt;-t&lt;/span&gt; &lt;span class=&quot;va&quot;&gt;$HOME&lt;/span&gt; &lt;span class=&quot;at&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;va&quot;&gt;$DOTFILES_PROJECT_ROOT&lt;/span&gt;/system76-laptop cargo&lt;/span&gt;
&lt;span id=&quot;cb5-4&quot;&gt;&lt;a href=&quot;#cb5-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; ls &lt;span class=&quot;at&quot;&gt;-al&lt;/span&gt; &lt;span class=&quot;va&quot;&gt;$HOME&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;grep&lt;/span&gt; cargo&lt;/span&gt;
&lt;span id=&quot;cb5-5&quot;&gt;&lt;a href=&quot;#cb5-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;[Evidence&lt;/span&gt; that &lt;span class=&quot;va&quot;&gt;$HOME&lt;/span&gt;/.cargo points to the expected place in my dotfiles repository.]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This requires committing new changes to my dotfiles.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb6&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb6-1&quot;&gt;&lt;a href=&quot;#cb6-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; cd &lt;span class=&quot;va&quot;&gt;$DOTFILES_PROJECT_ROOT&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-2&quot;&gt;&lt;a href=&quot;#cb6-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; git add &lt;span class=&quot;at&quot;&gt;-n&lt;/span&gt; .&lt;/span&gt;
&lt;span id=&quot;cb6-3&quot;&gt;&lt;a href=&quot;#cb6-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;[I&lt;/span&gt; see lots of stuff that probably shouldn&lt;span class=&quot;st&quot;&gt;&amp;#39;t be in git, because I can download it.]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-4&quot;&gt;&lt;a href=&quot;#cb6-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;$ cd system76-laptop/cargo/.cargo&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-5&quot;&gt;&lt;a href=&quot;#cb6-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;$ vim .gitignore&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-6&quot;&gt;&lt;a href=&quot;#cb6-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;# In .gitignore&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-7&quot;&gt;&lt;a href=&quot;#cb6-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;# Stuff I can download any time&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-8&quot;&gt;&lt;a href=&quot;#cb6-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;registry&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-9&quot;&gt;&lt;a href=&quot;#cb6-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;bin&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-10&quot;&gt;&lt;a href=&quot;#cb6-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;# A nested git repository that I&amp;#39;&lt;/span&gt;m not going to track&lt;/span&gt;
&lt;span id=&quot;cb6-11&quot;&gt;&lt;a href=&quot;#cb6-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;fu&quot;&gt;git&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-12&quot;&gt;&lt;a href=&quot;#cb6-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; git status &lt;span class=&quot;at&quot;&gt;-s&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-13&quot;&gt;&lt;a href=&quot;#cb6-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;#39;system76-laptop/cargo/.cargo/.crates.toml&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-14&quot;&gt;&lt;a href=&quot;#cb6-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;#39;system76-laptop/cargo/.cargo/.gitignore&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-15&quot;&gt;&lt;a href=&quot;#cb6-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;#39;system76-laptop/cargo/.cargo/env&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-16&quot;&gt;&lt;a href=&quot;#cb6-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;[MUCH&lt;/span&gt; better. That all looks like pure configuration files.]&lt;/span&gt;
&lt;span id=&quot;cb6-17&quot;&gt;&lt;a href=&quot;#cb6-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; git add &lt;span class=&quot;at&quot;&gt;-A&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-18&quot;&gt;&lt;a href=&quot;#cb6-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; git commit &lt;span class=&quot;at&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;We can now stow Cargo.&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-19&quot;&gt;&lt;a href=&quot;#cb6-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; git push offsite-backup&lt;/span&gt;
&lt;span id=&quot;cb6-20&quot;&gt;&lt;a href=&quot;#cb6-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; popd&lt;/span&gt;
&lt;span id=&quot;cb6-21&quot;&gt;&lt;a href=&quot;#cb6-21&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;# I have `cd` aliased to `pushdga`, so every `cd` is just a `pushd`. I like it.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-22&quot;&gt;&lt;a href=&quot;#cb6-22&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; ls &lt;span class=&quot;at&quot;&gt;-al&lt;/span&gt; &lt;span class=&quot;va&quot;&gt;$HOME&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;grep&lt;/span&gt; cargo&lt;/span&gt;
&lt;span id=&quot;cb6-23&quot;&gt;&lt;a href=&quot;#cb6-23&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;lrwxrwxrwx&lt;/span&gt;  1 jbrains jbrains     70 Sep 21 14:49 .cargo &lt;span class=&quot;at&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;va&quot;&gt;$DOTFILES_PROJECT_ROOT&lt;/span&gt;/system76-laptop/cargo/.cargo&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now I can try to do something with &lt;code&gt;cargo&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;lets-do-something-with-cargo&quot;&gt;Let’s Do Something With &lt;code&gt;cargo&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;In principle, I should now be able to install &lt;code&gt;amp&lt;/code&gt; with &lt;code&gt;cargo&lt;/code&gt;. Let’s see.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb7&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb7-1&quot;&gt;&lt;a href=&quot;#cb7-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; cargo install &lt;span class=&quot;at&quot;&gt;--git&lt;/span&gt; https://github.com/jmacdonald/amp&lt;/span&gt;
&lt;span id=&quot;cb7-2&quot;&gt;&lt;a href=&quot;#cb7-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;[...]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-3&quot;&gt;&lt;a href=&quot;#cb7-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;   &lt;span class=&quot;ex&quot;&gt;Compiling&lt;/span&gt; gag v0.1.10&lt;/span&gt;
&lt;span id=&quot;cb7-4&quot;&gt;&lt;a href=&quot;#cb7-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;   &lt;span class=&quot;ex&quot;&gt;Compiling&lt;/span&gt; num-traits v0.1.43&lt;/span&gt;
&lt;span id=&quot;cb7-5&quot;&gt;&lt;a href=&quot;#cb7-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;   &lt;span class=&quot;ex&quot;&gt;Compiling&lt;/span&gt; thread-id v2.0.0&lt;/span&gt;
&lt;span id=&quot;cb7-6&quot;&gt;&lt;a href=&quot;#cb7-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;error:&lt;/span&gt; failed to run custom build command for &lt;span class=&quot;kw&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;onig_sys&lt;/span&gt; v68.0.1&lt;span class=&quot;kw&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-7&quot;&gt;&lt;a href=&quot;#cb7-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;process&lt;/span&gt; didn&lt;span class=&quot;st&quot;&gt;&amp;#39;t exit successfully: `/tmp/cargo-installES1HqJ/release/build/onig_sys-4b9d7f80a3b9005f/build-script-build` (exit code: 101)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-8&quot;&gt;&lt;a href=&quot;#cb7-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;--- stdout&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-9&quot;&gt;&lt;a href=&quot;#cb7-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;running: &amp;quot;cmake&amp;quot; &amp;quot;/mnt/extra-space/Workspaces/dotfiles/system76-laptop/cargo/.cargo/registry/src/github.com-1ecc6299db9ec823/onig_sys-68.0.1/oniguruma&amp;quot; &amp;quot;-DBUILD_SHARED_LIBS=OFF&amp;quot; &amp;quot;-DCMAKE_INSTALL_PREFIX=/tmp/cargo-installES1HqJ/release/build/onig_sys-849a1e77a747337f/out&amp;quot; &amp;quot;-DCMAKE_C_FLAGS= -ffunction-sections -fdata-sections -fPIC -m64&amp;quot; &amp;quot;-DCMAKE_C_COMPILER=/usr/bin/cc&amp;quot; &amp;quot;-DCMAKE_CXX_FLAGS= -ffunction-sections -fdata-sections -fPIC -m64&amp;quot; &amp;quot;-DCMAKE_CXX_COMPILER=/usr/bin/c++&amp;quot; &amp;quot;-DCMAKE_BUILD_TYPE=Release&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-10&quot;&gt;&lt;a href=&quot;#cb7-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-11&quot;&gt;&lt;a href=&quot;#cb7-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;--- stderr&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-12&quot;&gt;&lt;a href=&quot;#cb7-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;thread &amp;#39;&lt;/span&gt;main&lt;span class=&quot;st&quot;&gt;&amp;#39; panicked at &amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-13&quot;&gt;&lt;a href=&quot;#cb7-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;failed&lt;/span&gt; to execute command: No such file or directory &lt;span class=&quot;er&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;os&lt;/span&gt; error 2&lt;span class=&quot;kw&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-14&quot;&gt;&lt;a href=&quot;#cb7-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;fu&quot;&gt;cmake&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;`&lt;/span&gt; not installed&lt;span class=&quot;pp&quot;&gt;?&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-15&quot;&gt;&lt;a href=&quot;#cb7-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-16&quot;&gt;&lt;a href=&quot;#cb7-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;build&lt;/span&gt; script failed, must exit now&lt;span class=&quot;st&quot;&gt;&amp;#39;, /home/jbrains/.cargo/registry/src/github.com-1ecc6299db9ec823/cmake-0.1.31/src/lib.rs:643:5&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-17&quot;&gt;&lt;a href=&quot;#cb7-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;note: Run with `RUST_BACKTRACE=1` for a backtrace.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-18&quot;&gt;&lt;a href=&quot;#cb7-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-19&quot;&gt;&lt;a href=&quot;#cb7-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;warning: build failed, waiting for other jobs to finish...&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-20&quot;&gt;&lt;a href=&quot;#cb7-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;error: failed to compile `amp v0.5.0 (https://github.com/jmacdonald/amp#07e6c192)`, intermediate artifacts can be found at `/tmp/cargo-installES1HqJ`&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-21&quot;&gt;&lt;a href=&quot;#cb7-21&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-22&quot;&gt;&lt;a href=&quot;#cb7-22&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;Caused by:&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-23&quot;&gt;&lt;a href=&quot;#cb7-23&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;  build failed&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Nope.&lt;/p&gt;
&lt;p&gt;Interesting… “is &lt;code&gt;cmake&lt;/code&gt; not installed?” Let’s see.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb8&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb8-1&quot;&gt;&lt;a href=&quot;#cb8-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; cmake&lt;/span&gt;
&lt;span id=&quot;cb8-2&quot;&gt;&lt;a href=&quot;#cb8-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;zsh:&lt;/span&gt; command not found: cmake&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Fine. How do I install it, then?&lt;/p&gt;
&lt;p&gt;Oh, boy. According to &lt;a href=&quot;https://www.pyimagesearch.com/2018/05/28/ubuntu-18-04-how-to-install-opencv/&quot; class=&quot;uri&quot;&gt;https://www.pyimagesearch.com/2018/05/28/ubuntu-18-04-how-to-install-opencv/&lt;/a&gt;, this will take some work.&lt;/p&gt;
&lt;h2 id=&quot;install-cmake&quot;&gt;Install &lt;code&gt;cmake&lt;/code&gt;&lt;/h2&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb9&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb9-1&quot;&gt;&lt;a href=&quot;#cb9-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; python3 &lt;span class=&quot;at&quot;&gt;--version&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb9-2&quot;&gt;&lt;a href=&quot;#cb9-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;Python&lt;/span&gt; 3.6.5&lt;/span&gt;
&lt;span id=&quot;cb9-3&quot;&gt;&lt;a href=&quot;#cb9-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;[OK.]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb9-4&quot;&gt;&lt;a href=&quot;#cb9-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; sudo apt-get update&lt;/span&gt;
&lt;span id=&quot;cb9-5&quot;&gt;&lt;a href=&quot;#cb9-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; sudo apt-get upgrade&lt;/span&gt;
&lt;span id=&quot;cb9-6&quot;&gt;&lt;a href=&quot;#cb9-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;[Installing&lt;/span&gt; a handful of libraries, including something related to python. Maybe that&lt;span class=&quot;st&quot;&gt;&amp;#39;s good news?]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb9-7&quot;&gt;&lt;a href=&quot;#cb9-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;$ sudo apt-get install build-essential cmake unzip pkg-config&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb9-8&quot;&gt;&lt;a href=&quot;#cb9-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;[Indeed, cmake was not installed. Now it is installing.]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That wasn’t so bad! Let’s see whether that fixes the entire problem.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb10&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb10-1&quot;&gt;&lt;a href=&quot;#cb10-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; cargo install &lt;span class=&quot;at&quot;&gt;--git&lt;/span&gt; https://github.com/jmacdonald/amp&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This runs for a few minutes. And then it stops. And it appears to work!&lt;/p&gt;
&lt;h2 id=&quot;run-amp&quot;&gt;Run &lt;code&gt;amp&lt;/code&gt;&lt;/h2&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb11&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb11-1&quot;&gt;&lt;a href=&quot;#cb11-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; amp&lt;/span&gt;
&lt;span id=&quot;cb11-2&quot;&gt;&lt;a href=&quot;#cb11-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;[Something&lt;/span&gt; that looks like a text editor and an empty buffer. Yay!]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;All right! Now… how exactly does one use &lt;code&gt;amp&lt;/code&gt;?&lt;/p&gt;
</description>
        <pubDate>Fri, 21 Sep 2018 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/installing-amp-a-text-editor</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/installing-amp-a-text-editor</guid>
        
        
      </item>
    
      <item>
        <title>Moving to Linux: Evernote</title>
        <description>&lt;p&gt;I store a lot of stuff in Evernote. Too much. My Evernote library has become a graveyard. Sadly, Evernote doesn’t produce a Linux client, which leads to one severe user experience problem: deleting notes.&lt;/p&gt;
&lt;p&gt;On a desktop client, one can select many notes then delete them with a single command. One can’t do this on Android nor the web client.&lt;/p&gt;
&lt;p&gt;On Android, one can select 20 notes at a time—I can’t &lt;em&gt;begin&lt;/em&gt; to imagine the reason for this limitation—which doesn’t suffice when I have 210 notes to delete. Why not at least let me delete all the notes that match the current search criteria?!&lt;/p&gt;
&lt;p&gt;On the web, one can delete a single note at a time by clicking multiple times. No.&lt;/p&gt;
&lt;p&gt;What could possibly help here?&lt;/p&gt;
&lt;h2 id=&quot;what-could-possibly-help-here&quot;&gt;What Could Possibly Help Here&lt;/h2&gt;
&lt;p&gt;I search the web for &lt;code&gt;delete all notes evernote linux&lt;/code&gt;. This leads me to &lt;a href=&quot;http://www.linuxandubuntu.com/home/3-best-evernote-alternatives-with-official-linux-clients&quot; class=&quot;uri&quot;&gt;http://www.linuxandubuntu.com/home/3-best-evernote-alternatives-with-official-linux-clients&lt;/a&gt;, which suggests NixNote. NixNote threatens to synchronize with Evernote, and this threatens to meet my immediate needs.&lt;/p&gt;
&lt;p&gt;I learned about two versions of NixNote, and as of 2018-09-17, when I write these words, I recommend that you try the NixNote fork maintained by Github user &lt;code&gt;robert7&lt;/code&gt;. &lt;a href=&quot;https://github.com/robert7/nixnote2/&quot; class=&quot;uri&quot;&gt;https://github.com/robert7/nixnote2/&lt;/a&gt; There, you’ll find an AppImage release. Read &lt;a href=&quot;https://github.com/robert7/nixnote2/wiki/HowTo---Run-AppImage&quot; class=&quot;uri&quot;&gt;https://github.com/robert7/nixnote2/wiki/HowTo---Run-AppImage&lt;/a&gt; to install the AppImage.&lt;/p&gt;
&lt;h3 id=&quot;the-log&quot;&gt;The Log&lt;/h3&gt;
&lt;p&gt;I strongly recommend monitoring the NixNote logs to get an idea what’s going on, especially when you synchronize notes for the first time. I know that I prefer to see what’s happening in some detail when I use software for the first time, since I typically don’t trust it to work at all.&lt;/p&gt;
&lt;p&gt;I found logs in &lt;code&gt;$HOME/.nixnote/logs-*&lt;/code&gt;, where it looks like the directory name reflects some kind of account number internal to NixNote. My NixNote account (not the same as my Everote account) appears to be number &lt;code&gt;2&lt;/code&gt;, so that means that I’ll find the logs in the subdirectory &lt;code&gt;logs-2&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; cd &lt;span class=&quot;va&quot;&gt;$HOME&lt;/span&gt;/.nixnote/logs-2&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; tail &lt;span class=&quot;at&quot;&gt;-f&lt;/span&gt; messages.log&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This helps me see that NixNote is making progress on long-running jobs. Once it finishes synchronizing with Evernote the first time, NixNote becomes much more responsive and behaves the way one would expect such an application to behave.&lt;/p&gt;
&lt;h3 id=&quot;synchronize&quot;&gt;Synchronize&lt;/h3&gt;
&lt;p&gt;In order to connect NixNote to Evernote, I learn that I need to synchronize notes.&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;&lt;strong&gt;Tools &amp;gt; Synchronize&lt;/strong&gt; (&lt;code&gt;F9&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Log in to Evernote in order to authorize NixNote to talk to Evernote.&lt;/li&gt;
&lt;li&gt;Wait. Monitor the logs.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Sadly, apart from a spinning icon, NixNote doesn’t appear to report much in the way of status. At least, I don’t notice it right away. (If one can’t find the feature, then it doesn’t exist.) I learn that I can also check on how many notes NixNote has processed with &lt;strong&gt;Tools &amp;gt; Database Status&lt;/strong&gt;. This seems to update the number of notes that NixNote has synchronized, but in batches of 50.&lt;/p&gt;
&lt;p&gt;After a while, I notice a status update in the bottom-left corner. I don’t know why it sometimes appears and sometimes disappears, but it reports progress as “Download 12% complete”. You can follow an open issue at &lt;a href=&quot;https://github.com/baumgarr/nixnote2/issues/457&quot; class=&quot;uri&quot;&gt;https://github.com/baumgarr/nixnote2/issues/457&lt;/a&gt;. (It’s not clear to me whether I should have opened that issue at &lt;code&gt;baumgarr&lt;/code&gt;’s version or &lt;code&gt;robert7&lt;/code&gt;’s version, but &lt;code&gt;robert7&lt;/code&gt; has commented on it, so I think it’ll be fine.)&lt;/p&gt;
&lt;h3 id=&quot;backup-and-restore&quot;&gt;Backup and Restore&lt;/h3&gt;
&lt;p&gt;I want to keep my data safe, so I always look for some kind of export or backup feature. NixNote has it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;File &amp;gt; Backup Database&lt;/strong&gt;. Then choose a directory and a file name for your NixNote Export file, of type &lt;code&gt;.nnex&lt;/code&gt;. Prepare yourself for a large file: mine was 7.6 GiB.&lt;/p&gt;
&lt;h3 id=&quot;cli&quot;&gt;CLI?&lt;/h3&gt;
&lt;p&gt;NixNote appears to have some kind of command-line query interface, which I haven’t explored yet. It gives me the idea that I could do some interesting things with my notes. I don’t yet know how to use the command-line interface with the AppImage version of the application, so if you know how to do that, then please let me know.&lt;/p&gt;
&lt;h3 id=&quot;move-your-data-directory&quot;&gt;Move Your Data Directory&lt;/h3&gt;
&lt;p&gt;If you’d like to store your NixNote data elsewhere, then can do that. &lt;a href=&quot;https://github.com/robert7/nixnote2/wiki/Relocation-of-config-and-data-directory&quot; class=&quot;uri&quot;&gt;https://github.com/robert7/nixnote2/wiki/Relocation-of-config-and-data-directory&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;i-deleted-3000-notes&quot;&gt;I Deleted 3000 Notes&lt;/h3&gt;
&lt;p&gt;I managed to delete over 3000 notes and several old notebooks. I had to go to the web application to empty the trash, but I don’t mind doing that every so often.&lt;/p&gt;
&lt;h2 id=&quot;what-if-you-installed-nixnote-2-and-not-2.1&quot;&gt;What If You Installed NixNote 2 and not 2.1?&lt;/h2&gt;
&lt;p&gt;When I first started, I installed NixNote from my package manager. Fortunately, if you did the same, then you can move from it to the more updated AppImage version relatively easily.&lt;/p&gt;
&lt;p&gt;First, I had found the package and installed it.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; pushd /etc&lt;span class=&quot;kw&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;sudo&lt;/span&gt; git status &lt;span class=&quot;at&quot;&gt;-s&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;[Evidence&lt;/span&gt; of no uncommitted changes in /etc]&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a href=&quot;#cb2-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; popd&lt;/span&gt;
&lt;span id=&quot;cb2-4&quot;&gt;&lt;a href=&quot;#cb2-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-5&quot;&gt;&lt;a href=&quot;#cb2-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; sudo apt-cache search nixnote&lt;/span&gt;
&lt;span id=&quot;cb2-6&quot;&gt;&lt;a href=&quot;#cb2-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;nixnote2&lt;/span&gt; &lt;span class=&quot;at&quot;&gt;-&lt;/span&gt; Open Source Evernote client&lt;/span&gt;
&lt;span id=&quot;cb2-7&quot;&gt;&lt;a href=&quot;#cb2-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; sudo apt-get install nixnote2&lt;/span&gt;
&lt;span id=&quot;cb2-8&quot;&gt;&lt;a href=&quot;#cb2-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;[Evidence&lt;/span&gt; of installation.]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Next, I’d launched NixNote and synchronized notes.&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;&lt;strong&gt;Tools &amp;gt; Synchronize&lt;/strong&gt; (&lt;code&gt;F9&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Log in to Evernote in order to authorize NixNote to talk to Evernote.&lt;/li&gt;
&lt;li&gt;Wait.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;After moving notes around and generally exploring what NixNote could do, I migrated it to NixNote 2.1.&lt;/p&gt;
&lt;h2 id=&quot;migrating-to-nixnote-2.1&quot;&gt;Migrating To NixNote 2.1&lt;/h2&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;In NixNote 2 (installed by &lt;code&gt;apt&lt;/code&gt;), backup the database, just to be safe.&lt;/li&gt;
&lt;li&gt;Download the NixNote 2.1 (the AppImage version).&lt;/li&gt;
&lt;li&gt;Move NixNote 2.1 to an Applications directory, which I call &lt;code&gt;$APPLICATIONS&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Create a &lt;code&gt;.desktop&lt;/code&gt; file in &lt;code&gt;$HOME/.local/share/applications&lt;/code&gt; to launch the AppImage. See &lt;a href=&quot;https://stackoverflow.com/questions/12964512/creating-an-application-launcher-for-gnome-3-in-ubuntu&quot; class=&quot;uri&quot;&gt;https://stackoverflow.com/questions/12964512/creating-an-application-launcher-for-gnome-3-in-ubuntu&lt;/a&gt; for details.&lt;/li&gt;
&lt;li&gt;Launch NixNote 2.1. Verify that I can see my notes and synchronize them.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$ sudo apt-get remove nixnote2 &amp;amp;&amp;amp; sudo apt-get autoremove&lt;/code&gt; to uninstall NixNote 2.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Win!&lt;/p&gt;
</description>
        <pubDate>Mon, 17 Sep 2018 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/moving-to-linux-evernote</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/moving-to-linux-evernote</guid>
        
        
        <category>Moving to Linux</category>
        
      </item>
    
      <item>
        <title>Add a Personal Payee Your Own Damn Self</title>
        <description>&lt;blockquote&gt;
&lt;p&gt;As of October 2022, these instructions no longer work. Sorry about that, folks. Maybe someone out there knows how to fix them? Please &lt;a href=&quot;https://tell.jbrains.ca&quot;&gt;tell me&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;section style=&quot;filter: blur(5px)&quot;&gt;
&lt;p&gt;I have bank accounts with TD Canada Trust and I occasionally need to add a “personal payee”. One used to need to call them in order to do this, but now it appears that you can do this yourself using online banking as long as you know how. This might save you some effort, especially if you dislike banking over the phone.&lt;/p&gt;
&lt;h1 id=&quot;adding-a-personal-payee&quot;&gt;Adding a Personal Payee&lt;/h1&gt;
&lt;p&gt;These instructions were correct as of August 2018.&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Ask your intended recipient for their TD Canada Trust banking information: transit number and account number.&lt;/li&gt;
&lt;li&gt;Log in to TD Canada Trust online banking.&lt;/li&gt;
&lt;li&gt;Under “Pay Bills”, look for “Pay Canadian Bills” and then select “Add Payee”.&lt;/li&gt;
&lt;li&gt;Choose the right Access Card, in case like me, you have both personal and business access cards.&lt;/li&gt;
&lt;li&gt;Search for a “Payee Name” of “personal payee”. This means that you’re adding an individual instead of a known vendor/company like your mobile phone provider. (I know; what a hack!)&lt;/li&gt;
&lt;li&gt;Don’t be put off by the menacing-looking “Account Number” field. I’ve explained how to format the account number below.&lt;/li&gt;
&lt;li&gt;Enter a human-friendly name in the “My Payee Name” field.&lt;/li&gt;
&lt;li&gt;Press “Next”, then confirm what you’ve entered and save it.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Now you can check the list of payees for the one that you’ve just added. If you see a mistake, then press “Edit” to fix it. Now you can send this person money overnight and not pay Interac e-mail Transfer fees.&lt;/p&gt;
&lt;h2 id=&quot;formatting-the-account-number&quot;&gt;Formatting the Account Number&lt;/h2&gt;
&lt;p&gt;Your recipient will probably give you the following information:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Account Holder Name: Arbitrary Human&lt;/li&gt;
&lt;li&gt;Transit Number: 12345&lt;/li&gt;
&lt;li&gt;Institution Number: 004&lt;/li&gt;
&lt;li&gt;Account Number: 9876543&lt;/li&gt;
&lt;/ul&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Use the Institution Number unchanged as the “Bank Code”. It’s &lt;code&gt;004&lt;/code&gt; because that represents TD Canada Trust.&lt;/li&gt;
&lt;li&gt;Drop the last digit of the Transit Number and add a 0 to the front, so in this example, that becomes &lt;code&gt;01234&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Use the Account Number unchanged.&lt;/li&gt;
&lt;li&gt;Pick a “nickname”, which is up to 5 characters long and &lt;em&gt;must&lt;/em&gt; start with a letter. Choose only letters and numbers. I chose &lt;code&gt;HUMAN&lt;/code&gt; for this example.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Now put these four bits of text together and your personal payee “Account Number” is &lt;code&gt;004012349876543HUMAN&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If your recipient gives you an 11-digit account number, then use only the last 7 digits. For example, &lt;code&gt;0667&lt;/code&gt; refers to a small business bank account (or at least it once did).&lt;/p&gt;
&lt;h1 id=&quot;why-not-just-use-interac-e-mail-transfer&quot;&gt;Why Not Just Use Interac E-mail Transfer?&lt;/h1&gt;
&lt;p&gt;I like Interac e-mail transfers in some ways, but a TD Canada Trust personal payee offers a few advantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;No need to use a password with the transfer, since some people manage to stumble with passwords, especially if you send them money more than once.&lt;/li&gt;
&lt;li&gt;No extra fees to pay &lt;em&gt;nor to keep track of&lt;/em&gt;. I care more about the cost of the record-keeping than the cost of the transfer itself.&lt;/li&gt;
&lt;li&gt;Higher transaction limits. I can send CAD 5000 per day with no limit over a 7-day nor 3-day period.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Of course, if you know something that I don’t about TD Canada Trust direct transfers and you want to share it with me, then contact me through the various means on this page, because I’d prefer not know than not to know.&lt;/p&gt;
&lt;/section&gt;
</description>
        <pubDate>Wed, 29 Aug 2018 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/add-a-personal-payee-your-own-damn-self</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/add-a-personal-payee-your-own-damn-self</guid>
        
        
      </item>
    
      <item>
        <title>No, This Album Is Not A Compilation</title>
        <description>&lt;p&gt;In the process of switching from Mac OS to Pop!_OS, I liberated my music from iTunes, and then sought a music organizer for Linux. I am in the process of trying &lt;a href=&quot;https://www.clementine-player.org&quot;&gt;Clementine&lt;/a&gt;. I found it easy to import my music, but Clementine has listed some albums under “Various Artists” that I didn’t expect to see there. I know that a single artist recorded these albums, so I want them to show up where I expect to see them.&lt;/p&gt;
&lt;p&gt;Moving the albums into different directories didn’t change how Clementine organizes the music; Clementine uses metadata in the music files themselves to organize them by album and artist. I used &lt;a href=&quot;https://kid3.sourceforge.io/&quot;&gt;Kid3 Audio Tagger&lt;/a&gt; to change the metadata of the affected music files. Specifically, I used the command-line interface so that I could fix all my music with a single command.&lt;/p&gt;
&lt;p&gt;Visit &lt;a href=&quot;https://kid3.sourceforge.io/#download&quot; class=&quot;uri&quot;&gt;https://kid3.sourceforge.io/#download&lt;/a&gt; for installation instructions. I installed the package named &lt;code&gt;kid3-cli&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I did this:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Move the &lt;em&gt;real&lt;/em&gt; compilations to another directory somewhere out of the way, leaving a directory tree with only music that I want to mark as “not a compilation”.&lt;/li&gt;
&lt;li&gt;Go to the root of this directory tree with &lt;code&gt;cd&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Run this command.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; find . &lt;span class=&quot;at&quot;&gt;-type&lt;/span&gt; f  &lt;span class=&quot;at&quot;&gt;-exec&lt;/span&gt; kid3-cli &lt;span class=&quot;at&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;set Compilation 0&amp;quot;&lt;/span&gt; {} &lt;span class=&quot;dt&quot;&gt;\;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This sets the “Compilation” tag in each file to &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Next, I rescanned the music library within Clementine and the albums appeared where I expected them to appear. This made me happy.&lt;/p&gt;
&lt;p&gt;I then moved the compilations music directory back to where I store the rest of the music, and then rescanned the music library within Clementine once more. Of course, I could have figured out the &lt;code&gt;find&lt;/code&gt; magic to exclude that one directory, but I didn’t feel like it. If I have to do this more than once again, then I’ll figure out then how to do that.&lt;/p&gt;
</description>
        <pubDate>Tue, 17 Jul 2018 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/no-this-album-is-not-a-compilation</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/no-this-album-is-not-a-compilation</guid>
        
        
        <category>Taming Tools</category>
        
      </item>
    
      <item>
        <title>The Real Reason The WiFi Thermostats Didn&apos;t Work</title>
        <description>&lt;p&gt;Ignore everything I wrote at &lt;a href=&quot;https://jb.rainsberger.ca/permalink/honeywell-wifi-thermostats-not-connecting-to-wifi-network&quot; class=&quot;uri&quot;&gt;https://jb.rainsberger.ca/permalink/honeywell-wifi-thermostats-not-connecting-to-wifi-network&lt;/a&gt; about the failures with my WiFi thermostats. I got that wrong. I have it right now, and I have my wife, her Kobo, and her determination to thank for it.&lt;/p&gt;
&lt;h1 id=&quot;summary&quot;&gt;Summary&lt;/h1&gt;
&lt;p&gt;The Actiontec R3000 modem/router combination device appears to have a limit of 11 WiFi clients connected at once. This will cause devices to mysteriously stop joining the network. We worked around the problem by connecting a wireless access point over a wire (Ethernet) to the Actiontec router, then connecting our devices to the wireless access point. This reduces the number of WiFi clients on the Actiontec router and the problem disappears.&lt;/p&gt;
&lt;p&gt;No, I don’t know why the Actiontec R3000 has this limit. I find it silly. I don’t want to know why, because &lt;a href=&quot;https://blog.jbrains.ca/permalink/ask-why-but-never-answer&quot;&gt;knowing why will only make me feel more sad&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&quot;the-details&quot;&gt;The Details&lt;/h1&gt;
&lt;p&gt;It seemed to start about 6 weeks ago when the WiFi thermostats fell off the WiFi network at home and couldn’t rejoin it. I spent about a week exchanging email with Honeywell support, trying various silly things, watching them work intermittently, and then giving up by turning the thermostats’ WiFi radios off. Before giving up, I wrote &lt;a href=&quot;https://jb.rainsberger.ca/permalink/honeywell-wifi-thermostats-not-connecting-to-wifi-network&quot;&gt;“Honeywell WiFi Thermostats Not Connecting To WiFi Network”&lt;/a&gt;, prematurely concluding that if I reserved IP addresses for the thermostats, then they would stay on the network. This did, after all, seem to work… for a while. The next day, the thermostats fell off the network, I flipped a table, turned their WiFi radios off, and then resigned myself to owning programmable-but-no-longer-WiFi thermostats. It wouldn’t become a problem until the winter, anyway. Then, suddenly, Sarah’s Kobo e-reader wouldn’t join the network either.&lt;/p&gt;
&lt;p&gt;Srsly?!&lt;/p&gt;
&lt;p&gt;Good news: this pointed to the network, not the devices, as the problem. Bad news: I didn’t want to diagnose the problem. Good news: Sarah somehow &lt;em&gt;likes&lt;/em&gt; to look things up, dig through the details, and suggest possible causes. I got to keep working on my tasks while she occasionally tossed out a possible cause. After a few iterations of this, it sounded like she struck gold.&lt;/p&gt;
&lt;p&gt;Sarah found &lt;a href=&quot;https://www.digitalhome.ca/forum/192-bell-aliant-home-phone-internet-iptv/282938-hh-3000-wifi-devices.html&quot;&gt;a discussion thread&lt;/a&gt; at digitalhome.ca in which one participant mentioned that they’d learned from our ISP that the Actiontec R3000 could only handle 11 WiFi clients. The whole thing sounded bizarre to me, but plausible, so I looked at our router’s administrative page and sure enough, I saw 11 connected clients. Sarah was on to something.&lt;/p&gt;
&lt;p&gt;I knew that we had a very long Ethernet cable, which we could use to connect our signal range extender to the Actiontec router, which &lt;em&gt;should&lt;/em&gt; reduce the number of WiFi-connected clients. We tried that, and at first we were crestfallen: the Actiontec router reported WiFi clients connected to the signal range extender as “WiFi connected clients”. But… there were now 14! And the Kobos could connect to the network!&lt;/p&gt;
&lt;p&gt;We rebooted the Actiontec router, then saw only a few WiFi clients directly connected to it, like our television PVR. The Kobos connected without any difficulty. Every other WiFi device in the house seemed to be working, all connected to the signal range extender rather than the Actiontec router. So we tried the WiFi thermostats.&lt;/p&gt;
&lt;p&gt;It took about 2 minutes, but they connected. I turned their WiFi radios back on and one of them connected automatically while the other restarted in WiFi Setup mode, but I connected it to the signal range extender’s network without incident.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Success!&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-network-setup&quot;&gt;The Network Setup&lt;/h2&gt;
&lt;p&gt;We now have an Actiontec R3000 modem/router connected directly to our FibreOp box. It runs a WiFi network that we essentially don’t use. We currently have a Netgear EX7000 WiFi signal range extender connected by Ethernet to the Actiontec R3000, and this signal range extender acts as a WiFi router for the house. We could certainly replace this signal range extender with a plain WiFi router and that would just work, since it now connects to the main network by a wire rather than WiFi.&lt;/p&gt;
&lt;p&gt;WiFi speeds throughout the house have at least doubled.&lt;/p&gt;
&lt;p&gt;We have even connected the television PVR to the Netgear router over Ethernet, so literally nothing in the house uses the Actiontec WiFi network at the moment. This would make it easy to have a guest network separate from the network we use.&lt;/p&gt;
&lt;p&gt;Excellent! We did it!&lt;/p&gt;
&lt;p&gt;If your ISP forces an Actiontec R3000 modem/router on you, then I &lt;strong&gt;strongly&lt;/strong&gt; recommend that you connect another router to the R3000 and then connect your WiFi devices to the second router, in order to avoid this 11-device limit. I didn’t need any specialized networking knowledge to make this work. I simply connected my second router to the Actiontec by Ethernet, then ran the second router as an access point. Easy. Even I knew enough to do it without reading any online tutorial nor calling any networking-savvy friends.&lt;/p&gt;
&lt;p&gt;Enjoy.&lt;/p&gt;
</description>
        <pubDate>Tue, 03 Jul 2018 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/the-real-reason-my-wifi-thermostats-didnt-work</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/the-real-reason-my-wifi-thermostats-didnt-work</guid>
        
        
        <category>The Internet of Shit</category>
        
      </item>
    
      <item>
        <title>Honeywell WiFi Thermostats Not Connecting To WiFi Network</title>
        <description>&lt;p&gt;Against my better judgment, I purchased two Honeywell RTH8580WF WiFi thermostats several years ago. I did this &lt;em&gt;only&lt;/em&gt; after verifying that &lt;strong&gt;the thermostats work as expected, even when not connected to the network&lt;/strong&gt;. One can program schedules into them and they control the heating system, even when they can’t connect to the network. This gave me the confidence to try them. In the worst case, they become annoying-to-program-but-at-least-programmable thermostats.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Do not read any further. Read the next article for the &lt;em&gt;real&lt;/em&gt; reason why these thermostats stopped working, and then come back here for a laugh. No, really.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The devices worked just fine for several years. I could control them over the internet. I could program them relatively easily. I could even turn the heat on just before embarking on the 1-hour-long trip from the airport to home after a winter trip. I could turn the heat on from bed if I happened to wake up a little early (or a little late). I decided that I like the devices.&lt;/p&gt;
&lt;p&gt;And then they fell off the network and wouldn’t climb back on. For days. Ugh.&lt;/p&gt;
&lt;p&gt;I didn’t think I’d changed anything—at least not &lt;em&gt;recently&lt;/em&gt;. Yes, we changed routers, but several weeks prior. Suddenly, and with no recourse to useful diagnostic messages, neither thermostat could get an IP address from the router’s DHCP service. I contacted Honeywell support and, as I expected, they didn’t tell me anything beyond what I’d already read in the user manual. Turn WiFi off, then on. Enter WiFi setup mode. Nothing helped.&lt;/p&gt;
&lt;p&gt;And then they started working again… for a few days. And then they stopped again. Oy. This illustrates exactly why we shouldn’t put everything on the network. This illustrates in particular why we should never put anything on the network that doesn’t also work offline!&lt;/p&gt;
&lt;p&gt;And then it hit me: if these devices can’t get IP address reliably, then let’s cut some steps out. Specifically, let’s just ask the router to give them the same IP address every time. Maybe that would help.&lt;/p&gt;
&lt;p&gt;I do not know enough about networks to call myself anything more than an &lt;a href=&quot;https://en.wikipedia.org/wiki/Dreyfus_model_of_skill_acquisition&quot;&gt;Advanced Beginner&lt;/a&gt;, so if you know more and can suggest something, then please &lt;a href=&quot;#contact&quot;&gt;contact me&lt;/a&gt; and tell me what I should have done. Thanks.&lt;/p&gt;
&lt;p&gt;Fortunately, the thermostats display their MAC addresses on a little sticker, so I logged on to the router and asked it to reserve fixed IP addresses for the two WiFi thermostats using their MAC addresses. I had to change the first three bytes of the MAC addresses to &lt;code&gt;02:0f:b5&lt;/code&gt;, because of &lt;em&gt;virtual MAC addresses&lt;/em&gt;, so I even learned something in the process. Something I didn’t care to learn, but that’s sometimes how it goes.&lt;/p&gt;
&lt;p&gt;Now—for the moment, at least—the thermostats have IP addresses and I feel happy about that. I hope it stays that way.&lt;/p&gt;
&lt;p&gt;If you have these thermostats, then I recommend that you consider configuring your router to reserve fixed IP addresses for them, instead of negotiating new ones every time. This might save you some headache, especially in the winter, when you actually need these things to work.&lt;/p&gt;
</description>
        <pubDate>Thu, 17 May 2018 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/honeywell-wifi-thermostats-not-connecting-to-wifi-network</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/honeywell-wifi-thermostats-not-connecting-to-wifi-network</guid>
        
        
        <category>The Internet of Shit</category>
        
      </item>
    
      <item>
        <title>How To Exit Full-Screen Mode from Screen Sharing on MacOS</title>
        <description>&lt;p&gt;I use Screen Sharing on MacOS to connect to my Mac Mini machines. I like to use full-screen mode. I usually prefer to use &lt;a href=&quot;https://www.jinx.de/JollysFastVNC.html&quot;&gt;Jollys Fast VNC&lt;/a&gt;, but I haven’t installed it yet on my newest Mac Mini, so I used the built-in Screen Sharing. Sadly, this decision led to learning something that one shouldn’t need to learn.&lt;/p&gt;
&lt;p&gt;How does one exit full-screen mode on MacOS’s built-in Screen Sharing when one uses a mouse instead of a trackpad, and therefore can’t swipe? I couldn’t do this with the keyboard shortcuts that I knew (&lt;code&gt;Esc&lt;/code&gt; or &lt;code&gt;Cmd+Ctrl+F&lt;/code&gt;). I had to search the web.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;For Screen Sharing, in particular&lt;/strong&gt;, to exit full-screen mode, move the cursor up to the top of the screen &lt;strong&gt;and then wait several seconds for the Screen Sharing menu to appear&lt;/strong&gt;. You could have given me ten years and it wouldn’t have occurred to me to try this; instead, I moved the cursor up to the top of the screen, I didn’t seen anything happen, and then I moved the cursor wildly around the screen. Now I know.&lt;/p&gt;
&lt;p&gt;And now you know. Enjoy.&lt;/p&gt;
&lt;h1 id=&quot;reference&quot;&gt;Reference&lt;/h1&gt;
&lt;p&gt;Apple Support, &lt;a href=&quot;https://discussions.apple.com/message/19900322#message19900322&quot;&gt;“How do I exit full screen mode in Screen Sharing?”&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Fri, 05 Jan 2018 15:58:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/how-to-exit-full-screen-mode-from-screen-sharing-on-macos</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/how-to-exit-full-screen-mode-from-screen-sharing-on-macos</guid>
        
        
      </item>
    
      <item>
        <title>Moving Screenflow Markers Without Disturbing Your Clips</title>
        <description>&lt;p&gt;I produced over 2 hours of video, complete with chapter markers to export into &lt;a href=&quot;https://subler.org&quot;&gt;Subler&lt;/a&gt; as an index of the key moments of the video. Just before I went to export the final version for upload, I realized that I’d forgot to add transitions between the various clips. Leaving it this way would have looked terrible, but dragging clips around to add transitions doesn’t drag the markers with them unless you create all the markers on the clips themselves. I didn’t, because if I did, then they wouldn’t show up as chapter markers for the index.&lt;/p&gt;
&lt;p&gt;Sigh.&lt;/p&gt;
&lt;p&gt;Am I &lt;em&gt;really&lt;/em&gt; going to have to move the clips, then remember to move &lt;em&gt;every single marker&lt;/em&gt; on its own?! 12 frames for each transition? Really?! There was no way I would get this right.&lt;/p&gt;
&lt;p&gt;Then it hit me.&lt;/p&gt;
&lt;h2 id=&quot;a-brilliant-workaround&quot;&gt;A Brilliant Workaround&lt;/h2&gt;
&lt;p&gt;I wondered what would happen if I locked all the clips, then used Ripple Delete on a section of the video between markers—would it move the markers without disturbing the clips?&lt;/p&gt;
&lt;p&gt;It did.&lt;/p&gt;
&lt;p&gt;This became the workflow:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Go to the first transition point, where two clips meet.&lt;/li&gt;
&lt;li&gt;Unlock all the clips, then drag &lt;em&gt;all&lt;/em&gt; the later clips (as a big group) over the earlier clip to create the transition. I usually drag it 12 frames and use the “Cross Dissolve” transition. (I choose &lt;em&gt;all&lt;/em&gt; the clips after the transition point to avoid creating a gap later in the timeline.)&lt;/li&gt;
&lt;li&gt;Lock all the clips.&lt;/li&gt;
&lt;li&gt;Create In and Out Points over the 12-frame transition.&lt;/li&gt;
&lt;li&gt;Ripple Delete. Watch that the markers move, but the clips remain untouched.&lt;/li&gt;
&lt;li&gt;Breathe.&lt;/li&gt;
&lt;li&gt;Repeat all this for the remaining transition points, slowly and surely.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;What could have become hours of painstaking work suddenly became much less stressful. Of course, for a 2-hour-long video, it still look a long time, but at least I knew what I was doing and felt confident about it.&lt;/p&gt;
&lt;p&gt;Yay!&lt;/p&gt;
</description>
        <pubDate>Wed, 12 Jul 2017 20:19:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/moving-screenflow-markers-without-disturbing-the-clips</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/moving-screenflow-markers-without-disturbing-the-clips</guid>
        
        
      </item>
    
      <item>
        <title>Extracting Chapter Markers Quickly from Screenflow</title>
        <description>&lt;p&gt;I use Screenflow 6 (as of this writing) to edit and produce videos. Some of those videos are quite long, and so I use the &lt;em&gt;markers&lt;/em&gt; feature of Screenflow in order to allow viewers to skip ahead to various important points in the video, known as &lt;em&gt;chapter markers&lt;/em&gt; or &lt;em&gt;chapters&lt;/em&gt;. I provide notes along side these long videos to help the viewer find relevant information inside them, and I like to include in those notes an index of the video, which I produce from the chapter markers using a tool for Mac OS called Subler. Sadly, in order to export the chapter markers from Screenflow, I have to do two things:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Export the video.&lt;/li&gt;
&lt;li&gt;Remember to check the damn checkbox for “include chapter markers”.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Exporting the video can take a long time. Recently, I waited about an hour to export a 2-hour-long video. I don’t object to how long it takes to export video, but I mind that I have to export the entire video in order to export the chapter markers. &lt;em&gt;There has to be a better way&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I found one. I export the video without the video.&lt;/p&gt;
&lt;p&gt;When I export the video from Screenflow, I export it in &lt;code&gt;.mp4&lt;/code&gt; format, but I exclude the video track from the video, exporting only the audio. I tried exporting nothing, but this seemed to cause Screenflow to do nothing and I needed to kill Screenflow and restart it. (I can hear the meeting now: “No-one’s ever going to have a legitimate reason to export a video with &lt;em&gt;neither&lt;/em&gt; the video track &lt;em&gt;nor&lt;/em&gt; the audio track!”) When I tried again, I exported in &lt;code&gt;.mp4&lt;/code&gt; format, and then pressed &lt;code&gt;Customize...&lt;/code&gt;, which allowed me to select only the audio track. This time, exporting the 2-hour-long video took only about 3 minutes. Much better.&lt;/p&gt;
&lt;p&gt;So this becomes my workflow:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Edit the video, setting chapter markers throughout.&lt;/li&gt;
&lt;li&gt;Group the entire video into a single, large Nested Clip.&lt;/li&gt;
&lt;li&gt;Add the intro and outro as Nested Clips, so that I have the marker times right.&lt;/li&gt;
&lt;li&gt;Add a marker for the first frame of the video, as suggested by &lt;a href=&quot;http://telestream.force.com/kb/articles/Knowledge_Article/Chapter-Markers&quot; class=&quot;uri&quot;&gt;http://telestream.force.com/kb/articles/Knowledge_Article/Chapter-Markers&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Export the video in &lt;code&gt;.mp4&lt;/code&gt; format, exporting only the audio track.&lt;/li&gt;
&lt;li&gt;Open the exported “video” in Subler.&lt;/li&gt;
&lt;li&gt;From Subler, export the chapter markers as a text file.&lt;/li&gt;
&lt;li&gt;Process the text file to turn the output format into something a human can read.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Enjoy.&lt;/p&gt;
&lt;p&gt;Of course, since there exists a workaround, Telestream will never implement the feature to export only the chapter markers from a video, even though it means that you will almost certainly waste some non-trivial amount of time before discovering this article and learning what to do. Shame.&lt;/p&gt;
</description>
        <pubDate>Sun, 09 Jul 2017 17:46:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/extracting-chapter-markers-quickly-from-screenflow</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/extracting-chapter-markers-quickly-from-screenflow</guid>
        
        
      </item>
    
      <item>
        <title>Rescuing PDF Clerk Pro Files Made Easy</title>
        <description>&lt;h1 id=&quot;the-short-version&quot;&gt;The Short Version&lt;/h1&gt;
&lt;p&gt;Your &lt;code&gt;.pdfp&lt;/code&gt; files are just bundles containing the contents as a single PDF file and some metadata, so it doesn’t matter that PDF Clerk Pro no longer runs on current versions of MacOS.&lt;/p&gt;
&lt;h1 id=&quot;the-details&quot;&gt;The Details&lt;/h1&gt;
&lt;p&gt;I depend on PDFs to run my business: expense receipts, sending proposals to clients, contracts, and so on. I rely on tools that slice and dice PDFs, perform OCR, make annotations easy… on MacOS I used to use PDFClerk — so much so that I bought the Pro version. I used it for years, especially to wrangle expense receipts into expense reports. Eventually, I discovered &lt;a href=&quot;https://smilesoftware.com/PDFpen&quot;&gt;PDFPen&lt;/a&gt;, which I now use every day, and which I love. (If you buy PDFPen, please tell them that I said “Hi!” It’s one of a handful of tools that I &lt;em&gt;happily&lt;/em&gt; upgrade.) I left PDFClerk behind (sorry!) and, while I wasn’t looking, PDFClerk faded into the background. I preferred PDFPen in part because it didn’t use a specialized file format for its contents, but rather operated directly on PDFs.&lt;/p&gt;
&lt;p&gt;Fast forward to today, when I rudely discovered that MacOS 10.12 (Sierra) can’t open PDFClerk Pro 3.12. If you haven’t opened PDFClerk in a while, then I suggest trying it now, especially if you’re still on an older version of MacOS 10. I had a moment of panic. What will I do?! Who has MacOS 10.6 lying around on an old backup drive or something?&lt;/p&gt;
&lt;p&gt;No worry. The &lt;code&gt;.pdfp&lt;/code&gt; file is just a package that wraps its contents as a single PDF file and adds a metadata file (&lt;code&gt;main.clerkdata&lt;/code&gt;) and a QuickLook file. In Finder, right-click the &lt;code&gt;.pdfp&lt;/code&gt; package, choose Show Package Contents, and you’ll find the &lt;code&gt;.pdf&lt;/code&gt; file, which you can rescue. You’ll lose the PDFClerk metadata, but I don’t even remember what was in there, so I don’t mind losing that metadata.&lt;/p&gt;
&lt;p&gt;So if you used PDFClerk, there’s no need to fear no longer being able to use it: rescue the PDFs inside your &lt;code&gt;.pdfp&lt;/code&gt; files, use PDFPen, and all is well again. Enjoy.&lt;/p&gt;
</description>
        <pubDate>Sat, 10 Jun 2017 13:50:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/rescuing-pdf-clerk-pro-files-made-easy</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/rescuing-pdf-clerk-pro-files-made-easy</guid>
        
        
      </item>
    
      <item>
        <title>unZettling, or How I Discovered That Credit Card Companies Turn Cash Advances Into Absurd Uncertainty</title>
        <description>&lt;p&gt;If you use an iZettle device to purchase something by credit card in Sweden, then &lt;em&gt;check your credit card statement immediately&lt;/em&gt;, because your credit card company might treat the purchase as a cash advance and additional fees and interest might apply.&lt;/p&gt;
&lt;p&gt;Sigh.&lt;/p&gt;
&lt;p&gt;I learned this the hard way traveling in Sweden recently. Fortunately, the customer service representative at my credit card company agreed to reverse the cash advance-related charges; however, this highlights &lt;em&gt;two&lt;/em&gt; problems: that iZettle might report a purchase as a cash advance and that once you withdraw cash on a credit card, you can’t reasonably know how much to pay in interest. In my case, the purchase was somehow treated as a Swish mobile payment, and I have no way to know how this happened: did the vendor configure something incorrectly, report a sale incorrectly, did some automated system record the payment method incorrectly? &lt;em&gt;I would expect that nobody will ever know how this happened.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-izettle-problem&quot;&gt;The iZettle Problem&lt;/h2&gt;
&lt;p&gt;I want to support iZettle. I love not having to use cash in foreign countries, where foreign bank machine withdrawals carry uncertain exchange rates and unpredictable withdrawal fees. I also love the typical benefits of using a credit card: payment grace period, automatically tracking transactions, even cash-bank rewards (in the case of this particular credit card). I do not, however, wish to pay the price of a cash advance on a credit card for these benefits.&lt;/p&gt;
&lt;p&gt;I have asked iZettle through their web contact form for information regarding this problem. I made at least a dozen purchases around Stockholm using iZettle devices and only one—at a Christmas market vendor for hot chocolate—was reported as a cash advance. All the other purchases were reported as purchases and handled as one would expect of a typical (North American) credit card account. As of this writing, I don’t know whether iZettle will have a useful answer for me. I intend to add details to this article as they find me.&lt;/p&gt;
&lt;p&gt;I have a Square reader and make regular purchases at vendors who use them. I have never seen those purchases treated as cash advances. Is it possible that customers of Square-wielding vendors have experienced this problem, too? I’d like to know.&lt;/p&gt;
&lt;h2 id=&quot;the-cash-advance-problem&quot;&gt;The Cash Advance Problem&lt;/h2&gt;
&lt;p&gt;I will now describe my experience with an MBNA Mastercard in Canada, although I imagine that others have had similar experiences, at least in North America.&lt;/p&gt;
&lt;p&gt;Once I withdrew cash from a bank machine on my credit card account, the bank began charging interest immediately. This differs from purchases. On purchases, the credit card company gives me approximately 21 days to pay for my purchases before charging interest on those purchases, known as the &lt;em&gt;grace period&lt;/em&gt;. Your credit card statement probably describes at least the highlights of your grace period. This makes it possible to review my purchases and resolve disputes &lt;em&gt;before needing to pay&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Since the grace period covers purchases but not cash advances, then during the grace period, &lt;em&gt;interest accumulates on the cash advance&lt;/em&gt;. When MBNA Mastercard publishes my statement and claims “You owe $2,750”, &lt;em&gt;this amount is wrong by the time I see the statement&lt;/em&gt;. This means that if I pay $2,750 on the due date &lt;em&gt;that they publish on the statement&lt;/em&gt;, then I am still charged an uncertain amount of interest &lt;em&gt;unless, by chance, I know exactly how they are calculating the interest, which formula they do not publish&lt;/em&gt;. Yes, there are standard formulas for compound interest, but the best I can do is &lt;em&gt;overpay the balance due and hope that I overpay by enough to cover the interest charges&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Worse: credit card companies apply payments to purchases first, and then to cash advances. This means that I can’t just pay off the cash advance first, then pay off the purchases after the grace period. This leaves me a Morton’s Fork:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Overpay the statement balance before the statement date (the “closing date”), in the hopes that I correctly predict which purchases will be posted to the account before the credit card company publishes the statement, &lt;strong&gt;or&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Wait until the statement is published, then overpay the statement balance as soon as possible—certainly before the due date—in the hopes that I correctly calculate the interest that has accumulated on the cash advance.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Either way, this creates cash flow pressure: I have to pay my entire credit card balance 2-3 weeks before the vast majority of that debt becomes due in order to avoid an unpredictable amount of interest.&lt;/p&gt;
&lt;h2 id=&quot;big-deal-it-depends.&quot;&gt;Big Deal? It Depends.&lt;/h2&gt;
&lt;p&gt;Right now I can treat this as a minor inconvenience. The interest charge is less than $1 per month and I have enough slack in my cash flow to pay the statement balance early if I wanted to avoid the interest charge. After about 2 months, the outstanding interest on the cash advance falls below $0.005 and rounds down to $0.00. This costs me more in effort and energy than in money: tracking the charges, understanding what happened, recording the details in order to keep track of my personal financial situation. It’s like when your accountant has to spend 15 minutes understanding why a transaction is $4 out of balance: a significant waste of energy.&lt;/p&gt;
&lt;p&gt;For someone with no slack in their cash flow who is forced by their circumstances to rely on cash advances from a credit card account, however, this could create an endless loop. They can’t overpay their balance due; they have to pay the posted minimum payment; however, &lt;em&gt;the posted minimum payment is wrong by the time the credit card statement arrives by postal mail or email&lt;/em&gt;. This creates significant risk (and problems) for some people. I feel very bad for them.&lt;/p&gt;
&lt;p&gt;How to defend oneself? One has to understand what’s happening so that one can decide how to handle it. I hope that this article helps at least one person improve their understanding of day-to-day, practice personal finances.&lt;/p&gt;
&lt;aside&gt;
&lt;p&gt;If you have take cash advances from a credit card account, then even if you think that you’re paying off the full balance on your account, you aren’t. Estimate the interest and overpay by double that amount, if you can. In the worst case, you’re prepaying for some (I hope) small amount of your purchases in the next billing cycle.&lt;/p&gt;
&lt;p&gt;Check your statement regularly for transactions that you believe are purchases, but that your credit card company reports as cash advances. Call your credit card company to dispute the cash advance if you know that it was a purchase. Feel free to explain and defend yourself several times before the customer service representative understands you.&lt;/p&gt;
&lt;/aside&gt;
</description>
        <pubDate>Tue, 14 Feb 2017 15:15:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/unzettling</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/unzettling</guid>
        
        
        <category>Personal Finance</category>
        
      </item>
    
      <item>
        <title>Back Up an SD Card from Android</title>
        <description>&lt;p&gt;I wanted to replace the 64 GB SD card in my Galaxy Note 4 with a 128 GB SD card. I assumed that I could simply take the smaller SD card out of my phone, connect it by USB (with a USB-based SD card reader) to my MacBook, copy the contents to the larger SD card, insert the larger SD card into my phone, and then go on my merry way.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Of course not&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;When I inserted the smaller SD card into my MacBook, it told me that it could not read the SD card. I assume it is a formatting issue, so I guessed that I needed to transfer files by USB from the phone. I connected the phone by USB and launched Android File Transfer, but sadly, Android File Transfer is terrible. When I tried to copy a large amount of data at once — a single folder tree with 15 GB of audio in it — Android File Transfer froze up. I couldn’t tell the difference between “slow” and “stuck”. It seemed to handle smaller batches of data just fine, but I &lt;em&gt;refuse&lt;/em&gt; to babysit these tools. The devices &lt;em&gt;work for me&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Searching the web, I found a suggestion to &lt;strong&gt;use FTP to send the files from the phone to my MacBook&lt;/strong&gt;. This meant installing AndFTP on the phone and launching &lt;code&gt;ftpd&lt;/code&gt; on the MacBook. I tried that. Sadly, FTP is not a great protocol for “make these folders the same”. At best, it can “overwrite/resume”. When my phone didn’t copy all 58 GB of data in one session, I couldn’t tell how much it had copied and which files I needed to recopy. Moreover, it sent files at approximately 4 MB/s, which means that it takes about 4-5 hours to try to copy everything. This appears to be just long enough for copying to fail.&lt;/p&gt;
&lt;p&gt;Srsly.&lt;/p&gt;
&lt;p&gt;As a last-ditch effort, I tried installing &lt;code&gt;adb&lt;/code&gt; &lt;strong&gt;so that I could copy files with a command-line tool&lt;/strong&gt;, which is more likely to work and, more importantly, easier to script if I need to copy files in batches. Naturally, the Android world has decided to “make things easier” by repackaging the Android development tools inside Android Studio, thereby making it harder to learn how to use them as simple command-line tools.&lt;/p&gt;
&lt;aside&gt;
&lt;p&gt;After I posted this article, &lt;a href=&quot;https://twitter.com/sourcerebels/status/788734285096386560&quot;&gt;Edu Rodríguez showed me where to find the Android command-line tools&lt;/a&gt;. This led me to discover that I had a &lt;em&gt;very old&lt;/em&gt; version of the Android command-line tools installed at &lt;code&gt;/opt&lt;/code&gt;, which I suppose I installed some time in 2013. You might have the same thing! I had to remove files from &lt;code&gt;/opt/android-sdk-macosx&lt;/code&gt; and patch my &lt;code&gt;.zshrc&lt;/code&gt; to remove a &lt;code&gt;PATH&lt;/code&gt; reference to this old Android SDK. After I did all this, I realized “Homebrew &lt;em&gt;must&lt;/em&gt; package this somewhere…” and sure enough:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; brew install android-sdk&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; mvim ~/.zshrc&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;#cb1-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;set &lt;span class=&quot;ex&quot;&gt;ANDROID_HOME&lt;/span&gt; environment variable, per Homebrew&lt;span class=&quot;st&quot;&gt;&amp;#39;s post-installation instructions&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Gracias, Edu!&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;It turns out that, at the time, I ignorantly went “the long way”, so I ended up doing all this:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Launch Android Studio, since I had installed it previously in a desperate attempt to hack on some Android project about a year ago. (How do you &lt;em&gt;think&lt;/em&gt; it went?)&lt;/li&gt;
&lt;li&gt;Notice that Android Studio is out of date, so update it, then restart it.&lt;/li&gt;
&lt;li&gt;Notice that Android Development tools are out of date, so update them, then restart Android Studio.&lt;/li&gt;
&lt;li&gt;Try to launch &lt;code&gt;adb&lt;/code&gt; from a command line, and notice that the Android Development tools are not on the system path.&lt;/li&gt;
&lt;li&gt;Figure out where Android Studio installed the development tools, so that I can try putting that directory on the system path.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Finally, this seemed to help. I could launch &lt;code&gt;adb&lt;/code&gt; from the command line.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; export PATH=&lt;span class=&quot;va&quot;&gt;$HOME&lt;/span&gt;/Library/Android/sdk/platform-tools:&lt;span class=&quot;va&quot;&gt;$PATH&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; which adb&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a href=&quot;#cb2-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;/Users/jbrains/Library/Android/sdk/platform-tools/adb&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-4&quot;&gt;&lt;a href=&quot;#cb2-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; adb&lt;/span&gt;
&lt;span id=&quot;cb2-5&quot;&gt;&lt;a href=&quot;#cb2-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;adb &lt;span class=&quot;ex&quot;&gt;usage&lt;/span&gt; guide&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Yay! Now… how do I actually copy stuff?!&lt;/p&gt;
&lt;aside&gt;
&lt;p&gt;I assume adding &lt;code&gt;$HOME/Library/Android/sdk/platform-tools&lt;/code&gt; to my system path now conflicts with installing the Android SDK with Homebrew. Fortunately, &lt;em&gt;I never changed my system PATH, because I wasn’t sure whether this environment was stable&lt;/em&gt; — I only knew that “it works for now”, so I only changed it in my current &lt;code&gt;bash&lt;/code&gt; session.&lt;/p&gt;
&lt;p&gt;Even so, just to be sure, I launched &lt;code&gt;android sdk&lt;/code&gt; and &lt;em&gt;uninstalled&lt;/em&gt; the Platform Tools to make sure that I didn’t have an old, incompatible, partially-installed version lying around my file system somewhere. If I did, then I’d like to discover that now… and fortunately, I didn’t!&lt;/p&gt;
&lt;p&gt;This does mean, however, that as of 2016-10-22, when I write these words, you should probably use Homebrew to install &lt;code&gt;android-sdk&lt;/code&gt;, and then launch &lt;code&gt;android sdk&lt;/code&gt; to install the Platform Tools. As Homebrew warns, the formulae for &lt;code&gt;android-sdk&lt;/code&gt; and &lt;code&gt;android-platform-tools&lt;/code&gt; conflict, so &lt;em&gt;don’t try to install both together&lt;/em&gt;.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; brew uninstall android-platform-tools&lt;/span&gt;
&lt;span id=&quot;cb3-2&quot;&gt;&lt;a href=&quot;#cb3-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;maybe &lt;span class=&quot;ex&quot;&gt;Homebrew&lt;/span&gt; says, &lt;span class=&quot;st&quot;&gt;&amp;quot;No such keg&amp;quot;&lt;/span&gt;, which is fine&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-3&quot;&gt;&lt;a href=&quot;#cb3-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; brew uninstall android-sdk&lt;/span&gt;
&lt;span id=&quot;cb3-4&quot;&gt;&lt;a href=&quot;#cb3-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;maybe &lt;span class=&quot;ex&quot;&gt;Homebrew&lt;/span&gt; says, &lt;span class=&quot;st&quot;&gt;&amp;quot;No such keg&amp;quot;&lt;/span&gt;, which is fine&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-5&quot;&gt;&lt;a href=&quot;#cb3-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; ls &lt;span class=&quot;at&quot;&gt;-l&lt;/span&gt; /usr/local/bin &lt;span class=&quot;kw&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;grep&lt;/span&gt; android&lt;/span&gt;
&lt;span id=&quot;cb3-6&quot;&gt;&lt;a href=&quot;#cb3-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;if &lt;span class=&quot;ex&quot;&gt;there&lt;/span&gt; are symlinks to an android-related Homebrew keg, then remove them&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-7&quot;&gt;&lt;a href=&quot;#cb3-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; brew install android-sdk&lt;/span&gt;
&lt;span id=&quot;cb3-8&quot;&gt;&lt;a href=&quot;#cb3-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;maybe &lt;span class=&quot;ex&quot;&gt;Homebrew&lt;/span&gt; suggests setting ANDROID_HOME, in which case, do it&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-9&quot;&gt;&lt;a href=&quot;#cb3-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; android sdk&lt;/span&gt;
&lt;span id=&quot;cb3-10&quot;&gt;&lt;a href=&quot;#cb3-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;Use &lt;span class=&quot;ex&quot;&gt;the&lt;/span&gt; Android SDK UI to install the platform tools&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-11&quot;&gt;&lt;a href=&quot;#cb3-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; which adb&lt;/span&gt;
&lt;span id=&quot;cb3-12&quot;&gt;&lt;a href=&quot;#cb3-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;/usr/local/bin/adb&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Muuuuuuuch better.&lt;/p&gt;
&lt;p&gt;Wait.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb4&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb4-1&quot;&gt;&lt;a href=&quot;#cb4-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; ls &lt;span class=&quot;at&quot;&gt;-l&lt;/span&gt; /usr/local/bin/adb&lt;/span&gt;
&lt;span id=&quot;cb4-2&quot;&gt;&lt;a href=&quot;#cb4-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;[...]&lt;/span&gt; /usr/local/bin/adb &lt;span class=&quot;at&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt; ../Cellar/android-sdk/24.4.1_1/bin/adb&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So… which version of &lt;code&gt;adb&lt;/code&gt; do I have again? I thought I used the Android SDK Manager to install Platform Tools version 25! By coincidence, Platform Tools 24.4.1_1 and Platform Tools 25 have the same version of &lt;code&gt;adb&lt;/code&gt;, but now I’m back to not knowing what is installed on my machine.&lt;/p&gt;
&lt;p&gt;What am I missing? When I use Android SDK Manager to install Platform Tools, then I expect it to make &lt;em&gt;those&lt;/em&gt; Platform Tools the default choice for my environment. Am I wrong? Should I have to add &lt;code&gt;/usr/local/opt/android-sdk/platform-tools&lt;/code&gt; to my system path as a separate step? &lt;a href=&quot;http://tell.jbrains.ca&quot;&gt;Please tell me what I should expect&lt;/a&gt;.&lt;/p&gt;
&lt;/aside&gt;
&lt;h2 id=&quot;copying-files-from-android-phone-with-adb&quot;&gt;Copying Files from Android Phone With &lt;code&gt;adb&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;I assume that I need to “start a debugging session” with &lt;code&gt;adb&lt;/code&gt; by “mounting” my phone as a device, then I can use &lt;a href=&quot;http://www.droidviews.com/push-pull-files-android-using-adb-commands/&quot;&gt;&lt;code&gt;adb pull&lt;/code&gt;&lt;/a&gt; to pull the relevant files from my phone.&lt;/p&gt;
&lt;p&gt;First, however, I need to enabling USB debugging mode on my phone. Fortunately, I have done this before. Doing this seems to depend on the device and Android version, so I recommend that you search the web to learn how to enable USB debugging mode on your device. For example, I searched for &lt;code&gt;enable usb debugging mode samsung &quot;galaxy note 4&quot;&lt;/code&gt; and found &lt;a href=&quot;http://www.solvemix.com/index.php/android-smartphones/315-samsung-galaxy-note-4-how-to-activate-usb-debugging-solved&quot; class=&quot;uri&quot;&gt;http://www.solvemix.com/index.php/android-smartphones/315-samsung-galaxy-note-4-how-to-activate-usb-debugging-solved&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So far, so good. To recap:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Enable USB debugging mode on the phone.&lt;/li&gt;
&lt;li&gt;Unlock the phone.&lt;/li&gt;
&lt;li&gt;Connect the phone by USB.&lt;/li&gt;
&lt;li&gt;On the MacBook, dismiss and close Android File Transfer, because it is useless.&lt;/li&gt;
&lt;li&gt;On the phone, allow the MTP connection.&lt;/li&gt;
&lt;li&gt;On the MacBook, dismiss and close Android File Transfer &lt;em&gt;again&lt;/em&gt;, because it can’t take a hint.&lt;/li&gt;
&lt;li&gt;Check that &lt;code&gt;adb&lt;/code&gt; can find the phone.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb5&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb5-1&quot;&gt;&lt;a href=&quot;#cb5-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; adb devices&lt;/span&gt;
&lt;span id=&quot;cb5-2&quot;&gt;&lt;a href=&quot;#cb5-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;List&lt;/span&gt; of devices attached&lt;/span&gt;
&lt;span id=&quot;cb5-3&quot;&gt;&lt;a href=&quot;#cb5-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;meaningless &lt;span class=&quot;ex&quot;&gt;hex&lt;/span&gt; number&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt;    device&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I assume that &lt;code&gt;device&lt;/code&gt; is my phone, because what else could it be?&lt;/p&gt;
&lt;p&gt;Now, can I &lt;code&gt;pull&lt;/code&gt; a single file? First, let me poke around the phone.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb6&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb6-1&quot;&gt;&lt;a href=&quot;#cb6-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; adb shell&lt;/span&gt;
&lt;span id=&quot;cb6-2&quot;&gt;&lt;a href=&quot;#cb6-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;shell@trlecan:/&lt;/span&gt; $ cd sdcard&lt;/span&gt;
&lt;span id=&quot;cb6-3&quot;&gt;&lt;a href=&quot;#cb6-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;shell@trltecan:/sdcard&lt;/span&gt; $ ls&lt;/span&gt;
&lt;span id=&quot;cb6-4&quot;&gt;&lt;a href=&quot;#cb6-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;a &lt;span class=&quot;ex&quot;&gt;listing&lt;/span&gt; of the files on my SD card&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Yay! I want to &lt;code&gt;pull&lt;/code&gt; the directory tree &lt;code&gt;/sdcard&lt;/code&gt; from my phone to my MacBook. May I?!&lt;/p&gt;
&lt;p&gt;First, let me &lt;code&gt;pull&lt;/code&gt; a single file.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb7&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb7-1&quot;&gt;&lt;a href=&quot;#cb7-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; adb pull /sdcard/temporary_contacts.txt ~/Desktop&lt;/span&gt;
&lt;span id=&quot;cb7-2&quot;&gt;&lt;a href=&quot;#cb7-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;[100%]&lt;/span&gt; /sdcard/temporary_contacts.txt&lt;/span&gt;
&lt;span id=&quot;cb7-3&quot;&gt;&lt;a href=&quot;#cb7-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; ls ~/Desktop &lt;span class=&quot;kw&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;grep&lt;/span&gt; con&lt;/span&gt;
&lt;span id=&quot;cb7-4&quot;&gt;&lt;a href=&quot;#cb7-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;temporary_contacts.txt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Success! Now, clean up before moving on, then &lt;code&gt;pull&lt;/code&gt; a directory of reasonable size.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb8&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb8-1&quot;&gt;&lt;a href=&quot;#cb8-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; rm ~/Desktop/temporary_contacts.txt&lt;/span&gt;
&lt;span id=&quot;cb8-2&quot;&gt;&lt;a href=&quot;#cb8-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; ls ~/Desktop &lt;span class=&quot;kw&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;grep&lt;/span&gt; con&lt;/span&gt;
&lt;span id=&quot;cb8-3&quot;&gt;&lt;a href=&quot;#cb8-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;nothing&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb8-4&quot;&gt;&lt;a href=&quot;#cb8-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; mkdir &lt;span class=&quot;at&quot;&gt;-p&lt;/span&gt; ~/Desktop/pull-directory &lt;span class=&quot;kw&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;ex&quot;&gt;adb&lt;/span&gt; pull /sdcard/scanner ~/Desktop/pull-directory&lt;/span&gt;
&lt;span id=&quot;cb8-5&quot;&gt;&lt;a href=&quot;#cb8-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;an &lt;span class=&quot;ex&quot;&gt;actually&lt;/span&gt; useful progress report showing something that suggests that the computer is copying files to my Desktop!&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I stopped this job after it was 20% finished, because I felt convinced &lt;code&gt;adb pull&lt;/code&gt; would do what I want it to do. It copied about 170 MB in what seemed like less than 1 minute. At 170 MB/minute, a full copy of 58 GB would take about 6 hours. I hope it’s faster than that.&lt;/p&gt;
&lt;p&gt;Since I don’t know how long it will take to pull the entire 58 GB on the card, I start with a big-but-not-huge directory and time the &lt;code&gt;pull&lt;/code&gt; operation, so that I know how long to expect the whole backup to take.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb9&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb9-1&quot;&gt;&lt;a href=&quot;#cb9-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;# Clean up before moving on&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb9-2&quot;&gt;&lt;a href=&quot;#cb9-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; rm &lt;span class=&quot;at&quot;&gt;-fr&lt;/span&gt; ~/Desktop/pull-directory&lt;/span&gt;
&lt;span id=&quot;cb9-3&quot;&gt;&lt;a href=&quot;#cb9-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; mkdir &lt;span class=&quot;at&quot;&gt;-p&lt;/span&gt; ~/Desktop/pull-directory &lt;span class=&quot;kw&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;time&lt;/span&gt; adb pull /sdcard/scanner ~/Desktop/pull-directory&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Even though I’m using the &lt;code&gt;time&lt;/code&gt; tool, I start a stopwatch on the side, just in case &lt;code&gt;time&lt;/code&gt; somehow fails. Now I wait.&lt;/p&gt;
&lt;p&gt;Woohoo! &lt;code&gt;time&lt;/code&gt; worked and alleges that copying that directory took 4 minutes, 35 seconds, copying 1018 MB of data. My arithmetic says 3.70 MB/s, so 58 GB would take 16052 seconds or 4.45 hours to copy. I can live with it, as long as it actually works.&lt;/p&gt;
&lt;p&gt;And… &lt;em&gt;of course&lt;/em&gt;, the directory called &lt;code&gt;/sdcard&lt;/code&gt; on my phone &lt;em&gt;is in fact not&lt;/em&gt; the root of the SD card storage on my phone, &lt;em&gt;because that would make sense and be helpful and the universe is not that merciful&lt;/em&gt;. How did I discover this? I tried to check the size of &lt;code&gt;/sdcard&lt;/code&gt; and it reported something entirely unexpected.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb10&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb10-1&quot;&gt;&lt;a href=&quot;#cb10-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; adb shell&lt;/span&gt;
&lt;span id=&quot;cb10-2&quot;&gt;&lt;a href=&quot;#cb10-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;shell@trltecan:/data&lt;/span&gt; $ du &lt;span class=&quot;at&quot;&gt;-h&lt;/span&gt; /sdcard/ &lt;span class=&quot;kw&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;tail&lt;/span&gt; &lt;span class=&quot;at&quot;&gt;-n&lt;/span&gt; 1&lt;/span&gt;
&lt;span id=&quot;cb10-3&quot;&gt;&lt;a href=&quot;#cb10-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;4.9G&lt;/span&gt;    /sdcard/&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Uh… what?! I expect something closer to 58 GB, so why is there only 4.9 GB of stuff here?! &lt;em&gt;Sigh.&lt;/em&gt; What is this directory and why is it on my phone? Is it an alias? (Later I found out that it is indeed an alias. Fine.)&lt;/p&gt;
&lt;p&gt;Fine. Where is the SD card on my phone, O great Android?!&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb11&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb11-1&quot;&gt;&lt;a href=&quot;#cb11-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;shell@trltecan:/data&lt;/span&gt; $ df&lt;/span&gt;
&lt;span id=&quot;cb11-2&quot;&gt;&lt;a href=&quot;#cb11-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;a &lt;span class=&quot;ex&quot;&gt;bunch&lt;/span&gt; of Permission denied messages&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-3&quot;&gt;&lt;a href=&quot;#cb11-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;Filesystem&lt;/span&gt;                       Size     Used     Free   Blksize&lt;/span&gt;
&lt;span id=&quot;cb11-4&quot;&gt;&lt;a href=&quot;#cb11-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;a &lt;span class=&quot;ex&quot;&gt;bunch&lt;/span&gt; of irrelevant file systems&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-5&quot;&gt;&lt;a href=&quot;#cb11-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;/storage/7C2F-B7C8&lt;/span&gt;              59.7G    52.3G     7.5G    128.0K&lt;/span&gt;
&lt;span id=&quot;cb11-6&quot;&gt;&lt;a href=&quot;#cb11-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;a &lt;span class=&quot;ex&quot;&gt;bunch&lt;/span&gt; of irrelevant file systems&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Aha! 52.3 GB used out of 59.7 GB. That must be it. I’m &lt;em&gt;so glad&lt;/em&gt; that I wasted 5 minutes copying files from the wrong place onto my phone! At least now I can test again, in case my measurement of 3.70 MB/s changes due to copying from the SD card instead of my phone’s built-in storage. Let’s try that again.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb12&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb12-1&quot;&gt;&lt;a href=&quot;#cb12-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;# Clean up before moving on&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb12-2&quot;&gt;&lt;a href=&quot;#cb12-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; rm &lt;span class=&quot;at&quot;&gt;-fr&lt;/span&gt; ~/Desktop/pull-directory&lt;/span&gt;
&lt;span id=&quot;cb12-3&quot;&gt;&lt;a href=&quot;#cb12-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; mkdir &lt;span class=&quot;at&quot;&gt;-p&lt;/span&gt; ~/Desktop/pull-directory &lt;span class=&quot;kw&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;time&lt;/span&gt; adb pull /storage/7C2F-B7C8/scanner ~/Desktop/pull-directory&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The directory &lt;code&gt;/storage/7C2F-B7C8/scanner&lt;/code&gt; has 840 MB of data, which required 3 minutes, 25 seconds, for an average of 4.10 MB/s. Encouraging! At that rate, 52.3 GB would require about 13062 seconds or approximately 3.5-4 hours to copy. That would be nice!&lt;/p&gt;
&lt;p&gt;Finally, I think, I can just do it.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb13&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb13-1&quot;&gt;&lt;a href=&quot;#cb13-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;# Clean up before moving on&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb13-2&quot;&gt;&lt;a href=&quot;#cb13-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; rm &lt;span class=&quot;at&quot;&gt;-fr&lt;/span&gt; ~/Desktop/pull-directory ~/Desktop/BARNEY-SD&lt;/span&gt;
&lt;span id=&quot;cb13-3&quot;&gt;&lt;a href=&quot;#cb13-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; mkdir &lt;span class=&quot;at&quot;&gt;-p&lt;/span&gt; ~/Desktop/BARNEY-SD &lt;span class=&quot;kw&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;time&lt;/span&gt; adb pull /storage/7C2F-B7C8/ ~/Desktop/BARNEY-SD&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now, we wait…&lt;/p&gt;
&lt;h2 id=&quot;after-we-wait&quot;&gt;After We Wait…&lt;/h2&gt;
&lt;p&gt;It took 3 hours, 47 minutes and it seemed to work! The transfer ran at only about 4 MB/s, but at least I could more easily see progress and there’s no GUI to get in the way. Now I need to wait an hour or so to copy these files to my larger SD card so that I can install it in the phone. Now that I know how all this works, I can do this more easily next time.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;
&lt;p&gt;Use &lt;code&gt;adb&lt;/code&gt; to pull files from the SD card onto a new storage device, which could be the new SD card mounted on the computer.&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Enable USB debugging mode on the Android device.&lt;/li&gt;
&lt;li&gt;Install the Android Development tools, and specifically &lt;code&gt;adb&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Find the mount path on the device for the SD card using &lt;code&gt;df&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;adb pull &amp;lt;mount path on Android SD card&amp;gt; &amp;lt;destination drive&amp;gt;&lt;/code&gt;, then wait several hours.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It sounds so simple, once you’ve actually learned how to do it.&lt;/p&gt;
&lt;h2 id=&quot;but-wait-theres-more&quot;&gt;But Wait! There’s More!&lt;/h2&gt;
&lt;p&gt;There’s no globbing in &lt;code&gt;adb pull&lt;/code&gt;! If you want to copy a subset of the files in a directory, then you need to resort to lower-level trickery.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb14&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb14-1&quot;&gt;&lt;a href=&quot;#cb14-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; adb shell ls &lt;span class=&quot;va&quot;&gt;$1&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;tr&lt;/span&gt; &lt;span class=&quot;at&quot;&gt;-s&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;\r\n&amp;quot;&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;\0&amp;quot;&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;xargs&lt;/span&gt; &lt;span class=&quot;at&quot;&gt;-0&lt;/span&gt; &lt;span class=&quot;at&quot;&gt;-n1&lt;/span&gt; adb pull&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here, &lt;code&gt;$1&lt;/code&gt; is your pattern for matching files, such as &lt;code&gt;/storage/emulated/0/DCIM/Camera/20161207*&lt;/code&gt; to match all photos taken with your camera on December 7, 2016.&lt;/p&gt;
&lt;p&gt;Thanks to &lt;a href=&quot;http://stackoverflow.com/questions/11074671/adb-pull-multiple-files#11250068&quot; class=&quot;uri&quot;&gt;http://stackoverflow.com/questions/11074671/adb-pull-multiple-files#11250068&lt;/a&gt; and &lt;a href=&quot;https://github.com/sschuberth/dev-scripts/blob/master/android/pull_all.sh&quot; class=&quot;uri&quot;&gt;https://github.com/sschuberth/dev-scripts/blob/master/android/pull_all.sh&lt;/a&gt; for their help!&lt;/p&gt;
</description>
        <pubDate>Wed, 19 Oct 2016 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/back-up-an-sd-card-from-android</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/back-up-an-sd-card-from-android</guid>
        
        
      </item>
    
      <item>
        <title>A Little Tip for Using Typora with Pandoc</title>
        <description>&lt;p&gt;I have only been using &lt;a href=&quot;http://www.typora.io&quot;&gt;Typora&lt;/a&gt; for about a day, but I already love it. If you do any serious editing with &lt;a href=&quot;http://daringfireball.net/projects/markdown/syntax.php&quot;&gt;Markdown&lt;/a&gt;, then I strongly recommend that you try it. I especially recommend that you try it &lt;em&gt;now&lt;/em&gt;, while it remains free, and that you subsequently give the Typora production team money when they ask you for it. I recommend giving them at least 50% more than they ask for; I like it that much.&lt;/p&gt;
&lt;p&gt;(No, I have no affiliation with the production team, but if they launch an affiliate program, then I will join it.)&lt;/p&gt;
&lt;p&gt;Typora offers a hybrid WYSIWYG approach to editing: as you type Markdown syntax, you see Markdown syntax; and then as you type past it, it becomes rendered as HTML. I love it. You just have to try it. I’ve never used any Markdown editor that so wonderfully combines the experience of real-time preview with the transparency of a “source mode”, for when you absolutely need to tweak the Markdown source to get it just right. I love it.&lt;/p&gt;
&lt;p&gt;Of course, the only thing better than a perfect tool is a tool that is perfect except for one small flaw that we can pick at all night. I have only found one in Typora, so far, and it has to do with nested lists and the Markdown specification.&lt;/p&gt;
&lt;h2 id=&quot;after-installing-typora-do-this&quot;&gt;After Installing Typora, Do This!&lt;/h2&gt;
&lt;p&gt;Once you &lt;a href=&quot;http://www.typora.io&quot;&gt;download Typora&lt;/a&gt; and install it, open the Preferences, and then look for the option “Indent Size on Saving”. If the default is not 4 spaces, then change it to 4 spaces. If you don’t, then your nested lists will not always look right, depending on how you process your Markdown. I ran into this problem when I published an article on one of my other blogs. I had composed it in Typora, then processed it with &lt;code&gt;pandoc&lt;/code&gt; in order to publish it. When I published it, my nested lists were not so nested. I managed to track the problem down to this: the Markdown specification requires 4 spaces to nest lists within lists, and although many processors treat this with leniency (that worked &lt;em&gt;so&lt;/em&gt; well for browsers and HTML, so why not?!), they ought not to do that. In particular, &lt;code&gt;pandoc&lt;/code&gt; does not like you using only 2 spaces to nest lists. Don’t do it.&lt;/p&gt;
&lt;p&gt;Since I changed the default setting in my Typora installation, I can nest lists with total confidence that the lists will look right even when I process the final Markdown with &lt;code&gt;pandoc&lt;/code&gt; for publication. Yay!&lt;/p&gt;
&lt;h1 id=&quot;references&quot;&gt;References&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/jgm/pandoc/issues/137&quot; class=&quot;uri&quot;&gt;https://github.com/jgm/pandoc/issues/137&lt;/a&gt; The Github issue for &lt;code&gt;pandoc&lt;/code&gt; that discusses this very point, and the reason I assume that Typora, not &lt;code&gt;pandoc&lt;/code&gt; needs to change.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://twitter.com/jbrains/status/785144020683067392&quot; class=&quot;uri&quot;&gt;https://twitter.com/jbrains/status/785144020683067392&lt;/a&gt; Me asking the very nice Typora people to consider changing the default setting since, after all, they are currently not respecting the Markdown specification.&lt;/p&gt;
</description>
        <pubDate>Sun, 09 Oct 2016 15:50:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/using-typora-with-pandoc</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/using-typora-with-pandoc</guid>
        
        
        <category>Wrangling Technology</category>
        
      </item>
    
      <item>
        <title>LibreOffice Calc Won&apos;t Print This Sheet!</title>
        <description>&lt;p&gt;I love LibreOffice and OpenOffice both for helping me escape from the clutches of Microsoft Office. I have donated to LibreOffice as a measure of gratitude for helping me run my business and indeed my life. Sadly, no technology product seems impervious to silly problems, and I encountered one today with LibreOffice that made me scream in frustration.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2 id=&quot;the-symptom&quot;&gt;The Symptom&lt;/h2&gt;
&lt;p&gt;I have a workbook with 7 worksheets. I wanted to print only the 6th worksheet. I did this:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Deselect all the worksheets.&lt;/li&gt;
&lt;li&gt;Select only the 6th worksheet.&lt;/li&gt;
&lt;li&gt;Press Cmd+P for “Print…”.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The miniature print preview dialog did not show me the sheet that I want to print, but instead, the last sheet, quite arbitrarily. I tried selecting all the available options for choosing which parts of the workbook to print (“Select all sheets”, “Print only current selection”…), but I could only print the last sheet. I felt like this print dialog was mocking me.&lt;/p&gt;
&lt;h2 id=&quot;the-fix&quot;&gt;The Fix&lt;/h2&gt;
&lt;p&gt;Clear all the print ranges, because some arbitrary sequence of commands from the past that you didn’t notice managed to set the print range on some of your sheets to “none” or “empty”. Obviously.&lt;/p&gt;
&lt;h2 id=&quot;some-details&quot;&gt;Some Details&lt;/h2&gt;
&lt;p&gt;I have no idea why any print range was set on any sheet in this workbook at any point. Sadly, none of that matters; it suffices to know that the print range for a given worksheet filters what you can choose to print from the print dialog, so if you can’t print what you want to print, then you should check the print ranges.&lt;/p&gt;
&lt;p&gt;I did this:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Select all the sheets.&lt;/li&gt;
&lt;li&gt;Choose Format &amp;gt; Print Ranges &amp;gt; Clear. (If “Clear” is not available to select, then you have a different problem, and I don’t know what that is.)&lt;/li&gt;
&lt;li&gt;Deselect all the sheets.&lt;/li&gt;
&lt;li&gt;Try printing again.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Success!&lt;/p&gt;
&lt;h2 id=&quot;reference&quot;&gt;Reference&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://en.libreofficeforum.org/node/8024&quot;&gt;“Calc Will Not Print All Sheets in spreadsheet”&lt;/a&gt;. A forum discussion that gave me the idea to check for unexpectedly-set print ranges. Thank you, William Whalley, for noticing the cause of the unexpected behavior.&lt;/p&gt;
</description>
        <pubDate>Wed, 08 Jun 2016 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/libreoffice-calc-wont-print-this-sheet</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/libreoffice-calc-wont-print-this-sheet</guid>
        
        
        <category>Wrangling Technology</category>
        
      </item>
    
      <item>
        <title>I Can&apos;t Boot From My External USB Drive!</title>
        <description>&lt;p&gt;I take backups pretty seriously. It’s the primary reason I switched to Mac: once I learned that I could boot from an external backup drive I wanted that security. Today, when my shiny new external USB 3.0 drives arrived in the mail, I immediately started a backup, but was shocked when I couldn’t boot from the backup! Well… somewhat. I eventually got there, and it wasn’t obvious to me, so I wanted to make sure that you knew what to do.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2 id=&quot;the-symptom&quot;&gt;The Symptom&lt;/h2&gt;
&lt;p&gt;I did this:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Power down my MacBook Air.&lt;/li&gt;
&lt;li&gt;Connect the external drive to the MacBook Air by USB.&lt;/li&gt;
&lt;li&gt;Hold down the Alt/Option key while pressing the Power button to turn the computer on.&lt;/li&gt;
&lt;li&gt;Wait for the boot menu to appear and list both my internal storage and the external drive as bootable disks.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I waited and waited and waited, but the external drive never appeared in the boot menu, so I couldn’t boot from it.&lt;/p&gt;
&lt;h2 id=&quot;the-fix&quot;&gt;The Fix&lt;/h2&gt;
&lt;p&gt;While in the boot menu, disconnect the drive from the MacBook Air, wait a few seconds, then reconnect it. The drive should start to spin and after a few seconds, it should appear in the boot menu. Now you can boot.&lt;/p&gt;
&lt;h2 id=&quot;some-details&quot;&gt;Some Details&lt;/h2&gt;
&lt;p&gt;I booted successfully from the external drive using the Startup Disk section of System Preferences, so I guessed that SuperDuper! had correctly made the backup bootable.&lt;/p&gt;
&lt;p&gt;Of course, if I have to first boot from my internal storage in order to subsequently boot from the external drive, then that defeats the purpose of a bootable backup. I need to boot from the external drive precisely when my internal storage fails. (I did this once with my trusty Powerbook G4, whose internal hard disk died. I plugged in my external drive, rebooted, and kept working. Sure, the machine was slow, but it worked for the few days I needed before I could get to a repair shop. Can Windows do this yet?)&lt;/p&gt;
&lt;p&gt;I noticed that, at the boot menu, the computer was clearly sending enough power to the external drive, but that the activity light was not flashing with disk activity. With nothing left to lose, my wife disconnected the drive and reconnected it. Suddenly the disk activity light started flashing and, within a few second, the drive appeared in the boot menu. Success!&lt;/p&gt;
&lt;p&gt;Just another little stupid trick one needs to have up one’s sleeve to deal with modern technology.&lt;/p&gt;
</description>
        <pubDate>Fri, 06 May 2016 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/i-cant-boot-from-my-external-usb-drive</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/i-cant-boot-from-my-external-usb-drive</guid>
        
        
        <category>Wrangling Technology</category>
        
      </item>
    
      <item>
        <title>I Can&apos;t Find Stuff In My Markdown Files!</title>
        <description>&lt;p&gt;As I wrote previously in &lt;a href=&quot;/permalink/writing-with-pleasure-using-markdown-and-pandoc&quot;&gt;“Writing With Pleasure Using Markdown and Pandoc”&lt;/a&gt;, I use Markdown &lt;em&gt;a lot&lt;/em&gt; for writing. I don’t use it just for writing articles, but also for writing outlines and making notes. If I draft it using plain text, then I usually use Markdown as the format.&lt;/p&gt;
&lt;p&gt;Imagine my surprise this morning when I tried to search for an outline I’d drafted of a conference talk and couldn’t find it. I couldn’t even find it by file name. Panic! &lt;!-- more --&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-symptoms&quot;&gt;The Symptoms&lt;/h2&gt;
&lt;p&gt;Today, I was flipping through some paper notes, trying to clean them up by digitizing what I needed to save, adding tasks for things I needed to do with them, then shredding them for recycling. I came across handwritten notes for a conference talk I plan to record soon. I felt certain that I’d already transcribed the notes into a plain text file—in Markdown format, of course—so I popped open Spotlight to search for the text in my head along with the operator &lt;code&gt;kind:markdown&lt;/code&gt;, meaning “search in Markdown files”.&lt;/p&gt;
&lt;p&gt;Spotlight found nothing. Weird.&lt;/p&gt;
&lt;p&gt;I looked around my computer’s file system for where I thought I filed the outline document and I found it in a file called &lt;code&gt;60-Minute Talk Sketch.markdown&lt;/code&gt;. I opened it and found the exact line of text I’d searched for with Spotlight. Why didn’t Spotlight find it? I tried one more thing.&lt;/p&gt;
&lt;p&gt;I love &lt;a href=&quot;http://www.alfredapp.com&quot;&gt;Alfred&lt;/a&gt; for moving around my computer’s file system. I won’t even try to write about how much time it saves me. I hate using other people’s computers for more than a few minutes unless they have Alfred installed. I sometimes worry that it slowly makes me increasingly unable to use a typical Mac. I digress.&lt;/p&gt;
&lt;p&gt;Since Alfred uses data from Spotlight to find files, I opened Alfred to search for my conference talk outline. I couldn’t even find the file by name! Super weird.&lt;/p&gt;
&lt;p&gt;I asked Alfred to find some other files for me… it found them without trouble. Just not Markdown files.&lt;/p&gt;
&lt;p&gt;Ugh. I guess I have to “fix” something….&lt;/p&gt;
&lt;h2 id=&quot;spotlight-and-markdown&quot;&gt;Spotlight and Markdown&lt;/h2&gt;
&lt;p&gt;Fortunately, others have encountered this problem before I, and have written about how they solved it. It appears that, out of the box, Mac OS X has no idea what a Markdown file is, so we have to tell it. This makes sense to me, so while it annoys me, and least it doesn’t &lt;em&gt;surprise&lt;/em&gt; me. We need to tell Spotlight about the Markdown file format and in order to be able to search inside Markdown files, we can tell Spotlight, “Treat them like Rich Text files.” That sounds reasonable to me.&lt;/p&gt;
&lt;h2 id=&quot;the-steps-i-used-to-solve-the-problem&quot;&gt;The Steps I Used to Solve the Problem&lt;/h2&gt;
&lt;p&gt;An overview of the steps:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Download and install an “importer” that instructs Mac OS X to index Markdown files as though they were just another kind of Rich Text.&lt;/li&gt;
&lt;li&gt;Ask Spotlight to reindex everything.&lt;/li&gt;
&lt;li&gt;Wait several minutes and try again.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Now, the details.&lt;/p&gt;
&lt;h3 id=&quot;the-detailed-steps&quot;&gt;The Detailed Steps&lt;/h3&gt;
&lt;p&gt;Read &lt;a href=&quot;http://hiltmon.com/blog/2015/11/17/a-yosemite-markdown-spotlight-importer/&quot;&gt;“A Yosemite Markdown Spotlight Importer”&lt;/a&gt; for details.&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;http://cdn3.brettterpstra.com/downloads/Markdown.mdimporter.zip&quot;&gt;Click here&lt;/a&gt; to download the importer.&lt;/li&gt;
&lt;li&gt;Uncompress the importer.&lt;/li&gt;
&lt;li&gt;Copy the file &lt;code&gt;Markdown.mdimporter&lt;/code&gt; to &lt;code&gt;/Library/Spotlight&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Open Terminal and tell Spotlight to reindex the entire local hard disk. &lt;code&gt;sudo mdutil -E /&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Check that Spotlight is using the new importer. &lt;code&gt;mdimport -L&lt;/code&gt; should match at least one line of output, showing the location to which you copied &lt;code&gt;Markdown.mdimporter&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Wait several minutes. I’ll have a tea sounds nice.&lt;a href=&quot;#fn1&quot; class=&quot;footnote-ref&quot; id=&quot;fnref1&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre data-caption=&quot;Evidently, this is one big line of output...&quot;&gt;&lt;code&gt;2016-01-26 12:01:21.177 mdimport[27566:3379462] Paths: id(501) (
    [...some irrelevant importers...]
    &amp;quot;/Library/Spotlight/Markdown.mdimporter&amp;quot;,
    [...and so on...]
)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Some instructions tell you to copy the importer file to &lt;code&gt;$HOME/Library/Spotlight&lt;/code&gt;, meaning at the scope of the current logged-in user. Since some people reported that that didn’t work for them, and I wasn’t in the mood to mess around, I just copied it to &lt;code&gt;/Library/Spotlight&lt;/code&gt;, meaning at the scope of all users. If you want to experiment with copying this to &lt;code&gt;$HOME/Library/Spotlight&lt;/code&gt;, then feel free. It might also work.&lt;/p&gt;
&lt;p&gt;This worked for me. I hope it helps you.&lt;/p&gt;
&lt;h2 id=&quot;epilogue&quot;&gt;Epilogue&lt;/h2&gt;
&lt;p&gt;Someone asked about this &lt;a href=&quot;https://discussions.apple.com/thread/1392643&quot;&gt;in an Apple discussion board thread from 2008&lt;/a&gt;, but there seems no way to tell that person about the solution. This makes me sad.&lt;/p&gt;
&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;
&lt;p&gt;Hilton Lipschitz, &lt;a href=&quot;http://hiltmon.com/blog/2015/06/27/a-simple-markdown-spotlight-importer/&quot;&gt;“A Simple Markdown Spotlight Importer”&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Hilton Lipschitz, &lt;a href=&quot;http://hiltmon.com/blog/2015/11/17/a-yosemite-markdown-spotlight-importer/&quot;&gt;“A Yosemite Markdown Spotlight Importer”&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Stack Overflow, &lt;a href=&quot;http://stackoverflow.com/questions/365669/how-can-i-make-spotlight-index-markdown-files&quot;&gt;“How can I make spotlight index markdown files?”&lt;/a&gt;. More details on the solution, how it works, and alternative approaches.&lt;/p&gt;
&lt;p&gt;Anthony Craig, &lt;a href=&quot;https://theoveranalyzed.net/2015/12/3/how-to-force-spotlight-to-index-markdown-files-in-el-capitan&quot;&gt;“How to Force Spotlight to Index Markdown Files in El Capitan”&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Brett Terpstra, &lt;a href=&quot;http://brettterpstra.com/2011/10/18/fixing-spotlight-indexing-of-markdown-content/&quot;&gt;“Fixing Spotlight indexing of Markdown content”&lt;/a&gt;. All roads appear to lead to this article.&lt;/p&gt;
&lt;section class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot; role=&quot;doc-endnote&quot;&gt;&lt;p&gt;If you don’t get the reference, then I can’t help you.&lt;a href=&quot;#fnref1&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
        <pubDate>Tue, 26 Jan 2016 00:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/i-cant-find-stuff-in-my-markdown-files</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/i-cant-find-stuff-in-my-markdown-files</guid>
        
        
        <category>Wrangling Technology</category>
        
      </item>
    
      <item>
        <title>Handling Urgent Email With Todoist</title>
        <description>&lt;p&gt;I use &lt;a href=&quot;http://todoist.com&quot;&gt;Todoist&lt;/a&gt; to track my work. You might call them “projects” or “next actions” or “to do”s, but I try to call it simply “work”, if for no other reason than to make it easier to talk about. I strongly prefer to track work in one place, and I’ve chosen Todoist for that. I know that some of you use email to manage your tasks, and that doesn’t work for me, for a few reasons.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I sometimes don’t open email for several weeks.&lt;/li&gt;
&lt;li&gt;I really hate looking in multiple places to remind myself what I should be doing next.&lt;/li&gt;
&lt;li&gt;When I open email to look for work to do, I become easily distracted by the new email to process, so I end up doing that instead.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Yes, perhaps I should not be so weak-minded, but managing one’s work well involves creating systems to tolerate one’s weakness, rather than work against them. Suffice it to say that I don’t want to track significant work in email; I want to see it in Todoist or, in some cases, directly on my calendar.&lt;/p&gt;
&lt;h2 id=&quot;the-manual-system&quot;&gt;The Manual System&lt;/h2&gt;
&lt;p&gt;When I process my email inbox, I want to quickly assess which emails to delete immediately, file for future reference, answer someday, answer soon, or answer now. I always prefer to delete the message immediately or file it for future reference (notices, bills that I automatically pay, and so on), but when I have to answer the message, I apply the &lt;a href=&quot;#references&quot;&gt;Two-Minute Rule&lt;/a&gt;. If I can answer it in two minutes, then I answer it as soon as I’ve sorted all the incoming mail. If it takes longer, then I forward it to Todoist, and fortunately there exists a nice plugin for &lt;a href=&quot;http://mailplaneapp.com/&quot;&gt;Mailplane&lt;/a&gt; that lets me add a task to Todoist directly. If I prefer, I can also forward the email to a Todoist project and it will show up as an action in that project. As I process my email inbox, then, I decide quickly which of these to do for each email, in order of preference:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Delete it.&lt;/li&gt;
&lt;li&gt;Send it to Evernote, because I’m likely going to need to refer it.&lt;/li&gt;
&lt;li&gt;Archive it, because I might need to refer it.&lt;/li&gt;
&lt;li&gt;Label it “Answer Eventually” and rely on my standing Todoist task every week that says, “Respond to some ‘Answer Eventually’ emails.”&lt;/li&gt;
&lt;li&gt;Label it “Answer Soon” and send it to Todoist as a specific task in the project “Urgent Email”.&lt;/li&gt;
&lt;li&gt;Label it “Answer Now” and come back to it once I’ve processed the rest of the inbox.&lt;/li&gt;
&lt;/ol&gt;
&lt;aside&gt;
It usually takes only a few minutes to process the email inbox this way, so even if I find the message very urgent, it can wait 12 minutes while I get the rest of this email inbox out of the way. In very rare occasions, like “Book this flight before the price goes up”, I drop what I’m doing to deal with the email.
&lt;/aside&gt;
&lt;p&gt;The emails that end up as specific Todoist tasks, rather than simply going into the “Answer Eventually” pile (also known as “When I Get Around To It”), expose a flaw in the system, at least when I start trying to automate it a little.&lt;/p&gt;
&lt;h2 id=&quot;the-trouble-with-gmail-and-todoist&quot;&gt;The Trouble with GMail and Todoist&lt;/h2&gt;
&lt;p&gt;Members of &lt;a href=&quot;http://experience.jbrains.ca&quot;&gt;The jbrains Experience&lt;/a&gt;, my online learning and consulting circle, can ask me a question by posting a comment in a comment system. This sends me an email and that’s how I know that a question is waiting for me to answer it. Since I don’t look at email every day, and since those emails fall into the “Answer Soon” category, and since those emails follow a pattern (same sender, same words in the subject), I end up creating very similar Todoist tasks in the same project to remind me to answer these questions. After doing this five or six times, I wanted to set up a GMail filter to automatically forward the email to my “Urgent Email” project in Todoist. Sadly, I couldn’t.&lt;/p&gt;
&lt;p&gt;To forward the emails with GMail, one must verify the email address. GMail sends it a message, you read it and click a link, then GMail knows that you own that email address and consent to receive forwarded emails to it. Sadly, although Todoist provides an email address for every project, one cannot receive those emails outside Todoist in order to click GMail’s verification link. This means that one cannot register a Todoist project email address in GMail as a trusted email address to which to forward email.&lt;/p&gt;
&lt;h2 id=&quot;mailgun-to-the-rescue&quot;&gt;Mailgun To the Rescue&lt;/h2&gt;
&lt;p&gt;I have a Mailgun account and that gives me a solution to the problem. In Mailgun I create a Route that forwards emails from a middleman address I control to the Todoist project’s email address. Since I can read emails sent to this middleman address, I can verify that I control that address to GMail, then add a GMail filter that forwards the “I have a question” emails to the middleman. Mailgun then intercepts the email and forwards a copy to Todoist, which creates a task in the appropriate project. Problem solved.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;/img/handling-urgent-email-with-todoist/diagram-1.png&quot; title=&quot;fig:&quot; alt=&quot;Using Mailgun as a middleman between GMail and Todoist&quot; /&gt;
&lt;figcaption&gt;
Using Mailgun as a middleman between GMail and Todoist
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;You don’t have to use Mailgun in particular. You simply need an email address connected to a mailbox so that you can receive GMail’s address verification email and a service that can forward emails received at that address (or copies of them) to another email address (the Todoist project).&lt;/p&gt;
&lt;h2 id=&quot;an-example-would-be-handy&quot;&gt;An Example Would Be Handy…&lt;/h2&gt;
&lt;p&gt;Suppose you run a consulting circle like I do and you want to automatically create a Todoist task every time one of your members asks you a question by email. In order to make this easier, you’ve set up a question form so that questions always arrive from the same email address and have some magic string in the subject line that an email filter can easily match. Here are the steps to follow to create the email-to-task pipeline.&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Choose a Todoist project, then find the email address associated with it.&lt;a href=&quot;#fn1&quot; class=&quot;footnote-ref&quot; id=&quot;fnref1&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; I’ll call it &lt;code&gt;your-todoist-project@todoist.com&lt;/code&gt; here.&lt;/li&gt;
&lt;li&gt;Invent an email address on a domain that you have registered with Mailgun. I’ll call it &lt;code&gt;answer-consulting-circle-email-inbox@mydomain.com&lt;/code&gt;. (Of course, I don’t have &lt;code&gt;mydomain.com&lt;/code&gt;, but I have to watch for spam.)&lt;/li&gt;
&lt;li&gt;Tell GMail that you’d like to be able to forward emails to &lt;code&gt;answer-consulting-circle-email-inbox@mydomain.com&lt;/code&gt;.&lt;a href=&quot;#fn2&quot; class=&quot;footnote-ref&quot; id=&quot;fnref2&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt; Complete GMail’s verification instructions for the new forwarding email address.&lt;/li&gt;
&lt;li&gt;Create a GMail filter that matches the “somebody in my consulting circle asked me a question” emails and choose “forward to &lt;code&gt;answer-consulting-circle-email-inbox@mydomain.com&lt;/code&gt;” as one of the actions for that filter.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That’s it! Enjoy.&lt;/p&gt;
&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;
&lt;p&gt;David Allen, &lt;a href=&quot;http://link.jbrains.ca/WOXFIr&quot;&gt;&lt;em&gt;Getting Things Done&lt;/em&gt;&lt;/a&gt;. A system for managing work based on the principle of building a trusted system for figuring out what to do next so that your mind can focus on each task as you work on them.&lt;/p&gt;
&lt;p&gt;J. B. Rainsberger, &lt;a href=&quot;http://link.jbrains.ca/getting-started-with-gtd&quot;&gt;“Getting Started with Getting Things Done”&lt;/a&gt;. If you don’t have energy to read a book, then you can probably read &lt;strong&gt;four pages&lt;/strong&gt; to try out the basics of the system and see whether it’s worth learning more.&lt;/p&gt;
&lt;p&gt;J. B. Rainsberger, &lt;a href=&quot;http://blog.jbrains.ca/permalink/the-two-minute-rule&quot;&gt;“The Two-Minute Rule”&lt;/a&gt;. If you really don’t have the energy even to put the basics of Getting Things Done into action, you can certainly benefit from the Two-Minute Rule, which will help you avoid the day getting away from you, especially when trying to deal with email.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.todoist.com&quot;&gt;Todoist&lt;/a&gt;. My primary “projects” database. I choose a projects database based mostly on how easily I can get tasks into it, and Todoist makes that quite easy.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.mailgun.com&quot;&gt;Mailgun&lt;/a&gt;. I use Mailgun primarily for flexible email forwarding and sorting, as well as for creating email aliases whenever I need them.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.mailplaneapp.com&quot;&gt;Mailplane&lt;/a&gt;. If you use GMail on Mac OS, then you will probably enjoy Mailplane.&lt;/p&gt;
&lt;section class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot; role=&quot;doc-endnote&quot;&gt;&lt;p&gt;You can click &lt;a href=&quot;https://support.todoist.com/hc/en-us/articles/205749772&quot;&gt;https://support.todoist.com/hc/en-us/articles/205749772&lt;/a&gt; to see how to do this. By the time you read this, Todoist might have changed.&lt;a href=&quot;#fnref1&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn2&quot; role=&quot;doc-endnote&quot;&gt;&lt;p&gt;You can click &lt;a href=&quot;https://support.google.com/mail/answer/10957?hl=en&quot;&gt;https://support.google.com/mail/answer/10957?hl=en&lt;/a&gt; to see how to do this. By the time you read this, GMail might have changed.&lt;a href=&quot;#fnref2&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
        <pubDate>Wed, 20 Jan 2016 22:00:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/handling-urgent-email-with-todoist</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/handling-urgent-email-with-todoist</guid>
        
        
        <category>Productivity</category>
        
      </item>
    
      <item>
        <title>Writing with Pleasure Using Markdown and pandoc</title>
        <description>&lt;p&gt;I write a &lt;em&gt;lot&lt;/em&gt;, and I never know where or when my ideas will strike. In order to at least get things out of my head, I like to write in a format that I can use from just about anywhere, so I rely on Markdown. It’s plain text, which means that I can write it on my phone, my tablet, my laptop, with or without an internet connection. It’s also lightweight HTML, which means that I can add some structure to my writing, like lists, headings, and links, without distracting myself from what I’m trying to write.&lt;/p&gt;
&lt;p class=&quot;aside&quot;&gt;
A friend, &lt;a href=&quot;http://www.gargoylesoftware.com/mike_bowler&quot;&gt;Mike Bowler&lt;/a&gt;, once told me that he hated writing in a word processor, because the moment he started formatting what he was writing, he stopped writing and became fixated on the formatting. I found the same thing when I worked in Word, Pages, and other full-fledged word processors. I even have this problem in HTML, but I have to &lt;em&gt;get the formatting right&lt;/em&gt;. I’ve noticed that this problem mostly goes away when I write in Markdown. Even when I do a little formatting, I can do it quickly, unobtrusively, and then &lt;strong&gt;get back to the thing I’m actually writing&lt;/strong&gt;. This makes my job much easier.
&lt;/p&gt;
&lt;p&gt;I have also found it easier to write in Markdown without worrying about where I’m going to publish what I’m writing, in part due to &lt;code&gt;pandoc&lt;/code&gt;, the Swiss Army knife of text processing. Although &lt;code&gt;pandoc&lt;/code&gt; is not suitable for all users, I think that even non-technical users can enjoy the benefits of writing whatever, whenever, without worrying about producing “the right format” for how you will publish your writing. With &lt;code&gt;pandoc&lt;/code&gt;, I can write in Markdown, then decide later whether I need RTF, HTML, TeX, or any of a variety of formats. I can decide &lt;em&gt;later&lt;/em&gt; when to publish an article as a blog post, a whitepaper, or even as a chapter in a book! The combination of Markdown and &lt;code&gt;pandoc&lt;/code&gt; gives me options.&lt;/p&gt;
&lt;h2 id=&quot;the-simplest-case-publishing-to-a-blog&quot;&gt;The Simplest Case: Publishing to a Blog&lt;/h2&gt;
&lt;p&gt;If you publish to a blog, then you probably already have a system in place for publishing new posts. Whatever you do, working with Markdown and &lt;code&gt;pandoc&lt;/code&gt; will feel similar, and will probably not appear to give you much benefit over your current system. I felt the same way, which explains why I started using &lt;code&gt;pandoc&lt;/code&gt; only relatively recently. My old system worked well enough, which both means that there wasn’t much reason to change, but the similarity of the new system also makes it relatively easy to change.&lt;/p&gt;
&lt;p&gt;I tend to compose blog posts at my laptop, where I mostly use Atom. (I work in vim, too, but I remain at best an intermediate vim user.) I use an Atom plugin to let me preview my Markdown documents as HTML. The plugin, called &lt;code&gt;markdown-preview-plus&lt;/code&gt;, lets me use &lt;code&gt;pandoc&lt;/code&gt; as my Markdown processor, meaning that I get the same results in the preview window as when I publish to my &lt;code&gt;jekyll&lt;/code&gt; blog, which also uses &lt;code&gt;pandoc&lt;/code&gt; to convert Markdown to HTML. I don’t have to worry about formatting something one way while writing, then getting something unexpected when I publish, which normally causes me to scramble and fix something at the last moment. When I publish something, it just looks right.&lt;/p&gt;
&lt;p&gt;Since I travel quite extensively to work, I also find myself in airports and coffee shops when I have the urge to write something. In this situation, if I find inconvenient to pull out my laptop—or if its battery is dead—then I can pull out my &lt;a href=&quot;http://link.jbrains.ca/1QmC5qC&quot;&gt;Logitech K480 keyboard&lt;/a&gt; and &lt;a href=&quot;http://link.jbrains.ca/1RiDEGa&quot;&gt;Samsung Galaxy NotePro&lt;/a&gt; and write, using an app called &lt;a href=&quot;https://play.google.com/store/apps/details?id=com.jotterpad.x&quot;&gt;JotterPad&lt;/a&gt;. This app lets me compose in Markdown, get a quick preview (not with &lt;code&gt;pandoc&lt;/code&gt;, but it’s good enough), then move the composition onto my laptop (directly or through Dropbox), where I can give it a final check before publishing it. This just works, and I feel no extra friction when I want to write using my tablet compared to using my “full-fledged” system on the laptop. I can write anywhere and get consistent results, which makes it easier for me to &lt;em&gt;just write&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id=&quot;an-interesting-case-rescuing-old-articles&quot;&gt;An Interesting Case: Rescuing Old Articles&lt;/h2&gt;
&lt;p&gt;I’m in the process of moving away from Wordpress towards &lt;code&gt;jekyll&lt;/code&gt; for my blog at &lt;a href=&quot;http://blog.jbrains.ca&quot;&gt;blog.jbrains.ca&lt;/a&gt;. This means moving a bunch of articles from older formats into my current system. I &lt;em&gt;dreaded&lt;/em&gt; the prospect of doing this, because it meant reverse-engineering the Markdown source for 100 HTML articles. Bleh.&lt;/p&gt;
&lt;p&gt;Nope. I didn’t have to worry, thanks to &lt;code&gt;pandoc&lt;/code&gt;!&lt;/p&gt;
&lt;p&gt;The first wonderful discovery I made about &lt;code&gt;pandoc&lt;/code&gt; was that it can convert HTML back to Markdown with at least 95% accuracy. Yes, it misses things like embedded video, but it does 95% of this terribly tedious work, and for that, &lt;em&gt;I love it&lt;/em&gt;. (I love it as much as one can love software, anyway.) Now, when I have 30 free minutes, I can rescue a few old blog posts, by doing this:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Log in to my Wordpress blog. Edit an article.&lt;/li&gt;
&lt;li&gt;Load my new blog project into Atom and start a new document.&lt;/li&gt;
&lt;li&gt;Copy the blog post’s title and publication date into the new document in Atom.&lt;/li&gt;
&lt;li&gt;Add a category or two to the new document in Atom.&lt;/li&gt;
&lt;li&gt;Select the entire Wordpress blog post content and copy it.&lt;/li&gt;
&lt;li&gt;Run this command: &lt;code&gt;pandoc --no-wrap --read=html --write=markdown &amp;lt;(pbpaste) | pbcopy&lt;/code&gt;, which replaces the HTML on my clipboard with (almost) equivalent Markdown.&lt;/li&gt;
&lt;li&gt;Paste the Markdown on my clipboard into the document in Atom.&lt;/li&gt;
&lt;li&gt;Save, preview, publish.&lt;/li&gt;
&lt;li&gt;Redirect the old blog URL to the new one.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Granted, you need some technical chops to do the last step, and the &lt;code&gt;pandoc&lt;/code&gt; command looks intimidating, but at least it’s exactly the same command every time, so you can just copy/paste it in your Terminal/Command Prompt. (If you work on Windows, then find a power user friend to teach you the exact command. I don’t do Windows, so I don’t know it.)&lt;/p&gt;
&lt;p&gt;The important thing is this: &lt;strong&gt;&lt;code&gt;pandoc&lt;/code&gt; is helping me finally, after years, get away from Wordpress&lt;/strong&gt;. If you have a love/hate relationship with Wordpress, then you understand why I might want to get away from it. So far, I’m still on my honeymoon with &lt;code&gt;jekyll&lt;/code&gt;. :)&lt;/p&gt;
&lt;h2 id=&quot;whatever-you-want-pandoc-can-do-it&quot;&gt;Whatever You Want, &lt;code&gt;pandoc&lt;/code&gt; Can Do It&lt;/h2&gt;
&lt;p&gt;I really hate most modern software, because it lets me down constantly, but not &lt;code&gt;pandoc&lt;/code&gt;. I would even recommend it to non-technical users. Most non-technical users have two primary problems with software:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Installing it.&lt;/li&gt;
&lt;li&gt;Dealing with problems when it fails, because every failure looks equally disastrous. It either works or it doesn’t.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Granted, installing &lt;code&gt;pandoc&lt;/code&gt; isn’t pretty to non-technical users, even though highly-technical users probably love how simple it is. If you need someone to install &lt;code&gt;pandoc&lt;/code&gt; for you, then I think it’s worth the effort. One thing you &lt;strong&gt;won’t&lt;/strong&gt; have to worry about: &lt;code&gt;pandoc&lt;/code&gt; is solid. It just works. Once you learn how to ask it to process a document, it just does it, well and quickly. You won’t have to fiddle with it. It just works.&lt;/p&gt;
&lt;p&gt;This makes me trust &lt;code&gt;pandoc&lt;/code&gt;. I don’t trust most software any more, so when I find something that I can trust, I &lt;em&gt;really&lt;/em&gt; enjoy it. Now, if I need to convert some text from one format to another, I feel confident that &lt;code&gt;pandoc&lt;/code&gt; will do it for me. This means that I don’t have to worry about “Will I be able to republish these blog posts into a book?” It’ll just work. I can take 20 blog posts, paste some connective tissue around them, and then publish it as a &lt;a href=&quot;http://leanpub.com/&quot;&gt;Leanpub&lt;/a&gt; book and charge $7. No, it’s not the same as publishing to amazon, but it’s really good!&lt;/p&gt;
&lt;h2 id=&quot;the-bottom-line&quot;&gt;The Bottom Line&lt;/h2&gt;
&lt;p&gt;Markdown lets me focus on the writing. &lt;code&gt;pandoc&lt;/code&gt; gives me confidence that I can publish it anywhere, anytime, with minimal effort. I’ve written 50,000 words since I started using this pair of tools. I love it.&lt;/p&gt;
&lt;p&gt;If you want to get started, read on.&lt;/p&gt;
&lt;h2 id=&quot;the-first-detail-running-pandoc&quot;&gt;The First Detail: Running &lt;code&gt;pandoc&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Once you have installed it, running &lt;code&gt;pandoc&lt;/code&gt; can be as simple as this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ pandoc --read=markdown --write=html -o results.html my_awesome_post.markdown&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you don’t specify &lt;code&gt;-o&lt;/code&gt;, then you &lt;code&gt;pandoc&lt;/code&gt; just spits out the resulting HTML, so you can do it with whatever you want.&lt;/p&gt;
&lt;p&gt;Of course, &lt;code&gt;pandoc&lt;/code&gt; has many, many options. You’ll have to ask it for all the details: &lt;code&gt;pandoc --help&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;the-gory-details-setting-up-atom-with-pandoc&quot;&gt;The Gory Details: Setting up Atom with &lt;code&gt;pandoc&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Install both &lt;a href=&quot;http://atom.io/&quot;&gt;Atom&lt;/a&gt; and &lt;a href=&quot;http://pandoc.org/&quot;&gt;&lt;code&gt;pandoc&lt;/code&gt;&lt;/a&gt;, then read on.&lt;/p&gt;
&lt;h3 id=&quot;installmarkdown-preview-plus&quot;&gt;Install&lt;code&gt;markdown-preview-plus&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Press &lt;code&gt;Cmd+Shift+P&lt;/code&gt;, then start typing “Install packages”:&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;/img/writing-with-pleasure-using-markdown-and-pandoc/install-package-in-atom.jpg&quot; alt=&quot;Installing a package in Atom&quot; /&gt;&lt;figcaption aria-hidden=&quot;true&quot;&gt;Installing a package in Atom&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Search for &lt;code&gt;markdown-preview-plus&lt;/code&gt;, then press Install.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;/img/writing-with-pleasure-using-markdown-and-pandoc/find-markdown-preview-plus.jpg&quot; alt=&quot;Installing markdown-preview-plus&quot; /&gt;&lt;figcaption aria-hidden=&quot;true&quot;&gt;Installing markdown-preview-plus&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;After the package installs, choose Settings.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;/img/writing-with-pleasure-using-markdown-and-pandoc/change-markdown-preview-plus-settings.jpg&quot; alt=&quot;Changing the package settings&quot; /&gt;&lt;figcaption aria-hidden=&quot;true&quot;&gt;Changing the package settings&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;You might find it useful to change two settings:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Pandoc Options: Path&lt;/strong&gt;. Set this to wherever you installed &lt;code&gt;pandoc&lt;/code&gt;. In my case, &lt;code&gt;$HOME/.cabal/bin/pandoc&lt;/code&gt;. If you don’t know, then open a Terminal window/command prompt and type &lt;code&gt;which pandoc&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pandoc Options: Commandline Arguments&lt;/strong&gt;. I like to have my blog’s CSS available to the preview, so I choose &lt;code&gt;--css /Users/jbrains/Workspaces/jekyll-jbrains.ca/php/css/main.css&lt;/code&gt;. Great, no?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now you can close the Settings tab, open any file containing Markdown, and press &lt;code&gt;Ctrl+Shift+M&lt;/code&gt; to get the preview window. If, for some reason, that doesn’t work, then do this from Atom’s menu: &lt;strong&gt;Packages &amp;gt; Markdown Preview Plus &amp;gt; Toggle Preview&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Now you can use &lt;code&gt;pandoc&lt;/code&gt; from within Atom.&lt;/p&gt;
&lt;h2 id=&quot;more-gory-details-using-pandoc-with-jekyll&quot;&gt;More Gory Details: Using &lt;code&gt;pandoc&lt;/code&gt; with &lt;code&gt;jekyll&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Unless you speak &lt;code&gt;bash&lt;/code&gt;, you should probably skip this section.&lt;/p&gt;
&lt;p&gt;To use &lt;code&gt;pandoc&lt;/code&gt; with &lt;code&gt;jekyll&lt;/code&gt; requires creating a “relocatable binary”. Fortunately, &lt;a href=&quot;http:/%60pandoc%60.org/installing.html#creating-a-relocatable-binary&quot;&gt;the installation instructions for &lt;code&gt;pandoc&lt;/code&gt;&lt;/a&gt; make that relatively clear. Once you have a relocatable binary, you can include it in your blog and make it available to your blog’s “production environment”—or server, if you prefer. I publish to &lt;a href=&quot;http://openshift.com/&quot;&gt;OpenShift&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;ship-pandoc-with-your-jekyll-blog&quot;&gt;Ship &lt;code&gt;pandoc&lt;/code&gt; with your &lt;code&gt;jekyll&lt;/code&gt; blog&lt;/h3&gt;
&lt;p&gt;Since I want to schedule future posts to be published, I want my production environment (OpenShift) to rebuild my blog every so often. &lt;em&gt;If you plan to publish each post as you go, then you don’t have to worry about this part at all: instead, just run &lt;code&gt;jekyll build&lt;/code&gt; whenever you want to republish&lt;/em&gt;. This means that I need a way to rebuild my blog in production, then a way to schedule the “rebuild” command.&lt;/p&gt;
&lt;h4 id=&quot;tell-jekyll-to-use-pandoc&quot;&gt;Tell &lt;code&gt;jekyll&lt;/code&gt; to use &lt;code&gt;pandoc&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;I added the following to my configuration file (the default name is &lt;code&gt;_config.yml&lt;/code&gt;).&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# Bundle pandoc for production. See .openshift/action_hooks/deploy
markdown: pandoc
pandoc:
  format: html5
  extensions: [smart, mathjax]&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;rebuild&quot;&gt;Rebuild!&lt;/h4&gt;
&lt;p&gt;I put &lt;code&gt;pandoc&lt;/code&gt; in the folder &lt;code&gt;libs&lt;/code&gt; at the root of my blog project. On OpenShift, this corresponds to &lt;code&gt;$OPENSHIFT_REPO_DIR/libs/&lt;/code&gt;, so that I know how to use &lt;code&gt;pandoc&lt;/code&gt; to build my site on OpenShift.&lt;/p&gt;
&lt;p&gt;I created an action hook script at &lt;code&gt;.openshift/action_hooks&lt;/code&gt; that rebuilds my blog using &lt;code&gt;jekyll&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#!/bin/bash

echo &amp;quot;$(date) Regenerating blog.&amp;quot; &amp;gt;&amp;gt; $OPENSHIFT_LOG_DIR/regenerating-blog.log
export LC_CTYPE=en_CA.UTF-8
export LANG=en_CA.UTF-8
export LD_LIBRARY_PATH=/opt/rh/mysql55/root/usr/lib64:/opt/rh/ror40/root/usr/lib64:/opt/rh/ruby200/root/usr/lib64
export PATH=$OPENSHIFT_REPO_DIR/libs:~/.gem/bin:/opt/rh/ruby200/root/usr/bin:$PATH
gem install bundle
cd $OPENSHIFT_REPO_DIR &amp;amp;&amp;amp; bundle install &amp;amp;&amp;amp; bundle exec jekyll build --config _config.yml&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I found out the hard way that I have to set the locale explicitly by setting &lt;code&gt;LC_CTYPE&lt;/code&gt; and &lt;code&gt;LANG&lt;/code&gt;. I did not enjoy that little surprise.&lt;/p&gt;
&lt;p&gt;I put &lt;code&gt;$OPENSHIFT_REPO_DIR/libs/&lt;/code&gt; on the system path so that &lt;code&gt;bundle exec jekyll&lt;/code&gt; would find &lt;code&gt;pandoc&lt;/code&gt; and be able to run it.&lt;/p&gt;
&lt;h4 id=&quot;rebuild-every-hour&quot;&gt;Rebuild Every Hour!&lt;/h4&gt;
&lt;p&gt;I added the Cron cartridge to my OpenShift application and added this little script to &lt;code&gt;.openshift/cron/hourly&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#!/bin/bash
echo &amp;quot;$(date) Regenerating blog.&amp;quot; &amp;gt;&amp;gt; $OPENSHIFT_LOG_DIR/regenerating-blog.log
cd $OPENSHIFT_REPO_DIR &amp;amp;&amp;amp; bundle install &amp;amp;&amp;amp; bundle exec jekyll build&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I now realize that I should change the deploy script to just invoke this one, but my &lt;code&gt;bash&lt;/code&gt; skills aren’t excellent, so I’ll wait until I need to learn how to do that, then I’ll do it.&lt;/p&gt;
&lt;p&gt;Now, &lt;strong&gt;I can write posts with a date in the future and my production environment will publish them within an hour of the date I specify&lt;/strong&gt;. Nice, no?&lt;/p&gt;
&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;
&lt;p&gt;John Gruber, &lt;a href=&quot;http://daringfireball.net/projects/markdown/syntax&quot;&gt;“Markdown: Syntax”&lt;/a&gt;. A complete reference of the basics of Markdown. You’ll probably need to use this for a few weeks while you get used to how to write in Markdown.&lt;/p&gt;
&lt;p&gt;Adam Pritchard, &lt;a href=&quot;https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet&quot;&gt;“Markdown Cheatsheet”&lt;/a&gt;. You can never have too many good references for writing in Markdown.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://pandoc.org/&quot;&gt;pandoc.org&lt;/a&gt;. Get started here with &lt;code&gt;pandoc&lt;/code&gt;. The installation page looks pretty straightforward, especially for Windows.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://atom.io/&quot;&gt;atom.io&lt;/a&gt;. A fine text editor, especially if you speak Javascript and like to hack, but even if you don’t.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://atom.io/packages/markdown-preview-plus/&quot;&gt;Markdown Preview Plus for Atom&lt;/a&gt;. The plugin I use to get a WYSIWYGish view of what I’m composing in Atom.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://leanpub.com/&quot;&gt;leanpub.com&lt;/a&gt;. When you want to publish what you’ve written &lt;em&gt;and charge money&lt;/em&gt;, Leanpub provides a low-friction way to make that happen.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://jekyllrb.com/&quot;&gt;jekyllrb.com&lt;/a&gt;. When you want to publish what you’ve written to the web, Jekyll provides a very simple way to make that happen, and without Wordpress.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://blog.jbrains.ca/&quot;&gt;blog.jbrains.ca&lt;/a&gt;. A blog I publish with &lt;code&gt;jekyll&lt;/code&gt; that uses &lt;code&gt;pandoc&lt;/code&gt; to produce HTML from my posts composed in Markdown.&lt;/p&gt;
</description>
        <pubDate>Sun, 13 Dec 2015 18:24:00 +0000</pubDate>
        <link>http://jb.rainsberger.ca/permalink/writing-with-pleasure-using-markdown-and-pandoc</link>
        <guid isPermaLink="true">http://jb.rainsberger.ca/permalink/writing-with-pleasure-using-markdown-and-pandoc</guid>
        
        
      </item>
    
  </channel>
</rss>
