<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>simonh.uk - software</title><link href="https://simonh.uk/" rel="alternate"></link><link href="https://simonh.uk/feeds/software.atom.xml" rel="self"></link><id>https://simonh.uk/</id><updated>2026-02-12T00:00:00+00:00</updated><subtitle>Simon Harrison :: Burton on Trent :: UK</subtitle><entry><title>Backing Up Retro Game Library using Rsync</title><link href="https://simonh.uk/2026/02/10/backing-up-retro-game-library-using-rsync/" rel="alternate"></link><published>2026-02-10T00:00:00+00:00</published><updated>2026-02-12T00:00:00+00:00</updated><author><name>Simon Harrison</name></author><id>tag:simonh.uk,2026-02-10:/2026/02/10/backing-up-retro-game-library-using-rsync/</id><summary type="html">	&lt;p&gt;No &lt;span class="caps"&gt;GUI&lt;/span&gt; needed&lt;/p&gt;</summary><content type="html">	&lt;p&gt;&lt;img alt="rsync logo" src="/img/2026-02-10/rsync.webp" title="rsync logo" /&gt;&lt;/p&gt;

	&lt;p&gt;In this post, I thought I&amp;#8217;d share my simple method for keeping my (mainly) retro games backed up on a &lt;span class="caps"&gt;USB&lt;/span&gt; hard drive. To start with, I was doing it all manually, but that soon grew tiresome so I decided to use the tried and trusted &lt;a href="https://linux.die.net/man/1/rsync"&gt;rsync&lt;/a&gt; to save time. Before I ran any commands on my proper game directory, I created a test folder to make sure everything worked as I wanted. Rsync is a program with lots of options, but here I&amp;#8217;m only using it for a simple backup from one tree to another. Let&amp;#8217;s get started!&lt;/p&gt;

	&lt;p&gt;If you&amp;#8217;re not familiar with rsync, it generally takes a source folder and a destination folder, preceded by whatever options you want to use. Below, I&amp;#8217;m using &lt;code&gt;-navi&lt;/code&gt; which means:&lt;/p&gt;

	&lt;p&gt;&lt;code&gt;-n&lt;/code&gt; &amp;#8211; run in test mode (dry run)&lt;br /&gt;
&lt;code&gt;-a&lt;/code&gt; &amp;#8211; run in archive mode (which includes lots of options to save typing)&lt;br /&gt;
&lt;code&gt;-v&lt;/code&gt; &amp;#8211; run in verbose mode to give us info&lt;br /&gt;
&lt;code&gt;-i&lt;/code&gt; &amp;#8211; itemize what files are going to be added, deleted etc.&lt;/p&gt;

	&lt;p&gt;As you can see from the output below, rsync when used with &lt;code&gt;-navi&lt;/code&gt; gives us a summary of everything that it&amp;#8217;s going to do.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[simon@computer 14:38:24] ~/tmp
$ rsync -navi Games/ Games-backup
sending incremental file list
created directory Games-backup
cd+++++++++ ./
cd+++++++++ gb/
&amp;gt;f+++++++++ gb/A-mazing Tater (USA).gb
&amp;gt;f+++++++++ gb/Adventures of Lolo (Europe) (SGB Enhanced).gb
&amp;gt;f+++++++++ gb/Adventures of Star Saver, The (USA, Europe).gb
&amp;gt;f+++++++++ gb/Kirby&amp;#39;s Block Ball (USA, Europe) (SGB Enhanced).gb
&amp;gt;f+++++++++ gb/Kirby&amp;#39;s Dream Land (USA, Europe).gb
&amp;gt;f+++++++++ gb/Kirby&amp;#39;s Dream Land 2 (USA, Europe) (SGB Enhanced).gb
&amp;gt;f+++++++++ gb/Kirby&amp;#39;s Pinball Land (USA, Europe).gb
&amp;gt;f+++++++++ gb/Kirby&amp;#39;s Star Stacker (USA, Europe) (SGB Enhanced).gb
&amp;gt;f+++++++++ gb/Wario Blast Featuring Bomberman! (USA, Europe) (SGB Enhanced).gb
&amp;gt;f+++++++++ gb/Wario Land - Super Mario Land 3 (World).gb
&amp;gt;f+++++++++ gb/Wario Land 3 (World) (En,Ja).gbc
&amp;gt;f+++++++++ gb/Wario Land II (USA, Europe) (SGB Enhanced) (GB Compatible).gbc
&amp;gt;f+++++++++ gb/Yoshi (USA).gb
&amp;gt;f+++++++++ gb/Yoshi&amp;#39;s Cookie (USA, Europe).gb
cd+++++++++ gba/
&amp;gt;f+++++++++ gba/Celeste 2 (v1.0) (Aftermarket).gba
&amp;gt;f+++++++++ gba/Celeste Classic (World) (v1.2) (Aftermarket) (Unl).gba
cd+++++++++ gg/
&amp;gt;f+++++++++ gg/Castle of Illusion Starring Mickey Mouse (USA, Europe, Brazil) (En).sms
&amp;gt;f+++++++++ gg/Chase H.Q. (USA).sms
&amp;gt;f+++++++++ gg/Choplifter III (USA).gg
&amp;gt;f+++++++++ gg/Excellent Dizzy Collection, The (Europe).sms
&amp;gt;f+++++++++ gg/GG Aleste (Japan) (En).gg
&amp;gt;f+++++++++ gg/GG Aleste 3 (Japan) (En) (Aleste Collection).gg
&amp;gt;f+++++++++ gg/GG Aleste II (Japan) (En) (Aleste Collection).gg
&amp;gt;f+++++++++ gg/Galaga 2 (Europe).gg
&amp;gt;f+++++++++ gg/Sonic &amp;amp; Tails (Japan) (En).gg
&amp;gt;f+++++++++ gg/Sonic &amp;amp; Tails 2 (Japan) (En).gg
&amp;gt;f+++++++++ gg/Sonic The Hedgehog (World) (Rev A).gg
&amp;gt;f+++++++++ gg/Sonic The Hedgehog 2 (World).gg
&amp;gt;f+++++++++ gg/Streets of Rage (World).gg
&amp;gt;f+++++++++ gg/Streets of Rage 2 (World).gg
&amp;gt;f+++++++++ gg/Super Space Invaders (USA, Europe).gg
&amp;gt;f+++++++++ gg/Tails Adventure (World) (En,Ja).gg
&amp;gt;f+++++++++ gg/Terminator 2 - Judgment Day (World).gg
&amp;gt;f+++++++++ gg/Terminator, The (USA, Europe).gg
cd+++++++++ ngc/
&amp;gt;f+++++++++ ngc/Bust-A-Move Pocket (USA).ngc
&amp;gt;f+++++++++ ngc/Crush Roller (World) (En,Ja).ngc
&amp;gt;f+++++++++ ngc/Fantastic Night Dreams - Cotton (Europe).ngc
&amp;gt;f+++++++++ ngc/Fatal Fury F-Contact - Pocket Fighting Series (World) (En,Ja).ngc
&amp;gt;f+++++++++ ngc/King of Fighters R-2 - Pocket Fighting Series (World) (En,Ja).ngc
&amp;gt;f+++++++++ ngc/Last Blade, The - Beyond the Destiny (USA, Europe).ngc
&amp;gt;f+++++++++ ngc/Magical Drop Pocket (USA, Europe).ngc
&amp;gt;f+++++++++ ngc/Rockman - Battle &amp;amp; Fighters (Japan).ngc
&amp;gt;f+++++++++ ngc/SNK Gals&amp;#39; Fighters (USA, Europe).ngc
&amp;gt;f+++++++++ ngc/SNK vs. Capcom - Card Fighters&amp;#39; Clash - SNK Version (USA, Europe).ngc
&amp;gt;f+++++++++ ngc/SNK vs. Capcom - The Match of the Millennium (World) (En,Ja).ngc
&amp;gt;f+++++++++ ngc/Sonic The Hedgehog - Pocket Adventure (World) (En,Ja).ngc
cd+++++++++ pce/
&amp;gt;f+++++++++ pce/Bomberman &amp;#39;93 (USA).pce
&amp;gt;f+++++++++ pce/Bomberman (USA).pce
&amp;gt;f+++++++++ pce/Chase H.Q. (USA).pce
&amp;gt;f+++++++++ pce/Darius Alpha (Japan) (En) (SG Enhanced).pce
&amp;gt;f+++++++++ pce/Darius Plus (Japan) (En) (SG Enhanced).pce
&amp;gt;f+++++++++ pce/Final Soldier (Japan) (En).pce
&amp;gt;f+++++++++ pce/Galaga &amp;#39;88 (Japan) (En).pce
&amp;gt;f+++++++++ pce/Gradius (Japan) (En).pce
&amp;gt;f+++++++++ pce/ImageFight (Japan) (En).pce
&amp;gt;f+++++++++ pce/Pac-Land (USA).pce
&amp;gt;f+++++++++ pce/R-Type I (Japan) (En).pce
&amp;gt;f+++++++++ pce/R-Type II (Japan) (En) (V1.1).pce
&amp;gt;f+++++++++ pce/Raiden (USA).pce
&amp;gt;f+++++++++ pce/Salamander (Japan) (En).pce
&amp;gt;f+++++++++ pce/Soldier Blade (USA).pce
&amp;gt;f+++++++++ pce/Space Invaders - Fukkatsu no Hi (Japan).pce
&amp;gt;f+++++++++ pce/Super Star Soldier (USA).pce
&amp;gt;f+++++++++ pce/Turrican (USA).pce

sent 3,171 bytes  received 266 bytes  6,874.00 bytes/sec
total size is 54,620,304  speedup is 15,891.85 (DRY RUN)&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Once we&amp;#8217;re happy that our command is going to do what we intend it to do, we can remove the &lt;code&gt;-n&lt;/code&gt; switch to make the initial backup:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[simon@computer 14:38:40] ~/tmp
$ rsync -avi Games/ Games-backup
sending incremental file list
created directory Games-backup
cd+++++++++ ./
cd+++++++++ gb/
&amp;gt;f+++++++++ gb/A-mazing Tater (USA).gb
&amp;gt;f+++++++++ gb/Adventures of Lolo (Europe) (SGB Enhanced).gb
&amp;gt;f+++++++++ gb/Adventures of Star Saver, The (USA, Europe).gb
&amp;gt;f+++++++++ gb/Kirby&amp;#39;s Block Ball (USA, Europe) (SGB Enhanced).gb
&amp;gt;f+++++++++ gb/Kirby&amp;#39;s Dream Land (USA, Europe).gb
&amp;gt;f+++++++++ gb/Kirby&amp;#39;s Dream Land 2 (USA, Europe) (SGB Enhanced).gb
&amp;gt;f+++++++++ gb/Kirby&amp;#39;s Pinball Land (USA, Europe).gb
&amp;gt;f+++++++++ gb/Kirby&amp;#39;s Star Stacker (USA, Europe) (SGB Enhanced).gb
&amp;gt;f+++++++++ gb/Wario Blast Featuring Bomberman! (USA, Europe) (SGB Enhanced).gb
&amp;gt;f+++++++++ gb/Wario Land - Super Mario Land 3 (World).gb
&amp;gt;f+++++++++ gb/Wario Land 3 (World) (En,Ja).gbc
&amp;gt;f+++++++++ gb/Wario Land II (USA, Europe) (SGB Enhanced) (GB Compatible).gbc
&amp;gt;f+++++++++ gb/Yoshi (USA).gb
&amp;gt;f+++++++++ gb/Yoshi&amp;#39;s Cookie (USA, Europe).gb
cd+++++++++ gba/
&amp;gt;f+++++++++ gba/Celeste 2 (v1.0) (Aftermarket).gba
&amp;gt;f+++++++++ gba/Celeste Classic (World) (v1.2) (Aftermarket) (Unl).gba
cd+++++++++ gg/
&amp;gt;f+++++++++ gg/Castle of Illusion Starring Mickey Mouse (USA, Europe, Brazil) (En).sms
&amp;gt;f+++++++++ gg/Chase H.Q. (USA).sms
&amp;gt;f+++++++++ gg/Choplifter III (USA).gg
&amp;gt;f+++++++++ gg/Excellent Dizzy Collection, The (Europe).sms
&amp;gt;f+++++++++ gg/GG Aleste (Japan) (En).gg
&amp;gt;f+++++++++ gg/GG Aleste 3 (Japan) (En) (Aleste Collection).gg
&amp;gt;f+++++++++ gg/GG Aleste II (Japan) (En) (Aleste Collection).gg
&amp;gt;f+++++++++ gg/Galaga 2 (Europe).gg
&amp;gt;f+++++++++ gg/Sonic &amp;amp; Tails (Japan) (En).gg
&amp;gt;f+++++++++ gg/Sonic &amp;amp; Tails 2 (Japan) (En).gg
&amp;gt;f+++++++++ gg/Sonic The Hedgehog (World) (Rev A).gg
&amp;gt;f+++++++++ gg/Sonic The Hedgehog 2 (World).gg
&amp;gt;f+++++++++ gg/Streets of Rage (World).gg
&amp;gt;f+++++++++ gg/Streets of Rage 2 (World).gg
&amp;gt;f+++++++++ gg/Super Space Invaders (USA, Europe).gg
&amp;gt;f+++++++++ gg/Tails Adventure (World) (En,Ja).gg
&amp;gt;f+++++++++ gg/Terminator 2 - Judgment Day (World).gg
&amp;gt;f+++++++++ gg/Terminator, The (USA, Europe).gg
cd+++++++++ ngc/
&amp;gt;f+++++++++ ngc/Bust-A-Move Pocket (USA).ngc
&amp;gt;f+++++++++ ngc/Crush Roller (World) (En,Ja).ngc
&amp;gt;f+++++++++ ngc/Fantastic Night Dreams - Cotton (Europe).ngc
&amp;gt;f+++++++++ ngc/Fatal Fury F-Contact - Pocket Fighting Series (World) (En,Ja).ngc
&amp;gt;f+++++++++ ngc/King of Fighters R-2 - Pocket Fighting Series (World) (En,Ja).ngc
&amp;gt;f+++++++++ ngc/Last Blade, The - Beyond the Destiny (USA, Europe).ngc
&amp;gt;f+++++++++ ngc/Magical Drop Pocket (USA, Europe).ngc
&amp;gt;f+++++++++ ngc/Rockman - Battle &amp;amp; Fighters (Japan).ngc
&amp;gt;f+++++++++ ngc/SNK Gals&amp;#39; Fighters (USA, Europe).ngc
&amp;gt;f+++++++++ ngc/SNK vs. Capcom - Card Fighters&amp;#39; Clash - SNK Version (USA, Europe).ngc
&amp;gt;f+++++++++ ngc/SNK vs. Capcom - The Match of the Millennium (World) (En,Ja).ngc
&amp;gt;f+++++++++ ngc/Sonic The Hedgehog - Pocket Adventure (World) (En,Ja).ngc
cd+++++++++ pce/
&amp;gt;f+++++++++ pce/Bomberman &amp;#39;93 (USA).pce
&amp;gt;f+++++++++ pce/Bomberman (USA).pce
&amp;gt;f+++++++++ pce/Chase H.Q. (USA).pce
&amp;gt;f+++++++++ pce/Darius Alpha (Japan) (En) (SG Enhanced).pce
&amp;gt;f+++++++++ pce/Darius Plus (Japan) (En) (SG Enhanced).pce
&amp;gt;f+++++++++ pce/Final Soldier (Japan) (En).pce
&amp;gt;f+++++++++ pce/Galaga &amp;#39;88 (Japan) (En).pce
&amp;gt;f+++++++++ pce/Gradius (Japan) (En).pce
&amp;gt;f+++++++++ pce/ImageFight (Japan) (En).pce
&amp;gt;f+++++++++ pce/Pac-Land (USA).pce
&amp;gt;f+++++++++ pce/R-Type I (Japan) (En).pce
&amp;gt;f+++++++++ pce/R-Type II (Japan) (En) (V1.1).pce
&amp;gt;f+++++++++ pce/Raiden (USA).pce
&amp;gt;f+++++++++ pce/Salamander (Japan) (En).pce
&amp;gt;f+++++++++ pce/Soldier Blade (USA).pce
&amp;gt;f+++++++++ pce/Space Invaders - Fukkatsu no Hi (Japan).pce
&amp;gt;f+++++++++ pce/Super Star Soldier (USA).pce
&amp;gt;f+++++++++ pce/Turrican (USA).pce

sent 54,639,115 bytes  received 1,310 bytes  109,280,850.00 bytes/sec
total size is 54,620,304  speedup is 1.00&lt;/code&gt;&lt;/pre&gt;

	&lt;p class="info"&gt;Make sure to include the trailing slash after the source directory otherwise rsync will copy the &lt;code&gt;Games&lt;/code&gt; directory as well (which is not what we want):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[simon@computer 14:46:29] ~/tmp
$ rsync -navi Games Games-backup
sending incremental file list
cd+++++++++ Games/
cd+++++++++ Games/gb/
&amp;gt;f+++++++++ Games/gb/A-mazing Tater (USA).gb
&amp;gt;f+++++++++ Games/gb/Adventures of Lolo (Europe) (SGB Enhanced).gb
&amp;gt;f+++++++++ Games/gb/Adventures of Star Saver, The (USA, Europe).gb
&amp;gt;f+++++++++ Games/gb/Kirby&amp;#39;s Block Ball (USA, Europe) (SGB Enhanced).gb
&amp;gt;f+++++++++ Games/gb/Kirby&amp;#39;s Dream Land (USA, Europe).gb
&amp;gt;f+++++++++ Games/gb/Kirby&amp;#39;s Dream Land 2 (USA, Europe) (SGB Enhanced).gb
&amp;gt;f+++++++++ Games/gb/Kirby&amp;#39;s Pinball Land (USA, Europe).gb
&amp;gt;f+++++++++ Games/gb/Kirby&amp;#39;s Star Stacker (USA, Europe) (SGB Enhanced).gb
&amp;gt;f+++++++++ Games/gb/Wario Blast Featuring Bomberman! (USA, Europe) (SGB Enhanced).gb
&amp;gt;f+++++++++ Games/gb/Wario Land - Super Mario Land 3 (World).gb
&amp;gt;f+++++++++ Games/gb/Wario Land 3 (World) (En,Ja).gbc
&amp;gt;f+++++++++ Games/gb/Wario Land II (USA, Europe) (SGB Enhanced) (GB Compatible).gbc
&amp;gt;f+++++++++ Games/gb/Yoshi (USA).gb
&amp;gt;f+++++++++ Games/gb/Yoshi&amp;#39;s Cookie (USA, Europe).gb
cd+++++++++ Games/gba/
&amp;gt;f+++++++++ Games/gba/Celeste 2 (v1.0) (Aftermarket).gba
&amp;gt;f+++++++++ Games/gba/Celeste Classic (World) (v1.2) (Aftermarket) (Unl).gba
cd+++++++++ Games/gg/
&amp;gt;f+++++++++ Games/gg/Castle of Illusion Starring Mickey Mouse (USA, Europe, Brazil) (En).sms
&amp;gt;f+++++++++ Games/gg/Chase H.Q. (USA).sms
&amp;gt;f+++++++++ Games/gg/Choplifter III (USA).gg
&amp;gt;f+++++++++ Games/gg/Excellent Dizzy Collection, The (Europe).sms
&amp;gt;f+++++++++ Games/gg/GG Aleste (Japan) (En).gg
&amp;gt;f+++++++++ Games/gg/GG Aleste 3 (Japan) (En) (Aleste Collection).gg
&amp;gt;f+++++++++ Games/gg/GG Aleste II (Japan) (En) (Aleste Collection).gg
&amp;gt;f+++++++++ Games/gg/Galaga 2 (Europe).gg
&amp;gt;f+++++++++ Games/gg/Sonic &amp;amp; Tails (Japan) (En).gg
&amp;gt;f+++++++++ Games/gg/Sonic &amp;amp; Tails 2 (Japan) (En).gg
&amp;gt;f+++++++++ Games/gg/Sonic The Hedgehog (World) (Rev A).gg
&amp;gt;f+++++++++ Games/gg/Sonic The Hedgehog 2 (World).gg
&amp;gt;f+++++++++ Games/gg/Streets of Rage (World).gg
&amp;gt;f+++++++++ Games/gg/Streets of Rage 2 (World).gg
&amp;gt;f+++++++++ Games/gg/Super Space Invaders (USA, Europe).gg
&amp;gt;f+++++++++ Games/gg/Tails Adventure (World) (En,Ja).gg
&amp;gt;f+++++++++ Games/gg/Terminator 2 - Judgment Day (World).gg
&amp;gt;f+++++++++ Games/gg/Terminator, The (USA, Europe).gg
cd+++++++++ Games/ngc/
&amp;gt;f+++++++++ Games/ngc/Bust-A-Move Pocket (USA).ngc
&amp;gt;f+++++++++ Games/ngc/Crush Roller (World) (En,Ja).ngc
&amp;gt;f+++++++++ Games/ngc/Fantastic Night Dreams - Cotton (Europe).ngc
&amp;gt;f+++++++++ Games/ngc/Fatal Fury F-Contact - Pocket Fighting Series (World) (En,Ja).ngc
&amp;gt;f+++++++++ Games/ngc/King of Fighters R-2 - Pocket Fighting Series (World) (En,Ja).ngc
&amp;gt;f+++++++++ Games/ngc/Last Blade, The - Beyond the Destiny (USA, Europe).ngc
&amp;gt;f+++++++++ Games/ngc/Magical Drop Pocket (USA, Europe).ngc
&amp;gt;f+++++++++ Games/ngc/Rockman - Battle &amp;amp; Fighters (Japan).ngc
&amp;gt;f+++++++++ Games/ngc/SNK Gals&amp;#39; Fighters (USA, Europe).ngc
&amp;gt;f+++++++++ Games/ngc/SNK vs. Capcom - Card Fighters&amp;#39; Clash - SNK Version (USA, Europe).ngc
&amp;gt;f+++++++++ Games/ngc/SNK vs. Capcom - The Match of the Millennium (World) (En,Ja).ngc
&amp;gt;f+++++++++ Games/ngc/Sonic The Hedgehog - Pocket Adventure (World) (En,Ja).ngc
cd+++++++++ Games/pce/
&amp;gt;f+++++++++ Games/pce/Bomberman &amp;#39;93 (USA).pce
&amp;gt;f+++++++++ Games/pce/Bomberman (USA).pce
&amp;gt;f+++++++++ Games/pce/Chase H.Q. (USA).pce
&amp;gt;f+++++++++ Games/pce/Darius Alpha (Japan) (En) (SG Enhanced).pce
&amp;gt;f+++++++++ Games/pce/Darius Plus (Japan) (En) (SG Enhanced).pce
&amp;gt;f+++++++++ Games/pce/Final Soldier (Japan) (En).pce
&amp;gt;f+++++++++ Games/pce/Galaga &amp;#39;88 (Japan) (En).pce
&amp;gt;f+++++++++ Games/pce/Gradius (Japan) (En).pce
&amp;gt;f+++++++++ Games/pce/ImageFight (Japan) (En).pce
&amp;gt;f+++++++++ Games/pce/Pac-Land (USA).pce
&amp;gt;f+++++++++ Games/pce/R-Type I (Japan) (En).pce
&amp;gt;f+++++++++ Games/pce/R-Type II (Japan) (En) (V1.1).pce
&amp;gt;f+++++++++ Games/pce/Raiden (USA).pce
&amp;gt;f+++++++++ Games/pce/Salamander (Japan) (En).pce
&amp;gt;f+++++++++ Games/pce/Soldier Blade (USA).pce
&amp;gt;f+++++++++ Games/pce/Space Invaders - Fukkatsu no Hi (Japan).pce
&amp;gt;f+++++++++ Games/pce/Super Star Soldier (USA).pce
&amp;gt;f+++++++++ Games/pce/Turrican (USA).pce

