Abesto's woes

Adventures in LAMP-land and beyond

Dev Environment as Software - SSH and Aliases

In Mindset: Your Dev Environment Is Software I showed several small examples for how you can optimize parts of your development workflow, just by realizing that the stuff you’re using to develop is also software. (Yes, this is trivial, but stating it explicitly leads to interesting results.)

Today I’d like to give a detailed explanation of how a biggish refactor of your workflow might look like. Case in point: SSHing to nodes by ip, by hostname, by EC2 instance id, by Chef role, as different users. Fast.

Mindset: Your Dev Environment Is Software

If you write software for a living (or just for fun), you’re probably using a bunch of other pieces of software to help you get your job done.

At that moment, the developer was enlightened.

I’m going to rant a bit about how this realization should change your life. What realization? That the thing you are working on and the thing you are working with are of the same substance. You can, and you should, use the same tools to improve both.

CI for a Coding Dojo

Suppose you’re hosting a coding dojo and want to do continuous integration; that is, you want to always show the state of the tests while editing code. Here’s a pretty stable solution I came up with after a few tries.

Why I Left University

Note that there’s no “… and why you should too”. This post is decidedly not doing a bunch of things:

  • It’s not arguing for or against going to / finishing university
  • It’s not calling for arguments on either side to help me make a decision (it’s all done and in the past)
  • It’s also not a general statement about anything at all.

This post is instead the story of my very specific case. These are true for me, they may not be true for you. I share all details openly, recognizing that some of you don’t agree with my decision. My goal is also not to convince you about anything; I’m explaining my thinking and feelings so you may better understand, and if needed, more easily accept my decision.

Warning: it’s a really, really, really long post. It gives all the exposition needed to understand me (in this regard). I don’t mind if you don’t read it, but if you want to understand, then please do. These are the arguments I considered, how I weighed them, and how I came to the final conclusion.

The Prototype With the Split Personality

A tragedy in one act.
Sub-title: the case-insensitive file system strikes again.
Location: an OSX development machine.

Dramatis personae:

  • Node.JS, a lightweight webserver
  • HFS Plus, a file system that doesn’t care if something’s up or UP
  • alpha.js, an innocent-looking file with a single prototype
  • Developer, a simple monkey

Lights, camera, action.

Enter all.

alpha.js: exports.Class = function() {};


var alpha = require('./alpha');
var AlPhA = require('./AlPhA');

HFS Plus: Hah, those both point to the same file!

Node.js: But they’re still different modules. The names are not the same. 'a' != 'A'!

Developer (not having heard the previous two talking):

var obj = new alpha.Class();
console.log(obj instanceof alpha.Class);
console.log(obj instanceof AlPhA.Class);

Node.js: true, false

Developer: WTF? (commits suicide)


Journaling for Geeks

There’s a whole lot of material on the ‘net about why you should keep a diary, so I’m not writing about it. I’m writing about how I’m planning to do it, starting today. There are a few conditions the medium needs to satisfy:

  • Be software, obviously :)
  • Be plain-text
  • Have a nice-looking version I can read later
  • Be synchronized online
  • I want to have a lot of control over the data (no submitting entries in a web form)
  • Be encrypted

Plain text + nice output means some markup language. I decided to go with Markdown, but anything works. With regard to synchronization: there’s a trade-off between convenience and privacy. On one end we have a public GitHub repo, on the other end is the server running in your basement. Dropbox (my choice) is somewhere in the middle. Encryption is easy, GPG already does it pretty well.

Show me the codez!

#!/bin/bash -x
if [ "$DIARY_SYMMETRIC" == "yes" ]; then
cp "$file" "$tmp" && gpg --output "$tmp" --decrypt --yes "$file" && "$diary_editor" "$tmp" && gpg --output "$file" $encrypt --yes "$tmp"
rm "$tmp"

This creates a temporary file, decrypts the diary overwriting the temporary file, opens the decrypted file with an editor, and once that’s finished, re-encrypts the file into the original location, removing the temporary (decrypted) file in the end. Note that at no point does the plain-text version exist on Dropbox.

