OSX Terminal Notifications

I recently found myself task-switching quite a bit, and losing track of longer running programs in the process. I went looking for a low effort way to get Terminal to display a notification when a program exited while terminal (or the running shell session) was in the background. I quickly found a solution in two parts:

terminal-notifier

terminal-notifier is a Mac App that provides a simple CLI to create notifications in notification center. Pipe text in, get a notification out. Easy.

Now for the shell integration:

zsh-notify

zsh-notify is a plugin for zsh that supports terminal-notifier, as well as growl (for ye olden MacOS versions ;)).

Configuration

There’s really only one option to configure, and that’s the notification timeout. You set this as an environment variable:

export NOTIFY_COMMAND_COMPLETE_TIMEOUT=5

This will create a notification for any task that takes longer than 5 seconds. The default is 30, which is way too long for my twitchy, app-switching fingers.

Cool, but I don’t use zsh…

Well, you should give it a try!

I don’t use bash any longer, but with terminal-notifier it’s super easy to fire them off ad hoc:

./run-a-long-program && terminal-notifier -message "Finished run-a-long-program"

And voila!

terminal-notifier screenshot

But seriously, you should try zsh.

URI, URL, URN: UR Confused

I recently caught myself using URI and URL interchangeably, and realized I couldn’t explain the difference. Never one to pass up a learning opportunity, I did some digging.

URL

URL stands for Uniform Resource Locator. Here are some examples of URLs:

awesomephotos.com/cats/grumpster.png
awesomephotos.com/cats/grumpster.gif
awesomephotos.com/cats/grumpster.jpg
awesomephotos.com/cats/grumpster.psd

The URLs specify a specific type, version or representation of a resource. In this example, they each specify an image type: GIF, PNG, JPG or PSD.

URI

URI stands for Uniform Resource Indicator. A URI is a URL that doesn’t specify a specific representation. In the example above, the URI for all those cat pictures is:

awesomephotos.com/cats/grumpster

A URI indicates what resource is desired, but not a required type/representation of that resource. So a URL is a URI, but a URI is not a URL. Make sense? :)

At this point, you may be wondering to yourself, “Ok, I get it, but how is this distinction useful in the real world?” The answer is:

HTTP Content Negotiation

HTTP Content Negotiation is a mechanism built into the HTTP/1.1 standard that allows for a particular resource to be represented multiple ways, to support multiple clients or use cases.

There are different ways content negotiation is executed, but they all essentially utilize HTTP headers and status codes to communicate about what resources the client wants and the server has available. This is quite extensible, and was intended for many different use cases, including specifying versions of a resource. Cool, right?!

Read the Content negotiation article at MDN for more information.

Um, a real world application, please?

Ok! One example of HTTP content negotiation in the wild is browser support for different image formats. A website can have a GIF and PNG version of an image, and the browsers that support PNG will get PNG, otherwise they can get the GIF image. This is most apparent with IE < 9, where the PNG format is not properly supported.

In fact, If you've ever sent an HTTP request with the 'Content-Type' header, you've engaged in content negotiation! You've essentially told the server, "I want the JSON/XML/HTML representation of this resource."

Wait, wasn't there another acronym?

Ah, yes: URN, which stands for Uniform Resource Name. A URN bears much similarity with a URI, but uses a specific scheme, urn:, instead of http: or https:.

Essentially, URNs were supposed to be a stricter, persistent version of URIs. The standard was eventually deprecated in favor of the more generic URI syntax.

Further Reading

(Don’t) Lie to Me: A Story About Naming Things

Bob and Sarah are both programmers working on the same project. This project interacts with a popular HTTP service: “WibblyWobbly.”

The WibblyWobbly API is designed for simplicity. Interacting with Wibbles and Wobbles, the two main objects in the WibblyWobbly system, looks identical:

HTTP Method URI
GET /{wibbly_id}
GET /{wobbly_id}
UPDATE /{wibbly_id}
UPDATE /{wobbly_id}
DELETE /{wibbly_id}
DELETE /{wobbly_id}

Being good programmers, and wanting to follow best practices like the Single Responsibility Principle, Sarah and Bob decide that they should separate the code that makes HTTP requests from the application code that accesses that data.

In designing their service client, they decide to make more explicit the difference between Wibbles and Wobbles. Rather than have more generic methods:

WibbleWobbleClient#get(object_id)
WibbleWobbleClient#update(object_id, attributes)
WibbleWobbleClient#delete(object_id)

They implement the following interface:

WibbleWobbleClient#get_wibble(wibble_id)
WibbleWobbleClient#update_wibble(wibble_id, wibble_attributes)
WibbleWobbleClient#delete_wibble(wibble_id)
WibbleWobbleClient#get_wobble(wobble_id)
WibbleWobbleClient#update_wobble(wobble_id, wobble_attributes)
WibbleWobbleClient#delete_wobble(wobble_id)

Each of these methods looks different, but really ends up calling the same URIs for similar actions. This makes sense, because the client is attempting to provide an appropriate abstraction to the application, but at this point in the process they are just trying to get something working with the least amount of effort.

A long time from then, in a funding round far, far away…

