<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>cosine.blue</title>
<link>https://cosine.blue</link>
<description>Blog by Gregory Chamberlain.</description>
<webMaster>greg@cosine.blue (Gregory Chamberlain)</webMaster>
<copyright>GPLv3+ or CC BY-SA 4.0</copyright>
<atom:link href="https://cosine.blue/rss.xml" rel="self" type="application/rss+xml" />
<item><title>Emacs Keeps Surprising Me</title>
<author>greg@cosine.blue (Gregory Chamberlain)</author>
<pubDate>Sun, 12 Sep 2021 00:00:00 +0000</pubDate>
<guid>https://cosine.blue/vanilla-emacs.html</guid>
<description>&lt;p&gt;Emacs keeps surprising me.  Though I've been using it regularly for
about two years now, I am still discovering features and nuances that
have been right under my nose since day one.&lt;/p&gt;
&lt;p&gt;I'm not talking about writing your own Elisp.  I'm not even talking
about third-party packages.  I'm talking about stock, built-in,
everyday functionality that is right there when you open GNU Emacs for
the first time, wondering what all the fuss is about.&lt;/p&gt;
&lt;p&gt;There is &lt;em&gt;so much&lt;/em&gt; there.  It's overwhelming.  Really, it's insane.
Stuff you didn't think existed, stuff you didn't know was possible,
stuff you don't expect to find, stuff you didn't think you needed,
stuff you really really needed that one time but didn't know about or
even think to look for, and stuff you always suspected might exist but
hadn't looked into yet.&lt;/p&gt;
&lt;p&gt;Sometimes it's a default key binding, however obscure, that has been
waiting patiently under your fingers, hidden beneath the keyboard all
this time, never before invoked (except perhaps by mistake).
Sometimes it's a minor mode, or a unique tool for editing, or just a
subtlety in the behaviour of a command you've already been using for
months.&lt;/p&gt;
&lt;p&gt;Most of these things are documented thoroughly in the manual, so it's
not like they're deliberately hidden from us.  It's just that there is
such an abundance of features built into Emacs that they effectively
must compete for our attention.&lt;/p&gt;
&lt;h1&gt;Inserting special characters&lt;/h1&gt;
&lt;p&gt;Recently I finally got around to looking in more detail at a feature I
only vaguely knew of: &lt;strong&gt;input methods&lt;/strong&gt;.  I do not know why I waited
until &lt;em&gt;now&lt;/em&gt; to look into it but, as someone who is interested in
languages, it was curiosity that eventually led me there.&lt;/p&gt;
&lt;p&gt;Now, there are a couple of sections in the manual about input methods
(22.3 and 22.4), and I'm sure they're great, but that was not how I
went about learning this particular feature.  No, I just dove straight
in.  What little I did know of input methods was only because I
inadvertently hit &lt;kbd&gt;C-\&lt;/kbd&gt; from time to time, invoking
&lt;code&gt;toggle-input-method&lt;/code&gt;.  I knew it had something to do with
internationalisation but I had always hit &lt;kbd&gt;C-g&lt;/kbd&gt; to get out of
it and continue with whatever highly important task I was doing (such
as &lt;code&gt;M-x tetris&lt;/code&gt;).  This time I hit &lt;kbd&gt;TAB&lt;/kbd&gt; instead, revealing a
screenful or two of completion candidates.&lt;/p&gt;
&lt;p&gt;Among them were &lt;em&gt;czech&lt;/em&gt;, &lt;em&gt;arabic&lt;/em&gt;, &lt;em&gt;japanese&lt;/em&gt; and many other languages
and their related input methods.  No surprises there.  What caught my
eye, though, were &lt;em&gt;TeX&lt;/em&gt; and &lt;em&gt;sgml&lt;/em&gt;.  These are not spoken languages.
These are methods for inserting all kinds of special
characters—obscure diacritical marks, quote marks, superscript and
subscript mathematical symbols, playing card suits, smileys, various
shapes and arrows, and so on.&lt;/p&gt;
&lt;p&gt;Input methods allow you to insert characters that you &lt;em&gt;can’t&lt;/em&gt; type by
typing a &lt;em&gt;sequence&lt;/em&gt; of characters that you &lt;em&gt;can&lt;/em&gt; type.  For example,
using the &lt;code&gt;spanish-postfix&lt;/code&gt; input method, typing &lt;code&gt;n~&lt;/code&gt; produces &lt;code&gt;ñ&lt;/code&gt;.
&lt;kbd&gt;C-h C-\&lt;/kbd&gt; (&lt;code&gt;describe-input-method&lt;/code&gt;) shows you all the
sequences for a given input method.&lt;/p&gt;
&lt;p&gt;Until now I had been using &lt;kbd&gt;C-x 8 RET&lt;/kbd&gt; (&lt;code&gt;insert-char&lt;/code&gt;) to
insert special characters by name, if I could guess the name (was it
&lt;em&gt;SMALL LATIN LETTER ETH&lt;/em&gt; or &lt;em&gt;LATIN SMALL LETTER ETH&lt;/em&gt;?).  Suddenly I
had a much smoother, less cumbersome way of doing the same thing.&lt;/p&gt;
&lt;p&gt;This is a feature you can &lt;em&gt;just use&lt;/em&gt;.  There’s no Lisp to write or
variables to tweak to make it usable.  There’s no external package you
have to install from MELPA.  You hit &lt;kbd&gt;C-\&lt;/kbd&gt;, choose your
input method, and start writing.&lt;/p&gt;
&lt;p&gt;My last article was about IPA (the International Phonetic Alphabet)
and I had to write a lot of phonetic symbols like ə and ʧ.  There I
was going through Wiktionary, painstakingly copy-pasting symbols into
Emacs while its &lt;code&gt;ipa&lt;/code&gt; input method was right under my nose the whole
time.&lt;/p&gt;
&lt;p&gt;A few days later I discovered it.  That’s what prompted me to write
this article.&lt;/p&gt;
&lt;h1&gt;View and edit lines that match a pattern&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;grep&lt;/em&gt; is an old-school UNIX program for printing only the lines of a
file that match a regular expression.&lt;/p&gt;
&lt;p&gt;Emacs has a command called &lt;strong&gt;occur&lt;/strong&gt; (&lt;kbd&gt;M-s o&lt;/kbd&gt;), which does a
similar thing for Emacs buffers.  The matching lines are shown in the
&lt;code&gt;*Occur*&lt;/code&gt; buffer, which can be used to jump to the location in the
source buffer where that match occurs.&lt;/p&gt;
&lt;p&gt;What’s really cool is that you can edit the &lt;code&gt;*Occur*&lt;/code&gt; buffer and any
changes made there are reflected in the source buffer.  You just hit
&lt;kbd&gt;e&lt;/kbd&gt; to begin editing and &lt;kbd&gt;C-c C-c&lt;/kbd&gt; to apply the
changes when you’re done.  In that sense, it’s a bit like &lt;kbd&gt;C-x n
n&lt;/kbd&gt; (&lt;code&gt;narrow-to-region&lt;/code&gt;) but for “multiple regions,” if you like.&lt;/p&gt;
&lt;p&gt;As an example, let’s say I wanted to reword some of the headings in
this article.  I’m writing it in Markdown, so each heading is on its
own line beginning with &lt;code&gt;#&lt;/code&gt;.  So I begin with &lt;kbd&gt;M-s o ^# RET&lt;/kbd&gt;
to have all the headings reproduced in the &lt;code&gt;*Occur*&lt;/code&gt; buffer—not unlike
a table of contents.  In that buffer, I can use &lt;kbd&gt;o&lt;/kbd&gt; or
&lt;kbd&gt;C-o&lt;/kbd&gt; to jump to that section in my article.  I can also hit
&lt;kbd&gt;e&lt;/kbd&gt; to begin editing them.  When I’m happy with my reworded
headings, I can hit &lt;kbd&gt;C-c C-c&lt;/kbd&gt; to apply the changes.&lt;/p&gt;
&lt;p&gt;Occur is a built-in package.  &lt;kbd&gt;M-s o&lt;/kbd&gt; is a default global key
binding.  It’s right there from day one.  No external packages or
Elisp to copy and paste into your init file.  Just vanilla Emacs.&lt;/p&gt;
&lt;h1&gt;Visualisation of whitespace&lt;/h1&gt;
&lt;p&gt;The annoying thing about editing whitespace is that you can’t see it.
I mean, that’s kind of the point, but sometimes you need to know
exactly where it is and how much of it is there.  This is especially
true for some programming languages where whitespace and indentation
are significant to the compiler or interpretter.&lt;/p&gt;
&lt;p&gt;The Emacs developers know this pain all too well, and that’s why we
have &lt;strong&gt;whitespace-mode&lt;/strong&gt;.  It makes it abundantly clear where there
are spaces, tabs and newline characters by highlighting them and
denoting them with certain symbols—a middle dot (&lt;code&gt;·&lt;/code&gt;) for spaces, a
double chevron for tabs (&lt;code&gt;»&lt;/code&gt;), a dollar sign (&lt;code&gt;$&lt;/code&gt;) for newlines.
&lt;small&gt;The symbols shown can be changed or removed, of course—see
&lt;code&gt;whitespace-style&lt;/code&gt; and &lt;code&gt;whitespace-display-mappings&lt;/code&gt;.&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;Trailing whitespace is made particularly obvious because it is
highlighted in red.  Lines longer than &lt;code&gt;whitespace-line-column&lt;/code&gt;
characters (80 by default) are highlighted in yellow.  &lt;small&gt;These
colours may vary by theme.&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;I wouldn’t recommend keeping whitespace mode on at all times because
it makes the rest of the text quite hard to read.  I only enable it
for a moment while I check for stray whitespace, or sometimes when
editing tab-separated data.&lt;/p&gt;
&lt;h1&gt;Display buffer continuously over several windows&lt;/h1&gt;
&lt;p&gt;When I’m learning (or writing) a new piece of music, I like to have
the notes (chords, tabs, lyrics, etc.) for the entire song shown at
one time, if possible.  This way I can play through it from start to
finish without having to pause for scrolling.&lt;/p&gt;
&lt;p&gt;Usually I set it up in a column layout to make the most of the
horizontal screen space.  Emacs is perfect for this because of its
windowing capabilities combined with a minor mode called
&lt;strong&gt;follow-mode&lt;/strong&gt;.  Follow mode shows adjacent screenfuls of the same
buffer across multiple windows, like pages in a book.&lt;/p&gt;
&lt;p&gt;It’s hard to explain, so maybe it’s best to try it for yourself—for
example, by visiting this very page with &lt;kbd&gt;M-x eww&lt;/kbd&gt;.  Create a
side-by-side split using &lt;kbd&gt;C-x 3&lt;/kbd&gt; (&lt;code&gt;split-window-right&lt;/code&gt;), then
do &lt;kbd&gt;M-x follow-mode&lt;/kbd&gt; and try scrolling around.  The window on
the right shows the part of the buffer that immediately follows the
part in the window on the left.&lt;/p&gt;
&lt;h1&gt;Undo only within a region&lt;/h1&gt;
&lt;p&gt;This feature is phenomenal and it’s actually enabled already because
it’s just a nuance of the &lt;code&gt;undo&lt;/code&gt; command.  &lt;small&gt;I don’t know of
any other text editor that can do this.  I believe Vim has “time
travel” history which is cool in its own right, but not quite the
same.&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;Emacs allows you to undo changes that happened in a particular region
of the buffer, without undoing changes elsewhere across it.  Typically
that region will be a range of lines but it doesn’t have to be.&lt;/p&gt;
&lt;p&gt;All you do is select the region of text in which the changes occured,
then invoke &lt;code&gt;undo&lt;/code&gt; as normal (e.g. &lt;kbd&gt;C-/&lt;/kbd&gt;).&lt;/p&gt;
&lt;p&gt;Again, this is something that was right under my nose and for months I
had no idea Emacs could do this—I had never even &lt;em&gt;wondered&lt;/em&gt; if it was
possible; it simply didn’t occur to me.&lt;/p&gt;</description></item>
<item><title>How to Pronounce Any English Word</title>
<author>greg@cosine.blue (Gregory Chamberlain)</author>
<pubDate>Tue, 03 Aug 2021 00:00:00 +0000</pubDate>
<guid>https://cosine.blue/pronounce-any-word-ipa.html</guid>
<description>&lt;p&gt;We’ve all been there.  You’re reading something, maybe out loud, maybe even in front of an audience, and you’re met with some word whose spelling is so irregular and confusing as to incite fear in the hearts of native speakers and language learners alike.  Maybe it has an unreasonable combination of vowels or some weird consonant cluster that looks to be one dollar sign short of being a fairly secure email password.&lt;/p&gt;
&lt;p&gt;With a raised eyebrow and a rising tone, you make a guess or two based loosely on an ever-decaying recollection of primary school heuristics and rules that are supposed to be broken regularly.  English spelling is too fickle for such guesswork!&lt;/p&gt;
&lt;p&gt;Towards the end of secondary school and beginning of sixth form college, I began to take an interest in English phonology—the study of how our language arranges sounds.  While I didn’t exactly go on to become a linguist, I &lt;em&gt;did&lt;/em&gt; come out of it with one little skill that I want to share with you today.  It’s not too difficult to learn and and it solves this problem.  I use it all the time.&lt;/p&gt;
&lt;h1&gt;The International Phonetic Alphabet&lt;/h1&gt;
&lt;p&gt;Anyone who's flicked through a dictionary knows about the funny symbols that describe exactly how words are spoken, but few endeavour to study them.&lt;/p&gt;
&lt;p&gt;While traditional printed dictionaries vary in their choice of phonetic alphabet, the &lt;em&gt;de facto&lt;/em&gt; dictionary of the Internet, &lt;a href="https://wiktionary.org"&gt;Wiktionary&lt;/a&gt;, uses the &lt;abbrev title="International Phonetic Alphabet"&gt;IPA&lt;/abbrev&gt;.  And it tends to have an IPA transcription for just about any English word you’ll come across.  These pieces of phonetic notation tell us exactly what sounds to make and in what order, as well as other things like which syllables should be stressed.&lt;/p&gt;
&lt;p&gt;Of course, many words are pronounced differently throughout English-speaking parts of the world.  In these cases Wiktionary usually lists the main ones—US, Canada, Australia, New Zealand, UK—and sometimes others; the entry for &lt;em&gt;about&lt;/em&gt; has transcriptions for England, Scotland, Ireland, Canada, Virginia and elsewhere in the US.&lt;/p&gt;
&lt;p&gt;Whenever I’m reading and I come across an apparently unpronouncable word, I quickly punch it into Wiktionary and I’m almost always presented with an IPA transcription to fill that gap in my knowledge.  &lt;small&gt;If you use DuckDuckGo, try adding the &lt;code&gt;!wt&lt;/code&gt; bang to redirect your search to Wiktionary.&lt;/small&gt;  After reading the IPA transcription, I always try to say it out loud to myself to be sure, and voilà!  Word learnt.&lt;/p&gt;
&lt;p&gt;The IPA is well suited to English, and learning enough to read transcriptions is not too hard.  16 of the 23 consonant letters are pronounced exactly how you’d expect, and there aren’t more than a dozen or so vowel letters to learn.&lt;/p&gt;
&lt;p&gt;Most IPA transcriptions on Wiktionary are what we call &lt;em&gt;phonemic&lt;/em&gt; transcriptions, so they are delimited by slashes, like /bluː/ for the word &lt;em&gt;blue&lt;/em&gt;.  IPA notation can be written more precisely in the form of &lt;em&gt;phonetic&lt;/em&gt; transcriptions, delimited by square brackets, but we won’t be needing that level of detail.&lt;/p&gt;
&lt;h2&gt;Consonants&lt;/h2&gt;
&lt;p&gt;As I said, most consonants are exactly what you’d expect: /p/, /b/, /t/, /d/, /k/, /ɡ/, /f/, /v/, /s/, /z/, /h/, /m/, /n/, /w/, /r/, and /l/ are pronounced as they typically would be in English.&lt;/p&gt;
&lt;p&gt;Keep in mind that /ɡ/ represents a hard ‘g’ (as in &lt;em&gt;bag&lt;/em&gt;) whereas a soft ‘g’ (as in &lt;em&gt;badge&lt;/em&gt;) is written as /dʒ/, so &lt;em&gt;gadget&lt;/em&gt; is transcribed as /ˈɡædʒɪt/, for example.  This is because the soft ‘g’ is really two phonemes smooshed together—/d/ and /ʒ/ where /ʒ/ represents the sound of &lt;em&gt;s&lt;/em&gt; in &lt;em&gt;measure&lt;/em&gt; (/ˈmɛʒ.ə/) or &lt;em&gt;si&lt;/em&gt; in &lt;em&gt;vision&lt;/em&gt; (/ˈvɪ.ʒ(ə)n/).  We often write them with a curved line over the top to join them together, like /d͡ʒ/ in /ˈɡæd͡ʒɪt/ (&lt;em&gt;gadget&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;Next we have /ʃ/ which is the &lt;em&gt;sh&lt;/em&gt; in &lt;em&gt;fish&lt;/em&gt; (/fɪʃ/).  Analogous to /d͡ʒ/ we have /t/ and /ʃ/ smooshed together to form the sound of &lt;em&gt;tch&lt;/em&gt; in &lt;em&gt;hitch&lt;/em&gt; (/hɪt͡ʃ/) or &lt;em&gt;ch&lt;/em&gt; in &lt;em&gt;choice&lt;/em&gt; (/t͡ʃɔɪs/).&lt;/p&gt;
&lt;p&gt;IPA really only has 4 other consonants that may not be immediately obvious:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;/θ/ representing the &lt;em&gt;th&lt;/em&gt; in &lt;em&gt;thanks&lt;/em&gt; (/θæŋks/)&lt;/li&gt;
&lt;li&gt;/ð/ representing the &lt;em&gt;th&lt;/em&gt; in &lt;em&gt;then&lt;/em&gt; (/ðɛn/)&lt;/li&gt;
&lt;li&gt;/ŋ/ representing the &lt;em&gt;ng&lt;/em&gt; in &lt;em&gt;thing&lt;/em&gt; (/θɪŋ/) or the &lt;em&gt;n&lt;/em&gt; in &lt;em&gt;think&lt;/em&gt; (/θɪŋk/)&lt;/li&gt;
&lt;li&gt;/j/ representing the &lt;em&gt;y&lt;/em&gt; in &lt;em&gt;yes&lt;/em&gt; (/jɛs/)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Vowels&lt;/h2&gt;
&lt;p&gt;Unfortunately, the IPA letters for vowels are not quite as straightforward as for consonants.  To make matters worse, pronunciation of vowel sounds varies wildly between dialects.&lt;/p&gt;
&lt;p&gt;Below are the vowels which are basically the same for &lt;abbrev title="Received Pronunciation"&gt;RP&lt;/abbrev&gt; (a kind of “standard” British English), US and Canada:&lt;/p&gt;
&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;/ɑ/ as in &lt;em&gt;f&lt;strong&gt;a&lt;/strong&gt;ther&lt;/em&gt;&lt;/td&gt;
      &lt;td&gt;/u/ as in &lt;em&gt;s&lt;strong&gt;oo&lt;/strong&gt;n&lt;/em&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;/æ/ as in &lt;em&gt;tr&lt;strong&gt;a&lt;/strong&gt;p&lt;/em&gt;&lt;/td&gt;
      &lt;td&gt;/ə/ as in &lt;em&gt;comm&lt;strong&gt;a&lt;/strong&gt;&lt;/em&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;/ɪ/ as in &lt;em&gt;k&lt;strong&gt;i&lt;/strong&gt;t&lt;/em&gt;&lt;/td&gt;
      &lt;td&gt;/eɪ/ as in &lt;em&gt;f&lt;strong&gt;a&lt;/strong&gt;ce&lt;/em&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;/ʌ/ as in &lt;em&gt;str&lt;strong&gt;u&lt;/strong&gt;t&lt;/em&gt;&lt;/td&gt;
      &lt;td&gt;/aɪ/ as in &lt;em&gt;pr&lt;strong&gt;i&lt;/strong&gt;ce&lt;/em&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;/ʊ/ as in &lt;em&gt;f&lt;strong&gt;oo&lt;/strong&gt;t&lt;/em&gt;&lt;/td&gt;
      &lt;td&gt;/ɔɪ/ as in &lt;em&gt;b&lt;strong&gt;oy&lt;/strong&gt;&lt;/em&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;/ɛ/ as in &lt;em&gt;b&lt;strong&gt;e&lt;/strong&gt;d&lt;/em&gt;&lt;/td&gt;
      &lt;td&gt;/aʊ/ as in &lt;em&gt;m&lt;strong&gt;ou&lt;/strong&gt;th&lt;/em&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;/i/ as in &lt;em&gt;happ&lt;strong&gt;y&lt;/strong&gt;&lt;/em&gt;&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;For RP speakers, /ɒ/ is the vowel that occurs in words like &lt;em&gt;lot&lt;/em&gt; and &lt;em&gt;stop&lt;/em&gt;. The same is true for some Canadian, Australian and New Zealand speakers.  Canadian speakers also use /ɒ/ for words like &lt;em&gt;law&lt;/em&gt; and &lt;em&gt;caught&lt;/em&gt; and some use it for &lt;em&gt;father&lt;/em&gt; and &lt;em&gt;palm&lt;/em&gt; too.&lt;/p&gt;
&lt;p&gt;The vowel in words like &lt;em&gt;know&lt;/em&gt; and &lt;em&gt;hope&lt;/em&gt; are transcribed as /əʊ/ for RP and /oʊ/ for US and Canada.&lt;/p&gt;
&lt;p&gt;Finally we have /ɔ/ which is found in words like &lt;em&gt;law&lt;/em&gt; and &lt;em&gt;caught&lt;/em&gt; in RP and some US dialects.&lt;/p&gt;
&lt;p&gt;Particularly in British, Australian and New Zealand dialects you’ll often see a triangular colon following some vowels, like /ɑː/ in /ˈfɑːðə(r)/ (&lt;em&gt;father&lt;/em&gt;) or /uː/ in /ʃuːz/ (&lt;em&gt;shoes&lt;/em&gt;).  This symbol just means that the preceding vowel is elongated but honestly you can usually ignore it.&lt;/p&gt;
&lt;p&gt;There are a few other vowels like /ɜː/ (RP) or /ɜr/ (US) as in /nɜːs/ (RP) or /nɜrs/ (US) (&lt;em&gt;nurse&lt;/em&gt;) but these are quite rare.&lt;/p&gt;
&lt;h2&gt;Stress&lt;/h2&gt;
&lt;p&gt;English is one language where stress is semantically significant—for example, what’s the difference between /ˈkɒnkriːt/ and /kɒnˈkriːt/?  These are both ways of saying &lt;em&gt;concrete&lt;/em&gt;, but the first is a building material and the second is an adjective meaning “not abstract.”&lt;/p&gt;
&lt;p&gt;Stress is indicated with a stress mark (ˈ) placed before the syllable that should be stressed.  It looks an awful lot like a straight apostrophe (') but I promise it’s not.  Sometimes you’ll see the same mark written below the baseline (ˌ), indicating &lt;em&gt;secondary&lt;/em&gt; stress, as in /ˌɛd͡ʒʊˈkeɪʃn/ (&lt;em&gt;education&lt;/em&gt;) or /ˌnɒtwɪðˈstændɪŋ/ (&lt;em&gt;notwithstanding&lt;/em&gt;).&lt;/p&gt;
&lt;h1&gt;Where to go from here&lt;/h1&gt;
&lt;p&gt;Beside each IPA transcription on English Wiktionary you’ll find a link labelled “KEY” to an appendix page called &lt;a href="https://en.wiktionary.org/wiki/Appendix:English_pronunciation"&gt;English pronunciation&lt;/a&gt; which features a more comprehensive and detailed overview of the IPA symbols used on the site.  This is great if you need a quick reminder.  It’s also great if you need to know more about Australian and New Zealand vowels—I haven’t been able to cover those in great detail here since they differ considerably from RP.&lt;/p&gt;
&lt;p&gt;Of course, using Wiktionary requires a computer and an Internet connection and everything, so if you want to do this without all that you’ll need an offline or paper dictionary that features IPA, such as the Oxford English Dictionary.&lt;/p&gt;</description></item>
<item><title>Declarative Package Configuration In 5 Lines of Emacs Lisp</title>
<author>greg@cosine.blue (Gregory Chamberlain)</author>
<pubDate>Fri, 02 Apr 2021 00:00:00 +0000</pubDate>
<guid>https://cosine.blue/emacs-with-package.html</guid>
<description>&lt;p&gt;&lt;a href="https://www.gnu.org/software/emacs/"&gt;GNU Emacs&lt;/a&gt; is a real phenomenon of computing, not least thanks to the
&lt;a href="https://melpa.org" title="MELPA (Milkypostman’s Emacs Lisp Package Archive)"&gt;wealth&lt;/a&gt; of &lt;a href="https://www.gnu.org/philosophy/free-sw.html"&gt;free/libre&lt;/a&gt; packages available.&lt;/p&gt;
&lt;p&gt;Thing is, most of these packages are more like software &lt;em&gt;libraries&lt;/em&gt;
than programmes, having little to no effect out of the box; they
provide all the Lego bricks, but leave it to the user to put them
together.  And like Lego, putting the bricks together is the fun part!
The way we do that is by writing bits of Emacs Lisp.&lt;/p&gt;
&lt;p&gt;For example, here are a few lines of Elisp you could write to
configure one of my favourite packages, &lt;a href="https://github.com/Fuco1/dired-hacks" title="Collection of useful dired additions"&gt;dired-subtree&lt;/a&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-elisp"&gt;(setq dired-subtree-use-backgrounds nil)
(let ((map dired-mode-map))
  (define-key map (kbd &amp;quot;TAB&amp;quot;) #'dired-subtree-cycle)
  (define-key map (kbd &amp;quot;M-^&amp;quot;) #'dired-subtree-remove)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, there is a problem.  What happens when you write a bit of
Elisp to configure a certain package, but that package is not (yet)
installed?  You often get errors about undefined commands, files not
found, and so on.&lt;/p&gt;
&lt;h2&gt;Conditional configuration&lt;/h2&gt;
&lt;p&gt;One way around this is to put package-specific configuration behind a
conditional.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-elisp"&gt;(when (package-installed-p 'dired-subtree)
  (setq dired-subtree-use-backgrounds nil)
  (let ((map dired-mode-map))
    (define-key map (kbd &amp;quot;TAB&amp;quot;) #'dired-subtree-cycle)
    (define-key map (kbd &amp;quot;M-^&amp;quot;) #'dired-subtree-remove)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This works, but what if you want to then go ahead and install all
packages for which you have a conditional configuration?  There is no
record of the names of those packages.&lt;/p&gt;
&lt;p&gt;You could scan through your &lt;code&gt;user-init-file&lt;/code&gt; by eye and manually
install each package by hand using &lt;code&gt;M-x package-install
&lt;i&gt;pkg&lt;/i&gt; RET&lt;/code&gt;.  But that only gets more laborious the more
packages you want to have.&lt;/p&gt;
&lt;h2&gt;Installing packages programmatically&lt;/h2&gt;
&lt;p&gt;A more viable solution is to use a macro that does a similar thing
&lt;em&gt;and&lt;/em&gt; collects the package names into a list variable at the same
time.  That way, you could programmatically install all such packages
by iterating over the list.&lt;/p&gt;
&lt;p&gt;As it happens, such a variable is already defined and documented by
&lt;code&gt;package.el&lt;/code&gt; and it goes by the name &lt;code&gt;package-selected-packages&lt;/code&gt;.
What’s more, there exists a command &lt;code&gt;M-x package-install-selected-packages&lt;/code&gt; that asks the user for approval
before installing them all.  Making use of this variable, our job
becomes very easy.&lt;/p&gt;
&lt;p&gt;Each time this macro is called with the name of some package
&lt;code&gt;&lt;i&gt;pkg&lt;/i&gt;&lt;/code&gt;, we need to do three things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Add &lt;code&gt;&lt;i&gt;pkg&lt;/i&gt;&lt;/code&gt; to &lt;code&gt;package-selected-packages&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Try to &lt;code&gt;require&lt;/code&gt; the package feature;&lt;/li&gt;
&lt;li&gt;If successful, evaluate the &lt;code&gt;body&lt;/code&gt; using &lt;code&gt;progn&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Reproduced below is just 5 (logical) lines of Emacs Lisp sufficient to
define this macro.  I’ve named it &lt;code&gt;with-package&lt;/code&gt;, analogous to the
likes of &lt;code&gt;with-current-buffer&lt;/code&gt;, &lt;code&gt;with-selected-window&lt;/code&gt;, &lt;code&gt;with-editor&lt;/code&gt;,
etc.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-elisp"&gt;(defmacro with-package (package &amp;amp;rest body)
  &amp;quot;Add PACKAGE to ‘package-selected-packages’, then
attempt to ‘require’ PACKAGE and, if successful, 
evaluate BODY.&amp;quot;
  (declare (indent 1))
  `(and (add-to-list 'package-selected-packages ,package)
        (require ,package nil 'noerror)
        (progn ,@body)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;declare&lt;/code&gt; expression is related to code formatting and is not
strictly necessary for the macro to work.  Its purpose is to inform
Emacs that the body of the macro call should be indented by an
additional character.&lt;/p&gt;
&lt;p&gt;Here’s our &lt;code&gt;dired-subtree&lt;/code&gt; example from above, this time in
&lt;code&gt;with-package&lt;/code&gt; form.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-elisp"&gt;(with-package 'dired-subtree
  (setq dired-subtree-use-backgrounds nil)
  (let ((map dired-mode-map))
    (define-key map (kbd &amp;quot;TAB&amp;quot;) #'dired-subtree-cycle)
    (define-key map (kbd &amp;quot;M-^&amp;quot;) #'dired-subtree-remove)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that, even though this is a macro, the name of the package should
be quoted.  Otherwise Emacs treats it as a variable and tries to find
its value, which is not necessarily defined.&lt;/p&gt;
&lt;h2&gt;External solutions&lt;/h2&gt;
&lt;p&gt;All this is to neglect the elephant in the room, a highly popular
package by the name of &lt;a href="https://jwiegley.github.io/use-package/" title="A use-package declaration for simplifying your .emacs"&gt;use-package&lt;/a&gt; which provides a macro of the
same name that does what my little &lt;code&gt;with-package&lt;/code&gt; macro does and lots
more.  For a long time and until recently, my &lt;code&gt;user-init-file&lt;/code&gt; was
scattered with calls to &lt;code&gt;use-package&lt;/code&gt; for the external packages I
employed.&lt;/p&gt;
&lt;p&gt;I even had a little snippet near the top that would install the
&lt;code&gt;use-package&lt;/code&gt; package if it wasn’t present already.  This practice is
almost as popular as the package itself, it seems.&lt;/p&gt;
&lt;p&gt;There are several reasons why I ditched &lt;code&gt;use-package&lt;/code&gt; in favour of
&lt;code&gt;with-package&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;There is a way&lt;/em&gt; to install all packages for which a &lt;code&gt;use-package&lt;/code&gt;
form has been evaluated, but it does not ask interactively for consent
from the user before doing so.  Rather, the packages are installed at
startup without prompt nor warning.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;use-package&lt;/code&gt; is a mighty big package that does &lt;em&gt;way&lt;/em&gt; more than I need
it to do.  Simpler is usually better when you can get away with it.&lt;/p&gt;
&lt;p&gt;Among its more advanced features is a way to selectively defer the
loading of packages until they’re needed, shortening startup times.
That sounds great, but personally I’m happy with my startup time as it
is.&lt;/p&gt;
&lt;p&gt;The last reason is that, honestly, I was rather pleased with myself
after writing this macro.  And if you ask me, DIY programming is what
Emacs is all about.&lt;/p&gt;
&lt;p&gt;So yeah, a 5 line Lisp macro may be all you need to take your
&lt;code&gt;init.el&lt;/code&gt; to the next level.  If this post has inspired you to rip
apart your carefully crafted Emacs configuration as I did mine, do
send an email to &lt;a href="mailto:greg@cosine.blue"&gt;greg@cosine.blue&lt;/a&gt; letting me know.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;I ❤ Emacs!&lt;/p&gt;
&lt;p&gt;The wide-reaching applications of GNU Emacs have slowly invaded my
workflow over the past year and a half, and I have much more to write
about it.  To find out when new Emacs related content emerges on
cosine.blue, subscribe via &lt;a href="/rss.xml"&gt;RSS&lt;/a&gt; or follow me on &lt;a href="https://mastodon.social/@chambln"&gt;Mastodon&lt;/a&gt;.&lt;/p&gt;</description></item>
<item><title>Vanilla Firefox Keyboard Mastery</title>
<author>greg@cosine.blue (Gregory Chamberlain)</author>
<pubDate>Sun, 06 Dec 2020 00:00:00 +0000</pubDate>
<guid>https://cosine.blue/2020-12-06-firefox-keyboard.html</guid>
<description>&lt;small&gt;
  All software packages mentioned in this article
  are &lt;a href="https://www.gnu.org/philosophy/free-sw.html"&gt;free as in
  freedom&lt;/a&gt;.  There is no need to be using proprietary browsers
  these days.
&lt;/small&gt;

&lt;h1&gt;Is it worth the time?&lt;/h1&gt;

&lt;p&gt;Last weekend I carved out half an hour to read Mozilla’s support
page
titled &lt;a href="https://support.mozilla.org/en-US/kb/keyboard-shortcuts-perform-firefox-tasks-quickly"&gt;&lt;cite&gt;Keyboard
shortcuts - Perform common Firefox tasks quickly&lt;/cite&gt;&lt;/a&gt;.  Sounds
boring I know.  But it was time well spent and my only regret is not
having read it sooner (like 5 years sooner).&lt;/p&gt;

&lt;p&gt;Many of the key combinations described therein were familiar
friends of mine, but with others I had no acquaintance.  I won’t lie
to you: a fair number of them are worthless.  But others are essential
for keyboard-only browsing.&lt;/p&gt;

&lt;p&gt;Over the last decade I must have spent ten thousand hours using a
web browser.  And I don’t think I’m an outlier here.  The Web has
steamrolled into the twenty-first century and for better or worse
become the ubiquitous interface through which the world now wants us
to read and write, to listen and speak and to otherwise occupy
ourselves.&lt;/p&gt;

&lt;p&gt;Let’s say you have to use a web browser just once a day on average
for the next 5 years.  According to the chart below, even if you can
shave off 1 measly second from this daily obligation, it is worth your
time to set aside up to 30 minutes today to achieve that daily time
saving.&lt;/p&gt;

&lt;figure&gt;
    &lt;img src="xkcd1205.png" alt="xkcd: Is It Worth the Time?" /&gt;
    &lt;figcaption&gt;
        From xkcd:
        &lt;a href="https://xkcd.com/1205/"&gt;&lt;cite&gt;Is It Worth the Time?&lt;/cite&gt;&lt;/a&gt;
        (&lt;a href="http://creativecommons.org/licenses/by-nc/2.5/"&gt;CC BY-NC 2.5&lt;/a&gt;).
    &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;It takes half a second to move your hand from the typing position
to the mouse (or touch pad or whatever) and another half a second to
point your cursor at the right spot.  Learning a few keyboard
shortcuts will surely shave off a few seconds every now and then.&lt;/p&gt;

&lt;p&gt;You’ve already wasted 2 minutes reading this page and another 3
staring at that incredibly insightful chart so you’d better get
cracking.&lt;/p&gt;

&lt;p&gt;
  I’ve outlined below a few of my favourite shortcuts that comprise my
  general strategy for keyboard-only navigation, which works better on
  some sites than others.  A good site to practise on is Wikipedia
  (or, you know, this one).  In particular, we will eventually get to
  the apostrophe key &lt;kbd&gt;'&lt;/kbd&gt; which enables lightning fast link
  following and makes the whole experience much smoother.
&lt;/p&gt;

&lt;p&gt;
  You won’t need to go digging through any settings or configuration
  files to try these; they are built into Firefox and enabled by
  default.
&lt;/p&gt;

&lt;p&gt;
  Learning to use the keyboard as much as possible can be really
  beneficial to your efficiency and ergonomics when using a computer
  because it is profoundly more expressive and reliable than any
  pointing device.  If you’re looking to become more proficient with
  keyboard-driven software but not ready to learn something like Vim
  or Emacs then this article might be a good stepping stone.
&lt;/p&gt;

&lt;small&gt;Mozilla have made some
&lt;a href="https://blog.mozilla.org/blog/2020/02/25/firefox-continues-push-to-bring-dns-over-https-by-default-for-us-users/"&gt;increasingly&lt;/a&gt;
&lt;a href="https://arstechnica.com/information-technology/2020/08/firefox-maker-mozilla-lays-off-250-workers-says-covid-19-lowered-revenue/"&gt;questionable&lt;/a&gt;
&lt;a href="http://calpaterson.com/mozilla.html"&gt;decisions&lt;/a&gt;
&lt;a href="https://vpn.mozilla.org/"&gt;lately&lt;/a&gt;, but there are a few
&lt;a href="https://unixsheikh.com/articles/choose-your-browser-carefully.html"&gt;privacy-respecting alternatives&lt;/a&gt;
such as &lt;a href="https://www.gnu.org/software/gnuzilla/"&gt;GNU Icecat&lt;/a&gt;
and &lt;a href="https://www.torproject.org/"&gt;Tor Browser&lt;/a&gt;
which are based on Firefox and have all the same keyboard
shortcuts.&lt;/small&gt;

&lt;h1&gt;The basics&lt;/h1&gt;

&lt;p&gt;
  Obviously you can scroll the page screenful-by-screenful
  using &lt;kbd&gt;PgUp&lt;/kbd&gt; and &lt;kbd&gt;PgDn&lt;/kbd&gt;.  When the page is in
  focus, &lt;kbd&gt;Space&lt;/kbd&gt; and &lt;kbd&gt;Shift&lt;/kbd&gt; + &lt;kbd&gt;Space&lt;/kbd&gt; do
  the same and are more accessible from the home position on full size
  keyboards. The vertical arrows
  keys &lt;kbd&gt;&amp;uarr;&lt;/kbd&gt; &lt;kbd&gt;&amp;darr;&lt;/kbd&gt; are best reserved for
  making fine adjustments to the viewport.  For jumping to the
  beginning and end of the page, use &lt;kbd&gt;Home&lt;/kbd&gt;
  and &lt;kbd&gt;End&lt;/kbd&gt;.
&lt;/p&gt;

&lt;p&gt;
  &lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;Tab&lt;/kbd&gt; and its &lt;kbd&gt;Shift&lt;/kbd&gt;ed
  equivalent are not unheard of even among novice computer users, but
  holding &lt;kbd&gt;Alt&lt;/kbd&gt; and hitting &lt;kbd&gt;1&lt;/kbd&gt;&amp;ndash;&lt;kbd&gt;8&lt;/kbd&gt;
  to immediately switch to the corresponding tab will surely impress
  on-lookers.  If you need to switch quickly between adjacent tabs,
  try &lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;PgUp&lt;/kbd&gt; and &lt;kbd&gt;Ctrl&lt;/kbd&gt;
  + &lt;kbd&gt;PgDn&lt;/kbd&gt;.
&lt;/p&gt;

&lt;p&gt;You probably know &lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;w&lt;/kbd&gt; closes
  the current tab but did you know &lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;Shift&lt;/kbd&gt;
  + &lt;kbd&gt;W&lt;/kbd&gt; closes the current window?  Also essential
  are &lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;t&lt;/kbd&gt; to open a new tab and crucially
  &lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;Shift&lt;/kbd&gt; + &lt;kbd&gt;T&lt;/kbd&gt;
  to &lt;em&gt;restore&lt;/em&gt; that tab you really wish you hadn’t closed.
&lt;/p&gt;

&lt;p&gt;
  Continuing the &lt;kbd&gt;Shift&lt;/kbd&gt; key theme, I think most people are
  familiar with &lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;r&lt;/kbd&gt; to refresh the
  page&amp;mdash;but hold &lt;kbd&gt;Shift&lt;/kbd&gt; to clean the cache while doing
  so.
&lt;/p&gt;

&lt;p&gt;
  Of course there are shortcuts like &lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;h&lt;/kbd&gt;
  and &lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;b&lt;/kbd&gt; to open the history and bookmarks
  sidebars, but in practice I rarely use these&amp;mdash;instead I use
  &lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;l&lt;/kbd&gt; or &lt;kbd&gt;Alt&lt;/kbd&gt; + &lt;kbd&gt;d&lt;/kbd&gt; to
  bring the address bar into focus and begin searching through history
  and bookmarks right there.  &lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;d&lt;/kbd&gt;, however,
  is really handy for quickly throwing the current page into your
  bookmarks list&amp;mdash;you can then &lt;kbd&gt;Tab&lt;/kbd&gt;
  and &lt;kbd&gt;Shift&lt;/kbd&gt; + &lt;kbd&gt;Tab&lt;/kbd&gt; around the little dialogue
  window to make adjustments.
&lt;/p&gt;

&lt;p&gt;
  As with most graphical applications, you can generally ‘tab around’
  between UI elements and hyperlinks with &lt;kbd&gt;Tab&lt;/kbd&gt;
  and &lt;kbd&gt;Shift&lt;/kbd&gt; + &lt;kbd&gt;Tab&lt;/kbd&gt;.  This is a cumbersome and
  frustrating way of getting around but it is often necessary.  It can
  be tempting to rely on this in Firefox but think of it as a last
  resort.  In the next section we will learn some faster techniques.
&lt;/p&gt;

&lt;h1&gt;Quick find and navigation&lt;/h1&gt;

You may know you can hold &lt;kbd&gt;Alt&lt;/kbd&gt; and use the horizontal arrow
keys &lt;kbd&gt;&amp;larr;&lt;/kbd&gt; &lt;kbd&gt;&amp;rarr;&lt;/kbd&gt; to go back and forward.  Make
sure you’re comfortable using them as they’ll become somewhat
important later.

&lt;p&gt;Everybody knows &lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;f&lt;/kbd&gt; launches the
familiar &lt;em&gt;find in page&lt;/em&gt; rigmarole, and there is certainly a
time and a place for its case sensitive and whole word matching.  But
in most cases all you need is &lt;em&gt;quick find&lt;/em&gt;.  Hit forward
slash &lt;kbd&gt;/&lt;/kbd&gt; to begin.  It works much the same but is less
annoying because it soon gets out of your way; you can still
hold &lt;kbd&gt;Ctrl&lt;/kbd&gt; and hit &lt;kbd&gt;g&lt;/kbd&gt; and &lt;kbd&gt;Shift&lt;/kbd&gt;
+ &lt;kbd&gt;G&lt;/kbd&gt; to jump between matches, but when you do something else
like press &lt;kbd&gt;Tab&lt;/kbd&gt; or &lt;kbd&gt;Enter&lt;/kbd&gt;, or even just pause for
a few moments, the bar slides away and page focus is restored.  I
often use this to get back to where I was reading by quick-searching
for the short string of words I last read.  You can always upgrade to
the fully-featured find-in-page mode by hitting &lt;kbd&gt;Ctrl&lt;/kbd&gt;
+ &lt;kbd&gt;f&lt;/kbd&gt;.&lt;/p&gt;

&lt;small&gt;By the way, wherever you see an underlined letter in a menu,
that means you can hold &lt;kbd&gt;Alt&lt;/kbd&gt; and hit the corresponding key
to activate it.  Try toggling &lt;q&gt;Whole Words&lt;/q&gt; matching in the
find-in-page bar using &lt;kbd&gt;Alt&lt;/kbd&gt; + &lt;kbd&gt;w&lt;/kbd&gt;&lt;/small&gt;

&lt;p&gt;
  Finally we are ready to meet the apostrophe key &lt;kbd&gt;'&lt;/kbd&gt;.  This
  puts you into the same kind of quick search prompt,
  but &lt;strong&gt;results are limited to links only&lt;/strong&gt;.  This
  is &lt;em&gt;magical&lt;/em&gt;.  By using &lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;g&lt;/kbd&gt;
  and &lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;Shift&lt;/kbd&gt; + &lt;kbd&gt;G&lt;/kbd&gt; to jump
  between matches and &lt;kbd&gt;Enter&lt;/kbd&gt; to follow them, interspersed
  with the &lt;kbd&gt;Alt&lt;/kbd&gt; plus arrow key combos mentioned earlier, you
  can zip around between web pages at light speed with a modicum of
  keystrokes.
&lt;/p&gt;

&lt;p&gt;
  If you follow the wrong link and react before it loads, quickly
  reach for &lt;kbd&gt;Esc&lt;/kbd&gt; to cancel it.  If you’re too late, remember
  there’s always &lt;kbd&gt;Alt&lt;/kbd&gt; + &lt;kbd&gt;&amp;larr;&lt;/kbd&gt; to go back.
&lt;/p&gt;

&lt;p&gt;
  When following a focused link with &lt;kbd&gt;Enter&lt;/kbd&gt;, you can
  hold &lt;kbd&gt;Ctrl&lt;/kbd&gt; to make it open in a new tab.  It won’t switch
  to that new tab immediately though; to do that use &lt;kbd&gt;Ctrl&lt;/kbd&gt;
  + &lt;kbd&gt;Shift&lt;/kbd&gt; + &lt;kbd&gt;Enter&lt;/kbd&gt; instead.
&lt;/p&gt;

&lt;p&gt;
  These key commands are great and all, but some rely on &lt;em&gt;page
  focus&lt;/em&gt;; when the address bar or other UI element has keyboard
  focus, shortcuts like &lt;kbd&gt;/&lt;/kbd&gt; and &lt;kbd&gt;'&lt;/kbd&gt; become
  inaccessible.  Well, get used to hitting &lt;kbd&gt;F6&lt;/kbd&gt; to bring
  focus back to the page itself&amp;mdash;you should see a thin black and
  white dotted rectangle surrounding the page viewport to indicate
  page focus.
  &lt;small&gt;
    Frustratingly &lt;kbd&gt;F6&lt;/kbd&gt; actually &lt;em&gt;toggles&lt;/em&gt; focus
    between page and address bar so you can’t always be certain you’ll
    end up with one or the other without having first hit,
    say, &lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;l&lt;/kbd&gt; or looking for focus clues
    afterwards.
  &lt;/small&gt;
&lt;/p&gt;

&lt;h1&gt;A word for the wizards&lt;/h1&gt;

&lt;p&gt;
  Now, an elite minority among you will no doubt be laughing away from
  the comfort of one of those Vi-like modal keyboard layer add-ons
  that grant you web browsing super powers and sing and dance and brew
  your coffee at the same time.  They’re fantastic and I’ve been
  there.  There are even standalone browsers designed around this
  idea, and they certainly can be worth the time investment.
  &lt;small&gt;
    See add-ons &lt;a href="https://krabby.netlify.app/"&gt;Krabby&lt;/a&gt;
    and &lt;a href="https://github.com/philc/vimium"&gt;Vimium&lt;/a&gt;;
    standalone browsers &lt;a href="https://qutebrowser.org"&gt;Qutebrowser&lt;/a&gt;,
    &lt;a href="https://luakit.github.io/"&gt;Luakit&lt;/a&gt;,
    &lt;a href="https://nyxt.atlas.engineer/"&gt;Nyxt Browser&lt;/a&gt;,
    &lt;a href="https://fanglingsu.github.io/vimb/"&gt;Vimb&lt;/a&gt;,
    even &lt;a href="http://surf.suckless.org/"&gt;surf&lt;/a&gt;
    with &lt;a href="http://tools.suckless.org/tabbed/"&gt;tabbed&lt;/a&gt; and
    the right combination of patches; and
    &lt;a href="https://github.com/alexherbo2/krabby/blob/master/docs/alternatives.md"&gt;many
    others&lt;/a&gt;.  Also worth mentioning are terminal and text-based
    browsers such
    as &lt;a href="https://lynx.browser.org/"&gt;lynx&lt;/a&gt;, &lt;a href="http://w3m.sourceforge.net/"&gt;w3m&lt;/a&gt;
    and &lt;a href="https://www.gnu.org/software/emacs/manual/eww.html"&gt;EWW&lt;/a&gt;.
  &lt;/small&gt;
  But there are reasons to (and times when you have no choice but to)
  revert to the bog standard, vanilla, &lt;em&gt;de facto&lt;/em&gt; tool.
&lt;/p&gt;

&lt;p&gt;
  Also, those keyboard-centric browsers have steep learning curves.
  They can be dauntingly unfamiliar to new users and behave in
  unexpected ways to begin with.  On the other hand, picking up some
  of the keyboard-driven techniques outlined above doesn’t mean
  throwing everything you know about your browser out the window.
&lt;/p&gt;</description></item>
<item><title>Rudimentary Parsing with Idiomatic POSIX Shell</title>
<author>greg@cosine.blue (Gregory Chamberlain)</author>
<pubDate>Tue, 08 Sep 2020 00:00:00 +0000</pubDate>
<guid>https://cosine.blue/2020-09-08-posix-read.html</guid>
<description>&lt;h1&gt;POSIX shell idioms&lt;/h1&gt;
&lt;p&gt;You sit down before your obnoxiously clacky mechanical keyboard and
bang out the familiar &lt;code&gt;#!/bin/sh&lt;/code&gt; with that precious sense of optimism
like writing the first words in a new notebook: the margins are
aligned and you begin to think that your handwriting isn’t so bad
after all.  Soon enough, though, it’s riddled with scribbled out
paragraphs and arrows that swing around the pages.&lt;/p&gt;
&lt;p&gt;Maintaining safe and bug-free shell scripts can become troublesome as
they grow in complexity, and limiting one’s craft only to those few
blessed features defined by
&lt;abbrev title="Portable operating system interface"&gt;POSIX&lt;/abbrev&gt;
only amplifies that.&lt;/p&gt;
&lt;p&gt;However, what is lost in flexibility is &lt;a href="#portability"&gt;gained in
portability&lt;/a&gt;.  With some casual experimentation and a
handful
of powerful idioms, perhaps the purely POSIX shell language
can prove more elegant and expressive than it is given credit for.&lt;/p&gt;
&lt;p&gt;What follows are three ways to use one such idiom: the
&lt;cite&gt;read&lt;/cite&gt;(1)-while loop.&lt;/p&gt;
&lt;h1&gt;The &lt;cite&gt;read&lt;/cite&gt;(1) builtin&lt;/h1&gt;
&lt;p&gt;Built into any POSIX compatible shell is the
&lt;a href="https://pubs.opengroup.org/onlinepubs/9699919799/utilities/read.html"&gt;&lt;cite&gt;read&lt;/cite&gt;&lt;/a&gt;(1)
command.&lt;/p&gt;
&lt;blockquote&gt;read [-r] &lt;i&gt;var&lt;/i&gt;…&lt;/blockquote&gt;
&lt;p&gt;In its most basic usage, it can be used to gather a line of input from
the user at the terminal; that might be to answer a yes/no prompt, or
to provide a text string.  But more versatile is its ability to parse
text files in a rudimentary but reliable way.&lt;/p&gt;
&lt;p&gt;The &lt;cite&gt;read&lt;/cite&gt;(1) command always consumes exactly one line of
text—that’ll be from standard input or whatever you pipe or redirect
into it.  When it hits &lt;abbrev title="End of file"&gt;EOF&lt;/abbrev&gt; it
fails.  &lt;small&gt;EOF stands for
&lt;a href="https://en.wikipedia.org/wiki/End-of-file"&gt;end-of-file&lt;/a&gt; and marks the
end of a file or data stream.&lt;/small&gt; So, the general pattern is to
call &lt;cite&gt;read&lt;/cite&gt;(1) repeatedly until it fails.&lt;/p&gt;
&lt;p&gt;Below is a really simple example which simply prints each line read.
The entire content of each line, except the terminating newline
character, is assigned to the &lt;code&gt;line&lt;/code&gt; variable.  We set the &lt;abbrev
title="Internal field separator"&gt;&lt;code&gt;IFS&lt;/code&gt;&lt;/abbrev&gt; to the empty string to
prevent field splitting.  &lt;small&gt;It’s conventional to call the
variable &lt;code&gt;line&lt;/code&gt;, but really you can call it anything you like.&lt;/small&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sh"&gt;while IFS= read -r line
do printf '%s\n' &amp;quot;$line&amp;quot;
done
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;small&gt;Unless you know what you’re doing, you probably want to pass
the &lt;code&gt;-r&lt;/code&gt; option; its effect is described in the &lt;a href="https://pubs.opengroup.org/onlinepubs/9699919799/utilities/read.html"&gt;POSIX Programmer’s
Manual&lt;/a&gt;.&lt;/small&gt;
Beware that &lt;cite&gt;read&lt;/cite&gt;(1) still fails if a non-empty line is
missing its newline character before EOF, so the loop will not be
entered for that final line.  The solution is to check for emptiness
in the event that read fails&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sh"&gt;while IFS= read -r line || [ &amp;quot;$line&amp;quot; ]
do …
done
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;but you may instead prefer to assume that the input is well
formed—&lt;a href="https://en.wikipedia.org/wiki/Garbage_in,_garbage_out"&gt;garbage in, garbage
out&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;Case study 1 of 3: Linewise filtering&lt;/h1&gt;
&lt;p&gt;Let’s say we want to remove lines that begin with a hash sign
(#)—something akin to &lt;code&gt;grep -v ^\#&lt;/code&gt;.  This can be achieved with the
&lt;code&gt;#*&lt;/code&gt; glob pattern in a case statement.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sh"&gt;while IFS= read -r line
do
    case $line in
        \#*) ;;
        *) printf '%s\n' &amp;quot;$line&amp;quot;
    esac
done
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;small&gt;The backslash escape in &lt;code&gt;\#*&lt;/code&gt; is necessary to protect the hash
sign from becoming a shell comment.  &lt;/small&gt; Pattern matching each
line like this is a powerful way to interpret file contents.  Let’s
also ignore leading white space:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sh"&gt;while IFS= read -r line
do
    case ${line#${line%%[![:space:]]*}} in
        \#*) ;;
        *) printf '%s\n' &amp;quot;$line&amp;quot;
    esac
done &amp;lt;&amp;lt;EOF
one
# two
  # three
  four
EOF
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The precise workings of this parameter expansion wizardry is described
in &lt;a href="https://dylan.k1ss.org/"&gt;Dylan Arap&lt;/a&gt;’s excellent
&lt;a href="https://github.com/dylanaraps/pure-sh-bible#trim-leading-and-trailing-white-space-from-string"&gt;pure-sh-bible&lt;/a&gt;,
but understanding it is not necessary going forward—just know that it
expands to the value of &lt;code&gt;line&lt;/code&gt; stripped of any leading white space.
This time I fed it a &lt;a href="https://en.wikipedia.org/wiki/Here_document"&gt;here
document&lt;/a&gt;, resulting in
the following two lines being printed:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;one
  four
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;Case study 2 of 3: Key-value pairs&lt;/h1&gt;
&lt;p&gt;Let’s now try to parse a file consisting of lines of the form
&lt;code&gt;key=value&lt;/code&gt; where key contains no equals signs and value can be
anything at all.&lt;/p&gt;
&lt;p&gt;For this we set the &lt;code&gt;IFS&lt;/code&gt; to the equals sign and pass two variable
names as arguments to &lt;cite&gt;read&lt;/cite&gt;(1).&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sh"&gt;while IFS='=' read -r key value
do printf 'Key ‘%s’ has value ‘%s’.\n' &amp;quot;$key&amp;quot; &amp;quot;$value&amp;quot;
done &amp;lt;&amp;lt;EOF
name=banana
type=fruit
colour=yellow
EOF
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Setting &lt;code&gt;IFS='='&lt;/code&gt; tells &lt;cite&gt;read&lt;/cite&gt;(1) to split the line into
fields at every equals sign.  Since we named only two variables (&lt;code&gt;key&lt;/code&gt;
and &lt;code&gt;value&lt;/code&gt;) to assign fields to, any fields right of the second are
merged into &lt;code&gt;value&lt;/code&gt;. In other words, &lt;em&gt;all&lt;/em&gt; characters after the first
equals sign are considered part of the &lt;code&gt;value&lt;/code&gt;, so no quoting or
escaping is necessary.&lt;/p&gt;
&lt;p&gt;Running the above code results in the following output:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Key ‘name’ has value ‘banana’.
Key ‘type’ has value ‘fruit’.
Key ‘colour’ has value ‘yellow’.
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;Case study 3 of 3: User’s full name&lt;/h1&gt;
&lt;p&gt;Since the original Unix the fifth field of a user’s &lt;cite&gt;passwd&lt;/cite&gt;(5) record
has been the &lt;a href="https://en.wikipedia.org/wiki/Gecos_field"&gt;GECOS field&lt;/a&gt;
where users’ contact information is stored.  Here’s mine:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ grep ^$USER: /etc/passwd
greg:x:1000:1000:Gregory Chamberlain,,,:/home/greg:/bin/bash
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Among the colon-separated fields, you can see that my full name is the
first of four comma-separated values within the
&lt;abbrev title="General Comprehensive Operating System"&gt;GECOS&lt;/abbrev&gt;
field.  &lt;small&gt;Many desktop operating systems ask for your full name
during installation or when adding a new user and that’s where it’s
stored.  If not, try
&lt;a href="https://manpages.debian.org/stable/passwd/chfn.1.en.html"&gt;&lt;cite&gt;chfn&lt;/cite&gt;&lt;/a&gt;(1)
or just (carefully!) edit the /etc/passwd directly as root.&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;Assigning the first field to &lt;code&gt;user&lt;/code&gt; and the fifth to &lt;code&gt;gecos&lt;/code&gt;, we use
underscores in place of the other fields which we don’t care about.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sh"&gt;while IFS=: read -r user _ _ _ gecos _
do [ x&amp;quot;$user&amp;quot; = x&amp;quot;$USER&amp;quot; ] &amp;amp;&amp;amp; name=&amp;quot;${gecos%%,*}&amp;quot;
done &amp;lt; /etc/passwd
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Don’t be tempted to move the &lt;code&gt;&amp;lt; /etc/passwd&lt;/code&gt; file redirection closer
to the read statement; it needs to feed into the while loop itself so
that it progresses over successive lines.&lt;/p&gt;
&lt;p&gt;After reading each line, the resulting values of &lt;code&gt;user&lt;/code&gt; and &lt;code&gt;USER&lt;/code&gt; are
tested for equality.  &lt;small&gt;It’s important to protect arbitrary
strings from &lt;cite&gt;[&lt;/cite&gt;(1) options parsing by prefixing each with
any ol’ character, in this case &lt;code&gt;x&lt;/code&gt;—otherwise &lt;code&gt;$user&lt;/code&gt; could expand to
something like &lt;code&gt;-z&lt;/code&gt; and cause an error.  &lt;/small&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sh"&gt;[ x&amp;quot;$user&amp;quot; = x&amp;quot;$USER&amp;quot; ]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If the two match, then we know we are looking at the right line and so
we begin parsing the &lt;code&gt;gecos&lt;/code&gt; string for a &lt;code&gt;name&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sh"&gt;name=&amp;quot;${gecos%%,*}&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can’t use the same &lt;cite&gt;read&lt;/cite&gt;(1) trick again because we
already absorbed the line.  Anyway, we’re only interested in the first
field so we can just use a greedy suffix pattern in the expansion of
&lt;code&gt;gecos&lt;/code&gt;.  You can read about &lt;em&gt;Parameter expansion&lt;/em&gt; in
&lt;a href="https://manpages.debian.org/stable/dash/dash.1.en.html"&gt;&lt;cite&gt;dash&lt;/cite&gt;&lt;/a&gt;(1)
for the details but in short &lt;code&gt;%%,*&lt;/code&gt; means &lt;q&gt;remove everything after
the first comma.&lt;/q&gt;&lt;/p&gt;
&lt;p&gt;Below is a short script that illustrates how this could be integrated
into a larger program. I’ve also thrown in a &lt;cite&gt;read&lt;/cite&gt;(1)
command that prompts interactively for a name if one is not found,
demonstrating how &lt;cite&gt;read&lt;/cite&gt;(1) can be used outside of a loop
as well.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sh"&gt;#!/bin/sh
while IFS=: read -r user _ _ _ gecos _
do [ x&amp;quot;$user&amp;quot; = x&amp;quot;$USER&amp;quot; ] &amp;amp;&amp;amp; name=&amp;quot;${gecos%%,*}&amp;quot;
done &amp;lt; /etc/passwd

if [ &amp;quot;$name&amp;quot; ]
then
    printf 'Your real name is %s.\n' &amp;quot;$name&amp;quot;
else
    printf 'What’s your name? '
    IFS= read -r name
    printf 'Hello %s!\n' &amp;quot;$name&amp;quot;
fi
&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id="portability"&gt;Reasons not to use Bash&lt;/h1&gt;
&lt;p&gt;Most prominently, Bash scripts are not portable.
From Drew Devaults’s &lt;a href="https://drewdevault.com/2018/02/05/Introduction-to-POSIX-shell.html"&gt;&lt;cite&gt;Introduction to POSIX
shell&lt;/cite&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;q&gt;Any shell that utilizes features specific to Bash are not
portable, which means you cannot take them with you to any other
system.  […]  This is bad if your users wish to utilize your
software anywhere other than GNU/Linux.  If your build tooling
utilizes bashisms, your software will not build on anything but
GNU/Linux.  If you ship runtime scripts that use bashisms, your
software will not &lt;em&gt;run&lt;/em&gt; on anything but GNU/Linux.&lt;/q&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;He goes on to argue that&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;q&gt;you should stick to POSIX shell for your personal scripts, too.
You might not care now, but when you feel like flirting with other
Unicies you’ll thank me when all of your scripts work.&lt;/q&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Also, Bash is monstrously complex; even &lt;a href="https://manpages.debian.org/stable/bash/bash.1.en.html"&gt;its man
page&lt;/a&gt;
confesses it’s &lt;q&gt;too big and too slow.&lt;/q&gt; And let’s not forget
&lt;a href="https://en.wikipedia.org/wiki/Shellshock_%28software_bug%29"&gt;Shellshock&lt;/a&gt;,
the arbitrary code execution vulnerability in Bash responsible for
&lt;a href="https://blog.cloudflare.com/inside-shellshock/"&gt;millions of attacks&lt;/a&gt;
on web-facing servers.&lt;/p&gt;
&lt;h1&gt;See also&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html"&gt;&lt;cite&gt;Shell Command
Language&lt;/cite&gt;&lt;/a&gt;—part
of the POSIX specification published by The Open Group.&lt;/li&gt;
&lt;li&gt;Dylan Arap’s &lt;a href="https://github.com/dylanaraps/pure-sh-bible"&gt;&lt;cite&gt;pure sh
bible&lt;/cite&gt;&lt;/a&gt;, the sacred
holy text for disciples of purely POSIX shell scripting.  See also his
&lt;a href="https://github.com/dylanaraps/pash"&gt;&lt;em&gt;pash&lt;/em&gt;&lt;/a&gt;,
&lt;a href="https://github.com/dylanaraps/pfetch"&gt;&lt;em&gt;pfetch&lt;/em&gt;&lt;/a&gt; and
&lt;a href="https://github.com/dylanaraps/shfm"&gt;&lt;em&gt;shfm&lt;/em&gt;&lt;/a&gt;.  All MIT licensed.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.etalabs.net/sh_tricks.html"&gt;&lt;cite&gt;Rich’s sh (POSIX shell)
tricks&lt;/cite&gt;&lt;/a&gt; clears up
common misconceptions and pitfalls.&lt;/li&gt;
&lt;li&gt;Comprehensive &lt;a href="https://www.grymoire.com/Unix/Sh.html"&gt;&lt;cite&gt;POSIX Shell
Tutorial&lt;/a&gt; by the Grymoire.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://chris-lamb.co.uk/posts/joining-strings-in-posix-shell"&gt;&lt;cite&gt;Joining strings in POSIX
shell&lt;/cite&gt;&lt;/a&gt; by Chris Lamb.&lt;/li&gt;
&lt;/ul&gt;</description></item>
<item><title>How I Merged 36 Spreadsheets In 2 Minutes—LibreOffice on the
Command-Line</title>
<author>greg@cosine.blue (Gregory Chamberlain)</author>
<pubDate>Sat, 28 Mar 2020 00:00:00 +0000</pubDate>
<guid>https://cosine.blue/2020-03-28-libreoffice-concatenate.html</guid>
<description>&lt;h1&gt;A troublesome task&lt;/h1&gt;
&lt;p&gt;In a recent project, I found myself tasked with the laborious feat of
painstakingly joining together tables, hundreds of thousands of rows
each, from several years of new-file-every-month spreadsheets—by hand.&lt;/p&gt;
&lt;p&gt;At that moment, my human eyeballs were paused hovering, mouse hopelessly
scrolling past millions of cells; a bleak air beset the white walls of
my otherwise cozy student flat on that mild March morning.&lt;/p&gt;
&lt;p&gt;I soon gathered up my pessimism until it amounted to what you might call
a stubborn sort of frustration-fueled optimism and looked for a better
way.&lt;/p&gt;
&lt;h1&gt;A simple solution&lt;/h1&gt;
&lt;p&gt;Naturally, I reached for my office suite’s documentation. Although
LibreOffice is primarily a graphical application, its little-known
command-line features can be life saving. A leisurely perusal of its man
page armed me with the &lt;code&gt;--convert-to&lt;/code&gt; option, which does what you’re
thinking.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;libreoffice --convert-to csv ./*.ods
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Some ten billion CPU cycles later—a few seconds in mammal time—I had
trivialised a daunting task that otherwise would have threatened my
lunch break. My thirty-something spreadsheets were now thirty-something
CSV files, leaving only to concatenate them.&lt;/p&gt;
&lt;p&gt;Of course, CSV is not a spreadsheet format. Any formulas, comments,
charts and other media would be lost in this process. Fortunately for
me, these spreadsheets were just holding raw data.&lt;/p&gt;
&lt;p&gt;Each had its first five rows reserved for useless metadata (title and
time period), and the sixth for table headings; the remainder were the
dreaded data. Using sed(1) I was able to extract only the sixth row and
concatenate the data of all CSV files onto that, writing it to
&lt;code&gt;result.csv&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(
    sed -n 6p ./*.csv      # Print the table headings line;
    for i in ./*.csv; do   # For each CSV file,
        sed 1,6d &amp;quot;$i&amp;quot;      # print its contents except lines 1-6;
    done
) &amp;gt; result.csv             # Write that to result.csv.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With just a few simple commands, I had a single well-formed CSV file
holding &lt;em&gt;all&lt;/em&gt; the data, ready to be imported into LibreOffice or
indeed into R or Python or what have you. I needn’t have even fumbled
for the mouse.&lt;/p&gt;
&lt;h1&gt;Potential complications&lt;/h1&gt;
&lt;p&gt;Throughout that process, I was working under the assumption that each
spreadsheet was written the same way—five rows of information I don’t
care about, the same 10 or so table headings on the sixth row followed
by data and only data as far as the eye can scroll.&lt;/p&gt;
&lt;p&gt;The presence of stray cells or breaking changes to the overall design or
nature of data gatherment in the past few years could have rendered my
monstrous CSV a totally meaningless muddle of words and numbers riddled
with silly mistakes (like many of my assignments).&lt;/p&gt;
&lt;p&gt;In an effort to justify this assumption, I did poke around in some of
the spreadsheets at regular intervals until I was confident it was all
in the same format.&lt;/p&gt;
&lt;h1&gt;More terminal trickery&lt;/h1&gt;
&lt;p&gt;There are other things LibreOffice can do programmatically. For example,
you could print a huge batch of documents to PDF&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;--print-to-file&lt;/strong&gt; [&lt;strong&gt;--printer-name&lt;/strong&gt; &lt;em&gt;printer_name&lt;/em&gt;]
[&lt;strong&gt;--outdir&lt;/strong&gt; &lt;em&gt;output_dir&lt;/em&gt;] &lt;em&gt;file&lt;/em&gt;…&lt;/p&gt;
&lt;p&gt;Batch print files to file. If &lt;strong&gt;--printer-name&lt;/strong&gt; is not specified
the default printer is used. If &lt;strong&gt;--outdir&lt;/strong&gt; is not specified then
the current working directory is used as the output directory for the
converted files.&lt;/p&gt;
&lt;p&gt;Examples:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;--print-to-file *.doc
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Prints all .doc files to the current working directory using the
default printer.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;or onto actual paper.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;-p&lt;/strong&gt; &lt;em&gt;file&lt;/em&gt;…&lt;/p&gt;
&lt;p&gt;Prints the given files to the default printer and ends. The splash
screen does not appear.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;LibreOffice also has a flexible macro system for manipulating
spreadsheets and text documents with Java, Python, JavaScript, or its
own flavour of Basic—although documentation seems limited.&lt;/p&gt;
&lt;p&gt;While the &lt;code&gt;--convert-to&lt;/code&gt; option may not be groundbreaking, and there
may well be other viable solutions, I was pleasantly surprised to find
such functionality in an office suite. I’d be interested to hear of
praiseworthy command-line support in other graphical applications;
send me an email via &lt;a href="mailto:greg@cosine.blue"&gt;greg@cosine.blue&lt;/a&gt; if you know of any.&lt;/p&gt;</description></item>
<item><title>The Vim-Inspired Editor with a Linguistic Twist</title>
<author>greg@cosine.blue (Gregory Chamberlain)</author>
<pubDate>Fri, 06 Sep 2019 00:00:00 +0000</pubDate>
<guid>https://cosine.blue/2019-09-06-kakoune.html</guid>
<description>&lt;h1&gt;What is Kakoune?&lt;/h1&gt;
&lt;p&gt;&lt;a href="http://kakoune.org/"&gt;Kakoune&lt;/a&gt; (/kə'kuːn/) describes itself as &lt;q&gt;a code
editor heavily inspired by Vim&lt;/q&gt;, and like the venerable &lt;em&gt;vi&lt;/em&gt;(1) and its
successor, its internal model interprets the user’s keystrokes like
utterances of a sort-of &lt;q&gt;text-editing language&lt;/q&gt;, but with a certain
linguistic twist (more on that later). Available—for reasons that will
later become clear—only on Unix-like systems, it was written in C++ by
&lt;a href="https://github.com/mawww"&gt;Maxime Coste&lt;/a&gt;, has a clean &lt;a href="https://github.com/mawww/kakoune"&gt;code
base&lt;/a&gt; and runs like the wind in a
terminal. It is released under the Unlicense, which is &lt;a href="https://www.gnu.org/licenses/license-list.html#Unlicense"&gt;compatible with
the GPL&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;small&gt;Skip ahead to &lt;a href="#using-kakoune"&gt;Using Kakoune&lt;/a&gt; if you just
want to get stuck in right way.&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;As a long time Vim user, Kakoune quickly piqued my interest and before
long I was convinced that it was the editor for me, and not just because
it’s incredibly obscure. Its grammatical reshuffle and wise design
principles put it above the rest for me, and I’m starting to think it’s
more than just a comfy nook in which to hide from the large and looming
cold hand of Emacs, the curious GNUisance (sorry) that swings
periodically over my shoulder whispering &lt;q&gt;we have Org mode! And Lisp!&lt;/q&gt;
Maybe next year, Emacs. I really want to like you.&lt;/p&gt;
&lt;p&gt;But that’s an &lt;a href="rss.xml" title="Subscribe to
cosine.blue via RSS feed"&gt;essay for another day&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here I endeavour to introduce the reader to Kakoune and present my
thoughts on its merits and misfits in the context of a terminal-based,
keyboard-driven workflow. I make frequent comparisons to Vim, and the
reader would benefit from some experience with a modal editor such
thereas. That said, those uninitiated in modal editors might find that
Kakoune’s forgiving mechanics place it among the easier to learn.&lt;/p&gt;
&lt;h1&gt;Do we really need another Vim clone?&lt;/h1&gt;
&lt;p&gt;This is neither a fork nor clone.&lt;/p&gt;
&lt;p&gt;In an effort to provide incremental results and interactivity (words
whose meaning became clear once I met the &lt;kbd&gt;s&lt;/kbd&gt; key), the
&lt;q&gt;selection-oriented code editor&lt;/q&gt; takes a bold step away from some of
the Vim interactions familiar to many of us, while remaining competitive
keystroke-for-keystroke, millisecond-for-precious-millisecond.&lt;/p&gt;
&lt;p&gt;Its author cites the Unix philosophy as one of Kakoune’s virtues, and
certainly I would agree that it trumps Vim in adherence thereto
(examples of this to come); and that is not to say it lacks enough
features. Indeed it has built-in wrappers around Git, &lt;em&gt;grep&lt;/em&gt;, &lt;em&gt;make&lt;/em&gt;,
and &lt;em&gt;man&lt;/em&gt;, works with ctags, conforming linters and other things.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://asciinema.org/a/0MLTST9LQYdJ6JNQvmSsaBV7U"&gt;Screencast: browsing man pages in
Kakoune&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Vim is difficult to extend, not least because of the idiosyncratic
train wreck of a language that is VimL (or Vim Script, or
whatever). Conversely, Kakoune stands by its decision not to complicate
its language with flow control and whatnot, and instead relies on
languages we already know through its &lt;code&gt;%sh{…}&lt;/code&gt; blocks. And although
Kakoune is very usable out-of-the-box, one look at the &lt;a href="https://kakoune.org/plugins.html"&gt;plugins
page&lt;/a&gt; is enough to make any purist
cave.&lt;/p&gt;
&lt;small&gt;
  You can even whip some Perl or Ruby or anything you like into
  an &lt;code&gt;%sh{…}&lt;/code&gt; block; in fact&amp;mdash;that’s how some of the
  more complex plugins are built.
&lt;/small&gt;
&lt;h2&gt;So what’s the twist?&lt;/h2&gt;
&lt;p&gt;Whereas vi’s keystroke language follows &lt;strong&gt;verb-object&lt;/strong&gt; order, Kakoune
inverts that by following &lt;strong&gt;object-verb&lt;/strong&gt; order. In real terms, that
means you make a selection (object) before deciding what to do (verb)
with it. The object might be a character, word, sentence, paragraph,
parenthetical, regular expression, you name it; the verb might be
&lt;strong&gt;delete&lt;/strong&gt;, &lt;strong&gt;yank&lt;/strong&gt; (copy), &lt;strong&gt;change&lt;/strong&gt;, &lt;strong&gt;indent&lt;/strong&gt;, or even
transformative operations like &lt;strong&gt;lint&lt;/strong&gt;, &lt;strong&gt;format&lt;/strong&gt;, &lt;strong&gt;uppercase&lt;/strong&gt;, etc.
In Kakoune, it is with this reversed grammar, this postfix notation,
that you interactively sweep up a group or groups of characters before
acting on them. That way if your object isn’t quite right, you can
immediately correct it without having to undo and redo your verb.&lt;/p&gt;
&lt;p&gt;I like to think Kakoune’s &lt;q&gt;keystrokes as a text editing language&lt;/q&gt; model,
in comparison to that of vi, is what linguists would call an
&lt;em&gt;&lt;a href="https://en.wikipedia.org/wiki/Anastrophe"&gt;anastrophe&lt;/a&gt;&lt;/em&gt;—specifically an
object-verb inversion.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src="barn-swallow.jpg" alt="Photo of a barn swallow" /&gt;
  &lt;figcaption&gt;
    &lt;small&gt;
      &lt;a href="https://commons.wikimedia.org/wiki/File:BarnSwallow_cajay.jpg"&gt;Photo&lt;/a&gt;
      by &lt;a href="https://commons.wikimedia.org/wiki/User:Cajay"&gt;JJ
      Cadiz&lt;/a&gt;, &lt;a href="https://creativecommons.org/licenses/by/3.0/deed.en"&gt;CC
      BY-SA 3.0&lt;/a&gt;.
    &lt;/small&gt;
    Subject-object-verb order can be seen in this anastrophic idiom,
    &lt;q&gt;one swallow does not a summer make.&lt;/q&gt;
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;To English speakers, it might seem unnatural to place the verb last,
but about 45% of documented natural languages have subject-object-verb
order, including Latin, Ancient Greek, Japanese and Korean.&lt;/p&gt;
&lt;h2&gt;Isn’t that just Vim’s visual mode?&lt;/h2&gt;
&lt;p&gt;Well, yes, but Vim’s visual mode is a malformed afterthought in
comparison, and you have to hit &lt;kbd&gt;v&lt;/kbd&gt; every time you want to use
it. Kakoune is visual mode done right, but not just that; it permits—nay
thrives on—multiple selections (thousands if you wish but typically just
a few) and provides some really neat tools to narrow them down
incrementally, &lt;a href="#narrowing"&gt;as we’ll see later&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This paradigm shift necessitated a revised set of key mappings, which
Kakoune implements rather well if you don’t mind using
&lt;kbd&gt;Alt&lt;/kbd&gt;. Holding &lt;kbd&gt;Shift&lt;/kbd&gt; means causes the usual motion
keys to &lt;em&gt;extend&lt;/em&gt; the selection, so unlike in Vim, traversing
whitespace-separated words means holding &lt;kbd&gt;Alt&lt;/kbd&gt; instead.  And
what about text objects? How do you select in and around words,
parenthetical pairs, paragraphs, and so on? In Vim you begin by
hitting &lt;kbd&gt;v&lt;/kbd&gt; to enter visual mode followed by &lt;kbd&gt;a&lt;/kbd&gt; or
&lt;kbd&gt;i&lt;/kbd&gt;. In Kakoune, however, normal mode &lt;em&gt;is&lt;/em&gt; visual mode so
instead &lt;kbd&gt;Alt&lt;/kbd&gt; + &lt;kbd&gt;a&lt;/kbd&gt; and
&lt;kbd&gt;Alt&lt;/kbd&gt; + &lt;kbd&gt;i&lt;/kbd&gt; are used to avoid conflict with the
normal meanings of &lt;kbd&gt;a&lt;/kbd&gt; and &lt;kbd&gt;i&lt;/kbd&gt; (append and insert).&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;English&lt;/th&gt;
      &lt;th&gt;Vim&lt;/th&gt;
      &lt;th&gt;Kakoune&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Delete word&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;dw&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;wd&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Delete up to whitespace&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;dW&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;&amp;lt;a-w&amp;gt;d&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Delete inner word&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;diw&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;&amp;lt;a-i&amp;gt;wd&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Delete back four words&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;d4b&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;BBBBd or4Bd&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Change to end of word&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;ce&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;ec&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Yank a sentence&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;yas&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;&amp;lt;a-a&amp;gt;sy&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Change to next occurrence of ‘x’&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;ctx&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;txc&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Select to next occurrence of ‘x’&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;vtx&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;tx&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Indent three lines down&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;3&amp;gt;&amp;gt;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;xXX&amp;gt;&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Unindent within braces&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;&amp;lt;i}&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;&amp;lt;a-i&amp;gt;}&amp;lt;&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
  &lt;caption&gt;
    Keystroke idioms in Kakoune and compared to Vim.
  &lt;/caption&gt;
&lt;/table&gt;
&lt;p&gt;Admittedly, from the table above, my new favourite editor looks to be
more complicated than Vim. Perhaps that’s true in some sense, but
Kakoune’s strengths lie in its forgiving interactivity and incremental
results, which are best experienced first hand.&lt;/p&gt;
&lt;h1 id='using-kakoune'&gt;Using Kakoune&lt;/h1&gt;
&lt;p&gt;At this point, I encourage the reader to play around with Kakoune. Have
fun with it! Install it with your package manager or build it from
&lt;a href="https://github.com/mawww/kakoune"&gt;source&lt;/a&gt;. Skim over the manual page
for &lt;em&gt;kak&lt;/em&gt;(1) and open a file in the terminal like so&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;kak example.cc
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Make sure your terminal emulator supports alt key combinations and isn’t
overriding them.&lt;/p&gt;
&lt;p&gt;Have a look through &lt;code&gt;:doc faq&lt;/code&gt;, &lt;code&gt;:doc keys&lt;/code&gt; (then &lt;code&gt;:doc keymap&lt;/code&gt; for the
cheat sheet), and &lt;code&gt;:doc commands&lt;/code&gt;, experimenting as you go. That said,
the built-in help system is verbose and won’t exactly hold your hand.
The &lt;a href="https://github.com/mawww/kakoune/wiki"&gt;Kakoune wiki&lt;/a&gt; is more
navigable, and &lt;a href="https://github.com/mawww/kakoune/blob/master/contrib/TRAMPOLINE"&gt;this
walkthrough&lt;/a&gt;
is particularly helpful for learning the basics. You can edit files and
manipulate buffers with the following commands&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;:edit &amp;lt;filename&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:buffer &amp;lt;name&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:buffer-next&lt;/code&gt; and &lt;code&gt;:buffer-previous&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Use &lt;code&gt;:delete-buffer&lt;/code&gt; to delete a buffer. Write to disk with &lt;code&gt;:w&lt;/code&gt; and
quit with &lt;code&gt;:q&lt;/code&gt;. As you enter commands, you’ll see an ASCII art Clippy
show up in a box with the relevant documentation. Commands are
self-documenting, and many have a &lt;code&gt;-docstring&lt;/code&gt; argument in their
definition which enriches these info boxes.&lt;/p&gt;
&lt;p&gt;Depending on your terminal colours, things might be unreadable. If so,
or otherwise, pick a colour scheme using the &lt;code&gt;:colorscheme &amp;lt;name&amp;gt;&lt;/code&gt;
command. Try not to spend too many of your precious Earth seconds
fussing over which is best, as I did.&lt;/p&gt;
&lt;p&gt;Kakoune shares a good deal of elementary keys with Vim, which eases
the learning curve for veterans thereof. Of the lowercase letters,
only &lt;kbd&gt;s&lt;/kbd&gt;, &lt;kbd&gt;z&lt;/kbd&gt;, &lt;kbd&gt;x&lt;/kbd&gt;, &lt;kbd&gt;v&lt;/kbd&gt; and
&lt;kbd&gt;m&lt;/kbd&gt; have completely new jobs. Hitting the &lt;kbd&gt;a&lt;/kbd&gt; key,
&lt;kbd&gt;i&lt;/kbd&gt; or &lt;kbd&gt;o&lt;/kbd&gt; or their shifted equivalents will enter
insert mode in much the same way as in vi;
&lt;kbd&gt;Shift&lt;/kbd&gt; + &lt;kbd&gt;Q&lt;/kbd&gt; and &lt;kbd&gt;q&lt;/kbd&gt; handle macros; press
&lt;kbd&gt;u&lt;/kbd&gt; to undo (some will rejoice it’s
&lt;kbd&gt;Shift&lt;/kbd&gt; + &lt;kbd&gt;U&lt;/kbd&gt;, not
&lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;r&lt;/kbd&gt;, to redo); I could go on. As you’d
expect, many motion keys accept counts, as in
&lt;kbd&gt;4&lt;/kbd&gt; &lt;kbd&gt;w&lt;/kbd&gt; to traverse four words.&lt;/p&gt;
&lt;h2&gt;Motions&lt;/h2&gt;
&lt;p&gt;Get the hang of using motions—&lt;kbd&gt;h&lt;/kbd&gt;, &lt;kbd&gt;j&lt;/kbd&gt;,
&lt;kbd&gt;k&lt;/kbd&gt;, &lt;kbd&gt;l&lt;/kbd&gt;, &lt;kbd&gt;w&lt;/kbd&gt;, &lt;kbd&gt;e&lt;/kbd&gt;, &lt;kbd&gt;b&lt;/kbd&gt;,
&lt;kbd&gt;f&lt;/kbd&gt; and &lt;kbd&gt;t&lt;/kbd&gt; for starters—and their majuscule
equivalents; hold shift to extend the selection you already have; hit
&lt;kbd&gt;;&lt;/kbd&gt; to reset the selection range back to the cursor
itself. Then of course &lt;kbd&gt;r&lt;/kbd&gt;, &lt;kbd&gt;d&lt;/kbd&gt; and &lt;kbd&gt;c&lt;/kbd&gt; are
your destructive verbs, while &lt;kbd&gt;~&lt;/kbd&gt;, &lt;kbd&gt;`&lt;/kbd&gt;,
&lt;kbd&gt;&amp;lt;&lt;/kbd&gt; and &lt;kbd&gt;&amp;gt;&lt;/kbd&gt; are transformative; &lt;kbd&gt;i&lt;/kbd&gt;,
&lt;kbd&gt;a&lt;/kbd&gt;, &lt;kbd&gt;o&lt;/kbd&gt; and &lt;kbd&gt;Shift&lt;/kbd&gt; + &lt;kbd&gt;O&lt;/kbd&gt;
respect the selection range (try it to see what I mean), as do
&lt;kbd&gt;y&lt;/kbd&gt; (yank/copy) and &lt;kbd&gt;p&lt;/kbd&gt; (paste). Try combining some
of these with &lt;kbd&gt;Alt&lt;/kbd&gt; and see what happens. Try
&lt;kbd&gt;Alt&lt;/kbd&gt; + &lt;kbd&gt;i&lt;/kbd&gt; or &lt;kbd&gt;Alt&lt;/kbd&gt; + &lt;kbd&gt;a&lt;/kbd&gt; and
read the info box to see what you can do with them; same goes for
&lt;kbd&gt;[&lt;/kbd&gt; and &lt;kbd&gt;]&lt;/kbd&gt;, and their shifted equivalents
&lt;kbd&gt;{&lt;/kbd&gt; and &lt;kbd&gt;}&lt;/kbd&gt; which, predictably, extend the
selection.&lt;/p&gt;
&lt;p&gt;Press &lt;kbd&gt;g&lt;/kbd&gt; and you’ll see the ‘goto’ menu, which shows you the
handful of keys that could complete the key-stroke sequence. Familiarise
yourself with some of these.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;q&gt;Go to …&lt;/q&gt;&lt;/th&gt;
      &lt;th&gt;Vim&lt;/th&gt;
      &lt;th&gt;Kakoune&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Top of buffer&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;g&lt;/kbd&gt;, &lt;kbd&gt;g&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;g&lt;/kbd&gt;, &lt;kbd&gt;g&lt;/kbd&gt; or &lt;kbd&gt;g&lt;/kbd&gt;, &lt;kbd&gt;k&lt;/kbd&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;End of line&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;$&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;g&lt;/kbd&gt;, &lt;kbd&gt;l&lt;/kbd&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Beginning of line&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;0&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;g&lt;/kbd&gt;, &lt;kbd&gt;h&lt;/kbd&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;First non-blank character&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;^&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;g&lt;/kbd&gt;, &lt;kbd&gt;i&lt;/kbd&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Bottom of buffer&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;G&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;g&lt;/kbd&gt;, &lt;kbd&gt;j&lt;/kbd&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;End of buffer&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;G&lt;/kbd&gt;, &lt;kbd&gt;$&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;g&lt;/kbd&gt;, &lt;kbd&gt;e&lt;/kbd&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Top of window&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;H&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;g&lt;/kbd&gt;, &lt;kbd&gt;t&lt;/kbd&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Bottom of window&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;L&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;g&lt;/kbd&gt;, &lt;kbd&gt;b&lt;/kbd&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Centre of window&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;M&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;g&lt;/kbd&gt;, &lt;kbd&gt;c&lt;/kbd&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Last (alternate) buffer&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;^&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;g&lt;/kbd&gt;, &lt;kbd&gt;a&lt;/kbd&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Path under cursor / in selection&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;g&lt;/kbd&gt;, &lt;kbd&gt;f&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;g&lt;/kbd&gt;, &lt;kbd&gt;f&lt;/kbd&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Same goes for &lt;kbd&gt;v&lt;/kbd&gt; and the ‘view’ menu, which is for adjusting
your viewport into the buffer.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;q&gt;View …&lt;/q&gt;&lt;/th&gt;
      &lt;th&gt;Vim&lt;/th&gt;
      &lt;th&gt;Kakoune&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Centre cursor vertically&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;z&lt;/kbd&gt;, &lt;kbd&gt;z&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;v&lt;/kbd&gt;, &lt;kbd&gt;v&lt;/kbd&gt; or &lt;kbd&gt;v&lt;/kbd&gt;, &lt;kbd&gt;c&lt;/kbd&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Centre cursor horizontally&lt;/td&gt;
      &lt;td&gt;Nope(*)&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;v&lt;/kbd&gt;, &lt;kbd&gt;m&lt;/kbd&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Cursor on top&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;z&lt;/kbd&gt;, &lt;kbd&gt;t&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;v&lt;/kbd&gt;, &lt;kbd&gt;t&lt;/kbd&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Cursor on bottom&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;z&lt;/kbd&gt;, &lt;kbd&gt;b&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;v&lt;/kbd&gt;, &lt;kbd&gt;b&lt;/kbd&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Scroll left&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;z&lt;/kbd&gt;, &lt;kbd&gt;h&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;v&lt;/kbd&gt;, &lt;kbd&gt;h&lt;/kbd&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Scroll down&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;e&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;v&lt;/kbd&gt;, &lt;kbd&gt;j&lt;/kbd&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Scroll up&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;y&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;v&lt;/kbd&gt;, &lt;kbd&gt;k&lt;/kbd&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Scroll right&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;z&lt;/kbd&gt;, &lt;kbd&gt;l&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;v&lt;/kbd&gt;, &lt;kbd&gt;l&lt;/kbd&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;small&gt;
  (*) The closest approximations I can find are
  &lt;kbd&gt;z&lt;/kbd&gt;, &lt;kbd&gt;H&lt;/kbd&gt; and &lt;kbd&gt;z&lt;/kbd&gt;, &lt;kbd&gt;L&lt;/kbd&gt; to scroll
  half a screen width horizontally. Or there’s &lt;code&gt;set
  sidescrolloff=999&lt;/code&gt;.
&lt;/small&gt;
&lt;h2&gt;Multiple selections&lt;/h2&gt;
&lt;p&gt;Pressing &lt;kbd&gt;x&lt;/kbd&gt; selects a whole line, &lt;kbd&gt;x&lt;/kbd&gt; again the
next instead; or hold shift and see that &lt;kbd&gt;X&lt;/kbd&gt; sweeps up
multiple lines. Here’s where things get cool: sweep up a few lines
with &lt;kbd&gt;X&lt;/kbd&gt; or &lt;kbd&gt;Alt&lt;/kbd&gt; + &lt;kbd&gt;i&lt;/kbd&gt;, &lt;kbd&gt;p&lt;/kbd&gt; and
then press &lt;kbd&gt;Alt&lt;/kbd&gt; + &lt;kbd&gt;s&lt;/kbd&gt;. That splits the selection
&lt;em&gt;linewise&lt;/em&gt; into multiple selections. Another way to accrue selections
is using &lt;kbd&gt;Shift&lt;/kbd&gt; + &lt;kbd&gt;C&lt;/kbd&gt; or
&lt;kbd&gt;Alt&lt;/kbd&gt; + &lt;kbd&gt;Shift&lt;/kbd&gt; + &lt;kbd&gt;C&lt;/kbd&gt;. Play around with
these yourself. If things get out of hand you can hit &lt;kbd&gt;Space&lt;/kbd&gt;
to reset to one selection.&lt;/p&gt;
&lt;h3&gt;Aligning columns interactively&lt;/h3&gt;
&lt;p&gt;This is one case where multiple selections are your best friend. You
just make your selections and hit &lt;kbd&gt;&amp;amp;&lt;/kbd&gt; to align them
vertically.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://asciinema.org/a/EiuIMgYNAPSdGYzdP2bsmt0ZF"&gt;Screencast: aligning columns
interactively&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="narrowing"&gt;Narrowing&lt;/h3&gt;
&lt;p&gt;Still think multiple selections are a gimmick? So did I. Until I tried
some of the narrowing mechanisms. What do I mean by that? Well, let’s
say you want to replace all occurrences of ‘sir’ with ‘mate’ inside a
particular paragraph. With your cursor situated somewhere within it,
you’d press &lt;kbd&gt;Alt&lt;/kbd&gt; + &lt;kbd&gt;i&lt;/kbd&gt;, &lt;kbd&gt;p&lt;/kbd&gt; to select the
whole paragraph, then (and this is the good bit)&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;kbd&gt;s&lt;/kbd&gt;, &lt;kbd&gt;s&lt;/kbd&gt;, &lt;kbd&gt;i&lt;/kbd&gt;, &lt;kbd&gt;r&lt;/kbd&gt;, &lt;kbd&gt;Enter&lt;/kbd&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;to select each occurrence of ‘sir’. Now you have multiple selections.
Finally you’d type&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;kbd&gt;c&lt;/kbd&gt;, &lt;kbd&gt;m&lt;/kbd&gt;, &lt;kbd&gt;a&lt;/kbd&gt;, &lt;kbd&gt;t&lt;/kbd&gt;, &lt;kbd&gt;e&lt;/kbd&gt;,
&lt;kbd&gt;Esc&lt;/kbd&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;to change each into ‘mate’.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://asciinema.org/a/r0mCpLIWpF2LiFg5d0qlWPlTb"&gt;Screencast: Incremental search and
replace&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To achieve the same in Vim you’d need to specify the line range of the
paragraph in an ex command (perhaps with the help of visual mode,
i.e. &lt;kbd&gt;v&lt;/kbd&gt;, &lt;kbd&gt;i&lt;/kbd&gt;, &lt;kbd&gt;p&lt;/kbd&gt;), and provide the ‘g’ flag.
In Kakoune, everything is achieved with the keyboard-based &lt;q&gt;text-editing
language&lt;/q&gt; and as a result is more interactive in that it provides
incremental results so that you can make corrections on the fly.&lt;/p&gt;
&lt;p&gt;You &lt;em&gt;can&lt;/em&gt; enter a regular expression (see &lt;code&gt;:doc regex&lt;/code&gt;) into the
&lt;kbd&gt;s&lt;/kbd&gt; command, but often simple key-stroke-based interactions
thereafter can achieve the same effect while being easier to come up
with and adjust as you go. As a contrived example, imagine trying to
replace the word that comes immediately &lt;em&gt;after&lt;/em&gt; every occurrence of a
pattern.&lt;/p&gt;
&lt;p&gt;A commonly used technique is to press &lt;kbd&gt;%&lt;/kbd&gt; which selects the
entire buffer. Then you can hit &lt;kbd&gt;s&lt;/kbd&gt; to select occurrences of
some pattern throughout the file. The information in the bottom right
keeps count of how many selections you have.&lt;/p&gt;
&lt;p&gt;The &lt;kbd&gt;%&lt;/kbd&gt;, &lt;kbd&gt;Alt&lt;/kbd&gt; + &lt;kbd&gt;s&lt;/kbd&gt; combo is useful for
operating linewise on entire files. For example,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;kbd&gt;%&lt;/kbd&gt;, &lt;kbd&gt;Alt&lt;/kbd&gt; + &lt;kbd&gt;s&lt;/kbd&gt;,
&lt;kbd&gt;Alt&lt;/kbd&gt; + &lt;kbd&gt;k&lt;/kbd&gt;, &lt;kbd&gt;i&lt;/kbd&gt;, &lt;kbd&gt;n&lt;/kbd&gt;,
&lt;kbd&gt;c&lt;/kbd&gt;, &lt;kbd&gt;l&lt;/kbd&gt;, &lt;kbd&gt;u&lt;/kbd&gt;, &lt;kbd&gt;d&lt;/kbd&gt;, &lt;kbd&gt;e&lt;/kbd&gt;,
&lt;kbd&gt;Enter&lt;/kbd&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;will select all lines that contain the word ‘include’; or using
&lt;kbd&gt;Alt&lt;/kbd&gt; + &lt;kbd&gt;Shift&lt;/kbd&gt; + &lt;kbd&gt;K&lt;/kbd&gt; we can do&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;kbd&gt;%&lt;/kbd&gt;, &lt;kbd&gt;Alt&lt;/kbd&gt; + &lt;kbd&gt;s&lt;/kbd&gt;,
&lt;kbd&gt;Alt&lt;/kbd&gt; + &lt;kbd&gt;Shift&lt;/kbd&gt; + &lt;kbd&gt;K&lt;/kbd&gt;, &lt;kbd&gt;:&lt;/kbd&gt;,
&lt;kbd&gt;$&lt;/kbd&gt;, &lt;kbd&gt;Return&lt;/kbd&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;to select all lines that don’t end with a colon. We could then do&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;kbd&gt;Alt&lt;/kbd&gt; + &lt;kbd&gt;k&lt;/kbd&gt;, &lt;kbd&gt;^&lt;/kbd&gt;,
&lt;kbd&gt;d&lt;/kbd&gt;, &lt;kbd&gt;e&lt;/kbd&gt;, &lt;kbd&gt;f&lt;/kbd&gt;, &lt;kbd&gt;Enter&lt;/kbd&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;to narrow down further to only those that begin with ‘def’. Follow that
up with an &lt;kbd&gt;S&lt;/kbd&gt; key like so:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;kbd&gt;S&lt;/kbd&gt;, &lt;kbd&gt;\&lt;/kbd&gt;, &lt;kbd&gt;.&lt;/kbd&gt;, &lt;kbd&gt;Enter&lt;/kbd&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;to split each selection at every period. As you can see, the narrowing
tools are immensely powerful and the possibilities endless. And if
you’re still not satisfied, there’s the &lt;kbd&gt;$&lt;/kbd&gt; key which filters
your selections by piping each one through any program you like and
keeping only those for which the program exists successfully—meaning you
could always write a little shell script to be the predicate of that
filter.&lt;/p&gt;
&lt;h2&gt;Changes through external programs&lt;/h2&gt;
&lt;p&gt;Don’t get too excited about &lt;kbd&gt;$&lt;/kbd&gt; before you’ve met
&lt;kbd&gt;|&lt;/kbd&gt;.  This key is your program-wielding text-processing
glue. The idea is that you make your selection(s) in Kakoune, type
something of the form&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;|program args ...&amp;lt;ret&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and watch the magic happen. For each selection, Kakoune feeds it as
standard input to the program, and replaces it with the standard output.&lt;/p&gt;
&lt;small&gt;
  &lt;code&gt;&amp;lt;ret&amp;gt;&lt;/code&gt; refers to the Enter or Return key. See
  &lt;code&gt;:doc mapping&lt;/code&gt; for more key names like this.
&lt;/small&gt;
&lt;h3&gt;Word count and formatting&lt;/h3&gt;
&lt;p&gt;Starting with a simple example, you could select the entire buffer
with &lt;kbd&gt;%&lt;/kbd&gt;, then run it through &lt;em&gt;wc&lt;/em&gt;(1) to get a word count of
your prose:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;%|wc -w&amp;lt;ret&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or pipe it first through the appropriate
&lt;em&gt;&lt;a href="https://pandoc.org/"&gt;pandoc&lt;/a&gt;&lt;/em&gt;(1) command to convert it to plain text,
thereby eliding markup from your word count:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;%|pandoc -t plain|wc -w&amp;lt;ret&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or you could select a paragraph and pipe that through to &lt;em&gt;fmt&lt;/em&gt;(1) or
&lt;em&gt;par&lt;/em&gt;(1), which are programs that nicely reflow paragraphs of text from
standard input. This is why Kakoune seems to lack important features
such as text reflowing; instead it makes it easy to delegate this sort
of processing to other programs, thereby adhering a little closer to the
Unix philosophy.&lt;/p&gt;
&lt;h3&gt;Evaluating code within the buffer&lt;/h3&gt;
&lt;p&gt;If your buffer contained a Python expression, say&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-python"&gt;factorial = lambda n: 1 if n&amp;lt;1 else n*factorial(n-1)
print(factorial(13) + factorial(16))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;then you could select those lines and pipe it into &lt;em&gt;python&lt;/em&gt;(1) by typing
&lt;code&gt;|python&amp;lt;ret&amp;gt;&lt;/code&gt;, leaving you with &lt;code&gt;20929016908800&lt;/code&gt; as the
selection.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://asciinema.org/a/0BHzz6J9fTVDKhfhKeRsLgG43"&gt;Screencast: Piping the selection through
Python&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The &lt;kbd&gt;!&lt;/kbd&gt; key does the same but without piping anything
through to the program: it simply copies the output of the program
into the buffer. For instance, &lt;code&gt;!ls&amp;lt;ret&amp;gt;&lt;/code&gt; will add a list of the
contents of the current directory before the selection. &lt;code&gt;!cat example.sh&amp;lt;ret&amp;gt;&lt;/code&gt; will add the lines of the file &lt;code&gt;example.sh&lt;/code&gt; before
the selection.&lt;/p&gt;
&lt;h3&gt;Inserting Emoji&lt;/h3&gt;
&lt;p&gt;Use &lt;kbd&gt;Shift&lt;/kbd&gt; + &lt;kbd&gt;|&lt;/kbd&gt; to conveniently pipe words like
‘smile’ 😄 and ‘house’ 🏠 to a program that converts stdin to emoji,
like this one liner:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;#!/bin/sh
xargs -r printf ':%s:' | pandoc -f gfm -t plain
&lt;/code&gt;&lt;/pre&gt;
&lt;small&gt;
    The &lt;code&gt;-r&lt;/code&gt; option is a GNU extension.
&lt;/small&gt;
&lt;p&gt;Maybe Pandoc is overkill here, but you get the point.&lt;/p&gt;
&lt;h3&gt;Using the system clipboard&lt;/h3&gt;
&lt;p&gt;Piping to and from &lt;em&gt;xsel&lt;/em&gt;(1) or &lt;em&gt;xclip&lt;/em&gt;(1) is your interface to the X
clipboard. Now you can copy those snippets from Stack Overflow and feed
your cargo cult programming habit.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th style="text-align: left;"&gt;Primary selection&lt;/th&gt;
&lt;th style="text-align: left;"&gt;Clipboard&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="odd"&gt;
&lt;td&gt;&lt;strong&gt;Copy&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;code&gt;$xsel -i&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;code&gt;$xsel -bi&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="even"&gt;
&lt;td&gt;&lt;strong&gt;Cut&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;code&gt;|xsel -i&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;code&gt;|xsel -bi&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="odd"&gt;
&lt;td&gt;&lt;strong&gt;Paste&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;code&gt;!xsel&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;code&gt;!xsel -b&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1&gt;User configuration&lt;/h1&gt;
&lt;h2&gt;Mapping keys&lt;/h2&gt;
&lt;p&gt;Of course, you can create key mappings for these things to your heart’s
content. Nice thing about Kakoune is it has a proper way of keeping
&lt;em&gt;user&lt;/em&gt;-specific mappings separate from &lt;em&gt;global&lt;/em&gt; mappings, thanks to the
scope parameter of &lt;code&gt;:map&lt;/code&gt;. By default &lt;kbd&gt;,&lt;/kbd&gt; is the prefix to all
user mappings.&lt;/p&gt;
&lt;p&gt;As an example, here is a mapping I use all the
time:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;map global user m ': format;w;make&amp;lt;ret&amp;gt;ga: echo Making&amp;lt;ret&amp;gt;' -docstring 'Format and write the file, then call *make*(1)'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It’s scoped globally because I want this to work everywhere. Now I just
hit &lt;kbd&gt;,&lt;/kbd&gt;, &lt;kbd&gt;m&lt;/kbd&gt; to&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;fix my sloppy formatting (&lt;code&gt;: format&lt;/code&gt;)
&lt;ul&gt;
&lt;li&gt;the space after the colon prevents this command from being put
into Kakoune’s prompt history&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;write the file (&lt;code&gt;;w&lt;/code&gt;)
&lt;ul&gt;
&lt;li&gt;the semicolon separates Kakoune commands&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;run &lt;em&gt;make&lt;/em&gt;(1)
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;;make&amp;lt;ret&amp;gt;&lt;/code&gt; calls Kakoune’s &lt;code&gt;:make&lt;/code&gt; wrapper, which opens a new
buffer&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ga&lt;/code&gt; goes back to the buffer I was working on&lt;/li&gt;
&lt;li&gt;&lt;code&gt;: echo Making&amp;lt;ret&amp;gt;&lt;/code&gt; is just for visual feedback.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Have a look at &lt;code&gt;:doc mapping&lt;/code&gt; for the full story. Note that &lt;code&gt;:map&lt;/code&gt; is
one of those commands that can take a &lt;code&gt;-docstring&lt;/code&gt; argument, which
becomes part of the self-documenting hints that you see throughout the
UI.&lt;/p&gt;
&lt;p&gt;Classic line-editing shortcuts like &lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;w&lt;/kbd&gt;
and &lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;u&lt;/kbd&gt; that predate even Unix are missing
from Kakoune’s insert mode; &lt;q&gt;those shortcuts do not fit the paradigm
that Kakoune implements&lt;/q&gt; says the &lt;code&gt;:doc faq&lt;/code&gt;, but for me this is
one case where practicality beats purity.&lt;/p&gt;
&lt;p&gt;&lt;small&gt;See the
&lt;a href="https://github.com/chambln/kakoune-readline"&gt;kakoune-readline&lt;/a&gt;
plugin.&lt;/small&gt;&lt;/p&gt;
&lt;h2&gt;Persistent configuration&lt;/h2&gt;
&lt;p&gt;Let’s say you’ve mapped a few keys and set a few options. How do you
make them persistent between &lt;em&gt;kak&lt;/em&gt;(1) sessions?&lt;/p&gt;
&lt;p&gt;Create the file &lt;code&gt;$HOME/.config/kak/kakrc&lt;/code&gt; and place your mapping and
options in there. This is the analogue to one’s &lt;code&gt;$HOME/.vimrc&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;When you start &lt;em&gt;kak&lt;/em&gt;(1), before sourcing your &lt;code&gt;kakrc&lt;/code&gt; it first sources all
&lt;code&gt;*.kak&lt;/code&gt; files within your &lt;code&gt;$HOME/.config/kak/autoload/&lt;/code&gt; directory. That
means you can put anything—even Git repositories in there
(i.e. plugins)—and all non-Kakoune files don’t cause Kakoune any
grief.&lt;/p&gt;
&lt;p&gt;&lt;small&gt;See &lt;em&gt;kak&lt;/em&gt;(1) (&lt;code&gt;man kak&lt;/code&gt;) for details on how exactly
Kakoune’s run-time files are sourced.&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;Once your &lt;code&gt;autoload&lt;/code&gt; directory exists, however, Kakoune decides not to
source the system run-time files under &lt;code&gt;/usr/share/kak/autoload/&lt;/code&gt;, so
you’ll want to link that system directory symbolically into yours:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;    mkdir -p $HOME/.config/kak/autoload/
    ln -s /usr/share/kak/autoload/ $HOME/.config/kak/autoload/
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Formatting the entire buffer&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;:format&lt;/code&gt; command is like doing &lt;kbd&gt;%&lt;/kbd&gt;, &lt;kbd&gt;|&lt;/kbd&gt; and
specifying some format-fixing program—maybe &lt;em&gt;fmt&lt;/em&gt;(1), &lt;em&gt;par&lt;/em&gt;(1)
or something else. You just need to set the &lt;code&gt;formatcmd&lt;/code&gt; option.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;set-option window formatcmd par
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;window&lt;/code&gt; argument specifies the &lt;em&gt;scope&lt;/em&gt; of this particular
assignment. See &lt;code&gt;:doc options set-option&lt;/code&gt; and &lt;code&gt;:doc scope&lt;/code&gt; for more
explanation.&lt;/p&gt;
&lt;p&gt;Also look at &lt;code&gt;autowrap_fmtcmd&lt;/code&gt; and &lt;code&gt;autowrap-enable&lt;/code&gt; which wrap lines
for you while typing, so it doesn’t feel like you’ve reverted to using
Notepad.&lt;/p&gt;
&lt;h3&gt;Lightweight markup&lt;/h3&gt;
&lt;p&gt;If you’re writing in a lightweight markup language, be it Markdown,
ReStructuredText, AsciiDoc, or what have you, it’s nice to have a
program go through your writing and fix little formatting mistakes here
and there, remove trailing spaces and unnecessary line breaks and so
forth. Kakoune’s &lt;code&gt;:format&lt;/code&gt; command lets you do this really smoothly
without leaving the editor. Just set &lt;code&gt;formatcmd&lt;/code&gt; to some command that
calls your style linter with any appropriate arguments.&lt;/p&gt;
&lt;p&gt;Pandoc can neatly reformat your lazy keyboard-mash markup by telling
it that the input and output are of the same kind. ReStructuredText
for example,&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;set-option buffer formatcmd 'pandoc -f rst -t rst --reference-links'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;where passing &lt;code&gt;--reference-links&lt;/code&gt; is optional of course, but means you
can write an inline link and have it converted automatically to a
reference at the bottom of the file, which takes care of the otherwise
laborious task of managing references, their names and order by hand.&lt;/p&gt;
&lt;p&gt;This could become slow for particularly large documents; here I’m
using Pandoc to reformat some 600 lines of text and it takes a
fraction of a second.&lt;/p&gt;
&lt;h3&gt;SCSS&lt;/h3&gt;
&lt;p&gt;In &lt;a href="https://asciinema.org/a/9zGnkfE066JPBUKXQ3OzLnnxb"&gt;this
screencast&lt;/a&gt;
you can see me fixing a poorly written stylesheet using &lt;em&gt;prettier&lt;/em&gt;(1)
with the following &lt;code&gt;formatcmd&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;set-option window formatcmd 'prettier --parser=scss'
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Hooks&lt;/h2&gt;
&lt;p&gt;You can use hooks to trigger a command when some event happens, such as
opening a new file, resizing the window, pressing a key in insert mode,
or the user being idle for some length of time. These also have an
associated scope. Read &lt;code&gt;:doc hooks&lt;/code&gt; to see how they work.&lt;/p&gt;
&lt;h3&gt;Filetype-specific run commands&lt;/h3&gt;
&lt;p&gt;Now, what if you want to set an option differently depending on the kind
of file you’re editing? You can do that using the WinSetOption hook:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;hook &amp;lt;scope&amp;gt; WinSetOption 'filetype=&amp;lt;filetype&amp;gt;' &amp;lt;command&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This hook is triggered whenever the filetype option is set to
&lt;code&gt;&amp;lt;filetype&amp;gt;&lt;/code&gt;. The command can be any list of commands. So to set a few
options that would be something like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;hook global WinSetOption filetype=(css|scss) %{
    set-option buffer indentwidth 2
    set-option buffer tabstop 2
    set-option buffer scrolloff 5,0
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This can get repetitive for lots of different filetypes, so we can
factor this out using the function &lt;code&gt;filetype-hook&lt;/code&gt; as defined below:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;define-command filetype-hook -params 2 %{
    hook global WinSetOption 'filetype=(%arg{1})' %arg{2}
}

filetype-hook css|scss %{
    set-option window indentwidth 2
    set-option window tabstop 2
    set-option window scrolloff 5,0
    set-option window formatcmd 'prettier --parser=scss'
}

filetype-hook ruby|python %{
    set-option window indentwidth 4
    set-option window tabstop 4
    set-option window matching_pairs ( ) [ ] { }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;Should you use Kakoune?&lt;/h1&gt;
&lt;p&gt;There’s loads more to Kakoune, not least of which are its
&lt;a href="https://kakoune.org/plugins.html"&gt;plugins&lt;/a&gt;. But the potential for it to
be configured exactly how you like is huge, and it’s very easy to do so.
I haven’t even talked about &lt;code&gt;evaluate-commands&lt;/code&gt; and &lt;code&gt;%sh{…}&lt;/code&gt; blocks
here.&lt;/p&gt;
&lt;p&gt;Kakoune is so smooth in the way it uses existing programs; take the
clipboard for example: why should Kakoune bother with implementing a
feature specific to and dependent on X, when it can very easily be done
in run-time configuration by piping to and from a program such as xsel?
This is a taste of the Unix philosophy, and it’s what makes Kakoune so
wonderfully extensible.&lt;/p&gt;
&lt;p&gt;But due to the difference in key mappings, existing Vim users will
become frustrated in the transition, and Vim veterans will be leaving
their beloved configuration behind, putting them back to square one. I
can see many Vim users dismissing Kakoune as an interesting idea, but
not worth the effort to learn. I mean, even &lt;a href="https://github.com/mawww"&gt;its
creator&lt;/a&gt; describes it as an &lt;q&gt;experiment for a
better code editor&lt;/q&gt;.&lt;/p&gt;
&lt;p&gt;I have found that learning to use Kakoune’s key stroke language has
messed with my muscle memory somewhat when it comes to Vim and
crucially Readline, although not as much as I’d anticipated. Still, I
now use Emacs bindings in Readline, because they differ enough that I
don’t get confused.&lt;/p&gt;
&lt;p&gt;&lt;small&gt;&lt;a href="https://tiswww.case.edu/php/chet/readline/rltop.html"&gt;GNU Readline&lt;/a&gt; is
the line-editing library used by countless terminal-based programs.&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;&lt;small&gt;&lt;strong&gt;Update, August 2020:&lt;/strong&gt; After much experience with all four,
my muscle memory can switch smoothly between Emacs, Readline, vi and
Kakoune.  But &lt;abbrev title="Your mileage may
vary"&gt;YMMV&lt;/abbrev&gt;.&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;This write-up has been mostly positive, but my experience with Kakoune
has not been without issue:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I’m having to use &lt;kbd&gt;Alt&lt;/kbd&gt; all the time now, which can be a bit
fiddly to say the least.&lt;/li&gt;
&lt;li&gt;There’s just no way to have the cursor turn into a pipe shape while
in insert mode, which is a shame because many people rely on that to
indicate whether they’re in insert mode.&lt;/li&gt;
&lt;li&gt;Insert mode auto wrapping, which uses &lt;em&gt;fold&lt;/em&gt;(1), will occasionally
create a new line in the middle of a word I’m writing.&lt;/li&gt;
&lt;li&gt;Having lots of plugins and a lengthy &lt;code&gt;kakrc&lt;/code&gt; can increase startup
time, but this true of many if not all text editors.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Further reading&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://kakoune.org/"&gt;kakoune.org&lt;/a&gt; – Official site&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mawww/kakoune/blob/master/README.asciidoc"&gt;&lt;cite&gt;README.asciidoc&lt;/cite&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;the &lt;a href="https://github.com/mawww/kakoune/wiki"&gt;Kakoune wiki&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mawww/kakoune/blob/master/contrib/TRAMPOLINE"&gt;&lt;cite&gt;TRAMPOLINE&lt;/cite&gt;&lt;/a&gt;
– walkthrough of Kakoune’s basic editing primatives.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://discuss.kakoune.com/"&gt;Kakoune Community Hub&lt;/a&gt; where you can
find a &lt;a href="https://discuss.kakoune.com/t/the-vim-inspired-editor-with-a-linguistic-twist/"&gt;discussion of this
article&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kakoune.org/why-kakoune/why-kakoune.html"&gt;&lt;cite&gt;Why Kakoune — The quest for a better code editor&lt;/cite&gt;&lt;/a&gt; – Maxime Coste&lt;/li&gt;
&lt;li&gt;&lt;a href="https://brhfl.com/2018/07/kakoune/"&gt;&lt;cite&gt;Kakoune&lt;/cite&gt;&lt;/a&gt; – Bri Hefele&lt;/li&gt;
&lt;/ul&gt;</description></item>
<item><title>Guide to Installing the rc Shell with Line-Editing in
Linux</title>
<author>greg@cosine.blue (Gregory Chamberlain)</author>
<pubDate>Wed, 26 Jun 2019 00:00:00 +0000</pubDate>
<guid>https://cosine.blue/2019-06-26-rc-shell-setup.html</guid>
<description>&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;This article demonstrates how to download, compile and install Byron
Rakitzis’ reimplementation of the &lt;em&gt;rc&lt;/em&gt; shell, originally from the Plan 9
system. The first section is a brief history of &lt;em&gt;rc&lt;/em&gt; and some of its
newer forms, but feel free to skip ahead to the actual guide.&lt;/p&gt;
&lt;h1&gt;History&lt;/h1&gt;
&lt;p&gt;Around 10 years or so after creating Unix, the Computing Science
Research Center at AT&amp;amp;T Bell Labs developed the
&lt;a href="https://9p.io/plan9"&gt;Plan 9&lt;/a&gt; operating system, which further riffed on
the Unix philosophy. It was only used internally at Bell Labs until the
early ’90s when they made it available to universities and businesses.
Eventually they released it under an open-source license. Today it’s
only really used by hobbyists and people learning about operating
systems.&lt;/p&gt;
&lt;p&gt;Anyway, &lt;em&gt;rc&lt;/em&gt; (short for &lt;em&gt;“run commands”&lt;/em&gt;) was the system’s canonical
command-line interpreter, and it’s ace. Its syntax is much simpler than
that of the established Bourne shell from which Bash and most other
contemporary shells derive; and &lt;em&gt;rc&lt;/em&gt;’s handling of strings and
special characters makes it less error-prone overall.&lt;/p&gt;
&lt;p&gt;Many tools from Plan 9, including its fantastic &lt;em&gt;rc&lt;/em&gt; shell, have been
ported to Unix-like systems under the name &lt;em&gt;&lt;a href="https://9fans.github.io/plan9port"&gt;Plan 9 from User
Space&lt;/a&gt;&lt;/em&gt; (a.k.a. plan9port). A subset
of these programs packaged as &lt;a href="http://tools.suckless.org/9base/"&gt;9base&lt;/a&gt;
is provided by Suckless. The two are probably available from your
distribution’s package repository (but keep reading).&lt;/p&gt;
&lt;p&gt;An independent project by Byron Rakitzis saw a reimplementation of the
&lt;em&gt;rc&lt;/em&gt; shell for Unix-like systems. His implementation differs very
slightly from the &lt;em&gt;true&lt;/em&gt; Plan 9 shell (as ported by plan9port), but
before compiling it can be linked with line-editing libraries such as
GNU readline, which is why I much prefer it for interactive use.&lt;/p&gt;
&lt;h1&gt;Install the &lt;em&gt;rc&lt;/em&gt; shell&lt;/h1&gt;
&lt;p&gt;I recommend installing &lt;a href="https://github.com/rakitzis/rc" title="rc shell -- independent re-implementation for Unix of the Plan 9 shell (from circa 1992)."&gt;Byron Rakitzis’ reimplementation of
&lt;em&gt;rc&lt;/em&gt;&lt;/a&gt;,
which provides such nice features as &lt;strong&gt;line editing&lt;/strong&gt; and &lt;strong&gt;tab
completions&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;Compile from source&lt;/h2&gt;
&lt;p&gt;Clone the GitHub repository and run the bootstrap script:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;git clone https://github.com/rakitzis/rc
cd rc
./bootstrap
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This generates an &lt;code&gt;INSTALL&lt;/code&gt; file with detailed instructions. Then
configure and build like so:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;sh configure --with-edit=readline
make
sudo make install
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You now have &lt;em&gt;rc&lt;/em&gt; installed on your machine. To uninstall, use &lt;code&gt;sudo make uninstall&lt;/code&gt; in that same directory.&lt;/p&gt;
&lt;h1&gt;Start the &lt;em&gt;rc&lt;/em&gt; shell&lt;/h1&gt;
&lt;p&gt;You may need to log out and back in for it to work. Start the shell by
typing&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;rc
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or, in order to have &lt;em&gt;rc&lt;/em&gt; behave as a &lt;strong&gt;login shell&lt;/strong&gt;, pass the &lt;code&gt;-l&lt;/code&gt;
flag:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;rc -l
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As described in the manual (&lt;code&gt;man rc&lt;/code&gt;), this tells &lt;em&gt;rc&lt;/em&gt; to source
&lt;code&gt;$home/.rcrc&lt;/code&gt; when it starts. Much like one’s
&lt;a href="https://wiki.archlinux.org/index.php/Bash#Configuration_files"&gt;&lt;code&gt;.bashrc&lt;/code&gt;&lt;/a&gt;,
you might like to populate that file with commands that&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;change your &lt;code&gt;$prompt&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;change your &lt;code&gt;$path&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;define functions,&lt;/li&gt;
&lt;li&gt;assign environment variables,&lt;/li&gt;
&lt;li&gt;do whatever else.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;small&gt;In &lt;em&gt;rc&lt;/em&gt;, the home directory is stored in both the
lowercase variable &lt;code&gt;$home&lt;/code&gt; and the usual uppercase
environment variable &lt;code&gt;$HOME&lt;/code&gt;.  Also, the built-in
&lt;code&gt;$path&lt;/code&gt; variable is a list of directories that is kept in
sync with the usual &lt;code&gt;$PATH&lt;/code&gt; environment variable, a
colon-separated string of the same directories.&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;The default prompt is a semicolon, which seems an odd choice. According
to the manual,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[t]he reason for this is that it enables an &lt;em&gt;rc&lt;/em&gt; user to grab
commands from previous lines using a mouse, and to present them to
&lt;em&gt;rc&lt;/em&gt; for re-interpretation; the semicolon prompt is simply ignored by
&lt;em&gt;rc&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To quit the shell, press &lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;d&lt;/kbd&gt; or type &lt;code&gt;exit&lt;/code&gt;.&lt;/p&gt;
&lt;h1&gt;Make &lt;em&gt;rc&lt;/em&gt; your login shell&lt;/h1&gt;
&lt;p&gt;When you open your terminal, the first program it runs is your &lt;strong&gt;login
shell&lt;/strong&gt;. On most Linux machines, users’ login shells are set to Bash by
default. Changing your login shell is easy to do.&lt;/p&gt;
&lt;p&gt;Firstly, add &lt;em&gt;rc&lt;/em&gt;’s full path to your machine’s list of approved login
shells. This must be done as root, as so:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;sudo su -c 'which rc &amp;gt;&amp;gt; /etc/shells'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let’s do this next step in an &lt;em&gt;rc&lt;/em&gt; shell, demonstrating its backquote
substitution (analogous to the Bourne shell’s command substitution). And
we’ll use the built-in
&lt;a href="https://manpages.debian.org/stable/passwd/chsh.1.en.html"&gt;&lt;code&gt;chsh&lt;/code&gt;&lt;/a&gt; utility:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;rc
chsh $USER --shell `{ which rc }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That’s it! Next time you log in as the same user, your tty and
terminals will start with the &lt;em&gt;rc&lt;/em&gt; shell. This has had no effect on
other users; so if your &lt;em&gt;rc&lt;/em&gt; executable breaks or disappears, you can
simply log in as root and change your shell back to Bash or what have
you.&lt;/p&gt;
&lt;h2&gt;Make use of run commands&lt;/h2&gt;
&lt;p&gt;Many users like to use &lt;code&gt;la&lt;/code&gt; as an alias to &lt;code&gt;ls -A&lt;/code&gt;. To implement this in
our &lt;em&gt;rc&lt;/em&gt;, let’s define a function in &lt;strong&gt;&lt;code&gt;$home/.rcrc&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;small&gt;Unlike the Bourne shell, &lt;em&gt;rc&lt;/em&gt; does not support aliases.
Use functions instead! The &lt;code&gt;builtin&lt;/code&gt; keyword should be
used to avoid infinite recursion.&lt;/small&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;fn la { ls -A $* }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In short, &lt;code&gt;fn&lt;/code&gt; is the keyword for creating functions, and the braces
contain the sequence of commands the function shall execute. Arguments
of the function are stored in &lt;code&gt;$1&lt;/code&gt;, &lt;code&gt;$2&lt;/code&gt;, etc., but &lt;code&gt;$*&lt;/code&gt; stores the list
of &lt;em&gt;all&lt;/em&gt; arguments given, which we humbly and helpfully pass straight
through to the &lt;code&gt;ls&lt;/code&gt; program.&lt;/p&gt;
&lt;p&gt;I found that I had to log out and back in for the updated &lt;code&gt;$home/.rcrc&lt;/code&gt;
to be sourced automatically; starting a new instance of &lt;em&gt;rc&lt;/em&gt; was not
enough. But we can source the new commands manually with the &lt;code&gt;.&lt;/code&gt;
built-in, as so:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;. $home/.rcrc
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or, if we’re already in the home directory, simply&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;. .rcrc
&lt;/code&gt;&lt;/pre&gt;</description></item></channel></rss>
