iCal's Text Field Jumble

I've written here before about text fields, particularly the problem of having a good-looking 'display' mode and a separate 'edit' mode for data you don't edit so often, like in AddressBook.

The most recent version of iCal decided that events are write-once-read-many as well. You now have to use cmd-E to get into edit mode, while cmd-I just gives you a small display mode.

I'm mostly OK with that, although I find I edit events about as often as I look at their info windows - after editing I usually just deal with alarms, not the events themselves. The casual glance at the time and title is always enough - I think either you're looking at the time and title or you're editing. I don't see the appeal in the new 'info-only' mode (if it's actually new - it seems new.)

However, the change does highlight the jumble of editable text fields and text-like fields in the edit window:

The "Add Attendees" link and the "None" placeholder for url act the same - you click on them, and enter text. One's a link and one's mute gray text. Why? For my part, I think the gray text is too understated, and the link is too garish.

There are other differences: you can tab to the "url" field, but you can't tab to "attendees"... until you add one, then you can. Once you click on either of them, the url field pops up a plain white raised NSTextField, but the attendees field is sunken and translucent, apparently an NSTokenField?

Both of the blue links could also be buttons. I'm still not completely sold on replacing buttons with links, but I can understand the trend. I think a small plus-sign button would be fine for "Add File", though, and "Attendees" ought to be a text field. Why force the user to use the mouse when adding data to an event?

All in all, I think the "Add Attendees" link/field is pretty strange. I'm curious if I missing a precedent somewhere.

go juggle — an attention callback

Sometimes progress on a project for me consists of a few short bursts of activity in between stretches of waiting for some long-running thing to complete so I can figure out what I need to do with it next.

Because I always have more than one project going, I don't actually wait much. I just switch workspaces and try to make progress on the next thing. If I can't make progress on anything immediate, I'll end up checking email or looking up something for a side project.

This kind of multitasking is inefficient, but inevitable when I might have to wait for 20 minutes or more for a compute job or a compile to finish.

The problem with this approach is that the things I'm waiting for often finish while I'm off doing something else, and if I get too involved, the low-priority research or emails will eat up my day while the high-priority work sits waiting for me.

I've attacked this problem in the past when using OS X with growl, but I can't call growlnotify from remote systems. However, I just found dzen for X Windows, a lightweight notification display utility that compiles easily on every system I've tried, and works remotely with ssh X forwarding.

I wrote a simple script called go, which just executes its arguments and runs dzen when it's done. Now I type (for example) go make and I can switch over to something else, confident that I'll see a big popup window letting me know when I can get back to working on my highest priority project.

Here's basically the entire go script:

echo $@
echo $@ completed on `hostname` \
 | dzen2 -p -h 64 -bg darkblue

It's simple but it's working great for me. I've tried some improvements like randomizing window placement to avoid overlapping notifications, but the simple version above really does all I need.

Finally, a couple of details. zsh always seems to want to spell-check 'go', so I really named it '~/bin/executeAndNotify.sh' and just aliased 'go' to that. Also, I've found it can mess with shell quoting as is, so sometimes I have to do 'somecommand ; go echo done'. If someone has a tip on getting the quoting right in the script, I'd love to hear it. The problem crops up when you try something like 'go make CC="cc -g"' - the quotes don't make it through.

Two hours

Daniel Jalkut just wrote about a desktop bookmarking app called Pukka, which despite being apparently nice enough to warrant a positive review, was simple enough that Leo Laporte wasn't comfortable just saying it cost $15. I felt like adding to the discussion after a few commenters described the app as trivial - in one case saying that any good programmer could write it in two hours.

This bothered me, so I downloaded Pukka and gave it a try. I was curious to see if it was indeed trivial.

While it definitely doesn't seem like the most feature-rich program up front, there's a lot of stuff in there - it works with more than one bookmarking site, it integrates with RSS readers, uses the OS X keychain, includes Bonjour discovery of nearby users, and has AppleScript support.

Further, it shows attention to detail. Although I may not agree with some of Justin's UI design choices, it's clear that he spent time thinking about bookmarking workflow. I know in some of my projects, just pondering design choices takes hours - drawing mockups, and trying things out.

End-user app development isn't just programming, and programming isn't just typing.

I think it's fair to say that that although you might be able to retype the code by hand in a few hours, Pukka represents a good chunk of serious work. I'm sure the mac developers in the audience will agree - Applescript support alone is almost guaranteed to be more than two hours of work.

I'm glad that there's a market for small apps and small developers, and I hope downwards price pressure from large subsidized or bundled apps doesn't kill that off.

VoodooPad 3.5

From Flying Meat, VoodooPad 3.5 is out. (release notes here).

It's a solid update, including welcome image-editor integration and more. I thought I'd point out my favorite feature in the release notes:

"You can now edit pages and sort the results in the search window (woo!)."

I like this because it matches a kind of manual refactoring habit I picked up with Project Builder / XCode's excellent "Find in Project…" window - I search for a keyword that marks places I need to look at and edit the files right in the search window. (Note: 'occur-mode' and kin are a powerful way to do the same in Emacs…)

It's a powerful habit if you plan for it, by using comments in code to keep track of what you've touched when making a lot of cross-cutting changes, like # @addsearch Then when you think you're done with a change, you can run a quick search to see if you forgot to fix anything.

Sometimes in VoodooPad notes, I'll write in placeholders like that comment when I don't have a bit of information yet, and now I can follow my trails the same way I do in code.

Thanks, Gus!

PyObjC notes

I've been hacking around with PyObjC, the Python-ObjC/Cocoa bridge recently, and it's quickly becoming my favorite way to write Cocoa apps. It's really natural to mix Python idioms with Cocoa objects.

The latest version of PyObjC is 2.0, it's installed by default on OS X 10.5, and XCode now includes templates for starting a PyObjC project. There's even code autocomplete in XCode for PyObjC and IB integration, so aside from some smart-indenting issues, writing PyObjC in XCode is almost as natural as writing in ObjC.

I thought I'd post a few nice shortcuts and tips here.

You can use tuples for NSRect/Range/Point, for instance, this -

r = NSInsetRect(((0, 0) ,
                 (100, 100)),
                10, 10)

creates this NSRect -

NSRect origin=

Passing python arrays as NSArray instances (and dictionaries as NSDictionaries) works great, but sometimes you need to pass a C array. The Python 'array' module handles that nicely:

import array
g = NSGradient.alloc().

    array.array('f', [0.0, 1.0]),

ObjC selectors are just python strings in PyObjC.

# or
self.performSelectorOnMainThread_withObject_waitUntilDone_('doIt:', None, False)
# or
if o.respondsToSelector_("fun:"): return o.fun_(a)

Finally, something that comes in handy when working with KVC, the '_' method now defined on NSObjects in PyObjC:

o = 
print o._.myKey
o._.myKey = 44
# is equivalent to:
print o.valueForKey_('myKey')
o.setValue_forKey_(44, 'myKey')

That last example is straight from the NEWS page, where lots of other useful info can be found.

What is Site Reliability Engineering at Google

I've been looking around for some more detailed information about the "Site Reliability Engineering" positions at Google. Apparently the role is a real mix of very large-scale system administration, planning and automation.

I've collected some links to public info about the job.

The Google channel has a promotional video from one engineer about the role - he tells a quick story about being on call to monitor and address problems with Google talk.

A set of slides from a talk by James Youngman at the UK Unix & Open Systems User's Group gives a good description of the general task, and dives deeper into two specific examples - powering down failed disks, and protecting data with checksums, exploring how straightforward ideas can explode at scale. (These slides also have potentially the best proprietary-information disclaimer I've ever seen: "This has been written entirely in ASCII. No EBCDIC or animal fat.")

Here is another set of slides with a quick overview, from a 'lightning talk'.

A sampling of what Google SRE engineers put in their public resumes about their job includes quite a span - from troubleshooting mission critical services to writing automation software (in Python).

And finally, an interesting post from 2006 about the theory behind Google's hiring strategy, summarized as "only hire candidates who are above the mean of your current employees".

Twitter Stats in SVG using gnuplot

Damon Cortesi just shared a handy script for grabbing your tweets and compiling some stats about when you post to twitter and who you reply to.

His script generates a list of numbers and included a Numbers template to paste them into. Since I don't have Numbers, I've modified his script to write a file that can be read by gnuplot, and wrote a basic gnuplot script to output an SVG file version of the stats.

While I was at it, I changed it so it no longer counts "@someone" separately from "@someone:".

Both scripts are right here - gnuplot_twitterstats.tgz

It uses gnuplot 4.2, which you can get on OS X with macports using port install gnuplot +no_x11'. (Or it's a pretty easy build on its own, see the gnuplot download page )

Here are my stats: Sorry, it looks like your browser doesn't support SVG. You're really not missing much. Click here for a full-screen version.