Benjamin Esham

Quick impressions of Firefox Quantum

Mozilla made a big marketing push last month for Firefox Quantum, the newest version of Firefox. I’d been using Safari for a solid five years but decided to give Firefox another shot. A big reason was that I was juggling thirty or so tabs in Safari, which has horrible UI for dealing with that situation: the tabs far from the current one are displayed as stubs with no identifying icon or text at all.1 I was intrigued by eevee’s mention of the Firefox-only Tree Style Tab extension, which seemed like it might be perfect for me. (This extension replaces the usual horizontal tab bar with a vertical, hierarchically-nested list of tabs in the browser’s sidebar.) It turns out that I like the extension quite a lot, although it’s not a “can’t live without it” feature for me yet.

Switching browsers didn’t take too much time—I keep passwords in 1Password and bookmarks in Pinboard, so there wasn’t much to migrate. I do wish that Firefox could have imported the list of currently-open tabs and that it could have pulled my old Favorites into the Top Sites list. (I also wish that it had been easier to move the data for my browser extensions, like Stylish, but that isn’t Mozilla’s fault.)

My main complaint so far is how Firefox chews through my battery. This problem was severe until I installed an ad blocker; now it’s merely annoying. Battery life and performance are the top priority for Apple’s Safari team and that’s really been hammered home to me by using a different browser. If I switch back to Safari this is likely to be why.

Firefox has a more Mac-like interface now than I remember from the mid-2000s. Two things still stick out as non-native: the appearance of tall <select> elements and the lack of system text shortcuts.

On macOS, dropdowns will take up most of the available screen height before they start scrolling. When that happens, arrows are shown at the top and/or bottom of the list, pointing to the top and/or bottom, to indicate that there are more items available. Firefox makes these boxes much shorter and uses a scroll bar to indicate that there has been overflow. We can debate the merits of these two approaches but I don’t think the Firefox behavior is better enough to justify replacing the system-standard behavior.

Text shortcuts in macOS let you define short pieces of text that will, when typed, expand into other (presumably longer or harder-to-type) pieces of text. These are supported in all native text fields on macOS2 but they don’t work in Firefox. I really miss the ability to type “bbb” and have it expand into my email address.

