All articles
2024
Mini-rust in Rust 008: Refactoring our parser -
Mini-rust in Rust 007: Evaluating an operation -
Mini-rust in Rust 006: Parsing an operation -
Message order in Matrix: right now, we are deliberately inconsistent -
Mini-rust in Rust 005: Making our lexer an iterator -
Mini-rust in Rust 004: Refactoring our lexer -
Mini-rust in Rust 003: Much prettier errors -
Mini-rust in Rust 002: Errors while lexing -
Mini-rust in Rust 001: Lexing an int -
Rust 101 - 53: Exercises for module G (q4) -
Rust 101 - 52: Exercises for module G (q3) -
Rust 101 - 51: Exercises for module G (q2) -
Rust 101 - 50: Exercises for module G (q1) -
Rust 101 - 49: Foreign function interfaces (interacting with other languages) -
Rust 101 - 48: Exercises for module F (q3) -
Rust 101 - 47: Exercises for module F (q2) -
Heads-up: moving away from WordPress -
Rust 101 - 46: Exercises for module F (q1) -
Rust 101 - 45: Unsafe types and examples -
Rust 101 - 44: Undefined behaviour -
Rust 101 - 43: The two meanings of "unsafe" in Rust -
Rust 101 - 42: Why do we need unsafe? -
Rust 101 - 41: Exercises for module E (q2b) -
Rust 101 - 40: Exercises for module E (q2a) -
Rust 101 - 39: Exercises for module E (q1b) -
Rust 101 - 38: Exercises for module E (q1a) -
Rust 101 - 37: Async runtimes -
Rust 101 - 36: What async and await really do -
Rust 101 - 34: What is async? -
Rust 101 - 33: Exercises for module D (q3) -
Elected to the Matrix Foundation Governing Board! -
Rust 101 - 32: Exercises for module D (q2) -
Rust 101 - 31: Exercises for module D (q1) -
Rust 101 - 30: Good patterns and not so good -
Rust 101 - 29: Trait objects and object safety -
Rust 101 - 28: Dynamic dispatch -
New home for my videos: video.infosec.exchange -
Why I won't link to AI resources -
Rust 101 - 27: Exercises for module C (q2) -
Rust 101 - 26: Exercises for module C (q1) -
Choosing who to vote for in the 2024 UK General Election -
Rust 101 - 25: Threads, Mutexes, channels, Send and Sync -
Rust 101 - 24: Parallelism and Rayon -
Rust 101 - 23 Exercises for module B (q3) -
Rust 101 - 22 Exercises for module B (q2) -
Rust 101 - 21 Exercises for module B (q1) -
Rust 101 - 20: Unit, integration and benchmark tests -
Standing for the Matrix Governing Board -
Rust 101 - 19: Creating a nice API -
Rust 101 - 18: Dependencies and Cargo.toml -
Rust 101 - 17: Exercises for module A3 (part 2) -
Automated backups from Signal to Nextcloud -
Rust 101 - 16: Exercises for module A3 (part 1) -
Rust 101 - 15: Lifetime bounds -
Rust 101 - 14: Some standard library traits -
Rust 101 - 13: Type Parameters and Associated Types -
Rust 101 - 11: Exercises for module A2 -
[Fixed in FF 123] Deleting an Indexed DB store can be incredibly slow on Firefox -
Don't store normal arrays of numbers in Indexed DB - use UInt8Array instead -
Keep your Indexed DB keys and values small if you want good performance! -
Rust 101 - 9: Vecs, Boxes and slices -
Rust 101 - 8: Writing methods using impl blocks -
Rust 101 - 7: Error handling with panic and Result -
2023
Letter to my MP: using starvation as a weapon -
Follow this blog on the fediverse! -
Rust 101 - 6: Structs and Enums -
Rust 101 - 4: Exercises for module A1 -
Rust 101 - 3: Memory and ownership -
Rust 101 - 2: Language basics -
Combining two function types with & (ampersand) in TypeScript (intersection) -
Accessing services on the host from a Docker container or a Podman one -
Why I'm voting tactically against you - letter to my Conservative MP -
Rust WASM hello world - no need for webpack! -
Estimating software tasks and stories: avoid time-based estimates -
Maths: The Fun Parts - Graphs video -
Maths: The Fun Parts - Groups video -
Maths: The Fun Parts - Sets video -
Live code reviews make life better -
2022
Air-Source Heat Pump - 1 year later -
IETF115 Trip Report (Can Matrix help messaging standardisation through MIMI?) -
Setting the text selection in a browser: just use setBaseAndExtent -
Outreachy August 2022 update -
Transcoding video files for playback in a browser -
Matrix is a Distributed Real-time Database Video -
Building cross-platform Rust for Web, Android and iOS - a minimal example -
Deporting desperate people from the UK -
Improving my vimrc live on stream -
Comparison of Matrix events before and after "Extensible Events" -
Air-Source Heat Pump - our experience so far, 2 months in -
2021
Providing MapLibre-compatible style JSON from openstreetmap-tile-server -
Self-hosting maps on my laptop -
Streaming to Twitch and PeerTube simultaneously using nginx on Oracle cloud -
New game: Tron - frantic multiplayer retro action -
Preventing Virgin Media hijacking my DNS -
Letter to my MP about climate emergency -
What to cache when building Rust using Gitlab CI or similar -
Printing the version of a Maven project -
Minimal example of a Maven pom for a mixed Kotlin and Java project -
Importing/migrating from one peertube server to another -
Why write an entire game (including Graphics) in a single, hand-coded JavaScript file? -
Matrix is the only (chat) game in town -
Writing Snake in Terraform Video -
Suspending the computer using Kupfer -
Uploading to PeerTube from the command line -
Republishing Bartosz Milewski's Category Theory lectures -
Announcing I-DUNNO 1.0 and web-i-dunno -
Automatically filling in the UK COVID test results page with Selenium IDE -
Toggle window decorations on Linux GTK3 with Python3 -
Making Smolpxl work on phones and tablets -
Limiting the number of open sockets in a tokio-based TCP listener -
Recommendation against the use of WhatsApp in your company -
Streaming video with Owncast on a free Oracle Cloud computer -
Is your program a function or a service? -
2020
Shutdown order consistency: how Rust helps -
Schema upgrades should be reversible (also other transformations, actually) -
Make levels for Rabbit Escape using the level editor! -
Announcing Smolpxl Scores - a high score table for your game -
Dovecot not working after upgrade to Ubuntu 20.04.1 (dh key too small) -
Letter to my MP on the overseas aid budget. -
Profile a Java unit test (very quickly, with no external tools) -
Why a Free Software web games site? -
Code your first game: Snake in JavaScript (on Raspberry Pi) -
Play and create little retro games at Smolpxl -
shareon.js.org now has a Share to Mastodon button -
Coding a tiny game in JavaScript video -
short - command line tool to truncate lines to fit in the terminal -
Set the date (EXIF) of a photo on Linux -
How to send an SMS using netcat (via SMPP) -
Letter to my MP on racism in the US and UK -
Example Android project with repeatable tests running inside an emulator -
Creating a tiny Docker image of a Rust project -
Keeping track of podcast times with a simple bash script on Linux -
Custom Bash tab completion for my program -
Struggling with Rust to figure out the right types for a function signature -
Converting HTML slides to a PDF with Firefox -
Support the Software Freedom Conservancy -
2019
KotlinJS: First impressions (formed by writing Snake) video -
Dependency Injection frameworks: reasons to avoid them video -
Coding workshop example worksheets -
Building an all-in-one Jar in Gradle with the Kotlin DSL -
Creating a self-signed certificate for Apache and connecting to it from Java -
ACCU Talk "How Kotlin makes your Java code better" -
ACCU Talk "How Git really works" -
Examples of Kotlin making your Java code better video -
Build with a different Java version (e.g. 11) using Docker -
Scheduling a task in Java within a CompletableFuture -
Rabbit Escape 0.12 out now, with water -
Convert a video to a GIF with reasonable colours -
Gradle: what is a task, and how can I make a task depend on another task? -
Python Async basics video (100 million HTTP requests) -
Keybase chat bot in 10 lines of bash -
Performance of Java 2D drawing operations (part 3: image opacity) -
Performance of Java 2D drawing operations (part 2: images) -
Performance of Java 2D drawing operations (part 1: types of operation) -
London Python Meetup January 2019 - Async Python and GeoPandas -
Run bash inside any version of Linux using Docker -
Windows missing from grub menu after Ubuntu install -
2018
Poor performance in Chrome (especially on mobile) - caused by SVG background images -
Interesting Characters (UTF-16, utf-8, Unicode, encodings) video -
Elm makes me happy (updated for Elm 0.19) video -
Godot: make new objects at runtime (instancing) video -
Godot: Dragging and dropping physics objects video -
Godot: 2D shapes bouncing off each other video -
Graft Animation Language on Raspberry Pi -
Worksheet: "Tell a story by making animations with code" -
My experience upgrading to Elm 0.19 -
Bulk adding items to Wunderlist using wunderline on Ubuntu MATE -
Writing a new Flarum extension on Ubuntu -
Ubuntu "compose" key for easy unicode character input -
Redirecting all requests to https and www using .htaccess in Apache -
Example of a systemd service file -
Installing Flarum on Ubuntu 18.04 -
Migrating videos from YouTube to PeerTube inside a Docker container -
How to write a programming language articles -
Allow drag-to-side, but not drag-to-top in Ubuntu MATE (Marco) -
Connecting to Slack from an IRC client using slirc -
Using Matrix to connect to Slack from an IRC client on Ubuntu -
Clever Things People Do In Groovy So You Have To Know About Them video -
Examples of SQL join types (LEFT JOIN, INNER JOIN etc.) -
Fixing Slack emojis in HexChat -
Ideas on how lexing will work in Pepper3 -
Deleting commits from the git history -
Questions and answers about Pepper3 -
Recording gameplay videos on RetroPie -
2017
TECH(K)NOW Day workshop on "Writing a programming language" -
FileZilla with proxy not working with strange characters in the password -
HTML5 CSS Toolbar + zoomable workspace that is mobile-friendly and adaptive -
maven-assembly-plugin descriptor for a simple tarball with dependencies -
Blog aggregator/planet in WordPress using FeedWordPress -
Adding a day in Python datetimes - use timedelta, not the datetime constructor -
Broken Levels Challenge - Egham Raspberry Pi Jam July 2017 -
Women Who Code workshop on "Write your own programming language" -
Running a virtualenv with a custom-built Python -
Adding a concurrency limit to Python's asyncio.as_completed -
"git what" is "git status" on steroids -
Making 100 million requests with Python aiohttp -
Python - printing UTC dates in ISO8601 format with time zone -
Python 3 - large numbers of tasks with limited concurrency -
Basic ideas of Python 3 asyncio concurrency -
C++ iterator wrapping a stream not 1-1 -
How to write a programming language ACCU talk -
C++ iterator wrapper/adaptor example -
C++ iterator example (and an iterable range) -
Make Android Gradle display unit test failure messages -
A story about magic and how we treat each other -
Annual cost of clean water for every human -
Iterating over the lines of a file in Java -
Raspberry Pi Jam "Chaos Car!" -
Automated UI tests on Android -
Submitting a package to F-Droid -
Resources for year 6 teachers on coding and programming -
2016
Setting up a sane Maven project -
How to write a programming language - Part 3, The Evaluator -
Basic Haskell project setup (unit tests, code, formatting) -
How to write a programming language - Part 2, The Parser -
Mousedown events delayed or sluggish on mobile -
How to write a programming language - Part 1, The Lexer -
Simple example of Netty 4 usage -
Elm resizeable SVG canvas filling the screen -
Ambiguous names in Java due to non-normalised unicode - but all OK in Python -
Gracefully shutting down Firefox, to avoid the crash/session dialog -
Basic Concepts of Christianity video -
How to analyse a .phd heap dump from an IBM JVM -
Elm makes me happy (old: Elm 0.17) -
Which Raspberry Pi photo was funniest? -
Raspberry Pi Funniest Photo Game -
Out-of-school education settings -
2015
New open source project on work time - git-history-data -
Java HTTPS to a server with a self-signed certificate -
Vim as editor for Claws Mail -
Avoiding postfix error "status=deferred (unable to look up host" -
Finding the download count of GitHub releases -
Android: using a TextView to show rich text in an AlertDialog -
Assassination of individuals by the state -
Difficult merges in Git - don't panic! -
ZX Spectrum BASIC Web Server -
Letter to my MP on UK government assassination of British Citizens in Syria -
Rabbit Escape out now on Android! -
Changing the Docker daemon options in systemd on Ubuntu 15.04 -
Docker fails to start on Ubuntu 15.04 -
Preventing Audacity from crashing when using PulseAudio -
Movie podcast "The Good Robot Andys" -
Code for detecting when you leave an Android app -
Mocks are Bad, Layers are Bad -
Prediction result: corporate Linux -
Detecting whether an Android app is stopping (or starting) -
Order of Android Activity lifecycle events -
Preventing Kupfer switching to existing windows -
Rabbit Escape 0.3.1 - now with zoom! -
Treat warnings as errors in a (Gnu) Makefile -
Switching Xfce to use metacity -
Java game programming: image rendering hints make no difference to rendering time -
fetchmail complaining about GoDaddy SSL certificate -
Encapsulation as passing on responsibility -
Batch-converting audio files to be louder (on Linux) -
Why Rabbit Escape is Open Source / Free Software -
How to make your own levels for Rabbit Escape -
Rabbit Escape v0.1 out now for Linux, Windows and Mac video -
Rabbit Escape (a bit like Lemmings) v0.1 released for Linux, Windows and Mac -
Programmatic equivalents of web.xml sections for Tomcat -
JAX-RS (using Apache CXF) in embedded Tomcat example -
Vim persistent buffer list combined with saved sessions -
2014
Snowflake Christmas card web page on the Raspberry Pi -
Snowflake Christmas card in Scratch on the Raspberry Pi -
LibreOffice spell check not working in Lubuntu -
Is it ok to represent dates as Unix time (seconds since the epoch) in JSON? -
Using hexdump to represent a binary file in Java source code -
Disabling screensaver on LXDE -
Android development - saving state -
Android development - Rabbit Escape really working on Android -
Showing urgent (flashing) windows on all desktop in LXDE's taskbar (window list) in Lubuntu -
Launch an urgent window using Python and Xlib with the UrgencyHint flag -
Android programming - a non-Android, Android Game -
Android programming - drawing bitmaps in a game loop -
Don't use email auto-forwarding (emails will go missing) -
Fetchmail "mda" option makes emails bypass the spamassassin filter in postfix -
Android programming - a menu using Activities and Intents -
Raspberry Pi Minecraft Python summer project screenshots -
Android programming - setting up Android Studio -
Absolute Truth in programming languages -
Options for code reviews with Git -
Desktop sharing not working in Lubuntu 14.04 -
Best GCC warning flags for compiling C++ -
What git server should I use? -
Renewing self-signed certificate for ejabberd -
OpenID security in a REST API -
avconv performance slow in Ubuntu 14.04 trusty -
Does test-driven development harm clarity? -
Token-based security in a REST API -
Avoid mocks by refactoring to functional -
Using the final keyword in interface method parameters does nothing -
Using xscreensaver to lock the screen in Lubuntu -
2013
Avoid backslashes anywhere in Java code (Java error "illegal unicode escape") -
Using if:set, unless:set etc. with macrodefs in Ant -
Using if:set, unless:set etc. to execute a task conditionally in Ant -
Behaviour of Java String.split() when some answers are the empty string -
Checking the case of a filename on Windows -
Passing several values through a pipe in bash -
Goodness in programming languages, part 4 - Ownership & Memory -
Using gnome-mplayer to play DVB radio without asking whether you want to resume -
C++14 "Terse" Templates - an argument against the proposed syntax -
setUp and tearDown considered harmful -
Why use git for source control? -
Set the volume in OpenBox/LXDE (or on the command line) with PulseAudio and Ubuntu -
Everybody loves build.xml (test-driven Ant) -
Everybody hates build.xml (code reuse in Ant) -
Dry run mode for Ant (ant -n, ant --dry-run) -
My First Raspberry Pi Game " Part 12 " Scoring, done! -
My First Raspberry Pi Game " Part 11 " Being less rude -
2012
My First Raspberry Pi Game " Part 10 " Red square -
My First Raspberry Pi Game " Part 09 " Lots more words -
My First Raspberry Pi Game " Part 08 " Success and failure -
My First Raspberry Pi Game " Part 07 " A green circle -
Launching an OSGi app on the command line -
My First Raspberry Pi Game " Part 06 " A better class of waiting -
My First Raspberry Pi Game " Part 05 " Say something -
My First Raspberry Pi Game " Part 04 " A small black screen -
Length of Open Source licenses -
My First Raspberry Pi Game " Part 03 " It's like a magic spell -
My First Raspberry Pi Game " Part 02 " Saying hello -
My First Raspberry Pi Game - Part 01 - Before we start -
Running Dojo DOH tests in a browser without a web server -
Bash associative array examples -
Running Dojo 1.7+ DOH unit tests on the command line with Rhino -
Goodness in programming languages, part 3 " not doing the same thing more than once -
Tail Call Optimisation in C++ - lightning talk video -
Tail Call Optimisation in C++ published in Overload journal -
Scheme 4: Recursion - how to write functions in Scheme video -
Scheme 2: Basics - pairs and lists video -
Scheme 1: Feel the cool video -
Generalising tail call optimised C++ -
Performance of tail call optimised C++ -
Tail call optimisation in C++ -
Lighting talk - Tail call optimisation in C++ -
Scheme: pairs, lists and recursion -
What timezone Python thinks I'm in -
Freeview dvb-t scan gives "tuning failed!!!" after 18th April switchover -
Goodness in programming languages, part 2 " getting your code running -
Goodness in programming languages, part 1 - syntax and layout -
Ethernet not working on Ubuntu with Realtek RTL8111/8168B -
2011
Entertain your baby using your Android phone -
rdesktop swallows keyboard events -
Reclaiming desktop space with Ubuntu's window-picker-applet -
My Address Book 1.9.0 - rewritten from scratch -
Switching workspace in GNOME via the command line -
Anatomy of an interpreter: the Evaluator -
How to ask technical questions in person -
2010
Anatomy of an interpreter: the Parser -
Anatomy of an interpreter: the Lexer -
Subs Scheme Lisp Interpreter -
Ubuntu Lucid upgrade - a catalogue of disaster and pain -
2009
Don't design for performance until it's too late -
Technorati appear to have broken openid delegation -
NNDB 0.1 -
CBeebies and other channels not working with mplayer -
Firefox keyword search for finding C++ keywords -
Flaws in the software patents system -
IGCC - a real-eval-print loop for C/C++ -
Diffident - command line side-by-side diff editor -
Separate regular expressions, or one more complex one? -
New Baby -
2008
Fixing the vertical panel window list on Ubuntu Hardy -
An actual difficult bug fixed -
Debugging memory use and fragmentation on Windows using Address Space Monitor -
Public bzr branch of FreeGuide -
Finally released last.fm support for GSSMP -
2007
lighttpd on Ubuntu - alias.url doesn't work when included in a module config file -
FreeGuide updated to latest XMLTV, and bug fixes -
Caution: numbers that feel prime may be divisible by 3 -
Heartfelt apologies for the feed URL change -
FreeGuide - putting recording on hold -
(Badly wrong) usage statistics for FreeGuide -
Procmail Maildir messages disappearing -
lastfmsubmitd on Ubuntu Dapper -
Digital TV on Dapper with my Hauppauge WinTV Nova-T card -
Restoring a backup with Duplicity -
Remote encrypted backup with duplicity -
Creating .deb and RPM packages -
2006
Another FreeGuide release candidate -
FreeGuide 0.10.4 release candidate -
A Quick and desperate introduction to data recovery -
Keyboard layout change in Ubuntu -
FreeGuide source layout (and SVN migration) -
Donation -
Setting up my ideal email system 4 -
I spawn -
2005
Setting up my ideal email system 3 -
Setting up my ideal email system 2 -
Setting up my ideal email system -
Prince of Persia - The Sands of Time -
London -
The dangers of learning to code -
Constantly changing passwords -
Honestly my last post about my viva -
Mnemonic -
FreeGuide packaging and plugins -
DIYBlog -
RSS -
What is going on with FreeGuide? -
Google -