↓ Skip to Content Start of content

2019 half marathon race report

Running a half marathon was one of my three primary goals for 2019. My race was October 6th and I'm very pleased with how everything turned out.

This isn't very interesting to read.

Race Information

Date October 6th, 2019
Distance 13.1 miles
Time 2:22:56


Goal Description Completed?
A Finish in under 2:30 hours Yes
B Finish in under 3:00 hours Yes
C Finish the race Yes


Mile Time
1 11:28
2 10:29
3 10:49
4 10:37
5 10:09
6 10:40
7 11:01
8 10:25
9 10:48
10 11:44
11 11:49
12 11:50
13 11:22


I signed up for the half marathon on New Year's day. I'd thought about running one for a couple of years, but it was never really a concrete goal; it would just appear in the back of my head from time to time.

Prior to sign up the furthest I'd ever run without stopping was 2 miles. I'd tried Couch to 5K with some success, but I was still firmly in the "run/walk" cycle.

For training I followed Hal Higdon's half marathon Novice 1 plan.

Training was not without its issues. I started running properly in July when temperatures regularly hit 80 to 90f. Most of my runs were early in the day, but as they got longer I would end up hitting the heat.

My soccer season started in August, and although I'd worked it into my plans it still game me some surprises. The first game I ended up splitting my eyebrow and getting it glued together with liquid stitches. It healed pretty quickly, but I couldn't run the day after which was my day for long runs. Injuries aside, playing soccer on a Saturday made it hard to run distance on Sundays.

Two weeks before the race I gave myself hematuria after my longest run. I was tested for infections and kidney stones, but thankfully it was just due to running without drinking enough. I took a couple of days off and everything cleared up on its own. Tip: drink something before and during long runs.

The weekend before the race was probably my worst run. The first 5 or 6 miles weren't too bad, but the last couple of miles I had no energy and ended up walking home. It was extremely disappointing and didn't fill me with much confidence.


My diet for the days leading up to the race was heavy on potatoes and protein. The night before was fresh pasta and meatballs. I'd tested both these meals during training and knew they wouldn't make me feel heavy the day after.

The race start was 7am. I woke up at 3am to eat a small portion of oatmeal. I'd tried it the week before with some success; it wasn't fun to wake up early it did help keep me going.

I went through my checklist, made sure everything was packed and then headed off to the race. Nervous excitement is probably the best description of how I felt. Seeing all the other entrants made me realize I was actually going to do it.

I went for a little jog and stretched out before heading to the back of the pack. The race starts as a combined 5k and half marathon, so the start area was quite busy.

The nerves were still jangling, but there was someone behind me on stilts which took my mind off things. During the national anthem a dog was singing along.


I knew I needed an 11:25 pace to meet my primary goal.

I'd run most of the route before, so I knew what to expect which was a big help. The weather was quite chilly at the start, but once the sun came out it warmed up to the mid 60's. It stayed dry throughout.

Nearly all of my training runs were solo, so it was a big change to have so many people around. Getting cheered along was a huge motivator, and just seeing people along the route kept me going. There was someone playing the trombone, and someone else was dressed as a cow with a sign that said "Moo-ve it". They made it a little easier.

The first few miles I ran with a friend who was taking part in the 5k. He's much faster than me, but hadn't trained for distance so he kept his pace slower for me. The first mile was slow and pretty hilly, plus there were a lot of people to navigate around. Things flattened out after that and we found a good rhythm.

It was nice having someone to talk with and to keep me focused.

After he split for the 5k I stuck on some music and got myself mentally prepped for the next couple of hours. I didn't put together a proper race playlist which I regret. Towards the end I really needed a boost, but I didn't have the mental energy to mess around trying to find music.

Everything was fairly smooth in the early miles and I felt pretty good - my pace was faster than my training runs and I felt full of energy.

I made sure to take on a little Gatorade at each aid station, and I had some energy chews that I ate every couple of miles near the end. I don't know if they actually worked, but even if they didn't they were still a useful placebo. They also gave my mind something to focus on, and I counted down how long to go until I could eat the next one.

Mile 5 and 6 were extremely tough. It was a little hilly, but nothing out of the ordinary. I felt like someone had wrapped a chain around me and was pulling me back. The pack had really spread out at this point and there were already people running the other way (the race looped back on itself at mile 6.5). It was a little disheartening.

Once I'd got through this part I was back to familiar territory for the rest of the race.

By mile 10 I was starting to slow down considerably. I knew that my pace was good enough to get me over the finish line in time, so I eased off a little. I did try to run faster for the last mile but just couldn't muster up the energy.