Finally, one feature that I wish Firefox would outright steal from Safari: If you open a link in a new tab and then press Command-[ to go back, Safari will just close the current tab. This might sound weird but it makes total sense when you try it: it means that the behavior of Command-[ is now the same regardless of whether you opened a new tab when you navigated to the current page. You no longer have to remember whether you need to press Command-[ or Command-W to go back.

Mozilla employee (and IndieWeb guru) Tantek Çelik asked which CSS features people want to see next. Two that I’ve missed recently—things that are available in Safari—are CSS Initial Letter for fancy drop caps and CSS Backdrop Filter for attractively blurred backgrounds. These are, admittedly, minor features, though. I’m gratified at just how much functionality the leading browsers share these days.

  1. You can get a nice visual overview of your tabs in Safari by choosing View → Show All Tabs or pressing Command-Shift-Backslash. This shows you a thumbnail of each tab and groups consecutive tabs from the same domain. Inexplicably, though, you can’t rearrange tabs in this view, and the tabs’ “close” buttons are so small that I often accidentally click on something else instead. ↩︎

  2. These text shortcuts are supposed to sync between macOS and iOS but for some reason this is notoriously unreliable. ↩︎

Christmas in Rochester

Batteries

The only things I own that still take AA or AAA batteries are a wireless mouse and a pair of noise-cancelling headphones. My other devices either use proprietary batteries (like my camera) or don’t have user-replaceable batteries at all (like my phone and my laptop).

When I was growing up in the late 90s and early 2000s, I needed those standard-sized batteries for a bunch of things:

All of these are just functions of my phone now.

Another perspective on Twitter’s move to 280 characters

John Gruber is not a fan of Twitter’s recent change to allow tweets to be 280 characters long:

By doubling the character limit, Twitter has eliminated what made them unique. Yes, there were many trade-offs with the 140-character limit, both pros and cons. But one of the pros is it made Twitter unique. Twitter timelines now look more like Facebook — but Facebook is already there for Facebook-like timelines.

He quotes others, including J.K. Rowling and Stephen King, who are also down on the change. One of the uniquely appealing things about Twitter—especially, I think, to long-time users like Gruber—is the art of fitting a complete thought or joke into 140 characters. I enjoy writing with this constraint sometimes, and I definitely like reading well-done examples.

But here’s another way to think about it: Twitter is no longer an obscure forum for tech-industry early adopters. It has become a super-mainstream social network. The bulk of its users now are concerned not with crafting 140-character bons mots but with the ordinary, everyday sharing of information and opinions.1 For that application, the looser limit may be a boon. More characters mean room for more detail, more nuance, more subtlety on a platform that is rife with misinformation and clipped, tense exchanges. Does this mean people will begin to have more thoughtful conversations? Not universally. But Twitter admits that possibility now more than it did before, and for a site that is becoming an all-purpose public medium, I think the extra space could be a good thing.

(The elephant in the room, of course, is that Twitter voluntarily gives a platform to Nazis. In this context, the change from 140 to 280 is going to do little to cut down on abuse, and might well make it worse in some situations. Enforced terseness was causing some degree of social ill on Twitter, but it was nothing compared to the effects of Twitter’s refusal to address harassment in a meaningful way.)

  1. I’m talking about what Twitter is, not some notion of what it “should be.” ↩︎

TTYL, AIM

I haven’t used AIM in years. The last conversation I had with another human—not a spam bot or “aolsystemmsg”—was in 2012. Like a lot of people, I suppose, I got a smartphone in 2011 and never looked back.


When I was in fourth grade or so I was under the impression that a “chat” was when you sent an email to someone and they sent an email right back, because they were online right now! One of my mom’s college students, a guy named Chris, introduced us to AOL Instant Messenger in probably 1999. Compared to exchanging emails, this was a step further: it really felt like you were talking to the other person in real time.

Other parts of the country used MSN Messenger—presumably the same parts that drank “pop” and got their Girl Scout cookies from the other bakery—but AIM was ubiquitous in my school. Most of my free hours were spent in front of the computer and for most of those hours I had the AIM client (and later, Adium) open on the side. I rarely talked to my friends on the phone; it was all online and text-based.1 High school was a heady, hormonal time, which is why, fifteen years later, I still get a little thrill when I hear this sound:

Who’s this? A classmate, a friend, a crush, a secret admirer? Are they asking for homework help or spreading some choice gossip? AIM conversations never started with any subtlety. It was this mechanistic fanfare, every time.


Now instead of “instant messaging” we just have “messaging.” AIM profiles have been replaced with Facebook profiles. Status updates have taken the place of away messages, and who can really be “away” from the internet now anyway? Realistically, AIM has been irrelevant for a while now. It was the social glue of my formative years, though, and purely for nostalgia’s sake I’ll miss it.

  1. Still true today, although “online” no longer means “sitting in front of a desktop computer and monopolizing your parents’ phone line.” ↩︎

A summary of the versioning scheme of large companies’ iOS apps

New project: Microformats2 on a Map

A screenshot of the Microformats2 on a Map application.

Inspired by Homebrew Website Club, which I’ve been going to recently, I created a web app. Microformats2 on a Map reads webpages that have been marked up according to the microformats2 standard, extracts locations from them, and displays the locations on—yes—a map. You can try it out here.

The project isn’t complete yet; the UI is unpolished and nested microformats aren’t yet supported. See the GitHub project page for more caveats, usage information, and technical details. The source code is available there under the GNU GPL, version 3. Pull requests are welcome! Bug reports are also welcome but slightly less so.

Motivation

As part of my endless process of tinkering with this website instead of actually writing posts for it, I went back and added location data to all of my blog entries. Each one now shows the city and state whence it was posted. This information is marked up with the microformats2 h-adr standard to make it machine-readable.

After going through the effort of figuring out where I posted each entry from, I wanted to be able to see all of these locations on a map. It’s a form of gamification: I feel a sense of accomplishment in general when I post a blog entry, and seeing all of my posts laid out visually just reinforces that feeling. (Instagram used to have a similar feature but it seems that they’ve discontinued it… bummer!)

Same-origin woes

The same-origin policy bit me while I was making this. My original plan was to offer an interface where users could put in multiple URLs and then the app would retrieve each page and extract all of its locations. I was also hoping to make a completely client-side web app so that I could host a few static files but not worry about any server-side logic. But I realized that the same-origin policy would prevent a page hosted on my server from downloading pages from other servers.1

My solution was an awkward compromise. I added a mode in which the user could just put in some HTML and locations would be extracted from that. I also created a server with an endpoint that would take in a URL, retrieve it, and return its contents—the world’s simplest proxy. If someone downloads Microformats2 on a Map and runs the server, the client-side code detects that and offers the possibility to enter a list of URLs. (The pages are retrieved through this proxy, which is allowed by the same-origin policy since that server and the client-side code are coming from the same port on localhost.)

This solution adds a little bit of complexity but it allows me to host a copy of the application without being responsible for a server that could probably be made to DOS someone. It also provides for the ability—if you run the server piece—to map multiple webpages’ locations, which I think is much more useful than just mapping the locations from a single page.

Standing on the node_modules of giants

It’s been said that modern web development consists mostly of hooking together other people’s libraries. In this case, that’s totally true. I pulled in Leaflet for the maps, Leaflet.markercluster to gracefully handle markers that were visually close together, and microformat-node to extract Microformats data from HTML. The app uses OpenStreetMap for map tiles and OpenStreetMap’s Nominatim service for geocoding (turning addresses into latitudes and longitudes). My contribution was a paltry 255 lines of code on the client side and 32 for the server.

  1. It would work fine if the other server had the appropriate CORS headers set, but most sites don’t (and I think this is the right default for servers). ↩︎

Kibibytes are silly and we should all use them

The kibibyte and mebibyte and their ilk are ridiculous. Introduced in 1998, these units are related to each other by factors of 1,024, a number which is almost, but not quite the same as 1,000, the basis of the metric system. The only reason these units exist is to work around the ambiguity of some people using “kilobyte” to mean 1,000 bytes and others—understandably but unwisely—using “kilobyte” to mean 1,024 bytes. The sole advantage of the newfangled binary-based units is that they’re unambiguous.

For that reason, though, everyone should measure things in kibibytes, mebibytes, and so on when at all possible. After a decade or two of such sanity maybe we’ll be able to ease back into using “kilobyte” when we mean “kilobyte” and not have to worry about being misinterpreted.

Listing the last person who committed to each branch in a Git repository

Here is a command that will list all of the server branches for the current Git repository, ordered from least recently edited to most recently edited, and with the latest author shown for each:

git branch -r --sort=creatordate \
    --format "%(creatordate:relative);%(committername);%(refname:lstrip=-1)" \
    | grep -v ";HEAD$" \
    | column -s ";" -t

If the column command is not available on your system,1 you can replace it with

    | sed -e "s/;/\t/g"

for a similar effect. Note also that you will need Git 2.13 (released in May 2017) or later.

Using the Jekyll repository as an example,2 the output will look like

6 years ago             Tom Preston-Werner  book
4 years, 4 months ago   Parker Moore        0.12.1-release
4 years ago             Matt Rogers         1.0-branch
3 years, 11 months ago  Matt Rogers         1.2_branch
3 years, 1 month ago    Parker Moore        v1-stable
12 months ago           Ben Balter          pages-as-documents
10 months ago           Jordon Bedwell      make-jekyll-parallel
6 months ago            Pat Hawks           to_integer
5 months ago            Parker Moore        3.4-stable-backport-5920
4 months ago            Parker Moore        yajl-ruby-2-4-patch
4 weeks ago             Parker Moore        3.4-stable
3 weeks ago             Parker Moore        rouge-1-and-2
19 hours ago            jekyllbot           master

Motivation

My most recent project at work had several contributors from multiple teams. I took it upon myself to periodically prune our branches, which meant that I needed to know who was responsible for each branch. BitBucket didn’t seem to show that information anywhere so I rigged up this command.

(By the way, I highly recommend GitUp for macOS if you’re interested in a novel way of visualizing your branches:

A screenshot of GitUp.

Be sure to turn on the options to show stale branch tips and remote branch tips.)

How it works

The git command lists all of the branches on the server,3 ordered from least recently edited to most recently edited. For each branch, it prints the relative timestamp of the latest commit; the name of the author of the latest commit; and the branch name. The grep command removes the “HEAD” pointer from the list, since it’s probably just pointing to one of the other branches in the list and we don’t need to show that branch twice. Finally, the column command puts the information into a nice tabular form.

  1. column is part of BSD, so it’s available on macOS. It’s available under Ubuntu if the “bsdmainutils” package is installed, which it seems to be by default. ↩︎

  2. I’ve omitted some of Jekyll’s branches for brevity. ↩︎

  3. To be precise, it lists all of the remote-tracking branches. If your local copy of the repo is up to date then this is the same as “all of the branches on the server.” ↩︎

What I believe

Sarah Kenzidor recently said, “Write a list of things you would never do. Because it is possible that in the next year, you will do them. Write a list of things you would never believe. Because it is possible that in the next year, you will either believe them or be forced to say you believe them.” Well, we’re almost over the line, so now is as good a time as any.

I reject Donald Trump as President of the United States. (Later today he will be the President—I don’t dispute that—but his sneering disregard for the formal and informal rules of the office make him unfit for it.)

I reject authoritarianism and fascism.

I reject Trump’s contempt for the free press.

I reject the supremacy of cis, straight white men, even though I am all of those.

I reject the notion that anyone is not a “real American” because they are well-educated or well-off or liberal or live in a city.

I reject lying, whether shameless or subtle. I reject gaslighting. I reject the idea that truth is a meaningless concept. I reject anti-intellectualism. I reject climate-change denialism.

I reject the Electoral College. I reject our “first past the post” voting system. I reject the two-party system that they enforce. I reject the voter suppression that may have helped Trump to win. I reject the idea that Republican Party unity is more important than the health of the country.

I reject intolerance. I reject the idea that intolerance is an opinion as valid as any other.

I reject the assumption that a free society has capitalism as its core. I reject the notion that unfettered capitalism is even compatible with free society. I reject letting “the market” determine people’s health-care options, or their fates.

I reject racism. I reject bigotry. I reject sexual assault.

I refuse to accept that humanity is no better than this. I know that—eventually—we will do better.