I work in my OS X Terminal window all day long. When I want to run iCal or Address Book, I don't want to be bothered with clicking around to find the app, even though they live in my Dock. I could also use a program launcher like Alfred, which I like, but want it even faster.

For me, the fastest way to open iCal while I'm in the shell is to run "ical" from the prompt, which launches the app.

My ~/bin/ical program is simply

open /Applications/iCal.app/

and my ~/bin/addr is

open "/Applications/Address Book.app/"

You might think that it's overkill to write a shell program for such a silly task, but it's all about optimizing my time at the keyboard for my common cases.

Someone will note that I could have used a shell alias, and that's true, too. Either way, I want a super simple way to get the apps I use most often.

Ever open up a Terminal window and hit Tab and Bash sits for a few seconds until it finally comes back and asks

Display all 2224 possibilities? (y or n)

Because it went and compiled a list of EVERY executable you could possibly want to execute?

Yeah, me, too, and I hate it. The fix is simple. Add this to your ~/.bashrc

shopt -s no_empty_cmd_completion

No more completion on nothing!

I've been frustrated lately trying to juggle multiple SSH keys on various servers I'm on. If I've got one set up to the Subversion server at work, then I can't authenticate with github. If I let github be the server that I have a private key for, then I'm entering a password whenever I do an "svn up" on the work server.

I played with ssh-agent, but that seemed to require starting up a process every time I logged in, and I couldn't get it running in my .bashrc, and it required manually adding keys.

And then I stumbled across this article that introduced me to the IdentityFile argument. Now I have this in my ~/.ssh/config and all is well with the world.

Host github.com
    HostName github.com
    IdentityFile ~/.ssh/github_rsa
    User petdance

The always amazing Peteris Krumins is starting a series of blog postings on cool plugins for vim, starting with this post about surround.vim.

Just reading the article about the "old way" to do what surround.vim does was informative, showing me vim tricks I didn't know.

Seriously, anyone who reads Mechanix should have Peteris' blog in her syndication reader.

Too often I see web graphics that have been saved as JPEGs, not PNGs, and I cringe. How can I tell? This comic shows the difference.

Git is my hero

| | Comments (1)

By Selena Deckelmann

Last night, an incredible number of people showed up to Code-N-Splode to hear about Git.

I was not at all prepared for that number of people, but grateful that a couple experts were on hand to help - Sarah Sharp, Audrey Eschright and Michael Schwern (and others) all contributed to the discussion. Thanks for all the great questions! I'm looking forward to Sarah’s advanced tutorial next month.

Selena Deckelmann leads the Portland PostgreSQL Users Group and regularly contributes to Code-N-Splode, a group dedicated to getting more women involved in open source. She likes Perl. She'll be running a code sprint and giving a lightning talk on having more fun with open source at PostgreSQL Conference West, on October 17-19, 2008.

Downloading video with Awk

| | Comments (0)

Peteris Krumins, the prolific blogger and programmer, decided to explore TCP/IP networking in GNU Awk, and came up with this, a YouTube video downloader.

Subscribe to Peteris' blog. It's well worth reading.

Linux Journal has an article on creating Excel files using Spreadsheet::WriteExcel. It has its quirks, like creating corrupted spreadsheets if you try to populate a cell more than once, but when you need it, there's nothing else to do what it does.

I'm in the middle of a game of Scrabulous with Christoper Humphries on Facebook, and I get "tolkien" handed to me in my tray. Good letters, and I ought to be able to make a bingo out of them. Alas, the best I could get to play on the board was "knot", but what else could I have made? Perl to the rescue!

All I need to do is match across the contents of /usr/share/dict/words in a Perl one-liner. The -n flag means "loop over the input file, but don't print $_". My little program goes in -e, and it looks like this:

$ perl -lne'print if /t/ && /o/ && /l/ && /k/ && /i/ &&
    /e/ && /n/' /usr/share/dict/words 

Lots of good words, but they're awfully long. Let's limit it to seven-letter bingos. We have to use the -l flag to drop the linefeed from the input lines, so the length call is accurate.

$ perl -lne'print if /t/ && /o/ && /l/ && /k/ && /i/ &&
    /e/ && /n/ && length($_)==7' /usr/share/dict/words

Shoot, nothing there. Let's try eight.

perl -lne'print if /t/ && /o/ && /l/ && /k/ && /i/ &&
    /e/ && /n/ && length($_)==8' /usr/share/dict/words 

"knotlike"! That would have been beautiful. Oh well. :-(

Thread over on perlmonks talks about Tom Christiansen's assertion that you should use it, by default, even when you only have one command-line argument to parse:

What seems to happen is that at first we just want to add--oh say for example JUST ONE, SINGLE LITTLE -v flag. Well, that's so easy enough to hand-hack, that of course we do so... But just like any other piece of software, these things all seem to have a way of overgrowing their original expectations... Getopt::Long is just *wonderful*, up--I believe--to any job you can come up with for it. Too often its absence means that I've in the long run made more work for myself--or others--by not having used it originally. [Emphasis mine -- Andy]

I can't agree more. I don't care if you use Getopt::Long or Getopt::Declare or Getopt::Lucid or any of the other variants out there. You know know know that you're going to add more arguments down the road, so why not start out right?

Yes, it can be tricky to get through all of its magic if you're unfamiliar with it, but it's pretty obvious when you see enough examples. Take a look at prove or ack for examples. mech-dump is pretty decent as an example as well:

    'user=s'        => \$user,
    'password=s'    => \$pass,
    forms           => sub { push( @actions, \&dump_forms ); },
    links           => sub { push( @actions, \&dump_links ); },
    images          => sub { push( @actions, \&dump_images ); },
    all             => sub { push( @actions, \&dump_forms, \&dump_links, \&dump_images ); },
    absolute        => \$absolute,
    'agent=s'       => \$agent,
    'agent-alias=s' => \$agent_alias,
    help            => sub { pod2usage(1); },
) or pod2usage(2);

Where the value in the hashref is a variable reference, the value gets stored in there. Where it's a sub, that sub gets executed with the arguments passed in. That's the basics, and you don't have to worry about anything else. Your user can pass --abs instead of --absolute if it's unambiguous. You can have mandatory flags, as in agent=s, where --agent must take a string. On and on, it's probably got the functionality you need.

One crucial reminder: You must check the return code of GetOptions. Otherwise, your program will carry on. If someone gives your program an invalid argument on the command-line, then you know that the program cannot possibly be running in the way the user intended. Your program must stop immediately.

Not checking the return of GetOptions is as bad as not checking the return of open. In fact, I think I smell a new Perl Critic policy....