Feb 15

Automator: Often too overlooked

Tech 1 Comment »

My unix roots often make me jump to shell/ruby/perl when AppleScript is a better choice, especially with the Automator.

I wanted to automatically download the WebKit nightly build for testing, and instead of opening downloadwebkit.sh to wget, open, cp -r, etc I remembered to open up automator and build a simple workflow.

Many developers hate UIs and just want to vi a file and start typing. This is a good example of a useful UI as it helps you find the API that is available (much nicer than grep) and you can drop down into AppleScript too.

webkitautomator.png

Feb 14

gspreadsheet: running formulas from the command line

Google, Ruby, Tech 8 Comments »

I am spending time hacking away on Google APIs to really see what it is like.

I remember seeing the Google Spreadsheet Data API that allows you access to spreadsheets in Google Docs & Spreadsheets.

There is a full API that gives you access to create and modify spreadsheets even to the level of REST requests for each cell.

I was also surprised at the number of formulas available.

Suddenly I realised that I could create a spreadsheet and use a cell to do various calculations for me, so I hacked up a ruby script to do this:

% gspreadsheet [insert formula]
e.g.
% gspreadsheet ‘GoogleFinance(”GOOG”)’
467.3
% gspreadsheet ’sin(0.2)’
0.19866933079506

Behind the scenes the script used the Google APIs to put the formula in a cell, and then read from that field to get the calculated output.

Writing the script

To get this all working I just had to:

  • Find a Ruby library to the Google APIs
  • Work out how to authenticate using the Google ClientLogin API
  • Work out the location for the REST requests
  • Work out why I was getting a 404 error

Find a Ruby library to the Google APIs

I was surprised to not be able to find a nice API to Google Spreadsheets. I did find this script that helped a lot though.

I am working on packaging a gdata-ruby module that I will place in rubyforge soon. It will start out with just APIs such as ClientLogin and Spreadsheets, but hopefully we can grow it to cover more of them.

Work out how to authenticate using the Google ClientLogin API

The key to authentication is using the ClientLogin API to get the auth token, and hiding it away in a member variable so other requests will add it to the headers:

response = Net::HTTPS.post_form(https://www.google.com/accounts/ClientLogin,
{'Email'   => email,
'Passwd'  => password,
'source'  => "formula",
'service' => 'wise' })
@headers = {
'Authorization' => "GoogleLogin auth=#{response.body.split(/=/).last}",
'Content-Type'  => 'application/atom+xml'
}

Work out the location for the REST requests

To find out the location for feeds it helps to GET the feeds themselves and look for the post URLs in link tags.

To get the A1 cell (a.k.a. R1C1) you would use something like:

/feeds/cells/#{@spreadsheet_key}/1/#{@headers ? “private” : “public”}/basic/A1″

  • The spreadsheet key is the magic key for each of your spreadsheets that looks something like: pSYwzniwpzSFfn0KFRg9oWB.
  • The 1 right after that is the worksheet id.
  • The private/public check get changed in this based on if the code is authenticating you or not (and if you have allowed public access to the spreadsheet in question).
  • The ‘basic’ is a projection value. basic means just basic atom. ‘values’ means a full feed minus formula data, and ‘full’ means a full read/write feed with everything
  • Finally we give the A1 cell info

For reading this cell we just used basic projection, but for writing data into the cell we need to use the URL:

“/feeds/cells/#{@spreadsheet_key}/1/#{@headers ? ‘private’ : ‘public’}/full”

Notice that we use full here (as we want full access) and yet we do not put in the cell in question. This is because we will POST or PUT an entry piece of XML:

<entry xmlns='http://www.w3.org/2005/Atom' xmlns:gs='http://schemas.google.com/spreadsheets/2006'>
<gs:cell row='1' col='1' inputValue='=sin("0.2")' />
</entry>

This has the row and column and input value (in this case a formula).

Work out why I was getting a 404 error

At first I was getting 404 errors when I posted data up. The reason was that I wasn’t putting the full namespaces in the entry doc:

<entry xmlns='http://www.w3.org/2005/Atom' xmlns:gs='http://schemas.google.com/spreadsheets/2006'>

vs.

<entry>

XML always seems so frustrating and when these things happen. Really? You couldn’t work out what to do without that namespace? Really? Nice and forgiving. Give me JSON or YAML ;)

The full code

It was fun to be able to be productive with these APIs immediately because they are just basic REST actions that just require Net::HTTP to access. I will work on getting some nice helper libraries so the low level stuff doesn’t even need to be done.

For those that are interested, here is the quick hack as one script file. The code is ugly… I am sorry. The library version is a lot nicer (and is just a few lines of code after the require’s). You can also get weird behaviour if you use single ticks. For now use ” and all is well.

gspreadsheet

#!/usr/bin/env ruby

require 'net/http'
require 'net/https'
require 'uri'
require 'rubygems'
require 'hpricot'

#
# Make it east to use some of the convenience methods using https
#
module Net  class HTTPS < HTTP
def initialize(address, port = nil)
super(address, port)
self.use_ssl = true
end
end
end

class GoogleSpreadSheet
GOOGLE_LOGIN_URL = URI.parse('https://www.google.com/accounts/ClientLogin')

def initialize(spreadsheet_key)
@spreadsheet_key = spreadsheet_key
@headers = nil
end

def authenticate(email, password)
$VERBOSE = nil
response = Net::HTTPS.post_form(GOOGLE_LOGIN_URL,
{'Email'   => email,
'Passwd'  => password,
'source'  => "formula",
'service' => 'wise' })
@headers = {     'Authorization' => "GoogleLogin auth=#{response.body.split(/=/).last}",
'Content-Type'  => 'application/atom+xml'
}
end

def evaluate_cell(cell)
path = "/feeds/cells/#{@spreadsheet_key}/1/#{@headers ? "private" : "public"}/basic/#{cell}"

doc = Hpricot(request(path))
result = (doc/"content[@type='text']").inner_html
end

def set_entry(entry)
path = "/feeds/cells/#{@spreadsheet_key}/1/#{@headers ? 'private' : 'public'}/full"

post(path, entry)
end

def entry(formula, row=1, col=1)
<<XML
<?xml version='1.0' ?>
<entry xmlns='http://www.w3.org/2005/Atom' xmlns:gs='http://schemas.google.com/spreadsheets/2006'>
<gs:cell row='#{row}' col='#{col}' inputValue='=#{formula}' />
</entry>
XML
end

def add_to_cell(formula)    #puts entry(formula)
set_entry(entry(formula))
end

private
def request(path)
response, data = get_http.get(path, @headers)
data
end

def post(path, entry)
get_http.post(path, entry, @headers)
end

def get_http
http = Net::HTTP.new('spreadsheets.google.com', 80)
#http.set_debug_output $stderr
http
end
end

if __FILE__ == $0
formula = ARGV.first || 'sin(0.2)'

gs = GoogleSpreadSheet.new([INSERT YOUR SPREADSHEET KEY])
gs.authenticate('[email protected]', 'your password')
gs.add_to_cell formula
puts gs.evaluate_cell('A1')
end
Feb 14

Spanning Sync: iCal and Google Calendar

Apple, Google, Tech 2 Comments »

I was ready to get frustrated. I wanted it all.

If an event is sent to my Gmail account I want to be able to just click ‘add it’ and see conflicts.

I want to have iCal up to date for offline / nice rich app use.

I want to be able to create events in iCal OR Google Calendar and for everyone to be happy.

I was ready to sigh and just have iCal as a read-only offline view, or to not use Google Calendar, when I stumbled on Spanning Sync which does the hard work to get true two-way syncing. It is still in beta (which is worrying with a tool that can nuke your data) but it is working nicely, and backups are happening frequently.

Feb 13

Join the vi emacs debate tonight in the bay area

Tech 3 Comments »

