<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>Posts on Everything Tastes Better With Chilli</title>
		<link>https://blog.markhepburn.com/posts/</link>
		<description>Recent content in Posts on Everything Tastes Better With Chilli</description>
		<generator>Hugo -- gohugo.io</generator>
		<language>en-us</language>
		<copyright>This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.</copyright>
		<lastBuildDate>Fri, 02 Jan 2026 13:57:05 +1100</lastBuildDate>
		<atom:link href="https://blog.markhepburn.com/posts/index.xml" rel="self" type="application/rss+xml" />
		
		<item>
			<title>Running OpenCloud on Minimal Resources</title>
			<link>https://blog.markhepburn.com/posts/running-opencloud-on-minimal-resources/</link>
			<pubDate>Fri, 02 Jan 2026 13:57:05 +1100</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/running-opencloud-on-minimal-resources/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[
<p>
<em>There is a cliche that most blog posts consist of descriptions of their blogging setup and subsequent rewrites.  I am not immune to this trope.</em></p>
<p>
I have a small <a href="https://www.digitalocean.com/">DigitalOcean droplet</a> (VM) that runs this blog, and a few other personal services; the main one is storage sync, which for years has been <a href="https://nextcloud.com/">NextCloud</a>.  This was <em>fine</em>, but a but clunky (not helped by 3-container docker-compose setup), and sync was pretty unreliable in the incoming direction: for example, the &#34;open up laptop and receive incoming changes&#34; use-case was a bit flaky without a manual poke, and the even more complicated &#34;laptop is already open, receive incoming changes recently made elsewhere&#34; story was basically non-functional (without, again, manually clicking &#34;sync now&#34;).  Recently though I&#39;d been hearing good things about <a href="https://opencloud.eu/en">OpenCloud</a><sup class="footnote-reference"><a id="footnote-reference-1" href="#footnote-1">1</a></sup> and after a bit of testing decided to make the switch.  I needed to update the OS as well anyway, so good time for changes and a rebuild.</p>
<p>
The switch was essentially painless and has been running smoothly, but I did need to make some tweaks beyond the initial install, hence this post.</p>
<div id="outline-container-headline-1" class="outline-2">
<h2 id="headline-1">
Overview
</h2>
<div id="outline-text-headline-1" class="outline-text-2">
<p>
I prefer Podman over Docker where feasible, and I run OpenCloud as a <a href="https://www.redhat.com/en/blog/quadlet-podman">Quadlet</a>; essentially, a systemd service defined around a container rather than a command line.</p>
<p>
I use DigitalOcean&#39;s <a href="https://www.digitalocean.com/products/spaces">Spaces</a> S3-compatible storage.  I used this with NextCloud as well, but rather than try and migrate the data and recreate metadata etc, I simply created a fresh space and re-uploaded everything.</p>
<p>
Interestingly, OpenCloud doesn&#39;t use a database for metadata, but writes all metadata to the file system.  I mount these as external folders, so I can back them up easily.</p>
</div>
</div>
<div id="outline-container-headline-2" class="outline-2">
<h2 id="headline-2">
Tweaks
</h2>
<div id="outline-text-headline-2" class="outline-text-2">
<p>
Initial deployment impressions were a bit disappointing, with both sluggishness and even the OOM-killer appearing multiple times.  I needed to do some memory tuning.</p>
<p>
OpenCloud is continually running, rather than an on-demand PHP process, which both makes problems more evident, and is also easier to test.</p>
<div id="outline-container-headline-3" class="outline-3">
<h3 id="headline-3">
Swap
</h3>
<div id="outline-text-headline-3" class="outline-text-3">
<p>
This is probably table-stakes, but disappointingly took me a little while to realise!  For context, my droplet has 1G of memory.  Instead of a separate partition (I haven&#39;t looked if they even support it, but this isn&#39;t the default with DigitalOcean), you can allocate a  file to be used instead:</p>
<div class="src src-sh">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">sudo fallocate -l 2G /swapfile
</span></span><span class="line"><span class="cl">sudo chmod <span class="m">600</span> /swapfile
</span></span><span class="line"><span class="cl">sudo mkswap /swapfile
</span></span><span class="line"><span class="cl">sudo swapon /swapfile
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s1">&#39;/swapfile none swap sw 0 0&#39;</span> <span class="p">|</span> sudo tee -a /etc/fstab</span></span></code></pre></div>
</div>
<p>(note the last line which makes it permanent)</p>
</div>
</div>
<div id="outline-container-headline-4" class="outline-3">
<h3 id="headline-4">
Service Selection
</h3>
<div id="outline-text-headline-4" class="outline-text-3">
<p>
OpenCloud (and its brethren) isn&#39;t just a file storage, it&#39;s aiming to be an infinitely-extensible collaborative app platform, with calendaring, document-authoring, and the works.  Additionally, its desire to be scalable means that it is or can be a collection of services that can be replaced or separately-hosted.</p>
<p>
For convenience, you can <em>also</em> just run <code class="verbatim">opencloud server</code>, which runs everything you need in one self-contained executable.</p>
<p>
This is also the potential for problems, because I don&#39;t need most of what it provides: I use file-sync, and its built-in authentication, and that&#39;s about it.</p>
<p>
Fortunately, there is a way to disable services you don&#39;t need, freeing up resources, via the <code class="verbatim">OC_EXCLUDE_RUN_SERVICES</code> environment variable.  Presumably you can also shoot yourself in the foot this way so I was a little conservative, but I don&#39;t need search (no need to build an index), aren&#39;t worried about antivirus scans, don&#39;t send email, etc.  I wound up setting <code class="verbatim">OC_EXCLUDE_RUN_SERVICES=search,antivirus,app-registry,app-provider,invitations,notifications</code>.</p>
</div>
</div>
<div id="outline-container-headline-5" class="outline-3">
<h3 id="headline-5">
Scraping the bottom of the barrel
</h3>
<div id="outline-text-headline-5" class="outline-text-3">
<p>
Lastly (in full disclosure, this was a Gemini suggestion), I added some <a href="https://go.dev/doc/gc-guide">Go garbage-collector tweaks</a>.  I&#39;m not sure if they make any practical difference, but they&#39;re still there:</p>
<div class="src src-sh">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">GOMEMLIMIT</span><span class="o">=</span>700MiB
</span></span><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">GOGC</span><span class="o">=</span><span class="m">50</span></span></span></code></pre></div>
</div>
</div>
</div>
</div>
</div>
<div id="outline-container-headline-6" class="outline-2">
<h2 id="headline-6">
Wrapping Up
</h2>
<div id="outline-text-headline-6" class="outline-text-2">
<p>
For completeness, this is essentially what my quadlet <code class="verbatim">.container</code> file looks like:</p>
<div class="src src-sh">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl"><span class="o">[</span>Container<span class="o">]</span>
</span></span><span class="line"><span class="cl"><span class="nv">ContainerName</span><span class="o">=</span>opencloud
</span></span><span class="line"><span class="cl"><span class="nv">Image</span><span class="o">=</span>docker.io/opencloudeu/opencloud
</span></span><span class="line"><span class="cl"><span class="nv">AutoUpdate</span><span class="o">=</span>registry
</span></span><span class="line"><span class="cl"><span class="nv">PublishPort</span><span class="o">=</span>9200:9200
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">Environment</span><span class="o">=</span><span class="nv">OC_URL</span><span class="o">=</span>https://opencloud.example.com
</span></span><span class="line"><span class="cl"><span class="nv">Environment</span><span class="o">=</span><span class="nv">PROXY_TLS</span><span class="o">=</span><span class="nb">false</span>
</span></span><span class="line"><span class="cl"><span class="nv">Environment</span><span class="o">=</span><span class="nv">OC_INSECURE</span><span class="o">=</span><span class="nb">true</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># For webdav:</span>
</span></span><span class="line"><span class="cl"><span class="nv">Environment</span><span class="o">=</span><span class="nv">PROXY_ENABLE_BASIC_AUTH</span><span class="o">=</span><span class="nb">true</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">Environment</span><span class="o">=</span><span class="nv">STORAGE_USERS_DRIVER</span><span class="o">=</span>decomposeds3
</span></span><span class="line"><span class="cl"><span class="nv">Environment</span><span class="o">=</span><span class="nv">STORAGE_USERS_DECOMPOSEDS3_ENDPOINT</span><span class="o">=</span>https://syd1.digitaloceanspaces.com
</span></span><span class="line"><span class="cl"><span class="nv">Environment</span><span class="o">=</span><span class="nv">STORAGE_USERS_DECOMPOSEDS3_REGION</span><span class="o">=</span>syd1
</span></span><span class="line"><span class="cl"><span class="nv">Environment</span><span class="o">=</span><span class="nv">STORAGE_USERS_DECOMPOSEDS3_ACCESS_KEY</span><span class="o">=</span>XXXXXXSTORAGEACCESSKEY
</span></span><span class="line"><span class="cl"><span class="nv">Environment</span><span class="o">=</span><span class="nv">STORAGE_USERS_DECOMPOSEDS3_SECRET_KEY</span><span class="o">=</span>XXXXXXSTORAGEACCESSSECRET
</span></span><span class="line"><span class="cl"><span class="nv">Environment</span><span class="o">=</span><span class="nv">STORAGE_USERS_DECOMPOSEDS3_BUCKET</span><span class="o">=</span>bucketname
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Memory optimisation</span>
</span></span><span class="line"><span class="cl"><span class="nv">Environment</span><span class="o">=</span><span class="nv">GOMEMLIMIT</span><span class="o">=</span>700MiB
</span></span><span class="line"><span class="cl"><span class="nv">Environment</span><span class="o">=</span><span class="nv">GOGC</span><span class="o">=</span><span class="m">50</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Exclude unused services:</span>
</span></span><span class="line"><span class="cl"><span class="nv">Environment</span><span class="o">=</span><span class="nv">OC_EXCLUDE_RUN_SERVICES</span><span class="o">=</span>search,antivirus,app-registry,app-provider,invitations,notifications
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">Volume</span><span class="o">=</span>/local/data/dir:/var/lib/opencloud:z
</span></span><span class="line"><span class="cl"><span class="nv">Volume</span><span class="o">=</span>/local/config/dir:/etc/opencloud:z
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Entrypoint=/bin/sh # not supported on podman 4.9.3</span>
</span></span><span class="line"><span class="cl"><span class="nv">PodmanArgs</span><span class="o">=</span>--entrypoint<span class="o">=</span>/bin/sh
</span></span><span class="line"><span class="cl"><span class="nv">Exec</span><span class="o">=</span>-c <span class="s2">&#34;opencloud init --insecure true; exec opencloud server&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># This is the internal uid/gid; see podman inspect docker.io/opencloudeu/opencloud --format &#39;{{.Config.User}}&#39;</span>
</span></span><span class="line"><span class="cl"><span class="nv">User</span><span class="o">=</span>1000:1000
</span></span><span class="line"><span class="cl"><span class="c1"># And this maps the internal ids to the local opencloud user (which is uid 1002 as of current testing)</span>
</span></span><span class="line"><span class="cl"><span class="nv">UserNS</span><span class="o">=</span>keep-id:uid<span class="o">=</span>1000,gid<span class="o">=</span><span class="m">1000</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="o">[</span>Service<span class="o">]</span>
</span></span><span class="line"><span class="cl"><span class="nv">Restart</span><span class="o">=</span>always
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="o">[</span>Install<span class="o">]</span>
</span></span><span class="line"><span class="cl"><span class="nv">WantedBy</span><span class="o">=</span>default.target</span></span></code></pre></div>
</div>
</div>
</div>
<div id="outline-container-headline-7" class="outline-2">
<h2 id="headline-7">
Footnotes
</h2>
</div>
<div class="footnotes">
<hr class="footnotes-separatator">
<div class="footnote-definitions">
<div class="footnote-definition">
<sup id="footnote-1"><a href="#footnote-reference-1">1</a></sup>
<div class="footnote-body">
<p>The lineage as I understand it: in the beginning was <a href="https://owncloud.com/">OwnCloud</a>, written in PHP.  Then <a href="https://nextcloud.com/">NextCloud</a> forked off OwnCloud, also of course in PHP.  Next, OwnCloud embarked on a rewrite, &#34;<a href="https://owncloud.com/infinite-scale/">OwnCloud Infinite-Scale</a>&#34;, which is written in Go, re-architected, and makes a few other changes in approach as well.  Finally, OpenCloud is a fork of this infinite-scale.  I believe the recent European desire for self-hosting and SaaS sovereignty played a part here, but I&#39;m not sure.</p>
</div>
</div>
</div>
</div>
]]></content>
		</item>
		
		<item>
			<title>Books in 2025</title>
			<link>https://blog.markhepburn.com/posts/books-in-2025/</link>
			<pubDate>Thu, 01 Jan 2026 11:16:18 +1100</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/books-in-2025/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[
<p>
This is now my third full year of intentionally tracking my reading.  The pure numbers continued an unfortunate downward trend, with only 26 completed in 2025.  Sitting here with last night&#39;s hangover still gently jostling around, a book every fortnight feels about right, but also my notes were qualitatively less rigorous or thought-through, which is as much a benefit of this exercise as anything, so I&#39;ll endeavour to improve on that this coming year.</p>
<p>
Sometimes I&#39;ll make a note or two as I read (frequently, starting with why I&#39;m picking this particular book, as I&#39;m starting it), but sometimes I&#39;ll make a perfunctory comment at the end and that&#39;s it.  The former feels much more productive.</p>
<p>
In terms of content my recollection is that it was a mix of technical (largely explaining why I didn&#39;t get through as much this year, particularly reading technical content in bed at night) and &#34;easy reading&#34; when I felt like a break.  Looking back over the list though there&#39;s a bit more variety than I might have suspected.</p>
<div id="outline-container-headline-1" class="outline-2">
<h2 id="headline-1">
The books
</h2>
<div id="outline-text-headline-1" class="outline-text-2">
<table>
<thead>
<tr>
<th>Book</th>
<th>AUTHOR</th>
<th>STARTED</th>
<th>FINISHED</th>
</tr>
</thead>
<tbody>
<tr>
<td>Hail Mary</td>
<td>Weir, A.</td>
<td><span class="timestamp">&lt;2025-01-01 Wed&gt;</span></td>
<td><span class="timestamp">&lt;2025-01-22 Wed&gt;</span></td>
</tr>
<tr>
<td>Easy Go</td>
<td>Crichton, M.</td>
<td><span class="timestamp">&lt;2025-01-31 Fri&gt;</span></td>
<td><span class="timestamp">&lt;2025-02-08 Sat&gt;</span></td>
</tr>
<tr>
<td>Become an Effective Software Engineering Manager</td>
<td>Stanier, J.</td>
<td><span class="timestamp">&lt;2025-01-22 Wed&gt;</span></td>
<td><span class="timestamp">&lt;2025-02-11 Tue&gt;</span></td>
</tr>
<tr>
<td>Picks and Shovels</td>
<td>Doctorow, C.</td>
<td><span class="timestamp">&lt;2025-02-11 Tue&gt;</span></td>
<td><span class="timestamp">&lt;2025-02-22 Sat&gt;</span></td>
</tr>
<tr>
<td>The Endurance Handbook</td>
<td>Maffetone, P.</td>
<td><span class="timestamp">&lt;2025-02-22 Sat&gt;</span></td>
<td><span class="timestamp">&lt;2025-03-03 Mon&gt;</span></td>
</tr>
<tr>
<td>A Farewell to Arms</td>
<td></td>
<td></td>
<td><span class="timestamp">&lt;2025-05-14 Wed&gt;</span></td>
</tr>
<tr>
<td>Canadian Miracle</td>
<td>Doctorow, C.</td>
<td></td>
<td></td>
</tr>
<tr>
<td>The Eiger Sanction</td>
<td>Trevanian</td>
<td><span class="timestamp">&lt;2025-05-05 Mon&gt;</span></td>
<td></td>
</tr>
<tr>
<td>The Murder on the Links</td>
<td>Christie, A.</td>
<td><span class="timestamp">&lt;2025-04-27 Sun&gt;</span></td>
<td><span class="timestamp">&lt;2025-05-04 Sun&gt;</span></td>
</tr>
<tr>
<td>Kubernetes in Action</td>
<td>Lukša, M.</td>
<td><span class="timestamp">&lt;2025-04-03 Thu&gt;</span></td>
<td><span class="timestamp">&lt;2025-04-26 Sat&gt;</span></td>
</tr>
<tr>
<td>The Complete Short Stories of Ernest Hemingway</td>
<td>Hemingway, E.</td>
<td><span class="timestamp">&lt;2024-01-24 Wed&gt;</span></td>
<td><span class="timestamp">&lt;2025-04-27 Sun&gt;</span></td>
</tr>
<tr>
<td>Belles On Their Toes</td>
<td>Gilbreth, F. B. Jr</td>
<td><span class="timestamp">&lt;2025-05-14 Wed&gt;</span></td>
<td><span class="timestamp">&lt;2023-12-16 Sat&gt;</span></td>
</tr>
<tr>
<td>Security Chaos Engineering</td>
<td>Shortridge, K.</td>
<td><span class="timestamp">&lt;2025-05-18 Sun&gt;</span></td>
<td><span class="timestamp">&lt;2025-07-05 Sat&gt;</span></td>
</tr>
<tr>
<td>Tomorrow, and tomorrow, and tomorrow</td>
<td>Zevin, G.</td>
<td><span class="timestamp">&lt;2025-07-05 Sat&gt;</span></td>
<td><span class="timestamp">&lt;2025-07-17 Thu&gt;</span></td>
</tr>
<tr>
<td>1984</td>
<td>Orwell, G.</td>
<td><span class="timestamp">&lt;2025-07-18 Fri&gt;</span></td>
<td><span class="timestamp">&lt;2025-08-02 Sat&gt;</span></td>
</tr>
<tr>
<td>Gödel&#39;s Proof</td>
<td></td>
<td><span class="timestamp">&lt;2025-08-03 Sun&gt;</span></td>
<td><span class="timestamp">&lt;2023-12-26 Tue&gt;</span></td>
</tr>
<tr>
<td>Situational Awareness</td>
<td>Aschenbrenner, L.</td>
<td><span class="timestamp">&lt;2025-08-16 Sat&gt;</span></td>
<td><span class="timestamp">&lt;2025-08-24 Sun&gt;</span></td>
</tr>
<tr>
<td>Crucial Conversations</td>
<td>Grenny, J.; Patterson, K.</td>
<td><span class="timestamp">&lt;2025-08-10 Sun&gt;</span></td>
<td><span class="timestamp">&lt;2025-08-31 Sun&gt;</span></td>
</tr>
<tr>
<td>The Secret of Chimneys</td>
<td>Christie, A.</td>
<td><span class="timestamp">&lt;2025-08-31 Sun&gt;</span></td>
<td><span class="timestamp">&lt;2025-09-09 Tue&gt;</span></td>
</tr>
<tr>
<td>Deep Future</td>
<td>Holman, P.</td>
<td><span class="timestamp">&lt;2025-09-17 Wed&gt;</span></td>
<td><span class="timestamp">&lt;2025-09-27 Sat&gt;</span></td>
</tr>
<tr>
<td>The Enigma Story: The Truth Behind the &#39;Unbreakable&#39; World War II Cipher</td>
<td>Turing, J. D.</td>
<td><span class="timestamp">&lt;2025-09-27 Sat&gt;</span></td>
<td><span class="timestamp">&lt;2025-10-11 Sat&gt;</span></td>
</tr>
<tr>
<td>The Peak</td>
<td>Guthrie, S.</td>
<td><span class="timestamp">&lt;2025-10-11 Sat&gt;</span></td>
<td><span class="timestamp">&lt;2025-10-20 Mon&gt;</span></td>
</tr>
<tr>
<td>The Portable Henry Rollins</td>
<td>Rollins, H.</td>
<td><span class="timestamp">&lt;2025-10-20 Mon&gt;</span></td>
<td><span class="timestamp">&lt;2025-10-27 Mon&gt;</span></td>
</tr>
<tr>
<td>Serviceman J: The Untold Story of an NZSAS Soldier</td>
<td>Pennell, J.</td>
<td><span class="timestamp">&lt;2025-10-27 Mon&gt;</span></td>
<td><span class="timestamp">&lt;2025-11-01 Sat&gt;</span></td>
</tr>
<tr>
<td>Advanced React</td>
<td>Makarevich, N.</td>
<td><span class="timestamp">&lt;2025-11-02 Sun&gt;</span></td>
<td><span class="timestamp">&lt;2025-12-01 Mon&gt;</span></td>
</tr>
<tr>
<td>King of the Wilderness: the life of Deny King</td>
<td>Mattingley, C.</td>
<td><span class="timestamp">&lt;2025-12-01 Mon&gt;</span></td>
<td><span class="timestamp">&lt;2025-12-13 Sat&gt;</span></td>
</tr>
</tbody>
</table>
<div id="outline-container-headline-2" class="outline-3">
<h3 id="headline-2">
Hail Mary
</h3>
<div id="outline-text-headline-2" class="outline-text-3">
<p>
   I kept seeing glowing references to this, and it is every bit as good as people said!  I won&#39;t divulge too much because the spoilers start fairly early on, but I&#39;ve heard it described as &#34;collaboration porn&#34; in one throw-away line.  The author is also behind The Martian, which I haven&#39;t read (yet) but did enjoy the movie and it is fairly similar, down to the science-heavy space theme.</p>
</div>
</div>
<div id="outline-container-headline-3" class="outline-3">
<h3 id="headline-3">
Easy Go
</h3>
<div id="outline-text-headline-3" class="outline-text-3">
<p>
   It was cheap and I felt like something vaguely trashy and easy-reading, which this fit the bill well.  Being able to recognise all the Egyptian references (from recent travel) was a nice bonus.  Written under a pseudonym (John Lange) while he was still in medical school.</p>
</div>
</div>
<div id="outline-container-headline-4" class="outline-3">
<h3 id="headline-4">
Become an Effective Software Engineering Manager
</h3>
<div id="outline-text-headline-4" class="outline-text-3">
<p>
   <a href="https://pragprog.com/titles/jsengman/become-an-effective-software-engineering-manager/">https://pragprog.com/titles/jsengman/become-an-effective-software-engineering-manager/</a> I actually enjoyed this.   It&#39;s fairly comprehensive (and some chapters I paid a lot more attention to than others), but focused and pragmatic (&#34;start with these lists&#34;, although less dogmatically prescriptive than that sounds).</p>
</div>
</div>
<div id="outline-container-headline-5" class="outline-3">
<h3 id="headline-5">
Picks and Shovels
</h3>
<div id="outline-text-headline-5" class="outline-text-3">
<p>
   This is the third &#34;Martin Hench&#34; book, a tech-adjacent forensic accountant.  This is a prequel/origin story, and I quite enjoyed it.</p>
</div>
</div>
<div id="outline-container-headline-6" class="outline-3">
<h3 id="headline-6">
The Endurance Handbook
</h3>
<div id="outline-text-headline-6" class="outline-text-3">
<p>
   It was $2 so I might as well give it a go!  Maffetone comes up periodically in endurance discussion, roughly summarised as &#34;go slower to go fast&#34;, the &#34;180 - age&#34; heart rate target, and a more holistic approach to training that is focused on health and longevity as well as short-term performance.  My personal experience so far is that I like <em>racing</em> at that kind of heart rate, but to actually feel faster I need to train a bit higher, and definitely need the quality work.  Hopefully reading this I&#39;ll pick up more of the nuance though.  Nearly halfway through and I&#39;m not super impressed: there&#39;s a lot of blanket statements presented as fact, plenty of meandering, blocks of text &#34;reused&#34; close together as if the book was thrown together quickly from a batch of notes.  There isn&#39;t much how-to so much as a lot of opinion, even if much of it might have merit.  Even if not a how-to I&#39;d still like to see how to progress under such a slow-down in training, as it would represent for me; all the book really offers is assurances that you will, or if you don&#39;t then you&#39;re not healthy enough.  I skimmed a lot towards the end.  He&#39;s also into &#34;Paleo diet&#34;.</p>
</div>
</div>
<div id="outline-container-headline-7" class="outline-3">
<h3 id="headline-7">
A Farewell to Arms
</h3>
<div id="outline-text-headline-7" class="outline-text-3">
<p>
   Hemingway, now in public domain: <a href="https://standardebooks.org/ebooks/ernest-hemingway/a-farewell-to-arms.">https://standardebooks.org/ebooks/ernest-hemingway/a-farewell-to-arms.</a> I&#39;m not quite sure how I feel about it just after finishing; it may take some time. The setting is based on his own experience as an ambulance driver in Italy during the first world war (and being wounded and falling for a nurse). The book traces the downturn in morale as the war gets closer and more desperate, followed by a mass retreat and his desertion while officers are being shot for a lack of patriotism, then fleeing to Switzerland with his now pregnant girlfriend. It&#39;s not explicitly anti war, but the sentiment does seep through! Built on his sparse direct prose, and I&#39;m still processing the (bleak) ending.</p>
</div>
</div>
<div id="outline-container-headline-8" class="outline-3">
<h3 id="headline-8">
Canadian Miracle
</h3>
<div id="outline-text-headline-8" class="outline-text-3">
<p>
   Very short story in a near-future where the US is destroyed by climate change and MAGA politics, while a Canadian long-shot government is addressing problems and trying to help its southern neighbours, where the same MAGA elements accuse them of election interference. </p>
</div>
</div>
<div id="outline-container-headline-9" class="outline-3">
<h3 id="headline-9">
The Eiger Sanction
</h3>
<div id="outline-text-headline-9" class="outline-text-3">
<p>
  Years and years ago I read &#34;Shibumi&#34;, in part because of its focus on the board game Go which I was also a fan of.  Starting this as a holiday read. Early impressions not great; extremely dated (particularly around women, but also racism as a supporting act) and feels like the sex scenes were written by a 12yo. It did develop a little and the core climbing scene was OK, but ultimately wasn&#39;t much more than a quick and vaguely entertaining read. </p>
</div>
</div>
<div id="outline-container-headline-10" class="outline-3">
<h3 id="headline-10">
The Murder on the Links
</h3>
<div id="outline-text-headline-10" class="outline-text-3">
<p>
   Poirot, just felt like churning through an easy read while travelling.
   <a href="https://standardebooks.org/ebooks/agatha-christie/the-murder-on-the-links">https://standardebooks.org/ebooks/agatha-christie/the-murder-on-the-links</a></p>
</div>
</div>
<div id="outline-container-headline-11" class="outline-3">
<h3 id="headline-11">
Kubernetes in Action
</h3>
<div id="outline-text-headline-11" class="outline-text-3">
<p>
   This is a re-read, but the technologies I&#39;m encountering are coming into a similar orbit and while I may never deal with Kubernetes in the short-term it can&#39;t hurt to have a better understanding of the core building blocks.  My experience to date has been that the rationale and building blocks make sense, but the later infrastructure on top is where things get complicated (and why string-templating yaml ever became the dominant &#34;package&#34; &#34;format&#34; is beyond me). Now that I&#39;ve finished I don&#39;t think I can have read it completely through the first time; perhaps only a few chapters since it wasn&#39;t directly relevant. It&#39;s a few years old now, but I don&#39;t think it is all but dated. Written by a project contributor, it&#39;s much more about the what and why than individual specifics. I&#39;ve been working with Google Cloud recently and noticing the concepts that map over.</p>
</div>
</div>
<div id="outline-container-headline-12" class="outline-3">
<h3 id="headline-12">
The Complete Short Stories of Ernest Hemingway
</h3>
<div id="outline-text-headline-12" class="outline-text-3">
<p>
   (Started this when I realised I wasn&#39;t going to be engaging too
   deeply with <em>The History of the Decline and Fall of the Roman
   Empire</em>). I&#39;ve read at least a bunch of these already, I think via
   &#34;The first 49&#34;, so I&#39;ve revisited some and skipped others, until
   finding those that are new to me.</p>
<p>
   Finally finished off on a holiday. At his best they are beautifully concise and direct, and leave a little &#34;unsaid&#34; and to the imagination. Others though can feel a bit too laboured at being mysterious and repeatedly reminding you that there&#39;s <em>this thing</em> that won&#39;t be mentioned. I got the sense that a lot of these were like practice, working on ideas and perhaps there was a reason they weren&#39;t longer.</p>
</div>
</div>
<div id="outline-container-headline-13" class="outline-3">
<h3 id="headline-13">
Belles On Their Toes
</h3>
<div id="outline-text-headline-13" class="outline-text-3">
<p>
   I didn&#39;t know there was a sequel to Cheaper By The Dozen!  Whereas the first book was the story of their dad, this one is about their mum after he died, continuing the business but initially facing scepticism because she&#39;s a woman, and of course still raising the 11 (a 12th child died young) children.  It wraps it up nicely; a few anecdotes and stories, but ultimately covering the final child leaving home and getting married.  Lightweight reading, but a lovely revisit of childhood memories.</p>
</div>
</div>
<div id="outline-container-headline-14" class="outline-3">
<h3 id="headline-14">
Security Chaos Engineering
</h3>
<div id="outline-text-headline-14" class="outline-text-3">
<p>
   <a href="https://securitychaoseng.com/">https://securitychaoseng.com/</a>  Man that one was a slog, although mainly because of me: reading at night, unable to focus, and unable to get any momentum (and it&#39;s quite long).  I did appreciate the focus on people and circumstances, re-framing the problem away from &#34;who was responsible&#34; or &#34;root cause&#34;.  &#34;Chaos engineering&#34; is popularised out of Netflix, supposedly regularly taking down nodes or even data centres in production, to verify stability; this book is at pains to instead emphasise planning and gaining buy-in.  In this vein I probably got the most value out of the penultimate chapter which has a lot of concrete experiments to run; eg (in the staging environment) test if a new port was opened (accidentally or maliciously) would it be detected by your monitoring software, or how quickly are you able to revert if a bad version is pushed to production, or does your monitoring detect a spike in CPU (eg a crypto miner) or network egress (data exfiltration), etc.</p>
</div>
</div>
<div id="outline-container-headline-15" class="outline-3">
<h3 id="headline-15">
Tomorrow, and tomorrow, and tomorrow
</h3>
<div id="outline-text-headline-15" class="outline-text-3">
<p>
   I did enjoy this, and felt a little uncomfortable while identifying with some of the less-charitable attributes of Sam, one of the two main characters.  At the same time, I&#39;m not quite sure why it has attracted such widespread praise – it&#39;s pleasantly different I guess, and does capture a particular zeitgeist quite well.</p>
</div>
</div>
<div id="outline-container-headline-16" class="outline-3">
<h3 id="headline-16">
1984
</h3>
<div id="outline-text-headline-16" class="outline-text-3">
<p>
   I can&#39;t believe I haven&#39;t read this until now.  I found a paper copy; it seemed just too uncomfortable <a href="https://www.npr.org/2009/07/24/106989048/amazons-1984-deletion-from-kindle-examined">using a Kindle for this one</a>!  It is… bleak, as you can no doubt imagine.  These days there are ever-more comparisons between recent modern-day events and the book, and they&#39;re certainly not off-base.</p>
</div>
</div>
<div id="outline-container-headline-17" class="outline-3">
<h3 id="headline-17">
Gödel&#39;s Proof
</h3>
<div id="outline-text-headline-17" class="outline-text-3">
<p>
   $2 kindle deal.  It&#39;s even shorter than advertised, at just over 100 pages, and the writing is slightly old fashioned, but it&#39;s still a very approachable overview of the topic.</p>
</div>
</div>
<div id="outline-container-headline-18" class="outline-3">
<h3 id="headline-18">
Situational Awareness
</h3>
<div id="outline-text-headline-18" class="outline-text-3">
<p>
   <a href="https://situational-awareness.ai/">https://situational-awareness.ai/</a>  It&#39;s an elongated blog post, but it&#39;s still a 1-200 page book!  I saw a reference to it, and in an effort to understand (even learn) from the hype-side of the AI punditry I&#39;m engaging.  Essentially it&#39;s an effort to fit a straight line to the rate of progress (in &#34;OOMs&#34;) and coming out convinced that AGI and Super Intelligence is inevitable, happening incredibly soon, and as a national (US) security imperative everyone should be building out the energy requirements (don&#39;t leave that to the Middle East, and definitely don&#39;t let China take over), protect algorithms in the same way the Manhattan project protected physics advances, etc etc.  There are a few counter-positions explored, in a lot less detail (&#34;maybe we&#39;ll run out of useful data required soon&#34;), but mostly brushed away.  To his credit, the author (former OpenAI researcher) now runs a hedge fund that&#39;s long on AI related bets (and short a few areas likely to be adversely impacted), and so far apparently doing well.</p>
</div>
</div>
<div id="outline-container-headline-19" class="outline-3">
<h3 id="headline-19">
Crucial Conversations
</h3>
<div id="outline-text-headline-19" class="outline-text-3">
<p>I was encouraged to read this by someone who clearly felt I could benefit (I&#39;m not particularly arguing), and while it was a bit slow to get into, the latter parts are all very practical and digestible.</p>
</div>
</div>
<div id="outline-container-headline-20" class="outline-3">
<h3 id="headline-20">
The Secret of Chimneys
</h3>
<div id="outline-text-headline-20" class="outline-text-3">
<p>
   <a href="https://standardebooks.org/ebooks/agatha-christie/the-secret-of-chimneys">https://standardebooks.org/ebooks/agatha-christie/the-secret-of-chimneys</a>
   I queued this with the note &#34;Not a detective book, but next time I feel like Agatha Christie&#34;.
   Finished my last book while mum is in palliative care, in pain and confused, and I do not have the emotional stability myself to concentrate on anything demanding, so Christie it is.  It wound up being perfect for that; light reading, still interesting enough to keep attention for a while without dragging (and, it has to be said, the traditional amount of English racism of the period).  The ending was a trifle fantastical perhaps, but not out of place for some of the plot developments.</p>
</div>
</div>
<div id="outline-container-headline-21" class="outline-3">
<h3 id="headline-21">
Deep Future
</h3>
<div id="outline-text-headline-21" class="outline-text-3">
<p>$5 on kindle, from a Tim Ferris podcast.  I&#39;ll give it a go.  I had mixed impressions all the way through this; he talks about his involvement with Nathan Myhrvhold&#39;s &#34;Intellectual Ventures&#34;, which both did some cool stuff but also had a reputation as a massive patent troll.  Also, despite the accomplishments he talks about (the inventions he&#39;s been a part of), his name wasn&#39;t familiar to me so I was wondering if he had only just surfaced publicly or was perhaps claiming credit for group accomplishments.  I think I was just unaware (and he certainly doesn&#39;t claim he was solely responsible for any of the things talked about), but it did colour my reading a bit.  Anyway, he&#39;s now a VC investing in &#34;deep tech&#34; (basically, stuff harder than yet more software: hardware, biology, etc), and this book was intended to inspire people to think more about the harder, more life-changing problems.  It did do a bit of that for me, but it&#39;s also just a quick read.  To be honest the <a href="https://tim.blog/2025/09/16/pablos-holman/">podcast</a> I listened to with him was just as interesting for the stated goal.</p>
</div>
</div>
<div id="outline-container-headline-22" class="outline-3">
<h3 id="headline-22">
The Enigma Story: The Truth Behind the &#39;Unbreakable&#39; World War II Cipher
</h3>
<div id="outline-text-headline-22" class="outline-text-3">
<p>Another kindle deal.  It starts with possibly the most detailed description of an Enigma&#39;s operation I&#39;ve seen, with very little warmup!  I didn&#39;t actually notice the author&#39;s name when I started reading, but it turns out to be Alan Turing&#39;s nephew (who has, I notice, made a career out of writing books on both Alan and Bletchley Park).  He seems at times to be at pains <em>not</em> to indulge in Turing hagiography, and also to point out that the Enigma cracking wasn&#39;t the only code-breaking work done at Bletchley.  Possibly the flow could be tightened up at times, but it&#39;s a nice technically-focused contribution to the whole of the Bletchley Park contribution (I did get to make a pilgrimage to Bletchley on a recent trip to the UK, albeit we were late in the day and only had an hour to browse)</p>
</div>
</div>
<div id="outline-container-headline-23" class="outline-3">
<h3 id="headline-23">
The Peak
</h3>
<div id="outline-text-headline-23" class="outline-text-3">
<p>This was well-hyped, and I took the bait for some easy-reading thriller (and I like Hong Kong).  It&#39;s an interesting one; probably not what I was expecting, and without too many spoilers it&#39;s not the action-thriller you might be expecting.  Most of the development is told in hindsight (if, learned in the present), with most of the story happening in one day.  It doesn&#39;t end neatly, but that&#39;s a strength of it I feel, avoiding a too-tidy ending.</p>
</div>
</div>
<div id="outline-container-headline-24" class="outline-3">
<h3 id="headline-24">
The Portable Henry Rollins
</h3>
<div id="outline-text-headline-24" class="outline-text-3">
<p>Rollins&#39; writing can come across as trying a little hard to be hard-core (even of the angst-ridden teenage loner style, which to be fair he essentially was at the time), but it&#39;s no less compelling for it at times.  This is a collection of excerpts from his various books, include Get in the Van (a tour diary) and other diaries, and a bunch of fictional writing.  It also includes the &#34;<a href="https://www.artofmanliness.com/character/manly-lessons/henry-rollins-iron-and-soul/">Iron and the Soul</a>&#34; essay, published in a now-defunct magazine in 1994 and then replicated on various proto-blogs and printed out on gyms all over the world, including by me in I think 1999.</p>
</div>
</div>
<div id="outline-container-headline-25" class="outline-3">
<h3 id="headline-25">
Serviceman J: The Untold Story of an NZSAS Soldier
</h3>
<div id="outline-text-headline-25" class="outline-text-3">
<p>Another $2 kindle deal.  I&#39;m always curious about such a different world (including training, realities of operations, and contrasting with the Rogue Heroes tv series), and it didn&#39;t disappoint in that regard.  It&#39;s an easy read, and presumably very heavily vetted before publication, but still interesting.</p>
</div>
</div>
<div id="outline-container-headline-26" class="outline-3">
<h3 id="headline-26">
Advanced React
</h3>
<div id="outline-text-headline-26" class="outline-text-3">
<p>Time for another tech book!  <a href="https://www.advanced-react.com/">https://www.advanced-react.com/</a>  This is another recommendation via the <a href="https://bookoverflow.io/">Bookoverflow podcast</a>.  I quite enjoyed this; I&#39;m not a front-end specialist by any stretch, but I definitely use React (…. albeit, often via Clojurescript).  The highest-level mental model of React as &#34;describe the desired state, and let the diffing algorithm figure out the changes&#34; always sat well with me, but later React (and hooks in particular) never gelled for me, and I didn&#39;t get enough practice to learn them in anger.  This book does a really great job of breaking it all down, explaining the &#34;why&#34; (frequently with a lead-up of failed examples), and I&#39;m almost looking forward to my next front-end foray to put it into practice.</p>
</div>
</div>
<div id="outline-container-headline-27" class="outline-3">
<h3 id="headline-27">
King of the Wilderness: the life of Deny King
</h3>
<div id="outline-text-headline-27" class="outline-text-3">
<p>Deny King (pronounced &#34;Denny&#34;, but his name was Denis with a single &#34;n&#34;) was a legendary bushman who lived in the rugged South-West of Tasmania.  He was a little before my time, but apparently known by everyone; he&#39;d greet and feed bushwalkers arriving on the south coast track, and even built the runway that is still used today, and on which I&#39;ll soon be lucky enough to land on.  As well as a supremely resourceful and practical man, and blessed with superb strength and stamina (stories abound of people helping this poor old man, only to realise they couldn&#39;t lift even one of the 50kg tin bags he was handling 2 of), he was extremely observant and provided valuable observational data and collected specimens for the CSIRO and various scientists.  A few plants and insects have been named after him.</p>
<p>
   I really enjoyed it: it&#39;s perhaps not amazing writing, but he&#39;s just such a fascinating biographical character that you forgive the borderline hagiography.  Fascinating little side-notes seep through too, such as offhand mentions of sitings of Thylacines or finding a nest.</p>
</div>
</div>
</div>
</div>
<div id="outline-container-headline-28" class="outline-2">
<h2 id="headline-28">
Wrap-up
</h2>
<div id="outline-text-headline-28" class="outline-text-2">
<p>Part of the impetus for this exercise is to be more intentional about reading, and part of <em>that</em> involves being a little selective about what goes on the queue.  Unfortunately the slow pace of consumption this year means the queue is growing a little; not out of control, but long enough to start feeling infeasible so I may need to be a bit more ruthless.</p>
<p>
  Nonetheless, a few themes are likely to carry over.  I&#39;m currently reading another maths-of-finance one out of curiosity, and have some technical content (both foundational like probability, and exploratory like brushing up on reinforcement learning again), and with a trip to China coming up I&#39;d like to read Dan Wang&#39;s <a href="https://danwang.co/breakneck/">new book</a> beforehand.</p>
<p>
  I definitely also need to devote a little more time to reading!  There&#39;s a tendency to lie down for a little while after walking home, perhaps do a sudoku or scroll mastodon as a brain-break, but I think that as long as I&#39;m not <em>mentally</em> too fried I could use that time more effectively.</p>
</div>
</div>
]]></content>
		</item>
		
		<item>
			<title>Eglot With Mono Repos</title>
			<link>https://blog.markhepburn.com/posts/eglot-with-mono-repos/</link>
			<pubDate>Sat, 22 Nov 2025 16:33:33 +1100</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/eglot-with-mono-repos/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[
<div id="outline-container-headline-1" class="outline-3">
<h3 id="headline-1">
TL;DR
</h3>
<div id="outline-text-headline-1" class="outline-text-3">
<p>
Summary: The Emacs built-in LSP implemention, Eglot, uses the native project functionality to help configure your source project.  This doesn&#39;t work for VC repositories containing multiple &#34;logical&#34; projects, as either the built-in project-navigation functionlity is limited (if you configure each logical project as a separate Emacs project), or the LSP functionlity is broken because the relative source paths aren&#39;t correct.  There is a way around this but it isn&#39;t really documented, hence this post.</p>
</div>
</div>
<div id="outline-container-headline-2" class="outline-3">
<h3 id="headline-2">
The problem
</h3>
<div id="outline-text-headline-2" class="outline-text-3">
<p>
Emacs has two main implementations of <a href="https://microsoft.github.io/language-server-protocol/">LSP</a>; <a href="https://emacs-lsp.github.io/lsp-mode/">lsp-mode</a> and <a href="https://joaotavora.github.io/eglot/">Eglot</a>.  There are plenty of comparisons around, but it always felt like lsp-mode was a bit more glitzy, possibly more feature-complete, and did things like install language servers for you if you wanted.  Eglot on the other hand was focussed on integrating into Emacs itself rather than providing another layer of functionality on top.  Lsp-mode was the first that worked for me, more or less out of the box, while eglot seemed to require more manual setup and seemed like it would be more clunky, so I&#39;ve been using lsp-mode up until now.</p>
<p>
I recently switched to Eglot however<sup class="footnote-reference"><a id="footnote-reference-1" href="#footnote-1">1</a></sup>, and I couldn&#39;t be happier!  It actually seems simpler to get up and running, and does indeed just get out of the way.  I&#39;ll mention a couple of replacements for lsp-mode functionality at the end, but they&#39;re definitely not deal-breakers either way.</p>
<p>
However there was still one impediment that seemed like it <em>would</em> be a deal-breaker, and this post is about the solution.  Say you have a typical &#34;monorepo&#34; project, for example a website with a Django backend in the <code>backend/</code> directory, and a typescript UI in <code>frontend/</code>.  Eglot integrates into Emacs, as mentioned, and here that means it uses the <a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Projects.html"><code>project.el</code></a> library to identify the project root.  If you&#39;re not familiar with project functionlity, it provides complementary analogues to common commands that operate over a &#34;project&#34; (which is usually your git checkout): for example <code>C-x p f</code> opens any file from within that directory, or you can easily search over the project, etc.</p>
<p>
However: that doesn&#39;t work too nicely with Eglot in our multi-project case!  When we have a python language-server running, we want the project root to be <code>backend/</code>, and similarly to be <code>frontend/</code> for all our typescript work.  Not only that, but if those subdirectories <em>aren&#39;t</em> considered the root for their respective lang-servers, you&#39;ll get a lot more errors than you should because the relative paths are messed up.</p>
<p>
Emacs and <code>project.el</code> offers a solution to this, usually via the <code>project-vc-extra-root-markers</code> variable which lets you define additional project &#34;markers&#34;.  For example, if this variable contains the name <code>&#34;.project&#34;</code>, and you create the new file <code>backend/.project</code> then both <code>project.el</code> and Eglot know that this is a project root and your lang-server will be happy again.</p>
<p>
Unfortunately your <code>project.el</code> usage won&#39;t be!  Now if you are in <code>backend/</code> you won&#39;t be able to jump to a <code>frontend/</code> file because project thinks the project ends at <code>backend/</code>.</p>
</div>
</div>
<div id="outline-container-headline-3" class="outline-3">
<h3 id="headline-3">
Solution
</h3>
<div id="outline-text-headline-3" class="outline-text-3">
<p>
The solution is an undocumented dynamic variable <code>eglot-lsp-context</code>, which is set to <code>t</code> <em>only when eglot is using <code>project.el</code> functions</em>.  In other words, we can differentiate when it&#39;s eglot trying to figure out the project-root, and when I&#39;m opening a file.  The other component is plugging into this functionlity in <code>project.el</code> itself, and for that we&#39;ll use the (documented!) <code>project-find-functions</code> list.  This is a list of functions you can specify that will attempt to find the project root — the default of course just looks for a &#34;VC&#34; marker like <code>.git/</code>.</p>
<p>
My setup, then, uses &#34;<code>.eglot</code>&#34; files as markers but obviously use whatever makes sense:</p>
<div class="src src-elisp">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-elisp" data-lang="elisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span> <span class="nv">project-find-subroot-for-eglot</span> <span class="p">(</span><span class="nv">dir</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">when</span> <span class="nv">eglot-lsp-context</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nb">let</span> <span class="p">((</span><span class="nv">root</span> <span class="p">(</span><span class="nv">locate-dominating-file</span> <span class="nv">dir</span> <span class="s">&#34;.eglot&#34;</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nb">when</span> <span class="nv">root</span>
</span></span><span class="line"><span class="cl">        <span class="p">(</span><span class="nf">cons</span> <span class="ss">&#39;transient</span> <span class="nv">root</span><span class="p">)))))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-hook</span> <span class="ss">&#39;project-find-functions</span> <span class="nf">#&#39;</span><span class="nv">project-find-subroot-for-eglot</span><span class="p">)</span></span></span></code></pre></div>
</div>
<p>
(This is <a href="https://lists.gnu.org/r/emacs-devel/2022-11/msg01087.html">the blessed approach</a> I gather, since even the eglot author <a href="https://lists.gnu.org/r/emacs-devel/2022-11/msg01213.html">uses it</a>)</p>
</div>
</div>
<div id="outline-container-headline-4" class="outline-3">
<h3 id="headline-4">
Other tweaks
</h3>
<div id="outline-text-headline-4" class="outline-text-3">
<p>
Here&#39;s a couple of other Eglot-related notes from when I was making the switch.</p>
<ul>
<li>Breadcrumbs: lsp-mode provided a nice-looking contextual breadcrumb header, showing the current method, xpath, etc.  The Eglot author provided <a href="https://github.com/joaotavora/breadcrumb">this package</a> as a replacement.  It uses the imenu indexing system.</li>
<li>Server installation: lsp-mode would offer to install a server if one couldn&#39;t be found.  This did always feel a little <code>&#34;curl | bash&#34;</code> to me, although I still used it. I recently discovered that there&#39;s a separate effort, <a href="https://github.com/deirn/mason.el">mason</a>, to provide a registry of language servers (and more), and there&#39;s an Emacs client for it. I haven&#39;t felt the need for this one yet, but it&#39;s there if you want it.</li>
<li>Multiple servers: this is perhaps the biggest outstanding difference between the packages.  LSP happily supports multiple concurrent servers for a buffer, for instance pyright and ruff for python.  Eglot doesn&#39;t, and it sounds like it won&#39;t.  There is a &#34;<a href="https://github.com/thefrontside/lspx">multiplexer</a>&#34; around that will provide a unified interface to multiple, but discussion threads suggest that it isn&#39;t quite as simple as that (race conditions for messages that don&#39;t provide identifiers, I think is the gist).  I had a brief play with it and quickly abandoned it, but I&#39;ll keep an eye on it.</li>
</ul>
</div>
</div>
<div class="footnotes">
<hr class="footnotes-separatator">
<div class="footnote-definitions">
<div class="footnote-definition">
<sup id="footnote-1"><a href="#footnote-reference-1">1</a></sup>
<div class="footnote-body">
<p>I never got to the bottom of this, but Emacs started consuming memory rapidly, until systemd-oomd would kill it, and this happened over and over again.  I suspect lsp-mode, just because the amount of IO it needs to do seemed to provide opportunity for a memory leak, and while I didn&#39;t prove it or isolate anything further, the problem does seem to have gone away with the Eglot switch.</p>
</div>
</div>
</div>
</div>
]]></content>
		</item>
		
		<item>
			<title>Books in 2024</title>
			<link>https://blog.markhepburn.com/posts/books-in-2024/</link>
			<pubDate>Thu, 02 Jan 2025 08:28:15 +1100</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/books-in-2024/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[
<p>
Last year I <a href="https://blog.markhepburn.com/posts/2023-reading-in-review/">started an effort</a> to track, and partly as a result, be more intentional about books I read.  The act of tracking adds a small amount of motivation to read a book rather than kill time some other way, and the (token) notes on each one made me engage just that little bit more.  Both aspects could be vastly improved, but it&#39;s a start.  I&#39;m still only tracking books and may one day include things like articles of interest and projects and personal milestones, but for now it remains just books (again <a href="https://blog.fogus.me/2024/12/23/the-best-things-and-stuff-of-2024/">fogus</a> is an inspiration here).</p>
<p>
My numbers were a little bit down on last year; 35 compared to 40.  At times progress felt so slow — reading only at night and barely managing a few pages — that I&#39;m surprised that discrepancy wasn&#39;t worse.</p>
<div id="outline-container-headline-1" class="outline-2">
<h2 id="headline-1">
The books
</h2>
<div id="outline-text-headline-1" class="outline-text-2">
<table>
<thead>
<tr>
<th>TITLE</th>
<th>AUTHOR</th>
<th>STARTED</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>Mediations</td>
<td>Aurelius, M.</td>
<td><span class="timestamp">&lt;2024-01-01 Mon&gt;</span></td>
<td><span class="timestamp">&lt;2024-01-11 Thu&gt;</span></td>
</tr>
<tr>
<td>Hands-On Machine Learning with Scikit-Learn, Keras, and TensorFlow</td>
<td>Geron, A.</td>
<td><span class="timestamp">&lt;2023-12-25 Mon&gt;</span></td>
<td><span class="timestamp">&lt;2024-01-12 Fri&gt;</span></td>
</tr>
<tr>
<td>A Fish has no word for Water</td>
<td>Blue, V.</td>
<td><span class="timestamp">&lt;2024-01-16 Tue&gt;</span></td>
<td><span class="timestamp">&lt;2024-01-20 Sat&gt;</span></td>
</tr>
<tr>
<td>Your favourite band cannot save you</td>
<td>Moore, S.</td>
<td><span class="timestamp">&lt;2024-01-13 Sat&gt;</span></td>
<td><span class="timestamp">&lt;2024-01-16 Tue&gt;</span></td>
</tr>
<tr>
<td>Unix: A history and memoir</td>
<td>Kernighan, B. W.</td>
<td><span class="timestamp">&lt;2024-01-16 Tue&gt;</span></td>
<td><span class="timestamp">&lt;2024-01-19 Fri&gt;</span></td>
</tr>
<tr>
<td>Liar&#39;s Poker</td>
<td>Lewis, M.</td>
<td><span class="timestamp">&lt;2024-01-26 Fri&gt;</span></td>
<td><span class="timestamp">&lt;2024-02-10 Sat&gt;</span></td>
</tr>
<tr>
<td>The Bezzle</td>
<td>Doctorow, C.</td>
<td><span class="timestamp">&lt;2024-02-10 Sat&gt;</span></td>
<td><span class="timestamp">&lt;2024-02-15 Thu&gt;</span></td>
</tr>
<tr>
<td>The Murder of Roger Ackroyd</td>
<td>Christie, A.</td>
<td><span class="timestamp">&lt;2024-02-21 Wed&gt;</span></td>
<td><span class="timestamp">&lt;2024-02-28 Wed&gt;</span></td>
</tr>
<tr>
<td>Remember it!</td>
<td>Dellis, N.</td>
<td><span class="timestamp">&lt;2023-12-26 Tue&gt;</span></td>
<td><span class="timestamp">&lt;2024-03-05 Tue&gt;</span></td>
</tr>
<tr>
<td>Party Discipline</td>
<td>Doctorow, C.</td>
<td><span class="timestamp">&lt;2024-03-06 Wed&gt;</span></td>
<td><span class="timestamp">&lt;2024-03-09 Sat&gt;</span></td>
</tr>
<tr>
<td>The Box</td>
<td>Levinson, M.</td>
<td><span class="timestamp">&lt;2024-03-09 Sat&gt;</span></td>
<td><span class="timestamp">&lt;2024-03-21 Thu&gt;</span></td>
</tr>
<tr>
<td>M Train</td>
<td>Smith, P.</td>
<td><span class="timestamp">&lt;2024-03-21 Thu&gt;</span></td>
<td><span class="timestamp">&lt;2024-03-27 Wed&gt;</span></td>
</tr>
<tr>
<td>The Missing Billionaires</td>
<td>Haghani, V.; White, J.</td>
<td><span class="timestamp">&lt;2024-03-27 Wed&gt;</span></td>
<td><span class="timestamp">&lt;2024-04-21 Sun&gt;</span></td>
</tr>
<tr>
<td>The Durrells of Corfu</td>
<td>Haag, M.</td>
<td><span class="timestamp">&lt;2024-04-21 Sun&gt;</span></td>
<td><span class="timestamp">&lt;2024-04-25 Thu&gt;</span></td>
</tr>
<tr>
<td>People Skills for Analytical Thinkers</td>
<td>Eijkelenboom, G.</td>
<td><span class="timestamp">&lt;2024-04-25 Thu&gt;</span></td>
<td><span class="timestamp">&lt;2024-04-26 Fri&gt;</span></td>
</tr>
<tr>
<td>Advanced Portfolio Management</td>
<td>Paleologo, G.A.</td>
<td><span class="timestamp">&lt;2024-04-26 Fri&gt;</span></td>
<td><span class="timestamp">&lt;2024-05-14 Tue&gt;</span></td>
</tr>
<tr>
<td>Death on the Nile</td>
<td>Christie, A.</td>
<td><span class="timestamp">&lt;2024-05-14 Tue&gt;</span></td>
<td><span class="timestamp">&lt;2024-05-23 Thu&gt;</span></td>
</tr>
<tr>
<td>The Atrocity Archive (Laundry Files #1)</td>
<td>Stross, C.</td>
<td><span class="timestamp">&lt;2024-05-23 Thu&gt;</span></td>
<td><span class="timestamp">&lt;2024-06-10 Mon&gt;</span></td>
</tr>
<tr>
<td>Stung</td>
<td>Gershwin, L. A.</td>
<td><span class="timestamp">&lt;2024-04-26 Fri&gt;</span></td>
<td><span class="timestamp">&lt;2024-06-30 Sun&gt;</span></td>
</tr>
<tr>
<td>Divergent Mind: Thriving in a world that wasn&#39;t designed for you</td>
<td>Nerenberg, J.</td>
<td><span class="timestamp">&lt;2024-06-30 Sun&gt;</span></td>
<td><span class="timestamp">&lt;2024-07-07 Sun&gt;</span></td>
</tr>
<tr>
<td>Secure Coding: Principles and practices</td>
<td>Graff, M. G.; van Wyk, K. R.</td>
<td><span class="timestamp">&lt;2023-10-28 Sat&gt;</span></td>
<td><span class="timestamp">&lt;2024-07-07 Sun&gt;</span></td>
</tr>
<tr>
<td>Living Hot: Surviving and Thriving on a Heating Planet</td>
<td>Hamilton, C.</td>
<td><span class="timestamp">&lt;2024-07-07 Sun&gt;</span></td>
<td><span class="timestamp">&lt;2024-07-12 Fri&gt;</span></td>
</tr>
<tr>
<td>Rinsed: from cartels to crypto</td>
<td>White, G.</td>
<td><span class="timestamp">&lt;2024-07-12 Fri&gt;</span></td>
<td><span class="timestamp">&lt;2024-07-24 Wed&gt;</span></td>
</tr>
<tr>
<td>Fight Me</td>
<td>Grossman, A.</td>
<td><span class="timestamp">&lt;2024-04-26 Fri&gt;</span></td>
<td><span class="timestamp">&lt;2024-08-02 Fri&gt;</span></td>
</tr>
<tr>
<td>A Philosophy of Software Design</td>
<td>Ousterhout, J. K.</td>
<td><span class="timestamp">&lt;2024-08-02 Fri&gt;</span></td>
<td><span class="timestamp">&lt;2024-08-10 Sat&gt;</span></td>
</tr>
<tr>
<td>Thinking in Systems</td>
<td>Meadows, D.H.</td>
<td><span class="timestamp">&lt;2024-08-10 Sat&gt;</span></td>
<td><span class="timestamp">&lt;2024-08-27 Tue&gt;</span></td>
</tr>
<tr>
<td>Emotional Intelligence</td>
<td>Goleman, D.</td>
<td><span class="timestamp">&lt;2024-08-27 Tue&gt;</span></td>
<td><span class="timestamp">&lt;2024-09-18 Wed&gt;</span></td>
</tr>
<tr>
<td>Building a Large Language Model From Scratch</td>
<td>Raschka, S.</td>
<td><span class="timestamp">&lt;2024-09-18 Wed&gt;</span></td>
<td></td>
</tr>
<tr>
<td>The Mystery of the Blue Train</td>
<td>Christie, A.</td>
<td><span class="timestamp">&lt;2024-10-17 Thu&gt;</span></td>
<td><span class="timestamp">&lt;2024-10-20 Sun&gt;</span></td>
</tr>
<tr>
<td>The Cuckoo&#39;s Egg</td>
<td>Stoll, C.</td>
<td><span class="timestamp">&lt;2024-11-17 Sun&gt;</span></td>
<td><span class="timestamp">&lt;2024-12-01 Sun&gt;</span></td>
</tr>
<tr>
<td>Fundamentals of Software Architecture</td>
<td>Richards, M.; Ford, N.</td>
<td><span class="timestamp">&lt;2024-10-20 Sun&gt;</span></td>
<td><span class="timestamp">&lt;2024-12-06 Fri&gt;</span></td>
</tr>
<tr>
<td>The Money Game</td>
<td>Smith, A.</td>
<td><span class="timestamp">&lt;2024-12-07 Sat&gt;</span></td>
<td><span class="timestamp">&lt;2024-12-21 Sat&gt;</span></td>
</tr>
<tr>
<td>Radicalized</td>
<td>Doctorow, C.</td>
<td><span class="timestamp">&lt;2024-12-21 Sat&gt;</span></td>
<td><span class="timestamp">&lt;2024-12-26 Thu&gt;</span></td>
</tr>
<tr>
<td>Greenlights</td>
<td>McConaughey, M.</td>
<td><span class="timestamp">&lt;2024-12-27 Fri&gt;</span></td>
<td><span class="timestamp">&lt;2024-12-29 Sun&gt;</span></td>
</tr>
<tr>
<td>The AWK Programming Language</td>
<td>Aho, A.V.; Kernighan, B.W.; Weinberger, P.J.</td>
<td><span class="timestamp">&lt;2024-12-19 Thu&gt;</span></td>
<td><span class="timestamp">&lt;2024-12-31 Tue&gt;</span></td>
</tr>
</tbody>
</table>
<p>#+END</p>
<div id="outline-container-headline-2" class="outline-3">
<h3 id="headline-2">
Mediations
</h3>
<div id="outline-text-headline-2" class="outline-text-3">
<p>
   Picked up for $5 in a second hand bookshop; it&#39;s a &#34;miniature&#34; so
   probably not the complete meditations, but nice to read a few
   occasionally and ponder.</p>
</div>
</div>
<div id="outline-container-headline-3" class="outline-3">
<h3 id="headline-3">
Hands-On Machine Learning with Scikit-Learn, Keras, and TensorFlow
</h3>
<div id="outline-text-headline-3" class="outline-text-3">
<p>
   Had this on my bookshelf for a couple of years at least, and
   intended to only skim it but wound up reading basically all of it
   (the start date is a bit of a guess). It&#39;s quite good, both in
   practicality and explaining the how and why.  I appreciated the little details around the &#34;why&#34; of different architectures and the tricks in how deep learning became practical.</p>
</div>
</div>
<div id="outline-container-headline-4" class="outline-3">
<h3 id="headline-4">
A Fish has no word for Water
</h3>
<div id="outline-text-headline-4" class="outline-text-3">
<p>
   <a href="https://www.digitapub.com/collections/frontpage/products/a-fish-has-no-word-for-water-a-punk-homeless-san-francisco-memoir">https://www.digitapub.com/collections/frontpage/products/a-fish-has-no-word-for-water-a-punk-homeless-san-francisco-memoir</a>
   Via <a href="https://www.jwz.org/blog/2023/12/recent-books-3/">https://www.jwz.org/blog/2023/12/recent-books-3/</a> I read this
   essentially on a plane, and it is a fairly confronting look at how
   easily someone can become homeless, and once there how hard it is
   to escape.</p>
</div>
</div>
<div id="outline-container-headline-5" class="outline-3">
<h3 id="headline-5">
Your favourite band cannot save you
</h3>
<div id="outline-text-headline-5" class="outline-text-3">
<p>Via <a href="https://www.jwz.org/blog/2023/12/recent-books-3/">https://www.jwz.org/blog/2023/12/recent-books-3/</a> A fun short
   read, although the ending possibly isn&#39;t as memorable as the
   beginning. The underground cliquey music blogging community
   discovers an addictive music track, which turns out to be the first
   track of an album being released day by day, with each track having
   greater and greater effects on its audience.</p>
</div>
</div>
<div id="outline-container-headline-6" class="outline-3">
<h3 id="headline-6">
Unix: A history and memoir
</h3>
<div id="outline-text-headline-6" class="outline-text-3">
<p>I absolutely loved this, although as I&#39;m writing this a fortnight
   after finishing it I&#39;m struggling to recall specifics that I
   particularly enjoyed at the time. The details into the gradual
   implementation of Unix – while I was familiar with the basic story
   – was fantastic, as were the vignets about characters both
   familiar and otherwise to me.</p>
</div>
</div>
<div id="outline-container-headline-7" class="outline-3">
<h3 id="headline-7">
Liar&#39;s Poker
</h3>
<div id="outline-text-headline-7" class="outline-text-3">
<p>I started this on holidays, when I realised I didn&#39;t have the
   concentration for something heavier. I was probably expecting a
   history-style portrayal, but it&#39;s actually the author&#39;s
   autobiographical account of being hired and working as a bond
   salesman in the 80s, witnessing the heyday and collapse of Salomon
   Brothers. The personalities involved are interesting and probably
   exactly what you&#39;d expect.</p>
</div>
</div>
<div id="outline-container-headline-8" class="outline-3">
<h3 id="headline-8">
The Bezzle
</h3>
<div id="outline-text-headline-8" class="outline-text-3">
<p><a href="https://www.amazon.com.au/Bezzle-Red-Team-Cory-Doctorow-ebook/dp/B0CCXYG4LN/357-4247603-7631804?psc=1">https://www.amazon.com.au/Bezzle-Red-Team-Cory-Doctorow-ebook/dp/B0CCXYG4LN/357-4247603-7631804?psc=1</a>
   (pre/sequel to Red Team Blues) Not a long read – focuses on the
   prison industrial complex in the US, where the privatisation of
   prisons leads to an unbelievably cruel treatment of inmates,
   abetted by equally cruel legislation such as &#34;3 strikes&#34; and
   political incentives to imprison <em>more</em> people, all in the name of
   extracting more and more value for shareholders. The story has fun
   characters (Marty Hench, the forensic accountant with a lot of free
   time thanks to his usual policy of taking 25% of regained funds as
   compensation), but is mostly a vehicle to push awareness of the
   almost-insane state of affairs</p>
</div>
</div>
<div id="outline-container-headline-9" class="outline-3">
<h3 id="headline-9">
The Murder of Roger Ackroyd
</h3>
<div id="outline-text-headline-9" class="outline-text-3">
<p><a href="https://standardebooks.org/ebooks/agatha-christie/the-murder-of-roger-ackroyd">https://standardebooks.org/ebooks/agatha-christie/the-murder-of-roger-ackroyd</a>
   My mum had what I believe was the complete Agatha Christie set –
   all matching black and white jackets, from memory with 3 books to a
   volume, probably from Readers Digest or similar. As a child I read
   the complete Poirot stories (for some reason I identified fairly
   closely with the obsessive and symmetrical detective, but never got
   into the Miss Marple stories). My girlfriend read Death on the Nile
   to accompany our Egypt holiday, re-awakening my own interest, so
   I&#39;m diving back in courtesy of <a href="https://standardebooks.org/ebooks/agatha-christie/the-murder-of-roger-ackroyd">Standard Ebooks</a>. For once, I am not
   worried that I&#39;ll remember too much! (I think I would have been
   about 10 the first time).</p>
<p>
   I really enjoyed this in the end! It&#39;s not a difficult read, and
   there is a surprising amount of humour in it (particularly
   concerning his nosey sister). The only bit that seemed a bit forced
   was the description of the protagonist&#39;s workshop, which appeared
   out of nowhere but wound up being an important point.</p>
</div>
</div>
<div id="outline-container-headline-10" class="outline-3">
<h3 id="headline-10">
Remember it!
</h3>
<div id="outline-text-headline-10" class="outline-text-3">
<p>
   <a href="https://www.amazon.com.au/dp/B07G446SG2">https://www.amazon.com.au/dp/B07G446SG2</a> It was a kindle deal, but
   it also overlaps with (and was recommended by the presenter) of
   that &#34;Learning how to learn&#34; Coursera course I did recently.</p>
<p>
   The content is probably no <em>great</em> surprise if you&#39;ve seen anything
   of this ilk, creating visualisations that are more memorable than
   the (say) phone number, taking advantage of your superior spatial
   and visual memory systems. Nonetheless, it was pretty engaging and
   easy to follow. I didn&#39;t implement much as I went, but I plan to
   return to it and incrementally chip off small pieces.</p>
</div>
</div>
<div id="outline-container-headline-11" class="outline-3">
<h3 id="headline-11">
Party Discipline
</h3>
<div id="outline-text-headline-11" class="outline-text-3">
<p>I bought the <a href="https://www.humblebundle.com/books/cory-doctorow-novel-collection-tor-books-books">Doctorow Humble Bundle</a>, although I already have or
   have read nearly half of them. This is a short story while I figure
   out what I want to focus on next! I&#39;ve read a few Doctorow books
   now, partly through following him on social media, and his stance
   on DRM-free publishing. It&#39;s essentially a bit of a play-on-words
   of the &#34;party&#34; in &#34;communist party&#34;, in a fascistic dystopian US.</p>
</div>
</div>
<div id="outline-container-headline-12" class="outline-3">
<h3 id="headline-12">
The Box
</h3>
<div id="outline-text-headline-12" class="outline-text-3">
<p>The story of how the shipping container unlocked globalisation.
   Recommended by everyone it seems (eg <a href="https://www.gatesnotes.com/Holiday-Books-2013">Bill Gates</a> again). I love
   stories that take something seemingly mundane (&#34;loading cargo onto
   ships is dangerous and slow, what if we put everything into boxes
   first?&#34;) and does a deep dive into the ramifications and
   personalities: shipping becomes cheaper and faster, which means
   manufacturing internationally becomes feasible, with corresponding
   changes in economies and industries, but also means that factories
   no longer need to be co-situated with ports, etc. There&#39;s also a
   meta-story about standardisation here; chapter 2 talks about the
   &#34;before&#34; history, which actually includes multiple efforts to use
   boxes over manual packing, which for various reasons — mostly
   that everyone had a different-sized box — never took off.</p>
<p>
   I was a little surprised it didn&#39;t spend more time on the impacts,
   with most of it covering the detailed history of the various
   developments and changes, and occasional paragraphs mentioning the
   advent of globalisation. The first point that grabbed me was that
   containers actually benefit <em>short</em> voyages more, because their
   saving is in drastically reducing time in port; costs at sea are
   unaffected. Another interesting aspect was the importance of ports
   (which themselves are occasionally at the whims of shipping lines,
   and can find their massive investment wasted), for example Africa
   has rock-bottom labour costs, but doesn&#39;t attract investment
   because there&#39;s no efficient way of getting the outputs out.</p>
</div>
</div>
<div id="outline-container-headline-13" class="outline-3">
<h3 id="headline-13">
M Train
</h3>
<div id="outline-text-headline-13" class="outline-text-3">
<p>I absolutely loved &#34;Just Kids&#34;.  This is about her later life, and while still autobiographical is much less linear.  It&#39;s a mix of &#34;writer writes about writing&#34;, muses and the occasional dream sequence, visiting dead artists&#39; graves, and a whole lot of coffee.  Some of her dwelling on the details of banal objects reminds me of oddly William Gibson and Pattern Recognition.</p>
</div>
</div>
<div id="outline-container-headline-14" class="outline-3">
<h3 id="headline-14">
The Missing Billionaires
</h3>
<div id="outline-text-headline-14" class="outline-text-3">
<p>Following Liar&#39;s Poker (and being a regular reader of Matt Levine) I feel like going on a bit of a finance kick, to try and at least understand what&#39;s going on a bit better.  This book feels like it might be the next step up from Barefoot Invester, assuming you have capital to invest, and not wanting to overcomplicate things but needing guidance on a general strategy.  In particular, sizing gets extensive coverage, both Kelly criterion and the &#34;Merton share&#34; (which generalises to a Kelly proportion, for a particular risk aversion.  The first author was a founding partner of the specular flameout hedgefund LTCM, and is quite open about lessons learned there (noting that the deals that sunk the fund were ultimately profitable, but that their sizing meant they went bust because they couldn&#39;t ride out the early volatility).</p>
</div>
</div>
<div id="outline-container-headline-15" class="outline-3">
<h3 id="headline-15">
The Durrells of Corfu
</h3>
<div id="outline-text-headline-15" class="outline-text-3">
<p>&#34;My Family and Other Animals&#34; is one of my favourite books of all time; I read it multiple, multiple times as a kid (envious of and fantasising about the rich landscape he described), and I was immensely relieved to discover it just as vivid and colourful when I re-read it as an adult.  This book is an impulse buy, with the &#34;real life story&#34;, including photos, context such as where they came from and why the move to a Greek island, what happened to them after etc.  There&#39;s a danger that this could rob the original of colour, but if anything the real-life details only add to it.  The story does sour a little when you realise that their carefree living (with Larry and wife Nancy spending a lot of time bathing nude) clashed with the conservative residents and effectively drove them out — along with the approaching war of course.</p>
</div>
</div>
<div id="outline-container-headline-16" class="outline-3">
<h3 id="headline-16">
People Skills for Analytical Thinkers
</h3>
<div id="outline-text-headline-16" class="outline-text-3">
<p>Another $2 kindle deal, and topical for me. Short enough and cheap enough to be worth a shot.  It&#39;s a super quick read, with a surprising amount of overlap with &#34;Mindfulness Integrated CBT&#34; – essentially, learn to recognise your behaviours and what you react to.  From that perspective it was probably worth the short amount of time for me, as a handy reminder.  He refers to things as &#34;algorithms&#34; (essentially, &#34;when someone does X / I do Y (/because Z)&#34;), which is a bit twee but you get used to it.</p>
</div>
</div>
<div id="outline-container-headline-17" class="outline-3">
<h3 id="headline-17">
Advanced Portfolio Management
</h3>
<div id="outline-text-headline-17" class="outline-text-3">
<p>I bought this as the next level up from Missing Billionaires, which it is and also an alternative perspective I suspect.  At first glance it actually covers the basics very well, and with more mathematical rigour.</p>
<p>
   I did find that I was waning a bit towards the end, and stopped trying to follow the maths as much.  I suspect for me (and I am decidedly not the target audience) might have benefited from a few more worked-examples of a simplified factor model, and also a clearer definition of &#34;risk&#34; and how the various structures would be employed to accommodate it.</p>
</div>
</div>
<div id="outline-container-headline-18" class="outline-3">
<h3 id="headline-18">
Death on the Nile
</h3>
<div id="outline-text-headline-18" class="outline-text-3">
<p>We had a copy of this because we recently had our own trip to Egypt (and spied the hotel that appears in this book).  I&#39;m picking it up after rediscovering Agatha Christie via The Murder of Roger Ackroyd recently.  Idle observation of note: there&#39;s a description of landing the boat outside the Abu Simbel temple, which we recently visited outselves.  However: Abu Simbel is no longer accessible by boat!  It is both an ancient and modern marvel; the temple is spectacular enough on its own, but when the Nile was dammed it was going to be flooded and destroyed, so it was cut up and reassembled above the new water level (and in a constructed mountain).</p>
</div>
</div>
<div id="outline-container-headline-19" class="outline-3">
<h3 id="headline-19">
The Atrocity Archive (Laundry Files #1)
</h3>
<div id="outline-text-headline-19" class="outline-text-3">
<p>Promises a brand of occult / horror, where the magic actually relies on branches of (illegal) mathematics, and computer technicians are the wizards.  I don&#39;t generally go in for horror or occult stuff (China Mieville was a bit of an excursion there),  but I did enjoy the premise and the setup.   I probably got a bit bogged down in the latter half, and while I enjoyed it I wouldn&#39;t put it in my favourites so far (slightly unfortunately, as there&#39;s something like 11 or 12 more in the series now,  if I&#39;d felt inclined!)</p>
</div>
</div>
<div id="outline-container-headline-20" class="outline-3">
<h3 id="headline-20">
Stung
</h3>
<div id="outline-text-headline-20" class="outline-text-3">
<p>Another Kindle deal – I was aware of this book as I used to work in the same research organisation as its author.  I was a bit irritated by an early sensationalist tone, but it settles into a groove and manages to be thorough and educational, but with a familiar voice.  Essentially describes how jellyfish are &#34;weedy&#34;; thrive on disturbance, capable of existing and thriving in a range of environmental variations, and hardy, then systematically covers how through climate change and over-fishing and general neglect of the oceans that jellyfish uniquely poised to take over.</p>
</div>
</div>
<div id="outline-container-headline-21" class="outline-3">
<h3 id="headline-21">
Divergent Mind: Thriving in a world that wasn&#39;t designed for you
</h3>
<div id="outline-text-headline-21" class="outline-text-3">
<p><a href="https://www.amazon.com.au/Divergent-Mind-Thriving-World-Designed-ebook/dp/B07TF92Y3Z">https://www.amazon.com.au/Divergent-Mind-Thriving-World-Designed-ebook/dp/B07TF92Y3Z</a>
   After my deep-dive into understanding autism by reading everything to hand, I mostly moved on.  I passed on this book during that initial dive, partly because I was mostly done when I encountered it, and it focuses on autism as it pertains to women specifically.  I&#39;ve since become more curious about how it does present differently in women (and why boys and men are diagnosed way more), but I probably didn&#39;t focus too much whil ereading it.  It concentrates on sensitivity, but I didn&#39;t notice much about the male/female differences.</p>
</div>
</div>
<div id="outline-container-headline-22" class="outline-3">
<h3 id="headline-22">
Secure Coding: Principles and practices
</h3>
<div id="outline-text-headline-22" class="outline-text-3">
<p>
   Another one from the bookshelf; I&#39;ve read this, back in the day,
   when I started getting intrigued by the exploitability nature of
   security (and cryptography, etc), and the high-level approach of
   &#34;do you have an incident response plan?&#34; etc went a bit over my
   head. Now that I run a software consultancy, those practical
   measures are of much greater interest!</p>
</div>
</div>
<div id="outline-container-headline-23" class="outline-3">
<h3 id="headline-23">
Living Hot: Surviving and Thriving on a Heating Planet
</h3>
<div id="outline-text-headline-23" class="outline-text-3">
<p><a href="https://www.amazon.com.au/Living-Hot-Surviving-Thriving-Heating/dp/176145059X/">https://www.amazon.com.au/Living-Hot-Surviving-Thriving-Heating/dp/176145059X/</a>
   As they point out, most books on climate change, environmental degradation etc, usually include a hopeful &#34;way forward&#34; chapter at the end, perhaps at the urging of the publisher (it is often short, and frequently doesn&#39;t seem believable!).  This book is not like that: it is short, and arguing that while we should still reduce emissions (for moral and financial reaons), the battle has long been lost and it won&#39;t affect the climate.  Instead we need to accept the change that is coming and prepare for it: relocate communities prone to flooding and fires, etc.  For all that there isn&#39;t a lot of suggestions either, mostly seeming to be arguing for a change in mindeset.</p>
</div>
</div>
<div id="outline-container-headline-24" class="outline-3">
<h3 id="headline-24">
Rinsed: from cartels to crypto
</h3>
<div id="outline-text-headline-24" class="outline-text-3">
<p><a href="https://www.amazon.com.au/Rinsed-Cartels-Crypto-Industry-Deadliest-ebook/dp/B0CPBLXQH6">https://www.amazon.com.au/Rinsed-Cartels-Crypto-Industry-Deadliest-ebook/dp/B0CPBLXQH6</a></p>
<blockquote>
<p>&#34;High volume, flexible asset prices, lack of regulation and global scale: from Airbnb to OnlyFans to Uber to Bitcoin and more, tech has boomed by setting up shop in spaces where those four aspects are present. … technologists have a conspicuous habit of creating innovations that inadvertently have precisely the kind of attributes money launderers crave.&#34;</p>
</blockquote>
<p>The interest in this came from a podcast (the always-excellent Darknet Diaries), and while the book is an interesting look at the basics of how money is laundered, and how that moved online and through cryptocurrencies, it&#39;s more dramatisation through illustrative stories than deep-dive.</p>
</div>
</div>
<div id="outline-container-headline-25" class="outline-3">
<h3 id="headline-25">
Fight Me
</h3>
<div id="outline-text-headline-25" class="outline-text-3">
<p>I read this on <a href="https://pluralistic.net/2024/07/01/the-big-genx-chill/#im-super-thanks-for-asking">Cory Doctorow&#39;s recommendation</a>, and it was completely <em>fine</em>.  I am squarely in the same target audience (perhaps on the younger side if I&#39;m being generous to myself), and it was light and entertaining but perhaps didn&#39;t quite hit the same feels about identifying the same regrets-at-50.  I felt the ending just kind of petered out as well, and left the big question (the protagonists origin story) unanswered as well.</p>
</div>
</div>
<div id="outline-container-headline-26" class="outline-3">
<h3 id="headline-26">
A Philosophy of Software Design
</h3>
<div id="outline-text-headline-26" class="outline-text-3">
<p>I started this one after listening to both the book overview, and the interview with the author, on the <a href="https://bookoverflow.io/">Book-Overflow podcast</a> (which I recommend, incidentally).  It is exactly as advertised; deceptively simple (and just the right amount of opinionated) advice to make your code &#34;obvious&#34; (including defining what is obvious).</p>
</div>
</div>
<div id="outline-container-headline-27" class="outline-3">
<h3 id="headline-27">
Thinking in Systems
</h3>
<div id="outline-text-headline-27" class="outline-text-3">
<p>Loved this.  A while back I realised that this nebulous concept of &#34;systems thinking&#34; was a big weakness of mine (I do have a strength in going deep on a topic — which is a generous way of saying like most programmers I get stuck down rabbit holes).  This is a beautiful introduction to the field, and how complexity and unintended consequences can easily arise even with the best of intentions.</p>
</div>
</div>
<div id="outline-container-headline-28" class="outline-3">
<h3 id="headline-28">
Emotional Intelligence
</h3>
<div id="outline-text-headline-28" class="outline-text-3">
<p>I had to slog through this; we&#39;re doing a course at work on Emotional Intelligence so it was a topical read, but I found it slightly dated (it spends a bit of time on the debunked marshmallow study, for example) and perhaps it was a bit more revelatory when it was first published.</p>
</div>
</div>
<div id="outline-container-headline-29" class="outline-3">
<h3 id="headline-29">
Building a Large Language Model From Scratch
</h3>
<div id="outline-text-headline-29" class="outline-text-3">
<p>Another Manning pre-release; I find the &#34;MEAP&#34; model means I impulse-purchase something and then let the actual completion date push it onto my queue at some future date.  I have serious reservations about many aspects of generative AI and the utility of LLMs, but still find the actual technology fascinating (and their effectiveness at what they do do) so it&#39;s about time to go a bit deeper.  It wound up being a nice step by step explanation of the model itself, and various aspects of the code around training and fine-tuning.  I read the Karpathy article <a href="https://karpathy.github.io/2015/05/21/rnn-effectiveness/">The unreasonable effectiveness of recurrent neural networks</a> around the same time, which was a nice complement.</p>
</div>
</div>
<div id="outline-container-headline-30" class="outline-3">
<h3 id="headline-30">
The Mystery of the Blue Train
</h3>
<div id="outline-text-headline-30" class="outline-text-3">
<p>Mainly wanted some light fiction between technical content!  Apparently it&#39;s not one of her favourites (supposedly because it coincided with her husband&#39;s infidelity), but it&#39;s a fun easy read.</p>
</div>
</div>
<div id="outline-container-headline-31" class="outline-3">
<h3 id="headline-31">
The Cuckoo&#39;s Egg
</h3>
<div id="outline-text-headline-31" class="outline-text-3">
<p>Finally got around to reading this, and it&#39;s every bit as good as recommended.  I immediately resonated with the first chapter where he is tasked with tracking down a 75 cent (out of 2 thousand dollar) accounting discrepancy, and can&#39;t rest because he doesn&#39;t understand it (regardless of the relative impact).  The epilogue where the &#34;Morris worm&#34; appears was a fun coda, and one I was wondering about when Robert Morris made a few appearances.</p>
</div>
</div>
<div id="outline-container-headline-32" class="outline-3">
<h3 id="headline-32">
Fundamentals of Software Architecture
</h3>
<div id="outline-text-headline-32" class="outline-text-3">
<p>I&#39;ve had this queued up for a little while since hearing about it via the <a href="https://bookoverflow.io/">Book Overflow</a> podcast, but was going to wait when I realised they were working on a 2nd edition arriving next year.  Then it popped up in a Humble Bundle on architecture books (which included all three in this series) so I picked it (them) up and now I&#39;m getting around to it.  I started slogging in the middle and switched to The Cuckoo&#39;s Egg for a break, but it&#39;s a useful read.  Some of the discussion of possible architectures themselves was useful for the example &#34;scorecards&#34; classifying tradeoffs, but it was most useful for me in clarifying bounds of responsibilities, and some of the later chapters on people-factors (&#34;every decision will be challenged&#34;)</p>
</div>
</div>
<div id="outline-container-headline-33" class="outline-3">
<h3 id="headline-33">
The Money Game
</h3>
<div id="outline-text-headline-33" class="outline-text-3">
<p>Another $2 special.  It was… entertaining from an historical perspective but hardly educational.</p>
</div>
</div>
<div id="outline-container-headline-34" class="outline-3">
<h3 id="headline-34">
Radicalized
</h3>
<div id="outline-text-headline-34" class="outline-text-3">
<p>I picked this up in a Humble Bundle sale and promptly forgot about it, until reading an <a href="https://www.theguardian.com/us-news/2024/dec/20/cory-doctorow-radicalized-novella-healthcare-ceo-killing">article mentioning it</a>.  It&#39;s a collection of 4 short stories, formerly best-known for &#34;Unauthorized Bread&#34;, but funnily enough now perhaps for the title story about an uprising against the US health insurance system.  I read the title story first; it&#39;s a believable account of an online support forum for partners of people dying due to insurance-claim denials becoming a tool for radicalisation and violence against the health insurance system.  The protagonist is a &#34;good guy&#34;, mostly trying to private-message people on the verge of violence and talk them down, but the ending is a bittersweet one that doesn&#39;t end too well for him personally but includes a systemic change that is still hard to believe happening in reality.  Unauthorized Bread by comparison has a nicer ending, albeit with a dystopian setting that is all too believable (poor immigrants in rent-controlled apartments that saddles them with a bunch of subscription appliances that stop functioning when the providers go out of business, but the DMCA means their subsequent jail-breaking is illegal).  Model Minority is a superman alt-history (Bruce Wayne also has a supporting role, including making his billions selling arms and spyware to the government), about the limits of how much one superhero can do against systemic racism and issues.  Lastly, The Masque of the Red Death is a borderline-mocking portrayal of a group of super-wealthy (therefore supposedly super-smart) hedge-fund bros attempting to ride out the collapse of civilisation in a bunker, while (spoiler) outside civilisation starts to rebuild around cooperative efforts.  Not on my list right now, but there&#39;s a whole book about <a href="https://www.abc.net.au/news/2022-10-20/tech-billionaires-are-planning-for-the-apocalypse/101546216">these kind of people</a>.</p>
</div>
</div>
<div id="outline-container-headline-35" class="outline-3">
<h3 id="headline-35">
Greenlights
</h3>
<div id="outline-text-headline-35" class="outline-text-3">
<p>Probably padding my 2024 stats if I&#39;m honest; this was a quick and easy read after my girlfriend passed it on but maybe not one I would have picked up of my own accord.  It&#39;s an interesting life, but I&#39;m not taking anything from it (his aphorisms for how to live which are sprinkled throughout, notwishstanding).</p>
</div>
</div>
<div id="outline-container-headline-36" class="outline-3">
<h3 id="headline-36">
The AWK Programming Language
</h3>
<div id="outline-text-headline-36" class="outline-text-3">
<p>I have a feeling I read this around 2000 when I devoured all the &#34;Bell Labs&#34; books that the library had (the C book,  The Unix Programming Environment, etc).  I own most of those now and love the writing in them, and even though this wasn&#39;t the cheapest it felt like a worthy addition to the library.  (&#34;Unix: A History and Memoir&#34; did remind me, and one of the tidbits in that book was the mention of domain-specific languages as a core idea, which is probably a lesser-known principle next to &#34;everything is a file&#34; and piping for example).  It&#39;s a typically breezy and accessible read,  yet still clear and information-dense.  Kernighan doesn&#39;t waste words!  I&#39;ve always had a soft-spot for awk, yet somehow rarely reach for it these days.  Perhaps a new-year&#39;s resolution is to try and use it a little more often.</p>
</div>
</div>
</div>
</div>
<div id="outline-container-headline-37" class="outline-2">
<h2 id="headline-37">
Others
</h2>
<div id="outline-text-headline-37" class="outline-text-2">
<p>I originally planned to include technical books that I may have skimmed or only read a few chapters on for example, but didn&#39;t really follow through on that.  There&#39;s a few others I&#39;ll include though:</p>
<div id="outline-container-headline-38" class="outline-3">
<h3 id="headline-38">
Systems Performance, Brendan Gregg
</h3>
<div id="outline-text-headline-38" class="outline-text-3">
<p><a href="https://www.brendangregg.com/">Brendan</a> is astonishingly prolific, and has a gift for actually systematising and conveying the extent of his expertise in an educational fashion.  See &#34;first 10 commands to run on a Linux box&#34;, for example.  I originally bought this as an ebook, but later ordered a hard copy as well.  It is vast and detailed, so much of it I was skimming and/or didn&#39;t have the expertise to follow in detail.  As such I still haven&#39;t finished it end to end, and probably won&#39;t but I&#39;m keeping it on my bedside table for now.</p>
</div>
</div>
<div id="outline-container-headline-39" class="outline-3">
<h3 id="headline-39">
The Complete Short Stories of Ernest Hemingway
</h3>
<div id="outline-text-headline-39" class="outline-text-3">
<p>I don&#39;t mind a bit of Hemingway (at times he can also come across as quite braggadocious, but at his peak his direct clarity of expression and gift for what to omit was amazing to discover).  I&#39;ve read a bunch of his short stories so I thought this might be a case of &#34;fill in the blanks&#34;, but it turns out there&#39;s a lot more that I hadn&#39;t seen!  I&#39;ll eventually get through them all, but in bursts.  It&#39;s fun to see him exploring themes or techniques, assuming the collections are roughly in chronological order.  A few might be set around his experiences in the Spanish civil war, while others seemed to be experimenting with &#34;they looked at each other but did not speak.  The thing lingered between them,  but they both knew they would never speak of it.&#34;, and never explaining what &#34;the thing&#34; may have been (an affair?  Threesome?).  Sometimes it works well, sometimes – particularly when you&#39;ve read the third use of such a device in a row — it can get a bit weary.</p>
</div>
</div>
<div id="outline-container-headline-40" class="outline-3">
<h3 id="headline-40">
The History of the Decline and Fall of the Roman Empire
</h3>
<div id="outline-text-headline-40" class="outline-text-3">
<p><a href="https://standardebooks.org/ebooks/edward-gibbon/the-history-of-the-decline-and-fall-of-the-roman-empire">https://standardebooks.org/ebooks/edward-gibbon/the-history-of-the-decline-and-fall-of-the-roman-empire</a></p>
<p>
   I&#39;m calling this one right now, I didn&#39;t get very far and I am not going to finish it!  Memes about &#34;how often do you think about the Roman Empire?&#34; aside, we&#39;d recently been to Italy and coupled with the apparent degradation of the US political system I was curious about the parallels.  This book is free, and while it&#39;s a bit old and apparently critiqued a bit now, still considered a classic and apparently has a nice writing style as well.  It is also <em>enormous</em>, and while I gave it a good shot I didn&#39;t quite get into it and when I realised I still hadn&#39;t moved past 1% on the kindle I effectively gave up.  I started in late February, but I think I am officially giving up now!</p>
</div>
</div>
</div>
</div>
<div id="outline-container-headline-41" class="outline-2">
<h2 id="headline-41">
What&#39;s Next?
</h2>
<div id="outline-text-headline-41" class="outline-text-2">
<p>It is probably silly to speculate, as the reading queue tends to evolve a bit (mostly growing, but things do drop off as I get less-excited by something, or just realise I need to drop something to keep things realistic). However, a sample of what&#39;s currently on the shortlist:</p>
<ul>
<li><a href="https://pragprog.com/titles/jsenglb/become-a-great-engineering-leader/">Become a Great Engineering Leader</a> and/or <a href="https://pragprog.com/titles/jsengman/become-an-effective-software-engineering-manager/">Become an Effective Software Engineering Manager</a>.  As much as I&#39;d rather just be an engineer, this is my life now.</li>
<li><a href="https://hardcoresoftware.learningbyshipping.com/">Hardcore Software</a></li>
<li><a href="https://press.stripe.com/boom">Boom: Bubbles and the end of Stagnation</a> Bryne has an interesting newsletter and podcast (not always my thing, and sometimes feels a bit wanky using terms like &#34;marginal utility&#34; from economics and finance about otherwise everyday conceps), but I do enjoy an alternative perspective.</li>
<li><a href="https://standardebooks.org/ebooks/agatha-christie/the-seven-dials-mystery">The Seven Dials Mystery</a> Another Agatha Christie book into public domain.</li>
<li><a href="https://standardebooks.org/ebooks/ernest-hemingway/a-farewell-to-arms">A Farewell to Arms</a> Hemingway in the public domain!  I&#39;ve had this on my long-list for a while now too.</li>
<li><a href="https://www.manning.com/books/kubernetes-in-action">Kubernetes in Action</a> (re-fresh).  I did appreciate the &#34;why&#34; that this book (by a core contributor) has, but I haven&#39;t used k8s much in anger since then.  This may easily drop off the list.</li>
<li><a href="https://securitychaoseng.com/">Security Chaos Engineering</a> I&#39;m a paranoid software engineer rather than a security professional of any stripe, but I&#39;m always fascinated by the domain.  Not sure if I&#39;ll get to this, or all the way through it, depending on relevance but I&#39;m keen.</li>
<li><a href="https://geoffreyamoore.com/book/crossing-the-chasm/">Crossing the Chasm</a> I started this probably a decade ago and never finished it.  This year might be the time (or not).</li>
<li><a href="https://en.wikipedia.org/wiki/Carrying_the_Fire">Carrying the Fire</a> Everyone raves about this.  I&#39;m keen.</li>
<li><a href="https://en.wikipedia.org/wiki/The_Rosie_Result">The Rose Result</a>: I identify so strongly with the protagonist (not Rosie) that the second book in the series pissed me off (Rosie basically says &#34;I know you&#39;re quirky and different but now that I&#39;m pregnant I need someone more stable&#34;, and essentially checks out of the story) and I no longer felt like continuing the series.  Perhaps time will heal that wound enough to let me finish it.</li>
</ul>
</div>
</div>
]]></content>
		</item>
		
		<item>
			<title>2023 Reading in Review</title>
			<link>https://blog.markhepburn.com/posts/2023-reading-in-review/</link>
			<pubDate>Mon, 01 Jan 2024 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2023-reading-in-review/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[
<p>
This year I decided to not only make more of an effort to read more,
but to actually capture what I read, and while it wasn&#39;t the primary
goal the ability to do this year&#39;s-end post was enticing (I&#39;m always
impressed by people like <a href="http://blog.fogus.me/2023/12/18/the-best-things-and-stuff-of-2023/">Fogus</a>). There were probably auxilliary
intentions like reading more widely, and reflecting on what I&#39;d read
rather than just churning, but for the most part I had the most
success around simply capturing. One thing I did make a conscious
effort about was not multi-tasking; sometimes if a book is dragging on
and something else shiny is attracting my attention I&#39;ll switch to
that &#34;just for a bit&#34;, and before you know it I have 4 or 5 on the go,
and eventually abandon some of them. I allowed myself to explicitly
not finish books (although I don&#39;t think I did), but this made me more
intentional about what I was consuming and stifled a few urges to
meander.</p>
<p>
I read 40 books in total, with another 4 on the go at the end of the
year (Aurelien Geron&#39;s Machine Learning with TensorFlow book,
&#34;Remember It!&#34;, a mini collection of Aurelius&#39; &#34;Meditations&#34; from a
second-hand shop years ago that I never actually opened, and Brendan
Gregg&#39;s Systems Performance which is so good that I ordered a
hard-copy. I&#39;ll read a few more chapters, but probably leave it as a
reference for now).</p>
<div id="outline-container-headline-1" class="outline-2">
<h2 id="headline-1">
Process
</h2>
<div id="outline-text-headline-1" class="outline-text-2">
<p>
I used an org-mode file (of course), with a couple of nodes: one for
my backlog and in-progress, and one for everything completed. Each
book entry is simply archived into the finished node when I&#39;m done
(type &#34;w&#34; if you have <code>org-use-speed-commands</code> enabled). I also had a
node for &#34;skimming&#34;, which was intending to capture books I only read
part of (might be a technical topic, or training, or a cookbook), but
I didn&#39;t really use this. For each book I captured the author, and
start and finish date using <a href="https://orgmode.org/manual/Properties-and-Columns.html">properties</a>. I also used org <a href="https://orgmode.org/manual/Progress-Logging.html">TODO progress
tracking</a> with tags for notstarted/started/finished. Toggling to
&#34;finished&#34; also sets (a different) close date, as well as the one I
set manually in the properties. Then I&#39;d try and write at least a
brief note about the book, although I didn&#39;t do a great job of this.
Often it was a mix of &#34;wanted to read this because… &#34; followed by an
in-progress half-baked thought, and sometimes that was it! Not exactly
erudite reviews, but the simple attempt to jot down thoughts can
clarify things at times (even if that thing is &#34;I wish I could
remember the turn of phrase I thought of while out on a run&#34;)</p>
<p>
With all that in place I expected it to be a simple task to produce a
nicely-formatted list for the requisite year-in-review post, and
without pushing the envelope here that was a bit of a mixed outcome
(I&#39;m pretty sure I could do a lot better with a bit of elisp, but that
can be another job for next year). I&#39;ve wound up using a <a href="https://orgmode.org/manual/Capturing-column-view.html">dynamic
column block</a> for a summary table. I <em>intended</em> to tidy my notes up a
bit, but… at this stage that feels like cheating. (I did however
remove the &#34;FINISHED&#34; tags that otherwise accompany every entry, and
the &#34;CLOSED&#34; timestamp). I also feel that the dates could be formatted
better.</p>
</div>
</div>
<div id="outline-container-headline-2" class="outline-2">
<h2 id="headline-2">
Reflections
</h2>
<div id="outline-text-headline-2" class="outline-text-2">
<p>
A written backlog was surprisingly effective at making me think about
what I was reading. In the past I&#39;ve definitely been guilty of making
grand plans about what I&#39;ll read next(ish), which many people would
recognise tends to grow unbounded, but being able to view what I&#39;ve
already semi-committed to definitely makes you think harder about
what&#39;s realistic and desirable.</p>
</div>
</div>
<div id="outline-container-headline-3" class="outline-2">
<h2 id="headline-3">
The List
</h2>
<div id="outline-text-headline-3" class="outline-text-2">
<table>
<thead>
<tr>
<th>ITEM</th>
<th>AUTHOR</th>
<th>STARTED</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>Finished</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>The Book of Why</td>
<td>Pearl, J.</td>
<td><span class="timestamp">&lt;2022-12-25 Sun&gt;</span></td>
<td><span class="timestamp">&lt;2023-01-10 Tue&gt;</span></td>
</tr>
<tr>
<td>The Iron Samurai</td>
<td>Simmons, L.</td>
<td><span class="timestamp">&lt;2023-01-01 Sun&gt;</span></td>
<td><span class="timestamp">&lt;2023-01-06 Fri&gt;</span></td>
</tr>
<tr>
<td>Totem Pole</td>
<td>Pritchard, P.</td>
<td><span class="timestamp">&lt;2023-01-10 Tue&gt;</span></td>
<td><span class="timestamp">&lt;2023-01-15 Sun&gt;</span></td>
</tr>
<tr>
<td>Neurotribes</td>
<td>Silberman, S.</td>
<td><span class="timestamp">&lt;2023-01-15 Sun&gt;</span></td>
<td><span class="timestamp">&lt;2023-01-26 Thu&gt;</span></td>
</tr>
<tr>
<td>Doctor Adder</td>
<td>Jeter, K.</td>
<td><span class="timestamp">&lt;2023-01-25 Wed&gt;</span></td>
<td><span class="timestamp">&lt;2023-01-29 Sun&gt;</span></td>
</tr>
<tr>
<td>Cities for people</td>
<td>Gehl, J.</td>
<td><span class="timestamp">&lt;2023-01-29 Sun&gt;</span></td>
<td><span class="timestamp">&lt;2023-02-05 Sun&gt;</span></td>
</tr>
<tr>
<td>The man who solved the market</td>
<td>Zuckerman, G.</td>
<td><span class="timestamp">&lt;2023-02-05 Sun&gt;</span></td>
<td><span class="timestamp">&lt;2023-02-13 Mon&gt;</span></td>
</tr>
<tr>
<td>How the world really works</td>
<td>Smil, V.</td>
<td><span class="timestamp">&lt;2023-02-13 Mon&gt;</span></td>
<td><span class="timestamp">&lt;2023-02-25 Sat&gt;</span></td>
</tr>
<tr>
<td>Anapurna</td>
<td>Herzog, M.</td>
<td><span class="timestamp">&lt;2023-02-25 Sat&gt;</span></td>
<td><span class="timestamp">&lt;2023-03-04 Sat&gt;</span></td>
</tr>
<tr>
<td>How to Prevent a Climate Disaster</td>
<td>Gates, B.</td>
<td><span class="timestamp">&lt;2023-03-05 Sun&gt;</span></td>
<td><span class="timestamp">&lt;2023-03-13 Mon&gt;</span></td>
</tr>
<tr>
<td>Kraken</td>
<td>Mieville, C.</td>
<td><span class="timestamp">&lt;2023-03-13 Mon&gt;</span></td>
<td><span class="timestamp">&lt;2023-03-25 Sat&gt;</span></td>
</tr>
<tr>
<td>Snowcrash</td>
<td>Stephenson, N.</td>
<td><span class="timestamp">&lt;2023-03-26 Sun&gt;</span></td>
<td><span class="timestamp">&lt;2023-04-08 Sat&gt;</span></td>
</tr>
<tr>
<td>The Mastermind: The hunt for the World&#39;s most prolific criminal</td>
<td>Ratliff, E.</td>
<td><span class="timestamp">&lt;2023-04-08 Sat&gt;</span></td>
<td><span class="timestamp">&lt;2023-04-18 Tue&gt;</span></td>
</tr>
<tr>
<td>Life</td>
<td>Richards, K.</td>
<td><span class="timestamp">&lt;2023-05-06 Sat&gt;</span></td>
<td><span class="timestamp">&lt;2023-05-19 Fri&gt;</span></td>
</tr>
<tr>
<td>Podman in Action</td>
<td>Walsh, D.</td>
<td><span class="timestamp">&lt;2023-05-19 Fri&gt;</span></td>
<td><span class="timestamp">&lt;2023-05-27 Sat&gt;</span></td>
</tr>
<tr>
<td>Red Team Blue, Charles Stross</td>
<td>Stross, C.</td>
<td><span class="timestamp">&lt;2023-04-19 Wed&gt;</span></td>
<td><span class="timestamp">&lt;2023-05-06 Sat&gt;</span></td>
</tr>
<tr>
<td>The City and the City</td>
<td>Mieville, C.</td>
<td><span class="timestamp">&lt;2023-05-27 Sat&gt;</span></td>
<td><span class="timestamp">&lt;2023-06-06 Tue&gt;</span></td>
</tr>
<tr>
<td>The Rosie Project</td>
<td>Simsion, G.</td>
<td><span class="timestamp">&lt;2023-06-06 Tue&gt;</span></td>
<td><span class="timestamp">&lt;2023-06-15 Thu&gt;</span></td>
</tr>
<tr>
<td>Who&#39;s #1?</td>
<td>Langville, A.; Meyer, C.</td>
<td><span class="timestamp">&lt;2023-01-19 Thu&gt;</span></td>
<td><span class="timestamp">&lt;2023-06-26 Mon&gt;</span></td>
</tr>
<tr>
<td>Pricing Money</td>
<td>Wiseman, J. D. A.</td>
<td><span class="timestamp">&lt;2023-06-25 Sun&gt;</span></td>
<td><span class="timestamp">&lt;2023-07-12 Wed&gt;</span></td>
</tr>
<tr>
<td>The Rosie Effect</td>
<td>Simsion, G.</td>
<td><span class="timestamp">&lt;2023-07-13 Thu&gt;</span></td>
<td><span class="timestamp">&lt;2023-07-23 Sun&gt;</span></td>
</tr>
<tr>
<td>AWS Security</td>
<td>Shields, D.</td>
<td><span class="timestamp">&lt;2023-02-18 Sat&gt;</span></td>
<td><span class="timestamp">&lt;2023-08-04 Fri&gt;</span></td>
</tr>
<tr>
<td>How big things get done</td>
<td>Flyvbjerg, B.; Gardner, D.</td>
<td><span class="timestamp">&lt;2023-08-05 Sat&gt;</span></td>
<td><span class="timestamp">&lt;2023-08-12 Sat&gt;</span></td>
</tr>
<tr>
<td>Growing in to Autism</td>
<td>Thom-Jones, S.</td>
<td><span class="timestamp">&lt;2023-08-12 Sat&gt;</span></td>
<td><span class="timestamp">&lt;2023-08-18 Fri&gt;</span></td>
</tr>
<tr>
<td>Small is Beautiful</td>
<td>Schumacher, E. F.</td>
<td><span class="timestamp">&lt;2023-08-19 Sat&gt;</span></td>
<td><span class="timestamp">&lt;2023-09-01 Fri&gt;</span></td>
</tr>
<tr>
<td>Lessons in chemistry</td>
<td>Garmus, B.</td>
<td><span class="timestamp">&lt;2023-09-02 Sat&gt;</span></td>
<td><span class="timestamp">&lt;2023-09-07 Thu&gt;</span></td>
</tr>
<tr>
<td>The Internet Con</td>
<td>Doctorow, C.</td>
<td><span class="timestamp">&lt;2023-09-07 Thu&gt;</span></td>
<td><span class="timestamp">&lt;2023-09-10 Sun&gt;</span></td>
</tr>
<tr>
<td>Programming Pearls</td>
<td>Bentley, J. L.</td>
<td><span class="timestamp">&lt;2023-09-10 Sun&gt;</span></td>
<td><span class="timestamp">&lt;2023-09-24 Sun&gt;</span></td>
</tr>
<tr>
<td>The Icon Handbook</td>
<td>Hicks, J.</td>
<td><span class="timestamp">&lt;2023-09-24 Sun&gt;</span></td>
<td><span class="timestamp">&lt;2023-09-26 Tue&gt;</span></td>
</tr>
<tr>
<td>Around the world in 80 days</td>
<td>Verne, J.</td>
<td><span class="timestamp">&lt;2023-09-27 Wed&gt;</span></td>
<td><span class="timestamp">&lt;2023-10-03 Tue&gt;</span></td>
</tr>
<tr>
<td>Mindfulness-integrated CBT for Well-being and Personal Growth</td>
<td>Cayoun, B.</td>
<td><span class="timestamp">&lt;2023-04-05 Wed&gt;</span></td>
<td><span class="timestamp">&lt;2023-09-30 Sat&gt;</span></td>
</tr>
<tr>
<td>Rogue Code</td>
<td>Russinovich, M.</td>
<td><span class="timestamp">&lt;2023-10-14 Sat&gt;</span></td>
<td><span class="timestamp">&lt;2023-10-19 Thu&gt;</span></td>
</tr>
<tr>
<td>The Persuasion Story</td>
<td>Garfinkel, D.</td>
<td><span class="timestamp">&lt;2023-10-19 Thu&gt;</span></td>
<td><span class="timestamp">&lt;2023-10-25 Wed&gt;</span></td>
</tr>
<tr>
<td>Secrets of the autistic millionaire</td>
<td>Plummer, D. W.</td>
<td><span class="timestamp">&lt;2023-02-18 Sat&gt;</span></td>
<td><span class="timestamp">&lt;2023-10-31 Tue&gt;</span></td>
</tr>
<tr>
<td>The Importance Of Not Being Earnest</td>
<td>Kurlanksy, M.</td>
<td><span class="timestamp">&lt;2023-11-13 Mon&gt;</span></td>
<td><span class="timestamp">&lt;2023-11-24 Fri&gt;</span></td>
</tr>
<tr>
<td>Rogue Code</td>
<td>Russinovich, M.</td>
<td><span class="timestamp">&lt;2023-11-24 Fri&gt;</span></td>
<td><span class="timestamp">&lt;2023-12-07 Thu&gt;</span></td>
</tr>
<tr>
<td>The Joyous Season</td>
<td>Dennis, P.</td>
<td><span class="timestamp">&lt;2023-12-08 Fri&gt;</span></td>
<td><span class="timestamp">&lt;2023-12-12 Tue&gt;</span></td>
</tr>
<tr>
<td>The Way of Zen</td>
<td>Watts, A.</td>
<td><span class="timestamp">&lt;2023-12-13 Wed&gt;</span></td>
<td><span class="timestamp">&lt;2023-12-19 Tue&gt;</span></td>
</tr>
<tr>
<td>Zed Attack Proxy Cookbook</td>
<td>Soper, R.; Torres, N.N.; Almoailu, A.</td>
<td><span class="timestamp">&lt;2023-10-02 Mon&gt;</span></td>
<td><span class="timestamp">&lt;2023-12-24 Sun&gt;</span></td>
</tr>
<tr>
<td>The Autobiography of Benjamin Franklin</td>
<td>Franklin, B.</td>
<td><span class="timestamp">&lt;2023-12-19 Tue&gt;</span></td>
<td><span class="timestamp">&lt;2023-12-26 Tue&gt;</span></td>
</tr>
</tbody>
</table>
<div id="outline-container-headline-4" class="outline-3">
<h3 id="headline-4">
The Book of Why
</h3>
<div id="outline-text-headline-4" class="outline-text-3">
<p>
   I struggled to follow for a while because a lot of ideas (the
   &#34;rungs of causality&#34;) are introduced in the intro, and then taken
   as assumed knowledge. I felt that the &#34;do-calculus&#34; was also
   assumed a bit early. But otherwise, clearly illustrates how
   different variables in networks can be accomodated, mediated for,
   etc.</p>
</div>
</div>
<div id="outline-container-headline-5" class="outline-3">
<h3 id="headline-5">
The Iron Samurai
</h3>
<div id="outline-text-headline-5" class="outline-text-3">
<p>
   Louie&#39;s autobiography, in the third person (notionally as the
   titular &#34;iron samurai&#34; alter-ego, although this doesn&#39;t really come
   through), and history of Westside Barbell and its alumni. Not high
   literature, but the accomplishments alone are worth reading for.</p>
</div>
</div>
<div id="outline-container-headline-6" class="outline-3">
<h3 id="headline-6">
Totem Pole
</h3>
<div id="outline-text-headline-6" class="outline-text-3">
<p>
   Amazing account of survival and adapatation and recovery into a new
   life, from an accomplished climber. Describes the lead-up to the
   accident and his own recollections, as well as the aftermath and
   revisiting the site on the year anniversary for a documentary,
   sandwiched around his diary from his time in recovery.</p>
</div>
</div>
<div id="outline-container-headline-7" class="outline-3">
<h3 id="headline-7">
Neurotribes
</h3>
<div id="outline-text-headline-7" class="outline-text-3">
<p>
   A history of autism, from early misunderstandings through the
   gradual formulations of theories and attempts at treatments.
   Initially it was lumped in with schizophrenia, and considered a
   child-only disease. Coverage is in terms of the many personalities,
   with Aspberger and Kanner occupying early chapters, and the many
   parents who took matters into their own hands, refused to give up
   on their children, and mobilised grass-roots support networks.
   Aspberger is given quite a charitable coverage, relative (I gather)
   to his historical reputation due to association with Nazi Germany
   (the book proposes a theory of how he was both self-preserving but
   also endeavouring to save his patients). Chapter 3, with its focus
   on Nazi history and their extermination policies, was incredibly
   grim. It ends almost abruptly, but with a positive coverage of
   self-organising and how the internet provided a means for people to
   identify and more-effectively communicate and supporte each other.
   Also though, later pages emphasise that it&#39;s only society that
   makes a difference into a disability, and that much of progress is
   probably due to the diversity. The vaccine drama also of course
   gets coverage.</p>
<blockquote>
<p>By autistic standards, the &#34;normal&#34; brain is easily distractible, is
obsessively social, and suffers from a deficit of attention to detail
and routine. Thus people on the spectrum experience the neurotypical
world as relentlessly unpredictable and chaotic, perpetually turned up
too loud, and full of people who have little respect for personal
space.</p>
</blockquote>
<p>I cannot tell you how hard that quote spoke to me.</p>
</div>
</div>
<div id="outline-container-headline-8" class="outline-3">
<h3 id="headline-8">
Doctor Adder
</h3>
<div id="outline-text-headline-8" class="outline-text-3">
<p>
   <a href="https://twitter.com/cstross/status/1612386757147770883">https://twitter.com/cstross/status/1612386757147770883</a>
   Apparently the &#34;first&#34; cyberpunk book; shopped around but not
   published, until Neuromancer was a success.  Very-dystopian, where
   Dr Adder rules over the &#34;interface&#34; of LA, a surgeon who uses a
   drug cocktail to determine people&#39;s perversions, which usually
   involves amputation or disfiguration.</p>
</div>
</div>
<div id="outline-container-headline-9" class="outline-3">
<h3 id="headline-9">
Cities for people
</h3>
<div id="outline-text-headline-9" class="outline-text-3">
<p>
   One of the first things I noticed being aware of when I started
   travelling was the differences in city organisation and urban
   planning. I love to explore by walking, and I noticed things like
   the countdown on traffic lights, and I was particularly taken with
   the Hong Kong finance district, where the gleaming sky scrapers
   were actually part of the pedestrian landscape; a network of
   overpasses and lower floor shipping centres meant you could
   traverse on foot without crossing a road. Years later I attended a
   public meeting discussing the proposed redevelopment of my town&#39;s
   waterfront, to make the city more walkable, and presented many more
   examples of pedestrian friendly (and the opposite) cities around
   the world. The presenter is the author of this book, which is all
   about exactly what makes a walkable city and why. (He is not a fan
   of overpasses; see pp133-3!)</p>
</div>
</div>
<div id="outline-container-headline-10" class="outline-3">
<h3 id="headline-10">
The man who solved the market
</h3>
<div id="outline-text-headline-10" class="outline-text-3">
<p>
   This was a little disappointing; the introduction is essentially a
   long disclaimer that hardly anyone would talk to him about the
   topic, Jim himself did grant him an interview but also asked him
   not to write the book, and everyone who worked there signed a
   comprehensive NDA. The result is basically a dramatised version of
   what is publicly known, which had some interest for me but probably
   not relative to the length of the book. Ed Thorpe&#39;s &#34;A man for all
   markets&#34; is at least autobiographical, and includes his own
   perspective on independently developing the Black-Scholes equation
   which you can reference separately, etc.</p>
</div>
</div>
<div id="outline-container-headline-11" class="outline-3">
<h3 id="headline-11">
How the world really works
</h3>
<div id="outline-text-headline-11" class="outline-text-3">
<p>
   Smil is apparently Bill Gates&#39; <a href="https://www.gatesnotes.com/Books/How-the-World-Really-Works">favourite author</a>, which is a
   tempered recommendation (it could go a couple of different ways,
   really). I gather a lot of his books are a lot more detailed, but
   this is more of a ground-up exploration of… how the world works
   (and how it developed into that way), but also why we aren&#39;t going
   to be able to change in a hurry because of the deeply-embedded
   reliances on core materials and processes. Specifically, the carbon
   reduction spoken of as crucial isn&#39;t realistic by 2050 in his view.
   Each chapter picks a high-level topic, such as energy, food (using
   a quantity of diesel fuel to illustrate how much is involved in the
   production of a particular foodstuff, once you consider fertilizer,
   harvesting and processing, and transport), etc.  The later chapter
   on Risks feels a bit out of place.</p>
</div>
</div>
<div id="outline-container-headline-12" class="outline-3">
<h3 id="headline-12">
Anapurna
</h3>
<div id="outline-text-headline-12" class="outline-text-3">
<p>
   First hand account of the first successful ascent of an 8000m peak.
   &#34;The whole of this book has been dictated at the American Hospital
   in Neuilly where I am still having rather a difficult time.&#34;. Boy
   wasn&#39;t he! This was a classic old-school expedition, where not only
   did they complete the summit without the aid of supplementary
   oxygen or modern equipment, but they didn&#39;t even have maps of the
   region and had to undertake an extensive reconnaissance to even
   find a plausible route. The story of the climb is fascinating, but
   the descent and aftermath is harrowing.</p>
</div>
</div>
<div id="outline-container-headline-13" class="outline-3">
<h3 id="headline-13">
How to Prevent a Climate Disaster
</h3>
<div id="outline-text-headline-13" class="outline-text-3">
<p>
   Following from &#34;How the world really works&#34; (recommended by billg),
   which was ultimately fairly sceptical of our chances, I was curious
   about Bill&#39;s own takes.  Ultimately it&#39;s a more light-weight, and
   admittedly accessible version of the same; leaning on much of the
   same quantification at times, and a bit more optimistic that
   technology will find a way.</p>
</div>
</div>
<div id="outline-container-headline-14" class="outline-3">
<h3 id="headline-14">
Kraken
</h3>
<div id="outline-text-headline-14" class="outline-text-3">
<p>
   Recommended by a colleague; &#34;Kraken is probably my favourite – the
   sheer density of crazy ideas in that book is extraordinary. Plus he
   credits Pop Will Eat Itself with inspiring it!&#34;. I&#39;m not going to
   argue with any of that; it&#39;s notionally bizarro-supernatural I
   suppose which I wouldn&#39;t normally read, but superbly executed and
   great play on language.</p>
</div>
</div>
<div id="outline-container-headline-15" class="outline-3">
<h3 id="headline-15">
Snowcrash
</h3>
<div id="outline-text-headline-15" class="outline-text-3">
<p>
   Re-reading a classic, back in attention thanks to the recent
   &#34;metaverse&#34; flurry.  I recently went looking for a quote, and was
   reminded of so many more.  It held up very well for me!  I vaguely
   remember it, and it has something of a reputation for, finishing
   rather slowly (or dragging on and petering out rather than coming
   to a conclusion), which I didn&#39;t find this time.  Now I&#39;m curious
   to look more into Sumerian culture and language.</p>
</div>
</div>
<div id="outline-container-headline-16" class="outline-3">
<h3 id="headline-16">
The Mastermind: The hunt for the World&#39;s most prolific criminal
</h3>
<div id="outline-text-headline-16" class="outline-text-3">
<p>
   Started with a long-form <a href="https://magazine.atavist.com/the-mastermind/">series of articles</a>. Unbelievable in scope,
   although the flow of the book unfortunately slightly reflected the
   uncertainty around some of the facts (it&#39;s only a quasi-linear
   narrative, and basically jumps over the beginnings)</p>
</div>
</div>
<div id="outline-container-headline-17" class="outline-3">
<h3 id="headline-17">
Life
</h3>
<div id="outline-text-headline-17" class="outline-text-3">
<p>
   Read this on the road, and loved it! The Stones were one of the
   early bands that got me into music (long story), but I was
   surprisingly ignorant of a lot of their back-story, and Keith&#39;s
   personal history – legends aside, which get plenty of air-time.
   The story behind iconic riffs and songs were great.</p>
</div>
</div>
<div id="outline-container-headline-18" class="outline-3">
<h3 id="headline-18">
Podman in Action
</h3>
<div id="outline-text-headline-18" class="outline-text-3">
<p>
   I power-read this on the road, but it&#39;s quite accessible. Written
   by the core author (and SELinux contributor, I gather), it does a
   great job of explaining how Podman differs from Docker and the
   reasoning behind those decisions (with a particular emphasis on
   security, which has its own section).</p>
</div>
</div>
<div id="outline-container-headline-19" class="outline-3">
<h3 id="headline-19">
Red Team Blue
</h3>
<div id="outline-text-headline-19" class="outline-text-3">
<p>
   Finished as we were landing in Italy!  Short but fun read, with an
   emphasis on the non-IT side of &#34;red team&#34; hacking and mindset.</p>
</div>
</div>
<div id="outline-container-headline-20" class="outline-3">
<h3 id="headline-20">
The City and the City
</h3>
<div id="outline-text-headline-20" class="outline-text-3">
<p>
   I ended up quite enjoying this, albeit maybe not quite as much as
   my first Mieville book (Kraken).  The friend who put me on to
   Mieville mentioned that basically every book was a different genre.
   It took me a little while to get into it, because I read chapters
   sporadically and while travelling and tired, and so I didn&#39;t fully
   absorb the core concepts of the world described.  That world –
   around which a basic police crime-solving drama is set – consists
   of two interwoven cities, whose inhabitants are forbidden from and
   conditioned against even glancing at the others.  In common
   (&#34;crosshatched&#34;) areas, they are trained from birth to identify
   gaits and manerisms and avoid but not perceive inhabitants from the
   other.  Transgressions are called &#34;breach&#34;, with a mysterious
   shadowy power responsible for enforcement.  It&#39;s a bizarre world,
   but works well enough and is obviously key to the evolving story.
   (Note that inhabitants can legally enter the other city, via a
   single border-crossing, at which point they must cease noticing
   their own city for the duration)</p>
</div>
</div>
<div id="outline-container-headline-21" class="outline-3">
<h3 id="headline-21">
The Rosie Project
</h3>
<div id="outline-text-headline-21" class="outline-text-3">
<p>
   I loved this,  but boy-howdy did I feel like it was describing me
   at least 85% of the time.  Not <em>all</em> the time; I&#39;m not that
   meticulous with time for eg, and unfortunately don&#39;t quite have his
   memory, but pretty much every comment about scheduling, routine,
   clothing choice, mannerisms etc were… uncomfortably close to home!</p>
</div>
</div>
<div id="outline-container-headline-22" class="outline-3">
<h3 id="headline-22">
Who&#39;s #1?
</h3>
<div id="outline-text-headline-22" class="outline-text-3">
<p>
   I&#39;ve had this on the shelf (and in storage) for years now. I can&#39;t
   remember how it originally came across my radar (John Cook&#39;s blog
   is a reasonable bet, but I can&#39;t find the post if it was), but I
   think the original impetus was an interest in sports gambling. It&#39;s
   remarkably well-written and approachable, describing the approach
   in high-level terms before delving into the maths, and using some
   running sports examples. They cover a few different methodologies,
   then weighting (eg, more recent results should carry more
   importance than early-season) and aggregating multiple rankings,
   and also how to compare rankings.</p>
</div>
</div>
<div id="outline-container-headline-23" class="outline-3">
<h3 id="headline-23">
Pricing Money
</h3>
<div id="outline-text-headline-23" class="outline-text-3">
<p>
   Available <a href="http://www.jdawiseman.com/books/pricing-money/Pricing_Money_JDAWiseman.html">online</a>, converted to epub. Written for people coming into
   the industry, so mainly describes the various derived products,
   with a small amount of context such as the roles involved. Less
   clear, but explained by the author in a HN comment, is the &#34;why&#34;:
   &#34;The purpose of financial markets, sometimes but not always wholly
   achieved, is to transfer risks to those best able to hold them.
   E.g., you are not the optimal person to hold the risk that, through
   no fault of your own, your house burns down. That risk exists, and
   you are not the optimal holder of it. Hence insurance. A
   Lincolnshire farmer — and yes, I like the non-abstract solidly of
   the example — is not the optimal holder of the ‘risk’ that the
   Australian and Kansas wheat harvests are super-bountiful. Markets
   allow that risk to be transferred to a non-farmer better able to
   hold the risk.&#34;</p>
</div>
</div>
<div id="outline-container-headline-24" class="outline-3">
<h3 id="headline-24">
The Rosie Effect
</h3>
<div id="outline-text-headline-24" class="outline-text-3">
<p>
   I enjoyed this, although something of the novelty has possibly
   gone. I didn&#39;t find Rosie all that sympathetic this time around,
   possibly because I personally relate to Don. Still plenty of parts
   I once would have said I related to all too closely.</p>
</div>
</div>
<div id="outline-container-headline-25" class="outline-3">
<h3 id="headline-25">
AWS Security
</h3>
<div id="outline-text-headline-25" class="outline-text-3">
<p>
   May end up being one for the skimmed/dipped-into pile, but I feel
   like I need to understand IAM and associated constructs better
   (even though we don&#39;t do much work in AWS). Did end up skimming the
   latter half, but it was a good overview of IAM and the rest, and
   some examples of incident response.</p>
</div>
</div>
<div id="outline-container-headline-26" class="outline-3">
<h3 id="headline-26">
How big things get done
</h3>
<div id="outline-text-headline-26" class="outline-text-3">
<p>
   I did not have high expectations for this (it was a recommendation, and others in the genre often seem quite fluffy).  To be clear it was a little bit &#34;pop sci&#34;, but the core take-aways were fascinating: using prior art as your estimate anchor (which implicitly incorporates the unknown-unknowns in overruns), not focussing on the factors that make your project unique (it probably has more similarities than you think), etc.</p>
</div>
</div>
<div id="outline-container-headline-27" class="outline-3">
<h3 id="headline-27">
Growing in to Autism
</h3>
<div id="outline-text-headline-27" class="outline-text-3">
<p>
   This has personal implications obviously, and the first couple of chapters resonated <em>extremely</em> hard.  I even found myself suddenly incredibly emotional at one line, without being completely aware why (it was close to a personal experience, but not a traumatic one or anything like that).</p>
<p>
   The author describes it as &#34;autobiographical, but not an autobiography&#34;; it&#39;s what autism is like for her, with the aim of conveying the experience to those who are curious, or those on the spectrum themselves by way of support.  She clearly experiences more and more vividly than I do (for example, I am very affected by noise, but she is also very sensitive to lights, textures and even tastes.  Parts of it were so unfamiliar that I felt &#34;normal&#34; (which doesn&#39;t help my imposter syndrome), then other parts I felt incredibly validated.</p>
</div>
</div>
<div id="outline-container-headline-28" class="outline-3">
<h3 id="headline-28">
Small is Beautiful
</h3>
<div id="outline-text-headline-28" class="outline-text-3">
<p>
   Available online at <a href="http://www.ditext.com/schumacher/small/small.html">http://www.ditext.com/schumacher/small/small.html</a></p>
<p>
   <a href="https://en.wikipedia.org/wiki/Small_Is_Beautiful">https://en.wikipedia.org/wiki/Small_Is_Beautiful</a></p>
<p>
   Finding this a little tough going, partly because of the language
   and partly the distracted state I&#39;m reading it in. I wouldn&#39;t be
   surprised if it was a bit of a socialist &#34;textbook&#34; or icon, as it
   has a strong &#34;for the workers&#34; aspect to it, although the main
   thrust is how to help (for example) the third world: the main
   thrust is to get as close to full and gainful employment as
   possible, which means <em>not</em> automatically adopting the
   most-efficient factory processes which are automated. There&#39;s some
   interesting ideas in it, but I&#39;ve started speed-reading to a
   certain extent. It wound up with quite a socialist push, with
   profit-sharing and mutual ownership, etc. I didn&#39;t absorb most of
   the arguments and I suspect it&#39;s more preaching to the converted,
   which is a bit of a shame as I&#39;m interested in the general ideas.</p>
</div>
</div>
<div id="outline-container-headline-29" class="outline-3">
<h3 id="headline-29">
Lessons in chemistry
</h3>
<div id="outline-text-headline-29" class="outline-text-3">
<p>
   Light fluffy romance (kind of), but I didn&#39;t mind it. Was
   recommended to me because… in a similar vein to recent reading I
   suppose (not that there&#39;s an ASD element, but the main characters
   are fairly black-and-white rigid)</p>
</div>
</div>
<div id="outline-container-headline-30" class="outline-3">
<h3 id="headline-30">
The Internet Con
</h3>
<div id="outline-text-headline-30" class="outline-text-3">
<p>
   Subtitle: How to seize the means of computation. Essentially,
   looking at the reasons &#34;big tech&#34; got so big, and how it might be
   unpacked: basically, interoperability (both mandated, and allowing
   reverse-engineering), then examining all the issues that go in to
   enabling that such as past lobbying against such legislation.</p>
</div>
</div>
<div id="outline-container-headline-31" class="outline-3">
<h3 id="headline-31">
Programming Pearls
</h3>
<div id="outline-text-headline-31" class="outline-text-3">
<p>
   A re-read (I&#39;m not sure I ever finished it, to be honest) of a
   classic from my bookshelf. I did mostly skip the exercises which
   obviously makes it even shorter, but even only reading it the
   messages of thinking hard about a problem and considering the
   tradeoffs for data structures and algorithms is a lovely process.</p>
</div>
</div>
<div id="outline-container-headline-32" class="outline-3">
<h3 id="headline-32">
The Icon Handbook
</h3>
<div id="outline-text-headline-32" class="outline-text-3">
<p>
   At the start of my non-academic software engineering career, I was
   a &#34;full-stack engineer&#34; (ie, the only engineer). I was aware of the
   importance of design and aesthetics, but utterly incapable of
   implementing much by myself so I devoured a bunch of material like
   &#34;<a href="https://designforhackers.com/blog/impressionist-color-theory/">Design for Hackers</a>&#34; and articles on colour theory, etc. I still
   have no design sense, but I had this book on my shelf from those
   days. It&#39;s a little dated in places (mainly, icons presented as
   &#34;standards&#34; that are more rare these days, such as &#34;share&#34;), and
   more of a coffee table book with interviews and advice than a
   how-to, but a nice book nonetheless.</p>
</div>
</div>
<div id="outline-container-headline-33" class="outline-3">
<h3 id="headline-33">
Around the world in 80 days
</h3>
<div id="outline-text-headline-33" class="outline-text-3">
<p>
   I read this as a kid, so I&#39;m curious how it&#39;s going to read now, as
   a moderately-well-travelled adult. Verdict: still good fun, but I
   don&#39;t know that I resonated any further with any of the places! (or
   modes of transport)</p>
</div>
</div>
<div id="outline-container-headline-34" class="outline-3">
<h3 id="headline-34">
Mindfulness-integrated CBT for Well-being and Personal Growth
</h3>
<div id="outline-text-headline-34" class="outline-text-3">
<p>
   So, pushing 50, I have realised that I&#39;m autistic (topic for a
   separate post, perhaps), the psychologist I&#39;m seeing is the author
   of this book. I&#39;m only a few chapters in so far and, while I don&#39;t
   mind the practice, I&#39;m unsure how mindfulness and CBT will affect
   the visceral physical reaction to noise I get, that was the impetus
   for seeking help in the first place.</p>
</div>
</div>
<div id="outline-container-headline-35" class="outline-3">
<h3 id="headline-35">
Rogue Code
</h3>
<div id="outline-text-headline-35" class="outline-text-3">
<p>
   I just felt like some trashy fiction, because sleep etc was making
   progress through Systems Performance even slower than it might
   otherwise be. Now that I&#39;ve started it, I&#39;m enjoying it more than I
   expected (I don&#39;t remember being that into the first in the series,
   but I don&#39;t remember details at all). Once upon a time I&#39;d have
   sneered at the description of &#34;super-human&#34; malware, but following
   the <a href="https://googleprojectzero.blogspot.com/">Google Project Zero</a> blog (which reverse-engineers zero-days
   found in the wild), I am now more believing. (and it doesn&#39;t hurt
   that the author, as the blurbs all point out, does know his stuff
   so at the very least he&#39;s not going to destroy plausibility too
   easily!). It isn&#39;t exactly dated, but a couple of points were
   curious in the current context: no mention of ransomware (when
   describing what malware got up to), and the protagonist choosing a
   phone with &#34;his preferred Windows OS&#34; (hardly surprising given the
   author&#39;s employment, but amusing nonetheless)</p>
</div>
</div>
<div id="outline-container-headline-36" class="outline-3">
<h3 id="headline-36">
The Persuasion Story
</h3>
<div id="outline-text-headline-36" class="outline-text-3">
<p>
   For work (it was mentioned by my business partner), and while I&#39;m
   not the head of sales, I do like explaining things and taking that
   side seriously, plus a better way to represent your business always
   helps. (Also it was on sale for $1 so I didn&#39;t think very hard
   about it). It presents persuasion stories and shorter anecdotes
   (contrasted with hero&#39;s-journey style elaborate stories for
   entertainment), and covers a range of categories (origin stories,
   &#34;I feel your pain&#34;, etc) which were interesting but I didn&#39;t
   particularly gel with his examples, mainly because they seemed to
   be drawn from the sort of long-copy full-page web ads I tend to
   skip over. A penultimate chapter on common attributes was useful.</p>
</div>
</div>
<div id="outline-container-headline-37" class="outline-3">
<h3 id="headline-37">
Secrets of the autistic millionaire
</h3>
<div id="outline-text-headline-37" class="outline-text-3">
<p>
   <a href="https://www.amazon.com.au/Secrets-Autistic-Millionaire-Everything-Aspergers-ebook/dp/B09KGF6685">https://www.amazon.com.au/Secrets-Autistic-Millionaire-Everything-Aspergers-ebook/dp/B09KGF6685</a>
   Not sure about this one yet; might be a short interesting read, might be braggadacio.
   Via <a href="https://www.youtube.com/watch?v=xi1Lq79mLeE,">https://www.youtube.com/watch?v=xi1Lq79mLeE,</a> which I&#39;ll watch before making up my mind!</p>
<p>
   Then I noticed the &#34;commonly highlighted&#34; sections on Amazon: &#34;.. a
   sense of what the other might be thinking doesn’t come naturally,
   it becomes a much more mechanical and analytical process.&#34;; &#34;People
   with the symptoms of autism often seem particularly motivated to
   learn and know what is inside everything.&#34;; &#34;The biggest challenge
   for me is in knowing when to jump into a conversation amongst a
   group.&#34;, and… that&#39;s me. I&#39;ll dive in.</p>
<p>
   I wanted to like this more than I did, for a couple of reasons.
   Ignoring the obnoxious title, I thought that we might overlap a lot
   more since we share a profession (ie, perhaps we self-selected that
   way because of overlapping traits), but we probably don&#39;t.
   Secondly, because of that lack of identification, and his very
   literal coverage of a topic (like a typical autistic &#34;fact dump&#34;)
   without the accompanying broad-spectrum dive and explanation, a lot
   of it winds up being a description of how he&#39;s affected and what he
   does (but somehow, without enough depth to be that useful to anyone
   else). On the other hand I was skimming a bit by the end so perhaps
   I missed some gems.</p>
</div>
</div>
<div id="outline-container-headline-38" class="outline-3">
<h3 id="headline-38">
The Importance Of Not Being Earnest
</h3>
<div id="outline-text-headline-38" class="outline-text-3">
<p>
   A $2 kindle deal, but I do like a bit of (early) Hemmingway. I&#39;ve
   been pleasantly enjoying it; the author is a writer often musing
   about writing, as well as Hemingway&#39;s own life and writing,
   including his embellishments, in the historical context such as the
   Spanish civil war and Franco. It&#39;s making me want to revisit a few
   of his (Hemmingway) books: I found &#34;The Sun Also Rises&#34; to be a
   revelation when I first encountered it, but the case is made that
   it appeals to a certain younger generation.</p>
</div>
</div>
<div id="outline-container-headline-39" class="outline-3">
<h3 id="headline-39">
Rogue Code
</h3>
<div id="outline-text-headline-39" class="outline-text-3">
<p>
   Final one in the series. Just wanted some trash I didn&#39;t have to
   think about much. Didn&#39;t enjoy it as much as the previous one, but
   that may just have been a mood thing.</p>
</div>
</div>
<div id="outline-container-headline-40" class="outline-3">
<h3 id="headline-40">
The Joyous Season
</h3>
<div id="outline-text-headline-40" class="outline-text-3">
<p>
   I think mum read this to me (us) originally, and I&#39;m pretty sure I
   re-read it as a kid. The timing seems apt. Still entertaining; I&#39;m
   fairly sure passages of that would have gone over my head last time
   I read it!</p>
</div>
</div>
<div id="outline-container-headline-41" class="outline-3">
<h3 id="headline-41">
The Way of Zen
</h3>
<div id="outline-text-headline-41" class="outline-text-3">
<p>
   Another Kindle deal. I found it a bit heavy-going at times. Mainly
   I was trying to skim and it&#39;s really not a book that lends itself
   to that, and partly I suspect I was expecting a bit of a &#34;how-to&#34;
   and this had plenty of dense attempts at conveying the
   unconveyable.</p>
</div>
</div>
<div id="outline-container-headline-42" class="outline-3">
<h3 id="headline-42">
Zed Attack Proxy Cookbook
</h3>
<div id="outline-text-headline-42" class="outline-text-3">
<p>
   Purchase through work, as my part of a continuing-education drive.
   I&#39;m interested partly just in the pen-testing domain, and also if
   there&#39;s aspects we can practically apply to our own work, such as
   automated scanning as part of a CI run. Skimming at work for now,
   rather than working through next to a keyboard (may change, more
   likely I&#39;ll revisit later).</p>
<p>
   Ended up churning through it a little bit, and didn&#39;t do any of the
   exercises hands-on (although I will later, selectively). At first
   it seemed like they were trying to fill it out (every exercise in
   the first chapter started out with &#34;you will need ZAP installed…
   &#34;), but it got more detailed. The focus was more on pentesting,
   with the ZAP functionality essentially hand-editing requests and
   responses for the most part. Use in a CI pipeline was limited to
   the penultimate exercise, but still useful.</p>
</div>
</div>
<div id="outline-container-headline-43" class="outline-3">
<h3 id="headline-43">
The Autobiography of Benjamin Franklin
</h3>
<div id="outline-text-headline-43" class="outline-text-3">
<p>
   <a href="https://standardebooks.org/ebooks/benjamin-franklin/the-autobiography-of-benjamin-franklin">https://standardebooks.org/ebooks/benjamin-franklin/the-autobiography-of-benjamin-franklin</a>
   I&#39;ve been enjoying this, and despite the aged language style it is
   an easy read. Anecdotes I&#39;ve enjoyed or remembered: improving his
   writing by noting from a good piece and then attempting to
   reproduce it; resolving to cure his &#34;pride&#34; by allowing more space
   for disagreements and changing his responses to be more
   accommodating; how he maintained his belief in a god but didn&#39;t
   attend a service because he felt it was about being a better
   Presbyterian rather than a better person; …</p>
</div>
</div>
</div>
</div>
]]></content>
		</item>
		
		<item>
			<title>Tabbed Browsing and Attention</title>
			<link>https://blog.markhepburn.com/posts/tabbed-browsing-and-attention/</link>
			<pubDate>Wed, 25 Oct 2023 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/tabbed-browsing-and-attention/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>
It&#39;s a common observation that social media and screens have had a negative effect on people&#39;s attention spans.  I&#39;ve noticed related effects, such as Google and memory: why remember facts, when you can look them up instantly?<sup class="footnote-reference"><a id="footnote-reference-1" href="#footnote-1">1</a></sup></p>
<p>
The last few years I&#39;ve been off most social media and I (mostly) don&#39;t pick up my phone for entertainment, but I <em>still</em> notice that my ability to focus on a long article (non-work, ie I&#39;m reading for entertainment or self education) has diminished.</p>
<p>
I blame the sheer <em>amount</em> of content!  There&#39;s just so much to get through that there&#39;s always more in the queue, and anything that slows you down is discarded (&#34;for later&#34;, perhaps).  But as an early precursor, I  also speculate that tabbed browsing had a big part to play here.  My first introduction was the original <a href="https://en.wikipedia.org/wiki/ICab">iCab</a> browser, and it was a revelation: pages loaded slowly in those days, so I could open a bunch in parallel and flick between them to consume those that loaded first.  (Then of course you don&#39;t get around to finishing <em>all</em> of them so some are left for &#34;later&#34;… but I suspect that bad habit didn&#39;t fully develop until later)</p>
<p>
I don&#39;t have any particular answers, but in addition to re-starting a mindfulness meditation practice I have been making a concerted effort to read more books again which I have been happy about.</p>
<div class="footnotes">
<hr class="footnotes-separatator">
<div class="footnote-definitions">
<div class="footnote-definition">
<sup id="footnote-1"><a href="#footnote-reference-1">1</a></sup>
<div class="footnote-body">
<p>This does actually work pretty well for me, as I have good contextual memory: I may not remember the details, but I do remember that it exists and I can recall enough of the context to enable me to find it again.</p>
</div>
</div>
</div>
</div>
]]></content>
		</item>
		
		<item>
			<title>Atuin and per Directory History Import</title>
			<link>https://blog.markhepburn.com/posts/atuin-and-per-directory-history-import/</link>
			<pubDate>Sat, 07 Oct 2023 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/atuin-and-per-directory-history-import/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>
There&#39;s an oft-quoted Unix philosophy that tools should do one thing only, and do it well: searching, filtering, manipulation, etc, with the idea being the shell can quickly combine these into more sophisticated custom functionality. Perhaps ironically, the shells themselves are accumulating plenty of additional functionality themselves.</p>
<p>
I&#39;ve recently started using <a href="https://atuin.sh/">Atuin</a>, which is essentially a souped-up tool for managing your shell history.  Every shell (bash, zsh, etc) will keep a record of your previous commands, but they&#39;ll all store them in their own file, using their own format, with their own tweaks on accessing it.  Using atuin delegates all of that to a separate tool, which is now relatively shell-agnostic, <em>and</em> you get additional metadata such as the directory the command was executed in and the return status and duration, <em>and</em> you get more advanced search capabilities, <em>and</em> you can even sync history across machines (I don&#39;t use this feature, currently).</p>
<p>
If you clicked the link above you&#39;ll see that atuin provides a search UI as well.  I&#39;ve also been using <a href="https://andrew-quinn.me/fzf/">fzf</a> lately, which is an absolute game-changer.  I don&#39;t even make heavy use of its capabilities (although I&#39;m starting to integrate it more, <a href="https://gist.github.com/reegnz/b9e40993d410b75c2d866441add2cb55">eg as a jq repl</a>), but the real-time fuzzy filtering is amazing, and mirrors the experience I get in Emacs via <a href="https://github.com/emacs-helm/helm/">helm</a> or more recently <a href="https://github.com/markhepburn/dotemacs/blob/master/lisp/custom-selection.el">selectrum et al</a>.</p>
<p>
Atuin has a few different options for searching (prefix, fuzzy, exact, excluding, etc), including mostly mimicking the experience I was used to with fzf and Emacs, but ultimately didn&#39;t quite reproduce it.<sup class="footnote-reference"><a id="footnote-reference-1" href="#footnote-1">1</a></sup></p>
<p>
What completed the puzzle for me was a snippet from a <a href="https://news.ycombinator.com/item?id=35256206">Hacker News comment</a>, that combines the fzf UI with atuin for search management.  I have changed it slightly; by default it restricts the search to the current directory only, but a second <code>control-r</code> will search the entire history.</p>
<div class="src src-sh">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">atuin-setup<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> ! which atuin <span class="p">&amp;</span>&gt; /dev/null<span class="p">;</span> <span class="k">then</span> <span class="k">return</span> 1<span class="p">;</span> <span class="k">fi</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># bindkey &#39;^E&#39; _atuin_search_widget</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nb">export</span> <span class="nv">ATUIN_NOBIND</span><span class="o">=</span><span class="s2">&#34;true&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="nb">eval</span> <span class="s2">&#34;</span><span class="k">$(</span>atuin init zsh<span class="k">)</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">    fzf-atuin-history-widget<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">        <span class="nb">local</span> selected num
</span></span><span class="line"><span class="cl">        setopt localoptions noglobsubst noposixbuiltins pipefail no_aliases 2&gt;/dev/null
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="c1"># local atuin_opts=&#34;--cmd-only --limit ${ATUIN_LIMIT:-5000}&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="nb">local</span> <span class="nv">atuin_opts</span><span class="o">=</span><span class="s2">&#34;--cmd-only&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="nb">local</span> <span class="nv">fzf_opts</span><span class="o">=(</span>
</span></span><span class="line"><span class="cl">            --height<span class="o">=</span><span class="si">${</span><span class="nv">FZF_TMUX_HEIGHT</span><span class="k">:-</span><span class="nv">40</span><span class="p">%</span><span class="si">}</span>
</span></span><span class="line"><span class="cl">            --tac
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;-n2..,..&#34;</span>
</span></span><span class="line"><span class="cl">            --tiebreak<span class="o">=</span>index
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;--query=</span><span class="si">${</span><span class="nv">LBUFFER</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;+m&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;--bind=ctrl-d:reload(atuin search </span><span class="nv">$atuin_opts</span><span class="s2"> -c </span><span class="nv">$PWD</span><span class="s2">),ctrl-r:reload(atuin search </span><span class="nv">$atuin_opts</span><span class="s2">)&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="o">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="nv">selected</span><span class="o">=</span><span class="k">$(</span>
</span></span><span class="line"><span class="cl">            <span class="nb">eval</span> <span class="s2">&#34;atuin search </span><span class="si">${</span><span class="nv">atuin_opts</span><span class="si">}</span><span class="s2"> -c </span><span class="nv">$PWD</span><span class="s2">&#34;</span> <span class="p">|</span>
</span></span><span class="line"><span class="cl">                fzf <span class="s2">&#34;</span><span class="si">${</span><span class="nv">fzf_opts</span><span class="p">[@]</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">                <span class="k">)</span>
</span></span><span class="line"><span class="cl">        <span class="nb">local</span> <span class="nv">ret</span><span class="o">=</span><span class="nv">$?</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="o">[</span> -n <span class="s2">&#34;</span><span class="nv">$selected</span><span class="s2">&#34;</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">            <span class="c1"># the += lets it insert at current pos instead of replacing</span>
</span></span><span class="line"><span class="cl">            <span class="nv">LBUFFER</span><span class="o">+=</span><span class="s2">&#34;</span><span class="si">${</span><span class="nv">selected</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="k">fi</span>
</span></span><span class="line"><span class="cl">        zle reset-prompt
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="nv">$ret</span>
</span></span><span class="line"><span class="cl">    <span class="o">}</span>
</span></span><span class="line"><span class="cl">    zle -N fzf-atuin-history-widget
</span></span><span class="line"><span class="cl">    bindkey <span class="s1">&#39;^R&#39;</span> fzf-atuin-history-widget
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">atuin-setup</span></span></code></pre></div>
</div>
<p>
This &#34;toggle between directory and global history&#34; feature is something I&#39;ve been using in zsh via the <a href="https://github.com/jimhester/per-directory-history/">per-directory-history</a> plugin.  Atuin does have a history-import feature, but not surprisingly it doesn&#39;t work with the per-directory-history which is in a different format.  I wrote a little python snippet (below) to handle this.  The gist is that per-directory-history keeps a separate history file for each directory, where the directory tree is mirrored under a separate directory in your home: for example if you run a command in <code>/var/log/httpd</code>, it would go into the file <code class="verbatim">~/.directory_history/var/log/httpd/history</code>.  Most of the rest of the metadata we have to fake or guess (or in the case of timestamp resolution, adjust).  You may need to tweak to your situation, and I&#39;ve elided a few non-essential bits, but hopefully it helps someone!</p>
<div class="src src-python">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl">  <span class="kn">import</span> <span class="nn">os</span>
</span></span><span class="line"><span class="cl">  <span class="kn">import</span> <span class="nn">os.path</span>
</span></span><span class="line"><span class="cl">  <span class="kn">import</span> <span class="nn">sqlite3</span>
</span></span><span class="line"><span class="cl">  <span class="kn">import</span> <span class="nn">sys</span>
</span></span><span class="line"><span class="cl">  <span class="kn">import</span> <span class="nn">uuid</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="k">def</span> <span class="nf">load_history</span><span class="p">(</span><span class="n">fpath</span><span class="p">,</span> <span class="n">session</span><span class="p">,</span> <span class="n">hostname</span><span class="p">,</span> <span class="n">hist_dir</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">      <span class="n">history</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl">      <span class="n">cwd</span> <span class="o">=</span> <span class="n">fpath</span><span class="o">.</span><span class="n">removeprefix</span><span class="p">(</span><span class="n">hist_dir</span><span class="p">)</span><span class="o">.</span><span class="n">removesuffix</span><span class="p">(</span><span class="s1">&#39;/history&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;Using cwd </span><span class="si">{</span><span class="n">cwd</span><span class="si">}</span><span class="s1">&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="n">lastcmd</span> <span class="o">=</span> <span class="s1">&#39;&#39;</span>
</span></span><span class="line"><span class="cl">      <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">fpath</span><span class="p">,</span> <span class="s1">&#39;r&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">          <span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="nb">iter</span><span class="p">(</span><span class="n">f</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">              <span class="k">try</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                  <span class="k">while</span> <span class="n">line</span><span class="o">.</span><span class="n">strip</span><span class="p">()[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s1">&#39;</span><span class="se">\\</span><span class="s1">&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                      <span class="n">line</span> <span class="o">+=</span> <span class="nb">next</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                  <span class="n">line</span> <span class="o">=</span> <span class="n">line</span><span class="o">.</span><span class="n">lstrip</span><span class="p">(</span><span class="s1">&#39;: &#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                  <span class="n">tss</span><span class="p">,</span> <span class="n">line</span> <span class="o">=</span> <span class="n">line</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;:&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                  <span class="n">_</span><span class="p">,</span><span class="n">cmd</span> <span class="o">=</span> <span class="n">line</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;;&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                  <span class="k">if</span> <span class="n">cmd</span> <span class="o">!=</span> <span class="n">lastcmd</span><span class="p">:</span> <span class="c1"># Ignore dups, since the timestamp doesn&#39;t always have enough resolution</span>
</span></span><span class="line"><span class="cl">                      <span class="n">history</span><span class="o">.</span><span class="n">append</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">                          <span class="s2">&#34;id&#34;</span><span class="p">:</span> <span class="n">uuid</span><span class="o">.</span><span class="n">uuid4</span><span class="p">()</span><span class="o">.</span><span class="n">hex</span><span class="p">,</span>        <span class="c1"># id</span>
</span></span><span class="line"><span class="cl">                          <span class="s2">&#34;timestamp&#34;</span><span class="p">:</span> <span class="nb">int</span><span class="p">(</span><span class="n">tss</span><span class="p">)</span> <span class="o">*</span> <span class="mf">1e9</span><span class="p">,</span>   <span class="c1"># timestamp</span>
</span></span><span class="line"><span class="cl">                          <span class="s2">&#34;duration&#34;</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>                 <span class="c1"># duration</span>
</span></span><span class="line"><span class="cl">                          <span class="s2">&#34;exit&#34;</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>                     <span class="c1"># exit</span>
</span></span><span class="line"><span class="cl">                          <span class="s2">&#34;command&#34;</span><span class="p">:</span> <span class="n">cmd</span><span class="p">,</span>                <span class="c1"># command</span>
</span></span><span class="line"><span class="cl">                          <span class="s2">&#34;cwd&#34;</span><span class="p">:</span> <span class="n">cwd</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                          <span class="s2">&#34;session&#34;</span><span class="p">:</span> <span class="n">session</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                          <span class="s2">&#34;hostname&#34;</span><span class="p">:</span> <span class="n">hostname</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                      <span class="p">})</span>
</span></span><span class="line"><span class="cl">                      <span class="n">lastcmd</span> <span class="o">=</span> <span class="n">cmd</span>
</span></span><span class="line"><span class="cl">              <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                  <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;Error: </span><span class="si">{</span><span class="n">e</span><span class="si">}</span><span class="s1">&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="k">return</span> <span class="n">history</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">INSERT_SQL</span> <span class="o">=</span> <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="cl"><span class="s2">  insert into history (id, timestamp, duration, exit, command, cwd, session, hostname)
</span></span></span><span class="line"><span class="cl"><span class="s2">  values (:id, :timestamp, :duration, :exit, :command, :cwd, :session, :hostname)
</span></span></span><span class="line"><span class="cl"><span class="s2">  &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="k">def</span> <span class="nf">main</span><span class="p">(</span><span class="n">basedir</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">      <span class="n">basedir</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">expanduser</span><span class="p">(</span><span class="n">basedir</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="n">basedir</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">realpath</span><span class="p">(</span><span class="n">basedir</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;Using basedir: </span><span class="si">{</span><span class="n">basedir</span><span class="si">}</span><span class="s1">&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="n">db</span> <span class="o">=</span> <span class="n">sqlite3</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="s1">&#39;history.db&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="n">cur</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">cursor</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="n">session</span> <span class="o">=</span> <span class="n">uuid</span><span class="o">.</span><span class="n">uuid4</span><span class="p">()</span><span class="o">.</span><span class="n">hex</span>
</span></span><span class="line"><span class="cl">      <span class="n">hostname</span> <span class="o">=</span> <span class="s1">&#39;hostname:username&#39;</span> <span class="c1"># update as necessary</span>
</span></span><span class="line"><span class="cl">      <span class="k">for</span> <span class="n">dirpath</span><span class="p">,</span> <span class="n">_dirnames</span><span class="p">,</span> <span class="n">filenames</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">walk</span><span class="p">(</span><span class="n">basedir</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">          <span class="nb">print</span><span class="p">(</span><span class="n">dirpath</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">          <span class="k">if</span> <span class="s1">&#39;history&#39;</span> <span class="ow">in</span> <span class="n">filenames</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">              <span class="n">history</span> <span class="o">=</span> <span class="n">load_history</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">dirpath</span><span class="p">,</span> <span class="s1">&#39;history&#39;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">                                     <span class="n">session</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                                     <span class="n">hostname</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                                     <span class="n">basedir</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">              <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;Loaded </span><span class="si">{</span><span class="nb">len</span><span class="p">(</span><span class="n">history</span><span class="p">)</span><span class="si">}</span><span class="s1"> commands&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">              <span class="n">cur</span><span class="o">.</span><span class="n">executemany</span><span class="p">(</span><span class="n">INSERT_SQL</span><span class="p">,</span> <span class="n">history</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="n">db</span><span class="o">.</span><span class="n">commit</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">      <span class="n">db</span><span class="o">.</span><span class="n">close</span><span class="p">()</span></span></span></code></pre></div>
</div>
<div class="footnotes">
<hr class="footnotes-separatator">
<div class="footnote-definitions">
<div class="footnote-definition">
<sup id="footnote-1"><a href="#footnote-reference-1">1</a></sup>
<div class="footnote-body">
<p>In full disclaimer, it may have improved or changed, and I probably didn&#39;t spend a <em>lot</em> of time testing it.  That&#39;s not what this post is about anyway!</p>
</div>
</div>
</div>
</div>
]]></content>
		</item>
		
		<item>
			<title>TIL: yasnippets and .yas-parents</title>
			<link>https://blog.markhepburn.com/posts/til-yas-parents/</link>
			<pubDate>Sat, 22 Jul 2023 21:15:38 +1000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/til-yas-parents/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>
As Emacs <a href="https://blog.markhepburn.com/posts/experimenting-with-the-built-in-treesitter-support-in-emacs/">treesitter support</a> matures, I&#39;ve been adopting more and more of the built-in converted modes, for example <code class="verbatim">python-ts-mode</code> in place of <code class="verbatim">python-mode</code>, etc.  There&#39;s a <a href="https://www.masteringemacs.org/article/how-to-get-started-tree-sitter">great article</a> at <code class="verbatim">masteringemacs.org</code> on the process, but essentially you can specify that when <code class="verbatim">python-mode</code> <em>would</em> have been invoked, you should instead use <code class="verbatim">python-ts-mode</code>.</p>
<p>
This is not copmletely transparent; in particular, hooks defined for the old <code class="verbatim">python-mode</code> don&#39;t automatically run for <code class="verbatim">python-ts-mode</code> as well.</p>
<p>
The other day I found another omission, albeit with a fairly unobtrusive workaround.  I use the <a href="https://github.com/joaotavora/yasnippet">yasnippet</a> package for snippets<sup class="footnote-reference"><a id="footnote-reference-1" href="#footnote-1">1</a></sup>, and mostly rely on the <a href="https://github.com/AndreaCrotti/yasnippet-snippets/">yasnippet-snippets</a> predefined collection.  These are grouped by modes, and… not surprisingly a snippet defined in <code class="verbatim">python-mode</code> does not automatically become available in <code class="verbatim">python-ts-mode</code>.</p>
<p>
However — this examples assumes that you also load <code class="verbatim">~/.emacs.d/snippets/</code> — if you add a file <code class="verbatim">~/.emacs.d/snippets/python-ts-mode/.yas-parents</code>, containing the single line &#34;<code class="verbatim">python-mode</code>&#34;, then all snippets defined in <code class="verbatim">python-mode</code> will also be loaded and available in <code class="verbatim">python-ts-mode</code>.</p>
<p>
(prompted by <a href="https://fosstodon.org/@markhepburn/110722754115381866">this toot</a>)</p>
<div class="footnotes">
<hr class="footnotes-separatator">
<div class="footnote-definitions">
<div class="footnote-definition">
<sup id="footnote-1"><a href="#footnote-reference-1">1</a></sup>
<div class="footnote-body">
<p>For eg, in Python I can type <code class="verbatim">init</code> followed by <code class="verbatim">&lt;TAB&gt;</code>, and get a complete skeleton for <code class="verbatim">def __init__</code>, with the cursor in the right place etc.</p>
</div>
</div>
</div>
</div>
]]></content>
		</item>
		
		<item>
			<title>TIL: pmap</title>
			<link>https://blog.markhepburn.com/posts/til-pmap/</link>
			<pubDate>Sun, 09 Jul 2023 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/til-pmap/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>
The other day I was working on a Java application deployment, experimenting with some claimed performance improvements by installing native image libraries.</p>
<p>
I wanted to see if the native library was actually being loaded, and my first thought was &#34;this is a job for <code>strace -e trace=open</code>&#34;!  (reference: <a href="https://jvns.ca/categories/strace/">the always-excellent Julia Evans</a>.  You should go read those even if you don&#39;t read any further here).</p>
<p>
Something made me search first though, and what I actually discovered was the <a href="https://www.geeksforgeeks.org/pmap-command-in-linux-with-examples/"><code>pmap</code> command</a>, which can tell you exactly what file(s) are mapped (the <code>-p</code> is for &#34;path&#34;, not &#34;pid&#34;):</p>
<div class="src src-sh">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">pmap -p &lt;pid&gt;</span></span></code></pre></div>
</div>
<p>
It turns out that this is also exactly the contents of the <code>ls -l /proc/&lt;pid&gt;/map_files</code>, or <code>cat /proc/&lt;pid&gt;maps</code>.</p>
<p>
(Note that it is not the same as my original strace plan, which was to look for the library being <em>opened</em>; this shows files that are mmap-ed into the process)</p>
<p>
To test it out, I grabbed the <code>mmap</code> example from the man page, added a <code>getchar()</code> call to keep the process running, and ran it:</p>
<div class="src src-c">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;sys/mman.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;sys/stat.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;fcntl.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;unistd.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="cp">#define handle_error(msg)                                       \
</span></span></span><span class="line"><span class="cl"><span class="cp">        do { perror(msg); exit(EXIT_FAILURE); } while (0)
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="kt">char</span> <span class="o">*</span><span class="n">addr</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="kt">int</span> <span class="n">fd</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">struct</span> <span class="n">stat</span> <span class="n">sb</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="kt">off_t</span> <span class="n">offset</span><span class="p">,</span> <span class="n">pa_offset</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="kt">size_t</span> <span class="n">length</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="kt">ssize_t</span> <span class="n">s</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">argc</span> <span class="o">&lt;</span> <span class="mi">3</span> <span class="o">||</span> <span class="n">argc</span> <span class="o">&gt;</span> <span class="mi">4</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="nf">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#34;%s file offset [length]</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">argv</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">                <span class="nf">exit</span><span class="p">(</span><span class="n">EXIT_FAILURE</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="n">fd</span> <span class="o">=</span> <span class="nf">open</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">O_RDONLY</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                <span class="nf">handle_error</span><span class="p">(</span><span class="s">&#34;open&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="nf">fstat</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">sb</span><span class="p">)</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>           <span class="cm">/* To obtain file size */</span>
</span></span><span class="line"><span class="cl">                <span class="nf">handle_error</span><span class="p">(</span><span class="s">&#34;fstat&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="n">offset</span> <span class="o">=</span> <span class="nf">atoi</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">        <span class="n">pa_offset</span> <span class="o">=</span> <span class="n">offset</span> <span class="o">&amp;</span> <span class="o">~</span><span class="p">(</span><span class="nf">sysconf</span><span class="p">(</span><span class="n">_SC_PAGE_SIZE</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="cm">/* offset for mmap() must be page aligned */</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">offset</span> <span class="o">&gt;=</span> <span class="n">sb</span><span class="p">.</span><span class="n">st_size</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="nf">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#34;offset is past end of file</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">                <span class="nf">exit</span><span class="p">(</span><span class="n">EXIT_FAILURE</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">argc</span> <span class="o">==</span> <span class="mi">4</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="n">length</span> <span class="o">=</span> <span class="nf">atoi</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">3</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">                <span class="k">if</span> <span class="p">(</span><span class="n">offset</span> <span class="o">+</span> <span class="n">length</span> <span class="o">&gt;</span> <span class="n">sb</span><span class="p">.</span><span class="n">st_size</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                        <span class="n">length</span> <span class="o">=</span> <span class="n">sb</span><span class="p">.</span><span class="n">st_size</span> <span class="o">-</span> <span class="n">offset</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                <span class="cm">/* Can&#39;t display bytes past end of file */</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>    <span class="cm">/* No length arg ==&gt; display to end of file */</span>
</span></span><span class="line"><span class="cl">                <span class="n">length</span> <span class="o">=</span> <span class="n">sb</span><span class="p">.</span><span class="n">st_size</span> <span class="o">-</span> <span class="n">offset</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="n">addr</span> <span class="o">=</span> <span class="nf">mmap</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span> <span class="n">length</span> <span class="o">+</span> <span class="n">offset</span> <span class="o">-</span> <span class="n">pa_offset</span><span class="p">,</span> <span class="n">PROT_READ</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                    <span class="n">MAP_PRIVATE</span><span class="p">,</span> <span class="n">fd</span><span class="p">,</span> <span class="n">pa_offset</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">addr</span> <span class="o">==</span> <span class="n">MAP_FAILED</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                <span class="nf">handle_error</span><span class="p">(</span><span class="s">&#34;mmap&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="n">s</span> <span class="o">=</span> <span class="nf">write</span><span class="p">(</span><span class="n">STDOUT_FILENO</span><span class="p">,</span> <span class="n">addr</span> <span class="o">+</span> <span class="n">offset</span> <span class="o">-</span> <span class="n">pa_offset</span><span class="p">,</span> <span class="n">length</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">s</span> <span class="o">!=</span> <span class="n">length</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="k">if</span> <span class="p">(</span><span class="n">s</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                        <span class="nf">handle_error</span><span class="p">(</span><span class="s">&#34;write&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">                <span class="nf">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#34;partial write&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">                <span class="nf">exit</span><span class="p">(</span><span class="n">EXIT_FAILURE</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="k">while</span><span class="p">(</span><span class="nf">getchar</span><span class="p">()</span><span class="o">!=</span><span class="sc">&#39;\n&#39;</span><span class="p">);</span> <span class="cm">/* ADDED: Wait to exit */</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="nf">munmap</span><span class="p">(</span><span class="n">addr</span><span class="p">,</span> <span class="n">length</span> <span class="o">+</span> <span class="n">offset</span> <span class="o">-</span> <span class="n">pa_offset</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="nf">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="nf">exit</span><span class="p">(</span><span class="n">EXIT_SUCCESS</span><span class="p">);</span> <span class="p">}</span></span></span></code></pre></div>
</div>
<p>
Running:</p>
<div class="src src-sh">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">$ gcc maptest.c
</span></span><span class="line"><span class="cl">$ ./a.out maptest.c <span class="m">5</span></span></span></code></pre></div>
</div>
<p>
while this is running, in another terminal:</p>
<div class="src src-sh">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl"><span class="nv">PID</span><span class="o">=</span><span class="k">$(</span>pgrep a.out<span class="k">)</span>
</span></span><span class="line"><span class="cl">pmap -p <span class="nv">$PID</span></span></span></code></pre></div>
</div>
<p>
and sure enough, there&#39;s our file mapped into the process&#39; memory.</p>
]]></content>
		</item>
		
		<item>
			<title>Experimenting With the Built-in Tree-sitter Support in Emacs</title>
			<link>https://blog.markhepburn.com/posts/experimenting-with-the-built-in-treesitter-support-in-emacs/</link>
			<pubDate>Sun, 04 Dec 2022 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/experimenting-with-the-built-in-treesitter-support-in-emacs/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>
<em>Update: 22nd January:</em>
<em>As a commenter implies, things are in a fair bit of flux still.  I have been following development and while the existing treesit-enabled modes are bare-bones, new hooks and variables are being added all the time.  You are unlikely to want to completely switch at this stage,  but the future is very promising.</em></p>
<p>
<em>The following posts are a great place to start: <a href="https://archive.casouri.cc/note/2023/tree-sitter-in-emacs-29/">overview</a>, note in particular <code>major-mode-remap-alist</code>, <a href="https://archive.casouri.cc/note/2023/tree-sitter-starter-guide/">details</a>.</em></p>
<p>
<em>For another example of what can be unlocked, check out this <a href="https://github.com/casouri/lunarymacs/blob/eb6897d11e7849b7e8d131adeea82dc35223e4e9/site-lisp/expreg.el">minimalist expand-region replacement</a>.</em></p>
<p>
A quick post today, mostly my working notes.</p>
<p>
I have a Friday habit of building Emacs from the master branch, and
reading the additions to <code>etc/NEWS</code><sup class="footnote-reference"><a id="footnote-reference-1" href="#footnote-1">1</a></sup>. The last few years have
been particularly active, with support for built-in LSP (via eglot),
native compilation, improved long-lines performance, etc.</p>
<p>
The biggest news recently has been the incorporation of treesitter
support. This has already been available <a href="https://github.com/emacs-tree-sitter/elisp-tree-sitter">via dynamic modules</a>, but is
now available natively, with a bunch of language modes updated with
support for it as well. I won&#39;t dwell on what treesitter is, but
benefits include much improved font-lock and <a href="https://github.com/emacs-tree-sitter/ts-fold">code-folding</a> support and
the potential for semantic navigation, etc.</p>
<p>
I wanted to try this out, but because tree-sitter itself is an
external library, and new enough not to be available in my
distribution&#39;s package manager, it requires a bit more leg-work.
Because I&#39;m just experimenting (and don&#39;t use an immutable
distribution<sup class="footnote-reference"><a id="footnote-reference-2" href="#footnote-2">2</a></sup>), I didn&#39;t fancy installing the library, so had a
few more hoops to add and jump through. More detailed notes are
available <a href="https://git.savannah.gnu.org/cgit/emacs.git/tree/admin/notes/tree-sitter/starter-guide">here</a>.</p>
<ol>
<li><code>git clone https://github.com/tree-sitter/tree-sitter</code></li>
<li><code>cd tree-sitter; make all</code></li>
<li>Now we need to configure Emacs <code>--with-tree-sitter</code>, <em>but</em> because it&#39;s
not installed we need to tell it the library to link against (and
where to find it), and where to find the dev headers.  Ignoring
other options<sup class="footnote-reference"><a id="footnote-reference-3" href="#footnote-3">3</a></sup>, for me this looks like <code>TREE_SITTER_CFLAGS=-I~/Projects/tree-sitter/lib/include TREE_SITTER_LIBS=&#34;-L~/Projects/tree-sitter -ltree-sitter&#34; ./configure  --with-tree-sitter</code></li>
<li>Now, that&#39;s dynamically linked, so to <em>run</em> it we still need to
modify the environment so it can find the library:
<code>LD_LIBRARY_PATH=~/Projects/tree-sitter ~/Projects/emacs/src/emacs</code>
<em>Update: I now also needed <code>LD_LIBRARY_PATH</code> set to <strong>build</strong> as well, because building involves starting a bare-bones Emacs in order to dump.  Not sure if I missed this earlier, or the build process has changed</em>.</li>
</ol>
<p>Now you have an Emacs with built-in support, and you can verify by
evaluating <code>(treesit-available-p)</code>, but it doesn&#39;t get you very far
because the language-specific information is still missing. To see
this, open a supported mode, say a javascript file, and run <code>M-x
js-ts-mode</code>. You will probably see a warning like <em>&#34;Cannot activate tree-sitter, because language definition for javascript is unavailable (not-found): (libtree-sitter-javascript libtree-sitter-javascript.so) No such file or directory&#34;</em>.</p>
<p>
To resolve this we need the language-specific modules (the equivalent
of <a href="https://github.com/emacs-tree-sitter/tree-sitter-langs">https://github.com/emacs-tree-sitter/tree-sitter-langs</a> for the
dynamic-module project), which you can obtain from
<a href="https://github.com/casouri/tree-sitter-module/.">https://github.com/casouri/tree-sitter-module/.</a> These can either be
built, or just downloaded from the releases; you can extract them into
<code>/.emacs.d/tree-sitter</code> (see variable <code>treesit-extra-load-path</code> for
details or customisation). Now if you try again — no restart
necessary — your new mode should load successfully!</p>
<p>
So far I haven&#39;t observed any issues from having both the built-in and
the dynamic-module support. You will see that the built-in support
uses the prefix <code>treesit-</code> while the third-party package uses
<code>tree-sitter-</code>. The updated modes contain <code>-ts-</code>, eg <code>python-ts-mode</code>,
<code>js-ts-mode</code>, etc.</p>
<div class="footnotes">
<hr class="footnotes-separatator">
<div class="footnote-definitions">
<div class="footnote-definition">
<sup id="footnote-1"><a href="#footnote-reference-1">1</a></sup>
<div class="footnote-body">
<p>My git alias <code>dlp = diff ORIG_HEAD..FETCH_HEAD</code> is handy here.</p>
</div>
</div>
<div class="footnote-definition">
<sup id="footnote-2"><a href="#footnote-reference-2">2</a></sup>
<div class="footnote-body">
<p><a href="https://nixos.org/"><a href="https://nixos.org/">https://nixos.org/</a></a>, <a href="https://guix.gnu.org/"><a href="https://guix.gnu.org/">https://guix.gnu.org/</a></a></p>
</div>
</div>
<div class="footnote-definition">
<sup id="footnote-3"><a href="#footnote-reference-3">3</a></sup>
<div class="footnote-body">
<p>My full line is: <code>TREE_SITTER_CFLAGS=-I~/Projects/tree-sitter/lib/include TREE_SITTER_LIBS=&#34;-L~/Projects/tree-sitter -ltree-sitter&#34; ./configure  --with-native-compilation --without-mailutils --with-json --with-xwidgets --with-xinput --with-tree-sitter</code></p>
</div>
</div>
</div>
</div>
]]></content>
		</item>
		
		<item>
			<title>Finally Getting LVM</title>
			<link>https://blog.markhepburn.com/posts/finally-getting-lvm/</link>
			<pubDate>Sun, 06 Nov 2022 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/finally-getting-lvm/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[
<p>
I&#39;ve used LVM – Linux&#39;s &#34;Logical Volume Manager&#34; – before. Intuitively it
makes sense, and is almost-magically awesome: you can take a bunch of
separate disks, and represent them as one big disk! Not only that, you
can later add more disks to make an even bigger virtual disk,
completely transparently.</p>
<p>
Previously all I&#39;ve done is follow some instructions and type out a
few commands. Actually <em>understanding</em> what I was doing beyond the
rough concepts was a different thing. The commands, and there are
plenty, have names like <code>pvcreate</code> and <code>lvconvert</code>, which were
completely unfamiliar and after a short search which got bogged down
in terminology, I moved on.</p>
<p>
The third time I resolved to actually dig in just a bit more, and
happily the terminology at least now makes more sense!  The key for me
was the high-level hierarchy, and secondly the similar structure of
the commands (once the intuitive concepts made a bit more sense).</p>
<p>

<figure><picture>
          <source srcset="/images/lvm-intro_hu400fb0219609710ae091aa4914f43dd5_90176_1242x848_fit_q75_h2_box_3.webp" type="image/webp">
          <source srcset="/images/lvm-intro_hu400fb0219609710ae091aa4914f43dd5_90176_1242x848_fit_q75_bgffffff_box_3.jpg" type="image/jpeg">
          <img src="/images/lvm-intro_hu400fb0219609710ae091aa4914f43dd5_90176_1242x848_fit_q75_h2_box_3.webp"  width="1242"  height="848" />
        </picture></figure></p>
<ul>
<li>Physical Volumes:  These are the disks themselves<sup class="footnote-reference"><a id="footnote-reference-1" href="#footnote-1">1</a></sup>.  Commands
all use the <code>pv</code> prefix.</li>
<li>Volume Groups: These create a storage pool out of the physical
volumes; every virtual disk is drawn from a single volume group.
Commands all use the <code>vg</code> prefix.</li>
<li>Logical Volumes: These are the &#34;virtual disks&#34; that you mount as a
single block device.  This is what gets mounted in the server&#39;s file
system.  Commands all use the <code>lv</code> prefix.</li>
</ul>
<div id="outline-container-headline-1" class="outline-3">
<h3 id="headline-1">
Simple operations
</h3>
<div id="outline-text-headline-1" class="outline-text-3">
<p>
This isn&#39;t intended to be a tutorial, but once I had absorbed the
high-level concepts, there&#39;s a certain uniformity to the commands and
they become less mysterious.  Check the man pages or an actual
tutorial for the necessary options.</p>
<p>
<strong>Creating:</strong> <code>pvcreate</code> creates (registers?) a physical volume;
<code>vgcreate</code> creates a volume group; <code>lvcreate</code> creates your logical
volume.</p>
<p>
<strong>Listing:</strong> In a nod to <code>ls</code> — <code>pvs</code> to list physical volumes;
<code>vgs</code><sup class="footnote-reference"><a id="footnote-reference-2" href="#footnote-2">2</a></sup></p>
<p>
<strong>Extending:</strong> You may also be interested later in adding more storage.
This will involve <code>vgextend</code> to add another physical volume to your
logical volume, then <code>lvextend</code> to increase the size of the logical
volume.</p>
</div>
</div>
<div id="outline-container-headline-2" class="outline-3">
<h3 id="headline-2">
Questions I still have
</h3>
<div id="outline-text-headline-2" class="outline-text-3">
<p>
The main thing I don&#39;t understand is where the metadata exists: how
does LVM retain information about what groups, etc it has?  I suspect
it is in the <code>/dev</code> file system, but I&#39;m guessing beyond that.</p>
<p>
I suspect there has been some changes in either convention or
operation.  When you create a logical volume <code>lv1</code> in a volume group
<code>vg00</code>, it seems it can be accessed at either <code>/dev/mapper/vg00-lv1</code>
<em>or</em> <code>/dev/vg00/lv1</code>.  In fact in the system I just tested, both were
symlinks to (for me) <code>/dev/dm-1</code>.</p>
</div>
</div>
<div class="footnotes">
<hr class="footnotes-separatator">
<div class="footnote-definitions">
<div class="footnote-definition">
<sup id="footnote-1"><a href="#footnote-reference-1">1</a></sup>
<div class="footnote-body">
<p>I think partitions can also be used.</p>
</div>
</div>
<div class="footnote-definition">
<sup id="footnote-2"><a href="#footnote-reference-2">2</a></sup>
<div class="footnote-body">
<p>Probably won&#39;t affect you, but on this machine — courtesy of
an <a href="https://ohmyz.sh/">oh-my-zsh</a> plugin — <code>vgs</code> is actually aliased to <code>vagrant
global-status</code>!</p>
</div>
</div>
</div>
</div>
]]></content>
		</item>
		
		<item>
			<title>On Competent Elites</title>
			<link>https://blog.markhepburn.com/posts/on-competent-elites/</link>
			<pubDate>Mon, 24 Oct 2022 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/on-competent-elites/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>
<em>I have no idea where this post is going.</em></p>
<p>
&#34;Imposter syndrome&#34; can feel like something designed to make you feel
better as long as you don&#39;t look too closely under the covers: &#34;smart
people often feel like imposters&#34; does not, unfortunately, imply that
if you feel like an imposter then you must in fact be competent.</p>
<p>
The other day I came across one of those articles that skewers
directly to your soul, specifically targeting those deep
insecurities! It was via a <a href="https://twitter.com/ID_AA_Carmack/status/1582578724087554053">tweet from John Carmack</a>, referencing an
<a href="https://www.lesswrong.com/posts/CKpByWmsZ8WmpHtYa/competent-elites">article on lesswrong.com</a>:</p>
<blockquote>
<p>Even so, these people of the Power Elite <em>were visibly much smarter
than average mortals</em>. In conversation they spoke quickly, sensibly,
and by and large intelligently. When talk turned to deep and difficult
topics, they understood faster, made fewer mistakes, were readier to
adopt others&#39; suggestions.</p>
<p>
No, even worse than that, much worse than that: these CEOs and CTOs
and hedge-fund traders, these folk of the mid-level power elite,
seemed <em>happier</em> and <em>more alive</em>.</p>
<p>
This, I suspect, is one of those truths so horrible that you can&#39;t
talk about it in public. This is something that reporters must not
write about, when they visit gatherings of the power elite.</p>
<p>
Because the <em>last</em> news your readers want to hear, is that this person
who is wealthier than you, is also smarter, happier, and not a bad
person morally. Your reader would <em>much</em> rather read about how these
folks are overworked to the bone or suffering from existential ennui.</p>
</blockquote>
<p>
In some ways the last time I remember feeling so confronted, as if the
author were focussing on me particularly across a crowded room and
pointing out <em>that thing</em> you were feeling awkward about, was Neal
Stephenson&#39;s Snow Crash:</p>
<blockquote>
<p>Until a man is twenty-five, he still thinks, every so often, that
under the right circumstances he could be the baddest motherfucker in
the world. If I moved to a martial-arts monastery in China and studied
real hard for ten years. if my family was wiped out by Colombian drug
dealers and I swore myself to revenge. If I got a fatal disease, had
one year to live, devoted it to wiping out street crime. If I just
dropped out and devoted my life to being bad. Hiro used to feel that
way, too, but then he ran into Raven. In a way, this is liberating. He
no longer has to worry about trying to be the baddest motherfucker in
the world. The position is taken.</p>
</blockquote>
<p>
I first read that when I was 23. I was a gym junkie and martial artist
(albeit, starting to realise I might never be Bruce Lee), and with
just enough budding awareness to realise that I was exactly the sort
of person he was talking to, and that he was 100% right.</p>
<p>
It is possible that the rest of your life is determined, in some ways
at least, by what you do with that realisation. Do you pack it in once
it is obvious you&#39;ll never be the best; do you keep switching paths
searching for something you <em>might</em> be the best at (or at least,
switching frequently enough to plausibly claim that perhaps you could
have been if only you had kept going); or are you comfortable enough
to be <em>your</em> best?</p>
<p>
I think by and large I settled on the last option. If anything, I
became a little <em>too</em> comfortable. This can manifest as abrogating
responsibility: I followed the training program and did everything I
was supposed to do, so if I&#39;m not great it&#39;s just because I was never
going to be and that&#39;s ok.</p>
<p>
(To be clear, it <em>is</em> ok, particularly if you&#39;re ok with it, but there
is still the nagging realisation that anything beyond satisfactory
requires some amount — possibly lots — of perseverance through
sticking points and plateaus, and perhaps just a little bit of
stubborness and foolhardy desire will get you through. Stuhlberg and
Magness cover just this contradiction in <a href="http://www.stevemagness.com/books/">The Passion Paradox</a>).</p>
<p>
My whole life has basically been assuming that I could, to a point,
outwork people or otherwise accomplish things I didn&#39;t seem talented
at, just by being persistent (&#34;showing up&#34;) and studying up on it. I
have obsessive-compulsive tendencies and enjoy the routine so this is
not a hair shirt I wear.</p>
<p>
I was never particularly good at chess, relative to others who spent
more sporadic time in the lunchtime chess room in high school, but I
played board 1 in the state high-school championship because I spent a
lot of time playing through games and learning opening lines. I was
never interested in endurance sports at all, and instead spent 25
years in the gym trying to get as strong as I could, but recently
became involved in ultra running purely because so much of it involves
simply putting in the hours<sup class="footnote-reference"><a id="footnote-reference-1" href="#footnote-1">1</a></sup>.</p>
<p>
So back to <em>Competent Elites</em>: the author is correct, it&#39;s a
confronting observation because we all know (and have probably seen)
the Peter Principal, and we often hear how the pursuit of money or
success is a Faustian bargain so contradictory evidence can make us
feel like we&#39;ve been lied to.</p>
<p>
That&#39;s actually not quite what the author is saying, on closer
examination. The two points I took away are that some types of job
(such as CEO) are <em>their own particular type of</em> difficult, and that
some people are more widely informed than others.</p>
<p>
Delving in a little, it seems entirely possible that the people he&#39;s
describing (CEOs, venture capitalists, and to simplify wildly, the
sort of people who get invited to those gatherings) are by necessity
smart and skilled in a particular way: of being widely read, and
connecting the dots, often on their feet. You could hypothesise that a
deep specialist such as <a href="https://www-cs-faculty.stanford.edu/~knuth/">Donald Knuth</a> would not seem as impressive in
this company, by the author&#39;s assumed definition.</p>
<p>
Having worked through that, possibly the reason this article struck a
nerve is simply the very personal realisation that it&#39;s easy to fall
too far on the &#34;good enough&#34; side. It&#39;s a timely kick-in-the-pants
that in my current career I might be better served studying more on
systems-thinking, since these days I don&#39;t find the time to specialise
much. It&#39;s also a reminder to assess how effective my current
practices are. For example, my chess improvement was limited because I
didn&#39;t actually <em>play</em> enough<sup class="footnote-reference"><a id="footnote-reference-2" href="#footnote-2">2</a></sup>, probably because ego got in the
way and it&#39;s easier to open another book. In general while I love
diving in and absorbing new topics, I often tend to focus on that
aspect instead of critically analysing or thinking of wider
implications, or sometimes even of exercising the new knowledge.</p>
<p>
All in all, I doubt I&#39;ll ever get invited to those parties, but I
enjoyed the thought-process the article prompted!</p>
<div class="footnotes">
<hr class="footnotes-separatator">
<div class="footnote-definitions">
<div class="footnote-definition">
<sup id="footnote-1"><a href="#footnote-reference-1">1</a></sup>
<div class="footnote-body">
<p>Also, if I&#39;m honest, I like that it&#39;s not purely about running
ability. I&#39;ll never have a fast road 10K time, but I can enjoy that
preparation takes you a long way, and when you&#39;re vomitting and still
have 50% to go that you can tough it out and keep going.</p>
</div>
</div>
<div class="footnote-definition">
<sup id="footnote-2"><a href="#footnote-reference-2">2</a></sup>
<div class="footnote-body">
<p>The boardgame Go has a proverb &#34;lose your first 100 games as
quickly as possible&#34;. I did not do this with Chess. (… or with Go).</p>
</div>
</div>
</div>
</div>
]]></content>
		</item>
		
		<item>
			<title>Isearch vs Ctrlf Mode</title>
			<link>https://blog.markhepburn.com/posts/isearch-vs-ctrlf-mode/</link>
			<pubDate>Sat, 24 Sep 2022 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/isearch-vs-ctrlf-mode/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[
<div id="outline-container-headline-1" class="outline-2">
<h2 id="headline-1">
or; why I still use isearch over ctrlf
</h2>
<div id="outline-text-headline-1" class="outline-text-2">
<p>
TL;DR: When you&#39;re in isearch-mode you can&#39;t use the usual editing
commands, but you <em>can</em> use <code>M-e</code> to edit the current search term.</p>
<div id="outline-container-headline-2" class="outline-3">
<h3 id="headline-2">
How I use isearch
</h3>
<div id="outline-text-headline-2" class="outline-text-3">
<p>
<a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Incremental-Search.html">isearch</a> is the basic search command built into Emacs. The &#34;i&#34; stands
for &#34;incremental&#34;; it starts searching as soon as you start typing,
and refines the search term as you keep typing. There are also
commands to search based on where your cursor starts out: to search
for occurences of the term under the cursor, to gradually add
successive words to the search term, etc. You initiate a search with
<code>control-s</code>, and successive <code>control-s</code> while searching jump to
successive matches of the term.</p>
<p>
A few subtle operational points make it a natural navigational aid:</p>
<ul>
<li>if you hit <code>ENTER</code> your cursor is left at the current term,
otherwise if you quit by <code>control-g</code> it returns the cursor back to
where you started, and</li>
<li>when you start a search, the mark is left at the start-point.</li>
</ul>
<p>My workflow then typically looks like:</p>
<ul>
<li>start a search with <code>control-s</code></li>
<li>Let&#39;s assume I&#39;m looking for some function, or want a quick reminder
of what I&#39;ve defined, so I search for &#34;defun&#34;</li>
<li>I keep hitting <code>control-s</code>, quickly looking at each one</li>
<li>
<p><em>Then:</em></p>
<ul>
<li>If I&#39;ve seen enough, I quit with <code>control-g</code> and I&#39;m back where I was.</li>
<li>If I want a more in-depth look, I stop searching with <code>ENTER</code>.
When I&#39;m finished, I can invoke <code>control-SPACE</code> to jump back to
where I was.</li>
</ul>
</li>
</ul>
</div>
</div>
<div id="outline-container-headline-3" class="outline-3">
<h3 id="headline-3">
What, and why, is ctrlf-mode?
</h3>
<div id="outline-text-headline-3" class="outline-text-3">
<p>
That all works great, and is so hard-wired that I don&#39;t even notice
the little inconsistences or iritations around the process!  The big
one is: it actually takes you outside of &#34;Emacs&#34; mode in a way.  That
is to say, once you start searching, you can&#39;t use your normal editing
commands to edit the search term.</p>
<p>
For example, say I start searching for the string &#34;save&#34;, but quickly
realise that there&#39;s a lot of these that I&#39;m not interested in, so I
<code>control-a</code> in order to go to the start of my term and refine it to eg
&#34;_save&#34;.</p>
<p>
This does not do what you expect! It actually quits your current
search, and jumps to the beginning of whichever line the cursor was
currently on. In other words, <code>isearch-mode</code> displays your term in the
minibuffer, but you can&#39;t otherwise operate on it as you normally
would.</p>
<p>
Most of the time I bump into this accidentally, curse and start again.</p>
<p>
Others with more agency over their environment did not accept the
status-quo however, and there is now a competing <a href="https://github.com/radian-software/ctrlf"><code>ctrlf-mode</code></a>. This
works much the same as <code>isearch</code>, but actually feels like more of a
first-class citizen of Emacs, because all your normal editing commands
operate as they should on your search term. When I grokked this, I
immediately switched.</p>
<p>
Strangely, the swiitch didn&#39;t take and I&#39;ve now reverted back to
vanilla <code>isearch</code>, paper-cuts and all. Why?</p>
</div>
</div>
<div id="outline-container-headline-4" class="outline-3">
<h3 id="headline-4">
One tiny inconvenience to keep my current workflow
</h3>
<div id="outline-text-headline-4" class="outline-text-3">
<p>
My chief problem is that my isearch workflow has accreted several
extensions over the years, which seemed to be incompatible with
<code>ctrlf-mode</code>, and to boot the nicer aspects of <code>isearch</code> aren&#39;t
replicated.</p>
<ul>
<li>The ability to add words (or characters, etc) <a href="https://github.com/radian-software/ctrlf/issues/65">is missing</a>.  I
realised I used these way more than I might have realised!</li>
<li>
<p>Because <code>ctrlf-mode</code> does actually use the minibuffer, it&#39;s possibly
harder to jump into other &#34;modal&#34; commands from it<sup class="footnote-reference"><a id="footnote-reference-1" href="#footnote-1">1</a></sup>. I use two such
examples in my regular workflow:</p>
<ul>
<li>Start searching, then use <code>control-&#39;</code> to immediately <a href="https://github.com/markhepburn/dotemacs/blob/ba22cf01bd09b311f8e07dfd018bc66e7308f0ec/lisp/custom-general.el#L257-L261">jump to my
desired location</a> via <code>avy-isearch</code></li>
<li>Start searching, then hit <code>meta-i</code> to <a href="https://github.com/markhepburn/dotemacs/blob/ba22cf01bd09b311f8e07dfd018bc66e7308f0ec/lisp/custom-selection.el#L97-L100">switch to <code>consult-line</code></a> for
an overview that I can fuzzily refine (<code>ctrlf-mode</code> does let you
switch to <code>occur-mode</code>, but this isn&#39;t as interactive).</li>
</ul>
</li>
</ul>
<p>Added up, I found I wasn&#39;t gaining enough benefit from the
improvements of <code>ctrlf-mode</code> to warrant keeping it — so, I finally
went looking for &#34;how to edit the isearch search-term&#34;: low and
behold, it&#39;s entirely possible and just needs to be invoked with the
command <code>M-e</code>!  Just hit <code>control-s</code> again, or <code>ENTER</code>, and you&#39;re
back to searching — not quite as smooth, but given the other
benefits above, more than enough for me.</p>
</div>
</div>
</div>
</div>
<div id="outline-container-headline-5" class="outline-2">
<h2 id="headline-5">
Footnotes
</h2>
</div>
<div class="footnotes">
<hr class="footnotes-separatator">
<div class="footnote-definitions">
<div class="footnote-definition">
<sup id="footnote-1"><a href="#footnote-reference-1">1</a></sup>
<div class="footnote-body">
<p>I haven&#39;t tried very hard to implement this, so perhaps it is
possible after all?  I haven&#39;t found examples either though, and it
doesn&#39;t seem to be a priority for the authors.</p>
</div>
</div>
</div>
</div>
]]></content>
		</item>
		
		<item>
			<title>Github and Infinite Builds</title>
			<link>https://blog.markhepburn.com/posts/github-and-infinite-builds/</link>
			<pubDate>Sun, 17 Jul 2022 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/github-and-infinite-builds/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[
<div id="outline-container-headline-1" class="outline-2">
<h2 id="headline-1">
I heard you like builds so I built inside my build
</h2>
<div id="outline-text-headline-1" class="outline-text-2">
<p>
There is very little educational value in this post, it&#39;s more just a
mea-culpa admission of guilt! TL;DR though I inadvertently managed to
create an infinite loop of builds in Github.</p>
<p>
The story begins not at work — and this is the primary thing I
should re-learn — but one evening at home, idly hacking away at a
simple task involving <a href="https://github.com/features/actions">Github Actions</a>. I was updating an existing
build, and just wanted to additionally create a release from the
build, for later installation by our Ansible playbooks. I didn&#39;t have
to be doing it in the evening, it wasn&#39;t urgent, I just wanted to tie
off a loose-end and knew it was a simple task.</p>
<p>
I have done this multiple times before, so I simply copied the
relevant lines from another project and pasted them in. It involves a
<a href="https://docs.github.com/en/actions/security-guides/encrypted-secrets">secret</a>, so I created a personal-access token and a new secret to
accompany it, and… that&#39;s odd, it was rejected because of the
<code>GITHUB_</code> prefix, presumably that is a new change but not to worry, I
renamed the secret in the workflow, created a new secret with matching
name, pushed my changes and went to bed.</p>
<div id="outline-container-headline-2" class="outline-3">
<h3 id="headline-2">
…the disappointment
</h3>
<div id="outline-text-headline-2" class="outline-text-3">
<p>
I woke up to roughly 800 successive builds — and it&#39;s even worse
than that because I didn&#39;t notice at the time! Other members of that
organisation received an email overnight for every single one, and
strangely I didn&#39;t so I only realised when I rolled into work, a bit
late to boot.</p>
</div>
</div>
<div id="outline-container-headline-3" class="outline-3">
<h3 id="headline-3">
What happened
</h3>
<div id="outline-text-headline-3" class="outline-text-3">
<p>
Two things:</p>
<ul>
<li>The release process involves creating a tag for the release (as well
as uploading 150M .war file).<sup class="footnote-reference"><a id="footnote-reference-1" href="#footnote-1">1</a></sup></li>
<li>The workflow was triggered by a push.</li>
</ul>
<p>To tie it all together, the token I inadvertently created was <em>not</em> a
recent change, it was a <a href="https://docs.github.com/en/actions/security-guides/automatic-token-authentication">special token to avoid just this scenario</a>.
When my workflow created the tag it generated a push event, which in
turns triggers an entire new build. Look, it&#39;s right there in the
documentation:</p>
<blockquote>
<p>When you use the repository&#39;s GITHUB_TOKEN to perform tasks, events
triggered by the GITHUB_TOKEN will not create a new workflow run. This
prevents you from accidentally creating recursive workflow runs. For
example, if a workflow run pushes code using the repository&#39;s
GITHUB_TOKEN, a new workflow will not run even when the repository
contains a workflow configured to run when push events occur.</p>
</blockquote>
</div>
</div>
</div>
</div>
<div id="outline-container-headline-4" class="outline-2">
<h2 id="headline-4">
Meta disappointment
</h2>
<div id="outline-text-headline-4" class="outline-text-2">
<p>
So, oops.  But more than that, I should have been way smarter than
that.  I don&#39;t feel I have improved as developer in quite some
time<sup class="footnote-reference"><a id="footnote-reference-2" href="#footnote-2">2</a></sup>, but the single thing I <em>have</em> noticed is: an improved
ability to go to bed!  We&#39;ve all that situation where it&#39;s late but we
feel fine, I&#39;m really close to finding this bug, perhaps if I just try
this next thing… and then <em>actually</em> solving it within 5 minutes the
next day.  Now, I&#39;m disciplined enough to realise that I&#39;m probably
just doing stupid things, and going to bed.  Trust the process.</p>
<p>
I did not do that here; I was programming for the heck of it, when
there was no need to. That&#39;s the biggest disappointment<sup class="footnote-reference"><a id="footnote-reference-3" href="#footnote-3">3</a></sup>, so
perhaps if one person avoids this mistake after reading this, I&#39;ll
feel better!</p>
</div>
</div>
<div class="footnotes">
<hr class="footnotes-separatator">
<div class="footnote-definitions">
<div class="footnote-definition">
<sup id="footnote-1"><a href="#footnote-reference-1">1</a></sup>
<div class="footnote-body">
<p>Yes, 800 times.</p>
</div>
</div>
<div class="footnote-definition">
<sup id="footnote-2"><a href="#footnote-reference-2">2</a></sup>
<div class="footnote-body">
<p>Just because you have imposter syndrome, doesn&#39;t mean you&#39;re
not incompetent.</p>
</div>
</div>
<div class="footnote-definition">
<sup id="footnote-3"><a href="#footnote-reference-3">3</a></sup>
<div class="footnote-body">
<p>It&#39;s actually worse than that! Before cleaning up I carefully
wrote an email expressing my sincere apologies, and explaining why it
had happened and what I would be doing about it. Then I promptly sent
it to the wrong person, thanks to a similar name in my email&#39;s
auto-complete.</p>
</div>
</div>
</div>
</div>
]]></content>
		</item>
		
		<item>
			<title>Understanding use-package Optimisations</title>
			<link>https://blog.markhepburn.com/posts/understanding-use-package-optimisations/</link>
			<pubDate>Mon, 30 May 2022 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/understanding-use-package-optimisations/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[
<p>
There was a <a href="https://blog.d46.us/advanced-emacs-startup/">recent appearance on HN</a> of an article about improving
Emacs startup time, with a few mentions of <a href="https://github.com/jwiegley/use-package"><code>use-package</code></a>. This was
topical for me as I&#39;d just been through my own yak-shaving exercise
(startup time now down to about 1.5s, and yes this is immaterial
because I run it as a daemon on login).</p>
<p>
There were plenty of useful suggestions, but lacking for me was any
discussion of exactly <em>how</em> <code>use-package</code> works, so this article
attempts to explain the ones I found most useful.</p>
<div id="outline-container-headline-1" class="outline-2">
<h2 id="headline-1">
Background: investigating for yourself
</h2>
<div id="outline-text-headline-1" class="outline-text-2">
<p>
By far the simplest tactic is to just see what <code>use-package</code> is doing:
it is a macro, so you can look at the code generated.  I&#39;ve been using
<a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Lisp-Interaction.html">ielm</a> for convenience.</p>
<p>
This is the basic code generated when requiring a package<sup class="footnote-reference"><a id="footnote-reference-1" href="#footnote-1">1</a></sup>.</p>
<div class="src src-elisp">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-elisp" data-lang="elisp"><span class="line"><span class="cl"><span class="nv">ELISP&gt;</span> <span class="p">(</span><span class="nf">macroexpand</span> <span class="o">&#39;</span><span class="p">(</span><span class="nb">use-package</span> <span class="nv">foo</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">progn</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">defvar</span> <span class="nv">use-package--warning146</span>
</span></span><span class="line"><span class="cl">    <span class="nf">#&#39;</span><span class="p">(</span><span class="nb">lambda</span>
</span></span><span class="line"><span class="cl">        <span class="p">(</span><span class="nv">keyword</span> <span class="nv">err</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="p">(</span><span class="nb">let</span>
</span></span><span class="line"><span class="cl">            <span class="p">((</span><span class="nv">msg</span>
</span></span><span class="line"><span class="cl">              <span class="p">(</span><span class="nf">format</span> <span class="s">&#34;%s/%s: %s&#34;</span> <span class="ss">&#39;foo</span> <span class="nv">keyword</span>
</span></span><span class="line"><span class="cl">                      <span class="p">(</span><span class="nf">error-message-string</span> <span class="nv">err</span><span class="p">))))</span>
</span></span><span class="line"><span class="cl">          <span class="p">(</span><span class="nv">display-warning</span> <span class="ss">&#39;use-package</span> <span class="nv">msg</span> <span class="nb">:error</span><span class="p">))))</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">condition-case-unless-debug</span> <span class="nv">err</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nb">if</span>
</span></span><span class="line"><span class="cl">          <span class="p">(</span><span class="nv">not</span>
</span></span><span class="line"><span class="cl">           <span class="p">(</span><span class="nb">require</span> <span class="ss">&#39;foo</span> <span class="no">nil</span> <span class="no">t</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">          <span class="p">(</span><span class="nv">display-warning</span> <span class="ss">&#39;use-package</span>
</span></span><span class="line"><span class="cl">                            <span class="p">(</span><span class="nf">format</span> <span class="s">&#34;Cannot load %s&#34;</span> <span class="ss">&#39;foo</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                            <span class="nb">:error</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="ne">error</span>
</span></span><span class="line"><span class="cl">     <span class="p">(</span><span class="nf">funcall</span> <span class="nv">use-package--warning146</span> <span class="nb">:catch</span> <span class="nv">err</span><span class="p">))))</span></span></span></code></pre></div>
</div>
<p>Taking out the error handling boilerplate, we&#39;re left with:</p>
<div class="src src-elisp">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-elisp" data-lang="elisp"><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">if</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nv">not</span>
</span></span><span class="line"><span class="cl">       <span class="p">(</span><span class="nb">require</span> <span class="ss">&#39;foo</span> <span class="no">nil</span> <span class="no">t</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nv">display-warning</span> <span class="ss">&#39;use-package</span>
</span></span><span class="line"><span class="cl">                       <span class="p">(</span><span class="nf">format</span> <span class="s">&#34;Cannot load %s&#34;</span> <span class="ss">&#39;foo</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                       <span class="nb">:error</span><span class="p">))</span></span></span></code></pre></div>
</div>
<p>In other words, require the package!</p>
<p>
Now let&#39;s look at some variations.</p>
</div>
</div>
<div id="outline-container-headline-2" class="outline-2">
<h2 id="headline-2">
Efficiencies
</h2>
<div id="outline-text-headline-2" class="outline-text-2">
<p>
All of these are standard start-up hacks, implemented in a nice DSL by
use-package.</p>
<div id="outline-container-headline-3" class="outline-3">
<h3 id="headline-3">
Deferring
</h3>
<div id="outline-text-headline-3" class="outline-text-3">
<p>
Firstly, let&#39;s see the difference when using <code>:defer t</code>:</p>
<div class="src src-elisp">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-elisp" data-lang="elisp"><span class="line"><span class="cl"><span class="nv">ELISP&gt;</span> <span class="p">(</span><span class="nf">macroexpand</span> <span class="o">&#39;</span><span class="p">(</span><span class="nb">use-package</span> <span class="nv">foo</span> <span class="nb">:defer</span> <span class="no">t</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">progn</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">defvar</span> <span class="nv">use-package--warning147</span>
</span></span><span class="line"><span class="cl">    <span class="nf">#&#39;</span><span class="p">(</span><span class="nb">lambda</span>
</span></span><span class="line"><span class="cl">        <span class="p">(</span><span class="nv">keyword</span> <span class="nv">err</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="p">(</span><span class="nb">let</span>
</span></span><span class="line"><span class="cl">            <span class="p">((</span><span class="nv">msg</span>
</span></span><span class="line"><span class="cl">              <span class="p">(</span><span class="nf">format</span> <span class="s">&#34;%s/%s: %s&#34;</span> <span class="ss">&#39;foo</span> <span class="nv">keyword</span>
</span></span><span class="line"><span class="cl">                      <span class="p">(</span><span class="nf">error-message-string</span> <span class="nv">err</span><span class="p">))))</span>
</span></span><span class="line"><span class="cl">          <span class="p">(</span><span class="nv">display-warning</span> <span class="ss">&#39;use-package</span> <span class="nv">msg</span> <span class="nb">:error</span><span class="p">))))</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">condition-case-unless-debug</span> <span class="nv">err</span> <span class="no">nil</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="ne">error</span>
</span></span><span class="line"><span class="cl">     <span class="p">(</span><span class="nf">funcall</span> <span class="nv">use-package--warning147</span> <span class="nb">:catch</span> <span class="nv">err</span><span class="p">))))</span></span></span></code></pre></div>
</div>
<p>Stripping away the boilerplate and we&#39;re left with… nothing!  That
shouldn&#39;t be surprising; we don&#39;t load the package, we&#39;ll need to take
care of that ourselves somehow.  Most of the remaining snippets we&#39;ll
look at concern themselves with different ways of ensuring that a
package is loaded when needed, but not at startup.</p>
<p>
On its own, <code>:defer t</code> is mainly useful for packages that will be
loaded by other packages.</p>
<div id="outline-container-headline-4" class="outline-4">
<h4 id="headline-4">
Delaying
</h4>
<div id="outline-text-headline-4" class="outline-text-4">
<p>
The <code>:defer</code> keyword can also take a numeric argument, representing
the number of seconds to wait before loading.  Looking at the
expansion:</p>
<div class="src src-elisp">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-elisp" data-lang="elisp"><span class="line"><span class="cl"><span class="nv">ELISP&gt;</span> <span class="p">(</span><span class="nf">macroexpand</span> <span class="o">&#39;</span><span class="p">(</span><span class="nb">use-package</span> <span class="nv">foo</span> <span class="nb">:defer</span> <span class="mi">1</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="c1">;...</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nv">run-with-idle-timer</span> <span class="mi">1</span> <span class="no">nil</span> <span class="nf">#&#39;</span><span class="nb">require</span> <span class="ss">&#39;foo</span> <span class="no">nil</span> <span class="no">t</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="c1">;...</span></span></span></code></pre></div>
</div>
<p>
In other words, use an <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Idle-Timers.html">idle timer</a> to delay requiring the package for a
second.  This is useful for large packages that can take a while to
load, but that may not be necessary immediately (which is probably
most of them, if you&#39;re launching from your login profile!).  <a href="https://emacs-helm.github.io/helm/">Helm</a> was
one such candidate for me.</p>
</div>
</div>
</div>
</div>
<div id="outline-container-headline-5" class="outline-3">
<h3 id="headline-5">
Autoloading
</h3>
<div id="outline-text-headline-5" class="outline-text-3">
<p>
A large part of the work that use-package does is to defer loading a
package by configuring <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Autoload.html">autoloads</a>. This is a core facility provided by
Emacs to trigger loading of a package only when some function is first
called, and there are a few ways <code>use-package</code> identifies functions to
use as triggers.</p>
<div id="outline-container-headline-6" class="outline-4">
<h4 id="headline-6">
Key bindings
</h4>
<div id="outline-text-headline-6" class="outline-text-4">
<p>
Possibly the most common requirement is to associate a command from a
package with a keybinding; this is Emacs after all!  Use-package
offers a rich and convenient way to do this:</p>
<div class="src src-elisp">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-elisp" data-lang="elisp"><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">use-package</span> <span class="nv">foo</span>
</span></span><span class="line"><span class="cl">    <span class="nb">:bind</span> <span class="p">(</span><span class="s">&#34;C-cd&#34;</span> <span class="o">.</span> <span class="nv">foo-bar</span><span class="p">))</span></span></span></code></pre></div>
</div>
<p>This associates the interactdive command <code>foo-bar</code>, assumed to be in
the package <code>foo</code>, to the key sequence control-c, d.  The expansion is
more interesting:</p>
<div class="src src-elisp">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-elisp" data-lang="elisp"><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">progn</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nb">unless</span>
</span></span><span class="line"><span class="cl">        <span class="p">(</span><span class="nf">fboundp</span> <span class="ss">&#39;foo-bar</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nf">autoload</span> <span class="nf">#&#39;</span><span class="nv">foo-bar</span> <span class="s">&#34;foo&#34;</span> <span class="no">nil</span> <span class="no">t</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nv">bind-keys</span> <span class="nb">:package</span> <span class="nv">foo</span>
</span></span><span class="line"><span class="cl">               <span class="p">(</span><span class="s">&#34;C-cd&#34;</span> <span class="o">.</span> <span class="nv">foo-bar</span><span class="p">)))</span></span></span></code></pre></div>
</div>
<p>In order, this:</p>
<ol>
<li>Checks that the function <code>foo-bar</code> isn&#39;t already loaded, and
assuming it isn&#39;t;</li>
<li>Sets up an autoload (note that we didn&#39;t have to configure this
ourselves) triggered by the <code>foo-bar</code> function;</li>
<li>Binds the function to the desired key sequence<sup class="footnote-reference"><a id="footnote-reference-2" href="#footnote-2">2</a></sup>.</li>
</ol>
<p>Naturally as a result it does <em>not</em> need to <code>require</code> the package.
This is the core of use-package; anything that can be identified as
deferable, will have an autoload configured for it.</p>
</div>
</div>
<div id="outline-container-headline-7" class="outline-4">
<h4 id="headline-7">
Modes
</h4>
<div id="outline-text-headline-7" class="outline-text-4">
<p>
Another very common requirement is to associate a package (mode) with
a file-type.  Again, <code>use-package</code> offers a very convenient way to do
this:</p>
<div class="src src-elisp">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-elisp" data-lang="elisp"><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">use-package</span> <span class="nv">foo</span>
</span></span><span class="line"><span class="cl">    <span class="nb">:mode</span> <span class="s">&#34;\\.asdf\\&#39;&#34;</span><span class="p">)</span></span></span></code></pre></div>
</div>
<p>The expansion, again:</p>
<div class="src src-elisp">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-elisp" data-lang="elisp"><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">progn</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nb">unless</span>
</span></span><span class="line"><span class="cl">        <span class="p">(</span><span class="nf">fboundp</span> <span class="ss">&#39;foo</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nf">autoload</span> <span class="nf">#&#39;</span><span class="nv">foo</span> <span class="s">&#34;foo&#34;</span> <span class="no">nil</span> <span class="no">t</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nv">add-to-list</span> <span class="ss">&#39;auto-mode-alist</span>
</span></span><span class="line"><span class="cl">                 <span class="o">&#39;</span><span class="p">(</span><span class="s">&#34;\\.asdf\\&#39;&#34;</span> <span class="o">.</span> <span class="nv">foo</span><span class="p">)))</span></span></span></code></pre></div>
</div>
<p>In other words, set up another autoload, and add it to the
<code>auto-mode-alist</code>.  This of course assumes that the name of the
package is the name of the mode; if our package was still called <code>foo</code>
but our mode was actually <code>foo-mode</code>, the syntax variant will set up
the autoload and alist for <code>foo-mode</code> instead:</p>
<div class="src src-elisp">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-elisp" data-lang="elisp"><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">use-package</span> <span class="nv">foo</span>
</span></span><span class="line"><span class="cl">    <span class="nb">:mode</span> <span class="p">(</span><span class="s">&#34;\\.asdf\\.&#34;</span> <span class="o">.</span> <span class="nv">foo-mode</span><span class="p">))</span></span></span></code></pre></div>
</div>
</div>
</div>
</div>
</div>
<div id="outline-container-headline-8" class="outline-3">
<h3 id="headline-8">
Hooks
</h3>
<div id="outline-text-headline-8" class="outline-text-3">
<p>
Another common scenario is to configure a hook from the package; for
example, to turn on <code>flycheck-mode</code> from <code>prog-mode-hook</code> (ie, all
programming languages).  Once again <code>use-package</code> provides convenient
syntax, and by now the expansion should not be a surprise:</p>
<div class="src src-elisp">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-elisp" data-lang="elisp"><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">use-package</span> <span class="nv">flycheck-mode</span>
</span></span><span class="line"><span class="cl">    <span class="nb">:hook</span> <span class="nv">prog-mode</span><span class="p">)</span></span></span></code></pre></div>
</div>
<p>With expansion (note, the syntax saves you the hassle of adding the
<code>-mode</code> suffix, although this behaviour can be altered)</p>
<div class="src src-elisp">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-elisp" data-lang="elisp"><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">progn</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nb">unless</span>
</span></span><span class="line"><span class="cl">        <span class="p">(</span><span class="nf">fboundp</span> <span class="ss">&#39;flycheck-mode</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nf">autoload</span> <span class="nf">#&#39;</span><span class="nv">flycheck-mode</span> <span class="s">&#34;flycheck-mode&#34;</span> <span class="no">nil</span> <span class="no">t</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nv">add-hook</span> <span class="ss">&#39;prog-mode-hook</span> <span class="nf">#&#39;</span><span class="nv">flycheck-mode</span><span class="p">))</span></span></span></code></pre></div>
</div>
<div id="outline-container-headline-9" class="outline-4">
<h4 id="headline-9">
Manually
</h4>
<div id="outline-text-headline-9" class="outline-text-4">
<p>
Finally, you can manually specify commands to autoload. For example, I
have a package to generate <a href="https://github.com/jschaf/emacs-lorem-ipsum">lorem-ipsum</a> text. It&#39;s rarely used and I
don&#39;t want to bind any of the commands, so I also don&#39;t want the
package loaded unless I need it.</p>
<p>
Your friend here is <code>:commands</code>, and you can guess the expansion by
now:</p>
<div class="src src-elisp">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-elisp" data-lang="elisp"><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">use-package</span> <span class="nv">lorem-ipsum</span>
</span></span><span class="line"><span class="cl">    <span class="nb">:commands</span> <span class="p">(</span><span class="nv">lorem-ipsum-insert-sentences</span>
</span></span><span class="line"><span class="cl">               <span class="nv">lorem-ipsum-insert-paragraphs</span><span class="p">))</span></span></span></code></pre></div>
</div>
</div>
</div>
</div>
</div>
<div id="outline-container-headline-10" class="outline-3">
<h3 id="headline-10">
Dependencies and configuration
</h3>
<div id="outline-text-headline-10" class="outline-text-3">
<p>
Now that everything is autoloaded, a secondary step is to ensure that
a package isn&#39;t inadvertently loaded by another package.  You can use
<code>:defer</code> here if you know that a package is only used by something
else, for example you want to ensure<sup class="footnote-reference"><a id="footnote-reference-3" href="#footnote-3">3</a></sup> some library is installed,
but only required by packages that needed it.</p>
<p>
Sometimes however you want to load an entire package as part of
another package.  In this case, you can specify <code>:after</code>; an example
from my own setup involves dired extensions:</p>
<div class="src src-elisp">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-elisp" data-lang="elisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">use-package</span> <span class="nv">dired-quick-sort</span>
</span></span><span class="line"><span class="cl">  <span class="nb">:after</span> <span class="nv">dired</span><span class="p">)</span></span></span></code></pre></div>
</div>
<p>The expansion this time looks a little different:</p>
<div class="src src-elisp">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-elisp" data-lang="elisp"><span class="line"><span class="cl">  <span class="p">(</span><span class="nv">eval-after-load</span> <span class="ss">&#39;dired</span>
</span></span><span class="line"><span class="cl">    <span class="o">&#39;</span><span class="p">(</span><span class="nb">if</span>
</span></span><span class="line"><span class="cl">         <span class="p">(</span><span class="nv">not</span>
</span></span><span class="line"><span class="cl">          <span class="p">(</span><span class="nb">require</span> <span class="ss">&#39;dired-quick-sort</span> <span class="no">nil</span> <span class="no">t</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">         <span class="p">(</span><span class="nv">display-warning</span> <span class="ss">&#39;use-package</span>
</span></span><span class="line"><span class="cl">                          <span class="p">(</span><span class="nf">format</span> <span class="s">&#34;Cannot load %s&#34;</span> <span class="ss">&#39;dired-quick-sort</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                          <span class="nb">:error</span><span class="p">)))</span></span></span></code></pre></div>
</div>
<p>The core functionality this time is <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Hooks-for-Loading.html"><code>eval-after-load</code></a>, which is
another special form that only executes its body after another package
has loaded.</p>
<p>
This same macro is often used in old-school Emacs configurations to
delay configuration of a package until it has been loaded. Not
surprisingly, <code>use-package</code> has your back here too; this is exactly
what <code>:config</code> does when used in conjunction with anything triggering
autoloading:</p>
<div class="src src-elisp">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-elisp" data-lang="elisp"><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">use-package</span> <span class="nv">dired-quick-sort</span>
</span></span><span class="line"><span class="cl">    <span class="nb">:commands</span> <span class="p">(</span><span class="nv">dired-quick-sort</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="nb">:config</span> <span class="p">(</span><span class="nv">dired-quick-sort-setup</span><span class="p">))</span></span></span></code></pre></div>
</div>
<p>And the core expansion:</p>
<div class="src src-elisp">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-elisp" data-lang="elisp"><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">progn</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nb">unless</span>
</span></span><span class="line"><span class="cl">        <span class="p">(</span><span class="nf">fboundp</span> <span class="ss">&#39;dired-quick-sort</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nf">autoload</span> <span class="nf">#&#39;</span><span class="nv">dired-quick-sort</span> <span class="s">&#34;dired-quick-sort&#34;</span> <span class="no">nil</span> <span class="no">t</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nv">eval-after-load</span> <span class="ss">&#39;dired-quick-sort</span>
</span></span><span class="line"><span class="cl">      <span class="o">&#39;</span><span class="p">(</span><span class="nb">condition-case-unless-debug</span> <span class="nv">err</span>
</span></span><span class="line"><span class="cl">           <span class="p">(</span><span class="nb">progn</span>
</span></span><span class="line"><span class="cl">             <span class="p">(</span><span class="nv">dired-quick-sort-setup</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">             <span class="no">t</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">         <span class="p">(</span><span class="ne">error</span>
</span></span><span class="line"><span class="cl">          <span class="p">(</span><span class="nf">funcall</span> <span class="nv">use-package--warning206</span> <span class="nb">:config</span> <span class="nv">err</span><span class="p">)))))</span></span></span></code></pre></div>
</div>
<p>In other words, defer loading the package by setting up an autoload,
and then also configure some code to run when the package does finally
load.</p>
</div>
</div>
</div>
</div>
<div id="outline-container-headline-11" class="outline-2">
<h2 id="headline-11">
Summary
</h2>
<div id="outline-text-headline-11" class="outline-text-2">
<p>
Hopefully by now you have a better undersatnding of what <code>use-package</code>
is doing, and how to use it to improve your own startup time:</p>
<ol>
<li>Use <code>macroexpand</code> in order to check what <code>use-package</code> is doing;</li>
<li>Only load packages when necessary, using whatever is appropriate to
ensure it will be autoloaded;</li>
<li>Set the variable <code>use-package-verbose</code> to <code>t</code> — this prints out
each package-load to the <code>*Messages*</code> buffer, so you can detect if
something is being loaded earlier than you would like, and it also
warns if something takes too long in loading (more than 0.3s by
default).</li>
<li>(and if you really want to lower that number!) Use idle-timers to
defer non-essential packages until after startup. </li>
</ol>
</div>
</div>
<div class="footnotes">
<hr class="footnotes-separatator">
<div class="footnote-definitions">
<div class="footnote-definition">
<sup id="footnote-1"><a href="#footnote-reference-1">1</a></sup>
<div class="footnote-body">
<p>I actually see a bit more boilerplate because I enable both
<code>use-package-always-ensure</code> and recently <code>use-package-verbose</code>, which
is handy for identifying slow-loading packages.</p>
</div>
</div>
<div class="footnote-definition">
<sup id="footnote-2"><a href="#footnote-reference-2">2</a></sup>
<div class="footnote-body">
<p><code>bind-keys</code> is a separate package but managed as part of
<code>use-package</code>.</p>
</div>
</div>
<div class="footnote-definition">
<sup id="footnote-3"><a href="#footnote-reference-3">3</a></sup>
<div class="footnote-body">
<p>I have <code>use-package-always-ensure</code> set, or you can manually add
<code>:ensure t</code>.</p>
</div>
</div>
</div>
</div>
]]></content>
		</item>
		
		<item>
			<title>WH 1000XM3 Audio Controls in Linux   AVRCP and MPRIS</title>
			<link>https://blog.markhepburn.com/posts/wh-1000xm3-audio-controls-in-linux---avrcp-and-mpris/</link>
			<pubDate>Sun, 06 Mar 2022 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/wh-1000xm3-audio-controls-in-linux---avrcp-and-mpris/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[
<p>
A year or two ago I bought a pair of <a href="https://store.sony.com.au/archived-headphones-noisecancelling/WH1000XM3B.html">Sony WH-1000xm3</a> noise-cancelling
headphones, and as an introvert – they were absolutely life-changing.
The noise cancellation is fantastic, and they&#39;re also quite nifty with
some touch controls built into the right cup: stroke up and down to
raise and lower the volume, double-tap to toggle play or pause, and
stroke forwards or backwards to skip forward or backwards.</p>
<p>
At work I usually have some mindless background noise via <a href="https://soundcloud.com/">Soundcloud</a>
in a browser tab. That does the job against office noise, but it&#39;s
slightly inconvenient having to switch to that tab just to pause.</p>
<p>
Recently I learned that browsers <em>should</em> support media keys out of
the box, just like a regular media player, without having to switch to
the tab! I&#39;m a <a href="https://github.com/markhepburn/dotxmonad">hair-shirt wearing</a> Linux user however, and occasionally
you don&#39;t get the just-works integration with every new bit of kit
that other OS users may enjoy, so I wasn&#39;t too surprised that it
didn&#39;t work for me, and forgot about it. Until, that is, I was booted
into Windows and suddenly realised that it <em>did</em> just work, and
regained some motivation to investigate.</p>
<p>
Anyway, the short version is: it more or less does <em>just work™</em>, but
you need to decide how to wire it up.  There are two parts to the
puzzle; MPRIS and AVRCP.</p>
<div id="outline-container-headline-1" class="outline-3">
<h3 id="headline-1">
MPRIS
</h3>
<div id="outline-text-headline-1" class="outline-text-3">
<p>
MPRIS is the standard interface for media players, including web
browsers in this instance. It stands for &#34;Media Player Remote
Interfacing Specification&#34;, and is a DBUS interface. The <a href="https://wiki.archlinux.org/title/MPRIS">Arch Linux
docs</a> are again a useful resource.</p>
<p>
To test it in action, you just need something that speaks the client
side of the protocol. I picked <a href="https://github.com/altdesktop/playerctl">playerctl</a>, which was in the Ubuntu
repo.</p>
<p>
Start some music playing in a browser tab (it doesn&#39;t have to be
selected), and execute <code>playerctl play-pause</code> to toggle playing and
pausing.</p>
</div>
</div>
<div id="outline-container-headline-2" class="outline-3">
<h3 id="headline-2">
AVRCP
</h3>
<div id="outline-text-headline-2" class="outline-text-3">
<p>
The other half of the equation: I spent a bit of time expecting to
need to dig into dark corners to hook up my headphones, but it turns
out that they implement something called AVRCP, which is apparently
another standard interface and stands for &#34;Audio/Visual Remote Control
Protocol&#34;.</p>
<p>
I hadn&#39;t heard of it, but it turns out that the headphone&#39;s gesture-controls I
mentioned in the intro already generate media key events!  You can
test this by – with the headphones connected of course – running
<code>xev</code> and double-tapping, stroking, etc.  For instance, when
double-tapping you will observe <code>XF86AudioPlay</code>, or <code>XF86AudioNext</code>
when stroking forward, etc.</p>
</div>
</div>
<div id="outline-container-headline-3" class="outline-3">
<h3 id="headline-3">
Wiring it all up
</h3>
<div id="outline-text-headline-3" class="outline-text-3">
<p>
With those in place, it pretty much <em>does</em> just work: you just need to
decide what to do with those keys. You have plenty of options here,
but I went with <a href="https://wiki.archlinux.org/title/Xbindkeys">xbindkeys</a>, which is simple to set up and even offers a
GUI configuration if you wish. I handle play/pause, and the
next/previous events (the headphones have their own internal volume
control which is fine for my purposes).</p>
<p>
The relevant bit from my config:</p>
<div class="src src-sh">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl"><span class="c1">#Play/pause</span>
</span></span><span class="line"><span class="cl"><span class="s2">&#34;playerctl play-pause&#34;</span>
</span></span><span class="line"><span class="cl">    m:0x0 + c:209
</span></span><span class="line"><span class="cl">    XF86AudioPause 
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">#Skip Forward</span>
</span></span><span class="line"><span class="cl"><span class="s2">&#34;playerctl next&#34;</span>
</span></span><span class="line"><span class="cl">    m:0x0 + c:171
</span></span><span class="line"><span class="cl">    XF86AudioNext 
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">#Skip Back</span>
</span></span><span class="line"><span class="cl"><span class="s2">&#34;playerctl previous&#34;</span>
</span></span><span class="line"><span class="cl">    m:0x0 + c:173
</span></span><span class="line"><span class="cl">    XF86AudioPrev</span></span></code></pre></div>
</div>
<p>
That&#39;s all!</p>
</div>
</div>
]]></content>
		</item>
		
		<item>
			<title>Pinboard Daily Links Email</title>
			<link>https://blog.markhepburn.com/posts/pinboard-daily-links-email/</link>
			<pubDate>Sat, 16 Oct 2021 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/pinboard-daily-links-email/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>
I&#39;m a happy customer of the <a href="https://pinboard.in/">Pinboard</a> bookmark service.  I was
grandfathered in on the original one-time payment plan, and even
recently converted to a regular subscription when he politely requested
I consider it.</p>
<p>
The thing is… I hardly ever <em>use</em> pinboard!  Bookmarking just isn&#39;t
on my radar these days; that&#39;s what search-engines are for.</p>
<p>
What I&#39;ve long wanted though is some sort of serendipity in the
service.  I don&#39;t have a problem locating something again if I
remember what it was, but I have <em>no idea</em> what I&#39;ve since forgotten
about.  As I discovered in my <a href="/posts/using-github-to-host-recurring-jobs/">last post</a> though, now I know that it&#39;s a
fairly simple job to implement a &#34;random links from your past&#34; email.</p>
<p>
In readiness, I&#39;ve tried to be a lot more cavailier about bookmarking
anything that seems remotely interesting.  I have a few &#34;interesting
links&#34; emails in my Inbox these days (<a href="https://digg.com/">Digg</a>, <a href="https://refind.com/">Refind</a>, etc) that try to
use social cues or AI to find interesting stuff… now I have one
more, but based on stuff I&#39;ve personally and explicitly already marked
as interesting!</p>
<p>
Feel free to <a href="https://github.com/markhepburn/daily_pinboard/">clone the repo</a> and run your own.  It should run out of
the box with a few secrets configured.<sup class="footnote-reference"><a id="footnote-reference-1" href="#footnote-1">1</a></sup></p>
<div class="footnotes">
<hr class="footnotes-separatator">
<div class="footnote-definitions">
<div class="footnote-definition">
<sup id="footnote-1"><a href="#footnote-reference-1">1</a></sup>
<div class="footnote-body">
<p>The email itself hasn&#39;t been styled at all… that&#39;s my next project!</p>
</div>
</div>
</div>
</div>
]]></content>
		</item>
		
		<item>
			<title>Using GitHub to host recurring jobs</title>
			<link>https://blog.markhepburn.com/posts/using-github-to-host-recurring-jobs/</link>
			<pubDate>Sat, 02 Oct 2021 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/using-github-to-host-recurring-jobs/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[
<div id="outline-container-headline-1" class="outline-2">
<h2 id="headline-1">
Overview
</h2>
<div id="outline-text-headline-1" class="outline-text-2">
<p>
  I manage my own server, and while I appreciate the sense of
  ownership and the learning that goes along with it, it can still
  increase the sense of <em>friction</em>.</p>
<p>
  For example, a few times lately I&#39;ve had an idea for a simple little
  program, to run regularly and email me something.  The programs
  aren&#39;t large, and the effort in developing and testing my Ansible
  playbook to host the program (including probably checking out from
  source, setting up deploy keys, etc) is probably about the
  same… so nothing gets done.  Yes, I&#39;m lazy.</p>
<p>
  Then suddenly I realised that GitHub<sup class="footnote-reference"><a id="footnote-reference-1" href="#footnote-1">1</a></sup> had free &#34;Actions&#34;
  (they&#39;ll run some code for you), and that these include cron-like
  scheduled triggers.  That was all I needed!</p>
</div>
</div>
<div id="outline-container-headline-2" class="outline-2">
<h2 id="headline-2">
Case-study: Weekly summary of budgets in Harvest
</h2>
<div id="outline-text-headline-2" class="outline-text-2">
<p>
  At my day-job we use <a href="https://www.getharvest.com/">Harvest</a> for time and budget tracking on
  projects.  Try as I might, my instincts to bury myself in a
  technical problem mean that periodically reviewing budgets doesn&#39;t
  happen anywhere nearly as often as it should.  Naturally this sounds
  like a technical problem to me!  I&#39;d like an email that gets sent
  every week to tell me how my projects are going: it&#39;s in my Inbox,
  and harder to ignore or forget.  Zero-friction.</p>
<p>
  Skipping ahead, the result is <a href="https://github.com/markhepburn/harvest_email/">on GitHub</a>.  Harvest have <a href="https://help.getharvest.com/api-v2/">an API</a> that&#39;s
  fairly easy to work with.  I wrote a <a href="https://github.com/markhepburn/harvest_email/blob/master/projects_status.py">simple Python program</a> that
  invokes it, formats the results <a href="https://www.makotemplates.org/">using Mako</a>, and writes to a file.
  For everything else, we will use GitHub&#39;s infrastructure.</p>
<p>
  Setting up GitHub Actions is fairly simple and <a href="https://docs.github.com/en/actions/quickstart">covered elsewhere</a>.</p>
<p>
  The key point I want to focus on here is the trigger (&#34;<code>on:</code>&#34;) that
  invokes your workflow, which normally is a repository action such as
  pushing a new commit, or a pull request.  It turns out, you can also
  <a href="https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows#schedule">define a schedule</a>, using a <a href="https://crontab.guru/">cron-style</a> syntax.  Also worth noting,
  you probably want to include <code>workflow_dispatch:</code> in your workflows,
  which means you can invoke them on-demand for testing.</p>
<div class="src src-yaml">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Harvest Budget Summary Report</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">on</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">workflow_dispatch</span><span class="p">:</span><span class="w">            </span><span class="c"># Enable manual invocation for testing</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">schedule</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">cron</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;0 22 * * THU&#34;</span><span class="w">      </span><span class="c"># 8am Fri, AEST</span></span></span></code></pre></div>
</div>
<p>
There is some boilerplate to create my python environment, then a
simple entry to run the program, configured by environment variables<sup class="footnote-reference"><a id="footnote-reference-2" href="#footnote-2">2</a></sup>:</p>
<div class="src src-yaml">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="l">python projects_status.py</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">env</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">HARVEST_ID</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.HARVEST_ID }}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">HARVEST_TOKEN</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.HARVEST_TOKEN }}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">ACCOUNT_EMAIL</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.ACCOUNT_EMAIL }}</span></span></span></code></pre></div>
</div>
<p>
Finally, we can lean on a third-party contribution to send the email,
and we are done!</p>
<div class="src src-yaml">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">dawidd6/action-send-mail@v3</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">with</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">server_address</span><span class="p">:</span><span class="w"> </span><span class="l">smtp.gmail.com</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">server_port</span><span class="p">:</span><span class="w"> </span><span class="m">465</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">username</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.SMTP_USERNAME }}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">password</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.SMTP_PASSWORD }}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">subject</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;[Harvest] Project Budget Tracking&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">html_body</span><span class="p">:</span><span class="w"> </span><span class="l">file://email.html</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">from</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.ACCOUNT_EMAIL }}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">to</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.ACCOUNT_EMAIL }}</span></span></span></code></pre></div>
</div>
<div id="outline-container-headline-3" class="outline-3">
<h3 id="headline-3">
Improvements
</h3>
<div id="outline-text-headline-3" class="outline-text-3">
<p>
   I really don&#39;t love the idea of having a Gmail application-password
   accessed by a third-party action.  This could/should probably be
   rolled back into my own Python code and <a href="https://docs.python.org/3/library/smtplib.html">smtplib</a>.  At the time it
   seemed like a nice separation of concerns; all I had to write was a
   simple and easily-testable program, and let the CI infrastructure
   handle the rest.  It certainly is convenient, but the overhead of
   doing it myself is minimal and the potential vulnerability impact
   is fairly high so I think I&#39;ll rewrite it shortly.</p>
</div>
</div>
</div>
</div>
<div class="footnotes">
<hr class="footnotes-separatator">
<div class="footnote-definitions">
<div class="footnote-definition">
<sup id="footnote-1"><a href="#footnote-reference-1">1</a></sup>
<div class="footnote-body">
<p>Also GitLab, probably others, but I&#39;m focussing on GitHub here
as that&#39;s the one most people are familiar with.</p>
</div>
</div>
<div class="footnote-definition">
<sup id="footnote-2"><a href="#footnote-reference-2">2</a></sup>
<div class="footnote-body">
<p>Pro-tip: I use <a href="https://direnv.net/">direnv</a> for local development, complete with
seamless <a href="https://github.com/wbolster/emacs-direnv">Emacs integration</a>.</p>
</div>
</div>
</div>
</div>
]]></content>
		</item>
		
		<item>
			<title>Automating SSH Login Involving TOTP Codes</title>
			<link>https://blog.markhepburn.com/posts/automating-ssh-login-involving-totp-codes/</link>
			<pubDate>Sat, 21 Aug 2021 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/automating-ssh-login-involving-totp-codes/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>In my day job I work with a lot of Linux servers, all only accessible
via a bastion host.  To make things slightly more complicated it is
a password-based login with a TOTP<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> two-factor step.  I use SSH
<a href="https://www.anchor.com.au/blog/2010/02/ssh-controlmaster-the-good-the-bad-the-ugly/">ControlMaster</a>
but still need to log in frequently.</p>
<p>The 2FA setup makes automation difficult, or at least so I assumed,
but the other day I finally managed to solve it.</p>
<p>I am very happy and paid-up user of
<a href="https://bitwarden.com/">BitWarden</a> (my vault contains over 350
passwords), and my usage in this scenario would typically involve
switching over to my browser, opening the extension then searching for
and copying the password, back to my terminal to paste it in, back to
the browser to search for and copy the TOTP code, and finally back to
the terminal again to finalise login.  It beats remembering and
typing, but it&rsquo;s still frustrating.</p>
<p>BitWarden has a number of clients, including for the command-line, but
because the vast majority of my usage is browser-based I&rsquo;d never
bothered downloading it.  It did seem like the perfect candidate to
automate my password-entry papercuts though.</p>
<h2 id="bitwarden-usage">Bitwarden Usage</h2>
<p>Installation of the <a href="https://github.com/bitwarden/cli">CLI</a> is
straightfoward, either via <code>npm</code> or several package-management
options.</p>
<p><a href="https://bitwarden.com/help/article/cli/">Usage</a> is also fairly
simple:</p>
<ul>
<li><code>bw unlock</code> will unlock your vault (and <code>bw status</code> reports several
statistics included locked status).</li>
<li>Unlocking outputs a line to paste into your shell that sets an
environment variable for the current session.<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup></li>
<li><code>bw get password &lt;item-id&gt;</code> will print the plain-text password for
an item.  You can of course search for items to find this id.</li>
</ul>
<p>Output is in JSON, if you need to script anything in conjunction with
<a href="https://stedolan.github.io/jq/">jq</a> for example.</p>
<p>As a bonus, you can enable shell completion via the tool itself:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="nb">eval</span> <span class="s2">&#34;</span><span class="k">$(</span>bw completion --shell zsh<span class="k">)</span><span class="s2">; compdef _bw bw;&#34;</span>
</span></span></code></pre></div><h2 id="first-attempt">First attempt</h2>
<p>When I was noodling this idea around my first thought was some variant
of <a href="https://linux.die.net/man/1/expect"><code>expect</code></a>.</p>
<p>However: expect is designed around automating the entire session,
whereas all I want is to be dropped into a shell with less typing.
So, that wasn&rsquo;t going to work.</p>
<h2 id="second-successful-attempt">Second, successful, attempt</h2>
<p>SSH goes to some lengths to avoid this type of automation, but it is
feasible.  There is a tool that allows several methods of password
entry (file, CLI, environment variable) and passes it to SSH:
<a href="https://sourceforge.net/projects/sshpass/">https://sourceforge.net/projects/sshpass/</a></p>
<p>Disclaimer: Possibly like you, I saw &ldquo;sourceforge&rdquo; and also assumed it
must be abandoned.  However it does appear that the maintainer, while
busy, is interested in <a href="https://sourceforge.net/p/sshpass/mailman/message/37318911/">considering modern needs for the
tool</a>
(just not adding patches that solve one specific case but not the
general requirements).</p>
<p>As of now it doesn&rsquo;t support TOTP codes though, but there are numerous
forks with varying approaches; I settled on
<a href="https://github.com/dora38/sshpass">https://github.com/dora38/sshpass</a></p>
<p>This variant supports TOTP codes by specifying an executable file
which generates a code.  Ours just needs to be a script containing <code>bw get totp &lt;id&gt;</code>.</p>
<p>I didn&rsquo;t want to have a file containing my password, even temporarily,
so my first instinct was to use <code>bw</code> to pipe the password in; eg</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">bw get password <span class="nv">$passwordid</span> <span class="p">|</span> sshpass....
</span></span></code></pre></div><p>This doesn&rsquo;t work because ssh then realises that stdin is redirected
and doesn&rsquo;t open a pseudo-tty.</p>
<p>So, my ultimate solution was to use an environment variable, just for
that invocation (<code>-e</code> to indicate it should look for a variable, and
you probably also want to configure the password and TOTP prompts):</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="nv">SSHPASS</span><span class="o">=</span><span class="k">$(</span>bw get password <span class="nv">$passwordid</span><span class="k">)</span> sshpass -e -c generate-totp ssh user@bastion.host
</span></span></code></pre></div><p>Success!</p>
<h1 id="follow-ups">Follow-ups</h1>
<p>Right now this is what I do, and it&rsquo;s only a control-r away (even
easier to search for since I&rsquo;ve started using
<a href="https://github.com/junegunn/fzf"><code>fzf</code></a>).  I did look at turning it
into a command for the purposes of this post, but there were a few
issues:</p>
<ul>
<li>an alias is problematic because of the amount of quoting, and not
wanting the get-password sub-shell to be prematurely evaluated.</li>
<li>A shell function would be ideal, but&hellip; doesn&rsquo;t give me an
interactive prompt at the end.</li>
</ul>
<p>I&rsquo;m sure it&rsquo;s solvable, but for a quick post I didn&rsquo;t invest enough
effort &mdash; sorry!</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Time-based One-Time Password&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p><del>Unfortunately it doesn&rsquo;t allow this to be automated, along the
lines of ssh-agent, for eg &ldquo;<code>eval $(bw unlock)</code>&rdquo;.</del>  <em>Update: yes it
does!</em>  <code>export BW_SESSION=$(bw unlock --raw)</code>&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content>
		</item>
		
		<item>
			<title>Restricting CI Accounts With Rush</title>
			<link>https://blog.markhepburn.com/posts/restricting-ci-accounts-with-rush/</link>
			<pubDate>Sun, 01 Aug 2021 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/restricting-ci-accounts-with-rush/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<h1 id="motivation-locking-down-ci-accounts">Motivation: locking down CI accounts</h1>
<p>This blog is written in Hugo.  The source is hosted on Gitlab, and
deployed automatically by a Gitlab Pipeline when I push a new post.
This is a fairly standard setup, involving running Hugo and then
rsync-ing the build to my server.</p>
<p>There was still one aspect that I wanted to improve, and couldn&rsquo;t find
much assistance on: best-practice on locking down the account used by
rsync, in case the ssh key is ever compromised.  It should obviously
be a dedicated account, with no unecessary privileges and only used
for that purpose, but that still leaves our hypothetical scenario of
escalation following a regular ssh entry.</p>
<p>I have previously used OpenSSH&rsquo;s
<a href="https://serverfault.com/a/660325"><code>internal-sftp</code></a> to set up an SFTP
server that can&rsquo;t be used for general shell access, so I was asking:
what is the equivalent for rsync?</p>
<h1 id="rush">Rush</h1>
<p>The answer seems to be: <a href="https://puszcza.gnu.org.ua/software/rush/manual/rush.html">GNU
Rush!</a> (For
&ldquo;Restricted user shell&rdquo;, which gives you an idea of its purpose)</p>
<p>I initially found the examples a bit hard to follow, and furthermore
the syntax in the online manual is a bit different from the version
included with the <a href="http://www.releases.ubuntu.com/20.04/">Ubuntu 20.04
LTS</a> system I was using it on.</p>
<p>So, two useful points to get started:</p>
<ul>
<li>The manual you want (on similar systems) is <a href="https://www.gnu.org.ua/software/rush/legacy/">this
one</a>; and</li>
<li>The first line in your config should probably be <a href="https://www.gnu.org.ua/software/rush/legacy/Debugging.html#Debugging"><code>debug 3</code></a>,
because any errors are otherwise hard to spot.  Output will be in
<code>/var/log/auth.log</code> by default.</li>
</ul>
<h2 id="how-it-works">How it works</h2>
<p>Firstly, set the CI user&rsquo;s shell to <code>/usr/sbin/rush</code>.</p>
<p>The configuration file (<code>/etc/rush.rc</code>) contains a number of rules,
which consist of <em>conditions</em> defining the commands to match on, and
transformations to undertake.</p>
<p>Conditions can include regexp matches over the whole command line, or
individual parts.  By default, only one rule matches unless you
specify <code>fall-through</code>.  The default configuration uses a fall-through
rule to set some ulimits and a restricted environment-variable
profile.</p>
<p>Transformations can include forcing a particular working directory
(possibly involving chroot), and manipulating paths.</p>
<p>Rsync is a common use-case, and the <a href="https://www.gnu.org.ua/software/rush/legacy/rsync.html">examples
provided</a>
should get you started.</p>
<p><em>Warning: the default configuration probably will not work out of the
box!</em>  This is because it refers to paths such as <code>/srv/rush</code> that you
probably don&rsquo;t have on your system.  Increasing the debug verbosity as
recommended above will help you track this down, but it is still a lot
to wade through.</p>
<h2 id="a-simple-example">A simple example</h2>
<p>We can see this in action with a very simple local example.  We will
create a user with the Rush shell, and only allow them to run the &ldquo;ls&rdquo;
command, and furthermore only in the <code>/tmp</code> directory.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">apt install rush
</span></span><span class="line"><span class="cl">adduser --shell /usr/sbin/rush --disabled-password rushdemo
</span></span></code></pre></div><p>Simplify <code>/etc/rush.rc</code> to the following:</p>
<pre tabindex="0"><code class="language-conf" data-lang="conf">debug 3  # change back to 1 when you&#39;re happy

rule ls-demo
  command ^ls
  set /bin/ls
  chdir /tmp
</code></pre><p>Now we can try it out:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">$ sudo -u rushdemo -i ls
</span></span><span class="line"><span class="cl">... /tmp listing elided...
</span></span></code></pre></div><p>Success!  Now try another directory:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">$ sudo -u rushdemo -i ls /etc
</span></span><span class="line"><span class="cl">... /tmp listing elided...
</span></span></code></pre></div><p>Also success!  Or is that really what we wanted?  We can do better; it
is more likely that you want to block attempts to list any other
directory.  We&rsquo;ll do this with 2 rules; the first to match legal
commands, and a second to reject anything else.</p>
<pre tabindex="0"><code class="language-conf" data-lang="conf">rule ls-demo
  command ^ls$
  set /bin/ls
  chdir /tmp

rule ls-trap
  command ^ls
  argc &gt; 1
  exit fatal: arguments not allowed
</code></pre><p>Note that we&rsquo;ve changed the first rule to match <em>only</em> on &ldquo;<code>ls</code>&rdquo;.  The
second will match anything else that starts with <code>ls</code>, and has more
than one component (the <code>argc</code>) line.  If this rule matches we exit
with an error:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">$ sudo -u rushdemo -i ls
</span></span><span class="line"><span class="cl">... /tmp listing elided...
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">$ sudo -u rushdemo -i ls /etc
</span></span><span class="line"><span class="cl">fatal: arguments not allowed
</span></span></code></pre></div><p>Now we&rsquo;re in business!</p>
]]></content>
		</item>
		
		<item>
			<title>Backing Up Nextcloud in DigitalOcean</title>
			<link>https://blog.markhepburn.com/posts/backing-up-nextcloud-in-digitalocean/</link>
			<pubDate>Fri, 16 Jul 2021 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/backing-up-nextcloud-in-digitalocean/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>A quick post, while I work on establishing some research and
publishing momentum.</p>
<p>TL;DR Docker + disk-space issues meant I had to be a little bit
creative, or at least careful.</p>
<p>This blog is hosted on a small
<a href="https://digitalocean.com/">DigitalOcean</a> droplet, which I also use
for a personal <a href="https://nextcloud.com/">Nextcloud</a> instance.<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>
<p>There&rsquo;s some redundancy already built into this; my files are
replicated across a couple of devices aside from the server, but it&rsquo;s
not ideal either.  A theoretical attack that deleted my files would
get propagated across those same devices, I suppose.</p>
<p>So, backups.  DigitalOcean offer
&ldquo;<a href="https://www.digitalocean.com/products/spaces/">Spaces</a>&rdquo;, their
implementation of object storage with an S3-compatible API, which
seems ideal.  My threat model at this stage does not include their
data centre being razed.</p>
<p>The S3 API means I can use something like
<a href="https://github.com/s3tools/s3cmd">s3cmd</a> to upload snapshots.  In
theory, I could just tar up the data directory and upload it via
s3cmd.</p>
<p>In practice, there are a couple of issues that motivated this post in
case anyone else has similar constraints:</p>
<ul>
<li>Nextcloud is running via
<a href="https://github.com/nextcloud/docker">Docker</a>, meaning the data
directory is slightly abstracted</li>
<li>I don&rsquo;t have a large server, so Nextcloud occupies &gt; 50% of disk
space and there&rsquo;s no room for that tar file!  I&rsquo;ll have to figure
out streaming as well.</li>
</ul>
<h1 id="solution">Solution</h1>
<h2 id="preparation">Preparation</h2>
<p>Minor note, but we want to put Nextcloud into maintenance-mode for the
duration.  The following command will do that:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">php occ maintenance:mode --on
</span></span></code></pre></div><p>I also install a trap-EXIT in the shell script to disable maintenance
mode at the end.</p>
<h2 id="docker">Docker</h2>
<p>Well&hellip; docker-compose, which is another minor layer of abstraction to
thread through. The command above would <em>actually</em> be invoked by</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">docker-compose <span class="nb">exec</span> -T --user www-data app php occ maintenance:mode --on
</span></span></code></pre></div><p>(&ldquo;app&rdquo; is the name of the docker-compose container running nextcloud;
there&rsquo;s also one for the database, and the server)</p>
<p>Accessing the data was something I tried a few things around, and it&rsquo;s
possibly not the best solution.  I feel like you should be able to
back up the volume in a portable way, but for now I rely on invoking
<code>tar</code> directly from within the container, streaming to stdout.</p>
<p>That final point &mdash; &ldquo;stdout&rdquo; &mdash; is also a bit tricky; the secret is
the <code>-T</code> argument to exec, so we wind up with:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">docker-compose <span class="nb">exec</span> -T --user www-data app tar czf - data
</span></span></code></pre></div><p>(and something similar for the database).  The <code>-T</code> <a href="https://docs.docker.com/compose/reference/exec/">disables the
pseudo-TTY</a> that
otherwise gets allocated.</p>
<h2 id="uploading-and-gotchas">Uploading, and gotchas</h2>
<p>Now we have a stream of data to upload.  From memory the documentation
wasn&rsquo;t great, but <code>s3cmd</code> <em>can</em> operate in this way, as long as you
specify the object name, so you end up with something like (note the
&ldquo;-&rdquo; in both commands):</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">tar cvzf - ... <span class="p">|</span>
</span></span><span class="line"><span class="cl">s3cmd put - s3://mystoragebucket/backup_file
</span></span></code></pre></div><p>And we&rsquo;re almost done.  But we don&rsquo;t want to back up everything for
ever more!  So you need to configure a
<a href="https://developers.digitalocean.com/documentation/spaces/#create-bucket-lifecycle">lifecyle</a>
for your backups, so they will expire (and also, so I don&rsquo;t tip over
the included storage quota).</p>
<p>As it turns out, I did tip over the edge (only by $4), because there&rsquo;s
a trick I wasn&rsquo;t aware of.  Your lifecycle can configure a <em>prefix</em>,
which determines the files your expiration policy applies to.  I have
everything under /backups, so I tried:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="cl"><span class="nt">&lt;Prefix&gt;</span>/backups<span class="nt">&lt;/Prefix&gt;</span>
</span></span></code></pre></div><p>This did not work!  Sparing the colourful language that ensued, it
turns out that <em>you don&rsquo;t want to include the first /</em>.  I needed</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="cl"><span class="nt">&lt;Prefix&gt;</span>backups<span class="nt">&lt;/Prefix&gt;</span>
</span></span></code></pre></div><p>(In fact, that bucket is only used for backups so now I just use
<code>&lt;Prefix /&gt;</code>, but note that <code>&lt;Prefix&gt;/&lt;/Prefix&gt;</code> has the same
problem).  I&rsquo;m assuming the API refers to object names, and I&rsquo;ve been
thinking in terms of directory structures.</p>
<h2 id="putting-it-all-together">Putting it all together</h2>
<p>To wrap up, this is the shell script (as an Ansible template) that I
install, and then gets invoked by cron:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="cp">#!/bin/bash
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="nb">set</span> -eufo pipefail
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">DB_BACKUP</span><span class="o">=</span>nextcloud-db-<span class="k">$(</span>date +%Y%m%d-%s<span class="k">)</span>.dmp
</span></span><span class="line"><span class="cl"><span class="nv">DATA_BACKUP</span><span class="o">=</span>nextcloud-data-<span class="k">$(</span>date +%Y%m%d-%s<span class="k">)</span>.tgz
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># maintenance mode off again, even if we error out:</span>
</span></span><span class="line"><span class="cl">finish<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    docker-compose <span class="nb">exec</span> -T --user www-data app php occ maintenance:mode --off
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">trap</span> finish EXIT
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">cd</span> /srv/www/nextcloud
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># maintenance mode on</span>
</span></span><span class="line"><span class="cl">docker-compose <span class="nb">exec</span> -T --user www-data app php occ maintenance:mode --on
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># docker-compose to tar to output</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">docker-compose <span class="nb">exec</span> -T --user www-data app tar czf - data <span class="p">|</span>
</span></span><span class="line"><span class="cl">s3cmd --access_key<span class="o">={{</span> storage_apikey <span class="o">}}</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>--secret_key<span class="o">={{</span> storage_secret_key <span class="o">}}</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>--region<span class="o">={{</span> storage_region <span class="o">}}</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>--host<span class="o">=</span>digitaloceanspaces.com <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>--host-bucket<span class="o">=</span><span class="s2">&#34;%(bucket)s.{{ storage_region }}.digitaloceanspaces.com&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>put - s3://<span class="o">{{</span> storage_bucket_name <span class="o">}}</span>/backups/<span class="nv">$DATA_BACKUP</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># db backup</span>
</span></span><span class="line"><span class="cl">docker-compose <span class="nb">exec</span> -T --user postgres db pg_dump -Fc nextcloud <span class="p">|</span>
</span></span><span class="line"><span class="cl">s3cmd --access_key<span class="o">={{</span> storage_apikey <span class="o">}}</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>--secret_key<span class="o">={{</span> storage_secret_key <span class="o">}}</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>--region<span class="o">={{</span> storage_region <span class="o">}}</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>--host<span class="o">=</span>digitaloceanspaces.com <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>--host-bucket<span class="o">=</span><span class="s2">&#34;%(bucket)s.{{ storage_region }}.digitaloceanspaces.com&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>put - s3://<span class="o">{{</span> storage_bucket_name <span class="o">}}</span>/backups/<span class="nv">$DB_BACKUP</span>
</span></span></code></pre></div><div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Prompted by Dropbox&rsquo;s change in policy to only allow 3 devices
on free plans&hellip; can&rsquo;t say I blame them.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content>
		</item>
		
		<item>
			<title>Why Blog?</title>
			<link>https://blog.markhepburn.com/posts/why-blog/</link>
			<pubDate>Sun, 27 Jun 2021 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/why-blog/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>There&rsquo;s a nerdy, yak-shaving satisfaction in <a href="/posts/2021-06-20-another-new-blog-post/">migrating my blog
again</a>, but there
were other motivations in mind.</p>
<p>I could certainly do with the practice in writing.  Mostly though,
it&rsquo;s an incentive to start exploring again: when I first got into
computers, I grew up on <a href="https://www.debian.org/releases/slink/">Linux
systems</a> and really
appreciated the simplicity and <a href="https://www.debian.org/doc/manuals/debian-tutorial/index.html">documentation
available</a>.
I felt that I could run <code>ps</code>, and see 20-ish processes and know what
each one of them did.</p>
<p>These days, I&rsquo;m still most at-home on a minimalist Debian derivative,
but even there I don&rsquo;t recognise most of the output I see in a <code>ps</code>
dump.  I maintain a bunch of Linux servers at work, yet I&rsquo;m
increasingly aware of the topics and sub-systems that I never learned
in the same way as when I hoovered up that early knowledge.</p>
<p>One of my nerd-heroes is <a href="https://jvns.ca/">Julia Evans</a>.  Her
willingness to <a href="https://austinkleon.com/show-your-work/">learn out in the
open</a> and enthusiastically
document it all, from deep topics to
<a href="https://github.com/jbranchaud/til/">&ldquo;TIL&rdquo;</a> tidbits, is incredibly
refreshing.  I&rsquo;ve bought a bunch of her zines, and even though some
are topics I know in principle I&rsquo;ve gained something of value from
each and every one.</p>
<p>In the same vein I&rsquo;ve been collecting a range of topics I want to
understand, or understand better, or just topics where it may be
beneficial to have one more problem-solution document out there.  Some
are quickies for when I have time, while others (possibly most) could
turn into research deep-dives.  There&rsquo;s no pre-defined schedule, or
even a plan to publish either incrementally or post-hoc, just &mdash; at
least for now &mdash; an enthusiasm to get started again!</p>
]]></content>
		</item>
		
		<item>
			<title>Another New-Blog Post</title>
			<link>https://blog.markhepburn.com/posts/2021-06-20-another-new-blog-post/</link>
			<pubDate>Sun, 20 Jun 2021 12:52:31 +1000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2021-06-20-another-new-blog-post/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>So, nearly exactly 4 years since my <a href="/2017/06/12/quickie-using-figwheel-and-leiningen-as-a-proxy-server-for-fun-and-profit/">last post</a>, it&rsquo;s time for the <a href="">traditional software refresh</a>.</p>
<p>To date, I have gone through:</p>
<ul>
<li><a href="https://en.wikipedia.org/wiki/Posterous">Posterous</a> (it&rsquo;s dead now,
but it was a simple service that you emailed posts to)</li>
<li><a href="http://jekyllbootstrap.com/">Jekyll-bootstrap</a>; also more or less
dead or at least abandoned, but offered some structure around the
Jekyll static-sites engine.</li>
</ul>
<p>An advantage of <a href="https://jekyllrb.com/">Jekyll</a> at the time was its
support by Github-pages, which was where I moved after migrating from
Posterous.  I&rsquo;ve found it&rsquo;s a bit clunky though, I don&rsquo;t want to
invest the time in understanding the jekyll-bootstrap templates enough
to do any hacking on them, and the community has moved on.</p>
<p>In addition, hosting has migrated from Posterous, to Github-pages, to
my own server.  Arguably I have spent more time hacking on the tech
than actually posting.  Hugo templates may also take some learning,
but it&rsquo;s nice and fast and I&rsquo;m happy with the current template.</p>
<h2 id="process">Process</h2>
<p>I&rsquo;m not going into details this time around, but I&rsquo;ll share some notes
in case anyone wants to follow up.</p>
<p>There was an initial import script, both built-in and a few python
scripts I experimented with, but they mostly tweaked the front-matter
a bit.  I used a few sed scripts to convert some syntax from jekyll to
Hugo, as well as just fixing some manually.</p>
<p>Deployment was a chance to practice some stuff.  I&rsquo;ve switched to
Gitlab for repository-hosting, so I set up a pipeline there to build
the site, added a section to my Ansible playbook to download that and
install it (as a bootstrap measure), then additionally added a stage
to the Gitlab pipeline to push after build for ongoing posting without
involving Ansible as well.  There were a few interesting steps there
around locking it down that I may write quick posts about.</p>
<h2 id="to-do">To Do</h2>
<p>It&rsquo;s not perfect.  The main thing is the galleries are currently dead,
which is unfortunate as the original purpose of setting up a blog was
to share travel pictures.  They were hosted on Picasa &mdash; <em>also</em> dead
&mdash; though, so until I figure out how to embed Google-photos galleries
most posts will remain devoid of colour.</p>
<p>Some search-engine links have broken, and I&rsquo;ve only just realised that
there&rsquo;s a mix of /yyyy-mm-dd-title/ urls, and hierarchical
/yyyy/mm/dd/title/, but I think I can live with that now that it&rsquo;s out
there.</p>
]]></content>
		</item>
		
		<item>
			<title>Quickie: Lazy XML Parsing in Clojure with Namespaces</title>
			<link>https://blog.markhepburn.com/2017/06/12/quickie-lazy-xml-parsing-in-clojure-with-namespaces/</link>
			<pubDate>Mon, 12 Jun 2017 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/2017/06/12/quickie-lazy-xml-parsing-in-clojure-with-namespaces/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<h1 id="tldr">TL;DR:</h1>
<ul>
<li>Idiomatic XML processing in Clojure is possible and even easy, but
under-documented;</li>
<li>Namespace-XML support seems to be particularly hidden;</li>
<li>It works naturally by mapping to namespaced keywords.</li>
</ul>
<h1 id="the-details">The Details</h1>
<p>I still occasionally find myself writing XML processing code in
Clojure, either for production or one-off data munging tasks.  XML
support is quite good, and quite idiomatic, but I&rsquo;ve found that
getting started is often confusing.
Is <a href="https://github.com/clojure/data.xml">data.xml</a> all you need?
Where does <a href="https://clojure.github.io/data.zip/">data.zip</a> fit in?</p>
<p>The short explanation is that the first function you are likely to
find returns a Clojure structure with maps representing elements, but
then there&rsquo;s a similar function that is <em>lazy</em>, and there&rsquo;s also a
zipper library with some awesome processing functions that is probably
what you want, at least on the input side.  The best overview I&rsquo;ve
found is
<a href="http://blog.korny.info/2014/03/08/xml-for-fun-and-profit.html">this blog post</a>.</p>
<p>My code usually starts off something like this:<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-clj" data-lang="clj"><span class="line"><span class="cl"><span class="p">(</span><span class="ss">:require</span> <span class="p">[</span><span class="nv">clojure.data.xml</span> <span class="ss">:as</span> <span class="nv">xml</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="nv">clojure.data.zip.xml</span> <span class="ss">:as</span> <span class="nv">zx</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="nv">clojure.java.io</span> <span class="ss">:as</span> <span class="nv">io</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="nv">clojure.zip</span> <span class="ss">:as</span> <span class="nv">zip</span><span class="p">])</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nb">-&gt; </span><span class="nv">filename</span> <span class="nv">io/resource</span> <span class="nb">slurp </span><span class="nv">xml/parse-str</span> <span class="nv">zip/xml-zip</span><span class="p">)</span>
</span></span></code></pre></div><p>which you can then process using
the <a href="https://clojure.github.io/data.zip/">data.zip.xml</a> utilities,
generally starting with either <code>xml-&gt;</code> or <code>xml1-&gt;</code> (the latter
just produces a single result), and using keywords to traverse down
tag names:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-clj" data-lang="clj"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">zx/xml-&gt;</span> <span class="nv">zipped-xml</span> <span class="ss">:RootElement</span> <span class="ss">:SomeChild</span> <span class="nv">custom-processing-fn</span><span class="p">)</span>
</span></span></code></pre></div><p>(where <code>custom-processing-fn</code> is probably returns a structure out of
the <code>&lt;SomeChild&gt;</code> element)</p>
<p>The problem is: what if your document is namespaced, such as
<code>&lt;myns:SomeChild&gt;</code>?  Fortunately, it turns out that you can map these
exactly to Clojure namespaced-keywords.  The trick is the <code>alias-uri</code>
function:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-clj" data-lang="clj"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">xml/alias-uri</span> <span class="ss">&#39;sld</span> <span class="s">&#34;http://www.opengis.net/sld&#34;</span><span class="p">)</span>
</span></span></code></pre></div><p>and then you can proceed exactly as before, but with namespaces:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-clj" data-lang="clj"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">zx/xml-&gt;</span> <span class="nv">zipped-xml</span> <span class="ss">::sld/StyledLayerDescriptor</span> <span class="nv">....</span><span class="p">)</span>
</span></span></code></pre></div><div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Note that while this uses the lazy versions of the parsing
functions, the input is read eagerly.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content>
		</item>
		
		<item>
			<title>Quickie: Using figwheel and leiningen as a proxy server for fun and profit</title>
			<link>https://blog.markhepburn.com/2017/06/12/quickie-using-figwheel-and-leiningen-as-a-proxy-server-for-fun-and-profit/</link>
			<pubDate>Mon, 12 Jun 2017 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/2017/06/12/quickie-using-figwheel-and-leiningen-as-a-proxy-server-for-fun-and-profit/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<h1 id="overview">Overview:</h1>
<p>Leiningen is an awesome part of the Clojurescript landscape, doing
live reloading of code and CSS.  It even offers a static-file server,
if you happen to be developing a client-only application.</p>
<p>Less appreciated is that you can plug in your
own <a href="https://github.com/ring-clojure/ring">Ring</a> handler.  A
particularly convenient use-case that I&rsquo;ve recently discovered is to
plug in a proxy server, which has uses beyond client-only
applications.</p>
<p>There&rsquo;s three main use-cases justifying it for me:</p>
<ul>
<li>We frequently use a <a href="http://www.django-rest-framework.org/">Django API</a>
backend so it would normally make sense to use the Django
<a href="https://docs.djangoproject.com/en/1.11/ref/django-admin/#runserver">development server</a>,
but on Windows this is unbearably slow (with the number of files
generated by Clojurescript in dev-mode).  Our previous solution
involved nginx, which works but is a more complicated set-up.</li>
<li>If you are using a third-party service that hasn&rsquo;t enabled CORS yet,
you can proxy to it from your local server instead.</li>
<li>If you <em>are</em> still doing client-only development, but need to assume
an AJAX service will be available on the eventual host, you can
still refer to it using server-less URL paths and simply proxy to
the test service.</li>
</ul>
<h1 id="how-to">How-To:</h1>
<p>There is a
<a href="https://github.com/bhauman/lein-figwheel/tree/master/examples/using-ring-handler">sample project</a> in
the leiningen repo, but essentially all you need to do is define your
handler, and specify it in the <code>:ring-handler</code> entry of your
<code>:figwheel</code> configuration in <code>project.clj</code> .</p>
<p>You have a few options for Ring proxy handlers, but the one I went
with is this one:
<a href="https://github.com/tailrecursion/ring-proxy">tailrecursion/ring-proxy</a>.</p>
<p>To use it, grab the leiningen sample and extend it for your needs:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-clj" data-lang="clj"><span class="line"><span class="cl"><span class="p">(</span><span class="kd">ns </span><span class="nv">com.etbwc.dev-handlers</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="ss">:require</span> <span class="p">[</span><span class="nv">compojure.core</span> <span class="ss">:refer</span> <span class="p">[</span><span class="nv">defroutes</span> <span class="nv">GET</span><span class="p">]]</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="nv">compojure.route</span> <span class="ss">:as</span> <span class="nv">route</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="nv">ring.middleware.defaults</span> <span class="ss">:refer</span> <span class="p">[</span><span class="nv">wrap-defaults</span> <span class="nv">site-defaults</span><span class="p">]]</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="nv">ring.util.response</span> <span class="ss">:as</span> <span class="nv">response</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="nv">tailrecursion.ring-proxy</span> <span class="ss">:refer</span> <span class="p">[</span><span class="nv">wrap-proxy</span><span class="p">]]))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">defroutes</span> <span class="nv">app-routes</span>
</span></span><span class="line"><span class="cl">  <span class="c1">;; NOTE: this will deliver all of your assets from the public directory</span>
</span></span><span class="line"><span class="cl">  <span class="c1">;; of resources i.e. resources/public</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nf">route/resources</span> <span class="s">&#34;/&#34;</span> <span class="p">{</span><span class="ss">:root</span> <span class="s">&#34;public&#34;</span><span class="p">})</span>
</span></span><span class="line"><span class="cl">  <span class="c1">;; NOTE: this will deliver your index.html</span>
</span></span><span class="line"><span class="cl">  <span class="o">#</span><span class="p">(</span><span class="nf">GET</span> <span class="s">&#34;/&#34;</span> <span class="p">[]</span> <span class="p">(</span><span class="nb">-&gt; </span><span class="p">(</span><span class="nf">response/resource-response</span> <span class="s">&#34;index.html&#34;</span> <span class="p">{</span><span class="ss">:root</span> <span class="s">&#34;public&#34;</span><span class="p">})</span>
</span></span><span class="line"><span class="cl">                  <span class="p">(</span><span class="nf">response/content-type</span> <span class="s">&#34;text/html&#34;</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nf">route/not-found</span> <span class="s">&#34;Not Found&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="k">def </span><span class="nv">app</span> <span class="p">(</span><span class="nb">-&gt; </span><span class="nv">app-routes</span>
</span></span><span class="line"><span class="cl">             <span class="p">(</span><span class="nf">wrap-defaults</span> <span class="nv">site-defaults</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">             <span class="c1">;; Use a django API on a different localhost port:</span>
</span></span><span class="line"><span class="cl">             <span class="p">(</span><span class="nf">wrap-proxy</span> <span class="s">&#34;/api&#34;</span> <span class="s">&#34;http://localhost:8000/api&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">             <span class="c1">;; Use the django static-files if you need for eg the admin site:</span>
</span></span><span class="line"><span class="cl">             <span class="p">(</span><span class="nf">wrap-proxy</span> <span class="s">&#34;/static&#34;</span> <span class="s">&#34;http://localhost:8000/static&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">             <span class="c1">;; Proxy requests to a third-party API without CORS enabled:</span>
</span></span><span class="line"><span class="cl">             <span class="p">(</span><span class="nf">wrap-proxy</span> <span class="s">&#34;/pq&#34;</span> <span class="s">&#34;http://third.party.com/pq&#34;</span><span class="p">)))</span>
</span></span></code></pre></div><p>Now to use the handler simply mention it in <code>project.clj</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-clj" data-lang="clj"><span class="line"><span class="cl"><span class="p">(</span><span class="kd">defproject </span><span class="s">&#34;etbwc-example&#34;</span> <span class="s">&#34;0.1.0-SNAPSHOT&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="c1">;;...</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="ss">:figwheel</span> <span class="p">{</span><span class="ss">:http-server-root</span> <span class="s">&#34;public&#34;</span>
</span></span><span class="line"><span class="cl">             <span class="ss">:server-port</span>      <span class="mi">3451</span>
</span></span><span class="line"><span class="cl">             <span class="ss">:nrepl-port</span>       <span class="mi">7892</span>
</span></span><span class="line"><span class="cl">             <span class="c1">;; Boom:</span>
</span></span><span class="line"><span class="cl">             <span class="ss">:ring-handler</span>     <span class="nv">com.etbwc.dev-handlers/app</span>
</span></span><span class="line"><span class="cl">             <span class="ss">:css-dirs</span>         <span class="p">[</span><span class="s">&#34;resources/public/css&#34;</span><span class="p">]}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1">;;...</span>
</span></span><span class="line"><span class="cl">  <span class="p">)</span>
</span></span></code></pre></div>]]></content>
		</item>
		
		<item>
			<title>Emacs and filenotify</title>
			<link>https://blog.markhepburn.com/2015/09/27/emacs-and-filenotify/</link>
			<pubDate>Sun, 27 Sep 2015 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/2015/09/27/emacs-and-filenotify/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>Here&rsquo;s another Emacs quickie.  Some time ago I wrote about
<a href="/2014/05/20/parsing-ssh-agent-variables-in-emacs/">parsing ssh agent variables in elisp</a>.
To recap, the issue was that in windows Emacs is started separately
from <a href="https://git-for-windows.github.io/">git-bash</a>, so it doesn&rsquo;t
inherit the environment variables to make it seemlessly use your ssh
keys.  My quick and dirty solution was to write a function to parse a
file containing those variables.</p>
<p>That works fine, but it does mean you have to manually invoke that
function.  You could run the function on load, but then you have to
remember to start git-bash first.</p>
<p>It&rsquo;s not an ideal situation, and the other day I finally wondered if
Emacs had any file-watching
library&hellip; <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/File-Notifications.html">of course it does</a>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-scheme" data-lang="scheme"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">defvar</span> <span class="nv">ssh-file-watcher</span> <span class="nv">nil</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">when</span> <span class="p">(</span><span class="nf">require</span> <span class="ss">&#39;filenotify</span> <span class="nv">nil</span> <span class="nv">t</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="c1">;; We&#39;re loading up, slurp SSH envs in case in they&#39;re already</span>
</span></span><span class="line"><span class="cl">  <span class="c1">;; correct:</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nf">mh/parse-sshagent-env</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="c1">;; Clear any existing watcher:</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="k">if </span><span class="nv">ssh-file-watcher</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nf">file-notify-rm-watch</span> <span class="nv">ssh-file-watcher</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">  <span class="c1">;; Create the new watcher:</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nf">setq</span> <span class="nv">ssh-file-watcher</span>
</span></span><span class="line"><span class="cl">        <span class="p">(</span><span class="nf">file-notify-add-watch</span> <span class="p">(</span><span class="nf">expand-file-name</span> <span class="s">&#34;~/.ssh/agent.env&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                               <span class="o">&#39;</span><span class="p">(</span><span class="nv">change</span> <span class="nv">attribute-change</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                               <span class="ss">&#39;mh/parse-sshagent-env</span><span class="p">)))</span>
</span></span></code></pre></div><p>In other words, another 5 minutes of hacking and now we simply load
the variables just in case, clear any existing watcher, and start
watching the file for changes &mdash; when it does, we simply slurp
again.  If you follow this verbatim, the only addition you&rsquo;ll need to
make is to ensure that your callback function accepts the arguments
filenotify will give it; I just ignored them: <code>(defun mh/parse-sshagent-env (&amp;rest ignored)... </code></p>
<p>Much more painless!</p>
]]></content>
		</item>
		
		<item>
			<title>Fail Environments</title>
			<link>https://blog.markhepburn.com/2014/07/05/fail-environments/</link>
			<pubDate>Sat, 05 Jul 2014 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/2014/07/05/fail-environments/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>Friends of mine have recently starting using the term &ldquo;fail
environment&rdquo;, as in &ldquo;you created a&hellip;&rdquo;.  It hasn&rsquo;t even hit
<a href="http://www.urbandictionary.com/">Urban Dictionary</a> yet so I think
they can safely claim it, but it&rsquo;s a brilliant expression.  Roughly,
it means</p>
<blockquote>
<p><em>Creating circumstances, typically by omission of information,
through which another person is more likely to fail.</em></p>
</blockquote>
<p>I&rsquo;m perhaps overly dramatising since I was first introduced to it when
I said <em>&ldquo;Meet me at Cafe X&rdquo;</em> when there were in fact two of them; none
the less, I believe it deserves to be in common usage.</p>
<p>Unfortunately, I was witness to a much more serious example only
yesterday.  I&rsquo;ve been doing some work with Microsoft&rsquo;s SQL Server,
working on a local copy of a database (importing data, writing
procedures, and so on).  It came time to reconcile some changes, and
to be cautious we decided to do it manually, using the
backup-and-restore feature to copy my database to the destination
server.</p>
<p>The Management Studio has a nice interface to backing up a database,
pretty much as you&rsquo;d expect a GUI environment to provide: right-click,
select &ldquo;backup&rdquo; and a save location, and you have a single portable
file.</p>
<p><em>Restoring</em> from this file is a little less intuitive, but the 2012
update made it
<a href="http://connect.microsoft.com/SQLServer/feedback/details/779190/sql-server-2012-ssms-silently-overwrites-db-name-and-can-cause-accidental-overwrites-and-data-loss">much, much worse</a>.</p>
<p>By default, when you restore a file it will restore the entire
database, to a database of the <em>same name</em> (granted, probably the main
use-case).  In our case though we were going to restore to a temporary
database on a different server, and manually copy selected changes
across to the original that way.</p>
<p>The process is basically to create a new database, right-click and
select &ldquo;restore&rdquo;&hellip; and now the fail environment emerges.  You have to
switch to a different tab to find your backup file, and when you
select it <em>the destination database silently changes, on the first
hidden tab, to the one with the same name as the original database,
NOT the temporary one you just selected</em>.  My colleague doing this is
very competent and experienced and actually knew this complication,
but while we were checking something else he forgot&hellip;<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> and overwrote
the last three days of his work with mine.</p>
<p>I call that a fail environment.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>In part there&rsquo;s a few other complications to performing this
procedure; you have to manually edit some file names as well for
example.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content>
		</item>
		
		<item>
			<title>Customising markdown-mode for Jekyll</title>
			<link>https://blog.markhepburn.com/2014/06/05/customising-markdown-mode-for-jekyll/</link>
			<pubDate>Thu, 05 Jun 2014 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/2014/06/05/customising-markdown-mode-for-jekyll/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>This blog is written using <a href="http://jekyllrb.com/">Jekyll</a>,<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> a
static site generator using
<a href="http://daringfireball.net/projects/markdown/">markdown</a> and
<a href="http://liquidmarkup.org/">Liquid</a> templates.  It&rsquo;s very easy to use,
can be hosted cheaply anywhere since everything is static, and Github
will
<a href="https://help.github.com/articles/using-jekyll-with-pages">even compile it</a>
for you in addition to hosting.</p>
<p>Naturally, there is a
<a href="http://jblevins.org/projects/markdown-mode/">markdown-mode</a> for
Emacs, and it&rsquo;s quite good.</p>
<p>I did run into one issue though, due to interactions with Liquid
syntax.  By way of example, this is the syntax for a link in markdown:</p>
<pre><code>[anchor text](http://www.google.com)
</code></pre>
<p>(Which renders as &ldquo;<a href="http://www.google.com">anchor text</a>&rdquo;).  Jekyll also
provides a useful Liquid tag to link to previous posts, for example:</p>
<pre><code>[older post]({% post_url 2014-05-20-parsing-ssh-agent-variables-in-emacs %})
</code></pre>
<p>This renders as &ldquo;<a href="/2014/05/20/parsing-ssh-agent-variables-in-emacs/">older post</a>&rdquo;.</p>
<p>The issue occurs in conjunction with
<a href="http://www.emacswiki.org/emacs/FillParagraph">paragraph filling</a>.
Both markdown and liquid require the examples above to be unbroken on
a single line.  Markdown-mode does the right thing and ensures the
anchor text won&rsquo;t be broken, but also correctly assumes that the URL
won&rsquo;t have spaces and thus will be safe.  In conjunction with liquid
though, it&rsquo;s possible to have a situation like this, which will break
Jekyll:</p>
<pre><code>[older post]({% post_url
2014-05-20-parsing-ssh-agent-variables-in-emacs %})
</code></pre>
<p>Creating a fix requires some understanding of how filling commands
work.<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup> Roughly, when a command like <code>fill-paragraph</code> is invoked
Emacs starts at the beginning of a line, jumps forward to the
<code>fill-column</code>, and then looks for white-space at which it can insert a
newline.  The wrinkle is it first checks if it is <em>safe</em> to break
there, using a customisable variable called <code>fill-nobreak-predicate</code>.
To get an example, we can look at how markdown-mode ensures it won&rsquo;t
break inside the square brackets of a link definition:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-scheme" data-lang="scheme"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">defun</span> <span class="nv">markdown-nobreak-p</span> <span class="p">()</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;Return nil if it is acceptable to break the current line at the point.&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="c1">;; inside in square brackets (e.g., link anchor text)</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nf">looking-back</span> <span class="s">&#34;\\[[^]]*&#34;</span><span class="p">))</span>
</span></span></code></pre></div><p>As you see, it just looks back to see if there&rsquo;s an opening bracket
(that isn&rsquo;t followed by a closing one).  We can use the same strategy
to check if we&rsquo;re in a liquid tag:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-scheme" data-lang="scheme"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">defun</span> <span class="nv">mh/liquid-nobreak-p</span> <span class="p">()</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nf">looking-back</span> <span class="s">&#34;({{ &#34;</span><span class="err">{</span><span class="nv">%</span><span class="s">&#34; }}[^%]*&#34;</span><span class="p">))</span>
</span></span></code></pre></div><p>Notice that we&rsquo;re <em>not</em> worried about the anchor-text case here!
That&rsquo;s because <code>fill-nobreak-predicate</code> is a <em>hook variable</em>; that is,
a list of functions, and in this case invoked until one of them
returns non-nil, indicating that we shouldn&rsquo;t break at this point.<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup>
In other words, we want to add to this list, not replace or advise
anything.</p>
<p>So now to incorporate our addition we just use the mode hook, and
remember to also use <code>add-hook</code> with our new predicate:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-scheme" data-lang="scheme"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">add-hook</span> <span class="ss">&#39;markdown-mode-hook</span>
</span></span><span class="line"><span class="cl">          <span class="p">(</span><span class="k">lambda </span><span class="p">()</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="nf">add-hook</span> <span class="ss">&#39;fill-nobreak-predicate</span> <span class="ss">&#39;mh/liquid-nobreak-p</span><span class="p">)))</span>
</span></span></code></pre></div><p>And now we&rsquo;re done, and can get back to blogging.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Specifically, <a href="http://jekyllbootstrap.com/">Jekyll Bootstrap</a>,
although I&rsquo;d probably just use plain Jekyll if I was starting
again.  It&rsquo;s a useful set of defaults though.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>See <code>fill-region-as-paragraph</code> for the details; follow down
through <code>fill-move-to-break-point</code> then <code>fill-nobreak-p</code> for the
invocation of <code>fill-nobreak-predicate</code>.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>See <code>run-hook-with-args-until-success</code>.&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content>
		</item>
		
		<item>
			<title>The next looming, slightly less serious, 2 digit year problem</title>
			<link>https://blog.markhepburn.com/2014/05/28/the-next-looming-slightly-less-serious-2-digit-year-problem/</link>
			<pubDate>Wed, 28 May 2014 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/2014/05/28/the-next-looming-slightly-less-serious-2-digit-year-problem/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>Roughly 15 years ago there was an
<a href="http://en.wikipedia.org/wiki/Year_2000_problem">intense crisis</a> as
people realised that the results of only storing the final two digits
of a year were about to become quite ambiguous.<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>
<p>A variation of this ambiguity still exists; date-parsing functions
such as <code>strptime</code> have to deal with it all the time.  The
standards<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup> pick a pivot value&mdash;69&mdash;and everything on or after
that is interpreted as 19XX, everything before as 20XX.</p>
<p>For example:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-C" data-lang="C"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;time.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">struct</span> <span class="n">tm</span> <span class="n">result</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">char</span> <span class="n">buf</span><span class="p">[</span><span class="mi">255</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="nf">strptime</span><span class="p">(</span><span class="s">&#34;68&#34;</span><span class="p">,</span> <span class="s">&#34;%y&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">result</span><span class="p">))</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">strftime</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">),</span> <span class="s">&#34;%Y&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">result</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="nf">puts</span><span class="p">(</span><span class="n">buf</span><span class="p">);</span>              <span class="cm">/* 2068 */</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="nf">strptime</span><span class="p">(</span><span class="s">&#34;69&#34;</span><span class="p">,</span> <span class="s">&#34;%y&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">result</span><span class="p">))</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">strftime</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">),</span> <span class="s">&#34;%Y&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">result</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="nf">puts</span><span class="p">(</span><span class="n">buf</span><span class="p">);</span>              <span class="cm">/* 1969 */</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>By my reckoning, this means we are heading for another crisis in about
45 years.<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup>  I suggest you start stocking your bomb shelter with
non-perishables now.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>It was so intense that there was almost a feeling of rage
afterwards; &ldquo;What do you mean, we spent all this money preventing
it, and then <em>nothing actually happened</em>??&rdquo;&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p><a href="http://en.wikipedia.org/wiki/X/Open">X/Open</a> Common Application
Environment and <a href="http://en.wikipedia.org/wiki/POSIX">POSIX</a>&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>Unless of course you believe the earlier-looming
<a href="http://en.wikipedia.org/wiki/Year_2038_problem">2038 problem</a>
spells doom first.&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content>
		</item>
		
		<item>
			<title>Embedding Git Revision in projects, via Powershell</title>
			<link>https://blog.markhepburn.com/2014/05/26/embedding-git-revision-in-projects-via-powershell/</link>
			<pubDate>Mon, 26 May 2014 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/2014/05/26/embedding-git-revision-in-projects-via-powershell/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p><a href="http://www.condense.com.au/">We</a> have been working on an
<a href="http://azure.microsoft.com/">Azure</a> cloud-services project, with a
web interface.  With constant updates it suddenly occurred to us that
we had no system for determining exactly which revision was deployed.
Embedding the revision identifier from your source control system&mdash;in
our case <a href="http://git-scm.com/">git</a>&mdash;is a standard approach, and this
post documents our implementation and a couple of wrinkles
encountered.<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>
<h1 id="overview">Overview</h1>
<p>Essentially, we need to do three things:</p>
<ol>
<li>Find the git SHA of the working copy;</li>
<li>Embed this somewhere useful;</li>
<li>Make sure it does this automatically before you deploy.</li>
</ol>
<p>^
The last step is the easiest: you just run it as a
<a href="http://msdn.microsoft.com/en-us/library/ms366724.aspx">pre-build hook</a>.</p>
<h1 id="how-to-display-it">How to display it</h1>
<p>The closest description I could find of what we envisaged was
<a href="https://gist.github.com/abdullin/63cdbbe71218561820e5">this article</a>.<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>
He outlines how to update the deployment label<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup> in the
<code>.azurepubXml</code>
<a href="http://msdn.microsoft.com/en-us/library/hh369934.aspx">profile</a>,
which was exactly what we were looking for.  We eventually abandoned
that aspect though because when you deploy directly from Visual Studio
the profile is read <em>before</em> you hit &ldquo;publish&rdquo;, or in other words
before your pre-build script has run and done anything useful.</p>
<p>Instead, we just write it to an HTML template that can be sourced
anywhere: in a comment in every page, or on the administrators-only
dashboard, or in the footer&hellip; it&rsquo;s up to you.</p>
<p>The catch of course is you will now have a modified-file showing up in
your git status every time you build.  The solution to this is two-fold:</p>
<ul>
<li>Add the file to your .gitignore, and</li>
<li>Change your <code>.csproj</code> file to only include the file if it exists.</li>
</ul>
<p>For the latter, you will need to edit it by hand:</p>
<pre tabindex="0"><code>&lt;Content Include=&#34;Views\Shared\_GitRev.cshtml&#34;
         Condition=&#34; Exists(&#39;Views\Shared\_GitRev.cshtml&#39;) &#34; /&gt;
</code></pre><p>As a bonus third step, you might want to think about how to gracefully
fail if that template doesn&rsquo;t exist for some reason.  Assuming
<a href="http://www.asp.net/web-pages">razor templates</a>, an extension method
is a useful approach:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-csharp" data-lang="csharp"><span class="line"><span class="cl"><span class="kd">public</span> <span class="kd">static</span> <span class="n">MvcHtmlString</span> <span class="n">PartialIfExists</span><span class="p">(</span><span class="k">this</span> <span class="n">HtmlHelper</span> <span class="n">html</span><span class="p">,</span> <span class="kt">string</span> <span class="n">viewname</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kt">var</span> <span class="n">controllerContext</span> <span class="p">=</span> <span class="n">html</span><span class="p">.</span><span class="n">ViewContext</span><span class="p">.</span><span class="n">Controller</span><span class="p">.</span><span class="n">ControllerContext</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">var</span> <span class="n">result</span> <span class="p">=</span> <span class="n">ViewEngines</span><span class="p">.</span><span class="n">Engines</span><span class="p">.</span><span class="n">FindView</span><span class="p">(</span><span class="n">controllerContext</span><span class="p">,</span> <span class="n">viewname</span><span class="p">,</span> <span class="kc">null</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">result</span><span class="p">.</span><span class="n">View</span> <span class="p">!=</span> <span class="kc">null</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">html</span><span class="p">.</span><span class="n">Partial</span><span class="p">(</span><span class="n">viewname</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="k">else</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">MvcHtmlString</span><span class="p">.</span><span class="n">Empty</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Then your templates might contain something like</p>
<pre tabindex="0"><code>...
&lt;!-- @Html.PartialIfExists(&#34;_GitRev&#34;) --&gt;
...
</code></pre><h1 id="attempt-1-gitexe-and-powershell">Attempt 1: git.exe and powershell</h1>
<p>The first version used the git executable to find the revision:</p>
<pre tabindex="0"><code>git rev-parse HEAD
</code></pre><p>A simple
<a href="http://technet.microsoft.com/en-us/library/bb978526.aspx">powershell</a>
script ties it together, and we&rsquo;re in business:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="nb">Get-Command</span> <span class="s2">&#34;git.exe&#34;</span> <span class="n">-ErrorAction</span> <span class="n">SilentlyContinue</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nv">$revision</span> <span class="p">=</span> <span class="n">git</span> <span class="nb">rev-parse</span> <span class="n">HEAD</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c"># make sure we don&#39;t include old versions if for some reason we</span>
</span></span><span class="line"><span class="cl">    <span class="c"># have one, but now can&#39;t find git.exe:</span>
</span></span><span class="line"><span class="cl">    <span class="nv">$template</span> <span class="p">=</span> <span class="s2">&#34;</span><span class="nv">$PSScriptRoot</span><span class="s2">\..\Views\Shared\_GitRev.cshtml&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="nb">Test-Path</span> <span class="nv">$template</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nb">Remove-Item</span> <span class="nv">$template</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nb">Set-Content</span> <span class="nv">$template</span> <span class="nv">$revision</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>For completeness, it&rsquo;s also worth pointing out here that it may be
necessary to
<a href="http://technet.microsoft.com/en-us/library/ee176949.aspx">enable script execution</a>
for powershell permissions.  I also include this line in my build
hook:</p>
<pre tabindex="0"><code>powershell -Command &#34;Set-ExecutionPolicy -Scope CurrentUser Unrestricted&#34;
</code></pre><h1 id="attempt-2-powershell-native">Attempt 2: Powershell-Native</h1>
<p>That worked, but it introduces complications such as the need for git
to be in your path, and generally feels a little fragile.</p>
<p>Luckily, I remembered <a href="http://libgit2.github.com/">libgit2</a>, a
portable standalone implementation of core git functionality.  There
are <a href="https://github.com/libgit2/libgit2sharp">.NET bindings</a> and
<a href="http://www.nuget.org/packages/LibGit2Sharp/">nuget</a> handles
installation so this was much more promising:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="k">try</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c"># Note use of wildcard to ignore the version.</span>
</span></span><span class="line"><span class="cl">    <span class="nb">Add-Type</span> <span class="n">-Path</span> <span class="nv">$PSScriptRoot</span><span class="p">\..\..\</span><span class="n">packages</span><span class="p">\</span><span class="n">LibGit2Sharp</span><span class="p">*\</span><span class="n">lib</span><span class="p">\</span><span class="n">net35</span><span class="p">\</span><span class="n">LibGit2Sharp</span><span class="p">.</span><span class="py">dll</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nv">$repo</span> <span class="p">=</span> <span class="nb">New-Object</span> <span class="n">-TypeName</span> <span class="n">LibGit2Sharp</span><span class="p">.</span><span class="py">Repository</span> <span class="n">-ArgumentList</span> <span class="s2">&#34;</span><span class="nv">$PSScriptRoot</span><span class="s2">\..\..\..\.git&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nv">$template</span> <span class="p">=</span> <span class="s2">&#34;</span><span class="nv">$PSScriptRoot</span><span class="s2">\..\Views\Shared\_GitRev.cshtml&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="nb">Test-Path</span> <span class="nv">$template</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nb">Remove-Item</span> <span class="nv">$template</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nv">$revision</span> <span class="p">=</span> <span class="nv">$repo</span><span class="p">.</span><span class="py">Head</span><span class="p">.</span><span class="py">Tip</span><span class="p">.</span><span class="py">Sha</span>
</span></span><span class="line"><span class="cl">    <span class="nv">$dirty</span> <span class="p">=</span> <span class="p">(</span> <span class="nv">$repo</span><span class="p">.</span><span class="py">Index</span><span class="p">.</span><span class="py">RetrieveStatus</span><span class="p">()</span> <span class="p">|</span> <span class="p">?</span> <span class="p">{</span> <span class="nv">$_</span><span class="p">.</span><span class="py">State</span> <span class="o">-eq</span> <span class="s2">&#34;Modified&#34;</span> <span class="p">}</span> <span class="p">).</span><span class="n">Count</span> <span class="o">-gt</span> <span class="mf">0</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="nv">$dirty</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nv">$revision</span> <span class="p">=</span> <span class="s2">&#34;</span><span class="nv">$revision</span><span class="s2">*&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nb">Set-Content</span> <span class="nv">$template</span> <span class="nv">$revision</span>
</span></span><span class="line"><span class="cl">    <span class="nb">Write-Host</span> <span class="s2">&#34;Labelled with </span><span class="nv">$revision</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="k">catch</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nb">Write-Host</span> <span class="s2">&#34;Exception during git-rev labelling; ignoring&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>We use <code>Add-Type</code> to load the DLL (the hard-coded paths here feel
slightly dirty, I admit, but we can use a wild-card to mitigate
against version changes at least), then instantiate the
<a href="https://github.com/libgit2/libgit2sharp/blob/master/LibGit2Sharp/Repository.cs"><code>Repository</code></a>
object.  The SHA can then be accessed with <code>$repo.Head.Tip.Sha</code>.  The
next line also checks if any files are modified, a tweak which wasn&rsquo;t
present in the previous version.</p>
<h1 id="aftermath">Aftermath</h1>
<p>This is the script now running as part of our builds.  It works like a
charm, but looking back it feels like more work than it should have
been.  I&rsquo;m still relatively new to the Microsoft environment and
tool-chain, so if there&rsquo;s an easier way of doing this that I&rsquo;m
overlooking please let me know!</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>It&rsquo;s worth pointing out that what we&rsquo;re about to do is a
standard feature in
<a href="http://svnbook.red-bean.com/en/1.4/svn.advanced.props.special.keywords.html">subversion</a>
and others.  Git doesn&rsquo;t, and although it&rsquo;s a pretty common
question on stackoverflow, Linus is
<a href="http://www.gelato.unsw.edu.au/archives/git/0610/28891.html">not a fan</a>.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>In between me finding that post and writing this, the
<a href="http://abdullin.com/">author</a> pulled it because he would do
things differently now.  He was kind enough to place it on github
and let me link to it though.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>In other words, instead of &ldquo;MyApp - 26/05/2014 16:32:39&rdquo; you now
see &ldquo;MyApp - 26/05/2014 16:32:39 -
01c5059500fa59c0f138d2f947f8493dd0a8914a&rdquo;&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content>
		</item>
		
		<item>
			<title>Parsing ssh agent variables in Emacs</title>
			<link>https://blog.markhepburn.com/2014/05/20/parsing-ssh-agent-variables-in-emacs/</link>
			<pubDate>Tue, 20 May 2014 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/2014/05/20/parsing-ssh-agent-variables-in-emacs/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>Recently I have found myself working in Windows land, for the first
time in quite a while.  It wasn&rsquo;t long before I had
<a href="http://ftp.gnu.org/gnu/emacs/windows/">Emacs</a> installed of course,
but my main incentive was actually
<a href="http://magit.github.io/">magit</a>.<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>
<p>The only problem was I still couldn&rsquo;t fetch or push using magit,
because it didn&rsquo;t have the ssh-agent environment variables.  This was
because I wasn&rsquo;t launching Emacs from a shell, but fortunately I
remembered that the bit of shell code I&rsquo;d
<a href="https://help.github.com/articles/working-with-ssh-key-passphrases">cribbed from github</a>
to set up ssh-agent there also handily left them in a file.</p>
<p>The file looks like this:</p>
<pre><code>SSH_AUTH_SOCK=/tmp/ssh-WOAJeX1728/agent.1728; export SSH_AUTH_SOCK;
SSH_AGENT_PID=4880; export SSH_AGENT_PID;
echo Agent pid 4880;
</code></pre>
<p>After realising this it was just a few minutes of rolling up the
sleeves and writing some elisp to parse this and set the variables
locally:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-scheme" data-lang="scheme"><span class="line"><span class="cl"><span class="c1">;;; Set variables for ssh interaction, assuming they exist in a file ~/.ssh/agent.env.</span>
</span></span><span class="line"><span class="cl"><span class="c1">;;; See https://help.github.com/articles/working-with-ssh-key-passphrases</span>
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">defun</span> <span class="nv">mh/parse-sshagent-env</span> <span class="p">()</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nf">interactive</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nf">with-temp-buffer</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nf">insert-file-contents</span> <span class="p">(</span><span class="nf">expand-file-name</span> <span class="s">&#34;~/.ssh/agent.env&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nf">dolist</span> <span class="p">(</span><span class="nf">varname</span> <span class="o">&#39;</span><span class="p">(</span><span class="s">&#34;SSH_AUTH_SOCK&#34;</span> <span class="s">&#34;SSH_AGENT_PID&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nf">goto-char</span> <span class="mi">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nf">re-search-forward</span> <span class="p">(</span><span class="nf">concat</span> <span class="nv">varname</span> <span class="s">&#34;=\\([^;]+\\)&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nf">setenv</span> <span class="nv">varname</span> <span class="p">(</span><span class="nf">match-string</span> <span class="mi">1</span><span class="p">)))))</span>
</span></span></code></pre></div><p>It&rsquo;s very quicky and dirty, but it works for me:</p>
<ul>
<li>slurp the file into a temporary buffer;</li>
<li>for each of the variables we&rsquo;re interested in, look for its value
(the regexp simply grabs everything in between the equals and the
following semi-colon);</li>
<li>finally, use
<a href="http://www.gnu.org/software/emacs/manual/html_node/elisp/System-Environment.html"><code>setenv</code></a>
to make it available inside Emacs.</li>
</ul>
<p>Of course, I was able to develop this without leaving Emacs once;
searching the documentation to remember how to access captured groups,
testing the regexp, incrementally developing and finally &ldquo;installing&rdquo;
the function and getting back to work.  I&rsquo;m sure this particular hack
has been done many times before, but it was just as much fun and
didn&rsquo;t take much longer to do it myself&mdash;this is why I love working
in Emacs!</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Unfortunately I still use the command-line most of the time;
magit on windows is frustratingly slow.  Simply expanding a diff
takes around 3 seconds.  If anyone has any fixes I&rsquo;d be very
grateful.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content>
		</item>
		
		<item>
			<title>Recovering svn bdb repositories from endian issues</title>
			<link>https://blog.markhepburn.com/2014/05/18/recovering-svn-bdb-repositories-from-endian-issues/</link>
			<pubDate>Sun, 18 May 2014 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/2014/05/18/recovering-svn-bdb-repositories-from-endian-issues/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p><em>Update: <a href="#comment-1736953527">Dominic</a> has a few tips to make this an
even easier process.</em></p>
<p>The other day I came across the old
<a href="http://subversion.apache.org/">subversion</a> repository for my thesis<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>,
and thought it would be a good idea to convert it to
<a href="http://git-scm.com/">git</a> and back it up
<a href="https://github.com/">somewhere</a>. Immediate problem: I couldn&rsquo;t even
read it!  This post is a short description of what the problem was,
and how it was resolved.</p>
<h1 id="the-problem">The Problem</h1>
<p>The repository uses the old (deprecated) BerkelyDB file-system type.
Let&rsquo;s try and browse it:</p>
<pre tabindex="0"><code>$ svn ls file:///home/mark/_SVNREPOS/thesis
svn: E180001: Unable to connect to a repository at URL &#39;file:///home/mark/_SVNREPOS/thesis&#39;
svn: E180001: Unable to open an ra_local session to URL
svn: E180001: Unable to open repository &#39;file:///home/mark/_SVNREPOS/thesis&#39;
svn: E160029: Berkeley DB error for filesystem &#39;/home/mark/_SVNREPOS/thesis/db&#39; while opening environment:

svn: E160029: BDB0087 DB_RUNRECOVERY: Fatal error, run database recovery
svn: E160029: bdb: BDB2530 Ignoring log file: /home/mark/_SVNREPOS/thesis/db/log.0000000018: magic number 88090400, not 40988
svn: E160029: bdb: BDB2527 Invalid log file: log.0000000018: Invalid argument
svn: E160029: bdb: BDB0061 PANIC: Invalid argument
svn: E160029: bdb: BDB1546 unable to join the environment
</code></pre><p>Oops.  The key is in the fragment &ldquo;<code>magic number 88090400, not 40988</code>&rdquo;, which looks suspiciously like an
<a href="https://en.wikipedia.org/wiki/Endianness">endianness</a> issue
(88-09-04-00 / 00-04-09-88).  It was created on a PPC Mac and I&rsquo;m now
trying to access it from an Intel box, so that seems like a reasonable
explanation.</p>
<p>At this point though I ran into something of a black-hole.  It was
hard to even find confirmation that it might be possible; &ldquo;bdb is
platform-independent&rdquo; is the prevailing opinion.  Some
<a href="http://svn.haxx.se/users/archive-2007-02/0456.shtml">evidence</a> did
exist but was otherwise thin on the ground, which is one reason I&rsquo;m
writing this.  One helpful
<a href="https://community.oracle.com/message/3727053">post</a> mentioned that
while the main database is platform-independent the <em>log files</em> are
not, and hence my problem.</p>
<h1 id="solution">Solution</h1>
<p>I no longer had access to a PPC machine, but the solution came when a
friend pointed out that <a href="http://wiki.qemu.org/Main_Page">QEMU</a> can
virtualise big-endian architectures, even on a little-endian host.
After that, it was just a matter of implementation details.</p>
<dl>
<dt>Create a PPC guest</dt>
<dd>With <a href="http://omega.cs.iit.edu/~bharatkris/blog/?p=211">this post</a> as
a guide, grab a
<a href="http://people.debian.org/~aurel32/qemu/powerpc/">pre-configured Debian image</a>,
and apply the
<a href="https://lists.ubuntu.com/archives/ubuntu-users/2011-November/254572.html">openbios</a>
fix as well.  Install subversion on it (<code>apt-get install subversion</code>).</dd>
<dt>Copy the repository onto the guest</dt>
<dd>QEMU doesn&rsquo;t provide out-of-the-box shared folders (well, apparently
it has a built-in SMB server, but I didn&rsquo;t investigate), but it does
make the host addressable on 10.0.2.2 which is all we need.  Tar up
the repository and run <code>python -m http.server</code><sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup> from the same
directory on the host, then from the guest download it with <code>wget http://10.0.2.2:8000/repo.tar</code>.</dd>
<dt>Migrate the repository</dt>
<dd>The reason we&rsquo;re here; we&rsquo;ll convert it to the
<a href="http://web.mit.edu/Ghudson/info/fsfs">FSFS format</a>.  This is
actually slightly fiddly; essentially you create a new repository in
the FSFS format, dump from your old repository and import into the
new one.  Assuming it has been extracted to <code>oldrepo</code>:
<ol>
<li><code>svnadmin create ./fsfsrepo --fs-type fsfs</code></li>
<li><code>svnadmin dump ./oldrepo -q | svnadmin load ./fsfsrepo</code></li>
</ol>
</dd>
<dt>Copy the recovered repository back to the host</dt>
<dd>Once again there are probably smoother ways, but I used a
quick-and-dirty approach (good old <code>netcat</code>!):
<ol>
<li>(from the host) <code>nc -l -p 8000 &gt; fsfsrepo.tar</code></li>
<li>(on the guest) <code>tar cvf - fsfsrepo | nc -p 8000 10.0.2.2</code></li>
</ol>
</dd>
<dt>Import your recovered repository into git</dt>
<dd>This step is entirely optional of course, but I&rsquo;m mentioning it for
the sake of completeness since that was my goal in this exercise.  I
used <a href="https://github.com/nirvdrum/svn2git">svn2git</a>, which is a
wrapper around <code>git-svn</code>.</dd>
</dl>
<h1 id="conclusion">Conclusion</h1>
<p>I hope this helps someone else in the future, and at the very least
adds Google-weight to the problem.  Thanks to the
<a href="https://plus.google.com/+MarkHepburn/posts/PxpMzPmVqXo">fine folk on Google+</a>
for their suggestions, and Paul for the QEMU tip!</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Way to make me feel old.  Not only was it in a long-deprecated
format, but this was actually the <em>rewrite</em> of my thesis.  The
first version was written under
<a href="http://en.wikipedia.org/wiki/Concurrent_Versions_System">CVS</a>&hellip;
(Remember when people were excited about the upcoming release of
subversion, and new announcements about it made the front page of
Slashdot?  Hell, remember Slashdot?  I think I&rsquo;m going to go drink
now, and feel like a fossil.)&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>Or <code>python -m SimpleHTTPServer</code> if you&rsquo;re still using python 2.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content>
		</item>
		
		<item>
			<title>North America 2013: Road Trip!</title>
			<link>https://blog.markhepburn.com/2014/05/16/north-america-2013-road-trip/</link>
			<pubDate>Fri, 16 May 2014 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/2014/05/16/north-america-2013-road-trip/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>After nearly 3 months it was almost time to head back home and to the
real world again, but there was one thing remaining&hellip; road trip!  The
third member of our
<a href="/2014/03/18/north-america-2013-old-friends-in-la-news-ones-in-yosemite/">friends from Patagonia</a>,
Dan, had been out of the country and I&rsquo;d missed catching up with him,
but things would finally work out: he had a meeting on the Colorado /
Arizona border and was going to drive there, and I had a few days
left.  Perfect!</p>
<p>I flew back to Ontario airport (I&rsquo;d learned my lesson about LAX),
Kevin picked me up again and we met up with Dan for one final meal
together before Dan and I hit the road for a late assault on Las
Vegas.</p>
<p>Vegas had never been on my itinerary.  Based purely on impressions, it
seemed like a place that might be fun with the right crew, but flying
solo it held little appeal for me.  I <em>was</em> still curious though, so
after we checked in around midnight I didn&rsquo;t require much urging to go
for a wander up the strip.  It is absolutely quite a sight, to say
nothing of the human spectacle with girls flicking cards in your face
to attract attention and nightclub touts every 15 metres (&ldquo;Gentlemen!
No cover charge tonight&hellip;  we got drunk chicks inside&rdquo;).</p>
<p>That was to be the extent of my Vegas experience though!  All of about
8 hours, and most of them asleep.  The next morning we were on the
road again, bound for
<a href="http://www.nps.gov/zion/index.htm">Zion National Park</a>.  We arrived
at the town of Springdale in late afternoon, so we kept going for a
short drive into the park.  This was also the first time I really
&ldquo;understood&rdquo; this type of scenery.  I am used to admiring lush or
snow-covered mountains, rain forest scenery, and so on&mdash;but when
everyone I talked to kept raving about all the &ldquo;red rock&rdquo; parks I
didn&rsquo;t really get it.  Sure, the rock formations looked cool, but how
much of it did you really need to see?  Well, standing there in the
middle of it, with enormous red sandstone cliffs and formations eroded
into being over thousands of years, in colours more vivid than any
photograph can ever convey, I did understand why.  I was definitely
looking forward to exploring properly the next day.</p>
<!-- raw HTML omitted -->
<p>The light was going down though so we headed back to
Springdale&hellip; only to discover that the hotel we&rsquo;d booked was
actually located on the other side of the park!  So, back through that
road for a third time, with the people at the gate giving us strange
looks.</p>
<p>Over dinner that night I learned that not only does (Mormon) Utah
actually have at least one brewery, but they have a sense of humour
about it: I washed my food down with a Polygamy Porter.</p>
<p>The following morning we again drove that road through the park for a
fourth time, saying good morning to our friends at the gate, and
parked at the visitor centre to investigate hikes before catching a
shuttle in.  We had planned to explore Hidden Canyon, but when that
was closed off not far from the entrance we took another path winding
up to Observation Point, with glorious views back over the main canyon
and river.</p>
<!-- raw HTML omitted -->
<p>My penultimate full day had us take a fifth and final trip through the
park, and head along the Arizona border towards Lake Powell.  We
didn&rsquo;t have time to see
<a href="https://www.google.com.au/search?q=rainbow+arch+lake+powell&amp;tbm=isch">Rainbow Arch</a>,
but the boat tour through the lake&rsquo;s canyons was still striking.
Sunset over Horseshoe Bend was even more spectacular (and put Grand
Canyon firmly on my list for my next trip, when you realise this
enormous bend was a fraction the size of those in Grand Canyon!)</p>
<!-- raw HTML omitted -->
<p>Hitting the road for the final time together, we drove through
Monument Valley&mdash;an expanse of
<a href="https://en.wikipedia.org/wiki/Mesa">mesas</a> and
<a href="https://en.wikipedia.org/wiki/Butte">buttes</a> that looks just like
every cowboy movie you&rsquo;ve seen, because that is indeed where they were
all filmed&mdash;towards the tiny town of Durango in Colorado.  Dan&rsquo;s
friends there showered us with hospitality, and in the morning even
took me on a short hike in the hills.  I was really sorry not to have
more time in Colorado; mountains still draw me, and there&rsquo;s a lot to
explore there.</p>
<!-- raw HTML omitted -->
<p>Unfortunately, it wasn&rsquo;t going to happen this trip, for that was the
end.  Dan drove me to the airport, and I began my 32-hour, 6-flight
(of which I had to sprint for 3!), return voyage.</p>
<h1 id="èl-fin-un-comienzo">Èl Fin, Un Comienzo</h1>
<p>I always pictured writing some final paragraph with my favourite
places and memories, but in reality I don&rsquo;t think I could separate
much.  I will pick out
<a href="/2013/12/27/stunning-alberta/">Alberta</a>
as my favourite outdoors experience, but
<a href="/2014/03/18/north-america-2013-old-friends-in-la-news-ones-in-yosemite/">Yosemite</a>
and Zion were both very different and equally spectacular.
<a href="/2014/01/18/north-america-2013-new-york/">New York</a>
was great, <a href="/2014/04/21/north-america-2013-pacific-north-west/">Portland</a>
was too for very different reasons&hellip; but again, there were very few
places I wouldn&rsquo;t gladly revisit and a long list of places I still
intend to but couldn&rsquo;t this time.</p>
<p>As always of course the people made the most difference&mdash;so to
everyone I met, old and new, and invited back to my home-town&hellip; I was
serious, come visit!</p>
<p>This post effectively marks the end of this blog as a place for my
travel pictures.<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>
<p>As I mentioned at
<a href="/2013/12/22/north-america-2013-back-to-vancouver/">the beginning</a>,
I quit my job before this trip, and together with a friend I&rsquo;m now
well into <a href="http://www.condense.com.au">something new</a>.  That means a
lot fewer travel-related posts for now, but on the other hand I do
have a long list of posts in technical and business areas I plan to
write.  Stay tuned!  (Or update your subscriptions accordingly)</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>It was originally a means for people to keep track of where I
was, but given the delays in recent posts it didn&rsquo;t do that very well.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content>
		</item>
		
		<item>
			<title>North America 2013: Pacific North West</title>
			<link>https://blog.markhepburn.com/2014/04/21/north-america-2013-pacific-north-west/</link>
			<pubDate>Mon, 21 Apr 2014 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/2014/04/21/north-america-2013-pacific-north-west/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>I was still disappointed not to be on the road and heading east to
<a href="http://www.nps.gov/brca/index.htm">Bryce Canyon</a>,
<a href="http://www.nps.gov/grca/index.htm">Grand Canyon</a>,
<a href="http://www.nps.gov/arch/index.htm">Arches</a>,
<a href="http://www.nps.gov/zion/index.htm">Zion</a>, &hellip;, but at least I now had
the time to head north.  My musical awakening as a teenager centred
around Nirvana and the grunge scene so Seattle had always been on my
radar; these days a love of coffee, craft beer, food, and independent
music made Portland an intriguing prospect as well<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>.</p>
<p>So I returned Kevin&rsquo;s truck, spent a few more days in Venice
exploring with friends (celebrated my birthday in Silverlake, went to
an anti-Monsanto rally, and followed up with chicken-and-waffles
breakfast at <a href="http://roscoeschickenandwaffles.com/">Roscoe&rsquo;s</a>&mdash;I
think I&rsquo;ve covered LA!), and caught a flight to Portland.</p>
<h1 id="portland">Portland</h1>
<p>I&rsquo;d booked close to a week in Portland, again to decompress and geek
out a little, and it really didn&rsquo;t disappoint.  By far the most
consistently excellent espresso of any place I&rsquo;d visited to date, and
just a thoroughly <em>comfortable</em> town.  I&rsquo;m from a small town myself, a
similar distance from the equator, so while the beautiful sunny
weather of the last two months had been great it was still quite nice
to feel a nip in the shade, and even to see the town mostly closed as
I explored on a Sunday.</p>
<p>I really hadn&rsquo;t done a lot of research<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>, and all I knew about
<a href="http://www.powells.com/">Powell&rsquo;s Bookshop</a> was that it seemed to be
one of the things to do in Portland.  It was only a block from where I
was staying, and I like a good bookshop so on my first morning I
wandered over.</p>
<p>I would not emerge until well after lunchtime.  Powell&rsquo;s, I
discovered, is famous because it&rsquo;s the largest independent bookstore
in the world.  It literally covers an entire block with 4 floors, and
if you wanted the technical books section&hellip; well, that&rsquo;s across the
road in another building, the size of most normal bookshops.  They
couldn&rsquo;t fit it in the main store.  Obscure topics (say, &ldquo;interior
decoration for attics with sloped ceilings&rdquo;) that would barely rate a
mention on Amazon, let alone your radar, in Powell&rsquo;s have multiple
shelves dedicated to them.</p>
<p>I caught a bus up to the
<a href="http://www.rosegardenstore.org/rose-gardens.cfm">Rose Gardens</a>, only
to overshoot the bus stop and find myself speeding past progressively
more distant stops.  Eventually I got off, and on a whim started
walking down a path off the road-side.  It not only went exactly where
I was intending, but soon became a very pleasant
<a href="http://www.hoytarboretum.org/">educational trail</a>&mdash;winning.  The
gardens themselves were picturesque enough and provided a fairly nice
view back out over the city, with Mount Hood just visible behind.</p>
<p>Portland is justifiably famous for its
<a href="http://www.foodcartsportland.com/">food trucks</a>, and many are
excellent (many others, of course, are not).  On my final morning I
made one final trip to an earlier favourite
(<a href="https://www.facebook.com/PeoplesPig">the peoples&rsquo; pig</a>, for
excellent porchetta sandwiches), and my afternoon bus to Seattle came
up in conversation.  They immediately told me about a place for cured
meats called <a href="http://www.salumicuredmeats.com/">Salumi</a>, literally
right next to where I would get off the bus&mdash;score!  It even turned
out that the place is run by the father of celebrity chef
<a href="http://www.mariobatali.com/">Mario Batali</a>.</p>
<!-- raw HTML omitted -->
<h1 id="seattle">Seattle</h1>
<p>So I rolled into Seattle and made a bee-line for Salumi&hellip; in
something of a harbinger of things to come, it was closed (only open
to the public a small number of days, and limited hours).  Undeterred
I checked into my hostel and after a quick chat with room-mates found
a pumping <a href="http://belltownpizza.net/">sports bar</a> to grab a counter
meal and watch the football game.  The local team won, spirits were
high, and it turned out the people around me were friends with the
owner and we wound up doing quite a few shots.  The night was rosy but
not out of control&hellip; until I cheerily rolled back to the hostel, and
agreed to go straight back out again with a room-mate who had itchy
feet.  I fear I may not have fully appreciated the excellent whisky we
wound up drinking.</p>
<p>The next morning my good mood from the night before had deserted me
and so, it was feeling like, had my persistent good luck on this trip.
Slightly underwhelmed by the hostel breakfast I went out, straight
into a thick damp fog making it apparent I didn&rsquo;t have enough warm
clothes on, and I immediately jarred my knee stepping down off the
curb, with my opposite hip already complaining about lugging my
backpack around yesterday.  Feeling slightly sorry for myself I
figured any coffee would help, and ducked into the first half-way
decent looking cafe I came across.  The vile espresso I forced down
had me cursing that decision too, and I was all but ready to either go
back to bed or pass through Seattle entirely.</p>
<p>Like a true soldier though I pushed on, and after exploring the
<a href="http://www.pikeplacemarket.org/">Pike Place Markets</a> for a while I
emerged into sunshine, with my headache and other pains gone, and
ready to conquer the town.</p>
<p>This time I didn&rsquo;t fail at Salumi, and enjoyed a tasty lunch in a
secluded
<a href="http://www.pioneersquare.org/go/waterfall-garden">Japanese waterfall-garden</a>
I stumbled upon nearby.</p>
<p>Late in the day I figured I should check out the standard Seattle
cliche, the <a href="http://www.spaceneedle.com/home/">Space Needle</a>.  I
wasn&rsquo;t that excited about it, but for once in my experience of
&ldquo;queuing to go up tall things&rdquo;, the queues weren&rsquo;t too bad.  Not only
that, but by the time I was up the top the skies were clear and the
light was great&hellip; and only then did I realise that if I just stuck
around for another half hour or so I would also get some great sunset
and night-time shots!</p>
<!-- raw HTML omitted -->
<h1 id="bellingham">Bellingham</h1>
<p>Bellingham was somewhat of a random choice.  An early tip from a
friend (Dan) was to check out the
<a href="http://en.wikipedia.org/wiki/San_Juan_Islands">San Juan Islands</a>, and
Bellingham was one jumping-off point for exploring them.  Also, and
completely randomly, it&rsquo;s where
<a href="https://www.youtube.com/watch?v=0wrsZog8qXg">The Postal Service</a>
originate from!</p>
<p>An early bus from Seattle unfortunately made such good time that we
were dropped at the terminal an hour early&mdash;which was already
scheduled to be about an hour before the first bus into town.  A long
cold wait, two buses and a long walk later and I was at the motel I&rsquo;d
booked, still hours before check-in time but a very friendly owner let
me grab breakfast and found a vacant room for me (as well as telling
me that the reason they didn&rsquo;t have microwaves was because drug
dealers used cheap hotel rooms as disposable cooking-labs).  I made
another long, grey walk into town, only to find (it was a Sunday
again) almost everything shut.  I did find some passable coffee, and
stumbled upon a water-side path that took me all the way to adjoining
Fairhaven (also shut).  On my return home I took a wrong turn and
wound up passing through the university campus&mdash;also scenic, and
rather close to my motel but with no way to cut through so by the time
I got home it had been quite a long day, and I had already seen most
of the town!  I grabbed take-away and started researching ways to
occupy the next couple of days.</p>
<!-- raw HTML omitted -->
<p>This time though, my luck really <em>had</em> run out.  Hiring a sea kayak?
Sorry, the season finished last month.  Perhaps whale watching again?
Nope, same story.  A visit to the San Juans?  Actually, it turns out
that you <em>can&rsquo;t</em> go directly from Bellingham any more, and my best
option was via Anacortes (the other town I&rsquo;d been considering), which
would be a 3 hour journey <em>each way</em>.  Oh well, it looked like this
was going to be another chill-out stop!  I spent the next day walking
the town, trawling record stores, and hacking in cafes.  My final day
I hired a bike in Fairhaven and hit a trail that eventually cruised
through pine forest along the water&rsquo;s edge, before a steep climb
finished with a short lake circuit hike.</p>
<p>I had one more night back in Seattle before flying back to LA, and
used the time to find the fantastic
<a href="http://en.wikipedia.org/wiki/Fremont_Troll">bridge troll</a> (also,
<a href="http://www.toppotdoughnuts.com/">Top Pot Donuts</a>).</p>
<!-- raw HTML omitted -->
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Yes, I am aware this makes me a closet hipster.  Guilty as
charged&hellip; but my legs just aren&rsquo;t skinny enough for their jeans,
and I refuse to wear plaid, regardless.  Also, my stubble is down
to laziness, not irony.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>Apart from Zdenka making me watch a series of
<a href="http://en.wikipedia.org/wiki/Portlandia_(TV_series)">Portlandia</a>!
And yes, apparently that show might as well be a documentary.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content>
		</item>
		
		<item>
			<title>North America 2013: Highway 1 Revisited</title>
			<link>https://blog.markhepburn.com/2014/03/28/north-america-2013-highway-1-revisited/</link>
			<pubDate>Fri, 28 Mar 2014 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/2014/03/28/north-america-2013-highway-1-revisited/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>With my plans for a national parks tour dashed, and the situation
looking unlikely to be resolved anytime soon, I had to make other
plans.  On the plus side I now had the opportunity to visit a number
of other places on the West Coast, places I previously thought I
wouldn&rsquo;t have time for.</p>
<p>So, rather than heading inland a bit we made a beeline back West to
the coast.  I dropped my Irish hiking buddy off in San Francisco, and
headed south to the old capital of
<a href="https://en.wikipedia.org/wiki/Monterey">Monterey</a>.</p>
<h1 id="monterey">Monterey</h1>
<p>Monterey was a curious mix; a very touristy small town centre, and
otherwise a very relaxed beach-town feel.  One of the big attractions
is its world-famous <a href="http://www.montereybayaquarium.org/">aquarium</a>
and associated research institute, on my radar from my previous life
in another <a href="http://www.cmar.csiro.au/">marine research centre</a>.  To be
honest, I found the aquarium amazing and incredibly well done, but
definitely aimed at children.</p>
<!-- raw HTML omitted -->
<h1 id="big-sur">Big Sur</h1>
<p>Just South of Monterey is
<a href="http://en.wikipedia.org/wiki/Big_Sur">Big Sur</a>, a coastal area with
steep mountains of redwood forest, rising straight up from the ocean.
I was planning on moving there next, but having left it to the last
minute (a recurring theme) and with no camping gear I decided to stay
on in Monterey and just drive down to Big Sur for day trips.</p>
<p>The first day was actually somewhat of a let-down.  I began by taking
the much-hyped
<a href="http://en.wikipedia.org/wiki/17-Mile_Drive">17-mile drive</a>; basically
a gated-commune of golf courses and beaches just outside Monterey.
You pay to drive around, and occasionally take photos through the
bus-tour crowds while Kenny Rogers plays on some oblivious gentleman&rsquo;s
iPad.  Avoid; if you drive just a little further you get much better
views, for free.  Then it was lunch-time, deep in Big Sur at the also
over-hyped and even more over-priced
<a href="http://www.nepenthebigsur.com/">Nepenthe</a> (I was at least prepared
for the cost).  I did at least manage a short walk, up through
redwoods to a pleasant but unremarkable view. The second day started
much more promisingly at the iconic
<a href="http://www.hikinginbigsur.com/hikes_mcwayfalls.html">McWay Falls</a>,
the only coastal waterfall in California.  After that I went on a
steep hike up the mountains behind it, with a rewarding view at the
summit dropping right down to the water.</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>As an aside<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>: I&rsquo;ve been a fan of the author
<a href="http://www.amazon.com/gp/product/0140283293/ref=as_li_ss_tl?ie=UTF8&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0140283293&amp;linkCode=as2&amp;tag=evertastbettw-20">Jack Kerouac</a>,
and it seemed appropriate to
<a href="http://www.amazon.com/gp/product/0140042520/ref=as_li_ss_tl?ie=UTF8&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0140042520&amp;linkCode=as2&amp;tag=evertastbettw-20">read more</a>
while road-tripping.  Fittingly, there&rsquo;s even one <em>called</em>
<a href="http://www.amazon.com/gp/product/0143119230/ref=as_li_ss_tl?ie=UTF8&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0143119230&amp;linkCode=as2&amp;tag=evertastbettw-20">Big Sur</a>,
so that was night-time reading for this part of the journey.  It is,
however&hellip; rather dark, I warn you!  Gone is the carefree and
foot-loose innocence, and all that&rsquo;s left is a descent into alcoholism
and depression as he struggles with fame and worries he&rsquo;s losing his
mind.  It put a bit more of a sombre mood on this leg than I was
planning on.</p>
<h1 id="highway-1">Highway 1</h1>
<p>Then it was time to leave Monterey for good, one last time through Big
Sur and keep going down that amazing coastline to LA again.  It is a
single-lane highway but obviously very popular, and steering the
enormous truck I was driving around blind corners knowing how many
cycle tourers were around got quite nerve-wracking.</p>
<p>Yet again though I realised how charmed I&rsquo;d been with the weather: a
heavy fog completely blanketed the ocean all morning, making for a
great change in atmosphere as I drove down, but probably less
appealing for anyone on their first trip.  Even the McWay Falls were
completely obscured as I drove past, thanking my luck for the perfect
weather I&rsquo;d had the previous 2 days as I did so!</p>
<p>Once the views have eased off a little, your next stop is likely to be
<a href="http://hearstcastle.org/">Hearst Castle</a>.  This place is hard to
describe: from the reception building you are escorted up to the
castle itself by coach.  It&rsquo;s a bizarre mix of old and new; built
within the last century, but with most of the interior coming from the
antiques collection of (the late) William Hearst.  He even had a
private zoo at the time; I saw a herd of zebras, still roaming around,
as I was leaving!</p>
<!-- raw HTML omitted -->
<p>I stopped for a couple of nights in San Luis Obispo.  It was a small
town, pleasant to wander without making undue demands, and in my case
a nice communal hostel to stay in.</p>
<p>I made another stop in Santa Barbara.  Many people talk about how
great it is, and I suspect it would be a fantastic place to live.  As
it was, I drove in through the opulent strip, stayed in a motel on
the beach which turned out to be fairly unexciting, and left the next
morning rather underwhelmed.  The one saving grace was Dan linking me
up with a good friend of his, who was kind enough to meet up and show
me a few of the watering holes, giving me some inkling of life in the
area.  Perhaps next time!</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>As another aside, I&rsquo;ve started to use affiliate links.  Please
feel free to buy any of these books; I get a few cents to spend on
more books, at no cost to you.  And you get some classic books, in
this case.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content>
		</item>
		
		<item>
			<title>North America 2013: Old friends in LA, new ones in Yosemite</title>
			<link>https://blog.markhepburn.com/2014/03/18/north-america-2013-old-friends-in-la-news-ones-in-yosemite/</link>
			<pubDate>Tue, 18 Mar 2014 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/2014/03/18/north-america-2013-old-friends-in-la-news-ones-in-yosemite/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p><em>Sorry for the delay!  A while ago
<a href="/2013/12/22/north-america-2013-back-to-vancouver/">I mentioned</a>
I had quit my job to attempt something with a friend; we suddenly
found ourselves with a lot of work, which has curtailed blogging a
fair bit.  I have an ever-growing list of non-travel posts to write,
long and short, technical and otherwise, so future travel updates
might be rather brief as I try and clear the slate first.</em></p>
<h1 id="on-to-los-angeles">On to Los Angeles</h1>
<p>One of the great pleasures of travelling&hellip; is meeting other
travellers, who can then help you out on your <em>next</em> journey!  And so
it was; the year before in Patagonia I had met 3 Los Angeles
residents: Kevin, understated but with immense resolve (hiking
Patagonia while needing both knee and shoulder surgery) and one of the
most thoroughly decent men you would ever meet; his friend and
counterpoint Dan, ebullient and a brilliant (and constant) story
teller; and a beautiful Czech lady with fascinating tales mixing old
communist Czechoslovakia and modern Hollywood, Zdenka.  A year later I
was determined to catch up with all of them again, so despite the city
itself having no other appeal to me at the time, it was my obvious next
stop.</p>
<p>Dan was out of the country again, but it was great meeting Kevin again
and spending more time with him, sharing another hike in the mountains
behind LA.  Then from suburbia outside LA (an hour and a half of
freeway traffic outside, which just appears to be a standard commute),
I spent a couple of days in the trendy-hippy beach towns of
Venice/Santa Monica with Zdenka, seeing a completely different side of
the area.</p>
<!-- raw HTML omitted -->
<h1 id="yosemite">Yosemite</h1>
<p>In so far as I had any plan for this trip, it was to spend roughly 2
months going East across Canada then back West across the US, seeing
mostly cities, before touring as much of the amazing national parks on
offer in America during my final month.  To date I was on schedule,
and in yet another display of generosity Kevin loaned me his
<a href="http://en.wikipedia.org/wiki/Ford_F-Series">truck</a>.  Swallowing my
nerves about driving on the other side of the road&mdash;I&rsquo;d overcome some
fear in <a href="/2013/12/27/stunning-alberta/">Alberta</a>, but
Californian freeways were another matter entirely&mdash;I made a
last-minute hostel booking and drove 7 hours up to Yosemite.</p>
<p>The next day, the
<a href="http://en.wikipedia.org/wiki/Government_shutdown_in_the_United_States">US Government Shutdown</a>
closed the national parks.</p>
<p>Ok, that was a slight exaggeration for dramatic effect.  The reality
is the next day I had a full day of hiking up to the (bone-dry)
Yosemite Falls, where I had lunch overlooking the incredible valley
view and watching crows joy-riding the thermal off the cliff edge.</p>
<p>The <em>next</em> day they really did close the parks.  No-one had any idea
what that was going to mean in practice however, so together with an
Irish dorm-mate (are Irish ever not great travellers?) we drove in to
try our luck.  The ranger at the gate also seemed unclear what the
shutdown entailed,<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> but said we could go in &ldquo;today&rdquo;.  From the sounds
of it we just got lucky; others were supposedly turned away, while
others were allowed in but later evicted by different rangers.  This
was a Tuesday, and at that time people expected things to be resolved
by Thursday&mdash;no doubt the parties of the 6 weddings apparently
planned inside the park that weekend were particularly hopeful, as
well as the climbers with months-long camping plans who were being
told to leave.</p>
<p>Still, we counted our blessings and enjoyed a much quieter hike to
Vernal and Nevada Falls.  There was no way I wasn&rsquo;t taking advantage
of any break&mdash;only the day before I&rsquo;d optimistically paid for a
year-long national-parks pass, and the chances of breaking even on my
investment by visiting 4 parks were now looking rather slim.</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Other than not being paid himself, of course, while the
politicians claiming it was necessary continued to draw their own
salaries.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content>
		</item>
		
		<item>
			<title>North America 2013: San Francisco</title>
			<link>https://blog.markhepburn.com/2014/01/30/north-america-2013-san-francisco/</link>
			<pubDate>Thu, 30 Jan 2014 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/2014/01/30/north-america-2013-san-francisco/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>I love travel; I love exploring new places, meeting new people, trying
new food, seeing different ways of doing every-day things and having
my comfort-zone pushed&hellip; I love the lot.  Fundamentally however,
there comes a time where you start to itch for that feeling of being
productive again.  At heart I&rsquo;m a nerd, and my fingers were missing
writing code and my mind was both starting to overflow with ideas and
starting to panic about atrophying.  A recent
<a href="/2014/01/25/north-america-2013-boston/">visit to MIT</a>
did not help these feelings.</p>
<p>So, it was time for a holiday from my holiday&mdash;time to chill out
without too much pressure to explore or plan the next few day&rsquo;s
travel, and time to hack if and when I felt like it.  San Francisco
was the perfect spot for this: I&rsquo;d already visited in the past so
wouldn&rsquo;t feel like I was missing out if I didn&rsquo;t spend all day
exploring, and of course it has a thriving tech community.  Add to
that a couple of friends in town and the deal was sealed.</p>
<p>It was glorious: I rented a nice room via
<a href="https://www.airbnb.com/">AirBnB</a>, perfectly located in a great area
near Alamo Square and on a couple of bus routes; I went to
<a href="http://www.meetup.com/">meetups</a> and pitch events; I had a lot of
great coffee and food; I hung out with friends, and wrote code in
cafes.<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>  Nerd-wise it was exactly what I was looking for, although
no-less intimidating (&ldquo;Hi, what do you do?&rdquo; &ldquo;Well, I wrote
<a href="http://www.wireshark.org/">WireShark</a>, but now I&rsquo;m&hellip;&rdquo; to pick a
random example).  I can definitely imagine working in SF for a few
years to turbo-charge your development, but by the same token it is
also easy to see why people feel the need to work such crazy hours
just to keep up, which doesn&rsquo;t seem sustainable or healthy.</p>
<p>I did of course still do plenty of walking&mdash;it&rsquo;s a very pretty and
walkable city.  My charmed run of weather continued, barring a single
morning downpour while I was doing laundry, in flagrant violation of
the apocryphal quote <em>&ldquo;The coldest winter I ever spent was a summer in
San Francisco&rdquo;</em>.<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>  The lack of touristy activities unfortunately
meant that I took very few photos; the car show pictured was a random
find on a walk through the Castro when for some reason I did happen to
have my camera with me.</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Yes, I&rsquo;m sure this all makes me a closet hipster, but I just
can&rsquo;t wear plaid and I don&rsquo;t think my legs would ever fit in jeans
that skinny.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>Probably not Mark Twain, but let&rsquo;s attribute it to him since
everything else is.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content>
		</item>
		
		<item>
			<title>North America 2013: Chicago</title>
			<link>https://blog.markhepburn.com/2014/01/29/north-america-2013-chicago/</link>
			<pubDate>Wed, 29 Jan 2014 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/2014/01/29/north-america-2013-chicago/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>I was quite excited about visiting
<a href="http://www.youtube.com/watch?v=yEtzKjTzmcM">Chicago</a>, and it was fun
to wander around, but ultimately I felt rather underwhelmed.  I
definitely feel that I missed out though; sometimes a city simply
fails to inspire, but in this case I think I just failed to find the
fun bits.  Notably, I completely failed to go to any Jazz or Blues
clubs.  I&rsquo;m definitely keen to return (will any show me around?)</p>
<h1 id="millennium-park-and-willis-tower">Millennium Park and Willis Tower</h1>
<p>The weather was already looking glorious, and I headed into town to
hunt down, first and foremost, the &ldquo;bean&rdquo;!  (Its actual title is the
<a href="http://en.wikipedia.org/wiki/Cloud_Gate">cloud gate</a>).  This
surprisingly-funky sculpture is just one of many in Millennium Park,
and on a sunny Saturday I was not the only one enjoying it.</p>
<p>The bean was definitely a highlight, and I couldn&rsquo;t help giggling when
I realised you could also stand underneath it.  Afro beats at a
near-by sound stage provided a backdrop for the rest of my
exploration.</p>
<p>That afternoon I yet-again braved the crowds end endless queuing for
<a href="http://en.wikipedia.org/wiki/Willis_Tower">Willis Tower</a>, still the
second-tallest building in the United States.  It was a pretty
familiar story for me by this stage however: great views, but by the
time we got up there I was more or less done.</p>
<p>To unwind I wandered the streets a little, although on a Saturday
evening in the business area the streets were pretty quiet.  There is
a collection of sculptures by famous artists, all roughly on the same
intersection, and I hunted those down.  My favourite was undoubtedly a
horse by Picasso, a 3-dimensional instantiation of his minimalist
line-drawing style, but up close rather massive and physical.  I even
watched some cyclists using it as a ramp at one point!  Apparently
this is a bit of a mascot of the city and they even dress it up in
team colours for sports events at times.  Close by was a
<a href="http://en.wikipedia.org/wiki/Mir%C3%B3%27s_Chicago">Miro</a>, and around
the corner one by Dubuffet, known colloquially and for obvious reasons
as
<a href="http://en.wikipedia.org/wiki/Monument_with_Standing_Beast">&ldquo;Snoopy in a blender&rdquo;</a>.</p>
<h1 id="rain-and-architecture">Rain and Architecture</h1>
<p>The following day the weather gods had deserted me, and I had to run
for the train downtown.  After grabbing a coffee I found a river
architecture cruise&mdash;for those unaware, Chicago is renowned for its
architecture (and in particular as a pioneer of the skyscraper age).
The old city was razed almost completely by a fire in 1871, followed
by architects flocking from all around lured by the blank slate
offered and the promise of modern building materials (steel and
concrete instead of wood).</p>
<p>The tour was impeccably run by a volunteer guide (a
<a href="http://www.architecture.org/">river docent</a>), although I was less
impressed having to buy a poncho!</p>
<p>The rain only got heavier, and I splashed out on a spectacular lunch
at a <a href="http://thepurplepigchicago.com/">gastro-pub</a>.  The rain eased
slightly so I had a bit of an explore around the hipster area of Logan
Square.</p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>North America 2013: Boston</title>
			<link>https://blog.markhepburn.com/2014/01/25/north-america-2013-boston/</link>
			<pubDate>Sat, 25 Jan 2014 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/2014/01/25/north-america-2013-boston/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>Word on the street said the best way to get to Boston from NY was the
<a href="https://www.boltbus.com/">Bolt Bus</a>: they&rsquo;re new, cheapest, have
wifi, etc.  I found the &ldquo;station&rdquo; (a sandwich board erected on the
footpath) nearly an hour early, and watched a Philidelphia service run
like clockwork, with all of the ticketed boarding, walk-ups, and
departure occuring exactly on time, and announced in a crystal-clear
projected voice I could hear even at the back.</p>
<p>Then we all sat back and waited for the Boston bus.  Soon enough a bus
pulled up&hellip; and ignored us, while we watched the driver eat fruit
salad in her seat.  About 10 minutes later she did briefly emerge to
say that she wasn&rsquo;t going to Boston, before locking the door again.
Confusion reigned, as both our boarding then departure times came and
went (observed silently by fruit salad lady.  I never did figure out
what route she <em>was</em> driving).  Eventually, a bus that had pulled up
behind her, and also denied he was going to Boston, did relent and
agree to take us&mdash;he did not look happy about it, and I suspect we
were eating into his home-time.  Missing: one NY-Boston Bolt Bus,
possibly still out there.  We did not have wifi for the journey
either.  First-world problems abounded.</p>
<p>Owing to my lack of advance planning (spontaneity has its downsides)
my hostel was actually in Everett, a suburb about half an hour by
train out from the city centre, and then a bus ride from the train
station (they did have a free shuttle once you&rsquo;d checked in).  The
hostel actually felt more like a half-way house than a typical
backpackers, but on the positive side it was located in a Brazillian
district and all-you-can-eat Brazillian BBQ joints abounded.  I
considered that a net win, really.</p>
<h1 id="boston-and-the-freedom-trail">Boston and the Freedom Trail</h1>
<p>I headed into the city the next day with a friend from the dorm, on a
brutally hot day (I think it pushed 40°C).  The main thing to do,
apparently, is to walk the
<a href="http://www.thefreedomtrail.org/">Freedom Trail</a>; a walk along sites
of historical significance associated with the American Revolution.
Most of these sites seemed to involve
<a href="https://en.wikipedia.org/wiki/Paul_Revere">Paul Revere</a>, often in
rather tenuous connections&mdash;his first-grade teacher&rsquo;s first house?
I&rsquo;m probably making that particular example up, but coupled with the
heat and an overloading of history, side-notes to an event to which we
felt no personal connection anyway, it started to feel that way.  But
apparently I am
<a href="http://www.washingtonpost.com/blogs/compost/wp/2014/01/17/nobody-knows-history-says-fox-host-then-proves-it/">not the only one</a>
to be slightly ignorant of the history!</p>
<p>After lunch we eventually managed to extract ourselves from the
air-conditioned bliss of a pub, where after a walk through the
financial district we parted ways for a bit and I hugged the shade on
a wander through a leafy upper-class neighbour hill, around the river,
and back along the main shopping and entertainment district.</p>
<!-- raw HTML omitted -->
<h1 id="nerding-out-in-cambridge">Nerding out in Cambridge</h1>
<p>One of the things my dorm friend and I had bonded over was that we
were both, well, nerds (&ldquo;engineers&rdquo;, in polite speak).  So, coupled
with some cooler weather we were both a lot more excited to head in to
Cambridge to check out Harvard and MIT.</p>
<p>We explored MIT first, found the hilariously jumbled Stata centre,
then headed for the museum for the best part of a couple of hours.
Highlight here: an original LISP machine<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>!</p>
<p>We took the subway another couple of stops to Harvard, but having
missed out on the tours (and not aided by the near-complete lack of
signage) the highlight was probably free liquid-nitrogen ice-cream
samples.</p>
<p>I spent some time in the nerd-heaven that is the
<a href="http://web.mit.edu/bookstore/www/">MIT bookstore</a>, before going to a
<a href="http://clojure.org/">Clojure</a> meetup at the
<a href="http://www.akamai.com/">Akamai</a> headquarters.</p>
<p>Several people had mentioned that Harvard was the prettier place to
see, with a beautiful historic campus, while MIT was just a mish-mash
of buildings.  Visually that may have been true, but accurately or not
the impression we both got was rather different: Harvard felt elitest,
old-money, look-but-don&rsquo;t-touch, marvel at the number of US presidents
among our alumni, etc.  MIT, on the other hand, felt <em>much</em> more
meritocratic: an absolute buzzing hive of activity, where if you were
smart enough and prepared to work hard enough there could be a place
for you.  Who knows if that&rsquo;s accurate in either case, but as
inspiration it certainly hit home.</p>
<!-- raw HTML omitted -->
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>As well as inspired, I also got depressed and that evening
booked a week in SF to decompress a little and write some code again.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content>
		</item>
		
		<item>
			<title>North America 2013: New York</title>
			<link>https://blog.markhepburn.com/2014/01/18/north-america-2013-new-york/</link>
			<pubDate>Sat, 18 Jan 2014 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/2014/01/18/north-america-2013-new-york/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>New York was one of the main attractions drawing me to the US on this
trip&mdash;probably not a surprise to many of you, but it had barely been
on my radar until the last few years when a combination of popular
culture and a number of friends raving about placed it front and
square in my awareness.</p>
<p>So, from Montreal it was time to head south across the border.  It
wasn&rsquo;t an auspicious beginning, as the train was delayed and we all
queued up the middle of the station while all around us everything
else (the non-Amtrak trains) ran on time.  Meanwhile, a gentleman
behind me muttered how typical that was, how poor these trains were
unlike in the golden days, and so on.  No-one had much idea what was
going on either; we all had our luggage, but periodically an Amtrak
employee would walk up and down the line, mumbling something about
reserved seating while looking away from us.  My gentleman friend said
absolutely no way was he going to try and find his luggage in central
station, he wouldn&rsquo;t trust them as far as he could throw them and he
was holding onto it thank you very much.</p>
<p>Eventually I found a seat.  &ldquo;May I sit with you?&rdquo; said a young lady
behind me.  Of course I replied; &ldquo;Great!  Could you put my bag up in
the rack then please?&rdquo;.  I think I was used!  Conversation after that
was quite pleasant, coupled with nice views of autumnal colour through
the countryside, and luckily since the journey was around 10 hours!
She was a manager from a software development shop in Finland, which
instantly gave us some common ground.  At one point she asked about my
chromebook and I was half-way through mentioning that I&rsquo;d turned it
into a passable
<a href="http://martintrojer.github.io/clojure/2013/04/06/clojure-on-the-samsung-arm-chromebook/">development environment</a>,
before reflexively halting&hellip; even today, &ldquo;Linux&rdquo; isn&rsquo;t that
well-known.  I needn&rsquo;t have worried: Linus is a national hero in
Finland!</p>
<p>Finally we disembarked, bleary-eyed and weary, into the cacophony of
central station.  My new Finnish friend was returning to New York, and
kindly guided me to the subway I needed.  A saxophone and bass busking
pair were playing a driving rhythm at ear-splitting volume.  It was
almost hypnotic, but we had to keep moving.  Even with guidance I
still somehow jumped on the subway in the wrong direction, before
realising several stops down and changing direction.  Eventually I
found the <a href="http://www.nylofthostel.com/">hostel</a> (complete with a
fellow Tasmanian in my room!), had a late-night taco from a truck
nearby, and crashed.</p>
<h1 id="new-york-attractions-on-the-cheap">New York attractions on the cheap</h1>
<p>New York has a deserved reputation for being expensive, but while all
the museums, galleries, buildings etc aren&rsquo;t individually expensive
they quickly add up just because there&rsquo;s so <em>many</em> of them!  If you
are travelling on a tight budget it is possible to save significantly
here though:</p>
<ul>
<li>Statue of Liberty?  The regular Staten Island ferry goes right past
it, at a fraction of the cost of a tour.</li>
<li>Several museums are actually donation-only; the signs make it look
like it&rsquo;s $20, but you can drop $1 and waltz past the dirty looks.</li>
<li>Those with an actual admission fee usually have a free afternoon.</li>
<li>There is apparently a superb view from the
<a href="http://www.nyhabitat.com/blog/2008/05/30/top-5-manhattan-views-1-the-roosevelt-island-tram/">cable car</a>.</li>
</ul>
<p>I did none of this (I never even made it to the cable car at all,
which I <em>am</em> disappointed about).  Instead, I bought a
<a href="http://www.citypass.com/new-york">city pass</a> book of tickets, which
saves you $80 over 6 attractions, if you go to them all.  Why would I
do this?  Because it also means you can jump a <em>whole</em> lot of queues
(not all of them; there&rsquo;ll still be a wait for the security check,
etc).  I was already well and truly over queuing, and the prospect of
an entire week more of it easily made me open my wallet!  Later
walking past <a href="http://www.moma.org/">MoMA</a> while the queue for free
admission stretched around the block was enough to validate my
decision.</p>
<h1 id="seeing-new-york">Seeing New York</h1>
<p>I had roughly two types of days in the city.  Some days I just cruised
different neighbourhoods, wandering around soaking up the place,
checking out restaurants and cafes, and doing a lot of walking.  Then
there were the days I spent at various capital-A Attractions.  New
York has a <em>lot</em> of these, but as I hinted above, I found the queuing,
the security checks, and so on all rather exhausting and border-line
dehumanising at times.  I&rsquo;m definitely glad I made the effort (perhaps
my
<a href="http://www.ted.com/talks/daniel_kahneman_the_riddle_of_experience_vs_memory.html">recollection will be better than the experience</a>!),
but at the time I enjoyed the on-foot exploration much more.</p>
<p>It is certainly not news, but I&rsquo;ll repeat it here: New York is a
fantastic city to explore on foot.  It&rsquo;s always my favourite way to
explore and experience a place, but some are much more suited to it
than others.  The subway goes everywhere, and often (random stoppages
aside), the footpaths are nice and wide.  Perfect.</p>
<p>Day 1 was all about exploration.  Subway to
<a href="http://www.youtube.com/watch?v=CNLLVTZCxbE">Union Square</a> to pick up
a US SIM card, then walking past all the brownstone to a spectacular
lunch at <a href="http://momofuku.com/">Momofuku</a>.  Off to a good start!  That
was followed by an espresso <em>and</em> (because I couldn&rsquo;t pass it up) a
<a href="http://www.youtube.com/watch?v=LkJKmiOcsv4">nitro cold brew</a>&mdash;this
is exactly what it sounds like; a cold-brewed coffee, served from a
nitrous keg so it looked like Guinness, and tasted exceptionally creamy
to boot.</p>
<p>After a walk through Central Park I wound up at
<a href="http://www.metmuseum.org/">The Met</a>, where I only had a short amount
of time which was probably perfect for not over-doing my
non-art-appreciating brain.</p>
<h1 id="highline-park">Highline Park</h1>
<p>Don&rsquo;t ask me where I&rsquo;d heard about it, but I was really looking
forward to the <a href="http://www.thehighline.org/">Highline Park</a>.  At the
time I had the impression it was a bit of undiscovered secret, but by
the time I arrived it had most definitely been discovered!  The
highline is a stretch of elevated railway, previously abandoned and
now converted into a park and walk-way, with great views along the way
to boot.  The beautiful weather and popularity at least ensured there
were plenty of lunch vendors available.</p>
<!-- raw HTML omitted -->
<p>That afternoon I hit up the <a href="http://www.moma.org/">MoMA</a>.  I really
enjoyed this; for some reason I <em>do</em> seem to have more of an affinity
with (some) modern art.  The lower floors also contained a lot of
applied and industrial design, milestone computer artefacts (including
an annotated print-out of the first Pacman code!), sound art, and so
on.  The upper two floors were more of a strain: this is where the big
names reside, the Picassos, the Van Gogh, the Warhols&hellip; and
apparently nearly all the visitors, screaming and running from piece
to piece to take a picture with their iphone
<a href="http://thebestpageintheuniverse.net/c.cgi?u=padhole">or ipad</a> and
running on to the next.  I did not last as long on the top floors.</p>
<p>With the sun down the next stop was the
<a href="http://www.rockefellercenter.com/">Rockerfeller Centre</a>.  It&rsquo;s not as
tall or possibly as famous as the Empire State Building, but everyone
says the views are better and I won&rsquo;t dispute that.</p>
<!-- raw HTML omitted -->
<h1 id="brooklyn-911-memorial-empire-state-building">Brooklyn, 9/11 Memorial, Empire State Building</h1>
<p>There was a simple plan for the day: walk the famous Brooklyn Bridge,
have a quick look at the 9/11 Memorial and make my way north on foot.</p>
<p>The first step was a success, and the bridge is a great walk.
Unfortunately, I naively <em>completely</em> misunderstood what was going to
be involved in a &ldquo;quick look&rdquo; at the memorial, and this consumed a lot
more time than I realised.  Even finding it is not simple, with many
paths blocked off due to construction and no signage anywhere, and
lots of coalesced groups of people that looked confusingly like queues
to somewhere.  Proving that capitalism was not defeated in the
attacks, however, were swarms of people hawking commemorative
booklets, tea-towels, and so on.  Once it <em>had</em> been found&hellip; of
course it involved more queuing.  Lots and lots of queuing, and lots
and lots of security checks, and at least two points at which your
donation was strongly encouraged.  The memorial itself is in fact a
great and somber tribute to those who died, but after all that I did
not stay long.</p>
<p>Naturally, I had to make it up north for more queuing!  This time, it
was for the Empire State building.  Great views, but by this time I
was done and after a <a href="http://thebreslin.com/">late lunch</a> and drink to
unwind I turned in early.</p>
<!-- raw HTML omitted -->
<h1 id="wall-st-central-park">Wall St, Central Park</h1>
<p>If yesterday was all about crowds and queuing, the following day was
going to be all on foot!  Starting by walking from the hostel through
hipster Williamsburg, then catching the subway down south to Wall
Street in order to walk north.  Up through Chinatown, Little Italy,
NoLita, a late lunch at
<a href="http://missionchinesefood.com/">Mission Chinese</a>.  I did fit in an
hour or so at the Natural History Museum, which was probably ideal to
fit in the dinosaurs and meteor exhibits.  It has been a while since
I&rsquo;ve thought more than passingly about dinosaurs&mdash;I felt like a kid
again, staring in amazement!  Being able to touch a massive lump of
iron metal that fell from the sky,
<a href="http://en.wikipedia.org/wiki/Widmanst%C3%A4tten_pattern">characteristic crystallisation</a>
and all, was also very cool.</p>
<p>Dinner was at the famous
<a href="http://katzsdelicatessen.com/">Katz&rsquo;s Delicatessen</a>.  This was a
recommendation from a friend, but of course it was also &ldquo;where Harry
met Sally&rdquo;.  I was completely unaware of this, until I realised that
there was a large arrow sign at the table diagonally across from me,
pointing down and telling everyone that&rsquo;s where it all happened
(amusingly, it had a solitary girl looking rather bored).  It is a
chaotic place and the ordering system takes a little while to figure
out.  For a start (this is not obvious!) there are multiple queues,
and if you are there for the famous pastrami-on-rye (as you should
be), you have about 4 to choose from.  You give your order (and pay on
the way out, based on the ticket they&rsquo;ll write on), the cutter will
get to work, first giving you a taste while he works, you tip him a
couple of dollars, and off you go with a veritable mountain of
unctuous meat!  It wasn&rsquo;t long since an equally large lunch so I was
rather nervous about the quantity, but that&rsquo;s what I train for!</p>
<p>Walking in the wrong direction for a while afterwards gave me another
chance to explore a rather swanky area.</p>
<!-- raw HTML omitted -->
<h1 id="river-cruise">River Cruise</h1>
<p>There was one attraction left in my City Pass book; a river cruise.  I
had mixed expectations about this, and was rather underwhelmed (by way
of example, we stopped by the Statue of Liberty for a while, while the
guide rhapsodised at length about &ldquo;freedom&rdquo;&mdash;a concept people from
outside NY are not expected to understand apparently&mdash;without once
mentioning France.  We passed the
<a href="http://onewtc.com/">One World Trade Centre</a> and he complained that it
used be called the Freedom Tower, but it&rsquo;s all about making money
after all and not everyone appreciates freedom so we hadda change it.
And so on).</p>
<p>From here it was back on foot, through the Chelsea Markets, and down
to Greenwich Village.  This is an incredibly funky area still, and as
a music fan it was amazing to stare at the who&rsquo;s-who list of artists
who have frequented <a href="http://www.cafewha.com/about/history">Cafe Wha?</a>.</p>
<p>Another meal at Momofuku rounded out my final day in the big apple!</p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>North America 2013: Montreal</title>
			<link>https://blog.markhepburn.com/2014/01/01/north-america-2013-montreal/</link>
			<pubDate>Wed, 01 Jan 2014 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/2014/01/01/north-america-2013-montreal/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>Back across the country again, this time to Francophone Montreal.
This particular point was underscored in baggage claim when a woman
came up and asked me a question in French&mdash;I had to apologise for not
speaking the language<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>, and she apologised herself but explained
that there are now laws requiring you to speak French first!  (I
assume this only applies to service personnel, but I don&rsquo;t know for
sure).  I also got to witness some proper Latin passion and anger, as
the storms that delayed our landing and many others, coupled with only
a single baggage crew, meant our bags were delayed by several hours.</p>
<p>This trip was easily the longest I had ever taken on my own, and I
wasn&rsquo;t sure exactly how I was going to go.  Until now it hadn&rsquo;t even
been an issue as I caught up with friends in Vancouver and stayed with
others in Alberta, and only had a few days to myself in Toronto.  By
pure fortune I was again blessed with company in Montreal; a good
friend from Vancouver had just moved to start attending MacGill
University with a few days free before term started, and a friend from
home put me in touch with a friend of hers now in Montreal, who then
spent 3 days showing us both around!</p>
<p>The company and the good times made Montreal one of my favourite
cities of the trip, but I&rsquo;d like to think that it would have been fun
regardless.  Toronto had been nice to explore, but perhaps I had had
misplaced expectations or didn&rsquo;t stumble over the right parts as it
didn&rsquo;t feel like anything more than that.  On landing in Montreal at
night though I checked in and headed out to find dinner, and there
seemed to be a real crackle, and electricity in the air.  I&rsquo;m sure the
brutal winters are a different story, but the summer certainly seemed
like fun!</p>
<h1 id="graffiti-galore">Graffiti Galore</h1>
<p>New friend Liv picked me up from the hostel and introduced me to the
<a href="https://bixi.com/">Bixi Bike</a> bike rental system.  I later saw the
same bikes under different names in later cities, but this was my
first encounter, and what a brilliant system it is, even if the
weather restricts their use to only 6 months in Montreal.  Montreal
also proved to be quite bike-friendly, and we followed a number of
bike paths to <a href="http://lecartet.com/">brunch</a>.</p>
<p>Well-fed, we wandered the old quarter, then headed north checking out
funky shops and landmarks.  There had recently been a graffiti
festival and there were great works everywhere.</p>
<p>That night all three of us went to dinner in the gay village
nearby&hellip; apparently it was fetish weekend, and the street fashion
parade was nothing if not educational (no photos, sorry).</p>
<!-- raw HTML omitted -->
<h1 id="tam-tams">Tam Tams</h1>
<p>After a much-needed sleep-in I met up with Vancouver friend Alissa and
we walked up to the Tam Tams on Mount Royale.  The mountain park looks
over the entire city and we had quite a nice view from the top.  The
Tam Tams themselves is a summer weekends gathering, including several
epic drum circles, lots of circus arts, DJs, some ancient battle
reenactments, and generally a vibe somewhere between a hippie festival
and the beach.</p>
<p>For all the colourful sites, the pick of the lot might have been
watching the drum circle when I noticed an older shirtless guy stick a
joint in one nostril, cover the other with a finger and inhale with
such effort his head was on his knees by the time he&rsquo;d finished his
drag, then repeated it with his other nostril.  I don&rsquo;t think I&rsquo;ve
ever seen eyes roll that far back into someone&rsquo;s head.</p>
<p>Joined again by Liv later that evening we hit up a whisky bar for a
while, then a brew pub, then finally at 2 or 3am&mdash;my very first
poutine.  Surely there can&rsquo;t have been a more appropriate time or
frame of mind for it!  (There was quite a queue for it too)</p>
<!-- raw HTML omitted -->
<h1 id="ile-st-helen">Ile St Helen</h1>
<p>Feeling rather subdued the next morning, I met Liv again for the
famous <a href="http://schwartzsdeli.com/">Schwartz&rsquo;s Smoked Meats</a>.  This is
one of those institutions that has a lengthy queue outside and
ultra-efficient staff inside.  Fortunately with local help I knew how
to order (they ask how fatty you want it, for example).  When it
arrives it&rsquo;s essentially a few tiny bits of bread, utterly dwarfed by
the mound of meat inside, and of course nigh-impossible to eat without
it all falling apart.</p>
<p>Even with that now lining our stomachs the residual hangovers, the
grey weather and a public holiday to boot all meant today was not
going to be energetic.  Picking up Alissa we caught the subway over to
Ile St Helene, now probably most notable as the somewhat-decaying
former site of <a href="http://en.wikipedia.org/wiki/Expo_67">Expo 67</a>.  We
listlessly explored the biodome, before jumping on the subway again to
check out Atwater where we explored the market and found dinner.</p>
<!-- raw HTML omitted -->
<h1 id="atwater">Atwater</h1>
<p>On my own for my final day, I managed to find a hair cut then set off
to explore the Italian district.  This didn&rsquo;t excite me as much as I&rsquo;d
hoped, and I worked my way slowly back down, exploring on the way,
then cycled back to Atwater for more of an explore.</p>
<p>I checked out a restaurant tip for my final dinner, where for some
reason I was the only customer (apparently it is normally pumping) and
the bored waitress was quite chatty and gave me plenty of tips for my
next destination&hellip; New York!</p>
<!-- raw HTML omitted -->
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>I did study it for 4 years in high school too.  Not a skerrick
remains, sadly.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content>
		</item>
		
		<item>
			<title>On Memes And Me</title>
			<link>https://blog.markhepburn.com/2014/01/01/on-memes-and-me/</link>
			<pubDate>Wed, 01 Jan 2014 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/2014/01/01/on-memes-and-me/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>Once upon a time I would have prided myself for being on top of a
sizeable portion of the internet, at least in the
<a href="http://www.reddit.com/">breaking</a>-<a href="http://news.ycombinator.com/">nerd</a>-<a href="http://slashdot.org/">news</a>
sphere.  Lately, again and again I keep stumbling across memes that
seem to have been entrenched for ages, but of which I was blissfully
ignorant.<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> Case in point: I only just heard about
<a href="http://knowyourmeme.com/memes/doge">doge</a>.  (Boy am I impressed by
the thoroughness of research behind
<a href="http://knowyourmeme.com/">knowyourmeme.com</a> though!)</p>
<p>I&rsquo;m not sure what to make of it, but I suspect it means I&rsquo;ve been more
productive recently.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Some just seem simply
<a href="http://knowyourmeme.com/memes/harlem-shake">stupid</a> too, but that&rsquo;s
probably me getting old.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content>
		</item>
		
		<item>
			<title>Stunning Alberta</title>
			<link>https://blog.markhepburn.com/2013/12/27/stunning-alberta/</link>
			<pubDate>Fri, 27 Dec 2013 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/2013/12/27/stunning-alberta/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>After having flown half-way across the country to
<a href="/2013/12/24/north-america-2013-toronto/">Toronto</a>,
I then turned around and flew most of the way <em>back</em>.  It&rsquo;s a long
story and I wasn&rsquo;t overly happy about this schedule, particularly
since I was only going to fly even further back again afterwards, but
that was the way events transpired.</p>
<p>I was to stay with a friend and fellow programmer I knew from my time
in Vancouver but who worked remotely out of Canmore, a little town not
too far from the famous Banff national park.  The view of Calgary from
the plane was overwhelmingly flat, and I even fell asleep not long
after catching the bus.  When I woke up&hellip; suddenly I was in
mountains!  Waiting for him to pick me up after the bus dropped me
off, gazing at the scenery all around, it wasn&rsquo;t hard to see why he
chose to work remotely.  When even the bus stop has vistas like that
your town has something going for it, and the views only got better
that week.</p>
<p>The other thing that stood out as the traffic dawdled by, and
apparently the first thing I said when he arrived&hellip; &ldquo;Does everyone
here drive a truck??&rdquo;.  Yes, yes apparently they do.  We&rsquo;re in
Alberta!  Trucks, or if you&rsquo;re a tourist, a big motor-home.  That was
pretty much all I saw on the roads for a week.</p>
<p>Not surprisingly, the view from their balcony was even better.</p>
<p>I was staying with them for a week, and we sketched out 4 days of
hiking.</p>
<h1 id="ha-ling-peak-and-spray-trail">Ha Ling Peak and Spray Trail</h1>
<p>I didn&rsquo;t stray too far from home base on my first day.  Firstly, in
Canmore you simply don&rsquo;t need to go far to find something amazing, and
secondly&hellip; driving.  They very kindly let me borrow their car
(truck), but I have only ever driven on the left side of the road and
even though I was carrying an international driver&rsquo;s license<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> I
wanted some time to get my confidence up.  With that in mind, we
mapped out directions to Ha Ling Peak, visible from the balcony as a
sheer rock face but more straightforwardly accessible from the rear.</p>
<p>Getting there involved a short trip through the town, which apart from
turning my windscreen wipers on multiple times I survived without
incident, then heading up through a saddle to the trailhead behind.
The climb itself was nice; I overestimated my hiking fitness and blew
out of the gate, through some nice forest, before having to concede
defeat and slow down significantly as the route gave way to exposed
rock, and my cardiovascular system humbled me.</p>
<p>The view from the top: out of this world.</p>
<p>After descending I kept driving for an hour or so along the Spray
Trail, periodically exclaiming in amazement, until I realised it was
useless to stop for photos every time.</p>
<p>By the time I turned back for home I was a little fatigued from the
driving, and luckily was tailing another car as it suddenly slowed and
pulled way out around a bend.  I followed cautiously&mdash;only to have a
moose on the road block out the full opposite side of the vehicle!
Unfortunately I&rsquo;d already put the camera away and by the time I&rsquo;d
wrestled the case from my backpack, and the camera from the case, I
only got the one shot of its backside retreating back into the forest.
Just the strangest combination of massive size (even for a small one),
ungainly looking proportions, and majestic grace in its movement.</p>
<!-- raw HTML omitted -->
<h1 id="lake-louise-and-the-plain-of-6-glaciers">Lake Louise, and the Plain of 6 Glaciers</h1>
<p>The next day, and time for my first entry into Banff itself.  Lake
Louise is a massive tourist draw, which this time <em>does</em> rather
detract from the experience; both the huge crowds clustered around the
shore, and the enormous ugly hotel right behind you.  It is definitely
pretty, just a little hard to appreciate in that atmosphere.</p>
<p>Fortunately as soon as you start walking even a little way around the
shore you leave the vast majority behind, and while I never felt
isolated as I headed up the valley it was much more pleasant.</p>
<p>First stop was the plain-of-6-glaciers tea-house where I had a snack
and watched the extremely well-fed and cheeky ground-squirrels climb
up onto the tables.  I pushed up closer to the glacier (and having
climbed off-track up a scree-slope, unfortunately missed witnessing an
avalanche), then returned back down the same way, before looping
around via Lake Agnes and Mirror Lake.</p>
<p>The other big tourist draw in the area was Moraine Lake, but
unfortunately I didn&rsquo;t have enough time left and had to head back.</p>
<!-- raw HTML omitted -->
<h1 id="stanley-glacier">Stanley Glacier</h1>
<p>Stanley Glacier it turns out, is actually in British Columbia again.
It was a fairly long drive to get there, followed by a moderate climb
through a burned-out area (although not unpleasant views).</p>
<p>Suddenly, you emerge into a large basin, with Stanley Glacier in the
corner and massive walls all around you&mdash;looking back it was actually
quite hard to see where the trail even entered!  Naturally I pulled
out the camera to start snapping again&hellip; and found a completely dead
battery.  Never skip a recharge opportunity.  The latter photos you
see are all from my phone, unfortunately.</p>
<!-- raw HTML omitted -->
<h1 id="moraine-lake--and-bears">Moraine Lake.  And Bears.</h1>
<p>One final hiking opportunity left!  Another big draw in the area is
the <a href="http://www.icefieldsparkway.ca/">ice fields</a>, but we decided this
was a bit much driving to be worth it and instead settled on a
&ldquo;compromise&rdquo; of Helen Lake, including a pass on the edge of the
fields.  After the requisit stops for photos on the way there (no,
apparently I&rsquo;m not yet habituated to the scenery!) I finally found the
trailhead&hellip; and a sign saying it was shut due to a bear + cubs in the
area.  Bugger.</p>
<p>The fallback plan I came up with was Moraine Lake, since I&rsquo;d missed it
a few days earlier, and I headed back up the highway and miraculously
managed to find a park (unlike Lake Louise, it is rather light-on in
that department).  It is still a large tourist draw, but this time it
detracted far less from the stunning view.</p>
<p>Once I&rsquo;d taken enough snaps I headed around the lake to a short hike I
was keen on&hellip; and another sign warning of bears in the area!  This
time the advice was not to hike in groups of less than 4, but after
waiting a while no further candidates appeared and I gave up.  Not an
ideal way to wind up my visit, but I can hardly complain given the
rest of the week!</p>
<p>I had some great times on this trip, but without detracting from the
rest at all I don&rsquo;t think anything quite topped Alberta.</p>
<!-- raw HTML omitted -->
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Obtaining this is a simple financial transaction.  Absolutely no
proof of competence required.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content>
		</item>
		
		<item>
			<title>North America 2013: Toronto</title>
			<link>https://blog.markhepburn.com/2013/12/24/north-america-2013-toronto/</link>
			<pubDate>Tue, 24 Dec 2013 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/2013/12/24/north-america-2013-toronto/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>Travel began for real when I left the familar environs of Vancouver
for bustling cosmpolitan Toronto.  I had been toying with the idea of
catching a
<a href="http://www.viarail.ca/en/explore-our-destinations/trains/rockies-and-pacific/toronto-vancouver-canadian">train</a>,
inspired by visions of getting some hacking and reading done when I
wasn&rsquo;t admiring the stunning scenery.  A little further investigation
revealed that it was rather pricy and just as slow, that most of the
stunning scenery whisked by while you slept on the first night, and
besides&hellip; every photo suggested I was not even remotely in their
target age bracket.  By this stage I had been making plans to visit
said stunning scenery in person anyway, so in the end I just flew.</p>
<h1 id="day-1-bearings">Day 1: Bearings</h1>
<p>My favourite way to explore a city is on foot, and there was perfect
weather for it.  My hostel, which was student accommodation most of
the year, was quite close the Ryerson university campus and Dundas
square.  Lots of buskers around; it turned out there was a festival
on.  After a bit of an explore around this area I took off up
<a href="http://en.wikipedia.org/wiki/Yonge_Street">Yonge Street</a>, the
(formerly) longest street in the world depending on your accounting
method.  One unexpected highlight before I left Yonge was a book store
dedicated to <a href="http://www.cook-book.com/">cook books</a>!</p>
<p>Turning left I wound back via the fashion district (I think?), the
rather striking museum facade, the college area (looking very
Ivy-league, and apparently portrays Harvard in movies more frequently
than Harvard itself does), Kensington markets, and the financial
district.</p>
<p>I closed the day up on the roof of the hostel when I realised it was
accessible!</p>
<!-- raw HTML omitted -->
<h1 id="day-2-niagara-falls">Day 2: Niagara Falls</h1>
<p>I had booked a tour to Niagara falls through the hostel, and went down
at the annointed time to wait&hellip; and wait and wait, introducing myself
at some point to the gentleman also clearly waiting.  After some time
the hostel rang on our behalf, to discover they had left without us!
This was one of the best pieces of luck to hit yet: they refunded our
money, booked us onto a tour leaving at lunch time for free, and in
the mean time gave us a free bus tour of the city, which added context
to parts I&rsquo;d wandered the day before and introduced me to others I
hadn&rsquo;t.</p>
<p>The tour itself I think is fairly standard; we stop for an ice-wine
tasting along the way, pass through the creepily Stepford-wives-like
town of
<a href="http://en.wikipedia.org/wiki/Niagara-on-the-Lake">Niagara on the Lake</a>
(so fastidious about preserving its appearance that tourist buses have
to park on the outskirts and no franchise is allowed in the
centre<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>), and finally the falls themselves.</p>
<p>The volume of water is definitely breathtaking (as is the Disney-like
shops and attractions surrounding it); the mist rises up at least as
high again as the falls themselves, and if you take the boat out will
drench you even further out than you&rsquo;d expect.</p>
<p>There was an interesting side-note to the boat ride: the operators
have a long-term lease that is now an incredible bargain.  Recently
there was a stand-off when the park authorities tried to raise their
rent, the boat operators refused and threatened to dismantle the dock
they had built themselves if evicted, and in the end were allowed to
continue as-is.  The lease expires very soon however, and not
surprisingly they were not awarded the next contract.</p>
<!-- raw HTML omitted -->
<h1 id="day-3-whiskey-district-and-people">Day 3: Whiskey District and People</h1>
<p>Let us just say that I may have miscalculated my schedule!  Again in
glorious weather I wandered south this time, to the whiskey district
(another one of those areas you&rsquo;d recognise, apparently the same the
world over; a long-time industrial complex of some description, now
rennovated into lots of trendy cafes and art galleries) and Lawrence
Market.</p>
<p>After lunch I headed over to the iconic
<a href="http://www.cntower.ca/">CN Tower</a>, with no inkling this might have
been a bad idea.  My Niagara companion had assured me he had visited
and didn&rsquo;t have to queue too long at all, and at no point had I
considered that perfect weather and this being Saturday would alter
anything (in truth, I had already lost track of what day it was
anyway).  Result: I had to queue to buy a ticket, then kill the next
hour somehow, then spend another hour and a half in the queue getting
up there, getting jostled by noisy kids and steadily going insane.</p>
<p>The view: yes, definitely impressive, but I also did not wait too long
in getting out of there.</p>
<p>After this assault on the senses I wandered back across town to the
ferry terminal, to check out the islands offshore.  Unfortunately, the
experience was remarkably similar: perfect weekend weather meant I was
far from alone, and by the time I got over there I took a few skyline
photos back at the city, and got the hell out of there too.</p>
<p>The busker festival was in full swing by the time I got back, so I did
wander up Yonge for a while taking in some performances and grazing on
street food for dinner, but getting thoroughly peopled-out and heading
back to the hostel.</p>
<!-- raw HTML omitted -->
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>An exception was recently made for a Starbucks, although they
had made so many changes to the livery it was hard to recognise.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content>
		</item>
		
		<item>
			<title>North America 2013: Back to Vancouver!</title>
			<link>https://blog.markhepburn.com/2013/12/22/north-america-2013-back-to-vancouver/</link>
			<pubDate>Sun, 22 Dec 2013 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/2013/12/22/north-america-2013-back-to-vancouver/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<h1 id="on-the-road-again">On The Road Again</h1>
<p>In August of 2013 I quit my safe and secure, well-paying, flexible job
that gave me a lot of time to travel for&hellip; the incredible uncertainty
of starting a company with a close friend but no clients lined up.</p>
<p>There is unlikely to be much international travel in my near future.</p>
<p>So, there was only one thing for it: one final excursion in between
comfort and the unpredictable future.  The only question remaining was
<em>where</em>.  A number of options were suggested or otherwise came to
mind: back to South America perhaps, or to see friends in the Tyrol
(and I still haven&rsquo;t seen much of Europe!).  In the end though, I
decided to go to another great continent I&rsquo;ve barely touched: North
America.</p>
<p>I booked flights into Vancouver and out of LA, with a vague plan to
work my way across Canada then back across the US.  In amongst that I
thought I could mix some of the classic cities and areas on offer with
the majestic national parks, and with any luck catch up with a few
friends scattered around the area.  Any attempt at a more detailed
plan only made it clear that 3 months was not going to be sufficient,
so I just took off to figure it out along the way and take what
opportunities presented themselves.</p>
<p>Apart from the general across-and-back opportunity afforded by this
schedule, Vancouver was the first stop because I&rsquo;ve spent a fair bit
of time in Vancouver over the last few years, and I still love it and
still have friends there (although a few are starting to migrate out,
sadly).  My starting point was thus always going to be more a social
visit than anything touristy, although I did mount a decent
investigation of the <a href="http://revolvercoffee.ca/">thriving</a>
<a href="http://www.49thparallelroasters.com/">espresso</a>
<a href="http://www.bumpngrindcafe.com/">culture</a> in the city (more on this
aspect of my travels later!)</p>
<h1 id="victoria">Victoria</h1>
<p>The main exception was a quick visit to Victoria on Vancouver Island,
the capital city of British Columbia.  I splashed out on the sea plane
across as well, well worth it for the views of the stunning coastline
and islands.</p>
<p>Victoria itself was really pretty, plenty of good cafes if you&rsquo;re in
to that, a rather touristy but nice historical area, and an attractive
harbour.</p>
<!-- raw HTML omitted -->
<p>My biggest win by far here was whale-watching, which wasn&rsquo;t even on my
radar before visiting.  When I realised it was a possibility I spent a
bit of time at the hostel researching the options in their brochures,
set off down to the harbor to ask more detailed questions&hellip; and
promptly went with the first operator I met, who offered a discount
and immediate departure (it turns out there are a <em>lot</em> of
whale-watching operators, lining the harbour on both sides).  Never
have I made a better impulse decision!  The guide explained that there
are a couple of resident pods and also a transient pod of Orcas in the
area, and that we would check in on the latest siting of the
transients before moving on to hang out with the residents.  As things
transpired though, we quickly found the transient group and in a very
playful mood, with only a couple of other boats for company so we
spent all our time watching them.  They repeatedly came quite close to
the boat (one passed right under), and I even saw one do a 3/4 breach
(not even close to being photographed though).  Photographically it is
another story, as anyone who has been whale-watching will probably
tell you: most pictures you grab are the result of a quick swivel just
in time to catch the animal on its way down again&mdash;the famous black
humps.</p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>South America 2012</title>
			<link>https://blog.markhepburn.com/2013/12/15/south-america-2012/</link>
			<pubDate>Sun, 15 Dec 2013 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/2013/12/15/south-america-2012/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>Yet another belated catch-up post!  At the start of 2012, only a few
months after returning from
<a href="/2013/12/08/back-to-nepal-annapurna-2011/">Nepal again</a>,
I took off for South America with a good friend and not much in the
way of planning.  Rather, we had a rough outline in mind, but apart
from our first night&rsquo;s accommodation and the (other) Inca Trail trek
we had nothing booked and all other &ldquo;plans&rdquo; went out the window on our
first night in Buenos Aires.</p>
<p>In an effort to get the blog back up to date, this post will cover the
entire 6 weeks in one hit, and be mostly photographs.  Unfortunately
this trip was also when I finally got frustrated with my photography
skills and camera; I have since upgraded the camera, although not the
ability.  I apologise for the sub-standard quality of most of the
pictures.</p>
<p><em>TL;DR:</em> I loved South America.  It is quite large though, and we
attempted to cover way too much of it in 6 short weeks, but I wouldn&rsquo;t
change much (just so long as I get to go back).</p>
<h1 id="argentina">Argentina</h1>
<p>We flew into Buenos Aires, and owing to that flight winding up while
we were away, were to fly out of Chile.  The first step is paying the
delightfully honestly named &ldquo;reciprocity fee&rdquo; (ie, &ldquo;your country
charges a fee to our citizens, so we&rsquo;re going to make some money off
you too&rdquo;).</p>
<p>Struggling with jetlag we set off exploring from the hostel, and
unfortunately managed to find the financial district &mdash; initial
impressions of the city weren&rsquo;t that glamorous.  The morning after we
met a returningtraveller at a hostel Spanish class, and she showed us
around.  Via a fasionable district (whose name I forget), and quite a
lot of wine, we spent the afternoon in bohemian-hip Palermo then had
some of the best steak I&rsquo;ve ever eaten at
<a href="http://www.parrillalacabrera.com.ar/">La Cabrera</a>.  Secondary
impressions were much different: Buenos Aires is a <em>sexxxxxy</em> city,
full of extraordinarily attractive people and very European-styled
architecture.</p>
<p>We also learned that wine carafs are shaped like penguins
(&ldquo;Pinguinos&rdquo;).  I don&rsquo;t know why either, but we saw quite a few of
them.</p>
<p>The next day travel exhaustion hit like a hammer, and we were woken
about midday by the hostel staff evicting us.  Blearily we wandered
out with our guide friend again and explored La Boca, including the
famous <a href="http://en.wikipedia.org/wiki/La_Bombonera">La Bombonera</a>
stadium where Boca Juniors (Maradona&rsquo;s club) play.</p>
<p>On a whim, based on nothing more than a conversation at the hostel the
day before, we found the bus station that evening and managed to
figure out how to buy over-night tickets to Mendoza &mdash; wine country!
Buses are a real treat (if you pay enough, which is still fairly
cheap); much roomier than aeroplanes, plus they feed you, play you a
movie, and even bingo!  (Good for practicing our still-limited
Spanish).</p>
<p>Mendoza was fun, and the main activity is hiring a bike and touring
the myriad vineyards.  The local drivers seem well acquainted with
slightly unsteady tourists late in the day.  Not many photos from that
experience however.</p>
<!-- raw HTML omitted -->
<h1 id="patagonia">Patagonia</h1>
<p>From Mendoza it was time to head south for the Torres del Paine&hellip; and
on no planning ahead that meant struggling with online booking forms
to eventually find flights, then fly <em>back</em> to Buenos Aires and spend
the night in a bar at the airport before an extremely early flight
south to El Calafate.  The plan was to catch a bus over the border
into Chilean Patagonia, to the town of Puerto Natales.
Unfortunately&mdash;it&rsquo;s almost as if this was planned&mdash;there is a single
bus a day, which leaves just before the only flight in arrives.  So,
there was nothing for it but to find accommodation, and book a tour to
the Perito Moreno glacier (the only attraction in El Calafate!).  The
glacier is amazing, but they also leave you there to try and see ice
breaking off, for <strong>7 hours</strong>.  There is a single cafe above the
viewing area: again, it could almost have been planned!  We instead
stuck it out, and as luck would have it got chatting to 3 others (one
couple and a solo) who we wound up walking with.</p>
<p>The next morning we caught the bus to Puerto Natales, found
accommodation and visited the regular trekker&rsquo;s information session
held at a local gear shop.  The rest of the day was shopping, hiring
equipment, and packing.</p>
<p>The trek itself was magnificent, and naturally the photos don&rsquo;t
capture it at all.  We were quite lucky with the weather too.  While
waiting for a ferry across the lake to the trailhead we went on a
short walk to a nearby waterfall&hellip; just as the heavens opened and we
got completely soaked through.  I will admit to a few misgivings at
this point, but after that we really had amazing weather (although
&ldquo;amazing&rdquo; also includes wind gusts that made it impossible to stand).</p>
<p>As we were leaving the park we suddenly realised that the
<a href="http://www.navimag.com/">Navimag ferry</a> was an option&mdash;we had heard
about it before leaving Australia, but our then-&ldquo;plan&rdquo; meant we would
miss it.  Back in Puerto Natales though we managed to get tickets,
then had to book an extra night (meaning two extra days since the
ferry left the evening of the following day).  The scenery through the
fjiordlands is unquestionably magnificent, but it is similarly
magnificent for 3 full days; that plus the extra days in Puerto
Natales wrote off close to a week, which in a 6 week holiday we could
ill-afford.  I would recommend it if you have the time, but it is the
only thing I would change about my own experience, really.</p>
<p>The boat arrives in Puerto Montt, for which the Lonely Planet&rsquo;s
inspiring advice is &ldquo;catch a bus to Puerto Varas&rdquo;.  So we did that,
and despite our early arrival meaning nothing was open we did find a
local hostel that agreed to take us on a tour.  Puerto Varas has quite
a lot of Germanic influences, but our tour was exploring the volcanic
mountains and the nearby lake.  My personal highlight was
noticing&mdash;and only just avoiding stepping on&mdash;a rather rare Darwin&rsquo;s
tree frog, which as you can see in the photo has almost lost its green
colour in order to again blend in with the now-dead foliage.</p>
<p>At the end of the day we caught another plane up to Santiago.</p>
<!-- raw HTML omitted -->
<h1 id="santiago-de-chile">Santiago de Chile</h1>
<p>We arrived late in the evening and had no accommodation booked, apart
from a &ldquo;tip&rdquo; from the hostel guy in Puerto Varas.  So we caught a taxi
to this tip, who was rather surprised to see us and certainly in no
position to offer lodging.  He did take us on a walk, rather bemused
at this point, a few blocks away where a few people all stuck their
heads out of second-story windows, and eventually a door opened and we
had a bed for the night.  It turned out that a few people on the
street offered spare rooms for rent, mostly to university exchange
students, but at the time it was quite a bizarre experience.</p>
<p>Initial impressions of Santiago were&hellip; rather underwhelming.  It was
only later that we realised it was Easter weekend and most people were
away (and those remaining were obviously not in a mood to open their
businesses).  We experienced a much more lively Santiago when we
stayed our final night there before flying home!</p>
<!-- raw HTML omitted -->
<h1 id="peru-macchu-picchu">Peru (Macchu Picchu)</h1>
<p>From Santiago we flew up to Cusco in Peru, the old capital and the
launching place for trekking to Machu Picchu.  This was the only thing
we had booked in, and because the main Inca Trail books out months in
advance (and we were not that organised) and has visitor limits, we
had opted for the less well-known
<a href="http://en.wikipedia.org/wiki/Salcantay">Salkantay route</a>.  I don&rsquo;t
regret this for a second; it was less populus, hits a higher altitude,
and generally definitely felt like an adventure (albeit, unlike in
Patagonia an adventure where most of our luggage was carried for us
and all meals prepared for us!).  It is also a porter route, which
means lots of horses go on the path, which meant it was incredibly
muddy.</p>
<p>We had a few slight detours around fresh land slips, none more so than
at the end where we had to catch a jeep to the spot where most of the
road had simply fallen down the steep incline, get out and nervously
walk the 1 metre of remaining road to the other side and catch another
jeep.</p>
<p>Eventually we arrived in Aguas Calientes for the morning visit to
Machu Picchu itself.  I honestly did not expect to be that impressed;
granted the photos are spectacular, but you typically only ever see
the same slightly-elevated view, and I cynically expected it to have
more a plasticy theme-park feel to it.  Boy was I wrong: not only is
the setting so much more stunning in person, but the scale and detail
up-close is just breath-taking.  We also climbed Huena Picchu for an
areal view.</p>
<!-- raw HTML omitted -->
<h1 id="bolivia">Bolivia</h1>
<p>We had booked flights into Bolivia before our trek, and had arrived
back in civilisation (internet) to find that they had been cancelled,
so we had to find a bus instead.</p>
<p>We spent a day or so exploring La Paz, which is a rather beautiful
city at quite a high elevation, and with markets that go even higher
with no end in site!  Following that we caught a bus to Uyuni for the
standard 3-day 2-nights &ldquo;salt flats of Uyuni tour&rdquo;.  Our jeep had 3
separate travel-pairs, and we all got on like a house on fire.  The
scenery is just remarkable too, from the train graveyard (so much more
fun than you&rsquo;d expect!), to the bizarre lack of visual perspective on
the salt flats themselves (watching people posing photographs is
almost as much fun as posing them yourself), to the surreal colours
and rock formations in the deserts.  Bolivia is beautiful, and
definitely on my list of places to visit more thoroughly.</p>
<p>We finished by crossing the border back into Chile in San Pedro de
Atacama.</p>
<!-- raw HTML omitted -->
<h1 id="valparaiso">Valparaiso</h1>
<p>For our final stop of the trip we had splurged on nice accommodation
in Valparaiso.  Unfortunately we were unable to splurge on transport
there, where our usual last-minute strategy let us down and we had to
watch our Canadian travel buddies have a leisurely dinner and fly
there, while we sucked it up on a 24 hour bus ride to Santiago, then
walk to a different bus station and catch another bus.  Then we
couldn&rsquo;t find a taxi at that time of night, but some local guy
loitering around was more than happy to pretend to be one.</p>
<p>Valparaiso is a beautiful town and amazing to wander.  Set on some
very steep hills, it was a once-booming port town that fell into
disrepair as the port business dried up, only to be reinvigorated as a
tourist town.  It still has that slightly edgy, slightly gritty feel
to much of it, while the other distinguishing feature is the
astonishing amount of graffiti murals covering the steep hills.</p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Back to Nepal: Annapurna 2011</title>
			<link>https://blog.markhepburn.com/2013/12/08/back-to-nepal-annapurna-2011/</link>
			<pubDate>Sun, 08 Dec 2013 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/2013/12/08/back-to-nepal-annapurna-2011/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>A very, very belated post I&rsquo;m sorry!  An early impetus for this blog
was to catalogue my travels&hellip; this is now <em>slightly</em> out of date,
such that if I have any hope of resurrecting it I&rsquo;d better start now.
I&rsquo;m also just back from yet another long trip so, yes, it&rsquo;s definitely
now or never.</p>
<p>Once upon a time
(<a href="/posts/2010-11-19-random-observations-from-the-nepal-himalaya/">2010</a>),
I fulfilled a life-long dream and went trekking in Nepal.  It was,
happily since &ldquo;life-long dreams&rdquo; are frequently let-downs, amazing.
It was so good that I knew I had to go back, and it was only going to
be a matter of time&hellip; in fact, less than a year later I started
planning with another travel-junkie friend.</p>
<p>This time, we did the
<a href="http://en.wikipedia.org/wiki/Annapurna_Circuit">Annapurna circuit</a>.
You will find this loop listed in many &ldquo;World&rsquo;s top treks&rdquo; lists, but
the reality is that it is rapidly losing its lustre as they build a
<a href="http://www.bbc.com/travel/feature/20110524-nepals-shrinking-annapurna-circuit">road</a>
in parallel to the path.  While this benefits many villages along the
route, for whom tourism is positive but not their main source of
income, its appeal to tourists is declining.  Our guide&rsquo;s tip as the
&ldquo;next big trekking circuit&rdquo; was the
<a href="http://wikitravel.org/en/Manaslu_Trek">Manaslu circuit</a>.</p>
<p>Yes, our guide.  In 2010 the three of us arrived with very little plan
and assuming we&rsquo;d find our own way.  We were talked into hiring a
guide by our hotel, which turned out in a stroke of luck to be a fine
decision as we wound up with a fantastic guide,
<a href="mailto:g.basnet@yahoo.com">Shyam</a>.  So, as we were planning this trip
I contacted him again, got a quote, and we paid our deposit.</p>
<p>Not long after, my new travel companion had friends telling her we&rsquo;d
been ripped off, that you can get a guide for half that in Kathmandhu,
and so on.  I felt bad for not even questioning it, but we were
committed at this point.  We surreptitiously asked fellow trekkers
along the way and indeed most were paying significantly less.</p>
<p>However!  There are definitely times when you get what you pay for.
Without going into details (the stories aren&rsquo;t mine to tell, for the
most part), at the end of the trek <em>every single other group</em> was
asking for Shyam&rsquo;s business card.  His experience and knowledge,
English language ability, easy-going manner and generosity with his
knowledge even for those who weren&rsquo;t paying him was, shall we say, in
contrast to the other guides we met along the way<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>.  I would
recommend him to anyone.</p>
<p>I won&rsquo;t go into much detail on the trek itself; check out some photos
below.  We didn&rsquo;t have the best weather, probably because we were too
early and on the tail of the monsoon season, and unfortunately had a
complete white-out at the top of the pass.</p>
<p>It is a completely different experience to trekking around Everest.
The <a href="http://en.wikipedia.org/wiki/Khumbu">Khumbu</a> region is stark, and
most tea houses are solely for tourism and close in the off seasons.
You rapidly gain altitude, and stay there for most of your trip.  In
contrast, the Annapurna circuit is a constant gradual climb, starting
much lower (and hence hotter).  You stay in actual villages, which is
a different experience (and you certainly eat better&mdash;not many
vegetables grow in the Khumbu!).</p>
<p>It was a great trip, despite the weather, and won&rsquo;t be my last.</p>
<!-- raw HTML omitted -->
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Not only that, but we did not discover along the way that he was
recently a Maoist rebel.  It&rsquo;s a long story, and as I said not mine to
tell.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content>
		</item>
		
		<item>
			<title>Andrew Hyatt&#39;s emacs calc tutorials</title>
			<link>https://blog.markhepburn.com/2013/12/07/andrew-hyatts-emacs-calc-tutorials/</link>
			<pubDate>Sat, 07 Dec 2013 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/2013/12/07/andrew-hyatts-emacs-calc-tutorials/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>If you use Emacs, then perhaps surprisingly one of the best places to
hang out is the
<a href="https://plus.google.com/communities/114815898697665598016">Google+ Emacs community</a>.</p>
<p>You also may or may not be aware of the
<a href="http://www.gnu.org/software/emacs/manual/html_mono/calc.html">calc</a>
facility embedded in Emacs.  It seems to be one of the lesser-known
features, and even among those who do know about it, many are unaware
how sophisticated it is.  You can invoke it with <code>M-x calc</code>, or <code>C-x * *</code> and at first glance it seems quite primitive&hellip; until you read the
manual, at which point it can instead seem impenetrable!</p>
<p>Hidden underneath the spartan, stack-based interface is matrix and
vector arithmetic, date and time calculations, unit-aware calculations
and conversion, symbolic manipulation, and on it goes.</p>
<p>Nearly a year ago <a href="http://google.com/+AndrewHyatt">Andrew Hyatt</a>
posted a series of tutorials that explored a lot of the corners, but
one of the weaknesses of Google+ is that content can be hard to
aggregate or find again.</p>
<p>So, when I remembered the other day I went back and dug up all the
ones I could find, in order to provide a pointer back to them!  Just
as I was completing the list I discovered that there is already
<a href="http://www.emacswiki.org/emacs/Calc_Tutorials_by_Andrew_Hyatt">one archive</a>
on the <a href="http://www.emacswiki.org">EmacsWiki</a>, but one more is
certainly not going to hurt discoverability.</p>
<h1 id="the-tutorials">The Tutorials</h1>
<ul>
<li><a href="https://plus.google.com/+AndrewHyatt/posts/goYiW8VfamS">Hex-decimal conversion</a>
(and general base conversion)</li>
<li><a href="https://plus.google.com/+AndrewHyatt/posts/TWdjoj1zirv">How old is David Hasselhoff?</a>
Basic date calculations.  Also, toggle digit grouping (number formatting)</li>
<li><a href="https://plus.google.com/+AndrewHyatt/posts/YFKHGksdeWy">More date-time manipulation</a>
In particular, Unix epoch conversion.</li>
<li><a href="https://plus.google.com/+AndrewHyatt/posts/QuN7vdJpSZN">Random numbers</a></li>
<li><a href="https://plus.google.com/+AndrewHyatt/posts/LNi5SJxXXxC">Unit conversion</a>,
including defining custom units.</li>
<li><a href="https://plus.google.com/+AndrewHyatt/posts/ggiQGdLyX41">Pi and digit precision</a></li>
<li><a href="https://plus.google.com/+AndrewHyatt/posts/VzAQ8QLyCXj">String to binary conversion</a></li>
<li><a href="https://plus.google.com/+AndrewHyatt/posts/bNw8CqAKpBR">Exact fractional arithmetic</a></li>
<li><a href="https://plus.google.com/+AndrewHyatt/posts/RYiWfs9NMTS">Algebreic manipulation</a></li>
<li><a href="https://plus.google.com/+AndrewHyatt/posts/YG2vYpGoLn3">More algebra</a></li>
<li><a href="https://plus.google.com/+AndrewHyatt/posts/YdwsbNmZ4NL">Finance</a></li>
<li><a href="https://plus.google.com/+AndrewHyatt/posts/a7HYKLnFuZh">Calculus</a>
(Integrals and derivatives)</li>
<li><a href="https://plus.google.com/+AndrewHyatt/posts/ECBKVLjtsok">Bit manipulation</a></li>
</ul>
]]></content>
		</item>
		
		<item>
			<title>Tagging blog posts from Emacs</title>
			<link>https://blog.markhepburn.com/2013/03/24/tagging-blog-posts-from-emacs/</link>
			<pubDate>Sun, 24 Mar 2013 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/2013/03/24/tagging-blog-posts-from-emacs/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>First, I apologise in advance (to all 3 of you subscribed) if you got
an avalanche of old new posts in your RSS feed.  I&rsquo;ve just gone
through and tagged a lot of posts.</p>
<p>What&rsquo;s most interesting, at least for me, was that I did it en-masse
via Emacs.  This blog is a set of static files generated by
<a href="http://jekyllbootstrap.com/">Jekyll Bootstrap</a>, as I have written
about <a href="/2012/06/23/new-blog/">previously</a>.  A post is
simply a file with a bit of <a href="http://yaml.org/">YAML</a> meta-data up the
top, optionally including tags applying to that post:</p>
<pre><code>---
layout: post
title: &quot;Sample yaml front-matter&quot;
tags: [SomeTag,AnotherTag]
---
Body of the post...
</code></pre>
<p>To simplify the repetitive work involved I wrote some elisp to take a
bunch of files, query for the relevant tags, and add them to the front
matter:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-scheme" data-lang="scheme"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">defun</span> <span class="nv">mh/tag-posts</span> <span class="p">(</span><span class="nf">tags</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;Apply tags (specified interactively) to the files marked in
</span></span></span><span class="line"><span class="cl"><span class="s">dired, merging with existing tags.  Assumes the use of
</span></span></span><span class="line"><span class="cl"><span class="s">jekyll-bootstrap, ie with the `---&#39; delimited yaml front-matter
</span></span></span><span class="line"><span class="cl"><span class="s">at the beginning.&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nf">interactive</span> <span class="p">(</span><span class="nb">list </span><span class="p">(</span><span class="nf">read-from-minibuffer</span> <span class="s">&#34;Tag(s), comma-separated: &#34;</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="k">let </span><span class="p">((</span><span class="nf">tags</span> <span class="p">(</span><span class="nf">split-string</span> <span class="nv">tags</span> <span class="s">&#34;[, ]+&#34;</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nf">labels</span>
</span></span><span class="line"><span class="cl">        <span class="p">((</span><span class="nf">do-tags</span> <span class="p">(</span><span class="nf">f</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                  <span class="p">(</span><span class="nf">with-current-buffer</span> <span class="p">(</span><span class="nf">find-file-noselect</span> <span class="nv">f</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                    <span class="p">(</span><span class="nf">save-excursion</span>
</span></span><span class="line"><span class="cl">                      <span class="p">(</span><span class="nf">goto-char</span> <span class="mi">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                      <span class="p">(</span><span class="k">if </span><span class="p">(</span><span class="nf">re-search-forward</span> <span class="s">&#34;^tags: \\[\\([[:alnum:], ]*\\)\\]&#34;</span> <span class="nv">nil</span> <span class="nv">t</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                          <span class="p">(</span><span class="k">let* </span><span class="p">((</span><span class="nf">existing-tags</span> <span class="p">(</span><span class="nf">split-string</span> <span class="p">(</span><span class="nf">match-string</span> <span class="mi">1</span><span class="p">)</span> <span class="s">&#34;[, ]+&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">                                 <span class="p">(</span><span class="nf">combined</span> <span class="p">(</span><span class="nf">union</span> <span class="nv">existing-tags</span> <span class="nv">tags</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">                                 <span class="p">(</span><span class="nf">new-tags</span> <span class="p">(</span><span class="nf">mapconcat</span> <span class="ss">&#39;identity</span> <span class="nv">combined</span> <span class="s">&#34;,&#34;</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">                            <span class="c1">;; replace-match wasn&#39;t working for some reason:</span>
</span></span><span class="line"><span class="cl">                            <span class="p">(</span><span class="nf">goto-char</span> <span class="p">(</span><span class="nf">match-beginning</span> <span class="mi">1</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">                            <span class="p">(</span><span class="nf">delete-region</span> <span class="p">(</span><span class="nf">match-beginning</span> <span class="mi">1</span><span class="p">)</span> <span class="p">(</span><span class="nf">match-end</span> <span class="mi">1</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">                            <span class="p">(</span><span class="nf">insert</span> <span class="nv">new-tags</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">                        <span class="p">(</span><span class="nf">progn</span>
</span></span><span class="line"><span class="cl">                          <span class="p">(</span><span class="nf">goto-char</span> <span class="mi">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                          <span class="p">(</span><span class="nf">forward-line</span> <span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                          <span class="p">(</span><span class="nf">re-search-forward</span> <span class="s">&#34;^---&#34;</span> <span class="nv">nil</span> <span class="nv">t</span><span class="p">)</span> <span class="c1">; find second occurence, assuming first is on line 1</span>
</span></span><span class="line"><span class="cl">                          <span class="p">(</span><span class="nf">goto-char</span> <span class="p">(</span><span class="nf">match-beginning</span> <span class="mi">0</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">                          <span class="p">(</span><span class="nf">insert</span> <span class="p">(</span><span class="nf">format</span> <span class="s">&#34;tags: [%s]\n&#34;</span> <span class="p">(</span><span class="nf">mapconcat</span> <span class="ss">&#39;identity</span> <span class="nv">tags</span> <span class="s">&#34;,&#34;</span><span class="p">))))))</span>
</span></span><span class="line"><span class="cl">                    <span class="p">(</span><span class="nf">save-buffer</span><span class="p">))))</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nf">mapcar</span> <span class="o">#</span><span class="ss">&#39;do-tags</span> <span class="p">(</span><span class="nf">dired-get-marked-files</span><span class="p">)))))</span>
</span></span></code></pre></div><p>The guts are in the last line: I mark files using
<a href="http://www.gnu.org/software/emacs/manual/html_node/emacs/Dired.html">dired</a>
in Emacs, then invoke <code>mh/tag-posts</code>, which applies a function to
every marked file.  This function then just has to take care of a few
corner cases such as the tag already being included (by using <code>union</code>
from the <code>cl</code> common lisp emulation library to avoid repetition), and
when there&rsquo;s no <code>tags: []</code> entry at all, in which case it must add
one.</p>
]]></content>
		</item>
		
		<item>
			<title>Query by example in Django</title>
			<link>https://blog.markhepburn.com/2013/03/14/query-by-example-in-django/</link>
			<pubDate>Thu, 14 Mar 2013 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/2013/03/14/query-by-example-in-django/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<h1 id="introduction">Introduction</h1>
<p>This is a quick hack, but I&rsquo;m throwing it out there in case anyone
knows of a better solution (or better yet, if I&rsquo;m missing something
obvious in the standard distribution).</p>
<p>The <a href="http://www.hibernate.org/">Hibernate</a> ORM for Java includes a
query-by-example facility: you create a template object, setting the
relevant fields to the values you&rsquo;re interested in, then it retrieves
all records that match that template (fields left un-set are ignored
in the query).</p>
<p>To the best of my knowledge, the
<a href="https://docs.djangoproject.com/en/1.5/topics/db/queries/">Django ORM</a>
doesn&rsquo;t support this style of querying.  I found myself wanting it
though,<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> and this post is what I came up with.</p>
<h1 id="implementation">Implementation</h1>
<p>The implementation is fairly simple: we use the meta attribute to get
the list of fields, and create a
<a href="https://docs.djangoproject.com/en/dev/topics/db/queries/#retrieving-specific-objects-with-filters">filter</a>
query from all non-<code>None</code> fields.  As simplification, I&rsquo;m currently
ignoring non-direct fields and many-many fields (in part because the
object I was working with hadn&rsquo;t been saved yet).  The id is also
skipped, because of course that should be unique!</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">QBEManager</span><span class="p">(</span><span class="n">Manager</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;&#34;&#34;A custom manager that adds query-by-example functionality (inspired
</span></span></span><span class="line"><span class="cl"><span class="s2">    by Hibernate)&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">similar_to</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">template</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;&#34;&#34;Find all objects that have fields matching those in the template
</span></span></span><span class="line"><span class="cl"><span class="s2">        object.  Fields that are set to None are ignored.&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="n">vals</span> <span class="o">=</span> <span class="p">{}</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">template</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">get_all_field_names</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">            <span class="n">_</span><span class="p">,</span><span class="n">_</span><span class="p">,</span><span class="n">direct</span><span class="p">,</span><span class="n">m2m</span> <span class="o">=</span> <span class="n">template</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">get_field_by_name</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="ow">not</span> <span class="n">direct</span> <span class="ow">or</span> <span class="n">m2m</span> <span class="ow">or</span> <span class="n">f</span> <span class="o">==</span> <span class="s1">&#39;id&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                <span class="k">continue</span>
</span></span><span class="line"><span class="cl">            <span class="n">val</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">template</span><span class="p">,</span> <span class="n">f</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="n">val</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                <span class="n">vals</span><span class="p">[</span><span class="n">f</span><span class="p">]</span> <span class="o">=</span> <span class="n">val</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="nb">super</span><span class="p">(</span><span class="n">QBEManager</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">get_query_set</span><span class="p">()</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="o">**</span><span class="n">vals</span><span class="p">)</span>
</span></span></code></pre></div><p>Then it can be used just like a regular manager:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Config</span><span class="p">(</span><span class="n">Model</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># ...</span>
</span></span><span class="line"><span class="cl">    <span class="n">objects</span> <span class="o">=</span> <span class="n">QBEManager</span><span class="p">()</span>
</span></span></code></pre></div><p>Using it anger is up to you:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">some_view</span><span class="p">(</span><span class="n">request</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># ...</span>
</span></span><span class="line"><span class="cl">    <span class="n">c</span> <span class="o">=</span> <span class="n">Config</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="n">c</span><span class="o">.</span><span class="n">start_time</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">date</span><span class="p">(</span><span class="mi">2012</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">27</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">c</span><span class="o">.</span><span class="n">length</span> <span class="o">=</span> <span class="mi">5</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># get all configs that start on 27/3/2013 and have length 5:</span>
</span></span><span class="line"><span class="cl">    <span class="n">matching_configs</span> <span class="o">=</span> <span class="n">Config</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">similar_to</span><span class="p">(</span><span class="n">c</span><span class="p">)</span>
</span></span></code></pre></div><h1 id="improvements">Improvements</h1>
<p>This solved my problem, but it&rsquo;s probably not fit for prime-time just
yet.  In particular, handling many-many fields could be added for
objects that are already saved (and hence are able to have m2m fields
established).</p>
<p>It is probably also better off written as a mixin; in particular, my
case was actually based off a GeoManager, and a mixin would enable
both base managers to be used.  Something like:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">QBEManagerMixin</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># ...</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">QBEManager</span><span class="p">(</span><span class="n">QBEManagerMixin</span><span class="p">,</span> <span class="n">Manager</span><span class="p">):</span> <span class="c1"># ...</span>
</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">QBEGeoManager</span><span class="p">(</span><span class="n">QBEManagerMixin</span><span class="p">,</span> <span class="n">GeoManager</span><span class="p">):</span> <span class="c1"># ...</span>
</span></span></code></pre></div><div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Specifically, I had a configuration model pre-populated,
and wanted to find if there was an existing result for that
configuration.  Basically I wanted caching, but there were reasons
that view caching (or even the low-level cache API) were not
appropriate.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content>
		</item>
		
		<item>
			<title>How to annoy a machine learner</title>
			<link>https://blog.markhepburn.com/2013/02/26/how-to-annoy-a-machine-learner/</link>
			<pubDate>Tue, 26 Feb 2013 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/2013/02/26/how-to-annoy-a-machine-learner/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p><a href="http://homes.cs.washington.edu/~pedrod/papers/cacm12.pdf">A Few Useful Things to Know about Machine Learning</a> (PDF):</p>
<blockquote>
<p>But bear in mind that features that look irrelevant in isolation may
be relevant in combination.  For example, if the class is an XOR of
<em>k</em> input features, each of them by itself carries no information
about the class.  (If you want to annoy machine learners, bring up
XOR).</p>
</blockquote>
<p>A fun paper, distilling the &ldquo;folk wisdom&rdquo; aspects of machine learning
that take up the majority of time into pithy and amusing quotes.
<a href="http://williamhartmann.wordpress.com/2012/12/31/a-few-useful-things-to-know-about-machine-learning/">Others</a>
have
<a href="http://blog.bigml.com/2013/02/15/everything-you-wanted-to-know-about-machine-learning-but-were-too-afraid-to-ask-part-one/">already</a>
<a href="http://blog.bigml.com/2013/02/21/everything-you-wanted-to-know-about-machine-learning-but-were-too-afraid-to-ask-part-two/">commented</a>
on the value it.</p>
]]></content>
		</item>
		
		<item>
			<title>More Electric Puncation</title>
			<link>https://blog.markhepburn.com/2013/02/19/more-electric-puncation/</link>
			<pubDate>Tue, 19 Feb 2013 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/2013/02/19/more-electric-puncation/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>Following on from
<a href="/2013/02/18/electric-punctuation-in-emacs/">my post yesterday</a>,
here&rsquo;s another quicky that I added recently.  This one is shamelessly
stolen from Eclipse, which has a handy option to correctly insert a
semi-colon or <code>{</code>-bracket from deep within a conditional or similar;
for example if you have,</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="n">Context</span><span class="w"> </span><span class="n">ctx</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">ContextFactory</span><span class="p">.</span><span class="na">getContext</span><span class="p">(</span><span class="n">Context</span><span class="p">.</span><span class="na">nullContext</span><span class="p">(</span><span class="o">|</span><span class="p">))</span><span class="w">
</span></span></span></code></pre></div><p>then hitting <code>; </code> straight away takes you to <code>getContext(...);|</code>
(mercifully, it has been a while).</p>
<p>I was missing this in python, where it was taking me a whole extra
keystroke or two, <em>every time!</em>, to jump to the end of the line to
insert a colon.  In the
<a href="https://github.com/fgallina/python.el">python mode I was using</a>
semicolon is already electric, so this time I had to advise it:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-scheme" data-lang="scheme"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">defadvice</span> <span class="nv">python-indent-electric-colon</span> <span class="p">(</span><span class="nf">around</span> <span class="nv">python-electric-colon-autoplace</span> <span class="p">(</span><span class="nf">arg</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                                                <span class="nv">activate</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="k">if </span><span class="p">(</span><span class="k">and </span><span class="p">(</span><span class="nf">looking-at</span> <span class="s">&#34;)&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">           <span class="p">(</span><span class="nb">not </span><span class="nv">arg</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nf">progn</span>
</span></span><span class="line"><span class="cl">      <span class="nv">ad-do-it</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nf">transpose-chars</span> <span class="mi">1</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="nv">ad-do-it</span><span class="p">))</span>
</span></span></code></pre></div><p>I.e. assuming we&rsquo;re not inserting multiple colons, insert then
transpose to leave the colon and cursor outside&hellip; but in fact, just
writing this I realise I didn&rsquo;t really go far enough at the time!  So
I&rsquo;ve just updated to this version:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-scheme" data-lang="scheme"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">defadvice</span> <span class="nv">python-indent-electric-colon</span> <span class="p">(</span><span class="nf">around</span> <span class="nv">python-electric-colon-autoplace</span> <span class="p">(</span><span class="nf">arg</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                                                <span class="nv">activate</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="k">if </span><span class="p">(</span><span class="k">and </span><span class="p">(</span><span class="nf">looking-at</span> <span class="s">&#34;)&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">           <span class="p">(</span><span class="nb">not </span><span class="nv">arg</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nf">progn</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nf">move-end-of-line</span> <span class="nv">nil</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="nv">ad-do-it</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nf">newline-and-indent</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="nv">ad-do-it</span><span class="p">))</span>
</span></span></code></pre></div><p>Insert correctly, indent, then ready to keep going on a new line: much
more efficient!</p>
]]></content>
		</item>
		
		<item>
			<title>Electric Punctuation in Emacs</title>
			<link>https://blog.markhepburn.com/2013/02/18/electric-punctuation-in-emacs/</link>
			<pubDate>Mon, 18 Feb 2013 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/2013/02/18/electric-punctuation-in-emacs/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>Funnily enough, the idea for this Emacs hack comes from my smart-phone
keyboard.</p>
<p>The awkward nature of pecking at glass, with no tactile feedback, also
means that there is a certain necessity for invention in order to
recapture the usability of a regular keyboard, and some nice ideas
come out of it.  Some of these make use of the different nature of the
surface itself, such as
<a href="http://www.youtube.com/watch?v=WuP6AQPRpUg">&ldquo;swipe&rdquo; typing</a>, while
others might provide a greater efficiency (in the average case), such
as automatically inserting punctuation, aggressive history-based
auto-completion, etc.</p>
<p>I swear by <a href="http://www.swiftkey.net/">SwiftKey keyboard</a>, and it has
been worth every one of the five dollars I think I spent on it &mdash; in
fact of all the examples I just provided they actually implement all
of them (now that they are
<a href="http://www.swiftkey.net/flow/">developing swipe typing</a> as well).</p>
<p>The other day at work, at a regular keyboard, I realised I was
actually missing one feature in particular, but luckily since I was in
Emacs it only took 10 minutes to implement!  That particular feature
was the way punctuation is correctly inserted in SwiftKey; if you
choose an auto-completion it will also insert a space, for example
leaving you with &ldquo;word |&rdquo; (where | is the cursor; note the trailing
space).  However, if you then type a comma it is inserted in the
correct place: &ldquo;word, |&rdquo;.</p>
<p>Basically, you never have to think about punctuation or spacing too
much, as it just works.  Here was the result of my
procrastination:<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-scheme" data-lang="scheme"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">defun</span> <span class="nv">mh/electric-punctuation</span> <span class="p">()</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;Tidy up whitespace around punctuation: delete any preceding
</span></span></span><span class="line"><span class="cl"><span class="s">  whitespace and insert one space afterwards.  Idea stolen from
</span></span></span><span class="line"><span class="cl"><span class="s">  the SwiftKey android keyboard.&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nf">interactive</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nf">when</span> <span class="p">(</span><span class="nf">looking-back</span> <span class="s">&#34;\s+&#34;</span> <span class="nv">nil</span> <span class="nv">t</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nf">delete-region</span> <span class="p">(</span><span class="nf">match-beginning</span> <span class="mi">0</span><span class="p">)</span> <span class="p">(</span><span class="nf">match-end</span> <span class="mi">0</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nf">call-interactively</span> <span class="ss">&#39;self-insert-command</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nf">just-one-space</span><span class="p">))</span>
</span></span></code></pre></div><p>In other words (assuming this function is triggered by punctuation),
if there is some preceding space then delete it, insert the original
character, and add a space afterwards.</p>
<p>Then to trigger this whenever I type a comma, semicolon, or period
within regular text, I add it to the base <code>text-mode</code> hook:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-scheme" data-lang="scheme"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">dolist</span> <span class="p">(</span><span class="nf">punc</span> <span class="o">&#39;</span><span class="p">(</span><span class="nv">?,</span> <span class="nv">?</span><span class="err">\</span><span class="c1">; ?.))</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nf">define-key</span> <span class="nv">text-mode-map</span> <span class="o">`</span><span class="p">[</span><span class="o">,</span><span class="nv">punc</span><span class="p">]</span> <span class="ss">&#39;mh/electric-punctuation</span><span class="p">))</span>
</span></span></code></pre></div><p>I will admit that it is taking me a little getting used to (it turns
out I have ingrained habits of typing punctuation+space, resulting in
lots of double-spacing!), and there&rsquo;s room for improvement.  In
particular, I suspect it needs a special case to handle numbers (you
don&rsquo;t want &ldquo;3.14&rdquo; to end up as &ldquo;3. 14&rdquo;).  I really appreciate SwiftKey
for the way they continually sand down corners, and there are no doubt
lots of corner-cases remaining here.  Still, it was the sort of
easy-to-implement idea that I love about Emacs!</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>&ldquo;Electric&rdquo; is common terminology in Emacs for keys &mdash;
typically punctuation &mdash; that perform some other action as well as
self-insertion.  These are particularly common in programming modes
where it may also indent, or even insert matching brace and
newline-and-indent.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content>
		</item>
		
		<item>
			<title>Enson Inoue and Yamato Damashii</title>
			<link>https://blog.markhepburn.com/2013/02/12/enson-inoue-and-yamato-damashii/</link>
			<pubDate>Tue, 12 Feb 2013 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/2013/02/12/enson-inoue-and-yamato-damashii/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<!-- raw HTML omitted -->
<p>The other day I randomly listened to an episode of the Joe
Rogan<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> podcast, featuring
<a href="http://vimeo.com/57925973">Chuck Liddell and Enson Inoue</a>.  In truth
I chose it because of Chuck, but he only played a bit-part and I wound
up gripped by the intensity of Enson.</p>
<p>Inoue was a pioneering mixed martial artist, with a reputation in
Japan for exceptional bravery &mdash; so much so, that they gave him the
nickname
<a href="http://en.wikipedia.org/wiki/Yamato-damashii">yamato damashii</a>.</p>
<p>This is a peculiarly Japanese term, and the wikipedia page describes a
lot more connotations than I was aware of during my own time in Japan
(the only time it was applied to me was a joking gee-up when I
hesitated at the top of a hairy ski run!).  It is typically translated
as &ldquo;Japanese Spirit&rdquo;, with strong Samurai and martial overtones, and
it was quite unusual for it to be applied to a foreigner.  Much of the
intensity from the podcast was his description of how he felt obliged
to live up to this honour, and the mental preparation he went through:
literally prepared to die in the ring.</p>
<p>One discussion in particular stood out for me though, as he was
discussing the subtlies in meaning of the term, and his own
interpretation (paraphrased):</p>
<blockquote>
<p>People compare it to bravery, but it&rsquo;s different from that.  A brave
man will feel no fear&hellip; a man with yamato damashii spirit feels
fear, but accepts it and moves forward anyway.  A strong man is one
who doesn&rsquo;t feel pain, but one with yamato damashii feels pain but
persists in what he knows he must do.</p>
</blockquote>
<p>A lot of the discussion in general was around mental attitude and how
that affects your choices and actions.  I think that one will stay
with me for a while.</p>
<p><strong>Update:</strong> Right on cue, Ross Enamait
<a href="http://rosstraining.com/blog/2013/02/12/chael-sonnen-on-confidence-and-doubt/">just published</a>
a post on the same themes of confronting doubts and fears by first
accepting them, using quotes from MMA and boxing (Mike Tyson&rsquo;s
trainer).  Less of Enson&rsquo;s acceptance of death itself, meaning he has
nothing to lose by not stopping in the ring, but the same message I
personally took away!</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Joe is a stand-up comic and former host of Fear Factor,
but more pertinently here he is a long-time martial artist and the
expert commentator on the UFC.  His podcast, broadcasting near-daily
and for several hours at a time, frequently has interesting guests
(but usually not from MMA or the UFC).&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content>
		</item>
		
		<item>
			<title>Org mode as exocortex: Introduction to mobile org</title>
			<link>https://blog.markhepburn.com/2013/02/10/org-mode-as-exocortex-introduction-to-mobile-org/</link>
			<pubDate>Sun, 10 Feb 2013 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/2013/02/10/org-mode-as-exocortex-introduction-to-mobile-org/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<h1 id="introduction">Introduction</h1>
<p>I recently read
<a href="http://pragprog.com/book/ahptl/pragmatic-thinking-and-learning">Pragmatic Thinking and Learning: Refactor your Wetware</a>,
after it had sat on my virtual bookshelf for a while.  I took a lot of
notes of things to try, and generally got a lot out of it
(interestingly,
<a href="http://www.amazon.com/Pragmatic-Thinking-Learning-Refactor-Programmers/dp/1934356050">Amazon commenters</a>
have turned on it a bit).</p>
<p>This post isn&rsquo;t about the book itself though, but one idea in it:
out-sourcing your memory and organisation to something like a wiki or
notebook that you can use as an &ldquo;exocortex&rdquo; (their terminology).</p>
<p>As an Emacs user and finding that org-mode is increasingly taking over
my day-to-day organisation anyway, it seemed the obvious choice.  One
requirement of your exocortex was that it be always accessible, and
fortunately there is a mobile client.  Unfortunately it might not work
the way you immediately expect it to, but this can be rectified.</p>
<h1 id="org-mode">Org-mode</h1>
<p>If you&rsquo;ve used Emacs for any length of time, there&rsquo;s a fair chance
you&rsquo;ve encountered <a href="http://orgmode.org/">org-mode</a>.  Org-mode is a
fantastic piece of software, relatively new in the Emacs scheme of
things, still growing at quite a clip and already with an amazing
breadth of capability.</p>
<p>This can be a problem though: it is <em>massive</em>.  Try any tutorial
(<a href="http://orgmode.org/worg/org-tutorials/">and there are a few</a>) and
there&rsquo;s a fair risk you&rsquo;ll get overwhelmed: hierarchical notes &mdash; ok;
notes can have tags &mdash; fine; what are drawers and why?; tables seem
cool; wait, you mean you can do spreadsheet calculations in them too?;
notes can have dates associated too; you can clock in and out; column
mode; time-tracking;&hellip; on it goes!  Many of them also introduce it in
the context of
<a href="http://en.wikipedia.org/wiki/Getting_Things_Done">GTD</a>, which can be
a further overload if you&rsquo;re not already familiar with it.</p>
<p>So if you have previously been overwhelmed, or you haven&rsquo;t tried it
yet, I would offer two pieces of advice:</p>
<h2 id="1-just-start-using-it">1. Just start using it</h2>
<p>Skim the most basic tutorial you find, then just start using it for
notes; for heavens sake don&rsquo;t try and master everything in one
sitting.  It was originally designed for scientific note taking, and
it does this brilliantly.  Get used to the hierarchy and commands for
manipulating it, then maybe start adding functionality as you need it:
perhaps you go back over notes and start classifying sections by
adding tags, for example.  Its table editing facilities are also quite
intuitive, but just get used to those first if you find yourself
needing a tabular display; don&rsquo;t worry about formulae.</p>
<h2 id="2-trial-and-error">2. Trial and error</h2>
<p>One reason the interface is so intuitive is you don&rsquo;t need to remember
a tonne of commands in order to be productive straight away.  Org
achieves this by over-loading most key combinations, with the result
that you can typically achieve what you want by trying one of them,
undoing if that didn&rsquo;t work, and trying the next most obvious
candidate.</p>
<p>Basically, try: <code>M-&lt;return&gt;</code>, <code>M-&lt;arrow key&gt;</code>, or <code>&lt;shift&gt;-&lt;arrow key&gt;</code>, or even <code>M-&lt;shift&gt;-&lt;arrow key&gt;</code>, and if it doesn&rsquo;t do what you
want: <code>C-/</code> to undo!  <code>C-c C-c</code> is always worth trying too.  Org is
quite context-sensitive, so if you&rsquo;re in a heading you will typically
operate on a heading, or if you&rsquo;re on a date you can manipulate the
date, and so on.</p>
<p>Depending on the exact context, those commands are likely to shuffle
headings around or insert new ones, promote or demote them, add tags,
changes dates, or change the priority.  Again, if something happened
that you didn&rsquo;t expect, don&rsquo;t worry: undo, and move on.</p>
<h1 id="mobile-org">Mobile-org</h1>
<p>Emacs isn&rsquo;t too mobile without some effort, but fortunately there
are org-mode clients for the <a href="http://mobileorg.ncogni.to/">iphone</a> and
for <a href="https://github.com/matburt/mobileorg-android">android</a>.  I have
no experience with the iphone app, but apparently they operate
similarly.</p>
<p>However these do not offer, out of the box, the seamless experience
you might expect: changes made on the phone do not silently propagate
back to your org files.  This is partly because the apps have been
designed to include the agenda functionality (I have alluded to dates
before; the basic idea is you can create your project notes in the
hierarchy that suits, add deadlines and so on, then org-mode will
generate an agenda from this), and partly because you can pick from a
number of different server backends.</p>
<p>There is confusion here too, because a common back-end is
<a href="https://www.dropbox.com/">Dropbox</a> &mdash; but this is not the same as
storing your org-files themselves on dropbox so they can be accessed
from several computers!</p>
<p>So first of all, there are a few things to understand:</p>
<ul>
<li>You (initially; we will fix this) need to explicitly push any
changes you make to the server, and pull any changes from your phone
back again.</li>
<li>This process also involves generating addtional files for the mobile
client.</li>
</ul>
<p>A common request is to have a directory of org files on Dropbox so
they are accessible from multiple computers (say, home and work), and
also to use dropbox as the server for the mobile client.  This is
possible, but it does mean keeping two copies of the files in dropbox
(for Emacs and for mobile-org).  I use a sub-directory of my org
directory to keep the mobile files:</p>
<pre><code>;; My org files:
(setq org-directory (expand-file-name (file-name-as-directory &quot;~/Dropbox/org&quot;)))
;; Files for mobile-org:
(setq org-mobile-directory (expand-file-name &quot;MobileOrg&quot; org-directory))
</code></pre>
<p>Next, you will need to tell org-mode what files it should treat as
mobile.  By default this consists of your agenda files (again, not
covered here), but you can set it to anything.  I do use the agenda
list, plus one file of general notes:</p>
<pre><code>(setq org-mobile-files (cons (expand-file-name &quot;notes.org&quot; org-directory)
                              org-agenda-files))
</code></pre>
<p>Having changed the location of the org directory, you will find you
also need to change one last variable (don&rsquo;t worry about what it does
if you don&rsquo;t mind, it&rsquo;s mostly transparent):</p>
<pre><code>(setq org-mobile-inbox-for-pull (expand-file-name &quot;from-mobile.org&quot; org-directory))
</code></pre>
<p>You are now mostly there; go ahead and set up mobile-org
<a href="https://github.com/matburt/mobileorg-android/wiki/Setup-Dropbox">for dropbox</a>
and read the rest of the
<a href="https://github.com/matburt/mobileorg-android/wiki/Documentation">documentation</a>.</p>
<h2 id="automation">Automation</h2>
<p>As mentioned, if you are used to something like
<a href="http://catch.com/">Catch</a> where changes on the phone get
transparently synced with a server, you might find the mobile-org
operation confusing.  Fortunately, there is some elisp code in
<a href="https://github.com/matburt/mobileorg-android/wiki/FAQ">the FAQ</a> for
mobile-org-android to regularly push and pull (yes, in our case this
does essentially mean copying from one dropbox folder into a
subdirectory, but this is not always the case!).  In case it ever
moves, or just if you&rsquo;re lazy, here are the snippets you need to include;</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>Combine this with a frequent update period in the mobile client, and
you will have a pretty smooth experience!</p>
]]></content>
		</item>
		
		<item>
			<title>Quick git tip</title>
			<link>https://blog.markhepburn.com/2013/01/29/quick-git-tip/</link>
			<pubDate>Tue, 29 Jan 2013 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/2013/01/29/quick-git-tip/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>I recently put the following couple of alias in my <code>~/.gitconfig</code>
file:</p>
<pre><code>[alias]
    dlp = diff ORIG_HEAD..FETCH_HEAD
    llp = log ORIG_HEAD..FETCH_HEAD
</code></pre>
<p>These stand for &ldquo;diff last pull&rdquo; and &ldquo;log last pull&rdquo; respectively.
When dealing with third-party submodules in particular, such as my
<a href="https://github.com/markhepburn/dotemacs">my emacs config</a> where most
extra code is contained in submodules, I&rsquo;ll often just run <code>git pull</code>
to update them.  After that, either out of curiosity or occasionally
afer the fact if I&rsquo;m tracking down some changed behaviour, I want to
know exactly what changed.</p>
<p>So this is what those two aliases accomplish.  When you fetch, git
creates an extra couple of refs referring to the HEAD before and after
the fetch.  You can then just use these to examine the new commits via
diff and log.</p>
<p>I&rsquo;m sure they&rsquo;ve been proposed numerous times in the past, and may
even be built-in for all I know, but they&rsquo;ve been quite useful for me
already so you&rsquo;re welcome to them too!</p>
]]></content>
		</item>
		
		<item>
			<title>On contributing to Emacs</title>
			<link>https://blog.markhepburn.com/2012/11/06/on-contributing-to-emacs/</link>
			<pubDate>Tue, 06 Nov 2012 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/2012/11/06/on-contributing-to-emacs/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<h1 id="tldr">TL;DR</h1>
<p>Writing patch: a couple of hours.  Getting permission from employers
to submit patch: a couple of months.  Contributing to Emacs:
priceless.</p>
<h1 id="introduction">Introduction</h1>
<p>Matlab is not my favourite language.  In fact, it&rsquo;s one I&rsquo;ve largely
managed to ignore, which is remarkably lucky since it is also quite
prevalent where I work.</p>
<p>One day though, I was morosely looking over a&hellip; rather organic mass
of Matlab, and got so depressed I started procrastinating.  I started
watching the latest episode of <a href="http://emacsrocks.com/e09.html">Emacs
Rocks</a>, which was demonstrating a new
minor mode to successively expand a selection around greater semantic
units (for example, just on a page of text it would first select the
word under the cursor, then the sentence, then paragraph, and so on).</p>
<p>This was much more interesting!  I started hacking on it to make it
work with Matlab.  Admirably, it also came with a <a href="http://ecukes.info/">test
suite</a> and a request that all contributions
include tests.  These I finished on the weekend, fixing up a couple of
corner cases they found along the way.</p>
<p>Flushed with a sense of achievement, I pushed to github and submitted
a pull request.</p>
<h1 id="trials-and-tribulations">Trials and Tribulations</h1>
<p>All stories are fundamentally about conflict or struggle in some
sense, and this is where mine started.  The maintainer thanked me, and
more-over informed me that his package had already been accepted into
Emacs itself, and therefore so would my small contribution!  I have
had a long love affair with Emacs and virtually live in it, so I was
ecstatic.</p>
<p>Well, ecstatic, and also rather nervous.  The Free Software Foundation
requires that all contributors must <a href="http://www.gnu.org/licenses/why-assign.html">assign
copyright</a> over to them.
Under local law, I do not in fact own the copyright, my employer does.
Now, I work in a research organisation, and as it is their life-blood
they are understandably twitchy about signing over IP.  Clearly my
patch was not going to leak valuable secrets, but it did put me in the
position of needing someone in a large bureaucracy to accept
responsibility for something that goes against the organisation&rsquo;s
grain, with absolutely no upside for them.</p>
<p>Merely getting to the stage of discovering what level of people might
have the authority took a decent amount of time, and after the first
apologetic rejection I did lose hope and let the trail go cold for a
while.  Eventually though I found someone who agreed, with experience
releasing projects as open source and an &ldquo;ask forgiveness not
permission&rdquo; attitude, to whom I will remain inordinately grateful.
Actually getting the physical signature then took a week or so longer,
but I was finally done.</p>
<h1 id="aftermath">Aftermath</h1>
<p>All was <strong>not</strong> finally done, as it turned out.  I gleefully informed
the (patient, long-suffering) maintainer that all was finally good to
go.  He in turn pulled the patch in, and informed me that my tests
were all failing!  As it turned out, I had written my code against
Emacs version 23 and he was using version 24, and the Matlab mode had
received a major face-lift in between with many breaking changes.  This
was mainly due to me simply using what shipped with Ubuntu, but I did
derive some hollow amusement that it felt like the process had taken
so long my changes were all out of date!  At any rate, I tweaked the
patch to work against both version, and <em>now</em> I&rsquo;m finally in a
package, that at some point in the future will be in Emacs.  In a very
small way.</p>
<h1 id="colophon-emacs-rhapsody">Colophon: Emacs Rhapsody</h1>
<p>Browse any geek news site for long enough and eventually someone will
mention Emacs, and someone else will reply &ldquo;oh yeah, it&rsquo;s a great
operating system, but needs a good text editor, har har&rdquo;.  Very droll.
The joke, in my opinion, is on them though because it <em>is</em> an
operating system!</p>
<p>Some time, read up on the history of the Lisp Machines and <a href="http://www.youtube.com/watch?v=5Xl-EgAe_a0">watch a
movie</a> or two of one in
action.  For various reasons, not all technical, this vision of
computing did not take off and we are poorer for it.  Every aspect of
the system, down to the metal, was not only written in Lisp but could
be examined <strong>and changed</strong> by the user.  Emacs makes sense in light
of this: it&rsquo;s essentially a poor-man&rsquo;s Lisp Machine.</p>
<p>Emacs Lisp is not the nicest Lisp, but hacking on Emacs is fun both
because what you write immediately improves how you work, and because
you have that instant-turn-around where (nearly) every bit of
functionality can be examined and updated, all without restarting.</p>
<p>Finally, if you&rsquo;ve never really looked into Emacs, or only used it
under sufferance as part of a Unix course or something, have a look at
the <a href="http://emacsrocks.com/">Emacs Rocks</a> movies some time.  The guy
is single-handedly doing an amazing publicity job, showing just what
can be accomplished and surprising even veterans.  And if I may say
so, he also makes a very gracious and incredibly patient project
maintainer :)</p>
]]></content>
		</item>
		
		<item>
			<title>New Blog!</title>
			<link>https://blog.markhepburn.com/2012/06/23/new-blog/</link>
			<pubDate>Sat, 23 Jun 2012 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/2012/06/23/new-blog/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>Well, a new life for the old one, anyway.  Ahem.  So, it has been a
while I believe?  Sorry about that!</p>
<p>In the last, err, over a year since last posting I have, at least:</p>
<ul>
<li>Been back to Nepal (trekking around the Annapurna Circuit this time)</li>
<li>Also spent 6 weeks in South America.</li>
</ul>
<p>Unfortunately the weather wasn&rsquo;t great for photos in Nepal this time,
so there&rsquo;s probably only one post there.  I don&rsquo;t have many great
pictures from South America either, but I can probably manage to eke
out a few more posts!</p>
<p>In the mean time though, I migrated this blog.  It spent the first
couple of years of its life on posterous, which was a great platform
at the time but more recently seemed a bit neglected while the team
cast around for ways to keep it alive before accepting a
pity-acquisition from Twitter.  I decided to move it to a new platform
&mdash; the rest of this gets a bit nerdy, sorry!</p>
<h2 id="jekyll-bootstrap-github-pages-and-the-migration-process">Jekyll-bootstrap, github-pages, and the migration process</h2>
<p>I decided to move to a static-site option, giving me a bit more
flexibility as well as control over my data: in other words, all of
the site is generated once per post, then served as simple files
rather than from a database.  I also wanted to be able to keep it in
git, although that&rsquo;s almost a given with most site-generator options.</p>
<p>There&rsquo;s plenty of options for site generation, but one of the most
popular alternatives is <a href="https://github.com/mojombo/jekyll">jekyll</a>.
By itself this only offers a flexible but bare site generation
framework; <a href="http://jekyllbootstrap.com/">jekyll-bootstrap</a> adds a
framework tailored for blogging on top, along with themes based on the
now-ubiquitous
<a href="http://twitter.github.com/bootstrap/">Twitter-bootstrap</a>.  I also
looked pretty hard at <a href="http://octopress.org/">Octopress</a>, again based
on jekyll, but made a slightly-arbitrary decision to go with
jekyll-bootstrap (<a href="http://ringce.com/hyde">Hyde</a> deserves mention too,
including because it&rsquo;s built on technologies I&rsquo;m more familiar with).
I think this decision was at least in part due to the greater
integration with github &mdash; see below &mdash; although in reality this is
almost a non-issue.</p>
<p>For those of you who don&rsquo;t know, github offers a <a href="http://pages.github.com/">static site hosting
service</a>, including custom domain names if
you wish.  All that&rsquo;s needed is a specially-named repository, and they
will serve it as a website for you.  As a bonus, they also have jekyll
integration and can generate your site for you (of course, otherwise
you just generate it yourself before pushing to git-hub, which is what
I ended up doing.  If at any time github becomes less suitable I can
easily host the files myself, or use Amazon S3, or any other
alternative.</p>
<p>Firstly though, I wanted to take all my previous content with me.
This wasn&rsquo;t too challenging, but did involve a couple of fiddly steps
&mdash; read on for the details!</p>
<h3 id="migration-steps">Migration steps</h3>
<ol>
<li>
<p>Download previous posts from Posterous!  Posterous does have an
API, and Jekyll includes a posterous importer.  The problem with this
is I wanted my images as well, and the existing importer didn&rsquo;t handle
that.  I <a href="https://github.com/markhepburn/jekyll/commit/5890740c4bb6e8d9da498a88a342daaf8356ce01">hacked it a
bit</a>
to download the images as well, into a separate directory for each
post and as a stop-gap measure just source them in a HTML list.  (I
submitted a pull request for the importer patch, but haven&rsquo;t heard back.
It&rsquo;s pretty hackish, but you&rsquo;re welcome to it.)</p>
</li>
<li>
<p>This got ugly pretty quickly, so I <a href="https://gist.github.com/2978398">wrote another
hack</a> to upload each image directory
to picasa.</p>
</li>
<li>
<p>Unfortunately, Picasa&rsquo;s &ldquo;embedding&rdquo; functionality seems to be
limited to effectively a link to the album on their site, or a shitty
flash slideshow.  So, I took the <a href="http://www.digitalia.be/software/slimbox2">smallest lightbox
implementation</a> I could
find, and wrapped it with <a href="http://code.lancepollard.com/picasa-jquery-plugin">this
plugin</a> for pulling
the image links from picasa&rsquo;s RSS feed (it saved me writing my own at
this point!), and tied them together with a bit of jquery.  Instant
lightbox, hosted by picasa.</p>
</li>
<li>
<p>Well, not quite.  I wrote a <a href="https://github.com/markhepburn/markhepburn.github.com/blob/master/_plugins/picasa.rb">simple little jekyll
plugin</a>
to wrap some boilerplate HTML around the picasa album-ID, and used an
emacs macro to help replace the old image links with that tag.  Then I
pushed to github, and immediately realised that of course for security
reasons they don&rsquo;t run extra plugins&hellip; so I used sed to swap the tags
for the boilerplate, and moved on (fortunately it wasn&rsquo;t a complicated
plugin).</p>
</li>
<li>
<p>Fixing up backlinks.  In some posts I have referred to earlier
posts, and posterous uses a different link format to jekyll
(/title-slug vs /yyyy/mm/dd/often-a-different-slug).  I was testing
out regular expressions ready to write a script to find all links,
trawl the _posts directory looking for which it was likely to refer to
and update it&hellip; when I realised that there were only 7 such
backlinks.  So I just fixed them up by hand! (Geek-cred lost, but time
gained).</p>
</li>
<li>
<p>Almost there&hellip; I switched to one of the themes provided with
jekyll-bootstrap, originally due to <a href="http://mark.reid.name/">Mark
Reid</a>.  I&rsquo;d like to do my own at some point,
but in the mean time it&rsquo;s nice and clean.  I like it.</p>
</li>
</ol>
<p>And now we&rsquo;re done! In theory this means I can go back to posting more
frequently; in practice it at least means I have less excuses.  I&rsquo;d
like to post more technical content as well, but I make no promises.
If you&rsquo;re interested in what I&rsquo;m reading, I tend to share technical
links on <a href="http://etbwc.com/+">Google+</a> at the moment.</p>
]]></content>
		</item>
		
		<item>
			<title>Mt Anne... almost</title>
			<link>https://blog.markhepburn.com/posts/2011-04-19-mt-anne-almost/</link>
			<pubDate>Tue, 19 Apr 2011 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2011-04-19-mt-anne-almost/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Thark Ridge to Mount Montagu</title>
			<link>https://blog.markhepburn.com/posts/2011-02-14-thark-ridge-to-mount-montagu/</link>
			<pubDate>Mon, 14 Feb 2011 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2011-02-14-thark-ridge-to-mount-montagu/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Wellington Falls via Milles Track</title>
			<link>https://blog.markhepburn.com/posts/2011-01-24-wellington-falls-via-milles-track/</link>
			<pubDate>Mon, 24 Jan 2011 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2011-01-24-wellington-falls-via-milles-track/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>FixMalk: Enable drinkmalk downloads for Aldiko again</title>
			<link>https://blog.markhepburn.com/posts/2011-01-15-fixmalk-enable-drinkmalk-downloads-for-aldiko-again/</link>
			<pubDate>Sat, 15 Jan 2011 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2011-01-15-fixmalk-enable-drinkmalk-downloads-for-aldiko-again/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Nepal: Chitwan National Park</title>
			<link>https://blog.markhepburn.com/posts/2010-12-28-nepal-chitwan-national-park/</link>
			<pubDate>Tue, 28 Dec 2010 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2010-12-28-nepal-chitwan-national-park/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>The traditional trekking holiday in Nepal I believe goes like this: go trekking, do 3 days / 2 nights in Chitwan National Park, go to Pokhara to unwind a bit. We did exactly this, and following the success of hiring a guide for the trek we felt sufficiently trusting in the travel agent to just ask him for a package to Chitwan. This time, I believe, we got rather ripped off! We seemed to be paying quite a lot more than a lot of other people there, and really, it just wasn&rsquo;t that great. <!-- raw HTML omitted --> Chitwan is near the southerly border with India, and at an altitude of only about 200m &ndash; it is quite tropical. The larger park itself sounds amazing, but the tourist packages are a bit, for wont of a better word, canned. Everyone does the same 3 days / 2 nights, and nothing changes, so not surprisingly the guides seem a bit jaded as well. The activities organised sound enticing (jungle safari, etc), but were also a bit underwhelming. On the first evening there was a visit to the elephant conservation centre, which was a bit distressing as they were all displayed on very short chains, many of them obviously upset about it (we were assured that was only for a couple of hours a day). <!-- raw HTML omitted --> All in all, I suppose if the park is using tourist visits to maintain conservation work then I&rsquo;m OK with that, but we more or less tuned out and lounged around reading for the most part. The highlight of the walking safari was probably the baby crocodile sunning itself on a rhino! (I should say that it wasn&rsquo;t all bad; while I&rsquo;m not sure I could live in the tropics, they&rsquo;re a fascinating place to poke around. Everything grows so quickly that there&rsquo;s life, usually freaky-looking, in every nook and cranny and under every leaf).</p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Nepal: Monkey Temple in Kathmandu</title>
			<link>https://blog.markhepburn.com/posts/2010-12-28-nepal-monkey-temple-in-kathmandu/</link>
			<pubDate>Tue, 28 Dec 2010 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2010-12-28-nepal-monkey-temple-in-kathmandu/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>Final Nepal post, I promise! The last real excursion we did on our remaining couple of days in Kathmandu was to the monkey temple. Even finding it was actually a bit problematic, because we&rsquo;d only really heard about it and it&rsquo;s not named as such on any map we had! As it turns out, it was on that big hill about twenty minutes walk away (which does actually locate it a fair bit, as Kathmandu is actually quite flat!). <!-- raw HTML omitted --> The concept is quite simple: as the name implies, it&rsquo;s a temple, and for whatever reason it is now teeming with monkeys. Teeming almost doesn&rsquo;t do justice to the place; it swarms with unkempt life of all sorts, co-existing in a half-chilled-out, half-suspicious state with each other. The monkeys easily dominate in numbers, but there were also quite a few feral dogs (including several bitches feeding pups just sprawled out in the middle of an open area), pigeons, and of course a mass of visitors. <!-- raw HTML omitted --> We had heard rumours that the monkeys could be quite aggressive, steal cameras and food, etc, but in general they just seemed to go about their business ignoring everyone else around them, even when a fight periodically broke out and other monkeys rush over screeching from everywhere and mothers climb to safety while their babies frantically regain their grip from the momentum change. <!-- raw HTML omitted --> The views from the top aren&rsquo;t too bad, or wouldn&rsquo;t be if not for the haze.</p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Nepal: Pokhara</title>
			<link>https://blog.markhepburn.com/posts/2010-12-28-nepal-pokhara/</link>
			<pubDate>Tue, 28 Dec 2010 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2010-12-28-nepal-pokhara/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>Pokhara as I&rsquo;ve mentioned has two purposes on the typical traveller&rsquo;s itinerary: it is the gateway town to the Annapurna region (as well as trekking, there were plenty of ads for white-water rafting and paragliding, and I believe the world&rsquo;s highest bungy jump is nearby too), and it is where you go to unwind after trekking. <!-- raw HTML omitted --> Accordingly we spent a few days there, and it most certainly is a lot more chilled out after the chaos of Kathmandu! It is also fully prepared for its reputation as the post-trek destination; it felt like every second shop on the main tourist strip was a barber trying to draw in the hairy foreigner. <!-- raw HTML omitted --> The Northern skyline of Pokhara is beautiful, with several of the Annapurna mountains visible (three peaks over 8000m are visible; Dhaulagiri and Manaslu in addition to Annapurna I), but really dominated by Machapuchare, the &ldquo;fishtail&rdquo; mountain, and one of the few in the Himalaya that is illegal to climb (there are a few others with spiritual significance whose climbing is expressly not encouraged). We got two improved views of the range; by rowing a boat across the lake there&rsquo;s a walk up to the &ldquo;World Peace Pagoda&rdquo; where we saw the sunset (then had to row back in the dark!), and even closer to the range on the other side of town you can climb Sarankot hill and watch the sunrise. <!-- raw HTML omitted --> There were a few sites on offer, but really the only other time we ventured out much was to the International Mountaineering Museum. This is not, it has to be said, the most professionally-presented museum (exhibits included printed power-point slides and screenshots from Google Earth!), but it does include a lot of information on the various mountain peoples in Nepal and of course on mountaineering exploits. In addition, it had some massive and stunning aerial mountain photographs by a Japanese guy called Koichiro Ohmori; his book &ldquo;Over The Himalaya&rdquo; I have just managed to track down second-hand. Highly recommended if, you know, you like pictures of mountains. <!-- raw HTML omitted --> (Note: the error message on the ATM was actually incredibly common, it&rsquo;s just coincidence that I grabbed a photo this time. It really could have been just about any I visited in Kathmandu or Pokhara. Variants included endless reboot cycles, generic application errors, and of course a blue screen).</p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Nepal Trekking Days 1-3: Kathmandu to Namche Bazaar</title>
			<link>https://blog.markhepburn.com/posts/2010-12-27-nepal-trekking-days-1-3-kathmandu-to-namche-bazaar/</link>
			<pubDate>Mon, 27 Dec 2010 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2010-12-27-nepal-trekking-days-1-3-kathmandu-to-namche-bazaar/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>To start with, this trek was anything but the epitome of organisation! Right up until leaving the three of us were tossing up between going to the Annapurna or the Everest regions, and really only decided on the plane to head in the Everest direction. We also decided to attempt the three-passes trek, which essentially skirts along the sides of famous Everest base-camp trek, avoiding most of the crowds and adding a bit more climbing effort. <!-- raw HTML omitted --> We were also undecided as to whether we&rsquo;d hire a guide or porter; in the end we spoke to the travel agent attached to our hotel in Kathmandu about flights to Lukla and they also &ldquo;just gave us some information on packages&rdquo;. Eventually we made a snap decision to go with their recommendation of a guide and two porters. This turned out to be one of the best decisions we could have made; I think everyone had their doubts in some form, but we couldn&rsquo;t have asked for a better guide (email me if you are going and would like his details). <!-- raw HTML omitted --> So, a couple of days later we flew to Lukla to start the trek (you can take a bus to Jiri then walk in, but this adds about six days to the start). The flight, and particularly the landing, is just as spectacular and tense as you may have heard! Flying out of Kathmandu in a tiny plane the scenery below gets more and more mountainous, with little villages clinging to the sides and fields terraced on, until eventually as you start to approach Lukla you are actually flying below the peaks and not, it seems, too far from the sides either. The actual landing strip is on a twelve degree incline at the edge of a precipice, with a small landing area at the top&hellip; terminated with a wall if the pilot doesn&rsquo;t brake in time! The chatter in the plane is quite entertaining too: the talk starts off with forced frivolity, getting more and more tense during the approach, before people either hold their breathes or scream during the landing, before everyone breaks into applause. Watch for yourself: <!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --> After surviving we met our two porters (our guide flew with us) who promptly loaded most of our baggage and took off ahead, had lunch and walked to the first stop at (the ammusing-named for everyone) Phakding. This is actually a decrease in altitude, from about 2800m in Lukla to 2600m, which needless to say was not a portent of things to come. Phakding was really nice; small, quiet, and pretty, surrouned by green with white-capped mountains visible. Being our first night on the trail we weren&rsquo;t quite sure what to expect, so I think everyone found the accomodation quite luxurious! (read: a room for the three of us, and beds off the floor). We also discovered that we were now down to just one porter, with the remaining one (Shyam) having taken a double rate to carry everything. <!-- raw HTML omitted --> In the morning we were woken with the soft bells as cattle hit the trail early. The next day is the real start of the trek, on the way to Namche Bazaar. The route follows a river for a while, before crossing a large suspension bridge and immediately doing the first sustained climb. People were already suffering on this, but we found that thanks to the relaxed pace set by our guide we never needed to rest and actually passed everyone. Up the top, if you peer through the trees, you can get your first glimpse of Everest. <!-- raw HTML omitted --> Namche Bazaar is quite a buzzing town. It&rsquo;s the starting point for nearly all the treks in the Everest region, and of course the finishing point so there are plenty of pubs, bakeries, and gear shops to stock up or try and offload on your way home. It has a kind of horse-shoe shape, and is right on the edge of a sheer valley with a huge wall rising opposite. We had our first rest/acclimatisation day here: &ldquo;rest&rdquo; of course means a five-hour trek and several hundred metres of climbing, very much feeling the effects of altitude by this point! The weather was quite overcast for the most part, but we did see the world&rsquo;s second highest air-strip (little more than a bit of gravel), and actually witnessed a plane land and take off, dropping off the Indian ambassador. The first stop was a luxury hotel, the Everest View, popular with Japanese tourists who get helicopter-ed in, met with oxygen to escort them to their rooms, before flying out again the next day. It does, as you might guess, have views of Everest and we had tea there, although said views were mostly clouded over. After this we visited two very picturesque Sherpa villages, Khumjung and Khunde. <!-- raw HTML omitted --> The next morning was brilliantly clear, so we rushed up to the lookout above the town to grab some photos before breakfast and hitting the road again.</p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Nepal Trekking Days 10-11: Cho-La, Lobuche, Gorak Shep, Everest Base Camp</title>
			<link>https://blog.markhepburn.com/posts/2010-12-27-nepal-trekking-days-10-11-cho-la-lobuche-gorak-shep-everest-base-camp/</link>
			<pubDate>Mon, 27 Dec 2010 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2010-12-27-nepal-trekking-days-10-11-cho-la-lobuche-gorak-shep-everest-base-camp/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>The climb over Cho-La felt a lot less strenuous than Renjo-La, although it eventually peaks at a slightly higher altitude (5420m). The others were now feeling much better, and the total climb was probably about half that required for Renjo-La! The view from the top was no less spectacular, although perhaps a little less expansive, and looks directly over a glacier on the far side. The descent down the glacier was very sunny and warm, before a bit of a rock scramble revealed a massive valley through which we walked to Tzongla, and provided quite an impressive lunch spot (first panorama). <!-- raw HTML omitted --> The original plan was to stay in Tzongla, but since it was full we pushed on for a few more hours to Lobuche. Lobuche is the penultimate stop before Gorak Shep, the launching pad for the base-camp and Kalla Patthar trips, and on the main trek route which meant a lot more people. Gorak Shep itself is just a couple of hours from Lobuche the next day, and after lunch there we walked to the famous base camp. <!-- raw HTML omitted --> To be honest, this is more of a &ldquo;tick the box&rdquo; destination than somewhere you go for the view: it is honestly not that scenic, and despite what you might think from the name, Everest is not even visible! That said, the glacier on which it is situated is fairly spectacular, seeming to consist of a mass of knife-like peaks. The Khumbu ice-fall behind is even more ominous, and incredibly is the start of the easiest route up Everest! (Although the ice-fall itself is the most dangerous part of that route) Mid-October when we arrived is actually the very tail end of the climbing season; someone was apparently summitting just as we were there, but there were only two groups left from the tent-city that normally occupies it during the height of the season. Most other visitors didn&rsquo;t venture right to the end, so it was fairly quiet at least. <!-- raw HTML omitted --> Included in the photos is the latrine tent, and in the final picture you can possibly make out a flat rock balancing on a sheer ice edge, over which you have to hop on the way along the glacier to the base camp! Now, stop for a moment and consider that some porter is going to be tasked with removing the contents of the latrine from the glacier, and will also be making that hop &ndash; albeit while carrying 60kg of poo! <!-- raw HTML omitted --> The weather was starting to turn at this stage, and was beginning to hail during the return journey.</p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Nepal Trekking Days 12-14: Kala Patthar, Lobuche, Dengboche, Chhukhung</title>
			<link>https://blog.markhepburn.com/posts/2010-12-27-nepal-trekking-days-12-14-kala-patthar-lobuche-dengboche-chhukhung/</link>
			<pubDate>Mon, 27 Dec 2010 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2010-12-27-nepal-trekking-days-12-14-kala-patthar-lobuche-dengboche-chhukhung/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>Day 12 was a long one: we started with a pre-breakfast trip up Kala Patthar, which as mentioned I don&rsquo;t believe is actually as nice as the view from Gokyo-Ri. That&rsquo;s not to say that it isn&rsquo;t stunning, of course! It was probably however the one time the weather really didn&rsquo;t cooperate for a major view point, and was quite over-cast (again, fortunately we didn&rsquo;t bother attempting the sunrise view, of which there was none). There was a periodic gap in the clouds however, so all was not completely lost. <!-- raw HTML omitted --> Also, you may have heard by now, there is actually a 3G tower up the top. <!-- raw HTML omitted --> After breakfast we actually made a second trip to base camp, because Susan had taken sick and had to turn back the day before, but really wanted to go. So, we made a quick return trip (no photos from the second time around!), had a hurried lunch back in Gorak Shep, and headed back down to Lobuche. The weather all this time was getting progressively worse, and from base camp onwards we were walking through worsening snow. <!-- raw HTML omitted --> Unfortunately, this ultimately had the effect of changing our plans. From Lobuche we were supposed to cross the third pass in the three-passes trek, Kongma-La, but when we woke up to a heavy blanket of snow we realised that was going to be off. Kongma-La is apparently the only &ldquo;pure tourist&rdquo; pass, by which I mean it has amazing views but is not actually otherwise used as a transport route; the porters on this section go around the base. It is also more of a rock scramble than a track, which would have been fun but when combined with the prospect of snow and ice probably also a lot more dangerous. <!-- raw HTML omitted --> So, instead we headed to Chhukhung the long way around; just outside Lobuche we walked through a field of monuments to people who had lost their lives on Everest&hellip; make sure you read the placard for Babu Chiri Sherpa! (He no longer holds the record for the fastest ascent though, which is now a ridiculous eight hours and ten minutes). Rather than push all the way to Chhukhung, we ended up having lunch at Dengboche and staying there for an extra rest (Susan was still recovering), and instead a few of us headed up into the hills behind for a beer in the clouds! The walk the next day through to Chhukhung was surprisingly fast, just over an hour, and in very pleasant weather. After an early lunch, we set off for the Island Peak base camp. Island Peak is a &ldquo;trekking peak&rdquo;; at 6189m it is no easy feat (and many still have to turn back due to the altitude), but is none-the-less accessible without having to be a trained mountaineer, although crampons are needed. The base-camp of course is just a collection of tents, so we headed up to the ridge off to the side to explore, where we unexpectedly ended up with a magnificent view all to ourselves! Directly on the other side, the ridge falls vertically down to a glacial lake with a dramatic mountain face on the other side. We spent probably an hour there, basking in the sun and view, and listening to the constant roar as the ice cracked in the sun and rocks broke loose to tumble down in to the lake, frequently causing mini avalanches.</p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Nepal Trekking Days 15-16: Chhukhung-Ri and Pangboche</title>
			<link>https://blog.markhepburn.com/posts/2010-12-27-nepal-trekking-days-15-16-chhukhung-ri-and-pangboche/</link>
			<pubDate>Mon, 27 Dec 2010 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2010-12-27-nepal-trekking-days-15-16-chhukhung-ri-and-pangboche/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>Day 15 turned out to be my favourite day of the entire trek, I think. We started early in the morning with a crystal clear day, and did a day-trip up Chhukhung-Ri, which at 5545m was also the highest point I reached. The views from the top are literally (more on that in a second!) breath-taking. We shared them with a lone Spanish trekker and a Slovenian couple, one of whom had climbed Lhotse twenty years ago! The panorama from the top is a full 360 degrees (I accidentally included half of Shyam&rsquo;s head too, I&rsquo;m sorry!): the massive feature on the left is the North face of Nuptse (hiding Everest), while over one the right Ama Dablam (6812m) is quite prominent, although not quite as prominent as in the first panorama, which was taken from outside our lodge! In the middle you can also just make out the lake next to the Island Peak base camp from the day before. <!-- raw HTML omitted --> The ascent was slightly curious; it was a lot of fun as it turned into a semi-exposed rock-scramble over slate under nice sun, but for some reason Paul and I simultaneously hit a wall. We didn&rsquo;t feel any other effects, but literally needed to stop to catch our breath every twenty steps or so! Whether we had simply gone a bit fast to that point, or if we had just hit the point of our current acclimatisation (it wasn&rsquo;t that much higher than Kala Patthar where we didn&rsquo;t have any trouble), who knows. It was certainly worth-while how-ever. <!-- raw HTML omitted --> The next morning we were again greeted with perfect trekking weather, as we commenced our descent towards Panboche. The plume of cloud from the summit of Ama Dablam was present every morning, so I assume there must be a jet-stream at that altitude. We quickly made it down below the tree-line for the first time in about ten days. <!-- raw HTML omitted --> Pangboche itself turns out to be in two parts. We stayed in the lower part with all the lodges which is pleasantly situated, however after a break we went for a five-minute walk into the obscured upper-Pangboche. This is quite a traditional village still, and was very pretty. (Including the dung disks you can see drying on a wall! These are used for both fuel and fertiliser; every lodge has a communal dining hall, with a dung-fueled heater in the centre. Presumably, these stoves are also carried in by porters&hellip;).</p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Nepal Trekking Days 17-18: Pangboche to Lukla</title>
			<link>https://blog.markhepburn.com/posts/2010-12-27-nepal-trekking-days-17-18-pangboche-to-lukla/</link>
			<pubDate>Mon, 27 Dec 2010 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2010-12-27-nepal-trekking-days-17-18-pangboche-to-lukla/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>Our descent was largely uneventful. Leaving Pangboche, we passed through Tengboche, site of the largest monastery in the region (and yes, that&rsquo;s yet another rescue helicopter over Tengboche!). The weather actually clouded over quite heavily by the time we arrived in Namche Bazaar, which made for some dramatic scenery along the way. <!-- raw HTML omitted --> Back in Namche we engaged in the traditional bakery crawl&hellip; I don&rsquo;t quite know why, but apple pie is a bit of a tradition! The plan was to spend another two days on a leisurely walk out, but there had been more flight delays due to weather so we decided we had better return in a single day in case we needed to wait. Judging by the crowds on the trail, everyone else had the same idea! To make matters more interesting, we were just missing the weekly market at Namche so there was a steady stream of porters coming in the other direction carrying all manner of goods, including animal carcasses in the hot sun. This is why I was vegetarian for the month. <!-- raw HTML omitted --> Last but not least&hellip; the celebration with the Shyams! (porter and guide, if you&rsquo;ve lost track). We had tried a few different local alcohols on the descent, but this was probably the nicest: it&rsquo;s called &ldquo;tongba&rdquo;, which is actually the name of the vessel I believe. They are filled with fermented millet, which is then drowned with hot water from a thermos before being left to stand for five minutes. Then you drink it through a straw (pinched off at the other end with a small hole, to act as a filter), before refilling with water and waiting again. The waiting is no doubt good for pacing and for conversation, although that doesn&rsquo;t really help when there is little common language (which there wasn&rsquo;t with Shyam the porter), but it was fun anyway. In the group shot, porter Shyam is giving the thumbs up (yes, that man carried his own bodyweight in our luggage, and did it quicker than we could walk relatively unencumbered), and our guide Shyam is on the right. <!-- raw HTML omitted --> The next morning, we miraculously managed to fly out more or less on schedule, and thus ended my dream holiday. (Thank you for joining me &ndash; there will be a couple of remaining posts on how we filled in the rest of the time after the mountains!)</p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Nepal Trekking Days 4-7: Thame, sickness, Lumde, Renjo-La</title>
			<link>https://blog.markhepburn.com/posts/2010-12-27-nepal-trekking-days-4-7-thame-sickness-lumde-renjo-la/</link>
			<pubDate>Mon, 27 Dec 2010 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2010-12-27-nepal-trekking-days-4-7-thame-sickness-lumde-renjo-la/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>The walk from Namche to Thame was short, but beautifully sunny and spectacular (including watching a rescue helicopter come and go as we were leaving, a site we would see a lot more of over the next few weeks!). The trees were starting to thin out, and Thame when we arrived (at about 3800m) felt much more off-the-main-path than the bustle of Namche Bazaar. We arrived before lunch, and after an hour spent soaking up the sun and surrounds went for another acclimatisation walk into the hills above to visit the monastery, the oldest in the region. <!-- raw HTML omitted --> That evening, unfortunately, wasn&rsquo;t quite so pleasant! I had up until that point been eating like a man possessed, but at dinner I suddenly lost all appetite. Heeding our guide&rsquo;s advice that you needed to eat in the mountains even when you don&rsquo;t feel hungry, I forced it down anyway&hellip; and soon after started vomiting, hard. After about six hours of this it turned into pure liquid diorrhoea, before the drugs kicked in. I suspect all of this was a mix of altitude symptoms and a bug; I hadn&rsquo;t experienced any symptoms up until then, but loss of appetite and vomiting are definitely signs of altitude sickness, while diorrhoea isn&rsquo;t. At any rate, I took the &ldquo;diorrhoea bomb&rdquo; drug cocktail, then started taking altitude medication just in case. Either way, I didn&rsquo;t have a single issue for the remainder of the trip, for which I am exceedingly grateful! Unfortunately, the other two members of our party both got sick with similar symptoms (if in reverse) in the next 24 hours. We had another acclimatisation day in Thame. <!-- raw HTML omitted --> Finally leaving there, the walk out wasn&rsquo;t too strenuous but took us over 4000m for the first time, to Lumde. This town is literally just three lodges, and exists solely to cater to tourists. We spent a cramped night with the three of us in a single bed that took up the entirety of a room (bar about half a metre of space at the end for our bags) which would have been small for two people! To make matters even more interesting, this was with the other two now suffering from vomiting and diorrhoea. <!-- raw HTML omitted --> The following day was the first of the three passes, Renjo-La (&ldquo;La&rdquo; means &ldquo;pass&rdquo;). This would be quite a tough climb under any circumstances, as it climbs from 4350m to the height of the pass at 5345m, but for the other two still very much suffering it was a brutal experience. For me personally, I was fully recovered and excited to be going over 5000m for the first time (and on my birthday too!), which lessened the pain quite a bit (that may also have been due to the frequent rest stops we needed to make). Either way the view from the top is just amazing, looking down to Gokyo and the lakes, with Everest and Lhotse behind (albeit, hidden by cloud again) and made everything worth-while.</p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Nepal Trekking Days 8-9: Gokyo and Dragnag</title>
			<link>https://blog.markhepburn.com/posts/2010-12-27-nepal-trekking-days-8-9-gokyo-and-dragnag/</link>
			<pubDate>Mon, 27 Dec 2010 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2010-12-27-nepal-trekking-days-8-9-gokyo-and-dragnag/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>A popular variant on the Everest base-camp trek, for those looking for just a little more adventure and scenery, is to detour via Gokyo then rejoin the main route by crossing over Cho-La. It is certainly worth doing; Gokyo is beautifully situated in its own right, with excellent day-walks to the other lakes in the district, and a world-beating panoramic view from the top of Gokyo-Ri (the mountain adjacent to Gokyo village). For this reason though it was a bit more crowded than we were used to from the last couple of days, and after arriving slightly later than planned we ended up in the porters&rsquo; accommodation on the first night. <!-- raw HTML omitted --> The rest day scheduled for Gokyo turned out to host the first truly breath-taking view (I appreciate this is all relative), one of my top three spots from the trek. We went on a walk, just of a few hours, up to the &ldquo;fifth lake&rdquo; (there are six in the Gokyo district, and Gokyo village is located on the third). What made it all the more special is it turned out to be the only spot that we truly had to ourselves; remarkably almost no-one else knew about this particular lookout! Score one for hiring a guide. We asked him how he came to find out about it; apparently fourteen years previously when he&rsquo;d been working as a porter (there is a strict progressing in the trekking industry, with all guides required to start as porters and work their way up) he had come there on a trek, and instantly knew he would take people there when he was a guide himself! <!-- raw HTML omitted --> The spot itself overlooks a glacier, with a panorama of some of the world&rsquo;s largest mountains behind and around it, and for some reason they appear to be much closer than any other spot I can recall. Everest is on the right in the panoramas below, just behind Nuptse. Also visible are Lohtse (8516m), Cho Oyu (8201m), and Makalu (8485m). <!-- raw HTML omitted --> It was also a great example of just how lucky we got with the weather. October is the peak season for trekking because you are most likely to get clear weather, but it was actually quite overcast for much of our trip (which also played havoc with the flights in and out of Lukla, manifesting itself as bursts of other trekkers as they cleared the backlogs). We saw quite a few &ldquo;scenic&rdquo; flights heading towards Everest with everything shrouded in clouds! For the most part though, every time there was a major view point it seemed to clear for us, and this short hike was no exception: it was quite dreary as we set out, and only started to clear about half an hour before we reached the lookout&hellip; when it was almost perfectly clear and sunny! It was clouding over again as we headed home from memory. <!-- raw HTML omitted --> The next morning we climbed Gokyo-Ri, for one of the world&rsquo;s definitive mountain views (for my mind it beats the view from the more famous Kala Patthar). Again the weather was perfect; we had wisely gone up about breakfast time, where-as the poor folk* who had got up before dawn to see the sunrise apparently had a spectacular view of clouds. <!-- raw HTML omitted --> *I say &ldquo;poor folk&rdquo; quite charitably, since that group includes the loud American banging on the doors of all his compatriots saying &ldquo;It&rsquo;s 3am, time to get up!&rdquo;, apparently forgetting that the walls are thin plywood and that other people were staying. But I digress. <!-- raw HTML omitted --> In the afternoon we left for Dragnag, which is a short couple of hours walk over a glacier and lies right at the base of the next pass: Cho-La.</p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Nepal Photos</title>
			<link>https://blog.markhepburn.com/posts/2010-12-25-nepal-photos/</link>
			<pubDate>Sat, 25 Dec 2010 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2010-12-25-nepal-photos/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>&hellip;.are coming soon, I promise! I&rsquo;ve just been doing the initial <!-- raw HTML omitted -->cull, so I can start posting shortly (I think I&rsquo;ll batch them, grouped <!-- raw HTML omitted -->by day or by trek segment). <!-- raw HTML omitted --> In the mean time, while you&rsquo;re eagerly waiting may I suggest you check <!-- raw HTML omitted -->out other people&rsquo;s photos, from the same trip: <!-- raw HTML omitted --> <!-- raw HTML omitted --><a href="http://paulmcc.posterous.com/nepal">http://paulmcc.posterous.com/nepal</a><!-- raw HTML omitted --> (or, &ldquo;Around the Himalaya in 15 <!-- raw HTML omitted -->photos&rdquo;). Paul was one of my travel companions. <!-- raw HTML omitted --> <!-- raw HTML omitted --><a href="http://picasaweb.google.com/100595625918224912002/NepalHike2010#">http://picasaweb.google.com/100595625918224912002/NepalHike2010#</a><!-- raw HTML omitted --> Matt <!-- raw HTML omitted -->both had a much better camera, and is a vastly better photographer <!-- raw HTML omitted -->than me, so really you don&rsquo;t need to check back here after looking at <!-- raw HTML omitted -->his (also, his trek was slightly more extensive). Matt was doing <!-- raw HTML omitted -->essentially the same itinerary as us so we kept bumping into him, and <!-- raw HTML omitted -->he ended up joining us for a few days when his other trek buddies had <!-- raw HTML omitted -->to leave. I&rsquo;m actually in a couple of those shots, for those who <!-- raw HTML omitted -->don&rsquo;t believe I was really there!</p>
]]></content>
		</item>
		
		<item>
			<title>Nepal Book List</title>
			<link>https://blog.markhepburn.com/posts/2010-11-22-nepal-book-list/</link>
			<pubDate>Mon, 22 Nov 2010 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2010-11-22-nepal-book-list/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>I used to be a voracious reader as a child.  These days, while I still try and read a fair bit, it does tend to be mostly technical in nature (I categorically deny that this makes me sad), and even that of late has been neglected while I try and cram in everything else I want to do.<!-- raw HTML omitted --> There is a lot of free time on the trail: most days you start pretty early and are usually at the destination for an early lunch, or around 2 or 3 at the latest.  Dinner is about 6:30, often by head-torch (most electricity is solar past a certain altitude), and you're in bed by about 8:30.  By way of comparison, at home I tend to aim for dinner about 8:30, end up actually eating any time between 9 and 10, and rarely get to bed much before midnight (unfortunately, my rising time isn't that different &ndash; some may say I should sleep more).<!-- raw HTML omitted --> At any rate, I had a lot of free time in Nepal, and resolved to spend it reading: the main target was <!-- raw HTML omitted -->&quot;Godel, Escher, Bach&quot;<!-- raw HTML omitted -->, which I started some time ago but eventually abandoned.  This was mostly because I didn't start reading until I got to bed &ndash; see above for what time this is &ndash; then read for a few minutes, wake up and peel the book or paper off my face, and turn the light out.  This is a book which requires some serious concentration, and that strategy was never going to work.<!-- raw HTML omitted --> So, for anyone who is curious, here is what I got through in that month (in order):<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->Godel, Escher, Bach: An Eternal Golden Braid<!-- raw HTML omitted --><!-- raw HTML omitted -->.  Symbolically, I triumphantly finished this in Chhukhung, the peak of our trip before we started descending.  Unfortunately I now probably need to read it again; in part to revisit a few of the earlier themes with a bit more context, but also because I want to listen to all of the music that is referenced, and I wasn't noting it down.  If anyone has a playlist I would love a copy!<!-- raw HTML omitted --> <!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->High Adventure: The True Story of the First Ascent of Everest<!-- raw HTML omitted --><!-- raw HTML omitted -->, by Edmund Hillary.  More boy's-own-adventure than high literature, but still a gripping read; some of the additional details like having to cajole porters into fording the rivers as they had to carry supplies up from India were worth it alone.  It was written just a year after the actual ascent: Paul (one of our group) had found a very old second-hand copy to bring along, so I borrowed it and read it in two nights.<!-- raw HTML omitted --> <!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->Shantaram<!-- raw HTML omitted --><!-- raw HTML omitted -->.  This book was <!-- raw HTML omitted -->everywhere<!-- raw HTML omitted -->; every single bookshop had a shelf of copies both new and second-hand, and nearly every person we met was either reading it or had read it&hellip; including another member of our group, and I bought my own copy after reading the first few pages.  The actual story gets a little fantastical towards the end, but it's amazingly colourful and yes, I want to go to India now (even more).<!-- raw HTML omitted --> <!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->Leaving Microsoft to Change the World<!-- raw HTML omitted --><!-- raw HTML omitted -->.  The story of a senior MS sales executive with a penchant for adventure tourism; a chance visit to a Himalayan school whose library contained just two books that were too precious to actually be read (one was a Mills and Boon!) leads him to promise to return with books.  This in turn snowballs as he solicits donations, tries to stock other libraries as well, enlists the help of the local Lions club, leaves his job to go full-time on what would eventually be called <!-- raw HTML omitted -->Room To Read<!-- raw HTML omitted -->, expands into other countries and so on.  An easy read (it took me about a day), but quite inspirational none the less and his enthusiasm is infectious.<!-- raw HTML omitted --> <!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->Sun Tzu (The Art of War)<!-- raw HTML omitted --><!-- raw HTML omitted -->.  I bought a cheap copy back in Kathmandu, figuring it was about time I actually read it.<!-- raw HTML omitted --><!-- raw HTML omitted --> <!-- raw HTML omitted --><!-- raw HTML omitted -->On the Road<!-- raw HTML omitted --><!-- raw HTML omitted --> (Kerouac).  Ditto.  A deserved classic: that book has rhythm.<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->The Curious Incident of the Dog in the Nighttime<!-- raw HTML omitted --><!-- raw HTML omitted -->.  I bought this in Hong Kong; it's an amazing book!  Written as a first-person account of a murder &ndash; of a dog &ndash; investigation by an autistic boy.  The author has worked with autistic kids so I'd imagine that it is a fairly accurate portrayal.<!-- raw HTML omitted --> <!-- raw HTML omitted -->Bonus: <!-- raw HTML omitted -->For the Win<!-- raw HTML omitted -->, by Cory Doctorow.  This one doesn't really count since I started reading it (on my phone, thanks <!-- raw HTML omitted -->Aldiko<!-- raw HTML omitted -->) on and off for some time, but I did finish off the last few chapters the day I returned home.  It's a fun read, albeit with a slightly abrupt finish, about the virtual economies spun out of online games and the exploitation and unionisation of the &quot;gold farmers&quot; in developing nations.  Like a lot of what is sometimes still called science fiction these days (hello William Gibson), the present has become sufficiently interesting that they no longer need to dream up much of a future to explore.<!-- raw HTML omitted --> <!-- raw HTML omitted --><!-- raw HTML omitted -->I think that's it; I have a nagging feeling that I've left one out&hellip;<!-- raw HTML omitted --></p>
]]></content>
		</item>
		
		<item>
			<title>Observations from the Himalaya, part 2: Bonus Observation</title>
			<link>https://blog.markhepburn.com/posts/2010-11-20-observations-from-the-himalaya-part-2-bonus-observation/</link>
			<pubDate>Sat, 20 Nov 2010 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2010-11-20-observations-from-the-himalaya-part-2-bonus-observation/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Random Observations from the Nepal Himalaya</title>
			<link>https://blog.markhepburn.com/posts/2010-11-19-random-observations-from-the-nepal-himalaya/</link>
			<pubDate>Fri, 19 Nov 2010 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2010-11-19-random-observations-from-the-nepal-himalaya/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Slides from the Lunar Image Recover Presentation</title>
			<link>https://blog.markhepburn.com/posts/2010-09-29-slides-from-the-lunar-image-recover-presentation/</link>
			<pubDate>Wed, 29 Sep 2010 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2010-09-29-slides-from-the-lunar-image-recover-presentation/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>A bit over a year ago I <!-- raw HTML omitted -->attended a lunch time talk<!-- raw HTML omitted --> at WWDC'09, on recovering the &quot;lost&quot; images from the Lunar Orbiter of the 60s before it was too late.<!-- raw HTML omitted --> At the time it blew my mind, and it still does.  By a happy coincidence I've just found the slides from that presentation online:<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --></p>
]]></content>
		</item>
		
		<item>
			<title>Vancouver: Blue Whale</title>
			<link>https://blog.markhepburn.com/posts/2010-09-20-vancouver-blue-whale/</link>
			<pubDate>Mon, 20 Sep 2010 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2010-09-20-vancouver-blue-whale/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Vancouver: Capilano Pacific Trail</title>
			<link>https://blog.markhepburn.com/posts/2010-09-20-vancouver-capilano-pacific-trail/</link>
			<pubDate>Mon, 20 Sep 2010 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2010-09-20-vancouver-capilano-pacific-trail/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Vancouver: Chinatown</title>
			<link>https://blog.markhepburn.com/posts/2010-09-20-vancouver-chinatown/</link>
			<pubDate>Mon, 20 Sep 2010 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2010-09-20-vancouver-chinatown/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Vancouver: Commercial Drive</title>
			<link>https://blog.markhepburn.com/posts/2010-09-20-vancouver-commercial-drive/</link>
			<pubDate>Mon, 20 Sep 2010 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2010-09-20-vancouver-commercial-drive/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>Commercial Drive, a stretch of road up the east end of Broadway (and adjacent blocks) is apparently a bit of an icon and alternative culture type scene, but somehow I&rsquo;d never been there before. I almost missed out this trip as well, and although I left it a bit late and only had time for a quick visit I&rsquo;m glad I did. <!-- raw HTML omitted --> Not much in the way of photos, but lots of cool graffiti, cafes, alternative shops, etc.</p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Vancouver: Day 1</title>
			<link>https://blog.markhepburn.com/posts/2010-09-20-vancouver-day-1/</link>
			<pubDate>Mon, 20 Sep 2010 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2010-09-20-vancouver-day-1/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Vancouver: Gastown</title>
			<link>https://blog.markhepburn.com/posts/2010-09-20-vancouver-gastown/</link>
			<pubDate>Mon, 20 Sep 2010 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2010-09-20-vancouver-gastown/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Vancouver: Stanley Park</title>
			<link>https://blog.markhepburn.com/posts/2010-09-20-vancouver-stanley-park/</link>
			<pubDate>Mon, 20 Sep 2010 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2010-09-20-vancouver-stanley-park/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>Last day in Vancouver, and a final visit to Stanley park before my flight in the evening. <!-- raw HTML omitted --> I loved the couple trying to emulate the pose of the &ldquo;mermaid&rdquo; statue (it&rsquo;s actually &ldquo;girl in a wetsuit&rdquo;, but I don&rsquo;t think it anyone calls it that), although I suspect there&rsquo;s quite a few attempts like that!</p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Vancouver: Tofino and Sea Kayaking</title>
			<link>https://blog.markhepburn.com/posts/2010-09-20-vancouver-tofino-and-sea-kayaking/</link>
			<pubDate>Mon, 20 Sep 2010 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2010-09-20-vancouver-tofino-and-sea-kayaking/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Vancouver: UBC Nitobe gardens</title>
			<link>https://blog.markhepburn.com/posts/2010-09-20-vancouver-ubc-nitobe-gardens/</link>
			<pubDate>Mon, 20 Sep 2010 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2010-09-20-vancouver-ubc-nitobe-gardens/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Phd Comics; in which I need to get a life</title>
			<link>https://blog.markhepburn.com/posts/2010-07-24-phd-comics-in-which-i-need-to-get-a-life/</link>
			<pubDate>Sat, 24 Jul 2010 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2010-07-24-phd-comics-in-which-i-need-to-get-a-life/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Ferntree / Zig-zag / Panorama / Shoobridge Tracks</title>
			<link>https://blog.markhepburn.com/posts/2010-06-19-ferntree-zig-zag-panorama-shoobridge-tracks/</link>
			<pubDate>Sat, 19 Jun 2010 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2010-06-19-ferntree-zig-zag-panorama-shoobridge-tracks/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Smith&#39;s Monument</title>
			<link>https://blog.markhepburn.com/posts/2010-06-11-smith-s-monument/</link>
			<pubDate>Fri, 11 Jun 2010 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2010-06-11-smith-s-monument/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Memoisation in Emacs Lisp</title>
			<link>https://blog.markhepburn.com/posts/2010-05-29-memoisation-in-emacs-lisp/</link>
			<pubDate>Sat, 29 May 2010 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2010-05-29-memoisation-in-emacs-lisp/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Icehouse Track</title>
			<link>https://blog.markhepburn.com/posts/2010-04-17-icehouse-track/</link>
			<pubDate>Sat, 17 Apr 2010 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2010-04-17-icehouse-track/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Linux: still free if your time is worth nothing</title>
			<link>https://blog.markhepburn.com/posts/2010-04-13-linux-still-free-if-your-time-is-worth-nothing/</link>
			<pubDate>Tue, 13 Apr 2010 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2010-04-13-linux-still-free-if-your-time-is-worth-nothing/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>At work I use a Dell laptop running Ubuntu, and which for the most part has painless and certainly better than the alternative (modulo the fun of using an alternative OS in a windows enterprise environment).  A couple of months ago however, after an update, I finally restarted &ndash; and realised that my network was no longer working.  We eventually realised that the ethernet interface had the wrong MAC address, which was odd because dmesg confirmed the kernel picking up the correct one, but ifconfig showed that eth0 and eth1 (the wireless card) had the same hardware address.  At any rate, using ifconfig to change it back to the correct value fixed things and away I went (note: this is actually because IPs where I work are assigned to registered MAC addresses; at home the wrong address was cheerily assigned an IP and worked fine).  Unfortunately, the problem was 100% repeatable: every time on reboot the wrong MAC was assigned and the network was useless.<!-- raw HTML omitted --> I suspected network-manager, but replacing it with wicd made no difference.  I suspected udev, but it was picking up the correct addresses too.<!-- raw HTML omitted -->I later noticed that wireless was also no longer functioning correctly: I could see all the available networks, but not connect to any of them.  I didn't initially correlate the two problems.<!-- raw HTML omitted --> Eventually I noticed that the wireless card wasn't getting the right address either, and again changing this back to the correct one fixed things.  At this point on a hunch I searched for the bogus MAC (AA:00:04:00:0A:04) I was seeing&hellip; and it turns out to be a fairly common problem, for example <!-- raw HTML omitted --><a href="http://ubuntuforums.org/showthread.php?t=465872">http://ubuntuforums.org/showthread.php?t=465872</a><!-- raw HTML omitted --> and <!-- raw HTML omitted --><a href="http://ubuntuforums.org/showthread.php?t=1268372">http://ubuntuforums.org/showthread.php?t=1268372</a><!-- raw HTML omitted --> (although none offer a solution).  I did however find this post: <!-- raw HTML omitted --><a href="http://blog.robertlee.name/2009/01/unicornscan-on-ubunto-some-updated.html">http://blog.robertlee.name/2009/01/unicornscan-on-ubunto-some-updated.html</a><!-- raw HTML omitted --><!-- raw HTML omitted --> And that, believe it or not, fixed things: yes, remove libdnet (DECnet support) and suddenly I once more have two functioning network interfaces without requiring manual interference.  What?  (and why did I even have DECnet in the first place?)  I can honestly say I would not have tracked that down myself, and I still don't understand <!-- raw HTML omitted -->why<!-- raw HTML omitted --> &ndash; but at this point I'm just happy it works and hoping it doesn't come back.</p>
]]></content>
		</item>
		
		<item>
			<title>Cape Raul and Shipstern&#39;s Bluff</title>
			<link>https://blog.markhepburn.com/posts/2010-04-06-cape-raul-and-shipstern-s-bluff/</link>
			<pubDate>Tue, 06 Apr 2010 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2010-04-06-cape-raul-and-shipstern-s-bluff/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Thark Ridge: In Search of the Devil&#39;s Throne</title>
			<link>https://blog.markhepburn.com/posts/2010-03-08-thark-ridge-in-search-of-the-devil-s-throne/</link>
			<pubDate>Mon, 08 Mar 2010 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2010-03-08-thark-ridge-in-search-of-the-devil-s-throne/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Lost World</title>
			<link>https://blog.markhepburn.com/posts/2010-02-22-lost-world/</link>
			<pubDate>Mon, 22 Feb 2010 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2010-02-22-lost-world/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>Another belated bush-walking post, sorry &ndash; these are from a couple of weeks ago. I did a circuit up on the mountain, and it was late afternoon so the light unfortunately isn&rsquo;t that great. The first path is so flat and well-maintained it could almost be paved; about 15 minutes along that you get to Sphinx rock, which has a pretty nice lookout from the organ pipes and over the city (first panorama). After that you pass a couple of stone huts, before reaching a third where a number of paths meet: Junction Cabin. I took the Lenah Valley fire trail from there, before getting onto the Old Hobartians&rsquo; track which climbs up through some nice forest and a few sandstone over-hangs. At the peak of that trail there&rsquo;s a detour up to Lost World, which was the main objective of this walk. The ascent involves mostly clambering over some pretty big boulders, before you suddenly crest and can see all of the &ldquo;lost world&rdquo; at once &ndash; it&rsquo;s a pretty breath-taking sight. Unfortunately as I said the light wasn&rsquo;t great and the photos really don&rsquo;t do justice to the scale of the place, but it&rsquo;s a huge ampitheatre-type area with some imposing cliffs slightly wrapped around a field of enormous boulders. Again, it&rsquo;s hard to get a feel for the size of things from the pictures, except maybe to note the trees growing up between the rocks! I took a panorama of the city (which didn&rsquo;t come out to well because of the light), but in the right you can just make out the two TV towers on top of Mount Wellington, to help situate things. The return trip was along the base of the Organ Pipes again, from where I got a reasonable panorama of the city. Great trip, sorry about the quality of the pictures. Speaking of quality: no GPS track this time, because although I was supposedly recording one, the results can only be described as &ldquo;ass-tacular&rdquo;. Apparently I was teleporting a lot. <!-- raw HTML omitted --> (I believe there&rsquo;s a nice short and easy walk to Lost World that approaches from the other side instead, but where&rsquo;s the fun in that!)</p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Tarn Shelf (this time, all the way around)</title>
			<link>https://blog.markhepburn.com/posts/2010-02-13-tarn-shelf-this-time-all-the-way-around-/</link>
			<pubDate>Sat, 13 Feb 2010 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2010-02-13-tarn-shelf-this-time-all-the-way-around-/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Per-User Database Authentication in Django </title>
			<link>https://blog.markhepburn.com/posts/2010-02-07-per-user-database-authentication-in-django-/</link>
			<pubDate>Sun, 07 Feb 2010 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2010-02-07-per-user-database-authentication-in-django-/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>A colleague was recently talking about the need for a data entry interface to a database, and I glibly said &quot;let me see how easy it is to put a Django-admin front-end on it!&quot;.  It turned out to be some-what less easy than expected; this post documents my solution to one of the less-easy aspects of it (there were others, but those were mostly to do with concerns of scale and better-documented issues surrounding legacy databases).  It is still quite an ugly solution, and please see the end for some fairly important caveats.  I'm documenting it here though because I did find other people with the same problem, but have yet to come across a solution.<!-- raw HTML omitted --> The problem is this: Django assumes that in general it will control the database, including creating the schema and implementing any logic.  This particular database made the opposite assumption; front-ends were merely conduits, and any verification etc would be handled internally.  In this case that wasn't much more complicated than updating fields such as &quot;added by&quot; via triggers, but the principles apply across a range of scenarios.  <!-- raw HTML omitted -->Here's a random example<!-- raw HTML omitted --> of the Django way.<!-- raw HTML omitted --> So, to play nicely with the database we'd ideally like each connection to be made using the credentials of the user using the application, and Django really isn't built for this.  One reason is that <!-- raw HTML omitted -->django.db.connection<!-- raw HTML omitted --> is a module-constant initialised with the database settings from <!-- raw HTML omitted -->settings.py<!-- raw HTML omitted -->, but if you are willing to swallow your pride we can also exploit this to our advantage.<!-- raw HTML omitted --> The first step is write an authentication back-end so the user will be authenticated using their database credentials:<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --> (I also changed the base admin template so it doesn't offer the &quot;change password&quot; option).  This is fairly standard; I'm using Oracle, but obviously any database can be made to work similarly.  Note that we still need the default database account in <!-- raw HTML omitted -->settings.py<!-- raw HTML omitted -->, and this will be used to create the new user in the <!-- raw HTML omitted -->django.contrib.auth<!-- raw HTML omitted --> tables for example.<!-- raw HTML omitted --> Step two is, err, to save the password in the session (I told you I felt dirty), so we can create a database connection using it each request.  This needs to happen in the login method, where you have access to both the session and the username/password.<!-- raw HTML omitted --> Step three is to convert <!-- raw HTML omitted -->django.db.connection<!-- raw HTML omitted --> to use these credentials instead of the defaults from <!-- raw HTML omitted -->settings.py<!-- raw HTML omitted -->; I did this using a custom middleware:<!-- raw HTML omitted --> <!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->At this point we're almost done, but a problem still remains: I'm using Oracle where each user has their own private schema, and the application is expecting to find a bunch of tables which don't exist in the user's schema.  We could get around this using synonyms for example, but instead I used a signal that is fired each time a connection is created (there seems to be precious little information or examples about this signal either) in order to change the schema the connection is using:<!-- raw HTML omitted --> <!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->This needs to be executed each time, so I put it in <!-- raw HTML omitted -->models.py<!-- raw HTML omitted -->.<!-- raw HTML omitted --> So, all in all, a fairly minimal solution, but&hellip;<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->Here be Dragons!<!-- raw HTML omitted --><!-- raw HTML omitted -->  As I mentioned, there are some pretty important caveats to be aware of if you ever use this (I accept no responsibility for any breakage, break-ins, yadda yadda yadda).  Most importantly, you are storing the user's password in plain-text for the duration of the session.  For our purposes this is fine; it's an internal application where security isn't exactly critical.  Your mileage may vary, significantly.<!-- raw HTML omitted --> Secondly and perhaps more importantly, the various other Django applications still need access to their tables, but now you are connecting as a different user, so each user using the application will also need permission on these tables.  This is the bit that turns my stomach the most!<!-- raw HTML omitted --> Lastly, there may well be consequences, race conditions, etc in manipulating <!-- raw HTML omitted -->django.db.connection<!-- raw HTML omitted --> that I have not come across yet.<!-- raw HTML omitted -->Please let me know if there is an easier/cleaner way!  <!-- raw HTML omitted -->(I still feel dirty)<!-- raw HTML omitted --></p>
]]></content>
		</item>
		
		<item>
			<title>Garie Beach, Royal National Park, NSW</title>
			<link>https://blog.markhepburn.com/posts/2010-01-09-garie-beach-royal-national-park-nsw/</link>
			<pubDate>Sat, 09 Jan 2010 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2010-01-09-garie-beach-royal-national-park-nsw/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>I spent a week in Sydney over the new year. There was walking. This particular lot is from around the coastal track around Garie Beach, in the Royal National Park. Fantastic weather (rain had been predicted!) as you can see, and for those of you expecting it &ndash; yes, I attempted a panorama, but it was so a-kilter that I haven&rsquo;t even bothered stitching it, sorry.</p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Spit to Manly Walk, Sydney</title>
			<link>https://blog.markhepburn.com/posts/2010-01-09-spit-to-manly-walk-sydney/</link>
			<pubDate>Sat, 09 Jan 2010 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2010-01-09-spit-to-manly-walk-sydney/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>A much easier walk around the headlands, winding up in Manly. With panoramas, this time.</p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Token Sydney Harbour panorama</title>
			<link>https://blog.markhepburn.com/posts/2010-01-09-token-sydney-harbour-panorama/</link>
			<pubDate>Sat, 09 Jan 2010 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2010-01-09-token-sydney-harbour-panorama/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Organ Pipes Track</title>
			<link>https://blog.markhepburn.com/posts/2009-12-26-organ-pipes-track/</link>
			<pubDate>Sat, 26 Dec 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-12-26-organ-pipes-track/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>Nothing special; I went for a quick walk to break in some new shoes. These are the &ldquo;Organ Pipes&rdquo;, the cliff at the top of Mount Wellington you can see from Hobart.</p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Tarn Shelf panoramas</title>
			<link>https://blog.markhepburn.com/posts/2009-12-22-tarn-shelf-panoramas/</link>
			<pubDate>Tue, 22 Dec 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-12-22-tarn-shelf-panoramas/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>A sample of the views available less than an hour into the walk!<!-- raw HTML omitted --></p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Tarn Shelf, Mt Field National Park</title>
			<link>https://blog.markhepburn.com/posts/2009-12-22-tarn-shelf-mt-field-national-park/</link>
			<pubDate>Tue, 22 Dec 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-12-22-tarn-shelf-mt-field-national-park/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>A shorter-than-intended (left it a bit late leaving, and it&rsquo;s a long way from home!) walk at Mt Field. The first shot is a token one from Russell Falls, which is a paved 10 minute walk from the car park. <!-- raw HTML omitted --> The main walk is a loop starting from Lake Dobson, which is a 20 minute drive above Russell Falls. It climbs up briefly through a pandani grove before hitting alpine territory, with some spectacular vistas (wait for the panoramas to be posted separately). Didn&rsquo;t get too far into it unfortunately; next time when I&rsquo;m more organised perhaps. Just (it was scurrying under the board-walk) caught an echnidna on the return trip.</p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Echo Point, Blue Mountains</title>
			<link>https://blog.markhepburn.com/posts/2009-12-07-echo-point-blue-mountains/</link>
			<pubDate>Mon, 07 Dec 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-12-07-echo-point-blue-mountains/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Collin&#39;s Cap Panorama, take 2</title>
			<link>https://blog.markhepburn.com/posts/2009-11-09-collin-s-cap-panorama-take-2/</link>
			<pubDate>Mon, 09 Nov 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-11-09-collin-s-cap-panorama-take-2/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Collinsvale Panoramas</title>
			<link>https://blog.markhepburn.com/posts/2009-11-09-collinsvale-panoramas/</link>
			<pubDate>Mon, 09 Nov 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-11-09-collinsvale-panoramas/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>Sent separately to be resized to a larger width.<!-- raw HTML omitted --></p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Photos, take 2, part 1</title>
			<link>https://blog.markhepburn.com/posts/2009-11-09-photos-take-2-part-1/</link>
			<pubDate>Mon, 09 Nov 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-11-09-photos-take-2-part-1/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>Apologies; there was a hiccup in posterous last it seems: I sent one email, with attachments, and got two posts, identical apart from one lacking any image gallery. So I deleted the gallery-less one, and&hellip; wound up with one post, with no gallery. (and no undo). The original email in gmail doesn&rsquo;t have the attachments either, perhaps because of the volume. so, anyway, here&rsquo;s the first lot of photos, again. Fingers crossed.</p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Three peaks</title>
			<link>https://blog.markhepburn.com/posts/2009-11-09-three-peaks/</link>
			<pubDate>Mon, 09 Nov 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-11-09-three-peaks/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>(but not <!-- raw HTML omitted -->those three peaks<!-- raw HTML omitted -->).  This weekend's adventures: a loop in Collinsvale, climbing Collin's Bonnet, Trestle Mountain, and Collin's Cap.  The track can be seen <!-- raw HTML omitted -->here<!-- raw HTML omitted -->.  Hmm, let's see what Posterous does with a track link:<!-- raw HTML omitted --> <!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->
<!-- raw HTML omitted -->View Larger Map<!-- raw HTML omitted --><!-- raw HTML omitted --> There's the usual GPS inaccuracies, including stopping short of the actual finishing point; what looks like an off-track detour to Trestle mountain though is actually correct, as the track in the guide (and on the map) was closed for re-vegetation).<!-- raw HTML omitted --> As you can tell from the photos, it was a spectacular day (note to self: 1200ml of water is probably not enough on a hot day.  Also, I got a bit burnt).  It's a really nice area, too.  It starts in Myrtle forest with a small water falls shortly along the track, then quickly climbs out of that and through Eucalyptus scrub into alpine.  There's two panoramas from Collin's Bonnet area; one just below the peak, and one from the peak.<!-- raw HTML omitted --> Trestle Mountain is accessible off a fire trail, and has some awesome rock formations up the top (panorama included), as well as great views back to the Bonnet.<!-- raw HTML omitted -->Collin's Cap is via another intersecting fire trail, and is a fairly popular walk from the Myrtle track where I started.  Thankfully, no-one was there by the time I got there!  In the final panorama you can see Collin's Bonnet on the left, and Trestle Mountain to the right.  (Hmm, gmail is dying trying to attach that last one &ndash; I might have to upload that separately)</p>
]]></content>
		</item>
		
		<item>
			<title>Cathedral Rock &#43; Montague Thumbs &#43; Wellington Falls loop</title>
			<link>https://blog.markhepburn.com/posts/2009-10-23-cathedral-rock-montague-thumbs-wellington-falls-loop/</link>
			<pubDate>Fri, 23 Oct 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-10-23-cathedral-rock-montague-thumbs-wellington-falls-loop/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>I walked up another (handful of small) mountains today; you can see the track (now with elevation profile!) <!-- raw HTML omitted -->here<!-- raw HTML omitted -->.  I think the time was reasonably quick; which is all the more surprising given that I got lost (and at other times just thought I might be lost) at least 3 times.  In fact, that started before I'd even commenced walking, so perhaps it was an omen: the directions just said to cross the bridge then park 20m after it.  There didn't seem to be any obvious parking (narrow gravel road), so eventually I pulled over in the widest bit.  Then I got out and started walking, and encountered a second bridge, with a handful of cars parked 20m after it (I took a calculated risk and didn't go back and move the car).  When I got back there were a couple of neighbours by the car, who explained that the first bridge I saw was just a log bridge until recently, so the guide authors presumably didn't count it.<!-- raw HTML omitted --> I walked to Cathedral Rock and had lunch (the first panorama, and yes there is a photo looking down from it as well &ndash; Dad, please don't point that out to Mum), then followed the ridge over to the &quot;thumbs&quot; (picture 5; picture 4 is Cathedral Rock from a slightly lower portion of it), then down and around, crossing over the river at the top of Wellington Falls before winding around to a lookout (where the second panorama is from, and where I again had lunch).  The last photo is of the thumbs again, from the other side of the gorge; Cathedral Rock is to the left of that, and apparently <!-- raw HTML omitted -->that<!-- raw HTML omitted --> photo didn't turn out properly.<!-- raw HTML omitted --> As I said, I lost my way several times.  The path to Cathedral Rock is pretty clear, provided you know that you're looking for a cairn and a stake in the track to turn off to it.  The Falls lookout is really well maintained, as is the track that runs from it down to the Pipeline Track.  Outside of those sections&hellip; you need to know where you're going.  I had a guide book, and there were plenty of cairns and bits of ribbon tied to trees, but on several occasions they were a bit sparse or I missed one and wandered off in the wrong direction, before realising I was probably on the wrong path and heading back.  Also, I fortunately met a guy at the top of the falls coming from the way I was going, who told me the way down &ndash; which was handy, as that bit of the journey didn't seem to mesh with the guidebook at all (I think there may have been a parallel track to the one down to the Pipeline that I actually took, and the track off the other side of the Pipeline wasn't marked as it was supposed to be).  All great fun though, and great<!-- raw HTML omitted --></p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>I walked up a mountain again</title>
			<link>https://blog.markhepburn.com/posts/2009-10-20-i-walked-up-a-mountain-again/</link>
			<pubDate>Tue, 20 Oct 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-10-20-i-walked-up-a-mountain-again/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Initialisation file portability tweaks </title>
			<link>https://blog.markhepburn.com/posts/2009-09-26-initialisation-file-portability-tweaks-/</link>
			<pubDate>Sat, 26 Sep 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-09-26-initialisation-file-portability-tweaks-/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>I did warn you&hellip; this is going to be about emacs!<!-- raw HTML omitted -->I keep my configuration under version control using <!-- raw HTML omitted -->github<!-- raw HTML omitted -->, and I use the same setup on two different platforms (linux and OSX).  Most of it is a collection of accumulated cruft and tweaks cannibalised from others, but there's two bits I haven't seen elsewhere that I think are worth sharing, which help make it portable:<!-- raw HTML omitted --> <!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->First of all I set a variable to the location of the checkout.  This is not novel, but the way the default is determined possibly is: file-truename resolves any symbolic links, etc to find the true-name of the file; this means you can check out the configuration anywhere, and all that is needed to install it is to symlink init.el to ~/.emacs.  file-name-directory just returns the directory base, which we now know is our checkout location where all our code is.<!-- raw HTML omitted --> Secondly, there is still occasionally the need for some platform-specific code.  I accomplish this by loading a file determined by the platform name (if it exists).  You need to be a bit careful here, because currently on my Ubuntu system 'system-type reports as gnu/linux and the forward-slash will be interpreted as a path separator, so I convert that to a dash with subst-char-in-string.  (For the record, OS X currently reports as &quot;darwin&quot;).  Obviously you could do something similar with hostname, for example.</p>
]]></content>
		</item>
		
		<item>
			<title>Meta-Post: The Future</title>
			<link>https://blog.markhepburn.com/posts/2009-09-09-meta-post-the-future/</link>
			<pubDate>Wed, 09 Sep 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-09-09-meta-post-the-future/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>Well, I initially set this up as a kind of travel blog to keep people posted on what I'd been up to.  Said travels have now finished, so either this just winds up, or I keep posting but in a different direction.  If the latter though, expect emacs to be involved fairly frequently, sorry   (especially now that <!-- raw HTML omitted -->posterous<!-- raw HTML omitted --> &ndash; which I use to host this &ndash; can embed <!-- raw HTML omitted -->gist<!-- raw HTML omitted --> urls!)<!-- raw HTML omitted --> If you have any alternative suggestions then of course let me know.  I also have seriously itchy feet now, so if I end up scratching those any time soon I'll presumably use the same forum for those stories!</p>
]]></content>
		</item>
		
		<item>
			<title>Whistler &#43; Blackcomb Mountains</title>
			<link>https://blog.markhepburn.com/posts/2009-09-09-whistler-blackcomb-mountains/</link>
			<pubDate>Wed, 09 Sep 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-09-09-whistler-blackcomb-mountains/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>The final excursion of my time in Vancouver, unfortunately. Last Thursday I went on a day-trip to Whistler before the workshop I&rsquo;m here for started. It was quite an early start, involving catching an 8am Greyhound bus (and yes, I managed to avoid any beheadings). First tip: when the website says you must turn up a minimum of 30 minutes before the scheduled departure, what they actually mean is: most people won&rsquo;t turn up until 5 minutes before, and the bus probably still won&rsquo;t be waiting. Anyway. <!-- raw HTML omitted --> So Whistler is the ultimate down-hill sports mountain; in winter it is covered with snow and snowboarders/skiers, and in summer &ndash; as it is now* &ndash; it is a mountain-biking haven. Unfortunately, this does mean that it&rsquo;s not the greatest spot for hiking, which is what we were there for: it&rsquo;s mostly alpine up the top, but the view is basically just of ski runs and chair lifts, until you get out the back. <!-- raw HTML omitted --> *For some definition of &ldquo;summer&rdquo;: it was bitterly cold up the top, as you&rsquo;ll see in the photos. <!-- raw HTML omitted --> The itinerary started with a cable car up Whistler, then a bit of &ldquo;scenic&rdquo; hiking, then catching another cable car up to the peak. As you can see from the photos, visibility was fair restricted, and so was circulation (I was in shorts). This didn&rsquo;t appear to deter a bunch of bikers though. We then caught the &ldquo;peak 2 peak express&rdquo; from Whistler to the neighbouring Blackcomb mountain. This is a bit of an engineering marvel; it&rsquo;s the longest cable car of its kind in the world (I haven&rsquo;t looked up what &ldquo;its kind&rdquo; is exactly, but it may be something like all the &ldquo;largest Buddha in the world&rdquo; statues there are, because the categories are things like &ldquo;wooden and seated&rdquo;; &ldquo;bronze seated in half-lotus&rdquo;, &ldquo;seated and picking nose&rdquo;, etc. None the less, it was very long and the view was quite spectacular). <!-- raw HTML omitted --> Blackcomb itself was similar to Whistler in terms of the view afforded, but there was a reasonable alpine walk out the back which offered a decent panorama a short distance from the base. I think both spots would actually have some reasonable hiking options if you had the time and the visibility was up to it, but we had neither unfortunately. From there anyway we caught another cable car down, which finished on the other side of Whistler village where we started. <!-- raw HTML omitted --> Random occurrence: Whistler has a bit of a reputation for having a large Australian population, working the chair-lifts etc, and sure enough we did bump into a mutual colleague there (hi Elio!). Small world. <!-- raw HTML omitted --> That was essentially my last adventure before finishing up with work and coming home. I had an absolute blast and I&rsquo;m going to miss you guys like hell, but I&rsquo;ll be back &ndash; there&rsquo;s just too much stuff I never got to do or see for a start! What a great place.</p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Lynn Canyon</title>
			<link>https://blog.markhepburn.com/posts/2009-09-02-lynn-canyon/</link>
			<pubDate>Wed, 02 Sep 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-09-02-lynn-canyon/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Bowen Island</title>
			<link>https://blog.markhepburn.com/posts/2009-08-09-bowen-island/</link>
			<pubDate>Sun, 09 Aug 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-08-09-bowen-island/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>Last weekend I made a short trip to Bowen Island, which is a small island about 20 minutes away by ferry. It was quite pretty (also, stinking hot that day), and for some reason apparently has a huge British population: it was almost disconcerting when a shopkeeper had a British accent! <!-- raw HTML omitted --> Not much else to say. Sample photos attached.</p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Harmony Arts Festival</title>
			<link>https://blog.markhepburn.com/posts/2009-08-09-harmony-arts-festival/</link>
			<pubDate>Sun, 09 Aug 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-08-09-harmony-arts-festival/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Mt Strachan hike, 18/7/2009</title>
			<link>https://blog.markhepburn.com/posts/2009-08-09-mt-strachan-hike-18-7-2009/</link>
			<pubDate>Sun, 09 Aug 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-08-09-mt-strachan-hike-18-7-2009/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>Ok, getting back up to date finally&hellip; in truth you haven&rsquo;t missed much, because I either haven&rsquo;t had a camera with me or just haven&rsquo;t been doing much that was photogenic. <!-- raw HTML omitted --> The last hike I did was a few weeks ago in Mt Strachan, which is in the skiing area of the north shore (and for all the mountain-bikers out there, yes, there were a lot of bikers). The hike itself wasn&rsquo;t actually that picturesque for the most part, because we basically just walked up the mountain under the ski tow, and picked up the trail right near the top. The view from the top however.. was another story. Absolutely stunning 360 vistas over the city, bay, and mountains behind. I took a few panoramas which I&rsquo;ve included. There were actually two &ldquo;peaks&rdquo;; after we hit the first one and had lunch (gratuitous &ldquo;finger shot&rdquo; included for fans of the genre), getting eaten alive by mosquitos because we didn&rsquo;t realise there was a fetid pond right behind us, there&rsquo;s a 10 minute saddle until you hit a slightly higher peak with even better views. <!-- raw HTML omitted --> We took a different (and occasionally off-track) route down which was a bit more scenic, and also included the remains of a Cessna crash. We had a brief stop at a lookout on the way home, which is the final panorama. <!-- raw HTML omitted --> That evening was a party on a private island (in Deep Cove; if you remember the boating trip up Indian Arm, it&rsquo;s along there), which is every bit as much fun as it sounds. Unfortunately (I swear I&rsquo;m not hiding anything) the only photo I took there was as we were boating over, which is the last photo in the set. Good times though.</p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Vancouver Aquarium</title>
			<link>https://blog.markhepburn.com/posts/2009-08-09-vancouver-aquarium/</link>
			<pubDate>Sun, 09 Aug 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-08-09-vancouver-aquarium/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Lake Wedgemount panoramas, and in praise of hugin</title>
			<link>https://blog.markhepburn.com/posts/2009-07-16-lake-wedgemount-panoramas-and-in-praise-of-hugin/</link>
			<pubDate>Thu, 16 Jul 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-07-16-lake-wedgemount-panoramas-and-in-praise-of-hugin/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>Here are the panoramas I promised; I&rsquo;m quite pleased by how they turned out, apart from the pink artifact in the bottom left of one of them. <!-- raw HTML omitted --> My camera has a panorama assist mode (yours might too), which overlays a portion of the last shot on the opposite side of the view finder to help you line things up, but you could do it manually as well. I use hugin to stitch them together (<!-- raw HTML omitted --><a href="http://hugin.sourceforge.net">http://hugin.sourceforge.net</a><!-- raw HTML omitted -->), which is basically just a front end to panorama-tools, which is a library that seems to back most of the commercial stitching tools as well. The UI of hugin isn&rsquo;t anything to write home about, but it gets the job done most of the time once you realise what it&rsquo;s asking for. <!-- raw HTML omitted --> The library uses the SIFT algorithm, which I just noticed is patented by&hellip; UBC. Apparently they&rsquo;re not just good at fisheries stuff. I think I actually skimmed the paper it&rsquo;s described in once; from memory it uses principal components analysis (or related algorithms do, I don&rsquo;t remember), but that&rsquo;s about all I can recall!</p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Wedgemount Lake (Garibaldi Provincial Park)</title>
			<link>https://blog.markhepburn.com/posts/2009-07-16-wedgemount-lake-garibaldi-provincial-park-/</link>
			<pubDate>Thu, 16 Jul 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-07-16-wedgemount-lake-garibaldi-provincial-park-/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Sunset from my balcony</title>
			<link>https://blog.markhepburn.com/posts/2009-07-13-sunset-from-my-balcony/</link>
			<pubDate>Mon, 13 Jul 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-07-13-sunset-from-my-balcony/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Stanley Park Seawall</title>
			<link>https://blog.markhepburn.com/posts/2009-07-06-stanley-park-seawall/</link>
			<pubDate>Mon, 06 Jul 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-07-06-stanley-park-seawall/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>Last weekend&rsquo;s notable excursion: I went for a walk around the seawall, which is a roughly 10km path (mostly separated into pedestrian and cycle/roller-bladers) around Stanley Park: <!-- raw HTML omitted --><a href="http://en.wikipedia.org/wiki/Seawall_%28Vancouver%29">http://en.wikipedia.org/wiki/Seawall_%28Vancouver%29</a><!-- raw HTML omitted --> <!-- raw HTML omitted --> The weather was a bit overcast, but it&rsquo;s a pretty nice walk. The pictures probably don&rsquo;t need much explanation. The first 6 were taken on the first km or two, around Canada Place. The rock on the corner (#8) is Siwash Rock. I&rsquo;m not sure who the guy in the penultimate photo is, but he was taking great care balancing a lot of rocks :) Then I met up with some friends and hung out in and around the International Jazz Festival that&rsquo;s on at the moment. <!-- raw HTML omitted --> A nice and cruisey weekend, not that news-worthy sorry.</p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>UBC Campus</title>
			<link>https://blog.markhepburn.com/posts/2009-07-03-ubc-campus/</link>
			<pubDate>Fri, 03 Jul 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-07-03-ubc-campus/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>Almost directly outside the office I&rsquo;m working (soon to be moving out of, as its rightful owner returns soon :() is the West Mall, but I haven&rsquo;t really been down it much because all the stuff like food, buses etc is out the other side of the building. At any rate, the other day I did have a walk down it, and it&rsquo;s really nice &ndash; no camera, yet again though. Today I rectified that, although it may be a little less photogenic this time, with the grass a bit browner and the odd cloud in the sky (yeah, I know you&rsquo;re feeling my pain). <!-- raw HTML omitted --> The building in pic #2 is the Koerner library, and the last time they were actually filming something: it had a big sign out the front that said &ldquo;School of Divinity&rdquo;, with bored-looking nuns standing around (I think one of them may even have been smoking). Apparently they do quite a lot of filming around the campus. <!-- raw HTML omitted --> Right up the end of the mall is the rose garden, of which I attempted to capture a panorama. Shortly before that is &ldquo;this thing that you stand on and your voice sounds funny when you speak&rdquo; (it&rsquo;s the W. Robert Wyman Plaza, and yes, your voice does sound funny). Right opposite the Koerner library is the I. K. Barber library, which looks a little odd with two modern glass-fronted buildings flanking it! <!-- raw HTML omitted --> Clearly I need to explore more of the campus! (It&rsquo;s huge).</p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Canada Day &#34;Fireworks&#34;</title>
			<link>https://blog.markhepburn.com/posts/2009-07-02-canada-day-fireworks-/</link>
			<pubDate>Thu, 02 Jul 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-07-02-canada-day-fireworks-/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>Apparently Wednesday (1st of July) was Canada day, with a public holiday and fireworks in the evening. I didn&rsquo;t actually get up to much during the day, but around 10pm a bunch of us headed to a beach above the downtown area and gathered along with 5000 others (numbers pulled from no-where, but it was packed). We found a bit of space and settled in, while all around us people were setting up tripods etc, and were generally a-buzz. <!-- raw HTML omitted --> Then&hellip; the distant sound of fireworks going off, somewhere way behind us, without a single flash to be seen! This was rapidly followed by the sound of 5000 people saying &ldquo;WTF?&rdquo;, and the beach pretty much cleared within 5 minutes. Photos (extremely blurry, sorry) of before and after. No, we didn&rsquo;t try and catch the end of them; they were obviously way away. <!-- raw HTML omitted --> This is Web 2.0 in real life, people: the wisdom of the crowd.</p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Night shots from Jericho Park</title>
			<link>https://blog.markhepburn.com/posts/2009-07-02-night-shots-from-jericho-park/</link>
			<pubDate>Thu, 02 Jul 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-07-02-night-shots-from-jericho-park/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>You&rsquo;ll have to use your imagination here, I apologise. This is from the park and beach a couple of minutes from where I&rsquo;m staying, and the views back to the downtown part of Vancouver are quite something. Hard to photograph with a shitty camera and no tripod though, apparently. Sorry about that.</p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Another weekend down, an organ lost</title>
			<link>https://blog.markhepburn.com/posts/2009-07-01-another-weekend-down-an-organ-lost/</link>
			<pubDate>Wed, 01 Jul 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-07-01-another-weekend-down-an-organ-lost/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p><!-- raw HTML omitted -->(Yes, I know this is a bit late, I'm sorry — you've all nagged enough!  There are (some) reasons).<!-- raw HTML omitted --><!-- raw HTML omitted -->Right, so weekend #2: there wasn't going to be that much to report, partly because I didn't get up to as much and the weather wasn't as nice, and also because what I did do wasn't accompanied by a camera.  Friday I went to a Jim Byrnes concert which was excellent; he's a blues musician born in Missouri but living in Vancouver since the 70s (he has also been missing his legs below his knees since around the same time).  There are actually some photos from this, courtesy of a friend's iphone (hence the sub-par quality).  Minor tidbit: the venue was &quot;Richards on Richards&quot; (located on Richards St), and the locals apparently use a contraction of that name.  Surprisingly, it's not a gay bar.<!-- raw HTML omitted -->
Saturday I was a bit washed-out, a consequence of getting home late and not having curtains &ndash; good morning, 5am.  As a result I didn't get up to much, but did go for a walk up to the beach and park 5 minutes north of my apartment, Jericho beach.  This was quite nice; much more laid-back than the meat-market of Kits beach that we were at on the first weekend.  There's some awesome views of the city at night to be had from there, so I'll try and get some pictures at some point.  Not this time though, sorry.  At night there was a street party, where they'd closed off a street for a charity race, so at the end they had food and beer, and people running on stilts, parties of women in bridal gear, parties of men in bridal gear, you get the idea.<!-- raw HTML omitted -->
&hellip;and here's where it gets a bit more interesting!  Sunday morning about 2am I woke up with abdominal pain, and it kept me awake for the rest of the night, leaving me further trashed for Sunday, so I didn't really get up to much.  It also didn't go away, which was vaguely disquieting and I was starting to think I should look for a doctor on campus if it was still there on Monday.  Sometimes it was very sharp and painful; at others it was just a large pressure feeling, as if a giant fart would clear it (if you'll pardon the image).  Unfortunately at this stage I looked up &quot;appendix&quot; on wikipedia, and having seen a list of symptoms could instantly find most of them on myself, and felt like a hypochondriac.  I was pretty certain that the pain was at least in the right place though.  Around 6pm I was talking to a friend (Sherman again &ndash; I told you he's been helpful!) and mentioned it, and it turns out he's done a couple of years of paramedic training in addition to computer science.  He convinced me to go get it checked out, and drove me in to UBC hospital.  This unfortunately wasn't the best place to go, as they don't have a surgery; they took some blood tests and xrays, and told me that it could it fact be appendicitis and I should see a surgeon.  So, we had to go to the Vancouver General Hospital, where this time it took a bit longer to be seen.  They did a CT scan (which unfortunately involves drinking some contrasts then waiting for a couple of hours first, all the while thinking &quot;I bet it <!-- raw HTML omitted -->is<!-- raw HTML omitted --> just wind&quot;), which confirmed that it was appendicitis and would have to come out.  I was almost relieved about this, since I was starting to seriously feel like a hypochondriac, especially when the pain receded a bit!  Sherman finally went home at this point, about 2am; he'd actually stuck with me all this time, I'm incredibly grateful for his help.<!-- raw HTML omitted -->
At this point I actually got really lucky: they told me that when the surgery actually happened would depend on the waiting list and how urgent they were, etc (my appendix hadn't ruptured, so I wasn't that urgent).  Then they rang the surgery who were just standing around, so it happened straight away!  Everything went well, I passed through recovery, and got transfered to a private room.  Lucky break #2: it was on the 8th floor, and had a spectacular view of the mountains and river!  (According to the nurses, during fireworks season patients in those rooms frequently get unknown &quot;visitors&quot;, due to the great vantage point).  So I spent most of Monday bored in a room, until they discharged me in the early evening.  Everything since has been smooth sailing; I have enough painkillers to knock out a horse, and I barely needed any — one at night for the first couple of nights to make sure I slept, basically.  Back at work the next day.<!-- raw HTML omitted -->
So that was my drama for the weekend; Canadian health-care is just as good as advertised, apparently.  Also, I'll try and carry a camera with me more often.<!-- raw HTML omitted --></p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Indian Arm</title>
			<link>https://blog.markhepburn.com/posts/2009-07-01-indian-arm/</link>
			<pubDate>Wed, 01 Jul 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-07-01-indian-arm/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>I&rsquo;m almost up to date again! <!-- raw HTML omitted --> I had a bit of a wander around Granville Island on Saturday (scarcely <!-- raw HTML omitted -->a proper island, really), which is a bit touristy but has some nice <!-- raw HTML omitted -->produce and stuff.  And some good coffee if you luck into the right <!-- raw HTML omitted -->place. <!-- raw HTML omitted --> Sunday was a bit more interesting; a boating trip around Indian Arm, <!-- raw HTML omitted -->which is a bit of an inlet off the main inlet, I suppose.  Getting a <!-- raw HTML omitted -->temporary boating licence is apparently as easy as signing a piece of <!-- raw HTML omitted -->paper!  Unfortunately, a lot of the pictures were taken while the boat <!-- raw HTML omitted -->was moving, so were at best very blurry and for the most-part also <!-- raw HTML omitted -->captured mostly sky or boat floor.  You&rsquo;ll just have to take my word <!-- raw HTML omitted -->on how spectacular it is! <!-- raw HTML omitted --> The second picture is a corner of Stanley park, with the sea wall <!-- raw HTML omitted -->going around the edge &ndash; I plan on running or cycling that at some <!-- raw HTML omitted -->stage; it&rsquo;s around 12km I think.  That yellow mound is sulfur <!-- raw HTML omitted -->apparently: lots of industrial action on the way there. <!-- raw HTML omitted --> (Oh yes, and I went to the night markets on Friday night, and yes <!-- raw HTML omitted -->they&rsquo;re exactly the same as night markets everywhere else).</p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Some photos from my hospital room</title>
			<link>https://blog.markhepburn.com/posts/2009-07-01-some-photos-from-my-hospital-room/</link>
			<pubDate>Wed, 01 Jul 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-07-01-some-photos-from-my-hospital-room/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Some views from the place I&#39;m staying</title>
			<link>https://blog.markhepburn.com/posts/2009-07-01-some-views-from-the-place-i-m-staying/</link>
			<pubDate>Wed, 01 Jul 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-07-01-some-views-from-the-place-i-m-staying/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>Very convenient; close to UBC and the bus routes. The first picture didn&rsquo;t come out too well, but you get the general idea. Great spot.</p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Grouse Grind</title>
			<link>https://blog.markhepburn.com/posts/2009-06-14-grouse-grind/</link>
			<pubDate>Sun, 14 Jun 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-06-14-grouse-grind/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>Vancouver, day 2 &ndash; Grouse Grind. This is a walk up a mountain to the north of the city (there&rsquo;s a lot of mountains to the north!), and it&rsquo;s a popular one &ndash; absolutely packed. So packed in fact that you aren&rsquo;t allowed to walk back down the same way, although there&rsquo;s a cable-car provided. According to wikipedia it climbs 853m elevation and covers 2.9km. Great fun. <!-- raw HTML omitted --> At the top they have a bunch of (mostly educational) tourist entertainment in addition to the usual food outlets. There was a guy giving a talk about bald eagles; they have a couple of grizzly bears there (although the only one I saw had hidden by the time I got the camera out sorry), and a lumberjack show (the log picture is from the set there, warming up I presume &ndash; turns out the guy at the far end of the log in picture is a 4-time world champion). Also, they made me eat a &ldquo;beavertail&rdquo;, which is basically dough stretched out and fried, then covered in sugar (and in my case, also cinnamon and lemon juice). Surprisingly good, and probably the equivalent of about 3 climbs. I swear I had abs until I ate that thing. <!-- raw HTML omitted --> The picture with me in it &ndash; don&rsquo;t expect there to be many of those, I&rsquo;m sure you&rsquo;ll be relieved to hear &ndash; is next to a carving of a Kodiak grizzly. It&rsquo;s 18ft high, which is apparently only a foot taller than the biggest real one ever seen. There was also a couple of timberwolves at the base of the climb, albeit sleeping. <!-- raw HTML omitted --> We got icecream on the way back. This place was insane: 218 flavours, including&hellip; curry. (I had chocolate and chilli &ndash; which had serious heat, even for me &ndash; and balsamic). That final picture is just one wall of 3 freezer displays! <!-- raw HTML omitted --> Work starts tomorrow; it might be a bit of a shock to the system! Looking forward to it though.<!-- raw HTML omitted --></p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Day 1 in Vancouver</title>
			<link>https://blog.markhepburn.com/posts/2009-06-13-day-1-in-vancouver/</link>
			<pubDate>Sat, 13 Jun 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-06-13-day-1-in-vancouver/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>Man Vancouver is pretty! We had spectacular weather for my first day here too; heaps of sun, and about mid-20s in temperature I think. Sherman picked me up in the morning along with some friends (for those of you who don&rsquo;t know, Sherman is the main programmer I&rsquo;ll be collaborating with at UBC, and has been a great help in getting me set up over here &ndash; and for those of you who are Sherman, many thanks :)) and gave me a driving tour, stopping for a bit in Stanley Park (first couple of pictures). We spent most of the afternoon on Kits beach (including a Capoeira display, pictured), and at the end of the day walked back around the waterfront (token sunset and beach shots). Great day. Great city.</p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Final hours in San Francisco: North Beach</title>
			<link>https://blog.markhepburn.com/posts/2009-06-13-final-hours-in-san-francisco-north-beach/</link>
			<pubDate>Sat, 13 Jun 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-06-13-final-hours-in-san-francisco-north-beach/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>I ended up blowing off the last session of WWDC on Friday in order to have one final walk around, choosing North Beach which is the Italian quarter (and right above Chinatown, which is where the first pic is from, on my way there). <!-- raw HTML omitted --> I started with another Lonely Planet walking tour, which actually focussed on the former haunts of the &ldquo;beat generation&rdquo;: pic #2 is &ldquo;Jack Kerouac Lane&rdquo;, and on its right is the City Lights bookshop, which was quite cool for a quick browse. Most of the rest of the pictures are just random, but fairly typical SF shots: I swear I must have over 100 that all look like that now!). <!-- raw HTML omitted --> Also, I found the SF Tricycle! (also pictured) And thank god too, because after a week of forcing down vats of pre-brewed &ldquo;Starbucks coffee&rdquo; from the convention &ndash; in fact, I even went without for a couple of days &ndash; I was almost off the habit. I am now espresso&rsquo;d up again, I am sure you will be relieved to hear. <!-- raw HTML omitted --> After that, I made it to the airport with plenty of time to spare, and finally got through customs etc in Vancouver about 11pm. More to follow..</p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>Around the edges of WWDC: techno-porn</title>
			<link>https://blog.markhepburn.com/posts/2009-06-11-around-the-edges-of-wwdc-techno-porn/</link>
			<pubDate>Thu, 11 Jun 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-06-11-around-the-edges-of-wwdc-techno-porn/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>Wednesday through Friday they've had lunch-time talks as well (so, obviously I've only been to two so far).  These are general interest subjects, usually with a vaguely mac-related theme.  Last time I was here they had a guy from Pixar talking about their tool development (a lot more interesting than it sounds :)) and how they put movies together, which was great.<!-- raw HTML omitted -->
There was a pretty interesting one on Wednesday by the guy from &quot;<!-- raw HTML omitted -->Smule<!-- raw HTML omitted -->&quot;, an iphone app company.  He's actually a Stanford PhD who did his thesis on a sound generation language called <!-- raw HTML omitted -->ChucK<!-- raw HTML omitted -->, which I've come across before but never looked at.  He started with a quick demonstration of the language and environment anyway, doing a live-coding performance :)  Then he moved on to talking about a few &quot;laptop orchestra&quot; projects and the like that had spun off from this work.  Then, he decided to leave an associate professor position at Stanford and form Smule, which is more or less about making music apps for the iphone (as in, apps that turn the iphone into an instrument; although their first was actually a &quot;virtual lighter&quot;).  All of them had a social aspect, such as being able to see who's playing what and where, voting on people's performances, etc, and a lot of the talk was about how they try and foster that, and the communities that had sprung up around it.  Fairly interesting, although I won't go into detail.<!-- raw HTML omitted -->
Last night I also went to a &quot;Coca Heads&quot; session at the Apple store near-by, which was about 6 short talks from developers and designers.  The common theme was definitely attention to detail in design and user-experience, but I won't go into details.  The speaker list is here for anyone who is curious: <!-- raw HTML omitted --><a href="http://theocacao.com/document.page/606">http://theocacao.com/document.page/606</a><!-- raw HTML omitted -->  It was great, I don't expect many of you to be interested though :)<!-- raw HTML omitted -->
Today's (Thursday) talk though was absolutely sensational!  It was on &quot;techno-archeology&quot;, and it covered a lot but the main theme was recovering images from the lunar surveyor films of the 60s.  Prior to the first moon landing they sent up about 5 of these robots to film the surface of the moon, looking for suitable landing places &ndash; this obviously requires a high degree of precision; 1m in this case (since that's about the size of boulder they wanted to avoid landing on).  The camera used had a staggering 24 inch aperture, and of course it was all analogue: the film was scanned on-board in space, then transmitted to 3 locations (including Woomoora) where it was stored.  Here it gets interesting, and I forget the precise details, but their processing &quot;workflow&quot; included photographing it, splicing things together manually by laying them out on the ground, and photographing them again!  (Then they'd manually walk around looking over them for a good landing spot).  Anyway, the tapes survived a couple of close-calls (&quot;should we just ditch them?&quot; &quot;Nah, better hang on to them&quot;), and were actually preserved in optimal conditions.  Next interesting fact: they hadn't degraded at all because, apart from the storage conditions, the binding agent was&hellip;. whale oil!  Ooops.  So the data-recovery aspect was in fact all about the hardware: there's only 4 machines left in the world that can read them, and most crucially, only one person with experience on the machines left.  (NASA do have detailed technical documents archived on the transmission format, etc).  It took them 3 months of restoration to get to the point where they could read anything, but the results are simply staggering (he also recounted with great glee about the various letters from people who didn't want to fund the project, stating that they wouldn't see any improvement over what they already had!).<!-- raw HTML omitted -->
This is the &quot;image of the century&quot;:<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->
And this is their restored image (it looks even better on a huge screen, as you can imagine):<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->
The project (still on-going) is documented here: <!-- raw HTML omitted --><a href="http://moonviews.com/">http://moonviews.com/</a><!-- raw HTML omitted --><!-- raw HTML omitted -->(Also, the computer that powered those robots had I think 256K of RAM, and performance measured in FLOPs!)</p>
]]></content>
		</item>
		
		<item>
			<title>The App Store Wall</title>
			<link>https://blog.markhepburn.com/posts/2009-06-09-the-app-store-wall/</link>
			<pubDate>Tue, 09 Jun 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-06-09-the-app-store-wall/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>WWDC Opening day</title>
			<link>https://blog.markhepburn.com/posts/2009-06-08-wwdc-opening-day/</link>
			<pubDate>Mon, 08 Jun 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-06-08-wwdc-opening-day/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>San Francisco, day 3</title>
			<link>https://blog.markhepburn.com/posts/2009-06-07-san-francisco-day-3/</link>
			<pubDate>Sun, 07 Jun 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-06-07-san-francisco-day-3/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>Main activity today was a bay cruise; I felt like doing something touristy and just seeing the sites. Unfortunately, I kind of ended up regretting it, mainly because of the other tourists (and the cheesy pre-recorded narration by &ldquo;Captain Nemo&rdquo;, although to be fair I couldn&rsquo;t hear it most of the time&hellip; due to the screaming kids jumping on my feet). Also, I really understand why people hate Fisherman&rsquo;s Wharf. <!-- raw HTML omitted --> While waiting for that I did a quick walk in to to Coit&rsquo;s monument (that phallic thing in the photos; a few of the shots were also from that hill). I didn&rsquo;t end up taking many shots on the cruise (especially after my camera copped a spray of salt water), but there&rsquo;s some token pics of the bridge again (I told you there were a lot of kite and wind surfers), Alcatraz, and the sea-lions of Pier 39. <!-- raw HTML omitted --> [Aside: my watch battery ran out about 6:30pm last night, and do you think I could find a place to replace it on a Sunday? Of course not; I&rsquo;ll have to try and duck out of the conference at lunch some time I think. So most of the day I had no idea what time it was, until I remembered that my camera also displayed the time] <!-- raw HTML omitted --> After that I registered for WWDC and went to an Australian delegates&rsquo; party (there&rsquo;s 10 in total from Tasmania, btw!). This was probably cutting things a bit fine; apart from the whole not-knowing-the-time thing, I possibly caught a sub-optimal tram back, which was then exacerbated just after I&rsquo;d got on when someone on a bike caught a wheel on the tracks in front, and hurt themselves &ndash; so we were delayed something like 15 minutes with fire engines (not ambulances, you say? Yeah, I have no idea either) parked in front, while I thought &ldquo;hmm, should I get off now and walk back and find a better option? Nah, won&rsquo;t be long now&hellip;. Ok, I really should have got off a while ago, how about now?&rdquo;. Fun times. <!-- raw HTML omitted --> Work starts tomorrow anyway, which is also fun in a geeky way. People are apparently going to be queuing outside from around 3, or worse (keynote starts at 10, people). I think 9am should be fine. I don&rsquo;t think you even get a better seat if you&rsquo;re early, either!</p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>TV in the US</title>
			<link>https://blog.markhepburn.com/posts/2009-06-07-tv-in-the-us/</link>
			<pubDate>Sun, 07 Jun 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-06-07-tv-in-the-us/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>40-odd channels, and nothing to watch.  The ads are quite revealing though; I think you can break them down into 3 categories that the majority seem to fall into:<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->Weight-loss and related (diabetes medication, etc)<!-- raw HTML omitted --></p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>San Francisco, day 2</title>
			<link>https://blog.markhepburn.com/posts/2009-06-06-san-francisco-day-2/</link>
			<pubDate>Sat, 06 Jun 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-06-06-san-francisco-day-2/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>Today&rsquo;s itinerary: Haight-Ashbury (home of the hippies in the 70s), the Golden-Gate Bridge, and Chinatown. <!-- raw HTML omitted --> The house featured there (pic 3) is where Janis Joplin lived for a year, before apparently being evicted for having a pet dog. The Jerry Garcia graffiti is on the footpath outside the house where he and a bunch of the Grateful Dead lived for a while. The actual Haight-Ashbury corner now has a Ben&amp;Jerry&rsquo;s on the opposite corner, and a clothes store on another. There were certainly a lot of hippies and whacked-out people around, but there&rsquo;s also heaps of chain clothes shops, tattoo parlours (&ldquo;I got a tattoo at Haight-Ashbury&rdquo;), etc. <!-- raw HTML omitted --> This set is only half-complete &ndash; my camera battery ran out just as I got to the other side of the bridge. Unfortunately, that was also the most picturesque side (you can get the city and Alcatraz in the background if your camera pans wide enough). It&rsquo;s certainly a spectacular site though. Also, for some reason at times there appeared to be as many kite-surfers as boats out in the bay! <!-- raw HTML omitted --> San Francisco is a fantastically pedestrian-friendly city: really wide footpaths (check out the pic, and also the bridge pic &ndash; that&rsquo;s actually fairly standard it seems), you don&rsquo;t have to wait long at traffic lights, and great public transport.</p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>San Francisco, day 1</title>
			<link>https://blog.markhepburn.com/posts/2009-06-05-san-francisco-day-1/</link>
			<pubDate>Fri, 05 Jun 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-06-05-san-francisco-day-1/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>I caught the cable car up to Chinatown (first photo is of them manually turning the car!), and had a walk around Russian Hill and down Lombard St (the &ldquo;crookedest street in the world&rdquo;). (I also walked around Fisherman&rsquo;s wharf and along the Embarcadero, but there wasn&rsquo;t much worth photographing there). That&rsquo;s Alcatraz in the second-last picture. <!-- raw HTML omitted --> Also, I face-planted at the top of Lombard St, when I caught my foot jumping off a vantage point. Go me. (This may have evened up my karma after I got upgraded to premium economy on the flight over! Boy is that worth it).</p>
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>SF day 1, ammendment</title>
			<link>https://blog.markhepburn.com/posts/2009-06-05-sf-day-1-ammendment/</link>
			<pubDate>Fri, 05 Jun 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-06-05-sf-day-1-ammendment/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
]]></content>
		</item>
		
		<item>
			<title>First Post -- I&#39;m off!</title>
			<link>https://blog.markhepburn.com/posts/2009-06-03-first-post-i-m-off-/</link>
			<pubDate>Wed, 03 Jun 2009 00:00:00 +0000</pubDate>
			
			<guid>https://blog.markhepburn.com/posts/2009-06-03-first-post-i-m-off-/</guid>
			<description><![CDATA[%!s(<nil>)]]></description>
			<content type="html"><![CDATA[<p>Apparently it's about time I had a blog, instead of emailing everyone I know about things I've found in other peoples'.  As you probably know&hellip; I'm off to Vancouver (via San Francisco) for 3 months, leaving tomorrow.  I will endeavour to keep this blog up to date with pictures and anything interesting that happens to me.  Let's see what happens though.<!-- raw HTML omitted -->
In case I do join the millions of people who sign up for a blog and never touch it again (<!-- raw HTML omitted -->median number of tweets per account: one<!-- raw HTML omitted -->), as my first post I give you these: Where the hell is Matt.<!-- raw HTML omitted -->
<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->
(out-takes and more here: <!-- raw HTML omitted --><a href="http://www.wherethehellismatt.com/videos.shtml">http://www.wherethehellismatt.com/videos.shtml</a><!-- raw HTML omitted -->)<!-- raw HTML omitted -->I'm sure you've seen them, but they're possibly my favourite things on the internet.  Never fails to make me grin for the rest of the day.  Watch them; you won't regret it.<!-- raw HTML omitted -->
I promise I won't dance, but I will try and keep you posted.</p>
]]></content>
		</item>
		
	</channel>
</rss>