sent 3,187 bytes  received 232 bytes  6,838.00 bytes/sec
total size is 54,620,304  speedup is 15,975.52 (DRY RUN)&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Now that we&amp;#8217;ve run rsync and copied all our games to our backup folder, running the same command again should not produce any changes. Let&amp;#8217;s check:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[simon@computer 14:55:15] ~/tmp
$ rsync -avi Games/ Games-backup
sending incremental file list

sent 2,957 bytes  received 17 bytes  5,948.00 bytes/sec
total size is 54,620,304  speedup is 18,365.94&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;rsync hasn&amp;#8217;t done anything by the looks of it, which is as we expect. Now, lets add a couple of new games to our source folder. We&amp;#8217;re in the mood for a bit of hockey so we&amp;#8217;ll add two games, one Gameboy game, one Game Gear one. Let&amp;#8217;s see if rsync spots them:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[simon@computer 14:55:20] ~/tmp
$ rsync -navi Games/ Games-backup
sending incremental file list
.d..t...... gb/
&amp;gt;f+++++++++ gb/NHL Blades of Steel (USA).gbc
.d..t...... gg/
&amp;gt;f+++++++++ gg/NHL All-Star Hockey (USA).gg

sent 3,040 bytes  received 29 bytes  6,138.00 bytes/sec
total size is 56,193,168  speedup is 18,309.93 (DRY RUN)&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;It sure did! Let&amp;#8217;s have rsync add them to our backup directory:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[simon@computer 15:00:19] ~/tmp
$ rsync -avi Games/ Games-backup
sending incremental file list
.d..t...... gb/
&amp;gt;f+++++++++ gb/NHL Blades of Steel (USA).gbc
.d..t...... gg/
&amp;gt;f+++++++++ gg/NHL All-Star Hockey (USA).gg

sent 1,576,360 bytes  received 69 bytes  3,152,858.00 bytes/sec
total size is 56,193,168  speedup is 35.65&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;I really like the &lt;code&gt;-i&lt;/code&gt; option, as we can see exactly what rsync has done. &lt;/p&gt;

	&lt;h2&gt;What about files I&amp;#8217;ve deleted?&lt;/h2&gt;

	&lt;p&gt;If you&amp;#8217;re trying to manage a backup directory manually, it can be a lot of work, keeping track of files and folders added, modified and deleted. rsync has a handy &lt;code&gt;--delete&lt;/code&gt; option which will delete files from the destination folder that aren&amp;#8217;t in the source folder. For our example use case in this post about managing our retro game library backups, we may have a rom that doesn&amp;#8217;t work. So we&amp;#8217;d like it gone from both folders. &lt;/p&gt;

	&lt;p&gt;We decide to get rid of a Wario game and a Turrican game. These have already been backed up, but the &lt;code&gt;--delete&lt;/code&gt; option tells rsync to delete anything that&amp;#8217;s in the destination folder, but not in the source folder. Let&amp;#8217;s run rsync in test mode:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[simon@computer 15:16:04] ~/tmp
$ rsync -navi --delete Games/ Games-backup
sending incremental file list
*deleting   gb/Wario Blast Featuring Bomberman! (USA, Europe) (SGB Enhanced).gb
*deleting   pce/Turrican (USA).pce
.d..t...... gb/
.d..t...... pce/

sent 2,942 bytes  received 120 bytes  6,124.00 bytes/sec
total size is 55,668,880  speedup is 18,180.56 (DRY RUN)&lt;/code&gt;&lt;/pre&gt;

	&lt;h2&gt;What about file / directory renames?&lt;/h2&gt;

	&lt;p&gt;Let&amp;#8217;s say we decide to stop being so lazy and rename &lt;code&gt;gb&lt;/code&gt; to &lt;code&gt;Gameboy&lt;/code&gt;. Will rsync be smart enough to notice that and simply rename it for us at the backup? Or, will it assume this a brand new directory and copy all the same files again? Let&amp;#8217;s find out:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[simon@computer 11:23:14] master ~/tmp
$ rsync -navi --delete Games/ Games-backup/
sending incremental file list
*deleting   gb/Yoshi&amp;#39;s Cookie (USA, Europe).gb
*deleting   gb/Yoshi (USA).gb
*deleting   gb/Wario Land II (USA, Europe) (SGB Enhanced) (GB Compatible).gbc
*deleting   gb/Wario Land 3 (World) (En,Ja).gbc
*deleting   gb/Wario Land - Super Mario Land 3 (World).gb
*deleting   gb/NHL Blades of Steel (USA).gbc
*deleting   gb/Kirby&amp;#39;s Star Stacker (USA, Europe) (SGB Enhanced).gb
*deleting   gb/Kirby&amp;#39;s Pinball Land (USA, Europe).gb
*deleting   gb/Kirby&amp;#39;s Dream Land 2 (USA, Europe) (SGB Enhanced).gb
*deleting   gb/Kirby&amp;#39;s Dream Land (USA, Europe).gb
*deleting   gb/Kirby&amp;#39;s Block Ball (USA, Europe) (SGB Enhanced).gb
*deleting   gb/Adventures of Star Saver, The (USA, Europe).gb
*deleting   gb/Adventures of Lolo (Europe) (SGB Enhanced).gb
*deleting   gb/A-mazing Tater (USA).gb
*deleting   gb/
.d..t...... ./
cd+++++++++ Gameboy/
&amp;gt;f+++++++++ Gameboy/A-mazing Tater (USA).gb
&amp;gt;f+++++++++ Gameboy/Adventures of Lolo (Europe) (SGB Enhanced).gb
&amp;gt;f+++++++++ Gameboy/Adventures of Star Saver, The (USA, Europe).gb
&amp;gt;f+++++++++ Gameboy/Kirby&amp;#39;s Block Ball (USA, Europe) (SGB Enhanced).gb
&amp;gt;f+++++++++ Gameboy/Kirby&amp;#39;s Dream Land (USA, Europe).gb
&amp;gt;f+++++++++ Gameboy/Kirby&amp;#39;s Dream Land 2 (USA, Europe) (SGB Enhanced).gb
&amp;gt;f+++++++++ Gameboy/Kirby&amp;#39;s Pinball Land (USA, Europe).gb
&amp;gt;f+++++++++ Gameboy/Kirby&amp;#39;s Star Stacker (USA, Europe) (SGB Enhanced).gb
&amp;gt;f+++++++++ Gameboy/NHL Blades of Steel (USA).gbc
&amp;gt;f+++++++++ Gameboy/Wario Land - Super Mario Land 3 (World).gb
&amp;gt;f+++++++++ Gameboy/Wario Land 3 (World) (En,Ja).gbc
&amp;gt;f+++++++++ Gameboy/Wario Land II (USA, Europe) (SGB Enhanced) (GB Compatible).gbc
&amp;gt;f+++++++++ Gameboy/Yoshi (USA).gb
&amp;gt;f+++++++++ Gameboy/Yoshi&amp;#39;s Cookie (USA, Europe).gb

sent 2,999 bytes  received 724 bytes  7,446.00 bytes/sec
total size is 55,668,880  speedup is 14,952.69 (DRY RUN)&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;As you see, rsync went with the second option. At the time of running this, I really wasn&amp;#8217;t sure what would happen. After doing a bit of research, it&amp;#8217;s because rsync doesn&amp;#8217;t keep any state between runs. Each time you run it, it simply compares the source and the destination and because we passed &lt;code&gt;--delete&lt;/code&gt; rsync simply sees a folder (and all it&amp;#8217;s contents) need deleting, and a new folder needs copying to the backup. &lt;/p&gt;

	&lt;p&gt;It&amp;#8217;s the same result if you rename a file or multiple files:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[simon@computer 11:30:08] master ~/tmp
$ rsync -navi --delete Games/ Games-backup/
sending incremental file list
*deleting   Gameboy/Blades of Steel (USA).gbc
.d..t...... Gameboy/
&amp;gt;f+++++++++ Gameboy/NHL Blades of Steel (USA).gbc

sent 2,953 bytes  received 60 bytes  6,026.00 bytes/sec
total size is 55,668,880  speedup is 18,476.23 (DRY RUN)&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;With files only a few kilobytes in size, it&amp;#8217;s not really an issue. However, if you&amp;#8217;re backing up big files taking up gigabytes, this is going to be a problem. There are patches and workarounds, but I think you should take this into account up front and try to avoid renaming directories in particular! &lt;/p&gt;

	&lt;h2&gt;Conclusion&lt;/h2&gt;

	&lt;p&gt;So now, I&amp;#8217;m happy that the command:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ rsync -avi --delete Games/ Games-backup/&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;is going to backup anything newly added, and delete any games that I deliberately deleted. By the way, rsync also keeps track of modified files. So if you replace a game with another one shaing exactly the same name (but different contents), rsync will copy that one to your backup folder too.&lt;/p&gt;

	&lt;p&gt;I think rsync is the perfect program for managing a backup of your games / roms. You only have &lt;strong&gt;one&lt;/strong&gt; folder that you need to keep tidy and rsync will keep a perfect duplicate of that folder for you. &lt;/p&gt;

	&lt;p&gt;A lot of people (myself included) may have had some fear of using rsync for this sort of task but once you&amp;#8217;ve tried it on a test directory and dialled in your options, I don&amp;#8217;t tnink anything can beat it. &lt;/p&gt;</content><category term="software"></category><category term="retro"></category><category term="tips"></category><category term="linux"></category><category term="software"></category></entry><entry><title>Using Emacs as a Word Processor</title><link href="https://simonh.uk/2025/09/27/using-emacs-as-a-word-processor/" rel="alternate"></link><published>2025-09-27T00:00:00+01:00</published><updated>2025-09-27T00:00:00+01:00</updated><author><name>Simon Harrison</name></author><id>tag:simonh.uk,2025-09-27:/2025/09/27/using-emacs-as-a-word-processor/</id><summary type="html">	&lt;p&gt;Is there anything Emacs can&amp;#8217;t do?&lt;/p&gt;</summary><content type="html">	&lt;p&gt;&lt;img alt="Emacs enriched text mode" src="/img/2025-09-27/emacs-enriched-mode.webp" title="Emacs enriched text mode" /&gt;&lt;/p&gt;

	&lt;p&gt;Ever since &lt;a href="https://lock.cmpxchg8b.com/"&gt;Tavis Ormandy&lt;/a&gt; got Wordperfect 8 &lt;a href="https://github.com/taviso/wpunix"&gt;working&lt;/a&gt; on modern Linux it&amp;#8217;s been bugging me that we don&amp;#8217;t have many options for word processing in the terminal. &lt;/p&gt;

	&lt;p&gt;Thanks to his amazing work, we do now have an enterprise grade word processor running in our terminals. However, there are problems.&lt;/p&gt;

	&lt;h2&gt;Problems with Wordperfect 8&lt;/h2&gt;

	&lt;p&gt;&lt;img alt="WordPerfect 8 for Unix" src="/img/2025-09-27/wpunix.webp" title="WordPerfect 8 for Unix" /&gt;&lt;/p&gt;

	&lt;p&gt;The most glaring problems are that it&amp;#8217;s closed source, hasn&amp;#8217;t been updated in &lt;em&gt;27 years&lt;/em&gt;, and it&amp;#8217;s not exactly, &lt;em&gt;user friendly&lt;/em&gt;. The &lt;span class="caps"&gt;PDF&lt;/span&gt; manual is ~700 pages! There&amp;#8217;s also the file format problem. It&amp;#8217;s not a publicly documented format. You can certainly open a &lt;code&gt;.wp&lt;/code&gt; file in plenty of software:&lt;/p&gt;

	&lt;ul&gt;
		&lt;li&gt;Libre Office&lt;/li&gt;
		&lt;li&gt;Abiword&lt;/li&gt;
		&lt;li&gt;Google Docs&lt;/li&gt;
	&lt;/ul&gt;

	&lt;p&gt;will all open an old wordperfect document, thanks most likely to &lt;a href="https://libwpd.sourceforge.net/"&gt;libwpd&lt;/a&gt; but you&amp;#8217;ll only be able to &lt;em&gt;edit&lt;/em&gt; it in Wordperfect. Which raises the question, &lt;/p&gt;

	&lt;blockquote&gt;
		&lt;p&gt;&amp;#8220;will I be able to open / edit these documents in twenty years time?&amp;#8221;&lt;/p&gt;
	&lt;/blockquote&gt;

	&lt;p&gt;So, while wpunix is an interesting piece of software, it&amp;#8217;s probably &lt;strong&gt;not&lt;/strong&gt; the best idea to do all your writing with it. &lt;/p&gt;

	&lt;p&gt;So, as I&amp;#8217;m inclined to do, I set about seeing what other options I have for editing documents on the command line.&lt;/p&gt;

	&lt;h2&gt;&lt;span class="caps"&gt;JOE&lt;/span&gt; Editor (Jstar)&lt;/h2&gt;

	&lt;p&gt;&lt;img alt="Joe jstar mode" src="/img/2025-09-27/joe-editor.webp" title="Joe jstar mode" /&gt;&lt;/p&gt;

	&lt;p&gt;I was already familiar with &lt;a href="https://joe-editor.sourceforge.io/"&gt;&lt;span class="caps"&gt;JOE&lt;/span&gt;&lt;/a&gt; and vaguely remembered that it had a Wordstar emulation mode. I&amp;#8217;ve never used Wordstar, but know it&amp;#8217;s still considered  irreplaceable by some &lt;a href="https://sfwriter.com/wordstar.htm"&gt;notable users&lt;/a&gt;. So, I had a play with it but it&amp;#8217;s not quite what I&amp;#8217;m after. The only formatting that one could consider somewhat out of the ordinary with Jstar is being able to centre text. &lt;/p&gt;

	&lt;h2&gt;What Should a Word Processor Do?&lt;/h2&gt;

	&lt;p&gt;To my mind, at a minimum, a word processor should be able to:&lt;/p&gt;

	&lt;ul&gt;
		&lt;li&gt;bold, underline and italicize text&lt;/li&gt;
		&lt;li&gt;Centre, left and right align text&lt;/li&gt;
		&lt;li&gt;Justify text&lt;/li&gt;
		&lt;li&gt;Have various types of headings&lt;/li&gt;
	&lt;/ul&gt;

	&lt;p&gt;I was amazed that no such command line program seemed to exist. Yeah sure, we&amp;#8217;ve got loads of Markdown editors, but I don&amp;#8217;t consider Markdown to be anything related to word processing. I even thought about attempting to make my own format (how hard could it be?!). But luckily, I came across:&lt;/p&gt;

	&lt;h2&gt;&lt;span class="caps"&gt;RFC&lt;/span&gt; 1896 The text/enriched &lt;span class="caps"&gt;MIME&lt;/span&gt; Content-type&lt;/h2&gt;

	&lt;p&gt;For some reason, I always forget than &lt;em&gt;any&lt;/em&gt; computer problem was almost certainly solved years ago. And so it was for this problem. &lt;a href="https://www.rfc-editor.org/rfc/rfc1896.html"&gt;&lt;span class="caps"&gt;RFC&lt;/span&gt; 1896&lt;/a&gt; was suggested in 1996 to allow formatting of email messages. Unfortunately, it never caught on. Still, it exists and is a standard and Emacs has an enriched mode! See &lt;a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Enriched-Text.html"&gt;here&lt;/a&gt; for online documentation. Here&amp;#8217;s the &amp;#8220;source&amp;#8221; code for the screenshot at the top of this post:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Content-Type: text/enriched
Text-Width: 70

&amp;lt;flushright&amp;gt;This is right aligned 

&amp;lt;/flushright&amp;gt;&amp;lt;center&amp;gt;

Here is some &amp;lt;bold&amp;gt;bold &amp;lt;/bold&amp;gt;text and here is some that is &amp;lt;italic&amp;gt;italic&amp;lt;/italic&amp;gt;.

&amp;lt;/center&amp;gt;&amp;lt;flushboth&amp;gt;

Enriched mode is a minor mode for editing formatted text files in a
WYSIWYG (What You See Is What You Get) fashion. When Enriched mode is
enabled, you can apply various formatting properties to the text in
the buffer, such as fonts and colors; upon saving the buffer, those
properties are saved together with the text, using the MIME
‘text/enriched’ file format.


Enriched mode is typically used with Text mode (see Text Mode). It is
not compatible with Font Lock mode, which is used by many major modes,
including most programming language modes, for syntax highlighting
(see Font Lock mode).  Unlike Enriched mode, Font Lock mode assigns
text properties automatically, based on the current buffer contents;
those properties are not saved to disk.

&amp;lt;/flushboth&amp;gt;&amp;lt;center&amp;gt;

&amp;lt;underline&amp;gt;Underlined Heading&amp;lt;/underline&amp;gt;