I just had two emails come in at once:

  1. People fighting about vi vs. emacs
  2. A reminder that Bram Moolenaar, creator of Vim, is speaking tonight at Google’s Mountain View headquarters at 7pm (Tuesday, February 13th)
  3. Bram Moolenaar, creator of the Vim text editor and Software Engineer in Google’s Zurich office, will be visiting our Mountain View headquarters on Tuesday, February 13th to discuss the “Seven habits for effective text editing, 2.0.” Bram’s presentation will give an overview of several ways to effectively use Vim to edit programs, structured text and documentation.

    Please join us for Bram’s presentation if you’re in the area. Doors will open at 6:30 PM and Bram will begin speaking at 7:00 PM. Refreshments will be served; please plan to sign in at Building 41 reception when you arrive.

    For those of you who were unable to attend the last session of the Open Source Developers @ Google Speaker Series, you can check out the video and slides from Ben Collins-Sussman and Brian Fitzpatrick’s talk on “How Open Source Projects Survive Poisonous People (And You Can Too).

    Since people not in the valley can read this blog, don’t worry, the talk will be put on Google Video shortly.

Feb 12

Enso Launcher: Windows people can get quickly silvered

Microsoft, Tech 6 Comments »

You often hear Mac folk talking about Quicksilver and how they love it. It is more than a launcher.

Now there is something interesting in the Windows world (better than adding shortcut keys to your applications).

Enso Launcher is now out in the wild.

I first saw Enso Launcher at the last Ajax Experience, as Aza Raskin was showing it off (and his love for Python).

They also released Enso Words showing off spellcheck everywhere.

So, if you hate the mouse and you are a Windows bloke, open http://www.humanized.com/products/enso/launcher/ and go.

enzolauncher.png

Feb 11

Hard to call it a win (England cricket team in Australia)

British, Personal, Sport 3 Comments »

It is a little comical that the English cricket team could win in the one day tournamant in Australia.

Only “we” could lose ~15 games, and then somehow win a couple in a row to end up victorious.

Feb 10

A docking station for the Macbook Pro

Tech 9 Comments »

I admit to missing the docking station with my Macbook Pro. It may be a small thing, but being able to just slide in a laptop and be set is nicer than futzing with chords and is one of those things that makes me less willing to jump around the house with the laptop (that and the fact that when ‘docked’ it is to a 30″ monitor).

But now
there is a docking station for the Macbook Pro
:


Not quite as elegant as a PC one huh. I hope that it is good so I can tease Ben who just moved to a 17″ Macbook pro (and that won’t fit of course).

Feb 09

11/10 Central

Personal 1 Comment »

I have heard ads for tv shows saying “8/7 Central” for a long time.

When I have lived on the east coast I always wished that shows were on earlier.

The Daily Show at 10pm is a lot nicer than 11pm.

Now I am on the west coast I assumed that it would at least be earlier. I know they aren’t going to put it on 3 hours earlier, but I thought that at least 10pm should work. I was wrong. I guess the TV guys know best, and work out that “we should put it on at 10pm Central as those middle country people go to bed early”.

The only upside is that we have time to get Sam to bed and most shows are still far from starting. I think that we will also be watching even more TV time shifted the next day, or on the Motherload.

Feb 09

IntelliRuby

Ruby, Tech 2 Comments »

I’ve got to admit it’s getting better
a little better all the time

IntelliJ Ruby support keeps getting better.

I wish there was a lightweight mode where I could just open one .rb file and have it edit without needing the project setup.

intelliruby.png

Feb 08

Seashore: Nice mac simple image editor

Tech 2 Comments »

Sometimes you don’t want the power of Photoshop (or you don’t want to fork out the money for it).

The Gimp doesn’t quite do it for me. Even GimpShop. It is just different enough to drive me crazy from time to time. The default selection tool color of yellow baffles my mind (yellow on white, nice and easy to see!).

I am always on the lookout for something good to take care of the simple tasks.

Picnik is surprisingly good for the uber-simple tasks (resizing, rotating, etc) but as soon as you want to chop and change you want to go elsewhere.

I was happy to hear about Seashore which uses code from The Gimp, but seems to be a lot nicer to use. A nice addition for the middle of the road tasks.