Panic recently released Status Board, an iPad app for creating digital panels with information about your organization. They include many kind of widgets (graph, table, calendar, feed, feed counter...) and include a time widget with either a clock or digital face. While it looks nice and well designed, it takes quite a bit of space, especially if you want to show more than one timezone on your screen.

I work in a team distributed across multiple timezones. To show everybody's timezone on our Status Board using the default Time widget would require about an full row in landscape orientation. Also, we would have to remember who is traveling where at anytime. Fortunately, Panic included a DIY widget, which allow users to include a re-sizable view on an arbitrary HTML page.

So I created nTime1, a simple webpage that you can embed in Status Board, which shows a name and the time for a given GMT offset. It's just a webpage with a bit of javascript that updates the time every 999 milliseconds, but I hope you'll find it useful.

Here is a example of a few nTime widgets side by side with a couple of default time widgets:

StatusBoard time Widget vs nTime widget
(See even more nTime widgets on flickr)

You can create your own nTime widget by going to niconomicon.net/statusboard-ntime/nTime/ (preferably on your iPad). There will be a simple form that asks for the location's name and the GMT offset2. Click on the button, and the page will show you the name and time on a white background3. Then, just tap on the "Open in Status Board link" to add it to your StatusBoard4.

As it is "just" an HTML page, any text, even with unicode characters will work, even right to left script like Arabic (though emojis seem broken5).

Examples:

Caveats:

  • For some reason, in status-board, if there is a "." in the page's address after the last'/', the document.location won't return anything after that last '/', so don't use Washington D.C. but rather Washington DC for the name part.
  • The widget doesn't support DST. Thus, if the timezone you are interested in is afflicted with DST, you'll have to update the url when they stop / start saving daylight again.

Of course, the source is available on github: nTime on github. It is licensed under the Creative Commons BY-NC-SA (3.0): © Nicolas Hoibian 2013 CC BY-NC-SA 3.0.


  1. The n stands for anyTime and namedTime. 

  2. In the examples, I used the timezone offset timeandate.com, which tells the nominal offset, if there is DST and then the actual offset. 

  3. The black background, gradients and font in the screenshot are transformations applied by Status Board. 

  4. By virtue of being black and well away from the top, that link won't show on your statusboard. 

  5. Emojis don't abide by the font-size property on the ipad, so they show, but so tiny as to be unreadable. 

TL;DR: this is the nicest computer I've used. It can handle Emacs, Eclipse, XCode & Virtual Box all at the same time, has enough power to transform 400+Megapixels images into displayables, and it can play Diablo 3 @ 30+fps. It is light enough to carry all day in a backpack.

Context

My previous computer was a late 2008 MacBook Air, 13", Core 2 Duo 1.86 GHz, 2GB RAM, 128GB SSD and an nVidia m9400 GPU. I bought it following Will Shipley endorsment, and it was the nicest machine I had the chance of using1. Actually, most of Will Shipley's review still holds. The exceptions are the port trap door, which is gone, and the fan exhaust/intake, which is now more toward the back than the bottom, so you can use the laptop on soft surfaces2.

I had been needing a new machine since the summer 2011, as mine had become too slow for my use. It was also prone to excessive heating (it would disable one of the core and throttle the other one way down), an issue in the tropics3 where it gets hot even with the aircon on.

After the meh MacBook Air updates when Apple switched to the Intel integrated GPU, this is the first generation which would have similar / slightly faster 3D frame rates than the 2008 models. I couldn't wait until the next CPU revision to get faster frame-rates as my 2008 model was painfully slow, and when I purchased it in September 2012, Haswell was most of a year away.

