Eagleson's law

“Any code of your own that you haven't looked at for six or more months might as well have been written by someone else.” - Eagleson's Law

Seems about right.

Leave A Reply

Bash: Using previous command's parameters

Bash allows you to save some typing by referencing the previous command's parameters via a variable. If you want to reference the first parameter from the previous command you would use !^ and if you want the last parameter you would use !$. A real world example would be something like this:

mkdir /long/dir/structure/new_dir
cd !$

This would make a new directory and then change to that directory. Alternately you can reference numbered parameters using !:2 to reference the 2nd parameter.

Leave A Reply

Apache: Blocking access to certain file types with .htaccess

My templating system uses .stpl files for it's definitions. I do not want to serve these files directly to my users so I used an .htaccess file to block them.

<Files ~ "\.stpl$">
    Order allow,deny
    Deny from all
Leave A Reply

PHP: Look in to a multi-dimensional array using array_dive()

I have a multi-dimensional array that I need to extract data from. Given a string in the format of "person.first" I want to descend in to the array looking for person -> first. I wrote this array_dive() function to facilitate this lookup.

function array_dive(string $needle, array $haystack) {
    // Split at the periods
    $parts = explode(".", $needle);

    // Loop through each level of the hash looking for elem
    $arr = $haystack;
    foreach ($parts as $elem) {
        //print "Diving for $elem<br />";
        $arr = $arr[$elem] ?? null;

        // If we don't find anything stop looking
        if ($arr === null) {

    // If we find a scalar it's the end of the line, anything else is just
    // another branch, so it doesn't cound as finding something
    if (is_scalar($arr)) {
        $ret = $arr;
    } else {
        $ret = null;

    return $ret;

Here is a sample script that shows the function in action.

Leave A Reply

Smarty: E_NOTICE warnings on undefined template variables

After upgrading my PHP and Smarty installations I started getting E_NOTICE warnings for any template variable that was not defined. There are valid reasons to have an undefined variable in your template, so I did not want to show a notice every time one is encountered. A real world example that I've encountered is:

{if $debug}
    Debug: {$error_string}

One could argue you could just test if $debug is non-empty, but that's more typing and feels redundant. I have a lot of old templates using this sysntax and didn't want to have to update all of them. The simple solution I found in the Smarty README.

// Don't show missing template variables as E_NOTICE
$smarty->error_reporting = E_ALL & ~E_NOTICE;

Note: This does not mask your normal PHP E_NOTICE errors, just ones generated by Smarty.

Leave A Reply

Perl: Named captures in regexps

In a regular expression you can capture strings into variables using the default syntax:

$str = "2020-05-20";
$str =~ m/(\d{4})-(\d{2})-(\d{2})/;

printf("Year: %s Month: %s Day: %s\n", $1, $2, $3);

In a more complex regular expression/string things may move around. In this case it's better to use named captures instead of numeric captures. This can be done by using the (?<name>) syntax. This will capture that parenthesis pair in to the hash %+ with the name specified.

$str = "2020-05-20";
$str =~ m/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;

printf("Year: %s Month: %s Day: %s\n", $+{year},$+{month},$+{day});

Using named captures you can easily update your regular expression if the position of elements in your string change.

Note: If you use named captures, Perl also populates the numeric equivalent.

Leave A Reply

Adjective and animal lists

For a personal project I wanted to generate AdjectiveAnimal pairs. This required me to find a list of animal names and adjectives. This was not a trivial endeavor and required me to find, clean up, and organize several lists.

Feel free to borrow my lists if you want to save yourself a headache. Using these lists I can generate pairs like: PracticalOsprey, HumorousTermite, and DiplomaticTarpon.

I also wrote a tool to generate pairs based on these two lists.

Leave A Reply

Perl: Time::Piece

Perl has a great core module for dealing with dates and times: Time::Piece.

use Time::Piece;

my $t = localtime();

my $unixtime = $t->epoch(); # Unixtime
my $human    = $t->cdate(); # Human readable

# Format a date/time for output
print $t->strftime("%Y-%M-%d") . "\n";

# Convert a specific format to a date/time object
my $bd = localtime->strptime("1985-02-14", "%Y-%M-%d");
print "You were born on a " . $bd->fullday . " in " . $bd->year . "\n";

# Date/Time addition
print "In one hour it will be: " . (localtime() + 3600)->hms . "\n";

It works by overriding the built in localtime() and gmtime() functions and giving them an object oriented interface. I highly recommend looking at it if you have to deal with dates and times.

Leave A Reply

C/C++: Force floating point math

In C/C++ if you want to get a floating point result from integer division you need to cast at least one of the values as a float to force floating point division (not integer):

int a = 1;
int b = 7;

float c = (float)a / b;

If you don't cast one of the variables as a float you will get an integer result. This is true even if your resulting variable is cast as a float.

Leave A Reply

Tasmota API via HTTP using Curl

Tasmota has a huge catalog of commands that can be run via the serial console, MQTT, or HTTP. These commands are great for scripting purposes. The easiest way I've found to send a command is with Curl.


The API will answer in JSON which is easily digestible with JQ.

curl -s | jq
Leave A Reply

Espressif WiFi MCU cost comparison

Espressif has just released their newest WiFi enabled MCU the ESP32-S2. It's a successor to the ESP8266 and has many improvements. Not only does it have more CPU, more memory, and more GPIO pins it's also cheaper. Just for posterity's sake here is the current cost for of WiFi enabled MCUs.

MCU Cost
ESP8266 $1.60
ESP8285 $1.05
ESP32 (gen 1) $3.00
ESP32 (gen 3) $1.50
ESP32-S2 $0.99

Note: This is the cost for the bare IC only.

Leave A Reply

PHP: Sanitize a string down to printable characters

I needed a function to make strings into usuable URL identifiers. This function will take an input string and replace all non-url friendly characters with underscores.

function string_sanitize(string $str) {
    // Replace any non-word chars with underscores
    $str = preg_replace("/[\W_]+/", "_", $str);
    // Remove any leading/trailing underscores that are leftover
    $str = trim($str, "_");

    return $str;
Leave A Reply

Linux file IO redirection matrix

Borrowing from this amazing post about Linux file IO redirection here is a cool table that breaks down how to get the data where you want it.

Syntax TermStdOut TermStdErr FileStdOut FileStdErr File
command > no yes yes no create
command >> no yes yes no append
command 2> yes no no yes create
command 2>> yes no no yes append
command &> no no yes yes create
command &>> no no yes yes append
command | tee yes yes yes no create
command | tee -a yes yes yes no append
command |& tee yes yes yes yes create
command |& tee -a yes yes yes yes append
Leave A Reply

Arduino Relay shield on a Wemos D1

I bought an Arduino Relay Shield to use on my Wemos D1 (ESP8266). After some poking around here is the mapping for which pins enable which relays:

Pin Relay
GPIO13 Relay #1
GPIO12 Relay #2
GPIO14 Relay #3
GPIO4 Relay #4

To enable the relays on this shield you pull the appropriate pin HIGH. Other relay boards I've seen require you to pull the pin LOW, so don't get confused.

Here is the Tasmota template I used for the relay shield.

{"NAME":"Relay Shield","GPIO":[0,0,0,0,24,0,0,0,22,21,23,0,0],"FLAG":0,"BASE":18}
Leave A Reply

List of Dune Characters and Locations for my reference

Dune character and location notes:

Item Description
Duke Leto Atreides Leader of the Atreides, Paul's father
Lady Jessica Paul's mother, Bene Gesserit concubine to Leto, bears a son against the wishes of the Bene Gesserit
Paul Atreides Main character, son of Leto and Jessica. Fifteen years old
Bene Gesserit Sisterhood of "witches" who seek to gain political power, addicted to spice
Caladan Ocean homeworld of the Atreides
Arakis Desert world, home of the spice melange, setting for the entire book
Gurney Halleck Troubador Warrior, skilled in the use of the baliset, loyal friend to Leto
Thufir Hawat Old Mentat, master of assassins that has served house Atreides for many years
Duncan Idaho Swordmaster of the Ginaz, one of Leto's right hand men
Dr. Wellington Yueh Betrays Duke Leto
Princess Irulan "Narrator" of the book. Each chapter begins with one of her short diary entries
Sardaukar Elite military force of the Emperor
Fremen Local peoples of Arakis, glowing blue eyes
Mentat Human "computers", vast memories, ability to organize lots of information
Muad'Dib Small desert mouse, Paul later adopts this as his Fremen name
Kwisatz Haderach Male Bene Gesserit who can bridge space and time, result of breeding program
Liet Kynes Planetologist assigned by the emperor to assist in transition of Arakis
Salusa Secundus Harkonnen prison planet
Leave A Reply