My Best of 2009

I decided to share a few of my favorite things of 2009. Yes I know 2009 was so last week, but I think this post still lands within the relevancy window.

My list doesn’t necessarily includes things that were newly created last year, but rather things that were new-to-me, or made a significant impact on me within the year. And we’ll start it off with…

Trip: Prague/Munich/Ghent

I went to Prague, Munich (Oktoberfest), and Ghent (for the third time) in September with two friends. It was, of course, awesome. Amazingly though, I still haven’t posted pictures from the trip. New Year’s resolution: suck less.

Runner-Up: (Tie) AEA/ACBF (Boston), WWDC (San Francisco)

It may seem like I’m cheating by listing every place I went in 2009, but I couldn’t really decide which trip was better. Both included technical conferences, good friends, and great memories.

Local Event: Philly Beer Week 2009

Philly Beer Week came at just the right time for me, and it was a lot of fun. Some standout sub-events were the Voodoo tasting at Doobie’s and the Zythos Belgian Beer Fest to cap off the week.

Runner-Up: BarCamp Philly 2009

Philly’s second BarCamp was twice as good as the first. If this trend continues…

Blog: Daring Fireball

I’ve been a DF reader for years, but this year I decided to support Mr. Gruber and buy a membership. It’s my favorite blog.

Runner-Up: UI&us

UI design is one of the most challenging, but also interesting aspects of software development for me, and this blog put forth a lot of great ideas. Plus Keith Lang is a really nice guy.

Programming Site: Stack Overflow

I was a little skeptical at first, but Stack Overflow has definitely changed the Q&A landscape for the better. It’s hard to go back to forums and mailing lists.

Runner-Up: GitHub

I’ve only skimmed the surface, but so far I’m impressed with GitHub. It really delivers on the promise of “Social Coding”.

Local (Philly) Site: (Tie) Technically Philly, Unbreaded

Both blogs are well-written and on-topic. I couldn’t pick a clear favorite, so they’ll share the honor.

Runner-Up: uwishunu

It’s not a new site, but it’s become my favorite place to find fun and interesting things to do in my fair city.

Album: Jaydiohead

Yes, a mashup album. Why? Because it rocks, and made a 30-year-old white guy who never cared for Jay-Z before into a fan.

Runner-Up: Infinity + 1 by A-Track

I picked this up from an Amazon MP3 deal on a whim, not knowing what to expect. Since then slowly but surely embedded itself in my brain. Super fun mix.

Movie: Up

Great film. Squirrel!

Runner-Up: Zombieland

Zombieland produced the most real-life LOLs for of any movie I saw in the theatre all year. Worth it for the Bill Murray cameo alone.

TV Show: Pushing Daisies

I know Pushing Daisies was actually cancelled before 2009 began, but it’s new to me. I loved the characters and the feel of the show. My only gripe was the rushed ending of the second season, but that is obviously attributed to it’s cancellation.

Runner-Up: Dexter

Another new-to-me show. I’m not quite sure what I was expecting, but I was surprised by how much I liked this show. I’ve only finished the first two seasons, but the third is already in my Netflix queue.

Podcast: The MDN Show

The new, unified show from The Mac Developer Network became an instant favorite of mine. I liked all the previous shows, but it’s nice having the content all in one place.

Runner-Up: Stack Overflow

I can’t exactly put my finger on why I like the Stack Overflow podcast so much, but I keep coming back to it. I think there is a good dynamic between Joel and Jeff. It’s also fun to listen to them discuss anything Apple-related. It’s like two polar bears trading tips on life in the rain forest.

Book (Fiction): The Road

Best novel I’ve read in awhile. And I read it before I knew it was being made into a movie, which makes my appreciation more authentic.

Runner-Up: Consider the Lobster and Other Essays

I actually consumed this particular work as an audiobook. I highly recommend it, especially since it’s read by the author, David Foster Wallace (may he rest in peace).

Book (Technical): Learn Objective–C on the Mac

Although I still think Cocoa Programming for Mac OS X is the best text for learning Cocoa, it lacks more foundational information about C and programming basics. We used this book for PhillyCocoa’s Cocoa Programming Foundations Workshop and were very happy with it.

Runner-Up: JavaScript: The Good Parts