When I finally turned the corner and saw the mile 13 marker, I felt a huge wave relief. All I wanted was to stop moving. I did manage a final speed up for the last few meters as I crossed the line. They had an announcer calling out times and congratulating finishers, but I was so focused on finishing that I didn't hear a thing.


I was handed my medal and then walked to the recovery area. I felt quite light headed and my jaw was clenching once I stopped. I couldn't really enjoy the immediate post-race feeling as I was worried about fainting.

Post-race food was a protein bar and a sports drink. After that I and paced around for a bit, and then put on a clean shirt and some clean socks and shoes. After about 10 minutes or so I felt much better and got some photos taken. I stayed to cheer on some more finishers and watch the awards ceremony.

Made with a new race report generator created by /u/herumph.

Groundhog Day Resolutions - November 2019

October's Primary Goals

1. Complete the MVP of my book

I still achieved quite a lot for October, but I fell short of having an MVP ready for editing. What I did get done:

  • Set up a word count goal on Beeminder
  • Set up the book on leanpub and got everything hooked up
  • Planned out my MVP along with version 1.0
  • Wrote notes for 5 chapters

I'm not much of a writer and I expected this goal to be tough. So far it's been even more difficult than I expected.

2. Complete FOUR secondary goals

I completed the following goals:

Primary Goals for November

1. Complete the MVP of my book

Let's try this one again.

2. Complete at least one secondary goal

At this stage it's unlikely I'll complete my entire goal list before the end of the year. I'd like to make at least a slight dent in it before January rolls around.

Writing is my priority for the month, but any additional goals completed are a bonus.

Thoughts on October

The first secondary goal I completed was updating crypto ticker mode. It took under an hour to do and it made me wonder why I left it until October to work on.

After that I finished writing the "Exploring my Emacs packages" series. I already had notes for the remaining posts, but they still needed writing and editing. I also needed to grab some screenshots to spruce things up.

The 6502 simulator was finished a couple of days before the deadline. It's still not 100%, but it's functional and can run some basic programs. I originally started the project so I could learn to write assembler for the Commodore 64, but I think that might be a little too advanced for me at this stage.

Finally I read the revised version of "Loving Common Lisp, or the Savvy Programmer's Secret Weapon". It's definitely worth a read if you're interested in learning about lisp.

Exploring my Emacs packages - web-mode

Project homepage : http://web-mode.org/

For a long time html-mode was the best option for web editing in Emacs. Although it works well for straight html, it can struggle when in template languages.

Packages like mumamo and mmm-mode make it possible to mix major modes together, but I haven't had much success with them.

web-mode is a mode made specifically for editing HTML with embedded templates. It supports the following languages:

  • ctemplate (for mustache, handlebars, ember etc)
  • django/liquid/twig
  • erb
  • lsp
  • php

And 15 more (at the time of writing).

It's one of the modes I use most, so it makes sense to learn some more about it.

Adding a file extension to web-mode

To make Emacs use web-mode for a specific file extension, add the following to .emacs.d/init.el (or another file where your configuration lives).

;; Make Emacs use web-mode for .phtml files.
(add-to-list 'auto-mode-alist '("\\.phtml\\'" . web-mode))

Navigation key bindings

C-c C-n
Jump between opening and closing tags. The cursor has to be on the tag (not the tag content) for this to work.
C-c C-e b
Jump to the beginning of the current element.
C-c C-e b
Jump to the end of the current element.

Region selection key bindings

C-c C-e s
Select the current element (opening through closing).
C-c C-m
Expand the current selection to the nearest element. I prefer to use expand region, but this is still quite useful.

Other useful key bindings

C-c C-e c
Clone the current element under the cursor. Useful when filling something like a table and wanting to replicate a column.
C-c C-f
Fold or unfold the current block.
Comment the current line or region. Automatically works with whatever template language is currently under the cursor.

Per-project indentation

Different projects may have different coding styles. Some require tabs, some require 4 spaces and some require 2 spaces.

Thankfully Emacs supports per-directory settings via dir-locals.el. The following code will set a project to use tabs instead of spaces, and to display tab width as 2 characters.

((web-mode . ((indent-tabs-mode . t)
	      (tab-width . 2))))

This example will use 4 spaces for indentation.

((web-mode . ((indent-tabs-mode . nil)
	      (web-mode-markup-indent-offset . 4))))


C-c C-s will insert a snippet at the current location. An example snippet looks a bit like this:

(setq web-mode-extra-snippets
      '(("php" . (("foreach" . "<?php foreach ( $items as $item ) : ?>\n(|)\n<?php endforeach; ?>")))))

Which inserts the following and places the cursor at the | character:

<?php foreach ( $items as $item ) : ?>
<?php endforeach ?>

I prefer to use emmet-mode for generating HTML quickly and yasnippet for other modes, so this isn't something I have much experience with.

This post is part of the "Exploring my Emacs packages" series.

Exploring my Emacs packages - yasnippet

Project homepage : http://joaotavora.github.io/yasnippet/

yasnippet is a template expansion library for Emacs. It's a great way to quickly insert code without doing a lot of typing. For example:

Simple expansion example

yasnippet also supports user-entered variables in snippets. They look a little bit like this:

Snippet expansion with variables

Previous versions of the extension came bundled with snippets, but they are no longer included with the main package. The yasnippet-snippets repository on GitHub contains templates for over 50 major modes.

Basic snippet development

Every snippet is contained in a file of its own. To create a new snippet, call M-x yas-new-snippet to open a new buffer that is set up for snippet development. C-c C-c will save the new snippet.

The snippet code for the second screenshot looks like this:

# -*- mode: snippet -*-
# name: Wrap a helper or model
# key: wrap_helper
# group: templates
# --
protected function $1() {
	if ( empty( $this->$1 ) ) {
		$this->$1 = new ${2:ClassName}();

	return $this->$1;

The $1 and ${2:ClassName} are replaced by user input when the snippet is expanded. ClassName is inserted as a placeholder until replaced by the user.

Snippet files start with a small amount of metadata, most of which is for organization. There is also an optional condition field that executes elisp to check if the snippet should be expanded or not. This can be helpful to prevent snippet insertion in certain places.

Complex snippets using elisp

Snippets can also execute elisp code contained between ` characters. For example, the current time can be inserted in a template by using `(current-time-string)`.

It takes a little while to get the hang of, but it can be used for a lot of different things:

  • Inserting the name of the current file.
  • Transforming user input. This can be used to generate ID's.
  • Prompting for input from a set list of choices via yas-choose-value.
  • Using when and unless to insert additional content depending on user input.

A very simple example of when snippet logic looks a little like this:

# key: how_am_i
Current emotion: $1

${1:$(when (string= ":D" yas-text) "You are VERY happy")}
${1:$(when (string= ":)" yas-text) "You are happy")}
${1:$(when (string= ":(" yas-text) "You are sad")}

and does this:

Snippet expansion with elisp logic

By using embedded elisp, the original snippet from screenshot 2 can be changed to a single input that is formatted automatically:

# -*- mode: snippet -*-
# name: Wrap a helper or model
# key: wrap_helper
# group: template
# --
protected function ${1:$(string-inflection-underscore-function yas-text)} {
	if ( empty( $this->${1:$(string-inflection-underscore-function yas-text)} ) ) {
		$this->${1:$(string-inflection-underscore-function yas-text)} = new ${1:ClassName}();

	return $this->${1:$(string-inflection-underscore-function yas-text)};

The ClassName parameter (which can be accessed in elisp via yas-text) is automatically converted to underscores using string-inflection-underscore-function.

Snippet expansion with embedded elisp

There are also functions for working with regions, fields and user input. The yasnippet homepage contains a in-depth guide to snippet development along with a complete function reference.

This post is part of the "Exploring my Emacs packages" series.

Groundhog Day Resolutions - October 2019

September was a tricky month, but I think it went quite well.

September's Primary Goals

1. Run a half marathon

Running a half marathon was the biggest goal I set myself for the year. I'm not an athletic person and I knew running would be a challenge for me. I set myself three times to beat, with 2:30 being the absolute quickest I felt I could do if I really pushed myself.

I finished in 2:23, better than I ever imagined I could do.

Preparation was a big part of this goal. Running was the main prep, but I also planned out meals and tested various combinations of running gear. By race day I knew exactly what to wear, what to eat before and after, and what to do for recovery. It helped make the day go much smoother and eliminated most worries during the actual run.

2. Complete two secondary goals

I released two new BlitzMax tools: blam and docgen. Blam is a build tool that I use for all my BlitzMax projects. docgen is a fairly small project that extracts documentation from source code so I don't have to type it out twice.

3. Write two chapters of my book

Two more chapters are now ready to be cleaned up and edited. The book is still just a pile of notes and rough pages at this point, but it's slowly starting to coalesce.

September's Secondary Goals

1. Write at least 3 blog posts

I didn't write as much as I wanted to, but I wrote enough to pass here.

Primary Goals for October

1. Complete the MVP of my book

This won't be the finished version, and it will still need editing, but I want the basic structure and chapters ready by November 11th.

2. Complete FOUR secondary goals

There are 13 secondary goals left for the year and 82 days to complete them in. I really need to start crossing off more goals if I want everything done by December 31st.