Bob notices that their application, SuperWibbWobblizer, is deleting Wobbles instead of Wibbles. When he begins debugging, this seems impossible:

“Even if the ids were somehow mixed up, there are totally separate methods for deleting Wibbles and Wobbles!” he says to himself, “If that were the issue, I’d expect the client to throw an exception.”

After hours of frustrating pair programming, Sarah remembers that tucked away inside their client library, the URLs for deleting Wibbles and Wobbles are the same. This means that their previous assumptions about the behavior of their service client were incorrect, and it has been blissfully passing through Wobble IDs as Wibble IDs.

Defend Against Lies of Omission

Bob and Sarah realized that this situation could have been avoided in different ways. They could have documented that the client was a simple pass-through that provided no validation or taken the time to implement those checks up front. They also realized that they did no negative testing along the way, at any level, to ensure that they were protected against this situation.

Building software is about choosing between tradeoffs. In Bob and Sarah’s case, simply documenting that no validations were provided would have taken a trivial amount of time, and would have at least prevented confusion when they were debugging the issue. This may have been the way to go for them.

The lesson here should be to think ahead when designing an interface of any sort. When you name any method or function, you’re defining an interface to a future engineer. Think carefully about what your class, function or variable name might convey to a future engineer reading your code. Weigh the cost of coding defensively against a strategically placed documentation comment.

Empathize with that frustrated future engineer. When they finally realize the miscommunication that has taken place, they may just think,

“Dude. Don’t lie to me…”

More on naming things

VirtualBox Hates Sendfile

I’ve begun using Vagrant with Virtualbox for Web Development, specifically for Rails development. This allows me to spin up an environment as close to production as possible, and it keeps my host system clean from various projects’ clutter. It’s quite lovely, and I’ll definitely devote a separate post to that topic. However:

Recently, I ran into an issue with Sendfile and Virtualbox’s shared folder support. It seems that the use of Kernel sendfile by either Apache (both debian and centos flavors) or Nginx to serve static files doesn’t work if you update those files at all once they’ve been served. Needless to say, this doesn’t work for doing any Javascript development…

After digging, the fix is simply to disable sendfile support in your HTTP server of choice. A quick search for ‘sendfile’ in your httpd.conf, apache.conf or nginx.conf will reveal an ‘On/Off’ toggle:

#
# EnableSendfile: Control whether the sendfile kernel support is
# used to deliver files (assuming that the OS supports it).
# The default is on; turn this off if you serve from NFS-mounted
# filesystems. Please see
# http://httpd.apache.org/docs/2.2/mod/core.html#enablesendfile
#
EnableSendfile off

The solution to the issue can be found in the VirtualBox forums: http://forums.virtualbox.org/viewtopic.php?f=1&t=24905

More info about Sendfile can be found in the Apache documentation: http://httpd.apache.org/docs/2.0/mod/core.html#enablesendfile

Sublime Text 2 Updated

Sublime Text 2 has been updated to include a Command Line Utility, subl!

Here’s a few gotchas:

  1. Be sure to specify the ‘-w’ or ‘–wait’ option in your git config.
  2. Currently, Sublime tries to keep folders opened from the command line in the same window. This is different behavior than TextMate, and I find it a bit obnoxious for searching and open quickly. To emulate ‘mate .’ behavior, use the ‘-n’ option to open the folder in a new Sublime editor window.

Sublime Text 2

TextMate users, meet Sublime Text. Its TextMate’s younger, flashier, cousin.

Don’t get me wrong, I love TextMate. It’s been the best native text editor on the Mac for quite some time. However, the message is clear:

Sublime to TextMate, “Anything you can do, I can [or likely will soon be able to] do better.”

Pros

  • Open Quickly kicks the pants off of TextMate’s ‘Go to File’. It’s faster, preloads documents, and allows you to jump right to functions and lines within files.
  • Split Panes! While I haven’t actually used this feature yet, I can recollect situations where it may prove useful. For example, jumping between models and schema.rb in rails apps…
  • Uses tmBundles for syntax highlighting and tmThemes for color schemes. Just copy and go.
  • You can configure just about anything, including hiding the obnoxious mini-map.

Cons

  • No CLI binary. This means I’m still in TextMate for my git commits… :/
  • Doesn’t do as well as TextMate with file reloads from outside Sublime. I’ve run into a couple instances where I’d switched git branches and Sublime didn’t update the open files.
  • The mini-map is weird. This is Sublime Text 2, not Starcraft II. Let’s be real guys, on my 15″ MacBook, I’ve got code over there.

Granted, it’s in alpha, so it’s bound to be a little flaky. However, it’s under active development and getting better all the time. I’ve been using it steady for a few days now and I find myself spending more time in Sublime than TextMate.

Homebrew & git +bash_completion

Install Homebrew

Full install instructions are available here: https://github.com/mxcl/homebrew/wiki/installation

ruby -e "$(curl -fsSLk https://gist.github.com/raw/323731/install_homebrew.rb)"

Install Git

brew install git

Enable Bash Completion

cp /usr/local/etc/bash_completion.d/git-completion.bash ~/.git-completion.sh

Add the following to ~/.profile

source ~/.git-completion.sh
PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '