Tuesday, June 2, 2009

Recommended Canadian Content of the Week: Leonard Cohen

The choice for my second RCCotW blog post was easy. Leonard Cohen is one of my favorite singer/songwriters, Canadian or not.

I was introduced to Leonard Cohen fairly early, but I guess I wasn't ready for him. A grade 7 a teacher whose name I can't recall (and who I didn't appreciate at the time) split us into groups and had us do a presentation comparing two artists. I wasn't assertive enough at the time to choose two artists I liked (and at 12, if I was aware of the creators of the music, books, movies and TV I enjoyed, I'm sure I didn't think of them as artists), so my partner (who I also don't recall) and I asked (or more likely whined) that we couldn't think of anyone. The teacher suggested two artists that I would enjoy comparing now, but back then I had never heard of: Leonard Cohen and Margaret Atwood. I'm sure our analysis didn't go very deep—we may not have done much more than describe their biographies and that in addition to them both being Canadian, that they are both poets. I think I recall showing an 8 mm movie about each (that the teacher found).

Unfortunately I missed that opportunity to discover the music of Leonard Cohen. I'm sure I heard it occasionally on CBC Radio, but neither of my parents listened to him so I didn't hear his music around the house.

I finally didn't come to enjoy his music until I heard an interview on CBC with Jennifer Warnes, who was promoting her album Famous Blue Raincoat, which is "a tribute to Leonard Cohen, with whom Warnes had toured as a backup singer in the 1970s." (That must have been late 1986 or early 1987.) I bought the CD (one of the first I bought as I began to replace my vinyl collection) and it became one of my favorites. As so often happens, I over-listened to it until I was tired of it, and I haven't listened to it much since then. (It would be interesting to come back to it and see if I enjoy it.)

I remember raving about it online, and someone else responded that I should really listen to Leonard Cohen himself. Later I remember enjoying the song "Everybody Knows" in the movie Pump Up the Volume (in 1990). But it wasn't until 1993 (or maybe late 1992) that I bought my first Leonard Cohen album The Future. Wikipedia tells me it is one of his most popular, so I guess that makes sense.

Not long after that I bought The Best of Leonard Cohen (and noticed how much his voice has changed since he was young) and later More Best of Leonard Cohen. A couple years ago I bought the soundtrack to the Leonard Cohen: I'm Your Man movie, which I haven't seen.

I recommend all of these albums, but I recommend you start with The Best of Leonard Cohen or maybe The Essential Leonard Cohen.

The songs I've marked 5 stars in iTunes are:
Famous Blue Raincoat
Take This Waltz
Hallelujah

And these two tributes from Leonard Cohen: I'm Your Man:
Antony's If It Be Your Will
Rufus Wainwright's Chelsea Hotel No. 2

What did I leave out?

Update: I remembered a very good interview of Leonard Cohen with Terry Gross on Fresh Air.

Friday, May 29, 2009

Geeky things to do on a first-time visit to the Bay Area

A friend of mine is making plans to visit the Bay Area for the first time, and asked me to recommend some things to do here. I explained that now that I have (young) kids, all I could recommend are toddler-friendly places not too far from home in Scotts Valley. (My memory of life pre-kids in San Francisco and San Jose is pretty cloudy.) But I had what turned out to be the good idea to ask for suggestions on the "fun-list" mailing list at work.

I don't think my friend would mind if I described him as a geek. (I'm one too, and I believe we both wear the label with honor.) And he doesn't have a driver's license. Not having a car limits one's choices in the Bay Area. But my co-workers (many of them also geeks, and not into cars) responded with many good ideas:

First a list of places to go or things to see...

In San Francisco:

Recommended San Francisco walks:

  • Hippie Hill (or DeYoung Museum) <-> Haight/Ashbury
    • hippies! druggies!
    • Giant Robot
    • Kid Robot
    • Amoeba Records
    • Thrift stores
    • If he wants a *long* walk, go all the way to Lower Haight for the urban / hip hop scene and Indian Oven
  • Castro <-> Dolores Park
    • gays! lesbians!
    • upper class shopping
    • The Castro Theater, as seen in Milk
    • dogs & sunshine in the park
  • Valencia St
    • hipsters! indie kids! moustaches!
    • The Pirate Supply Store (826 Valencia) (this is a must)
    • Four Barrel Coffee
    • Ritual Roasters
    • Spork, Dosa, Herbivore are good dinner places
    • Burrito joints

Napa Valley:

On the Peninsula:

In San Jose:

Web sites with ideas:

Some recommended books:

Did I leave anything out?

Update: added The Cartoon Art Museum

Update #2: added Segway Napa


Monday, May 25, 2009

Recommended Canadian Content of the Week: Blue Rodeo

Several weeks ago I took Gabe to San Francisco to participate with his t-ball team in a "Little League Day" at AT&T Park. Claire had the great idea of Gabe and I driving up Saturday and staying at a hotel so we could get to AT&T Park early Sunday morning for the Q&A with Giants coaches and players. (And then return in the early afternoon to sit in the bleachers with his team for the game.) It was a weekend of firsts for Gabe: riding in a "subway" (the Muni Metro), riding on a cable car, going to the top of a skyscaper, walking through Chinatown, going across the Golden Gate Bridge. Hopefully some of it made some lasting memories.

Driving home after the game Sunday, Gabe fell asleep (and slept all the way home—he was exhausted after a couple long, busy days). I didn't want to listen to my usual podcasts and risk waking him up (as I did on the way up Saturday), so I set my 5-star music playlist to shuffle. I enjoyed listening to a subset of my favorite music, something I don't make time to do very often.

I was struck by how much of it is Canadian. So I came up with an idea for a series of blog posts, each describing a favorite Canadian band or artist. My idea was to do this weekly, but since it has taken me weeks to finish writing up this first post, don't expect them that often. I'll do what I can.

Several of the tracks that played during my drive were by Blue Rodeo, and I've since noticed that there are more songs by them in my 5-star music playlist (13) than any other group or artist. (Runners-up are The Beatles and Louis Armstrong with 9, and R.E.M. with 8.)

I remember first noticing Blue Rodeo when Much Music took a liking to them after they released their first album Outskirts over 20 years ago. Their album with the most songs I've rated 5-stars (5) is Five Days in July, but I've over-listened to that album and need to leave it alone for a few years before I can enjoy it again.

If you buy only one song of theirs, I (currently) recommend Bulletproof from Palace of Gold. But I also recommend...

From Tremolo:
From The Days In Between:
(I'm a sucker for ballads.)

Sunday, May 24, 2009

Xenocide

Last week I finished listening to Xenocide, over 6 weeks after I started. I blogged about "reading" (listening to) Ender's Game and Ender in Exile in "Pleasures of a poor memory" and about reading Speaker for the Dead in "The tyranny of high expectations". To continue the expectations theme, I'll remind you that I went into this with low expectations. And again, the book exceeded them.

I found this book had the most interesting science of any of the series (so far). And while there wasn't a lot of action, I found certain sections moving, especially [SPOILER WARNING] the description of the riot that burns down the Pequeninos' forest. I found the "creation" and reintroduction of a new Valentine and Peter Wiggin contrived, but towards the end Peter at least began to get interesting.

Now I'm on to the last (audio)book in the series, Children of the Mind. (But a fairly large list of podcasts continue to take priority.) I guess my expectations are higher now. We'll see if they're exceeded.

Friday, April 3, 2009

The tyranny of high expectations

Have you ever suspected that expectations can shape your opinion?

I think I remember first running across this idea while reading a book on skiing about 20 years ago. (I thought it was something like “The Chi of Skiing”—I remember noting that it did not use the more common eastern religion words like “Tao” or “Zen”. But I can’t find it online. Maybe it’s long out of print.) The book talked about avoiding expectations, and instead trying to anticipate. I’ve learned in the 20 years since first encountering that idea that like so many prescriptions for living, this is much easier said than done.

It’s impossible to definitively test the influence of expectations on experience, of course, since we can’t rewind time and re-experience something with different expectations. But it could be statistically measured. It would be interesting to expose one group of people to negative reviews of a movie, for example, and another to positive reviews (and have a control group that knows nothing about the movie) and then analyze their ratings afterward. I suspect that (if most people are like me), negative expectations can often lead to my enjoying something more. (Provided it’s not completely horrid or absolutely great. I think this effect is strongest on shaping one’s opinion of a mediocre experience.)

But enough philosophizing. The reason I bring this up is that I’ve noticed this expectation effect twice lately. Last Thursday, while I was in Chicago for PyCon, I took the afternoon off and walked around the city. As it got late (and as I tired from all the walking) I decided I was in the mood for a movie. (I hadn’t seen one in a couple months.) I chose Watchmen. I enjoyed the graphic novel, which I read last year after I read a glowing recommendation of a friend. (He wrote something like “best graphic novel ever”, or maybe even “best novel ever”.) My expectations were high, especially after I saw that it is the only graphic novel to appear on Time’s “All-TIME 100 Greatest Novels” list. I enjoyed it, but I didn’t love it. (I suspect I would have enjoyed it more without such high expectations.) But I went into the movie with low expectations. I had seen some middling reviews, and heard some of a very negative review on the Slate Culture Gabfest (no. 29) before I skipped it to avoid spoilers. I enjoyed the movie immensely. It wasn’t great. But I had a very good time, and didn’t notice that it was long. I suspect I may not have enjoyed it as much if I had high expectations.

Yesterday I finished listening to Speaker for the Dead. I wrote about listening to the audiobooks Ender’s Game and Ender in Exile a little over a month ago in my Pleasures of a poor memory post. I had completely forgotten it. It was like reading (or hearing) it for the first time. But I had high expectations. I remember noting it as perhaps my favorite SF novel. Sadly, I wouldn’t rank it so highly anymore. Perhaps Orson Scott Card’s observations of human nature aren’t as impressive to me after I’ve acquired 25 more years of experience (and perhaps a tiny bit of wisdom). But I suspect the damping effect of my high expectations had a lot to do with it.

I guess my lesson is that to maximize my enjoyment, I should always expect the worst.

Speaker for the Dead did finish well though. Well enough that I just downloaded Xenocide (the next in the Ender series). I’m going to try not to expect much. (My expectations are lower actually, since I recall the series goes downhill after Speaker for the Dead.)

Friday, March 6, 2009

A tr.im TextExpander snippet that works for me

At the end of A TextExpander snippet to paste quoted text I gave myself a to-do to create (or find) a TextExpander snippet to create a tr.im shortened URL. tr.im is currently my favorite URL shortening service. Not only is the domain short and easy to remember, but (if you sign up for an account) they provide stats for each “tr.immed” URL.

A Google search found this post on the SmileOnMyMac Blog (from the makers of TextExpander), where you can download a snippet that works. But it’s unnecessarily complicated. After reading the tr.im API documentation I simplified it to this shell script:
#! /bin/bash
curl -u yacitus:xxxxx http://api.tr.im/api/trim_simple?url=`pbpaste`
Note that Blogger refuses to make this column any wider or use a scrollbar to show all of this code. But the text is there; just copy it and paste into your favorite text editor. (You'll need to use the same trick to see all of the code for the other bash one-liner and the Python code below.)

(You’ll of course want to replace “yacitus” with your tr.im username and replace “xxxxx” with your password.)

The problem with this is that it doesn’t work for me at work, where I use the Authoxy proxy server. I can make it work with:
#! /bin/bash
curl -u yacitus:xxxxx -x localhost:8080 http://api.tr.im/api/trim_simple?url=`pbpaste`
…but then it doesn’t work when I’m at home (and not using Authoxy). curl, unfortunately, doesn’t auto-detect proxy settings.

Once again, Python comes to the rescue. I read in “Fuzzyman’s” urllib2 - The Missing Manual that the Python urllib2 module will auto-detect proxy settings, so I wrote this script:
#!/usr/bin/env python
"""
This script writes to stdout a tr.im version of the indicated URL.

"""

import urllib2
import sys


TRIM_API_URL = 'http://api.tr.im/api'
USERNAME = 'yacitus'
PASSWORD = 'xxxxx'


def main():
"""The entry function."""
url_to_trim = sys.argv[1]
if not url_to_trim:
print "ERROR: one (and only one) argument accepted--the URL to GET"
return -1

response = urllib2.urlopen('%s/trim_simple?url=%s&username=%s&password=%s'
% (TRIM_API_URL,
url_to_trim,
USERNAME,
PASSWORD))
print response.read().strip()

print response.code

return 0



if __name__ == '__main__':
sys.exit(main())
Like in A TextExpander snippet to paste quoted text, I put this in a file called trim_url, did a chmod +x on it, created a symbolic link to it in /usr/local/bin/, and created my TextExpander snippet:










I could have saved myself a lot of time if I had stopped there. But I read on http://tr.im/api that basic HTTP authentication is preferred over the query string parameters I used above. So I figured it would be a learning opportunity to implement basic HTTP authentication in Python. The problem is, I’m not done learning yet! I have yet to get it to work. I posted my question on the BayPIGgies mailing list where I got some good advice on how to debug it (but no one saw the problem), and I also posted a question on stackoverflow.com where I got one answer that may be an improvement on the query string parameters, but again no one saw the problem. I guess I’ll have to take jj’s suggestion and look at what is being sent over the wire. When I figure it out I’ll post the answer on my PyPap blog (and of course on the BayPIGgies mailing list and stackoverflow.com).

Tuesday, March 3, 2009

A TextExpander snippet to paste quoted text

I prefer the inline replying posting style. So a frequent workflow for me is copying text, pasting it into BBEdit, applying "Increase Quote Level", "Rewrap quoted text...", "Select All", "Copy" and then pasting the text into (typically) Mailplane, where I finish composing my email. (Or if I'm running Outlook in Fusion, I may compose the email entirely in BBEdit and paste it as a whole back into Outlook.) Each time I do this, I get that "there's got to be a better way" itch. (But then I get back to what I'm working on and forget about it until next time.)

Yesterday I was reading Dan Frakes' "Plain Clip revisited" MacGem post, which explains how to use the free (donations excepted) Plain Clip utility with TextExpander to automatically paste whatever is in the clipboard with any formatting information removed when you type "ptp" (which is the abbreviation he chose to assign to this "snippet" in TextExpander). I need to do that occasionally (and again, I've been doing it by pasting into BBEdit and then copying back to the clipboard), so I downloaded Plain Clip and a free trial of TextExpander and began setting it up. Dan Frakes uses an AppleScript to run Plain Clip through the command-line. But I noticed I can define a shell script in TextExpander so I don't need to bother with an AppleScript "do shell script" wrapper. But I couldn't get it to work. I quickly found a link in the comments to Gordon Meyer's "A tip for using Plain Clip with TextExpander" blog post, which solved the problem for me.

And that's when a light bulb finally went off in (over?) my head. If I created a simple command-line utility to do word wrapping, I could create a TextExpander snippet to paste quoted text. And about 30 minutes later that's just what I had.

When I need to create a command-line utility, I almost always turn to Python. And as is so often the case with Python's "batteries included" nature, I found a textwrap module that provided almost everything I needed.
#!/usr/bin/env python
"""
This script wraps the textwrap module with a command-line interface.

"""

import optparse
import sys
from textwrap import TextWrapper


DEFAULT_WIDTH = 70
DEFAULT_QUOTE_STRING = '> '


def main():
"""The entry function."""
parser = optparse.OptionParser(description='Text wrapper', prog='wwrap')
parser.add_option('-w', '--width',
action='store',
metavar='NUM',
default='%d' % DEFAULT_WIDTH,
help='maximum length of wrapped lines; defaults to 70')
parser.add_option('-q', '--quote',
action='store_true',
default=False,
help="add '%s' to start of each wrapped line"
% DEFAULT_QUOTE_STRING)
parser.add_option('-r', '--remove',
action='store',
metavar='TXT',
help='remove TXT from start of each line prior to'
' wrapping')
parser.add_option('--removequotes',
action='store_true',
default=False,
help="remove '%s' from the start of each line prior"
" to wrapping" % DEFAULT_QUOTE_STRING)

options, arguments = parser.parse_args()

if not options.width:
print "I don't know how the width wasn't specified, since it's"
print "supposed to default to %d. Aborting." % DEFAULT_WIDTH
return -1

try:
width = int(options.width)
except ValueError:
print "ERROR: the width specified ('%s') is not a number" % (
options.width)
return -1

if options.remove and options.removequotes:
print "ERROR: cannot use both --remove and --removequotes options"
return -1

if options.removequotes:
options.remove = DEFAULT_QUOTE_STRING

wrapper = TextWrapper()
if options.quote:
wrapper.initial_indent = DEFAULT_QUOTE_STRING
wrapper.subsequent_indent = DEFAULT_QUOTE_STRING
wrapper.width = width

lines = sys.stdin.read().split('\n')
if options.remove:
for i, line in enumerate(lines):
if line.startswith(options.remove):
lines[i] = line[len(options.remove):]

print wrapper.fill('\n'.join(lines))

return 0




if __name__ == '__main__':
sys.exit(main())
Note that even though you can't see the code at the end of long lines, it's there. Just copy it all and paste it into your favorite text editor to read it all.

This code should be quite self-explanatory. As is (also) so often the case with Python, the "meat" of these 81 lines are the 7 lines starting with line 67 where I read in the text to be wrapped from stdin. All the preceeding lines are for handling the command-line options.

I put this in a file called "wwrap" and did a `chmod +x` on it. I then created a symbolic link to it in /usr/local/bin/, and I was ready to create my TextExpander snippet.

















Now I can just type 'qtp' and the quoted, wrapped form of whatever text is in the clipboard is pasted in.

I'm inspired to look for more workflows I can simplify with TextExpander and possibly Python. (I'm going to start by trying to figure out how to re-create the "Create tr.im shortened URL" in Dan Frakes' TextExpander screenshot.)