Technical books that approach a topic from a particular angle, instead of being just another tutorial or reference really stand out for me. I don’t even write much JavaScript, but I really enjoyed this book. Plus it’s a short read.

Mac Application: (Tie) Acorn, Opacity

I’m not a big fan of Photoshop. It’s expensive, cumbersome, and does much more than I need. I wanted some lighter, cheaper, and more geared towards developers. Enter Acorn, a well-designed, scriptable image editor. It’s usually the first place I go if I need to work with any graphics. However, this year I discovered a super-interesting application called Opacity. It’s obviously designed with the developer in mind, with bindable variables and it’s own “build” system. I do almost all my image work in these two apps, hence the tie.

Runner-Up: DTerm

I was aware of DTerm for awhile, but I didn’t “get it” until recently. It’s great for interacting with git from within Xcode, and supersedes the “Open Terminal Here” applications I’ve written about previously.

iPhone Application: Tweetie 2

Great application all-around. I love the “pull down to refresh” feature.

Runner-Up: Byline

Byline is the best Google Reader client I’ve tried. I love swipe to mark/unmark as read.

iPhone Game: Parachute Panic

Parachute Panic is a fun, casual game, but it’s the hand-drawn graphical style and music that pushed it to the top. ♫ The game is overrrr ♫ But not foreverrrr ♫ Try it again! ♫

Runner-Up: Flight Control

Again, a fun, casual game whith great graphical style and music.

Video Game: House of the Dead: Overkill

Yes, its bloody, campy, and kinda stupid, which is exactly why it won. Very fun in that “turn your brain off and shoot at things” kind of way.

Runner-Up: Tales of Monkey Island

Guybrush Threepwood, Mighty Pirate returns. Man, I miss adventure games.

Brunch: Café Estelle

Excellent food, friendly staff, and human-sized portions.

Runner-Up: Figs

This little BYO has great egg dishes and the thickest pancakes I’ve ever seen.

Lunch Truck: Honest Tom’s Tacos

I love the simplicity of the menu. For lunch, there are two kinds of tacos, coffee, and no step three. The sweet potato tacos are my favorite.

Runner-Up: La Dominique

This unassuming cart serves up delicious, painstakingly-crafted crêpes on Drexel’s campus.

Restaurant: Amada

I’ve actually been to Amada once previously, but it stood out in my mind as the best restaurant experience I had this year. The “Matador” cocktail was awesome.

Runner-Up: The Belgian Café

It gets mixed reviews from fellow Fairmount residents, but I really like The Belgian Café. Tasty veggie burgers and impressive beer list. Done.

Bar: National Mechanics

National Mechanics has become the go-to bar of the geek crowd in Philly. I’ve had several “good times” there this year, so this was an easy choice.

Runner-Up: The P.O.P.E.

I don’t make it out to this South Philly hangout very often, but I have blast every time I do.

Beer: Liefmans Cuvée Brut

This may seem like an odd choice, but I stand by it for a few reasons. First, I was given a tour of the Leifmans brewery in Belgium brewery courtesy of some awesome friends. Second, although sour fruit beers aren’t usually my first choice, this is actually a pretty damn good beer.

Runner-Up: (Tie) Dogfish Head Sah’tea, Palo Santo Marron

And a Dogfish Head double-whammie in the runner-up position. I discovered both these beers in 2009 but under very different circumstances. Palo Santo I first tried during a tour of the Dogfish Head brewery, and Sah’tea at the aforementioned Belgian Café after the first fateful night we spent with the little monster. Friends and I bought and split cases of each.

Predictions for 2010

  • Probably contain around 365 days.
  • Still no jetpacks.
  • Ragnarök.

Wildcard App ID and Push Notifications

Back in the Dark Ages of iPhone Development, when the NDA loomed over us all, getting information was hard. The deployment and code-signing piece was especially tricky to get working correctly. One was often thrilled to get it working at all.

One step of the process is choosing an application ID, which uses the common reverse domain name format. The documentation also stated that if you want to share information across multiple applications, a wildcard app ID (com.yourcompany.*) can be used. No drawbacks were given, and sharing is good, right? So I can only imagine that some people may have used a wildcard app ID for their application. And I can also only imagine that these people had no problems with their wildcard app ID, until iPhone OS 3.0 came out that is.