&amp;lt;/center&amp;gt;&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;The only thing that seems to be missing from enriched-mode is increasing the font size. There&amp;#8217;s a discussion on the mailing list that goes into detail:&lt;/p&gt;

	&lt;p&gt;&lt;a href="https://lists.gnu.org/archive/html/help-gnu-emacs/2025-06/msg00146.html"&gt;Making selected text larger in enriched mode&lt;/a&gt; &lt;/p&gt;

	&lt;p&gt;Apart from that, enriched-mode seems pretty much perfect for writing. &lt;/p&gt;

	&lt;h2&gt;Using Emacs Enriched Mode&lt;/h2&gt;

	&lt;p&gt;I won&amp;#8217;t go into great detail as the documentation link above explains everything, but here are my brief notes:&lt;/p&gt;

	&lt;p&gt;Type &lt;code&gt;M-x enriched-mode&lt;/code&gt; on a new file to activate the mode.&lt;sup class="footnote" id="fnrevcdc43bcf38f84d9db85f252972a5f99d-1"&gt;&lt;a href="#fncdc43bcf38f84d9db85f252972a5f99d-1"&gt;1&lt;/a&gt;&lt;/sup&gt; Then, you only really &lt;em&gt;need&lt;/em&gt; to remember two shortcuts:&lt;/p&gt;

	&lt;p&gt;&lt;code&gt;Alt-o&lt;/code&gt; to bring up the &lt;em&gt;Options(?)&lt;/em&gt; menu and &lt;code&gt;Alt-j&lt;/code&gt; to bring up the &lt;em&gt;Justify&lt;/em&gt; menu.&lt;/p&gt;

	&lt;p&gt;Then, you can just press a single letter:&lt;/p&gt;

	&lt;p&gt;&lt;img alt="Emacs enriched mode options menu" src="/img/2025-09-27/alt-o.png" title="Emacs enriched mode options menu" /&gt;&lt;/p&gt;

	&lt;p&gt;&lt;code&gt;Alt-o&lt;/code&gt; &lt;code&gt;b&lt;/code&gt; to bold for example&lt;/p&gt;

	&lt;p&gt;&lt;img alt="Emacs enriched mode justification menu" src="/img/2025-09-27/alt-j.png" title="Emacs enriched mode justification menu" /&gt;&lt;/p&gt;

	&lt;p&gt;&lt;code&gt;Alt-j&lt;/code&gt; &lt;code&gt;b&lt;/code&gt; to justify &lt;/p&gt;

	&lt;h2&gt;Plain Text Benefits&lt;/h2&gt;

	&lt;p&gt;As enriched text is simply plain text with a bit of markup, it&amp;#8217;s easily versionable (&lt;span class="caps"&gt;RCS&lt;/span&gt;, Mercurial / Git et al.). You can write a script to convert your enriched text to another format etc. &lt;/p&gt;

	&lt;h2&gt;Conclusion&lt;/h2&gt;

	&lt;p&gt;As I wrote in &lt;a href="https://simonh.uk/2025/09/13/why-i-use-gnu-nano-as-my-default-editor/"&gt;Why I use &lt;span class="caps"&gt;GNU&lt;/span&gt; Nano&lt;/a&gt; post, I don&amp;#8217;t use Emacs as my text editor. But, I&amp;#8217;ll probably start using it as my word processor instead&amp;#8230;&lt;/p&gt;

	&lt;h2 class="footnotes"&gt;Footnotes&lt;/h2&gt;

	&lt;p class="footnote" id="fncdc43bcf38f84d9db85f252972a5f99d-1"&gt;&lt;sup&gt;1&lt;/sup&gt; I&amp;#8217;m trying to find an easy way to start Emacs in enriched mode. Will update post if I find it!&lt;/p&gt;</content><category term="software"></category><category term="writing"></category><category term="emacs"></category><category term="gnu"></category></entry><entry><title>Microsoft Edit vs GNU Nano</title><link href="https://simonh.uk/2025/09/23/microsoft-edit-vs-gnu-nano/" rel="alternate"></link><published>2025-09-23T00:00:00+01:00</published><updated>2025-09-24T00:00:00+01:00</updated><author><name>Simon Harrison</name></author><id>tag:simonh.uk,2025-09-23:/2025/09/23/microsoft-edit-vs-gnu-nano/</id><summary type="html">	&lt;p&gt;An apple vs an orange&lt;/p&gt;</summary><content type="html">	&lt;p&gt;&lt;img alt="Edit v.1.2.0 running on Linux" src="/img/2025-09-23/edit_linux.webp" title="Edit v.1.2.0 running on Linux" /&gt;&lt;/p&gt;

	&lt;p&gt;I&amp;#8217;ve been seeing a few posts / videos claiming that Microsoft Edit is &lt;strong&gt;better&lt;/strong&gt; than &lt;span class="caps"&gt;GNU&lt;/span&gt; Nano. Sorry, it isn&amp;#8217;t. Furthermore, it hasn&amp;#8217;t been designed to be better than &lt;em&gt;anything&lt;/em&gt;! &lt;/p&gt;

	&lt;p&gt;Microsoft explained why they created Edit on their &lt;a href="https://devblogs.microsoft.com/commandline/edit-is-now-open-source/"&gt;Devblog&lt;/a&gt;:&lt;/p&gt;

	&lt;blockquote&gt;
		&lt;p&gt;&lt;em&gt;What motivated us to build Edit was the need for a default  CLI  text editor in 64-bit versions of Windows. 32-bit versions of Windows ship with the  MS-DOS editor , but 64-bit versions do not have a  CLI  editor installed inbox. From there, we narrowed down our options…&lt;/em&gt;&lt;/p&gt;
	&lt;/blockquote&gt;

	&lt;blockquote&gt;
		&lt;p&gt;&lt;em&gt;Many of you are probably familiar with the “How do I exit vim?” meme. While it is relatively simple to learn the magic exit incantation, it’s certainly not a coincidence that this often turns up as a stumbling block for new and old programmers.&lt;/em&gt;&lt;/p&gt;
	&lt;/blockquote&gt;

	&lt;blockquote&gt;
		&lt;p&gt;&lt;em&gt;Because we wanted to avoid this for a built-in default editor, we decided that we wanted a modeless editor for Windows (versus a modal editor where new users would have to remember different modes of operation and how to switch between them).&lt;/em&gt;&lt;/p&gt;
	&lt;/blockquote&gt;

	&lt;blockquote&gt;
		&lt;p&gt;&lt;em&gt;This unfortunately limited our choices to a list of editors that either had no first-party support for Windows or were too big to bundle them with every version of the OS. As a result, Edit was born.&lt;/em&gt;&lt;/p&gt;
	&lt;/blockquote&gt;

	&lt;p&gt;It should be noted that this &lt;em&gt;new&lt;/em&gt;, Rust written Edit, is a modern version of an old &lt;span class="caps"&gt;DOS&lt;/span&gt; program of the same name. Here&amp;#8217;s what that looked like:&lt;/p&gt;

	&lt;p&gt;&lt;img alt="DOS edit" src="/img/2025-09-23/edit_dos.webp" title="DOS edit" /&gt;&lt;/p&gt;

	&lt;p&gt;Edit is designed for very simple editing. Below is the &lt;em&gt;entire&lt;/em&gt; man page:&lt;/p&gt;

	&lt;p&gt;&lt;img alt="Manpage on Linux" src="/img/2025-09-23/edit_manpage.webp" title="Manpage on Linux" /&gt;&lt;/p&gt;

	&lt;p&gt;Nice and clear, and the program is learnable in approximately &lt;em&gt;5 minutes&lt;/em&gt;. In contrast, you&amp;#8217;ll probably need a couple of hours to fully learn and become productive with &lt;span class="caps"&gt;GNU&lt;/span&gt; Nano. They have different histories and purposes. Here is the first paragraph from the Nano &lt;span class="caps"&gt;README&lt;/span&gt;:&lt;/p&gt;

	&lt;p&gt;&lt;img alt="Nano history" src="/img/2025-09-23/nano_readme.webp" title="Nano history" /&gt;&lt;/p&gt;

	&lt;p&gt;Nano began life as a clone of Pico&lt;sup class="footnote" id="fnrevf5ed4a9ecbaf472bb2ef6f0ab7c7fe6f-1"&gt;&lt;a href="#fnf5ed4a9ecbaf472bb2ef6f0ab7c7fe6f-1"&gt;1&lt;/a&gt;&lt;/sup&gt;, then added features that users wished Pico had, whilst retaining its simple, easy to use nature. Edit is a re-implementation of &lt;span class="caps"&gt;DOS&lt;/span&gt; edit.com. The stated goal of Edit is&lt;/p&gt;

	&lt;blockquote&gt;
		&lt;p&gt;&lt;em&gt;&amp;#8230;to provide an accessible editor that even users largely unfamiliar with terminals can easily use.&lt;/em&gt;&lt;/p&gt;
	&lt;/blockquote&gt;

	&lt;p&gt;You can type characters, delete them, search and replace, and that&amp;#8217;s about it. Which is fine. Remember, this will ship with &lt;em&gt;Windows&lt;/em&gt;. Now I haven&amp;#8217;t used Windows at home since, maybe, 2006. MS Edit is not targeted at me, or anyone other than &lt;em&gt;their&lt;/em&gt; customers. It&amp;#8217;s there because they &lt;em&gt;should&lt;/em&gt; have a terminal text editor. It&amp;#8217;s not fancy or powerful but it will allow their customers to edit text files from the command line in a stress free way.&lt;/p&gt;

	&lt;p&gt;Personally, I like what they&amp;#8217;ve done. There&amp;#8217;s no configuration and no options to muck about with. You fire it up and do what you need to do. &lt;/p&gt;

	&lt;h2&gt;Conclusion&lt;/h2&gt;

	&lt;p&gt;I think Edit is a great bit of software. I like that Microsoft have released it as open source, and that they release Linux builds. I&amp;#8217;ve had a play with it and haven&amp;#8217;t felt the need to delete it. To my mind, it has already achieved it&amp;#8217;s stated goal. There&amp;#8217;s not really anything else that it needs at this point. I&amp;#8217;m sure Microsoft are fully aware that if they start adding new features, it becomes &lt;em&gt;harder&lt;/em&gt; to learn, &lt;em&gt;harder&lt;/em&gt; to use. &lt;span class="caps"&gt;GNU&lt;/span&gt; Nano doesn&amp;#8217;t have that contraint. It wants to be simple, but also useful. &lt;/p&gt;

	&lt;p&gt;Microsoft Edit is good but &lt;span class="caps"&gt;GNU&lt;/span&gt; Nano is better and always will be. &lt;/p&gt;

	&lt;h2 class="web"&gt;See Also&lt;/h2&gt;

	&lt;p&gt;&lt;a href="https://simonh.uk/2025/09/13/why-i-use-gnu-nano-as-my-default-editor/"&gt;Why I use &lt;span class="caps"&gt;GNU&lt;/span&gt; Nano as my Default Editor&lt;/a&gt;&lt;/p&gt;

	&lt;p&gt;&lt;a href="https://www.nano-editor.org/"&gt;&lt;span class="caps"&gt;GNU&lt;/span&gt; Nano Homepage&lt;/a&gt;&lt;/p&gt;

	&lt;p&gt;&lt;a href="https://github.com/microsoft/edit"&gt;Microsoft Edit Repository&lt;/a&gt;&lt;/p&gt;

	&lt;h2 class="footnotes"&gt;Footnotes&lt;/h2&gt;

	&lt;p class="footnote" id="fnf5ed4a9ecbaf472bb2ef6f0ab7c7fe6f-1"&gt;&lt;sup&gt;1&lt;/sup&gt; Pico (pi)ne (co)mposer was the editor for the &lt;a href="https://en.wikipedia.org/wiki/Pine_%28email_client%29"&gt;&lt;span class="caps"&gt;PINE&lt;/span&gt;&lt;/a&gt; email program. Very popular in the 90&amp;#8217;s and kept alive in the fork &lt;a href="https://alpineapp.email/"&gt;Alpine&lt;/a&gt; which I use on my servers.&lt;/p&gt;</content><category term="software"></category><category term="linux"></category><category term="windows"></category><category term="gnu"></category></entry><entry><title>Why I use GNU Nano as my Default Editor</title><link href="https://simonh.uk/2025/09/13/why-i-use-gnu-nano-as-my-default-editor/" rel="alternate"></link><published>2025-09-13T00:00:00+01:00</published><updated>2025-09-14T00:00:00+01:00</updated><author><name>Simon Harrison</name></author><id>tag:simonh.uk,2025-09-13:/2025/09/13/why-i-use-gnu-nano-as-my-default-editor/</id><summary type="html">	&lt;p&gt;Nano isn&amp;#8217;t Pico (or &lt;span class="caps"&gt;TIP&lt;/span&gt;)&lt;/p&gt;</summary><content type="html">	&lt;p&gt;&lt;img alt="GNU Nano Logo" src="/img/logo/nano-logo.png" title="GNU Nano Logo" /&gt;&lt;/p&gt;

	&lt;h2&gt;The Backstory&lt;/h2&gt;

	&lt;p&gt;For many years, my default text editor has been &lt;a href="https://community.linuxmint.com/software/view/xed"&gt;xed&lt;/a&gt; as it comes with Linux Mint, my distro of choice for some years. I&amp;#8217;ve used xed for most of the &lt;a href="https://bottlepy.org/docs/dev/"&gt;bottle.py&lt;/a&gt; programs I&amp;#8217;ve written. I never really thought about it, just used it as it got the job done. I generally use Nano for editing files over &lt;span class="caps"&gt;SSH&lt;/span&gt; and have also used that for many years.&lt;/p&gt;

	&lt;p&gt;A few weeks ago, I was thinking about my workflow and wondered why I wasn&amp;#8217;t using a terminal based editor? Here&amp;#8217;s how I use bottle.py&lt;/p&gt;

	&lt;p&gt;1. Fire up &lt;a href="https://github.com/tmux/tmux/wiki"&gt;tmux&lt;/a&gt;&lt;br /&gt;
2. Run &amp;#8220;python3 name-of-program.py&amp;#8220;&lt;br /&gt;
3. Open another tmux window for &lt;a href="https://www.mercurial-scm.org/"&gt;Mercurial&lt;/a&gt; checkins&lt;/p&gt;

	&lt;p&gt;Here&amp;#8217;s a screenshot of my terminal whilst writing this post:&lt;/p&gt;

	&lt;p&gt;&lt;img alt="" src="/img/2025-09-13/terminal.webp" /&gt;&lt;/p&gt;

	&lt;p&gt;It started bothering me that I was faffing about having to use my mouse to navigate between the terminal and my text editor. So I decided to find a terminal (non &lt;span class="caps"&gt;GUI&lt;/span&gt;) editor that would suit me. &lt;/p&gt;

	&lt;h2&gt;My Editor Requirements&lt;/h2&gt;

	&lt;p&gt;I was well aware of the &lt;strong&gt;hundreds&lt;/strong&gt; of editors available for Linux, having had a play with most of them at one time or another:&lt;/p&gt;

	&lt;p&gt;Emacs, Vim, Jed, Vile, Jove, Joe, Nano, mg, etc&amp;#8230;.&lt;/p&gt;

	&lt;p&gt;So I had a think about what was vital and what would be nice-to-have features.&lt;/p&gt;

	&lt;h3&gt;Vital&lt;/h3&gt;

	&lt;ul&gt;
		&lt;li&gt;&lt;strong&gt;Multiple buffers&lt;/strong&gt; &amp;#8212; I usually have at least two source code files open at a time when I&amp;#8217;m coding.&lt;/li&gt;
	&lt;/ul&gt;

	&lt;ul&gt;
		&lt;li&gt;&lt;strong&gt;Good support for keyboard shortcuts&lt;/strong&gt; &amp;#8212; Of course, this is subjective. Emacs and Vim let you do anything, but I don&amp;#8217;t normally need that much power! However, most things that I may need to do on a daily basis should have a shortcut.&lt;/li&gt;
	&lt;/ul&gt;

	&lt;ul&gt;
		&lt;li&gt;&lt;strong&gt;Remapping of keys&lt;/strong&gt; &amp;#8212; I&amp;#8217;ve used &lt;a href="https://colemak.com/"&gt;Colemak&lt;/a&gt; since about 2008, so what might be great for &lt;span class="caps"&gt;QWERTY&lt;/span&gt;, may not be great for me.&lt;/li&gt;
	&lt;/ul&gt;

	&lt;ul&gt;
		&lt;li&gt;&lt;strong&gt;Quickly delete lines&lt;/strong&gt; &amp;#8212; One of the features I really liked with Vim is &lt;code&gt;dd&lt;/code&gt; to delete a line, followed by &lt;code&gt;.&lt;/code&gt; to delete subsequent lines.&lt;/li&gt;
	&lt;/ul&gt;

	&lt;h3&gt;Nice to Have&amp;#8217;s&lt;/h3&gt;

	&lt;ul&gt;
		&lt;li&gt;&lt;strong&gt;Sensible Defaults&lt;/strong&gt; &amp;#8212; This is one of the things I&amp;#8217;ve always liked about Nano. You can just start using it. Shortcuts are visible at the bottom of the window if you need them.&lt;/li&gt;
	&lt;/ul&gt;

	&lt;ul&gt;
		&lt;li&gt;&lt;strong&gt;Show a line at 80 columns&lt;/strong&gt; &amp;#8212; I don&amp;#8217;t like long lines of code.&lt;/li&gt;
	&lt;/ul&gt;

	&lt;ul&gt;
		&lt;li&gt;&lt;strong&gt;Quickly comment / uncomment code&lt;/strong&gt; &amp;#8212; I got very used to xed&amp;#8217;s &lt;code&gt;Ctrl-/&lt;/code&gt; for this purpose!&lt;/li&gt;
	&lt;/ul&gt;

	&lt;ul&gt;
		&lt;li&gt;&lt;strong&gt;Auto ident&lt;/strong&gt; &amp;#8212; I use Python more than any other language, so auto indenting is hard to live without.&lt;/li&gt;
	&lt;/ul&gt;

	&lt;ul&gt;
		&lt;li&gt;&lt;strong&gt;Syntax Highlighting&lt;/strong&gt; &amp;#8212; Not 100% critical, but is often useful for seeing what&amp;#8217;s what.&lt;/li&gt;
	&lt;/ul&gt;

	&lt;ul&gt;
		&lt;li&gt;&lt;strong&gt;Bookmarks&lt;/strong&gt; &amp;#8212; Very useful to be able to mark lines in files and jump between them.&lt;/li&gt;
	&lt;/ul&gt;

	&lt;ul&gt;
		&lt;li&gt;&lt;strong&gt;Scroll without moving cursor&lt;/strong&gt; &amp;#8212; I liked this feature I first saw in Vim. You move the screen but the cursor stays where it is&lt;/li&gt;
	&lt;/ul&gt;

	&lt;ul&gt;
		&lt;li&gt;&lt;strong&gt;Insert a newline above / below current line&lt;/strong&gt; &amp;#8212; Some editors have a shortcut that will insert a newline without having to go to the end of the line, press enter&lt;/li&gt;
	&lt;/ul&gt;

	&lt;h2&gt;Where I Looked Closer at Nano&lt;/h2&gt;

	&lt;p&gt;I won&amp;#8217;t lie, Nano came first to mind. I was already familiar with it and it seems to be installed everywhere I need it. But did it do what I needed (and would like it to do)?&lt;/p&gt;

	&lt;p&gt;Yes, it would (I found out after an hour or so)!&lt;/p&gt;

	&lt;p&gt;I discovered pretty quickly that version 8, released in 2024 had introduced &amp;#8220;modern bindings&amp;#8221;:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;&lt;em&gt;Command-line option  -- modernbindings (-/) makes ^Q quit, ^X cut, ^C copy, ^V paste, ^Z undo, ^Y redo, ^O open a file, ^W write a file, ^R replace, ^G find again, ^D find again backwards, ^A set the mark, ^T jump to a line, ^P show the position, and ^E execute.&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;

	&lt;p&gt;I look at that as a sensible default. The original shortcuts aren&amp;#8217;t terrible, but I like the &lt;span class="caps"&gt;CUA&lt;/span&gt; ones more. So I downloaded the latest tarball (8.6) and compiled it. I added &lt;code&gt;alias nano="nano -/"&lt;/code&gt; to my &lt;code&gt;.bashrc&lt;/code&gt; (and on all my servers). &lt;/p&gt;

	&lt;h2&gt;What I Needed / Wanted&lt;/h2&gt;

	&lt;p&gt;&amp;check; multiple buffers: &lt;code&gt;set multibuffer&lt;/code&gt;&lt;br /&gt;
