5-Character Dev Environment

Messing with my .bash_profile this afternoon, post-diving into Laravel and Git (which I’ve been doing much of the last week), I realised I could boot my entire dev environment with 5 letters. Fewer, if I wanted.

So instead of going to the Dock, clicking each of the icons, going to each and faffing around, I could at least boot them all, and set off some commands in Terminal (or ITerm2 as I’m now using).

Weirdly, until Justine gave me an evening of command-line Git learning, and wanted my .bash_profile, “Like so,” I hadn’t realised you could do stuff like that, despite amusing myself with all manner of shell scripts. Now I know what’s possible, I’m over-achieving in efficient laziness.

What’s missing is:

  • Opening multiple windows in ITerm or Terminal and running a different command in each (I don’t want to boot multiple instances of an app).
  • Setting off a menu action in an opened app, e.g. in Transmit going to my work drive.
  • Extending it to boot the environment and then a specific project, e.g. “devup laravel” would open my laravel installation in each of the apps, like opening the database in Sequel Pro; cd-ing to the laravel folder after automatic SSH-ing into my Vagrant box, and so on.

Some of these are probably uncomplicated, but this was a 30-minute experiment that turned out to be very useful.

5-character dev environment
5-character dev environment

Bookmark Archaeology


I was cleaning out my browser bookmarks last night, first time in years, bookmarks going back to the early-’00s, thousands of them. I opened them in batches, every one, to see if I wanted to keep them. Hundreds, thousands of dead sites, no longer found, no longer existing. All that history and culture vanished as if it never was, only the link and title in my bookmarks proving they once existed, and once I deleted that …

Code Stupidity


I got sick of the tiny, Web1.0 images everywhere here, a hangover from the earliest days of supernaut, so I decided — ’cos I like visuality & pix — to make small, big. I thought it would be easy. Little did I know I also create and add to the pile of Technical Debt. So: most single images in the recent past are now huge-ified, 666px wide; recent image galleries which are not full of diverse image ratios are now evenly splitting the Number of the Beast. Older images and galleries should be retaining their previous diminutiveness, but who knows, 13 years of blog is difficult to homogenise. Mostly I got distracted with how to make portrait images not blow out of the available browser window space, which turns out to be a kinda traumatising process I didn’t achieve. Plus how to Lazy Load srcsets by preg_replacing the new WordPress caption shortcode. OMFG, Frances, WTF? All of which makes me think it might be time for yet another supernaut refresh. So much code. So many images. So much …

Website rsync Backups the Time Machine Way

Continuing my recent rash of stupid coding, after Spellcheck the Shell Way, I decided for Website rsync Backups the Time Machine Way.

For a few years now, I’ve been using a bash script I bodged together that does incremental-ish backups of my websites using the rather formidable rsync. This week I’ve been working for maschinentempel.de, helping get frohstoff.de‘s WooCommerce shop from Trabant to Hoonage. Which required repeated backing up of the entire site and database, and made me realise the shoddiness of my original backup script.

I thought, “Wouldn’t it be awesome, instead of having to make those stupid ‘backup.blah’ folders, to let the script create a time-stamped folder like Time Machine for each backup, and use the most recent backup for the rsync hard links link destination?” Fukken wouldn’t it, eh?

Creating time-stamped folders was easy. Using the most recent backup folder — which has the most recent date, and in standard list view on my Mac, the last folder in a list — was a little trickier. Especially because once a new folder was created to backup into, that previously most recent was now second to last. tail and head feels hilariously bodgy, but works? Of course it does.

Bare bones explaining: The script needs to be in a folder with another folder called ‘backups’, and a text file called ‘excludes.txt’.  Needs to be given chmod +x to make it executable, and generally can be re-bodged to work on any server you can ssh into. Much faster, more reliable, increased laziness, time-stamped server backups.