You see, Apple’s Push Notification service using a wildcard application ID.

Those same people may have been under the impression that it was the app ID that uniquely identified the application, and therefore changing it would yield a new application, and not update the existing one. This means that all ranking in the App Store would be lost, and users would not be notified of the update.

The good news is, this is not the case. An application’s app ID can be changed by generating a new app ID, re-generating a distribution the App Store distribution certificate, and submitting to the App Store.

So if you shipped your app with a wildcard ID, and now want to integrate push notifications, you are not screwed. Just generate a new, non-wildcard app ID.

An Event Apart 09

I attended the recent An Event Apart conference in Boston. An Event Apart is aimed at designers who build websites, and has a standards-oriented slant.

I am not a designer, but I have to play one from time to time. I don’t plan to make designing websites my primary focus, but some basic skills is necessary these days. Also I think the web might not be a passing fad, so investing in some expertise in that realm would probably pay off in the long run AEA seemed like a good way to jump-start that area of my professional skill set.

The talks were very high quality across the board, and the topics ranged from design psychology to CSS nuts and bolts. I found Jason Santa Maria and Dan Cederholm to have the most useful technical content. Whitney Hess’s DIY UX talk and Kristina Halvorson’s Content Strategy talk both had great information from a less technical, but still development-related standpoint. From a general-interest perspective, Jared Spool on Amazon and SimpleScott on the Obama campaign website were extremely interesting.

Beyond the talks, the conference itself was a great experience. The presenters were very down to earth, and I met a lot of cool people. The designers didn’t even seem to mind that I wasn’t “one of them”.

A few personal key takeaways:

  • “Websites don’t need to look the same in every browser.” This was the mantra of the conference. We were made to chant it over and over until it permeated our souls (just kidding (sorta)).
  • Grid-based layouts are your friend.
  • Fluid layouts are cool.
  • Sketch. “Sketchbooks are not about being a good artist, they’re about being a good thinker.” – Jason Santa Maria.
  • “The behavior you’re seeing is the behavior you’ve designed for.” – Joshua Porter
  • Charge for the value you bring to a client, not the hours you work.

I didn’t take many pictures but instead outsourced them via the AEA Boston 09 Flickr pool.

Finally, I wanted to put some of my newfound skills and excitement to use. Without further adieu, I give you: doesthissitejustshowonebigword.com.

And the winner is… wait… what?

The iPhone app we built for Wolfgang’s Vault, Concert Vault (iTunes link), was awarded Best iPhone/iPod touch application by Macworld UK.

This is quite the pleasant surprise. I had no idea it was even being considered. It’s an honor to be chosen out of all of the nominees, which are all great apps. I use several of them myself.

Working with Wolfgang’s Vault has been a great experience and we’re excited to continue building apps to deliver their extraordinary content on the iPhone platform.

WWDC 09 Post Mortem

WWDC 09 was my second WWDC, after first attending in 2008. I would have liked to do a more well-constructed breakdown of this year’s conference, but time has been scarce, and I didn’t want the information to get (more) stale. Instead, I give you a brain-dump of some of my experiences:

  • Keynote

    • Cheaper, better laptops? Yes please.
    • Snow Leopard for $29 is great.
    • Boos at AT&T were funny (and warranted).
    • “Find My Phone” was the surprise hit.
    • Too much time in demos (a third of which didn’t work!).
    • Scott Forstall seemed like a stronger presenter than Phil Schiller.
    • My prediction the new iPhone’s video chat feature would be demoed by calling Steve Jobs was wrong.
  • Events and Parties

    • sfMacIndie was worthwhile – bumped into some old friends and made some new ones.
    • First Stump the Experts. Fun, but I don’t know if I’d do it again.
    • Those WebKit guys and girls can throw a good party.
    • The Big Nerd Ranch was, of course, a lot of fun.
    • Beer Bash: Cake was good, but the food, not so much.
      • “Don’t bring hot dogs to a sausage party.” – @themartorana
  • Travel & Lodging

    • First Virgin American experience was positive, though the best part is their attitude, not the in-flight entertainment or wifi.
    • The InterContinental was really convenient and pleasant. Internet will cost you though.
  • Food & Drink