&amp;check; comment / uncomment code: &lt;code&gt;Alt-3&lt;/code&gt;&lt;br /&gt;
&amp;check; show end of line: &lt;code&gt;set guidestripe 80&lt;/code&gt;&lt;br /&gt;
&amp;check; syntax highlighting: &lt;code&gt;include /usr/local/share/nano/*.nanorc&lt;/code&gt;&lt;br /&gt;
&amp;check; quickly delete lines:&lt;br /&gt;
&lt;code&gt;Alt-delete&lt;/code&gt; to delete entire line&lt;br /&gt;
&lt;code&gt;Alt-backspace&lt;/code&gt; to  delete words&lt;br /&gt;
&amp;check; bookmarks: &amp;#8220;anchors&amp;#8221; in Nano speak.&lt;br /&gt;
&lt;code&gt;Alt-Insert&lt;/code&gt; to set/unset.&lt;br /&gt;
&lt;code&gt;Alt-PgUp&lt;/code&gt; / &lt;code&gt;Alt-PgDn&lt;/code&gt; to cycle through them&lt;br /&gt;
&amp;check; move viewport up and down: &lt;code&gt;Alt--&lt;/code&gt; / &lt;code&gt;Alt-+&lt;/code&gt;&lt;br /&gt;
&amp;check; insert a newline above / below current line&lt;br /&gt;
&lt;code&gt;bind ^N "{home}{enter}{up}" main&lt;/code&gt; &lt;br /&gt;
&lt;code&gt;bind ^k "{end}{enter}" main&lt;/code&gt;&lt;/p&gt;

	&lt;h2&gt;My Tweaks&lt;/h2&gt;

	&lt;p&gt;Many, many years ago,&lt;sup class="footnote" id="fnrev7c230fde80d3487a964040ef54382d56-1"&gt;&lt;a href="#fn7c230fde80d3487a964040ef54382d56-1"&gt;1&lt;/a&gt;&lt;/sup&gt; I came across the idea of having the arrow keys accessible on the home row using either the &lt;code&gt;CTRL&lt;/code&gt; or &lt;code&gt;ALT&lt;/code&gt; keys. Similar to this keyboard:&lt;/p&gt;

	&lt;p&gt;&lt;img alt="" src="/img/2025-09-13/arrow_keys.png" /&gt;&lt;/p&gt;

	&lt;p&gt;As I was hoping to somewhat optimize my text editing, I figured I&amp;#8217;d try and get some often used keys where I wanted them.&lt;sup class="footnote" id="fnrev7c230fde80d3487a964040ef54382d56-2"&gt;&lt;a href="#fn7c230fde80d3487a964040ef54382d56-2"&gt;2&lt;/a&gt;&lt;/sup&gt; Using &lt;span class="caps"&gt;QWERTY&lt;/span&gt; notation, I now have:&lt;/p&gt;

	&lt;p&gt;&lt;code&gt;Alt-j&lt;/code&gt; &amp;#8212; Left&lt;br /&gt;
&lt;code&gt;Alt-k&lt;/code&gt; &amp;#8212; Down&lt;br /&gt;
&lt;code&gt;Alt-i&lt;/code&gt; &amp;#8212; Up&lt;br /&gt;
&lt;code&gt;Alt-l&lt;/code&gt; &amp;#8212; Right&lt;br /&gt;
&lt;code&gt;Alt-u&lt;/code&gt; &amp;#8212; Home&lt;br /&gt;
&lt;code&gt;Alt-o&lt;/code&gt; &amp;#8212; End&lt;br /&gt;
&lt;code&gt;Alt-h&lt;/code&gt; &amp;#8212; Delete&lt;br /&gt;
&lt;code&gt;Ctrl-k&lt;/code&gt; &amp;#8212; Page Down&lt;br /&gt;
&lt;code&gt;Ctrl-i&lt;/code&gt; &amp;#8212; Page Up&lt;/p&gt;

	&lt;p&gt;Very nice! I&amp;#8217;m already used to them after only a few days. If you&amp;#8217;re interested, below is my &lt;code&gt;.nanorc&lt;/code&gt;&lt;/p&gt;

	&lt;h2&gt;My .nanorc&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;# $Id: .nanorc,v 1.6 2025/09/15 13:29:21 simon Exp simon $

set multibuffer
set tabsize 4
set tabstospaces
set autoindent
set wordbounds
set quickblank
set trimblanks
set linenumbers
set smarthome
set mouse
set indicator
set guidestripe 80
set positionlog
set quickblank
set stateflags

set brackets &amp;quot;&amp;quot;&amp;#39;)&amp;gt;]}&amp;quot;
set matchbrackets &amp;quot;(&amp;lt;[{)&amp;gt;]}&amp;quot;

set keycolor cyan
set functioncolor cyan
set numbercolor yellow

bind M-5 cycle main

#=============================================
# Experimental: bring useful keys to home row
#=============================================

bind M-n left main
bind M-i right main
bind M-u up main
bind M-e down main
bind M-l home main
bind M-y end main
bind M-h delete main

bind ^u pageup main
bind ^e pagedown main

# newline above current line
bind ^n &amp;quot;{home}{enter}{up}&amp;quot; main

# newline below current line
bind ^k &amp;quot;{end}{enter}&amp;quot; main

include /usr/local/share/nano/*.nanorc
include &amp;quot;~/.nano/tpl.nanorc&amp;quot;&lt;/code&gt;&lt;/pre&gt;

	&lt;h2&gt;Why Not Just Use&amp;#8230;&lt;/h2&gt;

	&lt;p&gt;Of course, anyone who comes here may have their own, possibly strong, opinions about which text editor is &lt;em&gt;the one true editor&lt;/em&gt;. Fair enough, but I can&amp;#8217;t be bothered to spend weeks learning how to use a text editor. &lt;/p&gt;

	&lt;p&gt;I set out to find a &lt;span class="caps"&gt;TUI&lt;/span&gt; editor to do my work with and have found it with &lt;span class="caps"&gt;GNU&lt;/span&gt; Nano.&lt;/p&gt;

	&lt;p&gt;I&amp;#8217;ll quickly mention why some other, obvious editors didn&amp;#8217;t beat Nano for me.&lt;/p&gt;

	&lt;p&gt;1. Emacs&lt;/p&gt;

	&lt;p&gt;Sorry, but having to type &lt;code&gt;Ctrl-X Ctrl-C&lt;/code&gt; to exit isn&amp;#8217;t for me.&lt;/p&gt;

	&lt;p&gt;2. Vim&lt;/p&gt;

	&lt;p&gt;Philosophically, I like the idea of a modal editor. However, in practice, I&amp;#8217;ve always found Vim&amp;#8217;s learning curve not worth the time. If I wrote software for a living, instead of as a hobby, I might invest more time in learning it. Maybe&amp;#8230;&lt;/p&gt;

	&lt;p&gt;3. Micro&lt;/p&gt;

	&lt;p&gt;Micro does seem interesting. However, Nano with &lt;code&gt;--modern-bindings&lt;/code&gt; possibly makes it less interesting.&lt;/p&gt;

	&lt;h2&gt;Conclusion&lt;/h2&gt;

	&lt;p&gt;Like a lot of people, I&amp;#8217;ve been unaware of exactly what Nano is capable of. I&amp;#8217;ve been pressing pageup repeatedly to get to the top of the screen when I could have just pressed &lt;code&gt;Ctrl-home&lt;/code&gt; or &lt;code&gt;Ctrl-end&lt;/code&gt; to go to the beginning or end of the file. &lt;/p&gt;

	&lt;p&gt;Likewise, I never knew that &lt;code&gt;Alt-home&lt;/code&gt; and &lt;code&gt;Alt-end&lt;/code&gt; would take me to the first / last lines in the viewport.&lt;/p&gt;

	&lt;p&gt;Embarrassingly, I didn&amp;#8217;t know that Nano supported multiple buffers. So like a fool, I&amp;#8217;d edit one file on a server, close it, open another one, close that, open the first one again&amp;#8230;&lt;/p&gt;

	&lt;p&gt;Today I&amp;#8217;ve just found that Nano supports &lt;em&gt;soft wrapping&lt;/em&gt; using &lt;code&gt;Alt-s&lt;/code&gt; which has proven useful writing this post in Textile where unwanted newlines are inserted.&lt;/p&gt;

	&lt;p&gt;I think some people in the Linux world see Nano as our Windows Notepad. Not something to be used by serious people with serious things to do. I never thought that, but after reading the excellent documentation on the Nano website (and man / info pages) I&amp;#8217;m now aware of exactly what it can do.&lt;/p&gt;

	&lt;p&gt;I hope that you too, will have another look at this awesome little editor.&lt;/p&gt;

	&lt;p&gt;&lt;a href="https://www.nano-editor.org/"&gt;&lt;img align="center" alt="" src="/img/logo/withnano.png" /&gt;&lt;/a&gt;&lt;/p&gt;

	&lt;h2 class="footnotes"&gt;Footnotes&lt;/h2&gt;

	&lt;p class="footnote" id="fn7c230fde80d3487a964040ef54382d56-1"&gt;&lt;sup&gt;1&lt;/sup&gt; I believe it was Ergoemacs that introduced me to this idea.&lt;/p&gt;

	&lt;p class="footnote" id="fn7c230fde80d3487a964040ef54382d56-2"&gt;&lt;sup&gt;2&lt;/sup&gt; If you want to do this yourself, here are a couple of tips. You press control by moving your palm outwards and &lt;em&gt;not&lt;/em&gt; by stretching your pinky! Alt is pressed by moving your thumb outwards. It takes a bit of getting used to but is worth it, I think.&lt;/p&gt;</content><category term="software"></category><category term="software"></category><category term="linux"></category><category term="gnu"></category></entry><entry><title>Trying Out OpenBSD Game of Trees (Got)</title><link href="https://simonh.uk/2025/06/08/trying-out-openbsd-game-of-trees-got/" rel="alternate"></link><published>2025-06-08T00:00:00+01:00</published><updated>2025-06-08T00:00:00+01:00</updated><author><name>Simon Harrison</name></author><id>tag:simonh.uk,2025-06-08:/2025/06/08/trying-out-openbsd-game-of-trees-got/</id><summary type="html">	&lt;p&gt;Is less more?&lt;/p&gt;</summary><content type="html">	&lt;p&gt;&lt;a href="https://gameoftrees.org"&gt;&lt;img alt="Got Website" src="/img/2025-06-08/got.webp" title="Got Website" /&gt;&lt;/a&gt;&lt;/p&gt;

	&lt;h2&gt;Background &amp;amp; Motivations&lt;/h2&gt;

	&lt;p&gt;I&amp;#8217;ve been a Mercurial user since about 2017. It&amp;#8217;s always worked well for me, &lt;em&gt;but&lt;/em&gt; I&amp;#8217;ve found myself wondering over the last couple of years if another &lt;span class="caps"&gt;VCS&lt;/span&gt; might be a better fit for me. One reason is that I&amp;#8217;m not an advanced user, using only a fraction of what Mercurial has to offer. I don&amp;#8217;t collaborate with anyone else so I only need to record changes, push my code out to backup servers, revert (occasionally), email patches to my production servers etc. &lt;/p&gt;

	&lt;p&gt;So today, I decided to use Got to track changes on a real project and this post documents how it went. &lt;/p&gt;

	&lt;h2&gt;Installation&lt;/h2&gt;

	&lt;p&gt;We&amp;#8217;ll need to download and compile Got from &lt;a href="https://gameoftrees.org/releases/portable/"&gt;here&lt;/a&gt;. At the time of writing version 0.113 is the latest. Then, it&amp;#8217;s the usual:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;./configure
make
sudo make install&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Which will install Got to &lt;code&gt;/usr/local&lt;/code&gt;&lt;/p&gt;

	&lt;p&gt;To check everything worked, run:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~$ got -h
usage: got [-hV] command [arg ...]
commands: init import clone fetch checkout update log diff blame tree status ref branch tag add remove patch revert commit send cherrypick backout rebase histedit integrate merge stage unstage cat info&lt;/code&gt;&lt;/pre&gt;

	&lt;h2&gt;The Got Way&lt;/h2&gt;

	&lt;p&gt;One of the things I found most appealing about Got is that repositories and work trees &lt;strong&gt;have&lt;/strong&gt; to live in different locations. When you think about it, that makes complete sense. Most of us are used to having our repo&amp;#8217;s inside our working directory. Yes, it&amp;#8217;s convenient but I&amp;#8217;ve now come to the conclusion that it&amp;#8217;s not optimal. Your repo is one thing, your working directory is another thing. &lt;/p&gt;

	&lt;h2&gt;Creating the Repo and importing code&lt;/h2&gt;

	&lt;p&gt;As this project is a static web site, I dectided to create a separate directory for my repo:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;got init /home/simon/tmp/repo/first_project.got&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;There&amp;#8217;s no requirement to append &lt;code&gt;.got&lt;/code&gt; to the project, but it reminds me what I&amp;#8217;m using. &lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~/tmp$ tree repo/first_project.got/&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Let&amp;#8217;s have a look to see what Got has created for us:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;tree repo/first_project.got
repo/first_project.got/
├── config
├── description
├── HEAD
├── objects
│   └── pack
└── refs

4 directories, 3 files&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Looks good. The next step may seem a bit clunky, but is what we need to do:&lt;/p&gt;

	&lt;ul&gt;
		&lt;li&gt;Import code into our repository&lt;/li&gt;
		&lt;li&gt;Check out the repository to a worktree&lt;/li&gt;
	&lt;/ul&gt;

	&lt;p&gt;Right now, our repo is empty. Let&amp;#8217;s do our first checkin:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~/tmp$ got import -r repo/first_project.got/ first_project/
A  /home/simon/tmp/first_project/css/pico.min.css
A  /home/simon/tmp/first_project/css/tacit.min.css
A  /home/simon/tmp/first_project/fonts/Inter-Italic-VariableFont_opsz,wght.woff2
A  /home/simon/tmp/first_project/fonts/Inter-VariableFont_opsz,wght.woff2
A  /home/simon/tmp/first_project/software/visitors/index.html
A  /home/simon/tmp/first_project/banner.png
A  /home/simon/tmp/first_project/index.html
Created branch refs/heads/main with commit 95f800a6d501db76d7fe56978e6c396d0c3736bb&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Now that our working directory&amp;#8217;s contents have been added to our repo, we can delete the working directory and check out a worktree:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~/tmp$ rm -r first_project&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~/tmp$ got co repo/first_project.got/ first_project
A  first_project/asus.png
A  first_project/css/pico.min.css
A  first_project/css/tacit.min.css
A  first_project/fonts/Inter-Italic-VariableFont_opsz,wght.woff2
A  first_project/fonts/Inter-VariableFont_opsz,wght.woff2
A  first_project/index.html
A  first_project/software/visitors/index.html
Checked out refs/heads/main: 95f800a6d501db76d7fe56978e6c396d0c3736bb
Now shut up and hack&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Now, inside our worktree&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~/tmp/first_project$ got log
-----------------------------------------------
commit 95f800a6d501db76d7fe56978e6c396d0c3736bb (main)
from: Simon Harrison &amp;lt;mail@simonh.uk&amp;gt;
date: Sun Jun  8 20:16:54 2025 UTC

 First checkin&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Got uses a hidden directory to keep track of things &amp;#8212; &lt;code&gt;.got&lt;/code&gt;. Let&amp;#8217;s see what&amp;#8217;s in there:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~/tmp/first_project$ ll
total 116K
drwxr-xr-x  6 simon simon 4.0K 2025-06-08 21:21 .
drwxrwxrwx 11 simon simon 4.0K 2025-06-08 21:21 ..
-rw-r--r--  1 simon simon  84K 2025-06-08 21:21 asus.png
drwxr-xr-x  2 simon simon 4.0K 2025-06-08 21:21 css
drwxr-xr-x  2 simon simon 4.0K 2025-06-08 21:21 fonts
drwxr-xr-x  2 simon simon 4.0K 2025-06-08 21:21 .got
-rw-r--r--  1 simon simon 4.6K 2025-06-08 21:21 index.html
drwxr-xr-x  3 simon simon 4.0K 2025-06-08 21:21 software
simon@computer:~/tmp/first_project$ tree .got
.got
├── base-commit
├── file-index
├── format
├── head-ref
├── lock
├── path-prefix
├── repository
└── uuid

1 directory, 8 files&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Obviously, we&amp;#8217;ll leave all that alone as Got will update them as we check in changes. &lt;/p&gt;

	&lt;p&gt;So at this point, we&amp;#8217;re all setup to track changes to our code. The last thing I want to do right now is set up a backup that I can push to one of my servers.&lt;/p&gt;

	&lt;p&gt;We&amp;#8217;ll do that in our repo:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~/tmp/first_project.got$ nano got.conf&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;And add the following, adjusting to fit your server&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;remote &amp;quot;simonh&amp;quot; {
  server myserver.com
  protocol ssh
  repository &amp;quot;/home/simon/repo/got/first_project.got&amp;quot;
}&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;For this to work, we need to create a Got repo on our server that matches the &lt;code&gt;repository&lt;/code&gt; value above.&lt;/p&gt;

	&lt;p&gt;With this done, we can &lt;code&gt;got send&lt;/code&gt; our changes. By the way, most commands have aliases:&lt;/p&gt;

	&lt;ul&gt;
		&lt;li&gt;&lt;code&gt;ci&lt;/code&gt; &amp;#8212; commit&lt;/li&gt;
		&lt;li&gt;&lt;code&gt;co&lt;/code&gt; &amp;#8212; checkout&lt;/li&gt;
		&lt;li&gt;&lt;code&gt;se&lt;/code&gt; &amp;#8212; send&lt;/li&gt;
		&lt;li&gt;&lt;code&gt;fe&lt;/code&gt; &amp;#8212; fetch&lt;/li&gt;
		&lt;li&gt;&lt;code&gt;pa&lt;/code&gt; &amp;#8212; patch&lt;/li&gt;
	&lt;/ul&gt;

	&lt;p&gt;Consult the excellent man pages for the full list. Let&amp;#8217;s send our changes to keep them safe:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~/tmp/first_project$ got se simonh
Connecting to &amp;quot;simonh&amp;quot; ssh://myserver.com/home/simon/repo/got/first_project.got
2 commits colored; 3 objects found; 6 trees scanned
packing 1 reference; 3 objects; deltify: 100%; uploading pack:  2.7K 100%
Server has accepted refs/heads/main&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Got also comes with Tog, a &lt;span class="caps"&gt;CLI&lt;/span&gt; repository browser:&lt;/p&gt;

	&lt;p&gt;&lt;img alt="Tog repository browser" src="/img/2025-06-08/tog.webp" title="Tog repository browser" /&gt;&lt;/p&gt;

	&lt;h2&gt;Creating &amp;amp; Listing Tags&lt;/h2&gt;

	&lt;p&gt;Tags are equivalent to Mercurial bookmarks &amp;#8212; a label for a commit. &lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~/tmp/first_project$ got tag -l
-----------------------------------------------
tag 0.2 807e609a829c43a9f3f9c8d4c1214b4371fe4485
from: Simon Harrison &amp;lt;mail@simonh.uk&amp;gt;
date: Sun Jun  8 16:12:03 2025 UTC
object: commit 3aa38f1608aee14a1a90a7eae3928f83e4c14baa

 Second test of using tags

-----------------------------------------------
tag 0.1 c291af4175f48db379169437ac1a09e381a631f8
from: Simon Harrison &amp;lt;mail@simonh.uk&amp;gt;
date: Sun Jun  8 13:34:21 2025 UTC
object: commit 8e431b7a506992d02d5e39b283652bb5d3ae9d03

 Just testing out tags&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Passing &lt;code&gt;-s&lt;/code&gt; gives us a &lt;em&gt;short&lt;/em&gt; one line summary:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~/tmp/first_project$ got tag -ls
2025-06-08 commit:3aa38f1608 0.2: Second test of using tags
2025-06-08 commit:8e431b7a50 0.1: Just testing out tags&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;We can create a tag easily:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~/tmp/first_project$ got tag &amp;#39;0.3&amp;#39;
Created tag d1d6792cb83866567525f66875b983faf7dcd4d7

simon@computer:~/tmp/first_project$ got tag -sl
2025-06-09 commit:f257381e43 0.3: Third version
2025-06-08 commit:3aa38f1608 0.2: Second test of using tags
2025-06-08 commit:8e431b7a50 0.1: Just testing out tags&lt;/code&gt;&lt;/pre&gt;

	&lt;h2&gt;Branching &amp;amp; Merging&lt;/h2&gt;

	&lt;p&gt;To be honest, I don&amp;#8217;t branch. If that changes I&amp;#8217;ll update this section.&lt;/p&gt;

	&lt;h2&gt;Conclusion&lt;/h2&gt;

	&lt;p&gt;Initial setup for basic tracking of changes should take no more than fifteen / twenty minutes. Once you&amp;#8217;ve done that, you&amp;#8217;ll have a nice, well-documented &lt;span class="caps"&gt;VCS&lt;/span&gt; that has a tight focus. I&amp;#8217;m going to continue using Got for this one project. I should point out that Got is not Git. Many features are not implemented (and may never be). However, it&amp;#8217;s perfectly usable right now and if you&amp;#8217;re looking for a &lt;em&gt;no frills&lt;/em&gt; &lt;span class="caps"&gt;VCS&lt;/span&gt;, Got may be just what you need.&lt;/p&gt;

	&lt;h2 class="web"&gt;See Also&lt;/h2&gt;

	&lt;p&gt;I wrote a post last year &lt;a href="https://simonh.uk/2024/10/29/first-look-at-openbsd-game-of-trees-got/"&gt;first look at Got&lt;/a&gt;  which may be of interest.&lt;/p&gt;</content><category term="software"></category><category term="version control"></category></entry><entry><title>First Look at OpenBSD Game of Trees (Got)</title><link href="https://simonh.uk/2024/10/29/first-look-at-openbsd-game-of-trees-got/" rel="alternate"></link><published>2024-10-29T00:00:00+00:00</published><updated>2024-10-29T00:00:00+00:00</updated><author><name>Simon Harrison</name></author><id>tag:simonh.uk,2024-10-29:/2024/10/29/first-look-at-openbsd-game-of-trees-got/</id><summary type="html">	&lt;p&gt;Git stripped back to the bare essentials&lt;/p&gt;</summary><content type="html">	&lt;h1&gt;Git, but simpler (to use, maybe&amp;#8230;)&lt;/h1&gt;

	&lt;p&gt;&lt;img alt="Game of trees logo" src="/img/2024-10-29/got.webp" title="Game of trees logo" /&gt;&lt;/p&gt;

	&lt;p&gt;I&amp;#8217;m a long time &lt;a href="https://www.mercurial-scm.org/"&gt;Mercurial&lt;/a&gt; user. Even so, I keep my eye on other &lt;span class="caps"&gt;VCS&lt;/span&gt;&amp;#8217;s to see what new ideas are developing. A few weeks ago, I came across &lt;a href="https://gameoftrees.org/"&gt;Got&lt;/a&gt;, a reimplementation / reimagining of &lt;a href="https:///git-scm.com"&gt;Git&lt;/a&gt; for use by the OpenBSD people, under a &lt;span class="caps"&gt;BSD&lt;/span&gt; compatible licence.&lt;/p&gt;

	&lt;p&gt;Got claims to take some of the best features from &lt;span class="caps"&gt;CVS&lt;/span&gt;, &lt;span class="caps"&gt;SVN&lt;/span&gt;, Git, Mercurial and Fossil. This I found very interesting. Here are the most noticeable differences I&amp;#8217;ve noticed (for a Git or Mercurial user).&lt;/p&gt;

	&lt;ul&gt;
		&lt;li&gt;Repositories must checked out to a worktree.&lt;/li&gt;
	&lt;/ul&gt;

	&lt;p&gt;Hg and Git users are used to having the repository &lt;em&gt;inside&lt;/em&gt; the worktree (working directory). Got treats a repository and a worktree as two completely different things. Or rather, Got treats the repository as one thing and you can have as many worktrees as you need. The benefit of this model is that you can have different branches checked out at the same time. You can checkout only a subset of the repository. This is also the same model that Fossil uses. When I tried using Fossil years ago, I intensely disliked this &amp;#8220;feature&amp;#8221;, but I&amp;#8217;m now starting to think it makes sense. &lt;/p&gt;

	&lt;ul&gt;
		&lt;li&gt;No built in help&lt;/li&gt;
	&lt;/ul&gt;

	&lt;p&gt;As always, OpenBSD prefers to have excellent man pages to document their software and answer any question you might have. &lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~$ got help
got: unknown command &amp;#39;help&amp;#39;
commands: init import clone fetch checkout update log diff blame tree status ref branch tag add remove patch revert commit send cherrypick backout rebase histedit integrate merge stage unstage cat info&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Whether that&amp;#8217;s planned to change, I&amp;#8217;m not sure. Probably not.&lt;/p&gt;

	&lt;ul&gt;
		&lt;li&gt;Some important features are currently missing&lt;/li&gt;
	&lt;/ul&gt;

	&lt;p&gt;Last time I checked, file renames weren&amp;#8217;t automatically handled. I believe this is planned to change. Little, quality of life features like &lt;code&gt;hg email&lt;/code&gt; will probably never be implemented. &lt;/p&gt;

	&lt;ul&gt;
		&lt;li&gt;There&amp;#8217;s a steeper learning curve&lt;/li&gt;
	&lt;/ul&gt;

	&lt;p&gt;You really do have to &lt;span class="caps"&gt;RTFM&lt;/span&gt; when it comes to Got. I got stuck on some basic stuff and asked on &lt;span class="caps"&gt;IRC&lt;/span&gt; for assistance. The lead developer, Stefan Sperling is actually a very helpful guy and got me going. Still, be prepared to read the entire man page!&lt;/p&gt;

	&lt;h1&gt;Features I&amp;#8217;d love to see&lt;/h1&gt;

	&lt;ul&gt;
		&lt;li&gt;hg shelve / Git stash&lt;/li&gt;
	&lt;/ul&gt;

	&lt;p&gt;Set aside changes and bring them back later. Very useful, (nearly) impossible to live with once you&amp;#8217;ve used it.&lt;/p&gt;

	&lt;ul&gt;
		&lt;li&gt;Easy emailing of patches&lt;/li&gt;
	&lt;/ul&gt;

	&lt;p&gt;I use &lt;code&gt;hg email -r tip&lt;/code&gt; &lt;em&gt;all the time&lt;/em&gt; when I&amp;#8217;m working on a project.&lt;/p&gt;

	&lt;ul&gt;
		&lt;li&gt;Local revision numbers&lt;/li&gt;
	&lt;/ul&gt;

	&lt;p&gt;Mercurial is (I think) the only current &lt;span class="caps"&gt;VCS&lt;/span&gt; that has local revision numbers. That feature is just &lt;em&gt;so handy&lt;/em&gt;. Much easier for humans to deal with &lt;code&gt;revision 17&lt;/code&gt; than &lt;code&gt;revision bf63491f5a5b&lt;/code&gt;&lt;/p&gt;

	&lt;h2&gt;Conclusion&lt;/h2&gt;

	&lt;p&gt;Got makes it clear on their website they aren&amp;#8217;t seeking to replace anything or to steal you away from your &lt;span class="caps"&gt;VCS&lt;/span&gt; of choice. In the &lt;span class="caps"&gt;FAQ&lt;/span&gt; they state:&lt;/p&gt;

	&lt;blockquote&gt;
		&lt;p&gt;If you are wondering why Got even exists, you can just ignore it.&lt;/p&gt;
	&lt;/blockquote&gt;

	&lt;p&gt;Quite right. There are &lt;strong&gt;far&lt;/strong&gt; too many people on the internet moaning that &lt;em&gt;their&lt;/em&gt; thing is the only thing that matters and if everyone would just use it everyone would be far happier as a result. Got isn&amp;#8217;t one of those projects. &lt;/p&gt;

	&lt;p&gt;It&amp;#8217;s written by, and for, the OpenBSD crew. There&amp;#8217;s a portable port for us Linux types. I&amp;#8217;ll be keeping an eye on this one in case it ends up as useful as &lt;a href="https://opensmtpd.org/"&gt;OpenSMTPD&lt;/a&gt;&lt;/p&gt;</content><category term="software"></category><category term="version control"></category></entry><entry><title>Using GNU RCS for Managing Configuration Files</title><link href="https://simonh.uk/2023/08/25/using-gnu-rcs-for-managing-configuration-files/" rel="alternate"></link><published>2023-08-25T00:00:00+01:00</published><updated>2023-08-25T00:00:00+01:00</updated><author><name>Simon Harrison</name></author><id>tag:simonh.uk,2023-08-25:/2023/08/25/using-gnu-rcs-for-managing-configuration-files/</id><summary type="html">	&lt;p&gt;Why didn&amp;#8217;t anyone tell me about this years ago?!&lt;/p&gt;</summary><content type="html">	&lt;p&gt;&lt;img alt="GNU Logo" src="/img/logo/gnu.webp" title="GNU Logo" /&gt;&lt;/p&gt;

	&lt;p&gt;As regular readers will know, I&amp;#8217;m a big fan of version control for software projects. You may also know that I&amp;#8217;ve recently started to use &lt;span class="caps"&gt;RCS&lt;/span&gt; for managing single files (shell/Python scripts, &lt;span class="caps"&gt;CGI&lt;/span&gt; scripts etc.). Tonight, I&amp;#8217;d like to present my &lt;strong&gt;simple&lt;/strong&gt; workflow for version controlling configuration files, also using &lt;span class="caps"&gt;RCS&lt;/span&gt;.&lt;/p&gt;

	&lt;h2&gt;The Problem&lt;/h2&gt;

	&lt;p&gt;We Linux users frequently have to create and edit config files. Here is a list of some of mine:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;.vimrc
.nanorc
/etc/smtpd.conf
/etc/aliases
/etc/hosts
/etc/apache2/*
/etc/apt/sources*
...&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Up until recently, I&amp;#8217;d usually rename a config file to &lt;code&gt;&amp;lt;filename&amp;gt;.bak&lt;/code&gt; in case something went horribly wrong. Come to think of it, that&amp;#8217;s pretty much &lt;b&gt;always&lt;/b&gt; the advice you&amp;#8217;ll be given online. &lt;/p&gt;

	&lt;p&gt;Of course, there&amp;#8217;s a better, more robust way of keeping track of changes you&amp;#8217;ve made, with the ability to roll back to any previous revision. But, it does take a little bit of discipline!&lt;/p&gt;

	&lt;h2&gt;The Solution&lt;/h2&gt;

	&lt;p&gt;Let&amp;#8217;s say you need to edit your &lt;code&gt;.nanorc&lt;/code&gt; &lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~$ mkdir RCS
mkdir: cannot create directory ‘RCS’: File exists&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;OK, good. I&amp;#8217;ve already got a repository setup in my home directory. Let&amp;#8217;s open it up and see what it contains:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;nano .nanorc
 GNU nano 6.2                         .nanorc                                  



















                                [ Read 0 lines ]
^G Help      ^O Write Out ^W Where Is  ^K Cut       ^T Execute   ^C Location
^X Exit      ^R Read File ^\ Replace   ^U Paste     ^J Justify   ^/ Go To Line&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;An empty file which means the file either didn&amp;#8217;t exist or was empty. Let&amp;#8217;s get to work. I&amp;#8217;ll add the settings I want, plus the &lt;span class="caps"&gt;RCS&lt;/span&gt; metadata so I can see the current version number and the date it was checked in:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  GNU nano 6.2                         .nanorc                           I   S  
#=====================================================================
# $Revision$
# $Date$
# $Author$
#======================================================================

set autoindent
set tabsize 4
set tabstospaces
set softwrap









                               [ Read 10 lines ]
^G Help      ^O Write Out ^W Where Is  ^K Cut       ^T Execute   ^C Location
^X Exit      ^R Read File ^\ Replace   ^U Paste     ^J Justify   ^/ Go To Line&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Now let&amp;#8217;s checkin the file&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~$ ci -l .nanorc 
RCS/.nanorc,v  &amp;lt;--  .nanorc
enter description, terminated with single &amp;#39;.&amp;#39; or end of file:
NOTE: This is NOT the log message!
&amp;gt;&amp;gt; First checkin 
&amp;gt;&amp;gt; .
initial revision: 1.1
done
simon@computer:~$ &lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Let&amp;#8217;s have a look at the file&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~$ cat .nanorc 
#=====================================================================
# $Revision: 1.1 $
# $Date: 2023/08/25 19:11:01 $
# $Author: simon $
#======================================================================

set autoindent
set tabsize 4
set tabstospaces
set softwrap&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;So, three things are immediately evident:&lt;/p&gt;

	&lt;p&gt;1. The file is version controlled&lt;br /&gt;
2. I can see how many revisions have been made to the file&lt;br /&gt;
3. I can see the datetime of the last revision. Nice. &lt;/p&gt;

	&lt;p&gt;I read somewhere that it&amp;#8217;s a good idea to add the .nanorc files from the &lt;code&gt;/usr/share/nano/*&lt;/code&gt; directory to enable syntax highlighting for lots of filetypes. Let&amp;#8217;s add that to my &lt;code&gt;.nanorc&lt;/code&gt; file:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  GNU nano 6.2                         .nanorc                           I   S  
#=====================================================================
# $Revision: 1.1 $
# $Date: 2023/08/25 19:11:01 $
# $Author: simon $
#======================================================================

set autoindent
set tabsize 4
set tabstospaces
set softwrap

include &amp;quot;/usr/share/nano/*.nanorc&amp;quot;







                               [ Read 13 lines ]
^G Help      ^O Write Out ^W Where Is  ^K Cut       ^T Execute   ^C Location
^X Exit      ^R Read File ^\ Replace   ^U Paste     ^J Justify   ^/ Go To Line&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Now I&amp;#8217;ll checkin the change&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~$ ci -l ./.nanorc 
./RCS/.nanorc,v  &amp;lt;--  ./.nanorc
new revision: 1.2; previous revision: 1.1
enter log message, terminated with single &amp;#39;.&amp;#39; or end of file:
&amp;gt;&amp;gt; Add all .nanorc files from /usr/share/nano/*
&amp;gt;&amp;gt; .
done
simon@computer:~$ &lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;If I accidently try and checkin an unchanged file, &lt;span class="caps"&gt;RCS&lt;/span&gt; will say:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~$ ci -l ./.nanorc 
./RCS/.nanorc,v  &amp;lt;--  ./.nanorc
file is unchanged; reverting to previous revision 1.2
done&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;If you&amp;#8217;re ever unsure you can always run &lt;code&gt;rlog&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~$ rlog ./.nanorc 

RCS file: ./RCS/.nanorc,v
Working file: ./.nanorc
head: 1.2
branch:
locks: strict
        simon: 1.2
access list:
symbolic names:
keyword substitution: kv
total revisions: 2;     selected revisions: 2
description:
First checkin
----------------------------
revision 1.2    locked by: simon;
date: 2023/08/25 19:20:20;  author: simon;  state: Exp;  lines: +6 -3
Add all .nanorc files from /usr/share/nano/*
----------------------------
revision 1.1
date: 2023/08/25 19:11:01;  author: simon;  state: Exp;
Initial revision
=============================================================================&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Yep, 1.2 is the latest revision. Another option is to run &lt;code&gt;rcsdiff&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~$ rcsdiff ./.nanorc 
===================================================================
RCS file: ./RCS/.nanorc,v
retrieving revision 1.2
diff -r1.2 ./.nanorc&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;No changes are shown (as no changes have been made). &lt;/p&gt;

	&lt;p&gt;What if we have changes? I&amp;#8217;ll add the setting to show line numbers (without checking the file in):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~$ rcsdiff -u ./.nanorc 
===================================================================
RCS file: ./RCS/.nanorc,v
retrieving revision 1.2
diff -u -r1.2 ./.nanorc
--- ./.nanorc   2023/08/25 19:20:20     1.2
+++ ./.nanorc   2023/08/25 19:29:15
@@ -8,6 +8,7 @@
 set tabsize 4
 set tabstospaces
 set softwrap
+set linenumbers

 include &amp;quot;/usr/share/nano/*.nanorc&amp;quot;&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;I&amp;#8217;ve now run &lt;code&gt;ci -l .nanorc&lt;/code&gt; but decide I don&amp;#8217;t really need to see to see line numbers. I want to go back to the revision before I added that line:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~$ co -l -r1.2 ./.nanorc 
./RCS/.nanorc,v  --&amp;gt;  ./.nanorc
revision 1.2 (locked)
writable ./.nanorc exists; remove it? [ny](n): y
co: ./RCS/.nanorc,v: warning: You now have 2 locks.
done&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Let&amp;#8217;s see the revision of the file now:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~$ cat .nanorc 
#=====================================================================
# $Revision: 1.2 $
# $Date: 2023/08/25 19:20:20 $
# $Author: simon $
#======================================================================

set autoindent
set tabsize 4
set tabstospaces
set softwrap

include &amp;quot;/usr/share/nano/*.nanorc&amp;quot;&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Ah good, we&amp;#8217;ve rolled back to where we were. And that&amp;#8217;s all there is to it. Here is the new workflow&lt;/p&gt;

	&lt;h3&gt;The New Workflow&lt;/h3&gt;

	&lt;p&gt;1. &lt;code&gt;mkdir RCS&lt;/code&gt; in the working directory&lt;br /&gt;
2. Add &lt;span class="caps"&gt;RCS&lt;/span&gt; metadata to the file if it doesn&amp;#8217;t exist&lt;br /&gt;
3. Make changes to the config file&lt;br /&gt;
4. Checkin the changes (&lt;code&gt;ci -l myfile.conf&lt;/code&gt;)&lt;br /&gt;
5. If you make a mistake or dislike a setting, &lt;code&gt;co -l -r1.?&lt;/code&gt;&lt;/p&gt;

	&lt;p&gt;Some nice features would be to automatically create the &lt;code&gt;RCS&lt;/code&gt; directory if it doesn&amp;#8217;t exist and to have all these &lt;code&gt;RCS&lt;/code&gt; directories backed up. That&amp;#8217;s for another post though&amp;#8230;&lt;/p&gt;</content><category term="software"></category><category term="rcs"></category><category term="version control"></category></entry><entry><title>Running bottle.py with systemd</title><link href="https://simonh.uk/2023/03/25/running-bottlepy-with-systemd/" rel="alternate"></link><published>2023-03-25T00:00:00+00:00</published><updated>2023-03-25T00:00:00+00:00</updated><author><name>Simon Harrison</name></author><id>tag:simonh.uk,2023-03-25:/2023/03/25/running-bottlepy-with-systemd/</id><summary type="html">	&lt;p&gt;systemd isn&amp;#8217;t so scary after all&lt;/p&gt;</summary><content type="html">	&lt;p&gt;&lt;img alt="Bottle.py Logo" src="/img/logo/bottle.svg" title="Bottle.py Logo" /&gt;&lt;/p&gt;

	&lt;p&gt;I have a number of &lt;a href="https://bottlepy.org/docs/dev/"&gt;bottle.py&lt;/a&gt; web services that I run on my servers. For the last few years, I&amp;#8217;ve been using &lt;a href="https://github.com/tmux/tmux/wiki"&gt;tmux&lt;/a&gt; to launch these services and then detaching them so they continue running after I logout of the &lt;span class="caps"&gt;SSH&lt;/span&gt; session. Recently, one of those servers had an issue causing the provider to require moving my &lt;span class="caps"&gt;VPS&lt;/span&gt; to another machine. So, when I went to use it, I got the &lt;code&gt;503 Service Unavailable&lt;/code&gt; message (that no one likes to see)!&lt;/p&gt;

	&lt;p&gt;Today, I finally got around to setting up &lt;a href="https://www.freedesktop.org/wiki/Software/systemd/"&gt;systemd&lt;/a&gt; service files for these services. It only took about an hour (including troubleshooting things not working). Below is the &lt;code&gt;shopping.service&lt;/code&gt; file (for a web based shopping list I wrote):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# Save this file in ~/.config/systemd/user/shopping.service
# then run:
# $ systemctl --user daemon-reload
# $ systemctl --user enable shopping.service
# Below will prevent the service stopping when we terminate the SSH session
# $ sudo loginctl enable-linger username

[Unit]
Description=Shopping List (bottle.py)
After=network.target

[Service]
Type=simple
WorkingDirectory=/home/simon/web/shopping
ExecStart=/usr/bin/python3 /home/simon/web/shopping/shopping.py
Restart=always

[Install]
WantedBy=default.target&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Note: make sure to follow the comments. Otherwise, you&amp;#8217;ll also have problems. &lt;/p&gt;

	&lt;p&gt;Once you&amp;#8217;ve created and symlinked the file to &lt;code&gt;~/.config/systemd/user&lt;/code&gt;, you&amp;#8217;ll be able to check all is good as you can for any system process. &lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@server:~/web/shopping [ssh] $ systemctl --user status shopping_list.service 
● shopping_list.service - Shopping List (bottle.py)
     Loaded: loaded (/home/simon/.config/systemd/user/shopping_list.service; enabled; vendor preset: enabled)
     Active: active (running) since Sat 2023-03-25 20:26:29 GMT; 9min ago
   Main PID: 32632 (python3)
      Tasks: 11 (limit: 1129)
     Memory: 100.3M
        CPU: 7.471s
     CGroup: /user.slice/user-1000.slice/user@1000.service/app.slice/shopping_list.service
             └─32632 /usr/bin/python3 /home/simon/web/shopping/run_sl2.py&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;I&amp;#8217;ll monitor this one service for a while, then I plan to use systemd service files for all my web services.&lt;/p&gt;</content><category term="software"></category><category term="python"></category><category term="linux"></category><category term="systemd"></category><category term="bottle.py"></category></entry><entry><title>Using GNU RCS in 2023</title><link href="https://simonh.uk/2023/02/11/using-gnu-rcs-in-2023/" rel="alternate"></link><published>2023-02-11T00:00:00+00:00</published><updated>2023-02-11T00:00:00+00:00</updated><author><name>Simon Harrison</name></author><id>tag:simonh.uk,2023-02-11:/2023/02/11/using-gnu-rcs-in-2023/</id><summary type="html">	&lt;p&gt;Version control for single files&lt;/p&gt;</summary><content type="html">	&lt;p&gt;&lt;img alt="GNU Logo" src="/img/logo/gnu.webp" title="GNU Logo" /&gt;&lt;/p&gt;

	&lt;h2&gt;Old School Version Control&lt;/h2&gt;

	&lt;p&gt;Since I started using &lt;a href="https://www.mercurial-scm.org/"&gt;Mercurial&lt;/a&gt; a few years back, I&amp;#8217;ve realised the value in having everything important under version control. The thing is, tools like Mercurial and Git don&amp;#8217;t seem to be quite the right tool when you&amp;#8217;re wanting to manage &lt;em&gt;single&lt;/em&gt; files. &lt;/p&gt;

	&lt;p&gt;Enter &lt;a href="https://www.gnu.org/software/rcs/"&gt;&lt;span class="caps"&gt;RCS&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;

	&lt;p&gt;&lt;span class="caps"&gt;RCS&lt;/span&gt; dates back to 1982, and was last updated in 2022 (still active). I believe that one of &lt;span class="caps"&gt;RCS&lt;/span&gt;&amp;#8217;s perceived weaknesses can actually be a strength: it was designed to work with single files. Using it is very easy. Let&amp;#8217;s get started!&lt;/p&gt;

	&lt;p&gt;The first thing I do is add some variables that &lt;span class="caps"&gt;RCS&lt;/span&gt; will populate for us. I&amp;#8217;ll add a bit of metadata to our fake program &lt;code&gt;my_program&lt;/code&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# $Date$
# $Revision$
# $Author$&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;These will be replaced when we &amp;#8220;checkout&amp;#8221; our file from &lt;span class="caps"&gt;RCS&lt;/span&gt;. But first we need to &amp;#8220;checkin&amp;#8221; our initial revision. &lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# $Date$
# $Revision$
# $Author$

This is the first version of my file. I&amp;#39;ve done a small amount of work that I want to save.&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Let&amp;#8217;s check in our first version.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~/tmp/my_script$ mkdir RCS&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~/tmp/my_script$ ll
total 16K
drwxrwxr-x  3 simon simon 4.0K 2023-02-11 11:16 .
drwxrwxr-x 18 simon simon 4.0K 2023-02-11 11:09 ..
-rw-rw-r--  1 simon simon  128 2023-02-11 11:15 my_program
drwxrwxr-x  2 simon simon 4.0K 2023-02-11 11:16 RCS&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~/tmp/my_script$ ci my_program 
RCS/my_program,v  &amp;lt;--  my_program
enter description, terminated with single &amp;#39;.&amp;#39; or end of file:
NOTE: This is NOT the log message!
&amp;gt;&amp;gt; Version 1 of my_program
&amp;gt;&amp;gt; .
initial revision: 1.1
done&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;So we&amp;#8217;ve performed our first commit. Let&amp;#8217;s see the state of our working directory&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~/tmp/my_script$ tree
.
└── RCS
    └── my_program,v

1 directory, 1 file&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;As you can see, our original file has been destroyed! We now have one file in the &lt;span class="caps"&gt;RCS&lt;/span&gt; directory &lt;code&gt;my_program,v&lt;/code&gt;. That file is our &amp;#8220;versioned&amp;#8221; file. Let&amp;#8217;s take a look at it&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~/tmp/my_script$ cat RCS/my_program,v 
head    1.1;
access;
symbols;
locks; strict;
comment @# @;


1.1
date    2023.02.11.11.16.25;    author simon;   state Exp;
branches;
next    ;


desc
@Version 1 of my_program
@


1.1
log
@Initial revision
@
text
@# $Date$
# $Revision$
# $Author$

This is the first version of my file. I&amp;#39;ve done a small amount of work that I want to save.


@
simon@computer:~/tmp/my_script$&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;As you can see, there&amp;#8217;s quite a bit of information in there, along with the text of &lt;code&gt;my_program&lt;/code&gt;&lt;/p&gt;

	&lt;p&gt;To retrieve our file and do some work, we need to check it out, with a lock, to prevent other people working on it at the same time as us (to avoid conflicts).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~/tmp/my_script$ co -l ./my_program 
./RCS/my_program,v  --&amp;gt;  ./my_program
revision 1.1 (locked)
done&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Let&amp;#8217;s see our working directory state now&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~/tmp/my_script$ tree
.
├── my_program
└── RCS
    └── my_program,v

1 directory, 2 files&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Great, the file is back! Let&amp;#8217;s take a look at the contents&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~/tmp/my_script$ cat my_program 
# $Date: 2023/02/11 11:16:25 $
# $Revision: 1.1 $
# $Author: simon $

This is the first version of my file. I&amp;#39;ve done a small amount of work that I want to save.&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;As I said earlier, the dollar variables have been expanded by &lt;span class="caps"&gt;RCS&lt;/span&gt;. Let&amp;#8217;s make another change and see what happens.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# $Date: 2023/02/11 11:16:25 $
# $Revision: 1.1 $
# $Author: simon $

This is the first version of my file. I&amp;#39;ve done a small amount of work that I want to save.

I&amp;#39;ve simply added a blank newline and this line now.&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Running &lt;code&gt;rcsdiff&lt;/code&gt; will show us unsaved changes. Use the &lt;code&gt;-u&lt;/code&gt; option to get unified diff output.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~/tmp/my_script$ rcsdiff -u ./my_program 
===================================================================
RCS file: ./RCS/my_program,v
retrieving revision 1.1
diff -u -r1.1 ./my_program
--- ./my_program        2023/02/11 11:16:25     1.1
+++ ./my_program        2023/02/11 11:29:41
@@ -4,4 +4,6 @@

 This is the first version of my file. I&amp;#39;ve done a small amount of work that I want to save.

+I&amp;#39;ve simply added a blank newline and this line now.
+

simon@computer:~/tmp/my_script$ &lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;All looks good, so we&amp;#8217;ll commit our changes.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~/tmp/my_script$ ci ./my_program 
./RCS/my_program,v  &amp;lt;--  ./my_program
new revision: 1.2; previous revision: 1.1
enter log message, terminated with single &amp;#39;.&amp;#39; or end of file:
&amp;gt;&amp;gt; Did a bit of work
&amp;gt;&amp;gt; .
done&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Very easy and painless, eh? Once again, our file will have been destroyed so we need to check it out again to either work on it (with the &lt;code&gt;-l&lt;/code&gt; option to have a locked version of the file) or without a lock for a read only version.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~/tmp/my_script$ co ./my_program 
./RCS/my_program,v  --&amp;gt;  ./my_program
revision 1.2
done
simon@computer:~/tmp/my_script$ cat my_program 
# $Date: 2023/02/11 11:31:42 $
# $Revision: 1.2 $
# $Author: simon $

This is the first version of my file. I&amp;#39;ve done a small amount of work that I want to save.

I&amp;#39;ve simply added a blank newline and this line now.&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;The date and revision have been updated and our most recent changes are there. Because we didn&amp;#8217;t lock our file, it&amp;#8217;s readonly. &lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  GNU nano 6.2                       my_program                                 
# $Date: 2023/02/11 11:31:42 $
# $Revision: 1.2 $
# $Author: simon $

This is the first version of my file. I&amp;#39;ve done a small amount of work that I w&amp;gt;

I&amp;#39;ve simply added a blank newline and this line now.












                      [ File &amp;#39;my_program&amp;#39; is unwritable ]
^G Help      ^O Write Out ^W Where Is  ^K Cut       ^T Execute   ^C Location
^X Exit      ^R Read File ^\ Replace   ^U Paste     ^J Justify   ^/ Go To Line&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;&lt;span class="caps"&gt;GNU&lt;/span&gt; Nano tells us at the bottom that the file is unwritable. Fair enough. &lt;/p&gt;

	&lt;p&gt;We&amp;#8217;ll checkout an editable version now with &lt;code&gt;co -l&lt;/code&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~/tmp/my_script$ co -l ./my_program 
./RCS/my_program,v  --&amp;gt;  ./my_program
revision 1.2 (locked)
done&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;If we want to view our changes &lt;code&gt;rlog&lt;/code&gt; will happily tell us&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~/tmp/my_script$ rlog ./my_program 

RCS file: ./RCS/my_program,v
Working file: ./my_program
head: 1.2
branch:
locks: strict
        simon: 1.2
access list:
symbolic names:
keyword substitution: kv
total revisions: 2;     selected revisions: 2
description:
Version 1 of my_program
----------------------------
revision 1.2    locked by: simon;
date: 2023/02/11 11:31:42;  author: simon;  state: Exp;  lines: +5 -3
Did a bit of work
----------------------------
revision 1.1
date: 2023/02/11 11:16:25;  author: simon;  state: Exp;
Initial revision
=============================================================================&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;And that&amp;#8217;s really all there is to it (for my purposes anyway). Take a look at the excellent &lt;a href="https://www.gnu.org/software/rcs/manual/"&gt;manual&lt;/a&gt; for everything else you can do with &lt;span class="caps"&gt;RCS&lt;/span&gt;.&lt;/p&gt;

	&lt;p&gt;I&amp;#8217;m sure you can see the value of &lt;span class="caps"&gt;RCS&lt;/span&gt; for shell scripts, single Python files, etc. &lt;/p&gt;</content><category term="software"></category><category term="version control"></category><category term="linux"></category><category term="gnu"></category><category term="rcs"></category></entry><entry><title>Manage Invoices with GNU Recutils</title><link href="https://simonh.uk/2022/08/13/manage-invoices-with-gnu-recutils/" rel="alternate"></link><published>2022-08-13T00:00:00+01:00</published><updated>2022-08-13T00:00:00+01:00</updated><author><name>Simon Harrison</name></author><id>tag:simonh.uk,2022-08-13:/2022/08/13/manage-invoices-with-gnu-recutils/</id><summary type="html">	&lt;p&gt;unix plain text databases!&lt;/p&gt;</summary><content type="html">	&lt;p&gt;&lt;img alt="GNU Logo" src="/img/logo/gnu.webp" title="GNU Logo" /&gt;&lt;/p&gt;

	&lt;p&gt;I&amp;#8217;ve been running an &lt;span class="caps"&gt;NDT&lt;/span&gt; business since 2017. After a couple of years getting annoyed at writing my reports in Libreoffice Writer, I decided to write my own software to generate the reports for me. This has saved me an enormous amount of time. A couple of years ago, I started thinking about how I should handle my invoices. I don&amp;#8217;t generate a lot of invoices, but sometimes I&amp;#8217;d lose track of who&amp;#8217;d paid, who hadn&amp;#8217;t and realised I needed &lt;em&gt;something&lt;/em&gt; to keep track of them.&lt;/p&gt;

	&lt;p&gt;One option was just to simply add it to my existing system. But, I couldn&amp;#8217;t really be bothered. So I decided to have a simple spreadsheet. This worked ok, I simply added a new row to my &amp;#8220;invoice_log_2022.xlsx&amp;#8221; and then email myself the new version so I had some redundancy. But it bugged me a little as it seemed there should be an easier way to handle a few records. For example, I had to use some spreadsheet program just to add / view my invoices. &lt;/p&gt;

	&lt;p&gt;So, I thought I&amp;#8217;d see what other options I could find. Eventually, I came across &lt;a href="https://www.gnu.org/software/recutils/"&gt;&lt;span class="caps"&gt;GNU&lt;/span&gt; Recutils&lt;/a&gt;. Here is the description from their site:&lt;/p&gt;

	&lt;blockquote&gt;
		&lt;p&gt;&lt;span class="caps"&gt;GNU&lt;/span&gt; Recutils is a set of tools and libraries to access human-editable, plain text databases called recfiles. The data is stored as a sequence of records, each record containing an arbitrary number of named fields. The picture below shows a sample database containing information about &lt;span class="caps"&gt;GNU&lt;/span&gt; packages, along with the main features provided by Recutils.&lt;/p&gt;
	&lt;/blockquote&gt;

	&lt;p&gt;&lt;img alt="recutils screenshot" src="/img/2022-08-13/recutils.png" title="recutils screenshot" /&gt;&lt;/p&gt;

	&lt;p&gt;This seemed to be worth a look! I converted my spreadsheet to csv, then imported it into the recfile format. &lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Invoice_No: N123456
Due_Date: 2022-07-31
Amount: £180.00
Customer: Some Customer
Description: MPI of fillet welds on fabricated assemblies
Amount_Paid: £180.00
Date_Paid: 2022-08-05

Invoice_No: N123457
Due_Date: 2022-07-31
Amount: £150.00
Customer: Another Customer
Description: DPI of condenser pipework
Amount_Paid: 
Date_Paid: &lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;The above shows two records. The first one has been paid, the second one has not. If I want to add a new invoice to the log, I simply copy the last record, edit the fields and save the file. It really doesn&amp;#8217;t get much easier than that. No need for anything more than a text editor. &lt;/p&gt;

	&lt;p&gt;I&amp;#8217;ve only been using recutils for a week and have just started scratching the surface of the tools that come with it, &lt;code&gt;recins&lt;/code&gt;, &lt;code&gt;recsel&lt;/code&gt;, &lt;code&gt;recdel&lt;/code&gt; etc. One thing I want to do is have a cron job that will email me any invoices that are overdue. &lt;/p&gt;

	&lt;h2&gt;Conclusion&lt;/h2&gt;

	&lt;p&gt;I really like Sqlite. I use it for loads of things, but sometimes even Sqlite is overkill. The next time you think about creating a new spreadsheet to save a few records, perhaps you&amp;#8217;ll try Recutils instead&amp;#8230;&lt;/p&gt;</content><category term="software"></category><category term="business"></category><category term="database"></category><category term="tips"></category><category term="gnu"></category></entry><entry><title>A Guide to Choosing, Starting and Finishing Software Projects</title><link href="https://simonh.uk/2021/12/18/a-guide-to-choosing-starting-and-finishing-software-projects/" rel="alternate"></link><published>2021-12-18T00:00:00+00:00</published><updated>2021-12-18T00:00:00+00:00</updated><author><name>Simon Harrison</name></author><id>tag:simonh.uk,2021-12-18:/2021/12/18/a-guide-to-choosing-starting-and-finishing-software-projects/</id><summary type="html">	&lt;p&gt;tldr: It needs to be useful and have an audience&lt;/p&gt;</summary><content type="html">	&lt;h1&gt;Intro&lt;/h1&gt;

	&lt;p&gt;I&amp;#8217;ve been a productive programmer for about four years now and believe I&amp;#8217;m in a position to offer some friendly advice to others who might be struggling. &lt;/p&gt;

	&lt;p&gt;I tried, and failed, to learn programming for many years. The turning point for me was a real world project for a company that I worked for. &lt;/p&gt;

	&lt;h2&gt;Step One&lt;/h2&gt;

	&lt;p&gt;&lt;ins&gt;Pick a real world project&lt;/ins&gt;&lt;/p&gt;

	&lt;p&gt;My first project was a system to record torque settings in a workshop. The way they had done it for many years, was for each technician to record the settings in a bound book. This would include &lt;/p&gt;

	&lt;ul&gt;
		&lt;li&gt;their clock number&lt;/li&gt;
		&lt;li&gt;the date&lt;/li&gt;
		&lt;li&gt;the job number&lt;/li&gt;
		&lt;li&gt;the torque value applied&lt;/li&gt;
		&lt;li&gt;the torque wrench used&lt;/li&gt;
		&lt;li&gt;the torque meter used&lt;/li&gt;
	&lt;/ul&gt;

	&lt;p&gt;And finally, they&amp;#8217;d stamp the last column instead of a signature (company policy) so if there was an issue, they could ascertain who&amp;#8217;d torqued a particular bolt.&lt;/p&gt;

	&lt;p&gt;The problems with this method, as I saw it, were:&lt;/p&gt;

	&lt;ul&gt;
		&lt;li&gt;someone had to regularly print out the new books (ME)!&lt;/li&gt;
		&lt;li&gt;finding a record was like finding a needle in a haystack&lt;/li&gt;
		&lt;li&gt;no backup &amp;#8211; if book is lost, all records gone&lt;/li&gt;
	&lt;/ul&gt;

	&lt;p&gt;Bear in mind, this company had about twenty of these books in daily use. Also, it was not uncommon to have to try to find a record (if an engine or transmission failed in service). &lt;/p&gt;

	&lt;p&gt;So, I offered to attempt to write a web based system, accessed using a couple of tablets the company already had. It took maybe a month or two of work in my spare time to have a prototype built. We tested it using one station, and when that proved to work better than the old way, we introduced the second tablet. &lt;/p&gt;

	&lt;p&gt;This was not a tech company and the supervisors were genuinely surprised and delighted that they could now search on any field:&lt;/p&gt;

	&lt;ul&gt;
		&lt;li&gt;all records for a particular job&lt;/li&gt;
		&lt;li&gt;all records for a particular technician&lt;/li&gt;
		&lt;li&gt;all records on a date or in a date range&lt;/li&gt;
	&lt;/ul&gt;

	&lt;p&gt;etc.&lt;/p&gt;

	&lt;p&gt;Unfortunately, their lazy, unskilled IT department didn&amp;#8217;t like me in their turf and started causing problems, so I decided to turn the program off. But, it was very successful and well liked by its users and management who were directly involved. &lt;/p&gt;

	&lt;h2&gt;Step Two&lt;/h2&gt;

	&lt;p&gt;&lt;ins&gt;Make it better than the old way&lt;/ins&gt;&lt;/p&gt;

	&lt;p&gt;Personally, I love writing software. Starting with nothing and ending up with something in use, better than how it was done previously. Every software project I&amp;#8217;ve written has been to replace something that could easily be improved, i.e. to replace a spreadsheet, a white board, or paper. &lt;/p&gt;

	&lt;p&gt;When you&amp;#8217;re starting out people can be nervous about change. So I always say to them:&lt;/p&gt;

	&lt;blockquote&gt;
		&lt;p&gt;&amp;#8220;If you don&amp;#8217;t like it, you can always go back to how you did it before.&amp;#8221;&lt;/p&gt;
	&lt;/blockquote&gt;

	&lt;p&gt;Knowing fine well that once they&amp;#8217;ve used my system, going back will be the last thing they want to do! But it&amp;#8217;s important to tell them, to reassure them that it&amp;#8217;s just a trial. That they are in control. People are weird like that. &lt;/p&gt;

	&lt;h2&gt;Step Three&lt;/h2&gt;

	&lt;p&gt;&lt;ins&gt;Launch as soon as you can&lt;/ins&gt;&lt;/p&gt;

	&lt;p&gt;Once you&amp;#8217;ve picked your real world project, get to work! As with all things, you&amp;#8217;ll get better and quicker and more confident as you write more code. You&amp;#8217;ll also get feedback from your users that you couldn&amp;#8217;t predict. The sooner you launch, the sooner your project improves. That&amp;#8217;s been my experience. &lt;/p&gt;

	&lt;h2&gt;Step Four&lt;/h2&gt;

	&lt;p&gt;&lt;ins&gt;Work as much as you can to improve it&lt;/ins&gt;&lt;/p&gt;

	&lt;p&gt;So your project is live, &lt;em&gt;real&lt;/em&gt; people are using it and benefiting from your skills. Over the next few weeks / months, try and make it better. Add new features that your users suggest (within reason). Make things simpler and easier for your users. I guarantee you that it will take months until you can officially say it&amp;#8217;s &amp;#8220;done.&amp;#8221; &lt;/p&gt;

	&lt;h2&gt;Summary and Conclusion&lt;/h2&gt;

	&lt;p&gt;So, lets recap&lt;/p&gt;

	&lt;p&gt;1. Pick a real world project&lt;br /&gt;
2. Make it better than the old way&lt;br /&gt;
3. Launch as soon as you can&lt;br /&gt;
4. Work as much as you can to improve it&lt;br /&gt;
5. &lt;span class="caps"&gt;GOTO&lt;/span&gt; step 1&lt;/p&gt;

	&lt;p&gt;And that&amp;#8217;s how I work. That&amp;#8217;s my system for writing software. Of course there&amp;#8217;s loads of other things that you should consider (version control, backups, security etc.) but for my first couple of projects, I didn&amp;#8217;t bother with version control software. I&amp;#8217;d struggle to go back to not using it now, but I muddled through. The other stuff you&amp;#8217;ll pick up as you need to. &lt;/p&gt;

	&lt;p&gt;In case you&amp;#8217;re interested, here is the before and after for the torque meter software project I mentioned above:&lt;/p&gt;

	&lt;p&gt;Before:&lt;/p&gt;

	&lt;p&gt;&lt;img alt="torque book" src="/img/2021-12-18/torque_book.jpg" title="torque book" /&gt;&lt;/p&gt;

	&lt;p&gt;After:&lt;/p&gt;

	&lt;p&gt;&lt;img alt="torque software" src="/img/2021-12-18/torque_software.jpg" title="torque software" /&gt;&lt;/p&gt;</content><category term="software"></category><category term="tips"></category><category term="programming"></category></entry><entry><title>Send SMS from Linux Computer via ADB</title><link href="https://simonh.uk/2021/11/14/send-sms-from-linux-computer-via-adb/" rel="alternate"></link><published>2021-11-14T00:00:00+00:00</published><updated>2021-11-14T00:00:00+00:00</updated><author><name>Simon Harrison</name></author><id>tag:simonh.uk,2021-11-14:/2021/11/14/send-sms-from-linux-computer-via-adb/</id><summary type="html">	&lt;p&gt;That&amp;#8217;s another itch, scratched.&lt;/p&gt;</summary><content type="html">	&lt;p&gt;Since I learnt how to send emails from my servers and desktop, I thought it would be useful to send &lt;span class="caps"&gt;SMS&lt;/span&gt; (Short Message Service) texts as well. No specific use cases yet, but I&amp;#8217;m sure one day it&amp;#8217;ll be needed&amp;#8230;&lt;/p&gt;

	&lt;p&gt;After looking into &lt;a href="http://smstools3.kekekasvi.com/"&gt;smstools&lt;/a&gt;, &lt;a href="https://wammu.eu/gammu/"&gt;Gammu&lt;/a&gt;, and loads of others, I was getting nowhere and ready to give up. But then, I remembered &lt;a href="https://developer.android.com/studio/command-line/adb"&gt;&lt;span class="caps"&gt;ADB&lt;/span&gt;&lt;/a&gt;.  Like most people, I&amp;#8217;ve got numerous Android phones knocking about, surely I could use an old Android phone + &lt;span class="caps"&gt;ADB&lt;/span&gt; to send an &lt;span class="caps"&gt;SMS&lt;/span&gt;. &lt;/p&gt;

	&lt;p&gt;I started off with my first Android phone, an &lt;a href="https://www.gsmarena.com/htc_desire-3077.php"&gt;&lt;span class="caps"&gt;HTC&lt;/span&gt; Desire&lt;/a&gt;. Even though this phone is now 11 years old, it still works perfectly and it&amp;#8217;d be nice to give it something to do!&lt;/p&gt;

	&lt;p&gt;&lt;ins&gt;Android 2 (Gingerbread)&lt;/ins&gt;&lt;/p&gt;

	&lt;p&gt;The first thing to notice is that we put the phone number in just as we&amp;#8217;d type in to to the phone. No +44XXXXXXXXX needed here. So let&amp;#8217;s start sending some &lt;span class="caps"&gt;SMS&lt;/span&gt; messages.&lt;/p&gt;

	&lt;p&gt;To send an sms with spaces, which is almost certainly required, we either escape each space character with a back slash, or far better, enclose the string in single quotes:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~$ adb shell service call isms 5 s16 &amp;quot;07123456789&amp;quot; i32 0 i32 0 s16 &amp;quot;&amp;#39;Here is some text with spaces but not escaped.&amp;#39;&amp;quot;
Result: Parcel(00000000    &amp;#39;....&amp;#39;)
simon@computer:~$&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;I wondered if I could send the output of shell commands (yep):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~$ adb shell service call isms 5 s16 &amp;quot;07123456789&amp;quot; i32 0 i32 0 s16 &amp;quot;&amp;#39;$(uptime)&amp;#39;&amp;quot;&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Here are some of the messages I received on my mobile. The last message was the uptime message above.&lt;/p&gt;

	&lt;p&gt;&lt;img alt="SMS received on phone" src="/img/2021-11-14/screenshot_sms.png" title="SMS received on phone" /&gt;&lt;/p&gt;

	&lt;p&gt;I also had a &lt;a href="https://www.gsmarena.com/nokia_5-8571.php"&gt;Nokia 5&lt;/a&gt; in a drawer. &lt;/p&gt;

	&lt;p&gt;&lt;ins&gt;Android 9&lt;/ins&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~$ adb shell service call isms 7 i32 0 s16 &amp;quot;com.android.mms.service&amp;quot; s16 &amp;quot;+447123456789&amp;quot; s16 &amp;quot;null&amp;quot; s16 &amp;quot;Hello\ from\ your\ home\ computer.&amp;quot; s16 &amp;quot;null&amp;quot; s16 &amp;quot;null&amp;quot;&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;As you can see, the syntax is different depending on your Android version. I&amp;#8217;ve only just started scratching the surface with &lt;span class="caps"&gt;ADB&lt;/span&gt;, but there&amp;#8217;s lots of potential for all sorts of helpful notifications.&lt;/p&gt;

	&lt;p&gt;I&amp;#8217;ll probably write a new post once I&amp;#8217;ve done some more experimenting.&lt;/p&gt;</content><category term="software"></category><category term="android"></category><category term="sms"></category><category term="linux"></category><category term="tips"></category></entry><entry><title>On the Pros and Cons of Software Testing</title><link href="https://simonh.uk/2021/06/10/on-the-pros-and-cons-of-software-testing/" rel="alternate"></link><published>2021-06-10T00:00:00+01:00</published><updated>2021-06-10T00:00:00+01:00</updated><author><name>Simon Harrison</name></author><id>tag:simonh.uk,2021-06-10:/2021/06/10/on-the-pros-and-cons-of-software-testing/</id><summary type="html">	&lt;p&gt;I understand the concept, just wonder if it&amp;#8217;s worth the time&lt;/p&gt;</summary><content type="html">	&lt;p&gt;Over the years, I&amp;#8217;ve noticed that there are two types of coders&lt;/p&gt;

	&lt;ol&gt;
		&lt;li&gt;Those who don&amp;#8217;t really see testing as something worth their time&lt;/li&gt;
		&lt;li&gt;Those who test everything&lt;/li&gt;
	&lt;/ol&gt;

	&lt;p&gt;I fall into the first camp. There&amp;#8217;s probably a transtion from 1 to 2, but it seems to be an all or nothing type arrangement to me. You don&amp;#8217;t come across many coders who do &amp;#8220;some&amp;#8221; automated testing. &lt;/p&gt;

	&lt;p&gt;Now, of course, we all &lt;strong&gt;test&lt;/strong&gt; functionally. You&amp;#8217;ve just added a new feature to your untested code, so you run it and test it out. Try and break it. Often, it will break quite happily. You missed something obvious and then you fix the code, retest, and all looks good. &lt;/p&gt;

	&lt;p&gt;I run quite a lot of code like this. As do many others. I think, secretly, many coders know that test suites are a bit of a con. You may run 5000 tests and everything passes. &lt;/p&gt;

	&lt;p&gt;So, therefore the code is good?! Bug free? Not necessarily&amp;#8230;&lt;/p&gt;

	&lt;p&gt;I mean, think about it. You are going to test &lt;strong&gt;every&lt;/strong&gt; permutation of permissable inputs? Or outputs? &lt;/p&gt;

	&lt;p&gt;Nope (unless you&amp;#8217;re &lt;a href="https://sqlite.org/testing.html"&gt;sqlite&lt;/a&gt;). &lt;/p&gt;

	&lt;p&gt;For a lot of code, it doesn&amp;#8217;t really matter. &lt;/p&gt;

	&lt;ul&gt;
		&lt;li&gt;You run it&lt;/li&gt;
		&lt;li&gt;It works&lt;/li&gt;
		&lt;li&gt;Something breaks&lt;/li&gt;
		&lt;li&gt;You fix it&lt;/li&gt;
		&lt;li&gt;You run it&lt;/li&gt;
	&lt;/ul&gt;

	&lt;p&gt;That seems reasonable to me. And it&amp;#8217;s exactly the same process with an automated test suite except there&amp;#8217;s a write tests step. &lt;/p&gt;

	&lt;p&gt;Small time coders can get away with dealing with bugs as they come up. I&amp;#8217;ve had a few chewy moments, but if you coded intelligently / defensively in the first place, you&amp;#8217;ve built workarounds in to handle minor bugs. &lt;/p&gt;

	&lt;h2&gt;My Workflow&lt;/h2&gt;

	&lt;p&gt;When I start a new project, I initialize a Mercurial repository, bring in all the files I know I&amp;#8217;ll need right away, and then start coding. I work alone, by the way, so there&amp;#8217;s no corner of the code that I haven&amp;#8217;t touched. &lt;/p&gt;

	&lt;p&gt;I work on one feature at a time. Anything that feature might touch, I functionally test as I go.&lt;/p&gt;

	&lt;h2&gt;Example&lt;/h2&gt;

	&lt;p&gt;Last year, I wrote a web based shopping list for my partner and me to use instead of a paper list. We&amp;#8217;ve been using it every week since, and generally it works perfectly. &lt;/p&gt;

	&lt;p&gt;But, eventually a very annoying bug showed up. This cropped up after it running for about six months. What went wrong was she created a new list, and started to add items. And then she got a 500 error (Internal Server Error). &lt;/p&gt;

	&lt;p&gt;Now, I&amp;#8217;d set up my database so that each shopping list was indexed by date. So if she created a list today (2021-06-11) and then tried to create a new list on the same date, she&amp;#8217;d be prompted whether to add to the existing list or whether she wanted to delete the existing list. The reason being; my partner will create a new shopping list every Wednesday, add all the items she knows we need, then on the Thursday, one of us ticks off the items on our phones to remove them as we&amp;#8217;re putting items in to the trolley. &lt;/p&gt;

	&lt;p&gt;But on this day, she created a new list (a week after the old one), started to add items to the list and got the 500 error for nearly every item she tried to add! I was at home at the time, so &lt;span class="caps"&gt;SSH&lt;/span&gt;&amp;#8217;d into the server to have a look what was going on. The traceback pointed to an sqlite integrity error. &lt;/p&gt;

	&lt;p&gt;It turned out that instead of creating a new list, she was adding to the old list. Not her fault as I&amp;#8217;d coded it that creating a new list would close the old list, and make a new one. I checked all the relevant code, and everything looked good. &lt;/p&gt;

	&lt;p&gt;When I designed the software, one of the features I thought she&amp;#8217;d like, was being able to look at previous lists, and just click each item to add it to the new list. She generally gets a lot of items each week that are the same as every other week.&lt;/p&gt;

	&lt;p&gt;Here is a screenshot of the /lists page:&lt;/p&gt;

	&lt;p&gt;&lt;img alt="Shopping List Program" src="/img/2021-06-10/shopping_list.png" title="Shopping List Program" /&gt;&lt;/p&gt;

	&lt;p&gt;So from here she can click on the first date (or any date) and every item added on that date can be clicked and that will add it to the current list:&lt;/p&gt;

	&lt;p&gt;&lt;img alt="Shopping List Items" src="/img/2021-06-10/shopping_list2.png" title="Shopping List Items" /&gt;&lt;/p&gt;

	&lt;p&gt;If the item has already been added, it won&amp;#8217;t be added again. &lt;/p&gt;

	&lt;p&gt;It was on the /lists page that I realised that a new list hadn&amp;#8217;t been created. The solution was to delete the old list, and create a new one. &lt;/p&gt;

	&lt;h2&gt;Conclusion&lt;/h2&gt;

	&lt;p&gt;I never found the actual cause of the bug. I think it was possibly a caching issue on her phone. It has never showed up again. Even if I&amp;#8217;d written tests for everything I could think of, I wouldn&amp;#8217;t have considered the possibility that today&amp;#8217;s date would be anything other than: today&amp;#8217;s date!&lt;/p&gt;</content><category term="software"></category><category term="software"></category><category term="testing"></category></entry><entry><title>Why I still Use Windows XP</title><link href="https://simonh.uk/2021/05/21/why-i-still-use-windows-xp/" rel="alternate"></link><published>2021-05-21T00:00:00+01:00</published><updated>2021-05-21T00:00:00+01:00</updated><author><name>Simon Harrison</name></author><id>tag:simonh.uk,2021-05-21:/2021/05/21/why-i-still-use-windows-xp/</id><summary type="html">	&lt;p&gt;In a virtual machine, obviously!&lt;/p&gt;</summary><content type="html">	&lt;p&gt;&lt;img alt="Windows XP booting" src="/img/2021-05-21/xp-boot.jpg" title="Windows XP booting" /&gt;&lt;/p&gt;

	&lt;p&gt;Windows XP was on the first PC I owned, built by my brother in about 2001/2002. The computer had a 20GB hard disk, a 750Mhz processor, and served me well for many years. &lt;/p&gt;

	&lt;p&gt;To be honest, I always liked XP. I upgraded to Vista at some point, but that ran so badly, I switched to using Linux permanently in about 2008 or 2009. &lt;/p&gt;

	&lt;p&gt;Ever since I&amp;#8217;ve had computers powerful enough to run &lt;a href="https://www.virtualbox.org/"&gt;VirtualBox&lt;/a&gt;, I&amp;#8217;ve always had a Windows XP virtual machine. &lt;/p&gt;

	&lt;h2&gt;Why?&lt;/h2&gt;

	&lt;ul&gt;
		&lt;li&gt;Lightweight and fast&lt;/li&gt;
		&lt;li&gt;Good enough&lt;/li&gt;
		&lt;li&gt;Runs &lt;em&gt;most&lt;/em&gt; of the Windows software I might need&lt;/li&gt;
		&lt;li&gt;Stable&lt;/li&gt;
	&lt;/ul&gt;

	&lt;p&gt;I&amp;#8217;m not a Free Software &amp;#8220;fanatic&amp;#8221;. There&amp;#8217;s nothing as good as Adobe Acrobat XI that runs natively on Linux. Some people, myself included, consider Acrobat 11 &lt;strong&gt;far&lt;/strong&gt; better than Acrobat DC. Recent Adobe software is more about them, and less about their users. Photoshop CS 5.1 also runs on XP and does pretty much anything you might need to do to a photo (if you can&amp;#8217;t figure out how do it in &lt;span class="caps"&gt;GIMP&lt;/span&gt;). &lt;/p&gt;

	&lt;p&gt;Windows XP &lt;span class="caps"&gt;RAM&lt;/span&gt; Usage (Idling)&lt;/p&gt;

	&lt;p&gt;&lt;img alt="Windows XP Task Manager" src="/img/2021-05-21/xp-taskmanager.png" title="Windows XP Task Manager" /&gt;&lt;/p&gt;

	&lt;p&gt;Linux Mint 20.1 Cinnamon (Idling)&lt;/p&gt;

	&lt;p&gt;&lt;img alt="Linux Mint" src="/img/2021-05-21/xp-htop.png" title="Linux Mint" /&gt;&lt;/p&gt;

	&lt;p&gt;MX Linux 19.4 (Idling)&lt;/p&gt;

	&lt;p&gt;&lt;img alt="MX Linux" src="/img/2021-05-21/xp-htop-mx.png" title="MX Linux" /&gt;&lt;/p&gt;

	&lt;p&gt;Big difference between the three, aren&amp;#8217;t there?!&lt;/p&gt;

	&lt;h2&gt;Tips&lt;/h2&gt;

	&lt;p&gt;My XP instance has no internet access (why would it?). I only use it for occasional Acrobat, a bit of WordPerfect and some IronPython stuff. &lt;/p&gt;

	&lt;p&gt;If you want to do some scripting, IronPython 2.7.8 is the last version that runs on XP (to my knowledge). I tried 2.7.9 to 2.7.11 (latest) but no dice, probably due to the .net framework 4.0 being the last to run on XP.&lt;/p&gt;

	&lt;p&gt;Make sure you&amp;#8217;re running SP3, which was the last service pack released. &lt;/p&gt;</content><category term="software"></category><category term="windows"></category><category term="virtualization"></category></entry><entry><title>Getting Started with GnuPG (gpg)</title><link href="https://simonh.uk/2021/05/20/getting-started-with-gnupg-gpg/" rel="alternate"></link><published>2021-05-20T00:00:00+01:00</published><updated>2021-05-20T00:00:00+01:00</updated><author><name>Simon Harrison</name></author><id>tag:simonh.uk,2021-05-20:/2021/05/20/getting-started-with-gnupg-gpg/</id><summary type="html">	&lt;p&gt;Encryption, Signing, Compression all in one&lt;/p&gt;</summary><content type="html">	&lt;p&gt;&lt;img alt="GNU GPG Logo" src="/img/logo/gnu_gpg.svg" title="GNU GPG Logo" /&gt;&lt;/p&gt;

	&lt;p&gt;I&amp;#8217;ve been meaning to spend a bit of time looking at use cases for &lt;a href="https://gnupg.org/"&gt;gpg&lt;/a&gt;&lt;/p&gt;

	&lt;p&gt;I wasn&amp;#8217;t aware that you don&amp;#8217;t even need to set up any accounts. You can start using for symmetric encryption right out of the box. Symmetric encryption relies on a shared password / passphrase that is shared with recipients. &lt;/p&gt;

	&lt;p&gt;I&amp;#8217;m using a fairly fresh installation of &lt;a href="https://mxlinux.org/"&gt;mxlinux&lt;/a&gt; in Virtual Box. GnuPG is already installed as with pretty much any distro.&lt;/p&gt;

	&lt;p&gt;As you can see below, lots of options are available.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@mx:~
$ gpg -h
gpg (GnuPG) 2.2.12
libgcrypt 1.8.4
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later &amp;lt;https://gnu.org/licenses/gpl.html&amp;gt;
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Home: /home/simon/.gnupg
Supported algorithms:
Pubkey: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
Cipher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH,
        CAMELLIA128, CAMELLIA192, CAMELLIA256
Hash: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
Compression: Uncompressed, ZIP, ZLIB, BZIP2

Syntax: gpg [options] [files]
Sign, check, encrypt or decrypt
Default operation depends on the input data

Commands:

 -s, --sign                  make a signature
     --clear-sign            make a clear text signature
 -b, --detach-sign           make a detached signature
 -e, --encrypt               encrypt data
 -c, --symmetric             encryption only with symmetric cipher
 -d, --decrypt               decrypt data (default)
     --verify                verify a signature
 -k, --list-keys             list keys
     --list-signatures       list keys and signatures
     --check-signatures      list and check key signatures
     --fingerprint           list keys and fingerprints
 -K, --list-secret-keys      list secret keys
     --generate-key          generate a new key pair
     --quick-generate-key    quickly generate a new key pair
     --quick-add-uid         quickly add a new user-id
     --quick-revoke-uid      quickly revoke a user-id
     --quick-set-expire      quickly set a new expiration date
     --full-generate-key     full featured key pair generation
     --generate-revocation   generate a revocation certificate
     --delete-keys           remove keys from the public keyring
     --delete-secret-keys    remove keys from the secret keyring
     --quick-sign-key        quickly sign a key
     --quick-lsign-key       quickly sign a key locally
     --sign-key              sign a key
     --lsign-key             sign a key locally
     --edit-key              sign or edit a key
     --change-passphrase     change a passphrase
     --export                export keys
     --send-keys             export keys to a keyserver
     --receive-keys          import keys from a keyserver
     --search-keys           search for keys on a keyserver
     --refresh-keys          update all keys from a keyserver
     --import                import/merge keys
     --card-status           print the card status
     --edit-card             change data on a card
     --change-pin            change a card&amp;#39;s PIN
     --update-trustdb        update the trust database
     --print-md              print message digests
     --server                run in server mode
     --tofu-policy VALUE     set the TOFU policy for a key

Options:

 -a, --armor                 create ascii armored output
 -r, --recipient USER-ID     encrypt for USER-ID
 -u, --local-user USER-ID    use USER-ID to sign or decrypt
 -z N                        set compress level to N (0 disables)
     --textmode              use canonical text mode
 -o, --output FILE           write output to FILE
 -v, --verbose               verbose
 -n, --dry-run               do not make any changes
 -i, --interactive           prompt before overwriting
     --openpgp               use strict OpenPGP behavior

(See the man page for a complete listing of all commands and options)

Examples:

 -se -r Bob [file]          sign and encrypt for user Bob
 --clear-sign [file]        make a clear text signature
 --detach-sign [file]       make a detached signature
 --list-keys [names]        show keys
 --fingerprint [names]      show fingerprints

Please report bugs to &amp;lt;https://bugs.gnupg.org&amp;gt;.&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Now, we&amp;#8217;ll take a man page (uptime as it&amp;#8217;s nice and short) and save it to a file ready to encrypt and email to test encryption.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@mx:~
$ man uptime &amp;gt; uptime.txt&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code&gt;simon@mx:~
$ gpg --armor --symmetric uptime.txt&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;We could save some keystrokes by just typing &lt;code&gt;gpg -ac &amp;lt;filename&amp;gt;&lt;/code&gt;&lt;/p&gt;

	&lt;p&gt;You&amp;#8217;ll be prompted for a password (which you have to enter twice), I chose &lt;code&gt;simonh&lt;/code&gt;&lt;/p&gt;

	&lt;p&gt;As you can see, gpg also compresses the encrypted file (&lt;code&gt;uptime.txt.asc&lt;/code&gt;).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@mx:~
$ ll
total 300K
-rw-r--r--  1 simon simon  113 Apr 17 18:18 dead.letter
drwxr-xr-x  2 simon simon 4.0K Apr 15 19:17 Desktop
drwxr-xr-x  2 simon simon 4.0K Apr 15 19:25 Documents
drwxr-xr-x  2 simon simon 4.0K Apr 15 19:25 Downloads
drwx------  2 simon simon 4.0K Apr 16 15:36 mail
drwx------  5 simon simon 4.0K Apr 16 17:26 Maildir
-rw-------  1 simon simon  467 Apr 19 18:26 mbox
drwxr-xr-x  2 simon simon 4.0K Apr 15 19:25 Music
drwxr-xr-x  2 simon simon 4.0K Apr 15 19:25 Pictures
drwxr-xr-x  2 simon simon 4.0K Apr 15 19:25 Public
drwxr-xr-x  3 simon simon 4.0K Apr 17 17:53 src
drwxr-xr-x  2 simon simon 4.0K Apr 15 19:25 Templates
-rw-r--r--  1 simon simon 1.9K May 20 16:52 uptime.txt
-rw-r--r--  1 simon simon 1.4K May 20 16:52 uptime.txt.asc
drwxr-xr-x 12 simon simon 4.0K May  9 20:00 var
drwxr-xr-x  2 simon simon 4.0K Apr 15 19:25 Videos&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Here is the (encrypted) contents of the uptime man page:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@mx:~
$ cat uptime.txt.asc 
-----BEGIN PGP MESSAGE-----

jA0ECQMCfoUA3aASbz7/0ukBogSiu3yxpUM+FfoTaCkTBqmUxYagw7ifq8R6WT4o
Za/3rgH7X7UXWuis9q+GKssabXdnZelUlUewnz5P/iHGYBP0C0KhCTHZm8r5abDg
L8E0nsLEYkSu1bcdz07Rdky0S6Pc3uqvFOJLnGBz+TUgWdzHEXtijCxYya1oasyf
izZD+QRGFcsCjh5Ji9BBK92Dza9lRRgvLeZ3PE9IDQjgtHz2qLEDJq82CRMqqzC5
Gv9xfG+sryEgWxKXjfa0XfiC9+9P1hZC4buaKxX26GS697ks2UikZ4EzOi6lpuUC
uGCwi3CdpjnrKnkkPqCixAVKmq6t81MMD1m6fbHnOJSHyRBdk+V7qgPQAq+wDbHM
BnQW4FmX5rVMPBKEezaM/HMJYjBwRjOpeBoAUF4gx8nr9YGTVJygNYgdH8P19mqf
rdxcCFf7OADpZOrxVl1aaaBC5EmEGhUO4zJ47a11m+Tg+0QNddRQOnUZQ6T76glM
Q6TvkxR/wewL3yAIfFqAYACWWyIlMsKOWi4BT8d4MQMauvRC039lQtrNb4E/DfSw
ZD4o4N28f5IrS2Icri0qpqCyK/5bhbSReXpcjgbCF61ckG8H6S6kucAidir7DCJS
gfxbTBuD+FmhN2D+tzerUV0WiMeHMBnvF24ng0zRS0bCG20yj3Kb2n4tsz64FIfj
bcDfPxjwnTNiSZUcmE75ClL9V/4M/NBIu0d1j/okdaTkbLHtsITrOSPenunhvFZp
cMcnDrvfAo+EpT4NIBJ6xrCRq/wRSSW5/cMAp3BF9RpYpmNr1MLQsVx4ax28Yid6
A2r865gPDVVyFBnIvmaFUpmGf9sGg3J2AnjcBpSAXzWnvn7nXXs84At4ZqwgBkhp
FLGWYaPv8MajifGjbjewjMJqYN/Xq8bBw+9x6HCL/AJT4XYeNhYYzHwqUhLFVJeS
PWisaW0bKx2lUYyHEMBW/+KSeTna+UiSEsnbhD+ZBrr9OBnRgPAgNlZwOUZPOVAM
RPvSJdMVkzMVDeHK7tJEUEUMHYpg/3VtVD/EjkHCRrkWStLx4IhJp4UszhH4H3Da
B/yklhNpbejjYOPFT75O/LCBM+cvzdBhO2QucsisyA6WD9fPTzR5clPsndHJSdKW
Ai8lfH5wI0D4Ci4kl2NTCEtIE/StbV4DhZx/VXVu08jSu+xuSribBGimGsAPu/lx
473lFEgjEujaXG2OvUZNBEQwqcBMd8cvkHT+9VyF1M/f8g==
=WzQF
-----END PGP MESSAGE-----&lt;/code&gt;&lt;/pre&gt;


	&lt;p&gt;We&amp;#8217;ll email it to ourselves now, read the email and save the message in the body to &lt;code&gt;uptime&lt;/code&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~$ gpg -d uptime &amp;gt; uptime-manual&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Of course, you&amp;#8217;ll be prompted for the password &lt;code&gt;simonh&lt;/code&gt; and you get the original file back.&lt;/p&gt;

	&lt;p&gt;Here&amp;#8217;s the original, decrypted text&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;UPTIME(1)                                 User Commands                                 UPTIME(1)

NAME
       uptime - Tell how long the system has been running.

SYNOPSIS
       uptime [options]

DESCRIPTION
       uptime  gives a one line display of the following information.  The current time, how long
       the system has been running, how many users are currently logged on, and the  system  load
       averages for the past 1, 5, and 15 minutes.

       This is the same information contained in the header line displayed by w(1).

       System  load  averages is the average number of processes that are either in a runnable or
       uninterruptable state.  A process in a runnable state is either using the CPU  or  waiting
       to  use  the  CPU.   A process in uninterruptable state is waiting for some I/O access, eg
       waiting for disk.  The averages are taken over the three time  intervals.   Load  averages
       are not normalized for the number of CPUs in a system, so a load average of 1 means a sin‐
       gle CPU system is loaded all the time while on a 4 CPU system it means it was idle 75%  of
       the time.

OPTIONS
       -p, --pretty
              show uptime in pretty format

       -h, --help
              display this help text

       -s, --since
              system up since, in yyyy-mm-dd HH:MM:SS format

       -V, --version
              display version information and exit

FILES
       /var/run/utmp
              information about who is currently logged on

       /proc  process information

AUTHORS
       uptime was written by Larry Greenfield ⟨greenfie@gauss.rutgers.edu⟩ and Michael K. Johnson
       ⟨johnsonm@sunsite.unc.edu⟩

SEE ALSO
       ps(1), top(1), utmp(5), w(1)

REPORTING BUGS
       Please send bug reports to ⟨procps@freelists.org⟩

procps-ng                                 December 2012                                 UPTIME(1)&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;So, just using this simple method, you can take any file, encrypt it (you can change the cipher by the way), compress it and then send it to someone who knows the key. If you accidentally send the message to someone who wasn&amp;#8217;t expecting it, they&amp;#8217;ll have little clue what it&amp;#8217;s all about. &lt;/p&gt;

	&lt;p&gt;Awesome!&lt;/p&gt;</content><category term="software"></category><category term="gpg"></category><category term="gnu"></category><category term="web"></category></entry><entry><title>Using WordPerfect 6.2 in DOSBox (Part 1)</title><link href="https://simonh.uk/2021/05/17/using-wordperfect-62-in-dosbox-part-1/" rel="alternate"></link><published>2021-05-17T00:00:00+01:00</published><updated>2021-05-17T00:00:00+01:00</updated><author><name>Simon Harrison</name></author><id>tag:simonh.uk,2021-05-17:/2021/05/17/using-wordperfect-62-in-dosbox-part-1/</id><summary type="html">	&lt;p&gt;Some say it went downhill from here&lt;/p&gt;</summary><content type="html">	&lt;p&gt;&lt;img alt="Wordperfect Logo" src="/img/2021-05-17/wp.gif" title="Wordperfect Logo" /&gt;&lt;/p&gt;

	&lt;h2&gt;Why?&lt;/h2&gt;

	&lt;blockquote&gt;
		&lt;p&gt;WordPerfect for &lt;span class="caps"&gt;DOS&lt;/span&gt;, in the opinion of many knowledgeable users, is still the greatest program ever written. Some of its features have not been matched even by the latest Windows software, and its interface remains unequaled for efficiency and elegance. Its support for multiple font formats has not been equaled by any other program or operating system, and its support for multiple alphabets, languages, and symbol sets has only been equaled by twenty-first-century versions of Windows, Linux, and the Mac OS.&lt;/p&gt;
	&lt;/blockquote&gt;

	&lt;p&gt;&lt;a href="http://www.columbia.edu/~em36/wpdos/"&gt;www.columbia.edu/~em36/wpdos/&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://www.dosdays.co.uk/topics/Software/wordperfect.php"&gt;www.dosdays.co.uk/topics/Software/wordperfect.php&lt;/a&gt;&lt;br /&gt;
&lt;a href="https://blog.cmpxchg8b.com/2020/09/finding-console-word-processor.html"&gt;blog.cmpxchg8b.com/2020/09/finding-console-word-processor.html&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://www.studymore.org.uk/wp51.htm"&gt;www.studymore.org.uk/wp51.htm&lt;/a&gt;&lt;/p&gt;

	&lt;h2&gt;My Reasons&lt;/h2&gt;

	&lt;p&gt;I use &lt;span class="caps"&gt;GNU&lt;/span&gt;/Linux and the obvious choices are LibreOffice, Apache OpenOffice and Abiword. They&amp;#8217;re all fine and the first two can go toe to toe with MS Office any day of the week. &lt;/p&gt;

	&lt;p&gt;But sometimes, I think it&amp;#8217;s a bit overkill. And LibreOffice isn&amp;#8217;t exactly &lt;em&gt;fast&lt;/em&gt; to load up. This isn&amp;#8217;t the first time I&amp;#8217;ve installed WordPerfect, but as I&amp;#8217;ve got a bit of time on my hands, I thought I&amp;#8217;d dig a bit deeper.&lt;/p&gt;

	&lt;p&gt;And to my knowledge, Linux never really had a &lt;em&gt;great&lt;/em&gt; word processor (correct me if I&amp;#8217;m wrong).&lt;/p&gt;

	&lt;h2&gt;Add Colemak Keyboard Layout to Dosbox&lt;/h2&gt;

	&lt;p&gt;I&amp;#8217;m awkward so I use an alternative keyboard layout called &lt;a href="https://colemak.com/"&gt;Colemak&lt;/a&gt;. I&amp;#8217;ve been using it since 2008 so the first order of business was to get that set up correctly.&lt;/p&gt;

	&lt;p&gt;Copy this &lt;a href="https://gist.github.com/gonejack/0655029de3465cb78f3e"&gt;mapper&lt;/a&gt;&lt;/p&gt;

	&lt;p&gt;Save that as &lt;code&gt;colemak-0.74.map&lt;/code&gt; in you dosbox settings directory. &lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~/.dosbox$ tree
.
├── colemak-0.74.map
├── dosbox-0.74-3.conf
└── dosbox-0.74.conf&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Open &lt;code&gt;dosbox-0.74-3.conf&lt;/code&gt; and find the line beginning with &lt;code&gt;mapperfile&lt;/code&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;mapperfile=mapper-0.74-3.map&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;I usually just comment out the original value and add the new one below:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#mapperfile=mapper-0.74-3.map
mapperfile=colemak-0.74.map&lt;/code&gt;&lt;/pre&gt;

	&lt;h2&gt;Obtain the Software&lt;/h2&gt;

	&lt;p&gt;I searched for &amp;#8220;Corel WordPerfect Suite 6.2 for &lt;span class="caps"&gt;DOS&lt;/span&gt;&amp;#8221; and the filesize of the &lt;code&gt;.7z&lt;/code&gt; file should be about 49.1MB.&lt;/p&gt;

	&lt;p&gt;Open with wine (5.0) and follow the prompts. I opted to only install WordPerfect, not the full suite. &lt;/p&gt;

	&lt;p&gt;Here are a few screenshots of the install process. Notice the help tips &lt;/p&gt;

	&lt;p&gt;&lt;img alt="installation 1" src="/img/2021-05-17/wp-install1.png" title="installation 1" /&gt;&lt;/p&gt;

	&lt;p&gt;&lt;img alt="installation 2" src="/img/2021-05-17/wp-install2.png" title="installation 2" /&gt;&lt;/p&gt;

	&lt;p&gt;&lt;img alt="installation 3" src="/img/2021-05-17/wp-install3.png" title="installation 3" /&gt;&lt;/p&gt;

	&lt;p&gt;When it&amp;#8217;s finished installing you&amp;#8217;ll need to launch &lt;code&gt;WP.EXE&lt;/code&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;simon@computer:~/.wine/drive_c/COREL/WP62$ ls
CVDASC.CVX   HRF6.FRS      TIBM.VRS     VMP.COM       WP_OS2.ICO
CVDTKT.CVX   INSTALL.EXE   T_LES1K.TUT  WP350M.ORS    WPSTAND.DR
CVDWP5X.CVX  LIBRARY.STY   T_LES1M.TUT  WP350.ORS     WPUS.ICR
CVDWP60.CVX  MACROS        T_LES2.TUT   WP480M.ORS    WP{WPC}.LCN
CVDWPG1.CVX  MCV.EXE       T_LES3.TUT   WP480.ORS     WP{WPC}.QKL
CVDWPG2.CVX  QFIGENUS.EXE  T_LES4.TUT   WP62.INS      WP{WPC}.SET
CV.EXE       README.ARS    T_LIB.TUT    WP62.PIF      WP_WP_US.BRS
EGA512.FRS   README.CV     T_LTRS.TUT   WP.COM        WP_WP_US.HLM
EGAITAL.FRS  README.FAX    VAPINUL.COM  WP_CV_US.DLG  WP_WP_US.HLP
EGASMC.FRS   README.MCV    VGA512.FRS   WP_CV_US.HLP  WP_WP_US.MRS
EGAUND.FRS   README.VRS    VGAITAL.FRS  WP.EXE        WP_WP_US.QRS
EGA.VRS      README.WP     VGASMC.FRS   WP.FIL        WP_WP_US.TRS
GRAPHICS     STANDARD.IRS  VGAUND.FRS   WPICONS.DLL   WP_WP_US.TUT
HRF12.FRS    TEMPLATE      VGA.VRS      WP.LRS&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Which will give you the following beautiful screen&lt;/p&gt;

	&lt;p&gt;&lt;img alt="wordperfect running" src="/img/2021-05-17/wp-dosbox1.png" title="wordperfect running" /&gt;&lt;/p&gt;

	&lt;p&gt;The first thing you&amp;#8217;ll want to do is choose &lt;code&gt;Help &amp;gt; Tutorial&lt;/code&gt; from the top menu.&lt;/p&gt;

	&lt;p&gt;&lt;img alt="help &amp;gt; tutorial" src="/img/2021-05-17/wp-dosbox2.png" title="help &amp;gt; tutorial" /&gt;&lt;/p&gt;

	&lt;p&gt;And spend about twenty minutes going through them. It&amp;#8217;s worth your time, I assure you.&lt;/p&gt;

	&lt;p&gt;&lt;img alt="help &amp;gt; tutorial" src="/img/2021-05-17/wp-dosbox3.png" title="help &amp;gt; tutorial" /&gt;&lt;/p&gt;

	&lt;p&gt;By the way, your mouse will be &lt;strong&gt;trapped&lt;/strong&gt; in the dosbox window. To free it hit &lt;code&gt;CTRL-F10&lt;/code&gt; (took me a while to discover that)!&lt;/p&gt;

	&lt;h2&gt;WordPerfect Tips&lt;/h2&gt;

	&lt;p&gt;&lt;a href="http://www.microcounsel.com/WPTIPS.HTM"&gt;www.microcounsel.com/WPTIPS.HTM&lt;/a&gt;&lt;br /&gt;
&lt;a href="https://www.youtube.com/watch?v=ML_GoEUhs4A"&gt;www.youtube.com/watch?v=ML_GoEUhs4A&lt;/a&gt;&lt;/p&gt;

	&lt;p&gt;And the first link at top of this page, has lots of great resources for getting help, manuals etc.&lt;/p&gt;</content><category term="software"></category><category term="software"></category><category term="dos"></category><category term="terminal"></category></entry><entry><title>Interesting UNIX, BSD, Linux programs and Packages</title><link href="https://simonh.uk/2021/04/19/interesting-unix-bsd-linux-programs-and-packages/" rel="alternate"></link><published>2021-04-19T00:00:00+01:00</published><updated>2021-04-19T00:00:00+01:00</updated><author><name>Simon Harrison</name></author><id>tag:simonh.uk,2021-04-19:/2021/04/19/interesting-unix-bsd-linux-programs-and-packages/</id><summary type="html">	&lt;p&gt;A Post-it&amp;#8482; note for *nix stuff.&lt;/p&gt;</summary><content type="html">	&lt;p&gt;&lt;img alt="Vintage Terminal" src="/img/2021-04-19/vt100.webp" title="Vintage Terminal" /&gt;&lt;/p&gt;

	&lt;h1&gt;Mail&lt;/h1&gt;

	&lt;p&gt;&lt;a href="https://mailutils.org/"&gt;Mailutils&lt;/a&gt;&lt;/p&gt;

	&lt;blockquote&gt;
		&lt;p&gt;Mailutils is a swiss army knife of electronic mail handling. It offers a rich set of utilities and daemons for processing e-mail.&lt;/p&gt;
	&lt;/blockquote&gt;

	&lt;p&gt;&lt;a href="https://github.com/leahneukirchen/mblaze"&gt;mblaze&lt;/a&gt;&lt;/p&gt;

	&lt;blockquote&gt;
		&lt;p&gt;The mblaze message system is a set of Unix utilities for processing and intseracting with mail messages which are stored in maildir folders.&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;&lt;a href="https://github.com/nicm/fdm"&gt;fdm&lt;/a&gt;&lt;/p&gt;

	&lt;blockquote&gt;
		&lt;p&gt;fdm is a program designed to fetch mail from POP3 or &lt;span class="caps"&gt;IMAP&lt;/span&gt; servers, or receive local mail from stdin, and deliver it in various ways.&lt;/p&gt;
	&lt;/blockquote&gt;

	&lt;p&gt;&lt;a href="https://getmail6.org/"&gt;getmail6&lt;/a&gt;&lt;/p&gt;

	&lt;blockquote&gt;
		&lt;p&gt;Welcome to getmail 6, a mail retriever with support for POP3, POP3-over-&lt;span class="caps"&gt;SSL&lt;/span&gt;, IMAP4, IMAP4-over-&lt;span class="caps"&gt;SSL&lt;/span&gt;, and &lt;span class="caps"&gt;SDPS&lt;/span&gt; mail accounts. It supports normal single-user mail accounts and multidrop (domain) mailboxes. getmail is written in Python, and licensed under the &lt;span class="caps"&gt;GNU&lt;/span&gt; General Public License version 2.&lt;/p&gt;
	&lt;/blockquote&gt;

	&lt;p&gt;&lt;a href="http://pyropus.ca/software/getmail/"&gt;getmail&lt;/a&gt;&lt;/p&gt;

	&lt;blockquote&gt;
		&lt;p&gt;getmail is a mail retriever designed to allow you to get your mail from one or more mail accounts on various mail servers to your local machine for reading with a minimum of fuss. getmail is designed to be secure, flexible, reliable, and easy-to-use. getmail is designed to replace other mail retrievers such as fetchmail.&lt;/p&gt;
	&lt;/blockquote&gt;

	&lt;p&gt;&lt;a href="https://public-inbox.org/"&gt;public-inbox&lt;/a&gt;&lt;/p&gt;

	&lt;blockquote&gt;
		&lt;p&gt;public-inbox implements the sharing of an email inbox via git to&lt;br /&gt;
complement or replace traditional mailing lists.  Readers may&lt;br /&gt;
read via &lt;span class="caps"&gt;NNTP&lt;/span&gt;, &lt;span class="caps"&gt;IMAP&lt;/span&gt;, Atom feeds or &lt;span class="caps"&gt;HTML&lt;/span&gt; archives.&lt;/p&gt;
	&lt;/blockquote&gt;

	&lt;p&gt;&lt;a href="https://www.dbmail.org/"&gt;dbmail&lt;/a&gt;&lt;/p&gt;

	&lt;blockquote&gt;
		&lt;p&gt;Fast and scalable sql based email services&lt;br /&gt;
Storage of mail messages in a relational database&lt;br /&gt;
Frontends: IMAP4, POP3, ManageSieve, LMTP&lt;br /&gt;
Backends: MySQL, PostgreSQL, Oracle, and &lt;span class="caps"&gt;SQL&lt;/span&gt;ite&lt;/p&gt;
	&lt;/blockquote&gt;

	&lt;p&gt;&lt;a href="https://puszcza.gnu.org.ua/software/mailfromd/"&gt;Mailfromd&lt;/a&gt;&lt;/p&gt;

	&lt;blockquote&gt;
		&lt;p&gt;Mailfromd is a general-purpose mail filtering daemon for Sendmail, Postfix and MeTA1. It is able to filter both incoming and outgoing messages using criteria of arbitrary complexity, supplied by the administrator in the form of a script file. The daemon interfaces with the &lt;span class="caps"&gt;MTA&lt;/span&gt; using Milter or PMilter protocols.&lt;/p&gt;
	&lt;/blockquote&gt;

	&lt;p&gt;&lt;a href="http://www.ivarch.com/programs/qsf/"&gt;&lt;span class="caps"&gt;QSF&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;

	&lt;blockquote&gt;
		&lt;p&gt;Quick Spam Filter (&lt;span class="caps"&gt;QSF&lt;/span&gt;) is an Open Source email classification filter, designed to be small, fast, and accurate, which works to classify incoming email as either spam or non-spam. To recognise spam, &lt;span class="caps"&gt;QSF&lt;/span&gt; strips the text out of the email (using &lt;span class="caps"&gt;MIME&lt;/span&gt; decoding and &lt;span class="caps"&gt;HTML&lt;/span&gt; stripping) and then splits it into tokens (words, word pairs, &lt;span class="caps"&gt;URL&lt;/span&gt;s, and so on). These tokens are then looked up in a database and analysed using the Bayesian technique to see whether the email should be classified as spam or not.&lt;/p&gt;
	&lt;/blockquote&gt;</content><category term="software"></category><category term="linux"></category><category term="debian"></category></entry><entry><title>Mercurial for the Lone Coder</title><link href="https://simonh.uk/2020/09/08/mercurial-for-the-lone-coder/" rel="alternate"></link><published>2020-09-08T00:00:00+01:00</published><updated>2020-09-08T00:00:00+01:00</updated><author><name>Simon Harrison</name></author><id>tag:simonh.uk,2020-09-08:/2020/09/08/mercurial-for-the-lone-coder/</id><summary type="html">	&lt;p&gt;Learn to Love Revision Control&lt;/p&gt;</summary><content type="html">	&lt;p&gt;&lt;img alt="Mercurial Logo" src="/img/logo/mercurial.svg" title="Mercurial Logo" /&gt;&lt;/p&gt;

	&lt;h2&gt;Background&lt;/h2&gt;

	&lt;p&gt;I&amp;#8217;ve been a (productive) programmer for about three years now.&lt;br /&gt;
My workflow has been the following:&lt;/p&gt;

	&lt;ol&gt;
		&lt;li&gt;set up a folder for the project&lt;/li&gt;
		&lt;li&gt;start working&lt;/li&gt;
		&lt;li&gt;create an archive of the folder with the current date each day and save that in multiple locations for backup&lt;/li&gt;
		&lt;li&gt;rename the folder to todays date&lt;/li&gt;
		&lt;li&gt;Back to step 2&lt;/li&gt;
	&lt;/ol&gt;

	&lt;p&gt;I was aware pretty much from day one that this wasn&amp;#8217;t the best setup, but it worked and I didn&amp;#8217;t have to worry about any tool clobbering my work and leaving me with &lt;a href="https://www.mail-archive.com/fossil-users%40lists.fossil-scm.org/msg04665.html"&gt;lost files&lt;/a&gt;&lt;/p&gt;

	&lt;p&gt;I remember that happening at the time, as Zed Shaw went from a massive fan of fossil, to, well, not a massive fan. &lt;/p&gt;

	&lt;p&gt;Over the years, I&amp;#8217;ve tried &lt;a href="https://fossil-scm.org/"&gt;Fossil&lt;/a&gt;, &lt;a href="https://git-scm.com/"&gt;Git&lt;/a&gt; and &lt;a href="https://www.mercurial-scm.org/"&gt;Mercurial&lt;/a&gt; (and probably others). &lt;/p&gt;

	&lt;p&gt;I always came to the conclusion that I&amp;#8217;d need to put in too much time to learn their intricacies to bother with them.&lt;/p&gt;

	&lt;p&gt;Anyway, last month I decided to revisit &lt;span class="caps"&gt;SCM&lt;/span&gt; again. As I&amp;#8217;d been using &lt;span class="caps"&gt;SQL&lt;/span&gt;ite a lot, I thought Fossil would be ideal as it&amp;#8217;s used as the &lt;span class="caps"&gt;SCM&lt;/span&gt; for &lt;span class="caps"&gt;SQL&lt;/span&gt;ite itself. &lt;/p&gt;

	&lt;h2&gt;My Thoughts about Fossil&lt;/h2&gt;

	&lt;p&gt;Fossil uses an sqlite database as the repository. One of it&amp;#8217;s best features is that it&amp;#8217;s an &lt;span class="caps"&gt;SCM&lt;/span&gt;, a wiki, a bug tracker, a forum, a website, and probably other stuff too.&lt;/p&gt;

	&lt;p&gt;What annoyed me very quickly though is the workflow:&lt;/p&gt;

	&lt;ul&gt;
		&lt;li&gt;Create a directory ~/fossil where you store your repositories&lt;/li&gt;
		&lt;li&gt;From that directory run &lt;code&gt;fossil new  project.fossil /path/to/where/actual/code/is&lt;/code&gt;&lt;/li&gt;
		&lt;li&gt;Then run &lt;code&gt;fossil open /path/to/where/actual/code/is&lt;/code&gt;&lt;/li&gt;
		&lt;li&gt;Get a warning from fossil that the directory is not empty and must use &lt;code&gt;--force&lt;/code&gt; to override&lt;/li&gt;
	&lt;/ul&gt;

	&lt;p&gt;I mean, come on! So, I ditched the idea of using fossil and thought I&amp;#8217;d see what Mercurial (hg) was like nowadays. &lt;/p&gt;

	&lt;p&gt;Here is the hg way:&lt;/p&gt;

	&lt;ul&gt;
		&lt;li&gt;Run &lt;code&gt;hg init&lt;/code&gt; in the directory you want to track&lt;/li&gt;
		&lt;li&gt;Run &lt;code&gt;hg add .&lt;/code&gt; to add everything&lt;/li&gt;
		&lt;li&gt;Make some changes, run &lt;code&gt;hg commit -m 'I changed some things'&lt;/code&gt;&lt;/li&gt;
		&lt;li&gt;Run &lt;code&gt;hg serve&lt;/code&gt; and have a web interface&lt;/li&gt;
	&lt;/ul&gt;

	&lt;p&gt;I recommend using &lt;code&gt;hg c 'Changed something else'&lt;/code&gt;&lt;/p&gt;

	&lt;p&gt;by adding the following to your &lt;code&gt;~/.hgrc&lt;/code&gt;&lt;/p&gt;

	&lt;p&gt;&lt;code&gt;[alias]&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;c = commit -m&lt;/code&gt;&lt;/p&gt;


	&lt;p&gt;TO BE &lt;span class="caps"&gt;CONTINUED&lt;/span&gt;&amp;#8230;&lt;/p&gt;</content><category term="software"></category><category term="python"></category><category term="mercurial"></category><category term="scm"></category><category term="coding"></category></entry><entry><title>My New Favourite Text Editor</title><link href="https://simonh.uk/2016/01/19/my-new-favourite-text-editor/" rel="alternate"></link><published>2016-01-19T00:00:00+00:00</published><updated>2016-01-19T00:00:00+00:00</updated><author><name>Simon Harrison</name></author><id>tag:simonh.uk,2016-01-19:/2016/01/19/my-new-favourite-text-editor/</id><summary type="html">&lt;p&gt;Notepad2-mod is great!&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;em&gt;Note: This post is from an old Pelican blog I used to have at simonh.me, which I found on a backup drive on 2025-01-07. It's probably of no use, but reposted for posterity!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Over the years, I've tried &lt;em&gt;lots&lt;/em&gt; of text editors. Vim, EMACS, Sublime Text,
Jedit, Nano, Notepad++ (and more). As I use Linux at home and Windows at work, I've been looking for a while, for one that I can use on either OS. &lt;/p&gt;
&lt;p&gt;As much as I love Linux (and I have &lt;strong&gt;no&lt;/strong&gt; desire to switch back to Windows after about six years), there is some software written for Windows that I think is fantastic. Foobar2000, imgburn (when I used to burn discs), Adobe Photoshop and namexif spring to mind. &lt;/p&gt;
&lt;p&gt;So, a few weeks ago I set about (again) finding a text editor that I could use just as well at work as I could at home. I had another go with Notepad++. It seemed to be trying to do a bit too much. The interface has too much going on. I needed something simpler. Plus there were some oddities running on Wine. I somehow stumbled upon Notepad2-mod &lt;a href="https://xhmikosr.github.io/notepad2-mod/"&gt;https://xhmikosr.github.io/notepad2-mod/&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;A text editor that wanted to be &lt;em&gt;slightly better&lt;/em&gt; than Notepad??? This doesn't sound good, I thought. But when I tried it, it seemed to be just what I was looking for. Syntax highlighting for Python and indentation guides are all I really need at the moment. Plus, it works great on Wine. &lt;/p&gt;
&lt;p&gt;It does very little for you, except what you &lt;strong&gt;need&lt;/strong&gt;. I class that as a
feature. I have the utmost respect for editors like Vim, but that it is pretty
much unusable "out of the box", without hunting around on the net for 
tips on how to set up your &lt;code&gt;.vimrc&lt;/code&gt; seems strange to me. &lt;/p&gt;
&lt;p&gt;If you haven't tried it, and are wanting to do some coding, rather than
learning the intricacies of a particular text editor, I urge you to give it
a go. &lt;/p&gt;</content><category term="software"></category><category term="coding"></category><category term="archived"></category></entry></feed>