# ---------------------------------------------------------------
# A script to manually back up your entire website
# Backup will include everything from the user directory up
# excludes.txt lists files and folders not backed up
# Subsequent backups only download changes, but each folder is a complete backup
# ---------------------------------------------------------------
# get the folder we're in
this_dir="`dirname \"$0\"`"
# set the folder in that to backup into
# cd to that folder
echo "******************"
echo "cd-ing to $backup_dir"
echo "******************"
cd "$backup_dir" || exit 1
# make a new folder with timestamp
time_stamp=$(date +%Y-%m-%d-%H%M%S)
mkdir "$backup_dir/${backuppath}supernaut-${time_stamp}"
echo "created backup folder: supernaut-${time_stamp}"
echo "******************"
# set link destination for hard links to previous backup
# this gets the last two folders (including the one just made)
# and then the first of those, which is the most recent backup
link_dest=`ls | tail -2 | head -n 1`
echo "hardlink destination: $link_dest"
echo "******************"
# set rsync backup destination to the folder we just made
backup_dest=`ls | tail -1`
echo "backup destination: $backup_dest"
echo "******************"
# run rsync to do the backup via ssh with passwordless login
rsync -avvzc --hard-links --delete --delete-excluded --progress --exclude-from="$this_dir/excludes.txt" --link-dest="$backup_dir/$link_dest" -e ssh username@supernaut.info:~/ "$backup_dir/$backup_dest"
echo "******************"
echo "Backup complete"
echo "******************"
# info on the backup commands:
# -a --archive archive mode; same as -rlptgoD (no -H)
# -r --recursive recurse into directories
# -l --links copy symlinks as symlinks
# -p --perms preserve permissions
# -t --times preserve times
# -g --group preserve group
# -o --owner preserve owner (super-user only)
# -D same as --devices --specials
# --devices preserve device files (super-user only)
# --specials preserve special files
# -v --verbose increase verbosity - can increment for more detail i.e. -vv -vvv
# -z --compress compress file data during the transfer
# -c --checksum skip based on checksum, not mod-time & size – SLOWER
# -H --hard-links preserve hard links
# --delete delete extraneous files from dest dirs
# --delete-excluded also delete excluded files from dest dirs
# --progress show progress during transfer
# --exclude-from=FILE read exclude patterns from FILE – one file or folder per line
# --link-dest=DIR hardlink to files in DIR when unchanged – set as previous backup
# -e --rsh=COMMAND specify the remote shell to use – SSH
# -n --dry-run show what would have been transferred

A Bit of Character Counting Stupidity

When I’m using WordPress’ Status Post Format, I like to keep it to 140 characters, so it’s like a Tweet. But how many characters have I typed? Cos The Visual Editor only shows Word Count. So I took a look around and saw various ways of doing it, quite a few using regex to strip ‘unwanted characters’—but a space counts as a character! So I wrote my own, based loosely on what I’d been using for counting characters in the Excerpt, and from a few different plugins and bits of code. Turned out to be surprisingly easy and uncomplicated (I say that now, of course).

So, first I need a function to call a couple of files if I happen to be editing a Post or Page:

function supernaut_character_count( $charcount ) {
  if ( 'post.php' == $charcount || 'post-new.php' == $charcount ) {
    wp_enqueue_style( 'character-count-css', get_stylesheet_directory_uri() . '/css/char-count.css', array() );
    wp_enqueue_script( 'character-count-js', get_stylesheet_directory_uri() . '/js/char-count.js', array( 'jquery' ), '20160519', true );
  else return;
add_action( 'admin_enqueue_scripts', 'supernaut_character_count' );

Then I slap together some jQuery:

jQuery( document ).ready( function( $ ) {
  if( $( '.post-php' ).length || $( '.post-new-php' ).length ) {
    $( '#post-formats-select input' ).click( function() {
      if ( $('#post-format-status').is(':checked') ) {
        $( '#post-status-info tr:first-child' ).after( 'Character count: ' );
        $( '#content_ifr' ).ready( function () {
          setInterval( function() {
            var tinymcebody = $( '#content_ifr' ).contents().find( 'body' );
            $( '#postdivrich .character-count' ).html( tinymcebody.text().length );
          }, 500 )
      } else {
        $( '#post-status-info tr:first-child' ).nextAll().remove();

Then a miniscule bit of CSS:

.post-php #wp-character-count {
  font-size: 12px;
  line-height: 1;
  display: block;
  padding: 0 10px 4px;

It’s a little bodgy, and if I had more than the 45 minutes to a) work out how the Visual Editor can be fiddled with, and b) write something that worked and looked ok—the bare minimum really—I’d do it slightly nice and maybe consider for a minute throwing it into a plugin (where it officially belongs). But I won’t. It does what I want: live updating of how many characters I’ve written in the Visual Editor, and shows it in a line underneath the Word Count (also aided me in delaying writing a residency application on the day it’s due).

supernaut Character Count
supernaut Character Count

Reading … What?


I am actually reading – to explain lack of book blogging. Merely finishing off a few in my pile of the non-fiction type I realised I’d left part-way through when I unpacked all my shelves a couple of months ago. New shit pile is currently getting dealt to, plus imminent arrival of a dozen or so tasty numbers.