Getting started

  1. Paste the above code into an executable text file on your PATH
  2. Create an (empty) encrypted file at $DIARY_FILE (see below)
  3. Run the script
  4. There is no step 4

I don’t like vim :(

There are some points you can customize in your .(|ba|z|c)shrc by exporting variables:

  • DIARY_EDITOR: the binary used for editing the decrypted journal file
  • DIARY_FILE: location of the encrypted diary file; note that you need to create the first version manually
  • DIARY_SYMMETRIC: if set to "yes", gpg will use symmetric encryption instead of the usual keypair-based encryption

For example:

export DIARY_EDITOR=/Applications/Mou.app/Contents/MacOS/Mou
export DIARY_FILE=$HOME/Dropbox/diary.gpg

Emacs can do all that and more!


I want more features!

Great! I’m looking for an excuse to make this a terribly over-engineered shellscript, complete with a GitHub repository and multi-page README file. Tell me what you need! Some crazy ideas:

  • Pluggable sync systems (anything that’s mounted to the local FS, git, svn, scp, rsync)
  • Pluggable encryption systems (no encryption, GPG/keypair, GPG/symmetric, no idea what else)
  • Create the empty encrypted diary file if it doesn’t exist at startup (ok, this one is not so crazy)
  • Fall back to EDITOR if DIARY_EDITOR is not set

An Intro to Lens With No Theory

Control.Lens is an awesome Haskell library by Edward Kmett that makes working with complex data-types a joy. That might sound boring, but consider updating a deeply nested value. Which of the following do you prefer?


-- With pattern matching
updateZ :: Alpha -> (Int -> Int) -> Alpha
updateZ a@Alpha{beta=b@Beta{gamma=g@Gamma{z=old}}} f = a{beta=b{gamma=g{z=f old}}}

-- With field accessors
updateZ' :: Alpha -> (Int -> Int) -> Alpha
updateZ' a f = a{beta=b{gamma=g{z=new}}}
                where b = beta a
                      g = gamma b
                      new = f $ z $ gamma $ beta a

-- With Control.Lens
-- There's some cheating going on, this is just here to show the difference.
-- See below for complete examples.
updateZ'' :: Alpha -> (Int -> Int) -> Alpha
updateZ'' a f = a&beta.gamma.z %~ f

If you picked number three, read on. First, here are two programs for actually running the above examples, so you can poke at them. Then we’ll examine parts of the tutorial at lens.github.io (which is totally great), look at some generalizations and finish with some extra coolness. You can also find some useful links at the bottom.

Recurring Madness: Functional Bash

There are some ideas that have a will of their own. All the mighty strength of these wills is focused on a single goal, with a narrow-mindedness comparable only to a surgical laser. That goal is to become reality. You know this is so because these crazy stupid ideas keep happening again and again to different people.

One of these ideas is functional programming in bash.

PlayStation 3 Jack Audio Output

Waiting for the PS4 I realized that (1) it’s still a while until it arrives, (2) it’ll probably be a bit expensive at first and (3) there won’t be a huge number of games for it. Conclusion: had to buy a PS3, and play some things I missed.

Having been a PC-only gamer, I had a screen and great headphones. Note: not a TV; a computer screen with no speakers built in. I asked about the video, and got a DVI-HDMI adapter. Simple. Surprise: I noticed after all else was et up that there’s no jack output on the thing. There are plenty of other outputs though. If you want 5.1, you can use the HDMI or optical digital output. If you want 7.1, you need to use HDMI. I just wanted my headphones to work, so I used the simple RCA output (which supports only stereo).

Django REST Framework: Add Id in HyperlinkedModelSerializer

from rest_framework import serializers
from models import MyModel

class WithPkMixin(object):
    def get_pk_field(self, model_field):
        return self.get_field(model_field)

class MyModelSerializer(WithPk, serializers.HyperlinkedModelSerializer):
    class Meta:
        model = MyModel

If that’s enough for you, glad to be of service. Some context follows, and also a way to wrap JSON top-level list responses in a JSON object.