Whew. I think that’s all the non-NDA-encumbered information I have for now. Again, WWDC proved to be a good experience. If you develop Mac or iPhone software, and can afford it, it is definitely worth your time.

Finally, it was awesome to travel with so many local friends this time (even the smelly ones) and of course, make some new ones. That’s what WWDC is really all about, anyway.

Oh, and the few photos I took can be found here.

Now let’s just hope the videos come out more promptly this year. ;-)

Another “Open Terminal Here” Toolbar App

In Learning the Terminal on the Mac – Part 4, I mentioned a mini-application called OpenTerminalHere that opens a new Terminal in the same directory as the current Finder window. Well recently Dan Benjamin linked to another, nearly identical application called cdto.

Both toolbar applications work as advertised, but cdto takes the extra step of clearing the scrollback buffer after changing directories, yielding a slightly cleaner workspace. cdto is also hosted on Google Code, so it’s easy to grab the source on hack on it.

Enjoy.

Terminal Quickie: Kill ‘Em All

More often than I’d like, my Mac gets into a very unhappy state. Running applications won’t respond, but they won’t force quit either. New applications won’t launch, and the unresponsive applications block a proper system restart.

Usually I want to cut my losses, and get my machine back into a good state as soon as possible. As a last resort, I could do a hard restart with the old hold-the-power-button-down-for-5-seconds trick, but then I have to wait for the machine to reboot and risk damaging my filesystem.

There is an alternative method that will kill all of your processes, responsive or not, and get you back working much more quickly – as long as you still have shell access:

$ kill -9 -1

Warning: this really will kill all your running processes immediately, without saving any data. Use wisely.

Discussion

So what’s going on here? Basically, the kill (man page) is used to terminate processes. Usually it is used to kill a single process, like so:

$ kill 1234

where 1234 is the process id. The process id can be obtained a number of ways, but the most common is with the ps (man page) command.

The kill command also lets you specify a signal to send to the process. By default, it sends the TERM signal, which ask the program to terminate. However, the TERM signal isn’t always enough. Sn unresponsive program often won’t be able to react to the signal, and programs can even choose to ignore the signal completely.

Luckily, the KILL signal does not suffer from the problem. When this signal is sent, the operating system will stop the process dead in its tracks, whether it wants to stop or not. The KILL signal is very powerful, but don’t only use it as a last resort because it does not allow processes to save data, close resources, and otherwise exit cleanly.

You can send the KILL signal to a process like this:

$ kill -KILL 1234

Or use the numeric value for the signal, which is 9:

$ kill -9 1234

There is one final piece to the puzzle. Notice that in the original command we pass a -1 as the process id. This is a special argument that tells kill to send the signal to all processes belonging to you (or every process on the system, if you’re the super user).

Basically, kill -9 -1 is a quick way or killing every process belonging to you. Running this on a OS X system is a quick a dirty way to clear your environment and start fresh. Remember, this will kill all processes immediately – without saving data – and log you out, so use with care.

Adding Debug-only Preferences in iPhone Applications

Recently I bumped into an iPhone application configuration/deployment problem, and thought someone else might benefit from my findings.

Motivation and Goals

