atom-tools’ *NIX tools
atom-tools’ bin directory has several UNIXy tools that I’ve never really mentioned before.
These tools operate on “collections”. I’m using the term in a broader sense than RFC 5023; a “collection” can be an AtomPub Collection, a directory containing Atom Entries, or a feed on stdin or stdout.
atom-cp
atom-cp copies the contents of a source collection to a destination collection.
atom-grep
atom-grep prints a feed to stdout containing all the entries in the source feed that match a given regexp.
atom-purge
atom-purge DELETEs every entry in the given collection.
atom-post
atom-post POSTs the contents of a file or stdin to a given URL.
It doesn’t do anything fancy, it’s just a convenient way of getting media or an Entry created by some other tool onto the web. Eventually this will construct Entries too, but not yet.
Use Cases
Back up your blog:
atom-cp http://example.org/coll ./backup/
Restore a backup, or post several pre-created entries:
atom-cp ./backup/ http://example.org/coll
Delete spam:
atom-grep poker http://example.org/comments | atom-purge -
Plagiarise somebody else’s blog:
atom-grep "popular content" http://example.org/coll | atom-cp - http://example.com/seo
Post a picture to your media collection:
atom-post -m image/png http://example.org/media icon.png
(Disclaimer: XML is a terrible format to pass down a pipe. It’s awfully convenient though, and my pipes and my collections haven’t been long enough for it to be a problem.)
about laboratory
This is the blog of Brendan Taylor. I try to stick to things of a technical nature here.
This exists as a record for myself. Anything you get out of it is a bonus.
It runs on custom software that I would be happy to share.
Seasonal Terminology
A word to describe the warmest part of the year is useful to everyone who ever goes outside.
A word to describe the period of time between a solstice and an equinox is only useful to astronomers, calendographers and people desperate for small talk.
Happy first day of summersolstice.
Google just released some statistics for GSoC 2008, which reminded me of something I’d noticed in last year’s Student/Mentor map:
- lots of people in and around Vancouver
- a couple of people scattered throughout BC
- two people in Calgary
- two people in Edmonton
And then a huge gap until Toronto.
Western Canada isn’t exactly a centre of exciting software activity. :(
Too many Ruby Atom libraries
Ruby now has 3 Atom Publishing Protocol libraries: atom-tools, atomutil and ratom. They all use the Atom namespace, and they’re all incompatible. Not a great situation.
ratom uses libxml-ruby rather than REXML. It’s embarassingly faster than atom-tools. ratom can parse the 1100 Atom Entries in my Venus cache in 0.25s; atom-tools takes 6s.
I haven’t been able to get atomutil to work. I expect it is faster than atom-tools, too (though not nearly so dramatically); atom-tools parses an XML tree into a tree of Ruby objects (instead of just wrapping the XML tree). This may have been a mistake.
atom-tools 2.0
Published atom-tools 2.0 a few days ago.
The XML parsing and building has been completely reworked. This should make handling extensions much easier.
A big feature for people writing clients is HTTP caching support (ported from Joe Gregorio’s httplib2). I actually commited this to the darcs repository the same day I published 1.0 but never released a 1.1 version (oops!).
It’s got some new UNIX-y tools that I’ll write about later.
I’ve gotten rid of the YAML mapping entirely; it wasn’t as human-read/writeable as I had hoped. I think there’s promise in doing something with Maruku for that.
I’m slowly moving from Test::Unit to rspec (thanks to a lot of grunt work by Simon Rozet). I think the result is a lot cleaner.
I’ve tried to keep things as backwards-compatible as possible, but some things have changed since the 1.0 release. The main difference is that Atom::Collection now represents an app:collection element, instead of just being a fancy Atom::Feed.
Civic Duty Alberta: 2008
I decided on a whim to vote in the provincial election yesterday.
The voting process was rather quaint; mark an X in the church basement and give your paper to the nice old lady. Edmonton-Strathcona is a University riding, so almost nobody at the polling station was registered (including myself) - students move too often.
I have little faith in representative democracy’s ability to be either representative or democratic at the best of times. I have even less faith in it in this province, which has had the same party in power for the past 37 years.
Election results confirm my disaffection; another huge majority for the Progressive Conservative party. 88% of the seats with only 53% of the popular vote; first past the post is a marvellous thing. (I especially like the part where the people with the power to change the system have the most to gain from the status quo.)
The Wildrose Alliance came in (a distant) second in Whitecourt-Ste. Anne, my parents’ riding. The candidate? Link Byfield, of Alberta Report fame. I cannot begin to express my distaste.
Once I’m done my degree, I’m out of here.
PushPin 2.0
I’ve rewritten PushPin, my Atom Publishing Protocol client. I’ve moved from Camping to Rails, giving the application some much-needed structure.
Major new features:
- stored passwords are encrypted with AES
- media collections
- service document autodiscovery
- AuthSub (I’m not sure if RFC 5023 support has been pushed onto mainline Blogger yet, though)
The UI should be much more polished, too (although there’s still lots of room for improvement).
Since I’ve got this this blog’s comments coming in via AtomPub, they’ll be broken until I implement OAuth.
In Vancouver, the crocuses are budding. Here in Edmonton, it’s just become warm enough to make snowmen.
Celebrating the New Year with Shoes

A bit late for most of the world, but I’ll post it anyways.
Finished cleaning the apartment and waiting for guests to arrive, I thought I’d play around a bit with Shoes. Turns out it’s a lot of fun!
require "time"
midnights = [ [ 5, 'Rio de Janeiro' ],
[ 4, 'Santiago' ],
[ 3.5, "St. John's" ],
[ 3, 'Halifax' ],
[ 2, 'Montréal' ],
[ 1, 'Winnipeg' ],
[ 0, 'Edmonton' ],
[ -1, 'Vancouver' ],
[ -2, 'Anchorage' ],
[ -3, 'Honolulu' ],
[ -4, 'Auckland' ] ]
new_year = Time.parse "2008-01-01"
Shoes.app do
background rgb(0,0,0)
stack do
seconds_left = (new_year - Time.now).to_i
midnight_ps = midnights.map do |offset,place|
para "#{place}: #{seconds_left - offset * 3600}", :stroke => white
end
animate(1) do |i|
seconds_left = (new_year - Time.now).to_i
midnight_ps.each_with_index do |p,i|
offset, place = midnights[i]
s = seconds_left - offset * 3600
stroke = s > 0 ? white : gray(90)
if s.abs < 500
size = 200
else
size = 100_000 / s.abs
end
p.replace "#{place}: #{s}", :font => "Arial #{size}px", :stroke => stroke
end
end
end
end