As my laptop is my only 'PC' and I became addicted to coding on the go, I needed something light yet powerful. My previous machine being a MacBook Air 13", that was the upper bound on weight and size. So the MacBook Pro, even 13" Retina, were out. For power, I mostly maxed out on spec (Core i7 2.0 / 8GB / 256 GB ), for portability I took the 11" model. As fast as a same gen 13" MacBook Air, but smaller and lighter (and, yes, less pixels and battery life than the 13").

Using it for work

These days I am mostly a Django web developer for Catalpa International and I do a little bit of Java & Objective-C on the side.

Some tasks involve a little bit of number crunching when importing/exporting data as json/csv/pdf, some module compilations for each virtual environment, a tiny postgres db instance, and sometimes a Windows 7 VM running in VirtualBox.

With the previous laptop, the fans were running audibly all the time, and became noisy as soon as the CPU was pegged for a minute. Sometime the fans wouldn't come down even after a while of low CPU usage. When doing number crunching, compilation or running VirtualBox, the system would become sluggish.

With this 2012 vintage, the fans come on when the compilations runs for more than a few minutes, and they are barelly audible. Emacs and Eclipse feel snappy4, and even module compilation and the odd Homebrew packages compilations feel fast. And the system stays responsive at all times.

256GB of SSD is fast and big enough for the iOS, Java and Python dcosets, alongside multiple iOS simulator versions. And there is still enough space for my personal stuff5.

Display and real estate

The internal screen is very nice. The pixel density feels high, and the old 1280x800 13" display became hard to look at6. I have no problem of ghosting or any color issue (eyeballing it).

The native resolution of 1366x768 feels good enough most of the times. On the move, it is big enough for coding with Eclipse and Emacs, photo fiddling in Pixelmator, and photo viewing in iPhoto. The only app I have some trouble with when not connected to the external display is Espresso, which is multi-window based, where it helps a lot to have the CSS and the live preview of the page that use it open and visible at the same time.

As, thanks to my former CERN colleagues I also have an iPad, I can have an external screen with the neat Air Display. It is mostly fast enough to leave a Colloquy window on it7.

To arrange windows, I use Divvy which allows to re-size and re-position a window by a simple shortcut or dragging over a grid 8. I also use Zooom/2 for moving and resizing windows outside the grid.

At the desk

Using it on tables and desks by itself is fine. The angle of the base make it nice to use, and you are not at risk of cutting your wrist on the edge. Of course the screen is small, so you'll have to crank your neck a bit if you're tall.

At the "office", I like to use an external keyboard and mouse (so I can improve the angle at which I see the screen). With the old 13" the pixel density was low enough that I could prop an Apple Bluetooth keyboard above the trackpad and still easily read the Terminal with the Homebrew theme (monaco 10pt green-on-black). Not so on the 11". The pixel density is high enough that this font is too small at arm length. So, until I had an external screen, I had to switch to the default terminal theme (12pt, black on cream).

MacBook Air usage - Desk | Rarely that clear.

With an external screen (Dell 24" @ 1920x1200), it is a very nice workstation, with plenty of real estate. Enough space and power to run Eclipse, Emacs, Firefox with way too many tabs, XCode with the Simulator open and a few python process in the Terminal without breaking a sweat. Using Espresso becomes much less challenging, almost a pleasure.

Again, Divvy is a great help to re-size and reposition all the windows when switching from the internal-only to the internal + external display.

Portability

MacBook Air usage - Bus

It is a very small and light laptop. I regularly use it on the bus when I have to go somewhere that is more than 20 minute away. I usually find a seat and slide it out of my backpack; open it all the way (otherwise the vibrations and bumps do it for me); fiddle with the iPhone to enable Wifi tethering and I'm online9. I can even chat with my colleagues 8 time zones away.

MacBook Air usage - Plane | Editing this very review on a Geneva-Nice flight.

In the planes, it comfortably fits on the food tray, better than the 13" did. As it fits in a smaller bag, it is easy and practical to put it "under the seat in front of you", which make it easier to pick it up once "the seat-belt sign is off".

It is delightful to write code and do some commits on the go and even more so to push some commits from the bus.

When abroad for the week-end, I usually bring the laptop with me while walking around, and barely notice the weight in my backpack.

I did not test the battery scientifically, but it seems to last around ~4 hours of coding in python/espresso/firefox + surfing the web with Wifi on and Bluetooth on (but not used) and almost 2/3 brightness. Slightly longer with lower brightness and more conservative radio use.

Using it for fun

While my previous MacBook Air could not play 720p MKV movies for more than a minute before starting to drop frames, the new one handle 1080p MKV with no trouble on the external 24", and I don't notice the fans.

I don't play much video games, as my hobbies since I got the new laptop involves mostly photography taking pictures or Ikea furnitures (sometimes at the same time), but the new one can mostly handle Diablo III. I can get up to 60fps in windowed mode @ 1024x768 (texture high, everything else low/off). The framerate oscillate between 30 and 60 fps depending on the environment, but stays nicely playable when killing demons and running around. The fans will come on though.

This 30+ frame-rate is on the external screen with the internal display activated. The game is alone on the virtual desktop, and Mail, Colloquy, Eclipse, Emacs, Firefox and python and sometimes XCode are idling in other desktops. Closing these apps doesn't yeld any noticeable framerate improvement so I don't bother.

There briefly was a time when you could set the internal display to 1024x768 and D3 would recognize that as a fullscreen resolution, and you could play in full screen mode with the above settings + anti-aliasing at upper 30 fps, but the game doesn't offer/recognize that resolution anymore.

Final words

Recommendation: buy. This model is plenty fast and very light and compact. It is a joy to use, painless to carry around and a delight to use on the go.

What about the next generation model? As always with electronics, a new faster/lighter/longer-lasting model is around the corner. Also, 11" is the last size that does not have a retina model10.

For me this model was a sufficiently impressive improvement over my previous laptop that I will not regret not having waited for the next generation: faster CPU, faster GPU , faster storage11, better screen, much improved thermal management, better battery, smaller and lighter. All of which result into a laptop that is a joy to use.


  1. I also had a 12" iBook G4, and a 15" MacBook Pro. The iBook had the nicest keyboard I have used. 

  2. For example on a blanket or a mattress. 

  3. I was living in Dili, Timor Leste between March 2011 and July 2012 with my wife. 

  4. Except for Emacs when fly-spell is running. Then I feel a kind of drag or slight delay when moving the cursor around or typing. 

  5. My iTunes library with all the iPhone and iPad apps, music, books etc... My iPhoto Library with all the iPhone taken pictures. Diablo III. 

  6. Really. The pixels stood out, especially on text. A bit like looking at anon-retina iphone after a while with a retina iphone, but to a slightly lower degree. 

  7. There are however some slight artefacts and a noticeable delay between the new message sound + notification and said message showing up 

  8. I use Ctrl-Alt-d + 1 to 6, to re-position windows in either quarter or halves of the screen, and § for full screen. Repeat the last key press to position and resize the window on the screen where the mouse cursor is not. 

  9. Swisscom includes tethering with their infinity monthly plan, not as an extra option like say, orange france. 

  10. The trouble with "retina" is that it needs some strong GPU (see the MacBook Pro 13" and the iPad 3"), so a Haswell retina MBA would be nice (retina is nice), but might have similar or lower frame-rates when scrolling web-pages or excel files, and especially in games due to the extra megapixels to animate. My guess is, if you need a strong yet light laptop now and don't do much gaming, this generation is good. The screen already feels very sharp. 

  11. And bigger too, thought of course already mostly full. 

Once upon a time, back in June 2011 (last year) I was making my website for Displayator.com and using some bash scripts to make the pages link together (there was only about 3 pages). About the same time, there was a few discussions on HN about the Jekyll and Hyde static site generators. I discovered that Marco Arment had also open sourced its PHP static site generator.

They were using Markdown and a scripting languages, (respectively Ruby & Python) and I was thinking, do you really need PHP, Python or Ruby to generate a static blog? As I was already generating a website with a few lines of bash spread over a few scripts, I thought "How hard can it be?". Anyway, I needed a blog for my Displayator site. So I got to work with a few constraints and a bonus card:

  • use bash but no variables nor for loops.
  • Fit all the code in a single file.
  • Bonus card: I can use a pre-compiled markdown converter.

My objective was to generate something that could look like Tom Preston Werner's homepage (the creator of Jekyll).

So I got to work, and soon had something that could pass for a static blog generator, in less than 60 lines of bash, including the help outputs & comments. I took a look, and thought I could shrink it a bit, by using the ; and cramming a few more things on the same line. For geek points, I went down to 42 lines of bash, with a few precious new lines.

To keep in the theme of literary creatures, the result of this assemblage is named ___.sh, after Frankenstein's creature. It is currently used for the Displayator blog and is the most (only) watched of my projects. Yay!

A few month latter I added the generation of a full text RSS feed, and refactored a bit more to keep the length down at 42 lines.

Today, I renamed it from ___.sh to ___ for neatness' sake. Edit on 2012/05/29: restored to the previous name (___.sh) as ___ is not search-engine-friendly enough.

To be able to do so much in so few lines, ___.sh is basically a bash script generator written in bash. It will transform the output of ls into a bash script and then pipe it (|) back to bash to write the HTML output. The generated commands involve Fletcher Penney's MultiMarkdown, and are obtained by applying copious amount of sed to the ls results. If you want to see what the generated command look like, edit ___.sh to replace the few |bash by >script.sh.

Unlike Second Crack, Jekyll & Hyde, ___.sh is on the simplistic side of simple and doesn't have any option. You can somewhat configure the HTML outputs by modifiying the - files, which contains the raw HTML for the non-markdown content of the output. There is also an index.css that you might want to change.

On the other hand ___.sh only has two dependency:

  1. a UNIX OS with bash, sed, cut, echo, cat etc...
  2. a Markdown to HTML program which must be in the path and called multimarkdown.

So, there you go, you can generate a static blog with a few lines of bash and a binary markdown compiler. You just need a few thousand lines of precompiled C.

More details about how ___.sh comes together is available in the for once detailed readme of the project.

And it's all because of Django & Unicode

So I have this error in my Django page when trying to get some values via a many-to-many relathionship:

filter() keywords must be strings

in

/[...]/VIRTUAL_ENV/lib/python2.6/site-packages/django/db/models/fields/related.py in get_query_set line 497


  def get_query_set(self):
    db = self._db or router.db_for_read(self.instance.__class__, 
                                        instance=self.instance)
    return superclass.get_query_set(self)
                        .using(db)
                        ._next_is_sticky()
                        .filter(**(self.core_filters)) #<< Here

Which took me while to figure as being a Unicode handling problem between Django and Python (2.6).

Here are the initial conditions:

  • Snow Leopard shipped with python 2.6.1.
  • I use homebrew for installing extra software
  • The web app I am working on depends on (amongst many other):
    • Django 1.3
    • Cairo

Some other facts I have to work with:

  1. Django 1.3.1 does not fix the problem.
  2. Django 1.4 is still pre-alpha.
  3. We use a library which has issues with python 2.7 so it's out.
  4. The official python 2.6.6 OSX binary is i386 only.
  5. There is no homebrew package for python2.6.* anymore.
  6. There is no pip package for Cairo (py2cairo).

Django 1.3.1: no luck

So I tried to use Django 1.3.1 but it does not include the fix for this particular problem.

Django 1.4 pre-alpha : it says it all on the tin

No more luck with a checkout of Django 1.4 sources. Is still too much on the bleeding part of the bleeding edge (renamed packages, disappearing classes ... )

As newer versions of Django don't fix the problem let's try newer versions of python.

Python 2.6.6: too much pain

I installed Python 2.6.6 from the official OSX binary distribution. I Set up a virtual environement, but there were some problem with compiling libraries and re-using previously compiled library. It mostly revolved around architecture mismatch between i386 and x86_64:

Error was: 

dlopen([...]/ENV_py266/lib/python2.6/site-packages/cairo/_cairo.so,2): 
       no suitable image found.  
Did find:
       [...]ENV_py266/lib/python2.6/site-packages/cairo/_cairo.so: 
       mach-o, but wrong architecture

I would have to recompile pycairo with a different architecture and possibly other libraries. So I decided to skip it and got to the next option.

Python 2.6.7:

So I then had to try and install a newer version of python, from source. I might as well get the last: Python 2.6.7. Googling around I found an article about recovering the old Homebrew formula for python from github when the tracked python was 2.6.

The formula/repository seems to have moved from when the article was written (curl just gets a 301 when fetching the article's URL), so I went to the page to copy the final url from my browser. I modified the python source url and md5 to match that of the 2.6.7 version. I renamed the Formula and class to python2.6.7 and Python2.6.7 respectively before moving them to their destination. Building and installing was as easy as:

brew install python2.6.7 --universal
sudo brew link python2.6.7

I then created a new virtualenv using that new python. I copied my python 2.6.1 site-packages from my previous virtualenv over as well as the django project itself. To cleanup afterwards I ran the command bellow in the virtual env's root.

find . -name '*.pyc' -exec rm '{}' ';'

Finally I could start the django project !

Alas, as soon as I tried to get a page I got

Fatal Python error: Interpreter not initialized (version mismatch?)`

I narrowed it down to using a py2cairo compiled for the wrong python.

otool -L _cairo.so
...
=> /System/Library/Frameworks/Python.framework/Versions/2.6/Python (compatibility version 2.6.0, current version 2.6.1)
...

To compile py2cairo with the new python, this stackoverflow question about installing py2cairo on mac os x helped me get started but a bit more research into waf and actually reading the ld man was needed until everything could work together.

After downloading the [py2cairo library source][py2cairo] from its homepage I evolved the following script:

########################
# my messy part: Created by adding and tweaking until it works. 
# Some of it might be unncesary.

python waf clean

export PATH=/usr/local/Cellar/python2.6.7/2.6.7/bin:$PATH
export PYTHONPATH=/usr/local/Cellar/python2.6.7/2.6.7
export LD_LIBRARY_PATH=/usr/local/Cellar/python2.6.7/2.6.7:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=/usr/local/Cellar/python2.6.7/2.6.7/lib:$LD_LIBRARY_PATH
export LINKFLAGS='-search_dylibs_first  -L /usr/local/Cellar/python2.6.7/2.6.7/lib/'

# from stackoverflow 
# http://stackoverflow.com/
# questions/6886578/how-to-install-pycairo-1-10-on-mac-osx-with-default-python

export ARCHFLAGS='-arch x86_64'
export CC=/usr/bin/gcc
export PKG_CONFIG_PATH=/usr/local/Cellar/cairo/1.10.2/lib/pkgconfig/

python waf configure
python waf build

#To check against which python the lib was linked
otool -L build_directory/src/_cairo.so
########################

(gist on gihtub)

Once that worked, the output became:

otool -L build_directory/src/_cairo.so
...
=> /usr/local/Cellar/python2.6.7/2.6.7/lib/libpython2.6.dylib (compatibility version 2.6.0, current version 2.6.0)
...

I installed it in the virtal environment:

cp build_directory/src/_cairo.so $PY267/lib/python2.6/cairo/
echo "from _cairo import *" >> $PY267/lib/python2.6/cairo/__init__.py

And then the Django site finally worked :-)

Yay! Finally, my iPhone app is available on the app store! It took a while to create, it is a bit barebone, but it works and it is "available on the app store"! Its homepage is at www.displayator.com. There is also the help included in the app. It's only the begining, but at least there is finally a visible step :-D.