Here’s the basic scenario: I wanted to expose certain options in my iPhone application that were only available in Debug builds. One choice would be to add the ability to change the options in the application itself, and use the usual conditional compilation (#ifdef DEBUG…) techniques to hide or expose them based on build configuration.

However, this would require adding a whole bunch of custom UI in my application, which didn’t really seem appealing. The application was already using the standard iPhone application Setting system, which is driven by simple plists. I thought to myself, boy it would be nice if my Debug-only options could be automagically added to Settings bundle at build time.

For example, the standard settings pane would look like this:

NoDebug.png

And debug-only options would be added automatically, to produce this:

HasDebug.png DebugPane2.png

I’m a believer in the DRY principle, so I wanted to avoid duplicating and information at all possible. Also I wanted to “set it and forget it” and not require any manual build steps.

After some experimentation, trial, and error, I arrived at the following solution:

  1. Store Debug settings in a separate child pane. The Settings system allows for child panes of the root pane. To keep the main settings and debug settings separate, we keep them on different panes.
  2. Add an reference to the child pane from the root pane at build time. To keep the main root settings clean, we’ll inject the reference to the debug clild pane at build time.

Create the Property List

First, add a Settings Bundle to your project if you haven’t already. Choose File -> New File… -> Settings -> Settings Bundle.

Next we need to add a second plist for our Debug settings. Xcode doesn’t allow you to create a new plist inside the Settings bundle (or any bundle for that matter), so we’ll have to create our Debug.plist by some other means. If you’re familiar with the shell, the easiest way is to navigate to Settings.bundle inside your project and simply duplicate the main Root settings to create Debug settings.

cp Settings.bundle/Root.plist Settings.bundle/Debug.plist

If you prefer to use Finder, navigate to Settings.bundle and then right- or control-click and choose Show Package Contents. Then option-drag to duplicate Root.plist and rename it to Debug.plist.

Once the file has been created, collapse and expand the Settings bundle in your projects Groups & Files section to refresh it’s contents. It should look like this:

AddDebugSettingsExample - Debug.plist .png

Note, you can name the child settings plist something other than “Debug” if you want. We’ll see how to do that in the next section.

The Injection Script

The purpose of the injection script is to add a child pane option to an existing settings plist file. It uses the built in PlistBuddy utility to do all the real work.

The addDebugSettingsChild.sh takes two arguments. The first is of course that path to the target plist file. The second is the name of the new child pane, or ‘Debug’ if unspecified.

Here’s the script:

#!/bin/sh

# addDebugSettingsChild.sh
#
# Simple script to inject a Debug menu in an iPhone Settings plist.
#
# created 10.15.2008 by Andy Mroczkowski, mrox.net

THIS="`basename $0`"
PLISTBUDDY="/usr/libexec/PlistBuddy -x"

set -e

if [ -z "$1" ]; then
    echo "Usage:"
    echo "   $THIS plist_file [child_pane_name]"
    echo "   - If unspecified, child_pane_name is 'Debug'"
    exit 1
fi

if [ ! -e "$1" ]; then
    echo "[$THIS] file not found: '$1'"
    exit 2
fi

if [ ! -z "$2" ]; then
    CHILD_PANE_NAME="$2"
else
    CHILD_PANE_NAME="Debug"
fi

TARGET="$1"
echo "[$THIS] adding '$CHILD_PANE_NAME' child to: $TARGET"

$PLISTBUDDY -c "Add PreferenceSpecifiers:0 dict" "$TARGET"
$PLISTBUDDY -c "Add PreferenceSpecifiers:0:Type string 'PSGroupSpecifier'" "$TARGET"

$PLISTBUDDY -c "Add PreferenceSpecifiers:1 dict" "$TARGET"
$PLISTBUDDY -c "Add PreferenceSpecifiers:1:Type string 'PSChildPaneSpecifier'" "$TARGET"
$PLISTBUDDY -c "Add PreferenceSpecifiers:1:Title string '$CHILD_PANE_NAME Settings'" "$TARGET"
$PLISTBUDDY -c "Add PreferenceSpecifiers:1:File string '$CHILD_PANE_NAME'" "$TARGET"

Download

Creating the Build Step

We’ve created a Debug settings child pane in our settings bundle, and a script to add an option to access our child pane from the root pane. Now we just have to tie the pieces together in Xcode’s build settings.

Copy addDebugSettingsChild.sh to your project’s folder. You don’t need to add it to the project itself. Next add a new “Run Script Build Phase” to the target for your application. Order it so be comes after the “Copy Bundle Resources” phase, and name it something more descriptive if you’d like. I called mine “Run Debug Settings Script”.

Debug.plist - AddDebugSettingsExample-2.png

Next we have to make the our new Run Script phase actually do something. Basically, we need to call the addDebugSettingsChild.sh if we’re building with the “Debug” configuration, and also set up the input and out files so Xcode knows when to run the script and when not to. Let’s set up the input and output files first.

Add the path to your Root settings plist as an input file. If you used the default names and locations, this should be:


$(SRCROOT)/Settings.bundle/Root.plist

The file we will be altering will be in the built products area, not the project source root, so the output file should be:


$(BUILT_PRODUCTS_DIR)/$(UNLOCALIZED_RESOURCES_FOLDER_PATH)/Settings.bundle/Root.plist

Finally create the body of the script. I only want to add my extra settings if I'm building the "Debug" configuration, so my script looks like this:

if [ "$CONFIGURATION" == "Debug" ]; then
    sh addDebugSettingsChild.sh "$SCRIPTOUTPUTFILE_0"
fi

You may notice that the script's input is specified as the output file. This is not a mistake. The addDebugSettingsChild.sh script modifies the specified plist in place, and we want to alter the one in our built-products area, not the source tree.

Again it's important to specify the input and output files. If you don't, Xcode may run the script on every build, which will result in repeated Debug child pane choices in our main settings plist.

Once you're done, it should look like this:

Run Script Phase for “AddDebugSettingsExample” Info.png

Conclusion

And that's it. You can now add edit the Root and Debug plists and they will be updated appropriately and everything will be happy. Well, mostly happy (see Caveats). I hope you found if useful. If not, I'm sorry. Here's some pictures of Robocop on a Unicorn to cheer you up.

Sample Project

You can download a sample project with all the above steps already completed here.

Caveats and Future Work

  • Be careful when switching configurations and using Build and Run. The products in the build folder for each configuration should always be correct, but Xcode won't necessarily re-install the right Setting bundle if it doesn't detect a change. The workaround is to just build clean and re-build when switching from Debug to Release or vice versa. Any suggestions on how to improve this are welcome.
  • Child pane options are always injected at the top. I'd prefer if I could add the "Debug Settings" option at the end of the main preferences, but I could not find a simple way to append an element to the end of an array with PlistBuddy. I considered using PlistBuddy to loop through the array to determine the size, and then use that to append it to the end, but I didn't want to add all that complexity to the script for a minor issue just yet.
  • Debug.plist still exists, but is inaccessible, in Release builds. This method does not prevent the installation of the Debug.plist, but there will be no way to get to it, since it's not referenced as a child from the root plist. If this bothers you, you'll probably have to set up another script to remove Debug.plist.
  • What if I'm not using a Settings bundle in my Release builds? This technique assumes that you're already using a Settings bundle to your application, and you want to add extra stuff to it based on build configuration. If you'd like to only have Settings bundle for Debug builds, this isn't going to work for you, though hopefully some of the information can help you get started on a similar solution.

Terminal Quickie: trash

I have been keeping myself quite busy with some other projects, but fear not, the Learning the Terminal series is not dead. Hopefully this will hold you over until I have some time to generate some real content.

Last time, we talked about Terminal and Finder integration. One topic we did not touch upon is how to move files to the Trash from the shell. Perhaps surprisingly, Mac OS does not have a built-in command for trashing files. Sure you can just mv files to the Trash folder directly, but this will not handle name collisions or alternate volumes correctly.

There have been a few attempts at a shell script to mimic the trash behavior, but the best I’ve come across is Dave Dribin’s osx-trash. This version is actually a small ruby program that uses the 10.5 scripting bridge to actually execute the Trash operation through Finder. It works “The Right Way”.

Please see Dave Dribin’s setup and installation directions for more information.

Learning the Terminal on the Mac – Part 4 – Bringing Finder and Terminal Together

The first few articles laid out a good foundation of basic shell usage, but little Mac-specific information. In this article, all that will change. We’re going to show a few ways to get back and forth between Terminal and Finder.

From Finder to Terminal

There a few methods to get information from Finder into the Terminal, or use Finder in Terminal-like ways.

Path Bar

One new feature in the 10.5 Finder is Path Bar. The Path Bar makes it easy to see the full path to the current folder. To enable the Path Bar (if you haven’t already), activate Finder, and choose View → Show Path Bar from the menu.

lt2-show-path-bar.png

Once enabled, the Path Bar will appear at the bottom of all your Finder windows, just above the Status Bar. Below is how the Path Bar appears when I have my Home folder open in Finder.

lt2-path-bar.png

The the above path would be interpreted as /Users/demo in the shell.

lt4-ls-path-bar.png

Go to Folder…

Finder also has a built in command called Go to Folder… that allows a path to be entered in a similar way as in the shell. This feature can be accessed by choosing Go → Go to Folder… from the menu, but it’s faster to use the shortcut ⌘⇧G.

lt2-go-to-folder.png

The path entry field of the Go to Folder… feature also has rudimentary tab-completion support. If you type a few letters and either press the tab key (⇥) or just wait a few seconds, it will complete the current path component with the first match it finds. It’s not nearly as good as the completion in bash, but it’s there.

Drag & Drop Paths

Files or folders in Finder can also be dragged and dropped directly onto Terminal. Doing so will insert the path to the file or folder into the shell.

lt4-drag-drop-path1.png

And voilà, the path is inserted into the shell:

lt4-drag-drop-path2.png

OpenTerminalHere

OpenTerminalHere is a small Applescript application that launches Terminal and automatically cd’s to the current folder in Finder. It was originally written by Marc Liyanage and has since been updated to make it more Leopard-friendly. I find it extremely handy, and if you think you would too, go here for the download and setup instructions.

OpenTerminalHere is meant to be installed into Finder’s toolbar. This is done by simply dragging the OpenTerminalHere icon to Finder’s toolbar and pausing a few seconds until a small green “plus” indicator appears next to the mouse pointer. If you want to tweak the position of OpenTerminalHere or add spacing, choose View → Customize Toolbar… in Finder’s menu after installing.

lt4-install-openterminalhere.png

Now just click on the OpenTerminalHere icon in the Finder window’s toolbar, and a Terminal will launch and cd to the current folder.

From Terminal to Finder

Even though the shell is a powerful tool, sometimes you may want to switch back to Finder to finish a task. Here are a couple tools to do just that.

open

We’ve used the open command (man page) a few times already to open files with their default application and folders in Finder. This command is actually specific to Mac OS and is not found in other Unix-like operating systems. The open command also allows you to choose the application with which to open the file, or open the file in the default text editor.

To open a file using a specific application, use the -a option:

open -a [application] [file]

For example, if I wanted to open a file called “hello.txt” in MacVim instead of the default editor, TextEdit, I would type:

open -a /Applications/MacVim.app hello.txt

Also as we mentioned just sentences ago, you can use the open command to open a file using the default text editor. This is done with the -t option.

open -t [file]

Let’s say I’m a curious individual, and I want to see exactly what iTunes stores in its XML library file. I would type:

open -t ~/Music/iTunes/iTunes\ Music\ Library.xml

(Remember those extra \’s are to escape the spaces, which was discussed in the second article.

Revealing Files in Finder

The open command can be used to open folders in Finder, but we don’t have a way to reveal a file within a folder. Many applications have a built-in “Show in Finder” feature, but unfortunately the shell does not. However, all hope is not lost.

One of the simplest ways to add new commands in the shell is through creating shell scripts. Shell scripting is a deep topic in itself, but for know, just think of a shell script as a small program that is interpreted by the shell itself. Shell scripts are written in plain text so they are quick to create and easy to modify.

A hint entitled “Select files in Finder from Terminal” on Mac OS X Hints presents a way add a “Show in Finder” feature to the shell using a custom shell script. Several others submitted improvements and alternative approaches in the comments. The solution I liked best is described in this comment by caesurae.

I liked this solution because it was relatively concise and easy to read (for the bash-literate), and it is contained within a single file. I modified the script very slightly to fix a problem with revealing directories.

Here is the full script. Immediately following is a download link, which is probably more useful. Following that, and even more useful still are installation instructions.

The Script

#!/bin/bash
#
# revealInFinder.bash
#
# 05.26.2006
#
# caesurae@gmail.com
#
# tested on Mac OS X 10.3.9 build 7W98 - Darwin 7.9.0 - AppleScript 1.9.3
#
# reveal the given file(s) and/or folder(s) in a Finder window
#
# usage: revealInFinder.bash ~/dir/file "/dir/dir/my file" file
#
########
#
# 08.07.2008
#
# Andy Mroczkowski
#
# minor update to allow for more reliable opening of directories
#
# tested on Mac OS X 10.5.4 - AppleScript 2.0.1k
#
##

# if no arguments are given, echo the usage string
if [ $# -lt 1 ]; then
  echo 'Usage: '`basename "$0"`' [files]' >&2
  exit 1
fi

# define $n, gets +1 for each argument given
# not sure if $n is needed, how to get index number of $1, $2, etc.?
n=0

# define $act, gets +1 for each argument that passes test
act=0

# step thru each argument one at a time
for thearg in "$@"; do

  n=$(( n + 1 ))

  # if $thearg exists then
  if [ -e "$thearg" ]; then

    # get the absolute path to the argument
    thearg="`cd \`dirname \"$thearg\"\`; pwd`/`basename \"$thearg\"`"

    # create a applescript statement using $thearg for osascript to execute
    osatext='tell application "Finder" to reveal POSIX file "'"$thearg"'"'
    /usr/bin/osascript -e "$osatext"

    # $act activates Finder after processing the remaining arguments
    act=$(( act + 1 ))

  # else if $thearg does not exist then
  else

    # if $thearg is not the last argument given then
    if [ $n -lt $# ]; then

      # ask to continue processing the remaining arguments
      echo -n '"'"$thearg"'" does not exist and will be ignored. continue?  (y/n)? ' >&2
      read ans
      case $ans in
        "n" ) exit 1 ;;
        "y" ) continue ;;
      esac

    # else if $thearg is the last arguement then
    else

      # print the "does not exist" string and exit
      echo '"'"$thearg"'" does not exist.' >&2

      # exit status 1 indicates an error occurred
      exit 1
    fi
  fi
done

# if $act is greater than 0 then activate the finder
if [ $act -gt 0 ]; then
  /usr/bin/osascript -e 'tell application "Finder" to activate'
fi

# exit status 0 indicates all is ok
exit 0

Download the reveal script (and unzip it if necessary).

Installation

Once you have reveal downloaded, you need to put it a place where the shell can find it. Executable files are usually kept in a directory called “bin“. To avoid any permissions problems, we’re just going to set up this script for the current user. To create a bin directory for yourself, type:

mkdir ~/bin

Now the reveal script must be moved into the bin directory. If you saved reveal in your Downlaods folder, you would type the following:

mv ~/Downloads/reveal ~/bin

Of course if you saved reveal to some place other than your Downloads folder, you’ll have use the appropriate path.

Finally we need to ensure that reveal is executable. If you downloaded it from the using the link above, the permissions should have been preserved within the zip file, but we’ll reset them just in case. Changing basic permissions from the command line is done with chmod (man page). We’ll go into detail on chmod later. For now just type

chmod +x ~/bin/reveal

Ok, now everything is in place, but there is still one more thing left to do. The shell only looks in a few pre-defined places for programs and although a ~/bin directory is common, it does not search that directory by default. We can tell the shell to look for programs in our ~/bin directory by adding it to our PATH.

The PATH variable controls where the shell looks for programs. You can manually type in the command to add ~/bin to our PATH, but the PATH variable is cleared every time we open a new shell. That’s a hassle. Instead we want it so our PATH is set up for us automatically. To do that, we will add the command to a special file called .bash_profile which is loaded every time a new shell is started.

First, create the file. The file must be in your home directory (~) or the shell won’t find it. If you already have a .bash_profile the following command won’t overwrite it.

touch ~/.bash_profile

Now open the new, empty .bash_profile file in your default text editor:

open -t ~/.bash_profile

Next add the following line exactly as it appears below. Copy and Paste are your friends. If you already have some stuff in your .bash_profile just add it to the end.

export PATH=$PATH:$HOME/bin

Save and close the file. Then close the Terminal you were working in and open a new one (your .bash_profile is only read when the shell starts up).

Congratulations, you now have installed a shell script. Have a beer.

Usage

Our new reveal script is easy to use. You just type reveal followed by one or more paths to files or directories. In fact, if you type reveal with no arguments, it prints a helpful usage statement:

Usage: /Users/demo/bin/reveal ~/dir/file "/dir/dir/my file" file

Of course since we went through all the trouble of putting reveal into our path, we can just type:

reveal ~/dir/file "/dir/dir/my file" file

Here it is in action:

lt4-reveal-in-action.png

Wrap-up

So there we have it – Terminal and Finder peacefully co-existing. What a wonderful world. If you have more suggestions about integrating these fine pieces of software, or a question, feel free to comment. Feedback is always welcome.