#!/bin/lsh

PDX JS Admirers Lightning Talk, 2015.10.28

It is, apparently, possible to prepare a talk from scratch in nineteen minutes, if it's a five-minute lightning talk and there happens to be some time free in your meetup's lightning talk session. Here is a transcript-like document of one I just gave at pdxjs about a couple of semi-obscure but highly useful things in the Javascript universe:

Javascript Heredocs!

There is a nasty rumor going around that Javascript doesn't have heredocs. This is totally false, although I'll admit the syntax is a bit odd and there's a small bit of glue needed:


    function hereDoc(f) {
      var s = f.toString();
      return s.slice(s.indexOf("/*")+2, s.lastIndexOf("*/"));
    }
    
    console.log(hereDoc(function () {/*
    My name is:
          'Leander'
          (lsh.io)
    
    And I say Javascript does so have
    these "heredoc" things.
    */}));
    

Output, when run:


    My name is:
          'Leander'
          (lsh.io)
    
    And I say Javascript does so have
    these "heredoc" things.
    

Before you freak out and run away, ask yourself: when you're writing a prototype and sticking handlebars templates inline, wouldn't you rather type this than make a whole separate script tag with its own id and type="text/x-handlebars-template" cruft? You can even have lexically (well, function, this is Javascript) scoped templates.

Server-Sent Events and EventSource

EventSource (MDN, WHATWG) is a dead-simple method of getting push event notifications in the browser using a reasonably well-supported (Google for polyfills - many exist) browser-native API. Here's a hopefully self-explanatory code sample:


    var es = new EventSource('/ev.es'); // your URL here
    es.onmessage = function(e) {
      console.log(e.data);
    };
    es.onerror = function() {
      console.log('ERROR!');
    };
    

What makes this worth paying attention to over something like WebSockets is how dead-simple the protocol is: it's just a formalization of long-polling (with attendant benefits in the browser like the browser being able to garbage-collect old events instead of having the ever-growing long-poll 'document' eat more and more RAM).

Even better, the transport format is even more stupidly simple (in fact, the following snippet is actually the content of a static file I served from lsh.io's static web server for my 'demo'):


    id: 1
    data: this is event A
    
    id: 2
    data: this is event II
    data: and it has two lines
    
    id: 3
    data: this is event three
    

That is, the above snippet represents three events, with ids of 1, 2, and 3 respectively, and corresponding data fields. The whole format is just field:value, blank lines delimit events, and if multiple lines in an event have the same field, their values get concatenated together. Even better, if the connection drops, the browser will reopen it automatically and send a header telling you what the last id it saw was, allowing your server to quickly figure out where in the stream to pick up.

All put together, this means you can build a push-notification backend in maybe a dozen lines, can have it go right through your load balancer like it's any other GET request, and have an event stream format that's easy to consume from non-browser clients.

Coming soon: blog posts on my remote clipboard and chat systems written in < 500 lines of bash that use the format internally.

Unpacking Browser Packaging

I don't only blog here. Here's a recent post of mine on the Cloud Four company blog: Unpacking Module Bundlers.

Static Accessibility and Generative Accessibility

For the first time in a while, I'm setting up bluetooth tethering on a new machine (unlike wifi tethering, I can leave a bluetooth connection up all day long without noticeably affecting my phone's battery life). For reasons outlined here, I do this using short snippets of shell script to bring the bluetooth connection up and down. In the past, this meant calling the pand CLI tool, but that's changed in the latest version of bluez. As found in the Arch Wiki's guide:

$ dbus-send --system --type=method_call --dest=org.bluez /org/bluez/hci0/dev_AA_BB_CC_DD_EE_FF org.bluez.Network1.Connect string:'nap'

Compare this to the previous pand invocation:

# pand -E -S -c AA:BB:CC:DD:EE:FF -e bnep0

Now, I don't know what the logic behind changing to a pure-dbus interface between bluez 4 and bluez 5 was. Presumably there was a good reason, but at the same time a few important things have been lost:

It's most likely that the reasoning behind this change is that the dbus interface is better suited for building GUI bluetooth management applets, which make bluetooth functionality accessible to the nontechnical masses. In essence, we're seeing a change from generative accessibility to static accessibility.

Wait, what? Let me 'splain:

Static accessibility is what is typically meant by 'it just works', or the 'appliance' approach. There is a single task and way of performing the task the tool implements. No additional capabilities are possible, but the ones provided are easy to use and foolproof in operation. It's accessible because it's easy to pick up and use without learning anything, and static because it can be used for only one task.

The new dbus interface represents the static approach: it's a low-level interface intended to be hard-wired into a certain type of larger system. It has definite ideas about the kind of use-case (making a bluetooth icon in a system tray able to control bluetooth connections). The main concern is that there is a very specific experience that needs to be provided, and anything not on the critical path to creating that experience is of secondary importance. Hence "static": The tool makes a capability accessible (as in not requiring training or documentation) in a specific way, and only that way.

Generative accessibility is a major component of what's often referred to as 'hackability' or 'the unix way'. The tool provides a certain ability without providing any policy of how to use that ability (e.g. a flathead screwdriver allows applying torque to opposite sides of a slot, a capability that can be used either to turn screws or crack open the case of a malfunctioning appliance), and provides the ability through a combination of documentation and an empirically discoverable interface the ability to be easily used in novel ways in conjunction with other tools. It's accessible because it's easy to learn to use, and generative because it can be used in creative and unexpected ways.

The old pand approach represents the generative approach: rather than providing an internal component for a certain experience, it provides a tool for controlling bluetooth network interfaces (this is a similar idea to the separation of mechanism and policy principle). The tool is designed to make the typical operations of bringing up and taking down an interface for a specific device simple, and is well (or at least basically) documented. This approach is generative because it enables creativity and use cases not forseen by the providers of the tool. In this case, pand could be used to build both GUI bluetooth connection managers, and the small shell script that lets me control tethering on my OpenPandora with a few quick keystrokes, all without having to be a developer on either the bluez project or Gnome/Android/KDE.

(As a sidebar, I'll note that in this specific case, simply documenting the dbus API to bluez properly would change things significantly, restoring much of what was lost by the elimination of the pand tool.)

If the value judgement I'm making here isn't already obvious, let me spell it out: for a project like bluez, Generative Accessibility is superior to Static Accessibility. Static Accessibility can be easily built on top of Generative Accessibility, but not vice versa. It's the easy hackability of tools like pand that has made Linux what it is today, and there's no defensible reason to undo the layered architecture that makes that hackability possible in the myopic pursuit of one particular type of user experience.

PLUG Advanced Topics: Living Desktop Free

Tonight I've given a talk at the Portland Linux User Group's Advanced Topics meeting on using Linux without a desktop environment. Slides for the talk, containing links to all mentioned resources, can be found here.

About LSH

Leander Samuel Harding is a full-stack web developer with over fifteen years of experience working on consumer-scale web applications. In that time, he has worked on a wide variety of projects and platforms, including:

He is a graduate of the Northeastern University College of Computer Science. In his spare time, he plays tabletop games, tweaks his Linux installs, and replaces various things with very small shell scripts.

Background imagery on this site by Jay Mantri.