<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/atom10full.xsl" type="text/xsl" media="screen"?><?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/itemcontent.css" type="text/css" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:gd="http://schemas.google.com/g/2005" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;DkIFQX84eyp7ImA9WxRQEUg.&quot;"><id>tag:blogger.com,1999:blog-6525469191850690957</id><updated>2008-10-04T17:08:30.133-04:00</updated><title>persistent.info</title><subtitle type="html" /><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://blog.persistent.info/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://blog.persistent.info/" /><link rel="next" type="application/atom+xml" href="http://blog.persistent.info/feeds/posts/default?start-index=26&amp;max-results=25" /><author><name>Mihai Parparita</name><uri>http://www.blogger.com/profile/12343650264888591427</uri><email>noreply@blogger.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>377</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><link rel="self" href="http://feeds.feedburner.com/PersistentInfo" type="application/atom+xml" /><feedburner:feedFlare href="http://add.my.yahoo.com/rss?url=http%3A%2F%2Ffeeds.feedburner.com%2FPersistentInfo" src="http://us.i1.yimg.com/us.yimg.com/i/us/my/addtomyyahoo4.gif">Subscribe with My Yahoo!</feedburner:feedFlare><feedburner:feedFlare href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2FPersistentInfo" src="http://www.newsgator.com/images/ngsub1.gif">Subscribe with NewsGator</feedburner:feedFlare><feedburner:feedFlare href="http://feeds.my.aol.com/add.jsp?url=http%3A%2F%2Ffeeds.feedburner.com%2FPersistentInfo" src="http://o.aolcdn.com/favorites.my.aol.com/webmaster/ffclient/webroot/locale/en-US/images/myAOLButtonSmall.gif">Subscribe with My AOL</feedburner:feedFlare><feedburner:feedFlare href="http://www.bloglines.com/sub/http://feeds.feedburner.com/PersistentInfo" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare href="http://www.netvibes.com/subscribe.php?url=http%3A%2F%2Ffeeds.feedburner.com%2FPersistentInfo" src="http://www.netvibes.com/img/add2netvibes.gif">Subscribe with Netvibes</feedburner:feedFlare><feedburner:feedFlare href="http://fusion.google.com/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2FPersistentInfo" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><feedburner:feedFlare href="http://www.pageflakes.com/subscribe.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2FPersistentInfo" src="http://www.pageflakes.com/ImageFile.ashx?instanceId=Static_4&amp;fileName=ATP_blu_91x17.gif">Subscribe with Pageflakes</feedburner:feedFlare><entry gd:etag="W/&quot;C04DR3o7cCp7ImA9WxdTFUg.&quot;"><id>tag:blogger.com,1999:blog-6525469191850690957.post-3280863692104848287</id><published>2008-05-11T20:26:00.001-04:00</published><updated>2008-05-11T20:26:16.408-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-05-11T20:26:16.408-04:00</app:edited><title>Porting Twitter Digest to Google App Engine</title><content type="html">&lt;p&gt;I've been meaning to play around with &lt;a href="http://appengine.google.com/"&gt;Google App Engine&lt;/a&gt; for a while, and as a quick project, I decided to port &lt;a href="http://blog.persistent.info/2007/08/twitter-digest.html"&gt;Twitter Digest&lt;/a&gt; to it (not as exciting as Kushal's &lt;a href="http://blog.kushaldave.com/2008/04/30/introducing-the-millidunst-calculator/"&gt;Millidunst Calculator&lt;/a&gt;). This looked to be pretty straightforward: the original version was already in Python, and wasn't very complicated (just a single CGI script). It did indeed end up pretty easy; the whole process took a couple of hours.&lt;/p&gt;

&lt;p&gt;The first step was to port the script from CGI-style invocation to the App Engine &lt;a href="http://code.google.com/appengine/docs/webapp/"&gt;webapp&lt;/a&gt; framework. Then I looked into what it would take to get &lt;a href="http://code.google.com/p/python-twitter/"&gt;Python Twitter&lt;/a&gt; (the library I used for fetching data from Twitter) running. Switching it from urllib2 to &lt;a href="http://code.google.com/appengine/docs/urlfetch/"&gt;urlfetch&lt;/a&gt; was pretty painless (though I don't use the posting parts of the API, so I didn't check if those work too). The other part of the library that I was relying on was its caching mechanism (since the digests are daily, there's no point in querying Twitter more often). &lt;a href="http://blog.unto.net/"&gt;DeWitt&lt;/a&gt; (the library's author) had thoughtfully put the caching functionality into a separate class, so it was easy to replace it with another one that implemented the same interface but was backed by App Engine's &lt;a href="http://code.google.com/appengine/docs/datastore/"&gt;datastore&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://twitter-digest.appspot.com/"&gt;The result&lt;/a&gt; (complete with &lt;a href="http://appgallery.appspot.com/about_app?app_id=agphcHBnYWxsZXJ5chMLEgxBcHBsaWNhdGlvbnMYyQsM"&gt;App Gallery entry&lt;/a&gt;) is not that exciting, in the sense that it functions identically to &lt;a href="http://persistent.info/twitter-digest/"&gt;the original&lt;/a&gt;. The only issue that I've run into so far is that when there are several cache misses, the URL fetches can take long enough that the request hits App Engine's deadline. However, since the successful fetches are cached, repeating the request will eventually succeed (so if consuming the digest via a feed, this shouldn't be a big deal). Ideally the &lt;code&gt;urlfetch&lt;/code&gt; functionality would also support asynchronous fetches, since it would be easy to adapt the code to fetch all user timelines in parallel.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/PersistentInfo/~4/288335460" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.persistent.info/feeds/3280863692104848287/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.persistent.info/2008/05/porting-twitter-digest-to-google-app.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6525469191850690957/posts/default/3280863692104848287?v=2" /><link rel="self" type="application/atom+xml" href="http://blog.persistent.info/feeds/posts/default/3280863692104848287" /><link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/PersistentInfo/~3/288335460/porting-twitter-digest-to-google-app.html" title="Porting Twitter Digest to Google App Engine" /><author><name>Mihai Parparita</name><uri>http://www.blogger.com/profile/12343650264888591427</uri><email>noreply@blogger.com</email></author><feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=PersistentInfo&amp;itemurl=http%3A%2F%2Fblog.persistent.info%2F2008%2F05%2Fporting-twitter-digest-to-google-app.html</feedburner:awareness><feedburner:origLink>http://blog.persistent.info/2008/05/porting-twitter-digest-to-google-app.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkABR3g4fip7ImA9WxZaEEk.&quot;"><id>tag:blogger.com,1999:blog-6525469191850690957.post-3393553598065557339</id><published>2008-04-24T08:38:00.000-04:00</published><updated>2008-04-24T08:39:16.636-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-04-24T08:39:16.636-04:00</app:edited><title>Intern on the Google Reader team</title><content type="html">&lt;p&gt;Having interns has worked out well for the Reader team. Following &lt;a href="http://blog.persistent.info/2007/03/intern-on-google-reader-team.html"&gt;my blog post&lt;/a&gt;, we were very pleased to get Nitin Shantharam and Jason Hall to help us out with Reader development. Their stints on the team resulted in a &lt;a href="http://googlereader.blogspot.com/2007/11/attack-of-interns-recommendations-and.html"&gt;a bunch of features&lt;/a&gt;, and Jason is now back at Google working full-time (Nitin wasn't a slacker, he's just still in school).&lt;/p&gt;

&lt;p&gt;We're looking for another intern or two this year. Internships generally last a couple of months to twelve weeks, are for full-time students, and would be in Google's &lt;a href="http://www.google.com/support/jobs/bin/static.py?page=why-ca-mv.html"&gt;Mountain View, California&lt;/a&gt; office. You can work on either Reader's backend (a C++ system for crawling millions of feeds, handling lots of items being read, shared, starred or tagged per second) or frontend (Java servers and JavaScript/AJAX-y craziness) depending on your interests and experience.&lt;/p&gt;

&lt;p&gt;If you or anyone you know is interested in this internship, contact me at &lt;code&gt;mihaip at google dot com&lt;/code&gt;. &lt;a href="http://www.google.com/support/jobs/bin/static.py?page=students.html&amp;sid=internships"&gt;This page&lt;/a&gt; also has more general information about interning at Google.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/PersistentInfo/~4/276882116" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.persistent.info/feeds/3393553598065557339/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.persistent.info/2008/04/intern-on-google-reader-team.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6525469191850690957/posts/default/3393553598065557339?v=2" /><link rel="self" type="application/atom+xml" href="http://blog.persistent.info/feeds/posts/default/3393553598065557339" /><link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/PersistentInfo/~3/276882116/intern-on-google-reader-team.html" title="Intern on the Google Reader team" /><author><name>Mihai Parparita</name><uri>http://www.blogger.com/profile/12343650264888591427</uri><email>noreply@blogger.com</email></author><feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=PersistentInfo&amp;itemurl=http%3A%2F%2Fblog.persistent.info%2F2008%2F04%2Fintern-on-google-reader-team.html</feedburner:awareness><feedburner:origLink>http://blog.persistent.info/2008/04/intern-on-google-reader-team.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkMHRng4eyp7ImA9WxZUEkk.&quot;"><id>tag:blogger.com,1999:blog-6525469191850690957.post-7276228201441256054</id><published>2008-04-03T14:46:00.000-04:00</published><updated>2008-04-03T14:47:17.633-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-04-03T14:47:17.633-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Meta" /><title>persistent.coffee</title><content type="html">&lt;p&gt;I've been trying my hand at &lt;a href="http://en.wikipedia.org/wiki/Latte_art"&gt;latte art&lt;/a&gt;. Though I have &lt;a href="http://www.flickr.com/photos/tonx/sets/48921/"&gt;a very long way to go&lt;/a&gt;, I've been  documenting my efforts, with a hope of learning from my mistakes. Blogger's &lt;a href="http://www.blogger.com/mobile-start.g"&gt;mobile&lt;/a&gt; support makes it pretty easy to collect pictures, and I've finally gotten around to making a decent template for the "blog."&lt;/p&gt;

&lt;p&gt;&lt;a href="http://coffee.persistent.info"&gt;coffee.persistent.info&lt;/a&gt; is the result. Technically, this isn't a Blogger template, since I just have some static HTML as the content. Instead, it uses the &lt;a href="http://googledataapis.blogspot.com/2006/11/calling-all-web-hackers-json-support.html"&gt;JSON output&lt;/a&gt; that Blogger's GData API supports. Rendering the page in JavaScript allows for more flexibility. I wanted to make pictures that I liked take up 4 slots (a layout inspired by &lt;a href="http://twitterposter.com/"&gt;TwitterPoster&lt;/a&gt;). This imposed additional constraints (in order to prevent overlap between sequential large pictures). The display is generally reverse-chronological starting from the top left, but images are occasionally shuffled around to prevent such overlaps. There is also a bit of interactivity, the pictures are clickable to display larger versions. To help with all this, I've been experimenting with &lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt; (also on &lt;a href="http://code.google.com/p/mail-trends/"&gt;Mail Trends&lt;/a&gt;), and am liking it quite a bit.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/PersistentInfo/~4/263498688" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.persistent.info/feeds/7276228201441256054/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.persistent.info/2008/04/persistentcoffee.html#comment-form" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6525469191850690957/posts/default/7276228201441256054?v=2" /><link rel="self" type="application/atom+xml" href="http://blog.persistent.info/feeds/posts/default/7276228201441256054" /><link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/PersistentInfo/~3/263498688/persistentcoffee.html" title="persistent.coffee" /><author><name>Mihai Parparita</name><uri>http://www.blogger.com/profile/12343650264888591427</uri><email>noreply@blogger.com</email></author><feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=PersistentInfo&amp;itemurl=http%3A%2F%2Fblog.persistent.info%2F2008%2F04%2Fpersistentcoffee.html</feedburner:awareness><feedburner:origLink>http://blog.persistent.info/2008/04/persistentcoffee.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DE8EQ3k6eSp7ImA9WxZVFEg.&quot;"><id>tag:blogger.com,1999:blog-6525469191850690957.post-2375831617290146364</id><published>2008-03-25T10:32:00.011-04:00</published><updated>2008-03-25T10:53:22.711-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-03-25T10:53:22.711-04:00</app:edited><title>Mail Trends</title><content type="html">&lt;p&gt;&lt;img src="http://persistent.info/images/mail-trends-graph.png" width="250" height="145" align="left" style="padding: 5px 3px 2px 0"&gt;I get a lot of email (especially at work). I'm trying a &lt;a href="http://www.43folders.com/izero"&gt;Inbox Zero&lt;/a&gt;-&lt;wbr&gt;&lt;/wbr&gt;like approach in order to keep up with it. Though that's helping me to stay on top of things, I had the nagging feeling that I was probably on too many mailing lists, and that some of them were probably not worth it from a signal-to-noise ratio perspective.&lt;/p&gt;

&lt;p&gt;Ideally something like the &lt;a href="http://googlereader.blogspot.com/2007/01/i-like-big-charts-and-i-cannot-lie.html"&gt;Reader Trends&lt;/a&gt; or &lt;a href="http://www.google.com/history/trends"&gt;Search History Trends&lt;/a&gt; page would exist for Gmail. I thought I could perhaps build it myself, but the absence of an official Gmail API deterred me. However, it occurred to me that the recently added &lt;a href="http://mail.google.com/support/bin/answer.py?hl=en&amp;answer=75725"&gt;IMAP support&lt;/a&gt; could act as an API of sorts. It should be easy to get just the message headers and slice and dice them to extract the stats that I was interested in.&lt;/p&gt;

&lt;p&gt;Thus was born &lt;a href="http://code.google.com/p/mail-trends/"&gt;Mail Trends&lt;/a&gt;, an IMAP-&lt;wbr&gt;&lt;/wbr&gt;based email analysis project. It can generate a bunch of tables, graphs and distributions based on time of day, senders, recipients, mailing lists, etc. To get a feel for what it can output, see &lt;a href="http://persistent.info/mail-trends/enron/"&gt;the results&lt;/a&gt; of running it on a piece of the &lt;a href="http://www.cs.cmu.edu/~enron/"&gt;Enron Email Dataset&lt;/a&gt;. To run it over your own email, see the &lt;a href="http://code.google.com/p/mail-trends/wiki/GettingStarted"&gt;getting started page&lt;/a&gt;. As a caveat, the program currently loads everything into memory, so my run on 200,000 messages resulted in 1.6 gigabytes being used. You may want to use the &lt;code&gt;--max_messages=&lt;/code&gt; flag to limit the dataset, at list for initial runs.&lt;/p&gt;

&lt;p&gt;The project is still in its early stages, so patches and suggestions are definitely welcome (my email address is at the footer). You can also subscribe to &lt;a href="http://persistent.info/mail-trends/svnlog.xml"&gt;the feed of check-ins&lt;/a&gt; to see changes as they are made. The &lt;a href="http://code.google.com/p/mail-trends/wiki/Plan"&gt;plan&lt;/a&gt; wiki page has a very brief outline of what I'm planning on working on next.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/PersistentInfo/~4/257698778" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.persistent.info/feeds/2375831617290146364/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.persistent.info/2008/03/mail-trends.html#comment-form" title="20 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6525469191850690957/posts/default/2375831617290146364?v=2" /><link rel="self" type="application/atom+xml" href="http://blog.persistent.info/feeds/posts/default/2375831617290146364" /><link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/PersistentInfo/~3/257698778/mail-trends.html" title="Mail Trends" /><author><name>Mihai Parparita</name><uri>http://www.blogger.com/profile/12343650264888591427</uri><email>noreply@blogger.com</email></author><feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=PersistentInfo&amp;itemurl=http%3A%2F%2Fblog.persistent.info%2F2008%2F03%2Fmail-trends.html</feedburner:awareness><feedburner:origLink>http://blog.persistent.info/2008/03/mail-trends.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkQFQns4cCp7ImA9WxZVEkw.&quot;"><id>tag:blogger.com,1999:blog-6525469191850690957.post-4967715591011246001</id><published>2008-03-22T14:23:00.001-04:00</published><updated>2008-03-22T14:25:13.538-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-03-22T14:25:13.538-04:00</app:edited><title>Two Safari 3.1 Tips</title><content type="html">&lt;p&gt;&lt;a href="http://www.apple.com/safari"&gt;Safari 3.1&lt;/a&gt; is out, and I've upgraded my Mac to it. Besides some issues with arrow keys in Reader (we're on it), it's working out well. Here are two hidden prefs that you may find useful:&lt;/p&gt;

&lt;pre&gt;defaults write com.apple.Safari IncludeInternalDebugMenu -bool true&lt;/pre&gt;

&lt;p&gt;The &lt;a href="http://www.simplebits.com/notebook/2008/03/18/safari.html"&gt;Develop&lt;/a&gt; menu that 3.1 includes is nice, but it seems to supplant the old "Debug" menu (i.e. the preference key that used to toggle it - &lt;code&gt;IncludeDebugMenu&lt;/code&gt; - now toggles the "Develop" menu). The old menu had functionality that isn't present in the official one, most notably the "Caches" window that displayed the number of live JavaScript objects and made tracking down memory leaks much easier. If you'd like to bring back the old menu, you can use the new &lt;code&gt;IncludeInternalDebugMenu&lt;/code&gt; key shown above&lt;/p&gt;

&lt;pre&gt;defaults write com.apple.Safari TargetedClicksCreateTabs -bool true&lt;/pre&gt;

&lt;p&gt;First &lt;a href="http://tweetscan.com/index.php?s=TargetedClicksCreateTabs"&gt;spotted on Twitter&lt;/a&gt;, this forces new windows to open in tabs, one &lt;a href="http://support.mozilla.com/en-US/kb/Options+window#Tabs_span_style_text_align_left_float_none_clear_none_class_win_Options_span_span_style_text_align_left_float_none_clear_none_class_noWin_Preferences_span_"&gt;feature&lt;/a&gt; that I missed from my Firefox days.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/PersistentInfo/~4/256149811" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.persistent.info/feeds/4967715591011246001/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.persistent.info/2008/03/two-safari-31-tips.html#comment-form" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6525469191850690957/posts/default/4967715591011246001?v=2" /><link rel="self" type="application/atom+xml" href="http://blog.persistent.info/feeds/posts/default/4967715591011246001" /><link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/PersistentInfo/~3/256149811/two-safari-31-tips.html" title="Two Safari 3.1 Tips" /><author><name>Mihai Parparita</name><uri>http://www.blogger.com/profile/12343650264888591427</uri><email>noreply@blogger.com</email></author><feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=PersistentInfo&amp;itemurl=http%3A%2F%2Fblog.persistent.info%2F2008%2F03%2Ftwo-safari-31-tips.html</feedburner:awareness><feedburner:origLink>http://blog.persistent.info/2008/03/two-safari-31-tips.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0IDQnszeyp7ImA9WxZQE0U.&quot;"><id>tag:blogger.com,1999:blog-6525469191850690957.post-2804284005628138851</id><published>2008-02-18T21:50:00.000-05:00</published><updated>2008-02-18T21:52:53.583-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-02-18T21:52:53.583-05:00</app:edited><title>Decommissioning Mscape Software</title><content type="html">&lt;p&gt;Before I became enamored with web development, I used to be a Mac software developer under the &lt;a href="http://www.mscape.com/"&gt;Mscape Software&lt;/a&gt; moniker. My first public release (clip2cicn, a helper tool for making the icon resources necessary for &lt;a href="http://kaleidoscope.net/"&gt;Kaleidoscope&lt;/a&gt; schemes) was almost 10 years ago, on June 26, 1998. My flagship product was Iconographer, an icon editing tool.&lt;/p&gt;

&lt;p&gt;I haven't had time for Mscape Software for about 4 years (the last Iconographer release was in July of 2003, and I last touched the code in early 2004). The site was still up, and I kept receiving registrations (Iconographer was a $15 shareware product). As time went on, I began to feel more and more guilty about not providing any support for (paying) customers. To this end, I have finally gotten around to dismantling Mscape Software, replacing the site with a &lt;a href="http://www.mscape.com/"&gt;placeholder&lt;/a&gt; with download links for all products. I've also put up a registration code for Iconographer so that the (annoying) registration reminder can be shut off.&lt;/p&gt;

&lt;p&gt;I've gotten some requests to open-source Iconographer, but I'm not sure I'll have time even for that. I'm not 100% sure I can build the product given software on hand (it was built with CodeWarrior). Even then, the codebase shows its age (it was my first large-ish project and still uses many Classic constructs like a &lt;code&gt;WaitNextEvent&lt;/code&gt; event loop).&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/PersistentInfo/~4/237312178" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.persistent.info/feeds/2804284005628138851/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.persistent.info/2008/02/decommissioning-mscape-software.html#comment-form" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6525469191850690957/posts/default/2804284005628138851?v=2" /><link rel="self" type="application/atom+xml" href="http://blog.persistent.info/feeds/posts/default/2804284005628138851" /><link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/PersistentInfo/~3/237312178/decommissioning-mscape-software.html" title="Decommissioning Mscape Software" /><author><name>Mihai Parparita</name><uri>http://www.blogger.com/profile/12343650264888591427</uri><email>noreply@blogger.com</email></author><feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=PersistentInfo&amp;itemurl=http%3A%2F%2Fblog.persistent.info%2F2008%2F02%2Fdecommissioning-mscape-software.html</feedburner:awareness><feedburner:origLink>http://blog.persistent.info/2008/02/decommissioning-mscape-software.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Dk4CQHs4eCp7ImA9WB9bEkw.&quot;"><id>tag:blogger.com,1999:blog-6525469191850690957.post-8581270645226207790</id><published>2007-11-16T10:14:00.000-05:00</published><updated>2007-12-21T00:29:21.530-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-12-21T00:29:21.530-05:00</app:edited><title>plusplusbot: Karma for anything and anyone</title><content type="html">&lt;p&gt;The recent release of &lt;a href="http://foamee.com"&gt;Foamee&lt;/a&gt; reminded me that I had never blogged here about &lt;a href="http://plusplusbot.com/"&gt;plusplusbot&lt;/a&gt;, a little toy of a site that I started to work on this past summer. The idea behind plusplusbot is that you can express your (dis)pleasure with something or someone over Twitter, and the site will keep track of the target's score over time. All of this is done over &lt;a href="http://twitter.com/"&gt;Twitter&lt;/a&gt;, in a &lt;a href="http://bokardo.com/archives/foamee-a-barnacle-app-for-indebted-drinkers/"&gt;barnacle-like fashion&lt;/a&gt;. The thinking being that Twitter handles message delivery over a variety of mediums (Jabber, SMS, Web) and provides a ready-made social network to piggyback on (you can view the activity of you and those you follow, for example, &lt;a href="http://plusplusbot.com/users/mihai#friends-header"&gt;here's mine&lt;/a&gt;). This concept should be familiar to those that have enountered "karmabots" in chatrooms.&lt;/p&gt;

&lt;p&gt;The targets can be anything. &lt;a href="http://plusplusbot.com/targets/apple"&gt;Companies&lt;/a&gt;, &lt;a href="http://plusplusbot.com/targets/coffee"&gt;food&lt;/a&gt;, &lt;a href="http://plusplusbot.com/targets/ak"&gt;people&lt;/a&gt;, even &lt;a href="http://plusplusbot.com/targets/twitter"&gt;Twitter itself&lt;/a&gt;. For whatever reason, the site has caught on most with Japanese Twitter users, so the homepage is often incomprehensible.&lt;/p&gt;

&lt;p&gt;Technically, the site is not too exciting. Like &lt;a href="http://persistent.info/twitter-digest"&gt;Twitter Digest&lt;/a&gt;, it also uses &lt;a href="http://code.google.com/p/python-twitter/"&gt;python-twitter&lt;/a&gt; to talk to Twitter and &lt;a href="http://davidbau.com/archives/2007/02/18/python_templates.html"&gt;templet&lt;/a&gt; for simple templates. The site itself is not dynamic at all, instead a script running on one of my machines polls Twitter every two minutes (since it has to fetch both friend updates and direct messages, fetching both every minute would go over Twitter's 70 requests/hour API rate limit). If it determines that a new plusplus or minusminus has been sent, it re-generates those pages (the user's and the target's) and uploads them. The simple design means that the site can be hosted nearly anywhere.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/PersistentInfo/~4/185817674" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.persistent.info/feeds/8581270645226207790/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.persistent.info/2007/11/plusplusbot-karma-for-anything-and.html#comment-form" title="8 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6525469191850690957/posts/default/8581270645226207790?v=2" /><link rel="self" type="application/atom+xml" href="http://blog.persistent.info/feeds/posts/default/8581270645226207790" /><link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/PersistentInfo/~3/185817674/plusplusbot-karma-for-anything-and.html" title="plusplusbot: Karma for anything and anyone" /><author><name>Mihai Parparita</name><uri>http://www.blogger.com/profile/12343650264888591427</uri><email>noreply@blogger.com</email></author><feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=PersistentInfo&amp;itemurl=http%3A%2F%2Fblog.persistent.info%2F2007%2F11%2Fplusplusbot-karma-for-anything-and.html</feedburner:awareness><feedburner:origLink>http://blog.persistent.info/2007/11/plusplusbot-karma-for-anything-and.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUMHR3o6eyp7ImA9WxdVFEU.&quot;"><id>tag:blogger.com,1999:blog-6525469191850690957.post-6510723071626999022</id><published>2007-11-05T21:09:00.001-05:00</published><updated>2008-07-19T13:10:36.413-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-07-19T13:10:36.413-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Greasemonkey" /><title>Macros for the new version of Gmail</title><content type="html">&lt;p&gt;As those of you on &lt;a href="http://gmailblog.blogspot.com/2007/10/code-changes-to-prepare-gmail-for.html"&gt;the new version of Gmail&lt;/a&gt; might have noticed, nearly all Greasemonkey scripts that used to work on the old version no longer do. Even though it looks pretty similar, the new Gmail is entirely different from a JavaScript, HTML and CSS perspective, so this isn't surprising. Some of the scripts are no longer necessary. For example, &lt;a href="http://blog.persistent.info/2005/03/adding-persistent-searches-to-gmail.html"&gt;saved searches&lt;/a&gt; aren't really needed, since searches now get their own URLs and can be bookmarked.&lt;/p&gt;

&lt;p&gt;However, my &lt;a href="http://blog.persistent.info/2005/12/greasemonkey-christmas.html"&gt;Macros&lt;/a&gt; script is still needed; while the new version of Gmail does have additional keyboard shortcuts, it's still not possible to do everything from the keyboard. I've therefore ported it for the new version of Gmail, to install it, click below.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://gmail-greasemonkey.googlecode.com/svn/trunk/scripts/gmail-new-macros.user.js"&gt;Install Gmail Macros&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;More specifically, the following keyboard shorcuts have been ported over:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;g:&lt;/strong&gt; Go to label&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;l:&lt;/strong&gt; Apply label&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;b:&lt;/strong&gt; Remove label&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;e:&lt;/strong&gt; Archive (regardless of view, unlike "y")&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;d:&lt;/strong&gt; Discard (mark as read and archive)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is also a new keyboard shortcut, which the old script didn't have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;f:&lt;/strong&gt; "Focus" the current view (only show unread, starred or inbox messages)&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;You may remember the script supporting other keyboard shorcuts. Since the new version of Gmail supports additional shortcuts, those have obsoleted. The new ones are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;shift + i&lt;/strong&gt;: Mark as read&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;shift + u&lt;/strong&gt;: Mark as unread&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;shift + 3&lt;/strong&gt;: Move to trash (not actually new, but not many people seem to know this one)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;shift + 8&lt;/strong&gt; followed by &lt;strong&gt;a&lt;/strong&gt;, &lt;strong&gt;n&lt;/strong&gt;, &lt;strong&gt;r&lt;/strong&gt;, &lt;strong&gt;u&lt;/strong&gt;, &lt;strong&gt;s&lt;/strong&gt;, or &lt;strong&gt;t&lt;/strong&gt;: Select all, none, read, unread, starred, or unstarred&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For those of you adventurous enough to look at the script source, you'll notice that it uses a &lt;code&gt;gmonkey&lt;/code&gt; object that is present on the window, which in turn gets you a &lt;code&gt;gmail&lt;/code&gt; object with methods like &lt;code&gt;getNavPaneElement()&lt;/code&gt; and &lt;code&gt;getActiveViewType()&lt;/code&gt;. What this means is that the version of Gmail, in addition to being faster, also has semi-official support for Greasemonkey scripts. I'm pretty sure docs for this API will be out soon, but in the meantime, feel free to look at the script and use a tool like Firebug to investigate the properties of the &lt;code&gt;gmonkey&lt;/code&gt; and &lt;code&gt;gmail&lt;/code&gt; objects and play around.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update on 11/06/2007:&lt;/strong&gt; And here are &lt;a href="http://code.google.com/p/gmail-greasemonkey/wiki/GmailGreasemonkey10API"&gt;the semi-official docs&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/PersistentInfo/~4/180339680" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.persistent.info/feeds/6510723071626999022/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.persistent.info/2007/11/macros-for-new-version-of-gmail.html#comment-form" title="144 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6525469191850690957/posts/default/6510723071626999022?v=2" /><link rel="self" type="application/atom+xml" href="http://blog.persistent.info/feeds/posts/default/6510723071626999022" /><link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/PersistentInfo/~3/180339680/macros-for-new-version-of-gmail.html" title="Macros for the new version of Gmail" /><author><name>Mihai Parparita</name><uri>http://www.blogger.com/profile/12343650264888591427</uri><email>noreply@blogger.com</email></author><feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=PersistentInfo&amp;itemurl=http%3A%2F%2Fblog.persistent.info%2F2007%2F11%2Fmacros-for-new-version-of-gmail.html</feedburner:awareness><feedburner:origLink>http://blog.persistent.info/2007/11/macros-for-new-version-of-gmail.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkcARn0_eCp7ImA9WB9SEkU.&quot;"><id>tag:blogger.com,1999:blog-6525469191850690957.post-3387954595038339056</id><published>2007-10-01T20:24:00.000-04:00</published><updated>2007-10-01T20:14:07.340-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-10-01T20:14:07.340-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Hammers" /><title>Feed Proxy: View Raw RSS/Atom Feed Data in Firefox 2.0</title><content type="html">&lt;p&gt;Firefox 2.0 has a nice RSS/Atom feed preview feature, which pretty-prints the feed and allows you easily subscribe to it in a feed reader. While this is nice from a user's standpoint, it can get in the way when trying to debug or otherwise see a raw feed as a developer. There is no option to turn this mode off, which seems to be making &lt;a href="http://www.evilgeniuschronicles.org/wordpress/2007/03/17/xml-view-in-mozilla/"&gt;some&lt;/a&gt; &lt;a href="http://groups.google.com/group/mozilla.dev.apps.firefox/browse_thread/thread/146f70eaf0e1686f/f35c316db3883cf8"&gt;people&lt;/a&gt; unhappy.&lt;/p&gt;

&lt;p&gt;To help with this use-case, I made &lt;a href="http://persistent.info/feed-proxy"&gt;Feed Proxy&lt;/a&gt;, a simple service that gives you back the raw XML output (by adding a 512 byte dummy header that makes Firefox not invoke its feed preview code). Its page has more details on how to invoke it and what its caveats are.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/PersistentInfo/~4/163940423" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.persistent.info/feeds/3387954595038339056/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.persistent.info/2007/10/feed-proxy-view-raw-rssatom-feed-data.html#comment-form" title="10 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6525469191850690957/posts/default/3387954595038339056?v=2" /><link rel="self" type="application/atom+xml" href="http://blog.persistent.info/feeds/posts/default/3387954595038339056" /><link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/PersistentInfo/~3/163940423/feed-proxy-view-raw-rssatom-feed-data.html" title="Feed Proxy: View Raw RSS/Atom Feed Data in Firefox 2.0" /><author><name>Mihai Parparita</name><uri>http://www.blogger.com/profile/12343650264888591427</uri><email>noreply@blogger.com</email></author><feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=PersistentInfo&amp;itemurl=http%3A%2F%2Fblog.persistent.info%2F2007%2F10%2Ffeed-proxy-view-raw-rssatom-feed-data.html</feedburner:awareness><feedburner:origLink>http://blog.persistent.info/2007/10/feed-proxy-view-raw-rssatom-feed-data.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkcNQXY6eyp7ImA9WB9TGEk.&quot;"><id>tag:blogger.com,1999:blog-6525469191850690957.post-8439220368791256078</id><published>2007-09-26T18:11:00.000-04:00</published><updated>2007-09-26T19:08:10.813-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-09-26T19:08:10.813-04:00</app:edited><title>Valleywag, brought to you by....Google?</title><content type="html">&lt;p&gt;Gawker Media's use of virtual hosting for its sites was being discussed in &lt;a href="http://techwalla.googlepages.com/home"&gt;PartyChat&lt;/a&gt;, so to verify this, I ran &lt;code&gt;host valleywag.com&lt;/code&gt; to compare it with &lt;code&gt;host fleshbot.com&lt;/code&gt;. Imagine my surprise when I saw this output:&lt;p&gt;

&lt;pre&gt;$ host valleywag.com
valleywag.com has address 69.60.7.199
valleywag.com mail is handled by 1 aspmx.l.google.com.
valleywag.com mail is handled by 5 alt1.aspmx.l.google.com.
valleywag.com mail is handled by 5 alt2.aspmx.l.google.com.
valleywag.com mail is handled by 10 aspmx2.googlemail.com.&lt;/pre&gt;

&lt;p&gt;If I am interpreting this correctly, Valleywag's email is being handled by Gmail/Google Apps, which is slightly ironic.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/PersistentInfo/~4/161715968" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.persistent.info/feeds/8439220368791256078/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.persistent.info/2007/09/valleywag-brought-to-you-bygoogle.html#comment-form" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6525469191850690957/posts/default/8439220368791256078?v=2" /><link rel="self" type="application/atom+xml" href="http://blog.persistent.info/feeds/posts/default/8439220368791256078" /><link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/PersistentInfo/~3/161715968/valleywag-brought-to-you-bygoogle.html" title="Valleywag, brought to you by....Google?" /><author><name>Mihai Parparita</name><uri>http://www.blogger.com/profile/12343650264888591427</uri><email>noreply@blogger.com</email></author><feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=PersistentInfo&amp;itemurl=http%3A%2F%2Fblog.persistent.info%2F2007%2F09%2Fvalleywag-brought-to-you-bygoogle.html</feedburner:awareness><feedburner:origLink>http://blog.persistent.info/2007/09/valleywag-brought-to-you-bygoogle.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkcFQX8_fCp7ImA9WB5bGE4.&quot;"><id>tag:blogger.com,1999:blog-6525469191850690957.post-9181566390968601787</id><published>2007-08-31T10:30:00.000-04:00</published><updated>2007-09-03T12:46:50.144-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-09-03T12:46:50.144-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Hammers" /><title>Twitter Digest</title><content type="html">&lt;p&gt;There are quite a few people on &lt;a href="http://twitter.com/"&gt;Twitter&lt;/a&gt; that I'd like to follow but can't, since they update way too often. For example, I'd like to know how &lt;a href="http://twitter.com/chockenberry"&gt;Craig Hockenberry&lt;/a&gt;'s &lt;a href="http://code.google.com/p/mobile-twitterrific/"&gt;MobileTwitterrific&lt;/a&gt; work is going. &lt;a href="http://twitter.com/gruber"&gt;John Gruber&lt;/a&gt; often posts advance tidbits from Daring Fireball. However, since Twitter doesn't seem to allow different notification levels for contacts, I'd rather not get overwhelmed with their updates on a regular basis.&lt;/p&gt;

&lt;p&gt;Twitter does have an &lt;a href="http://www.twitter.com/help/api"&gt;API&lt;/a&gt; though, and a pretty complete one at that. Additionally, &lt;a href="http://code.google.com/p/python-twitter/"&gt;python-twitter&lt;/a&gt; makes it pretty easy to code against it. The result is that it was pretty easy to make &lt;a href="http://persistent.info/twitter-digest"&gt;&lt;strong&gt;Twitter Digest&lt;/strong&gt;&lt;/a&gt;. You can give it a bunch of usernames and it will update a page once a day with all of those people's tweets. Feeds can also be generated, so that you can subscribe to your digest in your favorite feed reader. To give an example, here's &lt;a href="http://persistent.info/twitter-digest/generate?usernames=gruber+alcor+brentsimmons+cabel+chockenberry+jkottke+rael+rands+siracusa+stevenf+diveintomark+nelson&amp;output=html"&gt;my digest&lt;/a&gt; (and &lt;a href="http://persistent.info/twitter-digest/generate?usernames=gruber+alcor+brentsimmons+cabel+chockenberry+jkottke+rael+rands+siracusa+stevenf+diveintomark+nelson&amp;output=atom"&gt;its feed&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;Since python-twitter already has the the concept of caching API replies, this was especially easy to develop. Simply by juggling with cache timeout values, API replies are kept around for up to a day, thus I don't have to persist anything in my code. All digests are refreshed at GMT day boundaries because supporting timezones seemed like too much work.&lt;/p&gt;

&lt;p&gt;Digests can be thematic too. Here's &lt;a href="http://persistent.info/twitter-digest/generate?usernames=al3x+biz+blaine+bs+crystal+ev+goldman+jack+krissy&amp;output=html"&gt;one for the Twitter team&lt;/a&gt;. I'm sure there are other uses too. I'm pretty happy with how this turned out, and the only thing missing is better reply support (if a message is in reply to another, then (optionally) show that message inline too). Right now the API is missing support for this (even though the regular UI surfaces this information), but I'm sure something can be hacked together.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update on 9/3/2007:&lt;/strong&gt; Adding support for "in reply to" messages turned out to be easy enough (look for the first message from the other username that's before the one that's replying, but only up to an hour earlier, in case it's not actually connected).&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/PersistentInfo/~4/150535687" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.persistent.info/feeds/9181566390968601787/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.persistent.info/2007/08/twitter-digest.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6525469191850690957/posts/default/9181566390968601787?v=2" /><link rel="self" type="application/atom+xml" href="http://blog.persistent.info/feeds/posts/default/9181566390968601787" /><link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/PersistentInfo/~3/150535687/twitter-digest.html" title="Twitter Digest" /><author><name>Mihai Parparita</name><uri>http://www.blogger.com/profile/12343650264888591427</uri><email>noreply@blogger.com</email></author><feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=PersistentInfo&amp;itemurl=http%3A%2F%2Fblog.persistent.info%2F2007%2F08%2Ftwitter-digest.html</feedburner:awareness><feedburner:origLink>http://blog.persistent.info/2007/08/twitter-digest.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0EGQ3gyeyp7ImA9WB5WEU4.&quot;"><id>tag:blogger.com,1999:blog-6525469191850690957.post-2545031396202703507</id><published>2007-07-22T15:29:00.001-04:00</published><updated>2007-07-22T16:20:22.693-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-07-22T16:20:22.693-04:00</app:edited><title>iPhone Game Development: A Tale of Failure</title><content type="html">&lt;p&gt;Having acquired an iPhone, I've been playing around with it to see just how much can be done with the "SDK" that is the MobileSafari browser. I thought it would be fun to see if I could make a simple game for it, since that's different enough from the kind of UI coding I do at &lt;a href="http://www.google.com"&gt;work&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Most of the games for the iPhone that I've encountered thus far were of the puzzle/card variety, and there wasn't anything too exciting/button-mashing/mindless. It seemed like this was mainly caused by the limitations of the events that the browser exposes. With no real &lt;code&gt;mousemove&lt;/code&gt; events, and with &lt;code&gt;mousedown&lt;/code&gt; events actually firing when the cursor was lifted (i.e. at the same time as &lt;code&gt;mouseup&lt;/code&gt;), it was hard to get anything to happen on the screen quickly in response to a user action. One avenue that I tried was to have the screen covered in narrow vertical &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;'s, and to listen for click events on each of them. Unfortunately, while this worked when each was clicked separately (piano key-style), it didn't work when the user dragged his finger from one to another, since this would switch the browser into panning mode, even if the page/viewport was set to be only 320 pixels wide (i.e. no scrolling could actually occur).&lt;/p&gt;

&lt;p&gt;Since the viewport panning does not seem to expose any events, I thought that maybe there could be other ways of catching this user action. When scrolling quickly, the iPhone renders newly-visible areas with a checkerboard pattern before actually displaying their contents. I wondered if this meant that images contained in these areas would not be loaded until they were scrolled into view and rendered. If so, it would be possible to use a &lt;code&gt;load&lt;/code&gt; event listener as a notification that the user had scrolled to a particular part of the screen. Unfortunately this didn't seem to be the case, images are loaded as soon as the document is displayed, even if they are off the screen.&lt;/p&gt;

&lt;p&gt;I then remembered that the iPhone supports an additional gesture, a two-fingered scroll that can be used to scroll text-areas, elements with &lt;code&gt;overflow: auto&lt;/code&gt; and possibly other nodes. It would appear that &lt;code&gt;scroll&lt;/code&gt; events trigger for this scrolling motion, meaning that it's possible to detect and get continuous updates for this. Though having to use two fingers seemed a bit clumsy, this seemed pretty promising insofar as it allowed for quick responses to user input.&lt;/p&gt;

&lt;p&gt;I had lofty goals for my iPhone game (I thought a vertical scrolling shooter was a good fit for the dragging input method and the vertical screen layout), but I decided that I should do something simple for my first attempt. I thought I would recreate aa racing game that I hard first played on my TI-82 calculator, where a car that can only be moved left or right moves at a constant vertical speed through a winding, narrowing road, with the objecting being to avoid hitting the sides. I thought this would map well to a horizontal scrolling motion that I could get with a &lt;code&gt;scroll&lt;/code&gt; event handler as mentioned above.&lt;/p&gt;

&lt;p&gt;After writing a simple random road generator and the animation code, I was about to add collision detection. Out of curiosity, I tried to move the "car" left/or right as road moved by, even without collision detection, to see if the speed was too high. To my surprise, the road stopped moving as soon as I put my two fingers on the screen. It appeared that intervals (set up with &lt;code&gt;window.setInterval&lt;/code&gt;) do not fire when two-finger scrolling mode is engaged. I thought that maybe I could refresh the animation from the &lt;code&gt;scroll&lt;/code&gt; event handler, but that only seems to fire when there is actual motion, thus smooth animation can't be ensured.&lt;/p&gt;

&lt;p&gt;My failed attempt is visible &lt;a href="http://persistent.info/files/iphone-racer.html"&gt;here&lt;/a&gt;. Before pressing the "Start" button, use the two-fingered scrolling motion left and right to confirm the the "car" (the blue square) moves as expected. Then press "Start" and obverse the reasonably smooth animation. Unfortunately it all stops when placing two fingers on the screen again.&lt;/p&gt;

&lt;p&gt;This is rather disappointing, since there doesn't seem to be any fundamental technical reason why this should be the case. We're not talking about Mac OS 9 here (there, due to the way UI events were processed, normal event loop execution would be suspended while a menu was held open or a scrollbar thumb was dragged). It's quite clear, given what native iPhone apps can do, that the platform has quite a lot of CPU and graphics leeway. It's therefore unfortunate just how constrained the MobileSafari browser is, since just a few additional hooks would allow much richer interactions with the user.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/PersistentInfo/~4/136277391" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.persistent.info/feeds/2545031396202703507/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.persistent.info/2007/07/iphone-game-development-tale-of-failure.html#comment-form" title="14 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6525469191850690957/posts/default/2545031396202703507?v=2" /><link rel="self" type="application/atom+xml" href="http://blog.persistent.info/feeds/posts/default/2545031396202703507" /><link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/PersistentInfo/~3/136277391/iphone-game-development-tale-of-failure.html" title="iPhone Game Development: A Tale of Failure" /><author><name>Mihai Parparita</name><uri>http://www.blogger.com/profile/12343650264888591427</uri><email>noreply@blogger.com</email></author><feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=PersistentInfo&amp;itemurl=http%3A%2F%2Fblog.persistent.info%2F2007%2F07%2Fiphone-game-development-tale-of-failure.html</feedburner:awareness><feedburner:origLink>http://blog.persistent.info/2007/07/iphone-game-development-tale-of-failure.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEEEQHo4fip7ImA9WBFbEkU.&quot;"><id>tag:blogger.com,1999:blog-6525469191850690957.post-1685135159612437284</id><published>2007-05-04T09:43:00.000-04:00</published><updated>2007-05-04T08:43:21.436-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-05-04T08:43:21.436-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Meta" /><title>Bad Headlines</title><content type="html">&lt;p&gt;Headlines seen over the past few weeks on the start page that Verizon forces on its users, and what they refer to in parentheses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Daily Life is a Struggle" (life in Baghdad)&lt;/li&gt;
&lt;li&gt;"All Sides Deny Deals" (Iran/UK sailors hostage situation)&lt;/li&gt;
&lt;li&gt;"Panel Seeks Documents" (Alberto Gonzales' federal prosecutors firings)&lt;/li&gt;
&lt;li&gt;"Cheruiyot Wins Marathon" (Robert Kipkoech Cheruiyot won the Boston Marathon)&lt;/li&gt;
&lt;li&gt;"Gates: Clock is ticking" (Defense Secretary Robert Gates on the situation in Iraq)&lt;/li&gt;
&lt;li&gt;"Donkey Becomes Witness" (Dallas man is sued for noise disturbance caused by a donkey)&lt;/li&gt;
&lt;li&gt;"Dems Predict a Win" (House Democratic leaders predict that they can win a vote on a bill calling for a withdrawal from Iraq)&lt;/li&gt;
&lt;li&gt;"Candidates to Debate" (The Republican presidential candidate debate)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Someone forgot to read up on &lt;a href="http://www.useit.com/alertbox/980906.html"&gt;microcontent headlines&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/PersistentInfo/~4/114133603" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.persistent.info/feeds/1685135159612437284/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.persistent.info/2007/05/bad-headlines.html#comment-form" title="13 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6525469191850690957/posts/default/1685135159612437284?v=2" /><link rel="self" type="application/atom+xml" href="http://blog.persistent.info/feeds/posts/default/1685135159612437284" /><link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/PersistentInfo/~3/114133603/bad-headlines.html" title="Bad Headlines" /><author><name>Mihai Parparita</name><uri>http://www.blogger.com/profile/12343650264888591427</uri><email>noreply@blogger.com</email></author><feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=PersistentInfo&amp;itemurl=http%3A%2F%2Fblog.persistent.info%2F2007%2F05%2Fbad-headlines.html</feedburner:awareness><feedburner:origLink>http://blog.persistent.info/2007/05/bad-headlines.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEQDRX4-cSp7ImA9WBFVE00.&quot;"><id>tag:blogger.com,1999:blog-6525469191850690957.post-1960370276299529429</id><published>2007-04-11T11:40:00.000-04:00</published><updated>2007-04-11T11:46:14.059-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-04-11T11:46:14.059-04:00</app:edited><title>Tiled Windows Are the Way of the Future</title><content type="html">&lt;p&gt;Sorry Bill Atkinson. I know you &lt;a href="http://www.folklore.org/StoryView.py?project=Macintosh&amp;story=I_Still_Remember_Regions.txt"&gt;worked really hard&lt;/a&gt; to make regions and thus overlapping windows work. But since I now have 30 inch displays at both home and work, I've been tiling my windows and using &lt;a href="http://desktopmanager.berlios.de/"&gt;Desktop Manager&lt;/a&gt; (and soon Spaces?) to switch between workspaces. Not having to deal with z-ordering makes mental context switches faster.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/PersistentInfo/~4/108291694" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.persistent.info/feeds/1960370276299529429/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.persistent.info/2007/04/tiled-windows-are-way-of-future.html#comment-form" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6525469191850690957/posts/default/1960370276299529429?v=2" /><link rel="self" type="application/atom+xml" href="http://blog.persistent.info/feeds/posts/default/1960370276299529429" /><link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/PersistentInfo/~3/108291694/tiled-windows-are-way-of-future.html" title="Tiled Windows Are the Way of the Future" /><author><name>Mihai Parparita</name><uri>http://www.blogger.com/profile/12343650264888591427</uri><email>noreply@blogger.com</email></author><feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=PersistentInfo&amp;itemurl=http%3A%2F%2Fblog.persistent.info%2F2007%2F04%2Ftiled-windows-are-way-of-future.html</feedburner:awareness><feedburner:origLink>http://blog.persistent.info/2007/04/tiled-windows-are-way-of-future.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU4HQno9cSp7ImA9WBFWGEU.&quot;"><id>tag:blogger.com,1999:blog-6525469191850690957.post-6716318358896879544</id><published>2007-04-06T13:32:00.000-04:00</published><updated>2007-04-06T15:32:13.469-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-04-06T15:32:13.469-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Meta" /><title>Communicating through screenshots</title><content type="html">&lt;p&gt;My posts to the &lt;a href="http://googlereader.blogspot.com/"&gt;Reader&lt;/a&gt; blog often have screenshots, and I'm pretty picky about what goes in them. It's nice to see that others have noticed this too. My &lt;a href="http://googlereader.blogspot.com/2007/04/go-go-reader-gadget.html"&gt;most recent post&lt;/a&gt; has a link to &lt;a href="http://www.qwantz.com/"&gt;Dinosaur Comics&lt;/a&gt;, which the author &lt;a href="http://qwantz.livejournal.com/78807.html"&gt;seems to appreciate&lt;/a&gt;. Similarly, I intentionally left a reference to Valleywag in my &lt;a href="http://googlereader.blogspot.com/2007/01/i-like-big-charts-and-i-cannot-lie.html"&gt;trends post&lt;/a&gt;, which &lt;a href="http://valleywag.com/tech/self_congratulation/google-geek-exposed-as-valleywag-reader-226019.php"&gt;they noticed&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In some fashion, Apple does this too. A &lt;a href="http://www.appleinsider.com/article.php?id=2637"&gt;patent&lt;/a&gt; of theirs had a BBEdit reference, which &lt;a href="http://www.glorifiedtypist.com/2007/04/in_soviet_russia_apple_patents.html"&gt;amused the author of the software&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/PersistentInfo/~4/107148135" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.persistent.info/feeds/6716318358896879544/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.persistent.info/2007/04/communicating-through-screenshots.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6525469191850690957/posts/default/6716318358896879544?v=2" /><link rel="self" type="application/atom+xml" href="http://blog.persistent.info/feeds/posts/default/6716318358896879544" /><link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/PersistentInfo/~3/107148135/communicating-through-screenshots.html" title="Communicating through screenshots" /><author><name>Mihai Parparita</name><uri>http://www.blogger.com/profile/12343650264888591427</uri><email>noreply@blogger.com</email></author><feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=PersistentInfo&amp;itemurl=http%3A%2F%2Fblog.persistent.info%2F2007%2F04%2Fcommunicating-through-screenshots.html</feedburner:awareness><feedburner:origLink>http://blog.persistent.info/2007/04/communicating-through-screenshots.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ck4NQnczeip7ImA9WBFXGEo.&quot;"><id>tag:blogger.com,1999:blog-6525469191850690957.post-8192515560137189845</id><published>2007-03-25T20:32:00.000-04:00</published><updated>2007-03-25T21:03:13.982-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-03-25T21:03:13.982-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Hammers" /><title>Two Web Development Tips</title><content type="html">&lt;h3&gt;Memory Leaks&lt;/h3&gt;

&lt;p&gt;Fighting memory leaks in fancy AJAXy apps is a way of life for most UI developers. Besides &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/IETechCol/dnwebgen/ie_leak_patterns.asp"&gt;Internet Explorer-specific&lt;/a&gt; issues, leaks can also occur due to inadvertent remaining references to objects you don't actually need (frequent culprits are global event registries and history/state management stacks). Safari/WebKit turn out to have some useful built-in hooks for tracking these down. By enabling Safari's &lt;a href="http://developer.apple.com/internet/safari/faq.html#anchor14"&gt;debug menu&lt;/a&gt; and choosing the "Show Caches Window" command from there, you can see JavaScript object counts, force a garbage collection and see the types of objects that still have references pointing to them (note that the garbage collection has been improve in &lt;a href="http://www.webkit.org/"&gt;WebKit&lt;/a&gt; nightly builds so you'll probably want to use that).&lt;/p&gt;

&lt;p&gt;&lt;a href="http://outofhanwell.com/ieleak/index.php?title=Main_Page"&gt;Drip&lt;/a&gt; can provide some similar information for IE, and &lt;a href="http://dbaron.org/mozilla/leak-monitor/"&gt;Leak Monitor&lt;/a&gt; finds some Firefox-specific leak types, but it would be good for browser/add-on creators to provide even more debugging information to authors.&lt;/p&gt;

&lt;h3&gt;Browser Bugs&lt;/h3&gt;

&lt;p&gt;WebKit and Firefox/Mozilla both have publicly visible bug tracking systems. As they work on their respective new versions, regressions will occur that will break web sites, possibly including yours. Often, this is a genuine bug in the browser code, and hopefully it'll be fixed before the final release. However, it can sometimes be due to incorrect assumptions made by your code which no longer hold true  when browser code is tightened up. Both &lt;a href="http://bugs.webkit.org/query.cgi?format=specific"&gt;WebKit's&lt;/a&gt; and &lt;a href="https://bugzilla.mozilla.org/query.cgi"&gt;Mozilla's&lt;/a&gt; Bugzilla instances support generating RSS feeds from search results. By subscribing to feeds for bugs that mention your product name, you can stay on top of such bug reports. For example, here's &lt;a href="http://www.google.com/reader/shared/user/14548369432350969777/label/browser-bugs"&gt;a shared page&lt;/a&gt; (with &lt;a href="http://www.google.com/reader/public/atom/user/14548369432350969777/label/browser-bugs"&gt;feed&lt;/a&gt;) for the bugs that mention Reader on either site.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/PersistentInfo/~4/104375464" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.persistent.info/feeds/8192515560137189845/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.persistent.info/2007/03/two-web-development-tips.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6525469191850690957/posts/default/8192515560137189845?v=2" /><link rel="self" type="application/atom+xml" href="http://blog.persistent.info/feeds/posts/default/8192515560137189845" /><link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/PersistentInfo/~3/104375464/two-web-development-tips.html" title="Two Web Development Tips" /><author><name>Mihai Parparita</name><uri>http://www.blogger.com/profile/12343650264888591427</uri><email>noreply@blogger.com</email></author><feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=PersistentInfo&amp;itemurl=http%3A%2F%2Fblog.persistent.info%2F2007%2F03%2Ftwo-web-development-tips.html</feedburner:awareness><feedburner:origLink>http://blog.persistent.info/2007/03/two-web-development-tips.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C08EQHg8fip7ImA9WBFXGEo.&quot;"><id>tag:blogger.com,1999:blog-6525469191850690957.post-645543767147579896</id><published>2007-03-16T11:01:00.000-04:00</published><updated>2007-03-25T21:16:41.676-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-03-25T21:16:41.676-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Meta" /><title>Determining Twitter's Growth</title><content type="html">&lt;p&gt;Opinion on &lt;a href="http://www.twitter.com/"&gt;Twitter&lt;/a&gt; &lt;a href="http://web1979.wordpress.com/2007/03/14/rip-twitter-2007-2007/"&gt;is&lt;/a&gt; &lt;a href="http://www.feedblog.org/2007/03/rip_twitter.html"&gt;divided&lt;/a&gt;. What seems to be undisputed is that right now it's growing very quickly. I was curious just how "quickly" quickly was, preferably going beyond just anecdotal "my network doubled in size in the last 5 seconds" kind of observations. It seems like Twitter assigns globally unique, incrementing IDs to all messages it receives. By looking at the values of these IDs over time, it's possible to see how many status messages Twitter is keeping track of. I've generated a logarithmic graph of this.&lt;/p&gt;

&lt;p&gt;I'm not sure why there was an inflection point in early November. It's also possible that this is affected by technical changes on Twitter's side. Still possibly interesting. Also, Joshua's post on &lt;a href="http://joshua.schachter.org/2007/01/autoincrement.html"&gt;autoincrement considered harmful&lt;/a&gt; is related and an interesting read.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; As it was pointed out to me in the comments, Andy Baio had &lt;a href="http://www.waxy.org/archive/2007/03/15/tracking.shtml"&gt;the same idea&lt;/a&gt; except he executed it more throughly.&lt;/p&gt;

&lt;p style="text-align: center"&gt;&lt;img src="http://persistent.info/images/twitter-message-ids.png" width="592" height="389" alt="Twitter Message IDs"/&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/PersistentInfo/~4/102172871"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.persistent.info/feeds/645543767147579896/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.persistent.info/2007/03/determining-twitters-growth.html#comment-form" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6525469191850690957/posts/default/645543767147579896?v=2" /><link rel="self" type="application/atom+xml" href="http://blog.persistent.info/feeds/posts/default/645543767147579896" /><link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/PersistentInfo/~3/102172871/determining-twitters-growth.html" title="Determining Twitter's Growth" /><author><name>Mihai Parparita</name><uri>http://www.blogger.com/profile/12343650264888591427</uri><email>noreply@blogger.com</email></author><feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=PersistentInfo&amp;itemurl=http%3A%2F%2Fblog.persistent.info%2F2007%2F03%2Fdetermining-twitters-growth.html</feedburner:awareness><feedburner:origLink>http://blog.persistent.info/2007/03/determining-twitters-growth.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0ACRXY7eCp7ImA9WBFQFEo.&quot;"><id>tag:blogger.com,1999:blog-6525469191850690957.post-745789294912098473</id><published>2007-03-09T15:22:00.000-05:00</published><updated>2007-03-09T15:22:44.800-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-03-09T15:22:44.800-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Meta" /><title>Intern on the Google Reader team</title><content type="html">&lt;p&gt;The &lt;a href="http://www.google.com/reader"&gt;Reader&lt;/a&gt; team is hoping to have a student intern or two this coming summer. We're fast moving and always have more ideas than manpower, so an internship can be quite rewarding as far as the "working on real stuff" factor goes. For example, our intern last year, Brad, worked on the subscribe and feed search functionalities of the new Reader that launched last September. You can intern in Google's New York or Mountain View offices, working on either Reader's frontend/UI or backend.&lt;/p&gt;

&lt;p&gt;If you or anyone you know is interested in this internship, contact me at &lt;code&gt;mihai at persistent dot info&lt;/code&gt;. &lt;a href="http://www.google.com/support/jobs/bin/static.py?page=students.html&amp;sid=intern"&gt;This page&lt;/a&gt; also has more general information about interning at Google.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/PersistentInfo/~4/100578777"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.persistent.info/feeds/745789294912098473/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.persistent.info/2007/03/intern-on-google-reader-team.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6525469191850690957/posts/default/745789294912098473?v=2" /><link rel="self" type="application/atom+xml" href="http://blog.persistent.info/feeds/posts/default/745789294912098473" /><link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/PersistentInfo/~3/100578777/intern-on-google-reader-team.html" title="Intern on the Google Reader team" /><author><name>Mihai Parparita</name><uri>http://www.blogger.com/profile/12343650264888591427</uri><email>noreply@blogger.com</email></author><feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=PersistentInfo&amp;itemurl=http%3A%2F%2Fblog.persistent.info%2F2007%2F03%2Fintern-on-google-reader-team.html</feedburner:awareness><feedburner:origLink>http://blog.persistent.info/2007/03/intern-on-google-reader-team.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkEGSXo9fCp7ImA9WBFRFEk.&quot;"><id>tag:blogger.com,1999:blog-6525469191850690957.post-5118205039792752332</id><published>2007-02-25T16:55:00.000-05:00</published><updated>2007-02-25T16:57:08.464-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-02-25T16:57:08.464-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Meta" /><title>Blogger Migration Part II: Getting Data Into Blogger</title><content type="html">&lt;p&gt;Blogger doesn't have any built-in entry importing facilities. My plan for dealing with this was to use their &lt;a href="http://code.google.com/apis/blogger/overview.html"&gt;API&lt;/a&gt; to re-post all of the entries I had &lt;a href="http://blog.persistent.info/2007/02/blogger-migration-part-i-getting-data.html"&gt;exported&lt;/a&gt; from Movable Type. A quick test showed that such entries could be back-dated, which was my main concern.&lt;/p&gt;

&lt;p&gt;Using &lt;a href="http://vim-postblog.googlecode.com/svn/trunk/bloggerpost.py"&gt;some sample code&lt;/a&gt; that I found as a starting point, it was pretty easy to write a simple importing script for entries. Since I needed to parse the Atom responses from the API (e.g. to get at entry IDs), the &lt;a href="http://www.feedparser.org/"&gt;Universal Feed Parser&lt;/a&gt; came in handy. Since I had used the &lt;a href="http://www.sixapart.com/movabletype/docs/3.2/04_posting_entries/new_entry.html"&gt;Convert Line Breaks&lt;/a&gt; option on quite a few posts, I had to HTML-ify some post bodies before sending them to Blogger (I've turned off Blogger's similar setting. In addition to being only at the blog level, instead of a per-post setting, I've decided that the closer to regular HTML my posts are, the easier it will be to migrate again in the future).&lt;/p&gt;

&lt;p&gt;The Blogger API allows for posting of comments too, but unfortunately without the ability to &lt;a href="http://thread.gmane.org/gmane.comp.web.blogger.api/2892"&gt;impersonate others&lt;/a&gt; (even when anonymous comments are enabled). The solution was to impersonate the regular (non-API) comment posting form, which does allow for authors to be specified (but no backdating, which is why all imported comments are dated February 10th). This was made slightly trickier since a security token is required (to avoid &lt;a href="http://en.wikipedia.org/wiki/Cross-site_request_forgery"&gt;XSRF&lt;/a&gt; attacks), so the posting page had to be scraped first to extract it.&lt;/p&gt;

&lt;p&gt;Finally, since Blogger proved to be occasionally flaky when doing many API operations in a row, I had to add some simple checkpointing so that if the process failed I could restart it and it would continue from where it left off. Once I did all that, importing 350+ entries and 600+ comments took around an hour, but worked flawlessly.&lt;/p&gt;

&lt;p&gt;I've uploaded &lt;a href="http://persistent.info/files/blogger-upload.zip"&gt;an archive of my code&lt;/a&gt; that I used for the importing. It's not the cleanest it could be, but others may find it useful too. Additionally, in the time that has passed since I began my importing, it looks like &lt;a href="http://groups.google.com/group/bloggerDev/browse_frm/thread/d1c7855675023228/caad4b1ee97b0eb5#caad4b1ee97b0eb5"&gt;a similar script&lt;/a&gt; has appeared that does a similar import operation from WordPress, which may be worth a look too.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/PersistentInfo/~4/95912169"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.persistent.info/feeds/5118205039792752332/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.persistent.info/2007/02/blogger-migration-part-ii-getting-data.html#comment-form" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6525469191850690957/posts/default/5118205039792752332?v=2" /><link rel="self" type="application/atom+xml" href="http://blog.persistent.info/feeds/posts/default/5118205039792752332" /><link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/PersistentInfo/~3/95912169/blogger-migration-part-ii-getting-data.html" title="Blogger Migration Part II: Getting Data Into Blogger" /><author><name>Mihai Parparita</name><uri>http://www.blogger.com/profile/12343650264888591427</uri><email>noreply@blogger.com</email></author><feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=PersistentInfo&amp;itemurl=http%3A%2F%2Fblog.persistent.info%2F2007%2F02%2Fblogger-migration-part-ii-getting-data.html</feedburner:awareness><feedburner:origLink>http://blog.persistent.info/2007/02/blogger-migration-part-ii-getting-data.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkYFRXc7fip7ImA9WBFRFEk.&quot;"><id>tag:blogger.com,1999:blog-6525469191850690957.post-2106693380699369097</id><published>2007-02-18T17:48:00.001-05:00</published><updated>2007-02-25T16:48:34.906-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-02-25T16:48:34.906-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Meta" /><title>Understanding feed reader marketshare numbers</title><content type="html">&lt;p&gt;&lt;strong&gt;Update on 2/25:&lt;/strong&gt; FeedBurner has published &lt;a href="http://blogs.feedburner.com/feedburner/archives/2007/02/feedburners_view_of_the_feed_m.php"&gt;a post&lt;/a&gt; discussing this same issue but providing numbers for their whole userbase, which makes it even more interesting.&lt;/p&gt;

&lt;p&gt;Ever since the Reader team &lt;a href="http://googlereader.blogspot.com/2007/02/one-subscriber-two-subscribers-three.html"&gt;announced&lt;/a&gt; that we were making public subscriber counts (thanks Justin), bloggers have been &lt;a href="http://blogsearch.google.com/blogsearch?q=google+reader+feedburner"&gt;excitedly posting&lt;/a&gt; about the bumps they're seeing in their subscriber stats. I'm obviously very happy that Reader is getting all this attention, and that we turn out to be quite popular when compared to other feed readers. However, these statistics need a bit of interpretation. Most people post charts of their subscriber counts, like this one for this blog:&lt;/p&gt;

&lt;p style="text-align: center"&gt;&lt;img src="http://persistent.info/images/feedburner-subscribers.gif" width="435" height="191" alt="FeedBurner subscribers" /&gt;&lt;/p&gt;

&lt;p&gt;For web-based readers where feeds are fetched on behalf of multiple users, the subscriber number is based on what the site reports. To the best of my knowledge, with the exception of My Yahoo!, these number are total subscribers, even if an account is inactive. Unless the site is aggressive about cleaning up inactive accounts, these numbers are only upper bounds on the number of actual readers that you have.&lt;/p&gt;

&lt;p&gt;A more interesting number to look at is how many viewers each item gets from each feed reader. FeedBurner provides this as part of their &lt;a href="http://www.feedburner.com/fb/a/popup-whypro"&gt;TotalStats&lt;/a&gt; package. By embedding a small tracking image in your burned posts and looking at referrers, it's possible to see these item-specific views. Here are how many views and clicks &lt;a href="http://blog.persistent.info/2007/02/blogger-migration-part-i-getting-data.html"&gt;my post from yesterday&lt;/a&gt; got in various feed readers:&lt;/p&gt;

&lt;p style="text-align: center"&gt;&lt;img src="http://persistent.info/images/feedburner-item-use.gif" width="374" height="148" alt="FeedBurner item use" /&gt;&lt;/p&gt;

&lt;p&gt;From this it would appear that Reader has an even bigger lead over Bloglines (though given the biases in this blog's readership, I'm not reading too much into this). There are other factors involved here too. The user bases for feed readers are not identical, if an item appeals more to one population than another, that may skew things. Additionally, some readers (especially homepage-style ones like My Yahoo!, Google Personalized Homepage and Netvibes) don't have to display the item body and allow users to jump straight to the post page. These would show up in the "Clicks" column but not in the "Views" one.&lt;/p&gt;

&lt;p&gt;What becomes apparent is that none of these statistics provide a complete picture of your readership, but that when used together they can still give you broad trends and help you tailor your content to your audience.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/PersistentInfo/~4/92637940"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.persistent.info/feeds/2106693380699369097/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.persistent.info/2007/02/understanding-feed-reader-marketshare.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6525469191850690957/posts/default/2106693380699369097?v=2" /><link rel="self" type="application/atom+xml" href="http://blog.persistent.info/feeds/posts/default/2106693380699369097" /><link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/PersistentInfo/~3/92637940/understanding-feed-reader-marketshare.html" title="Understanding feed reader marketshare numbers" /><author><name>Mihai Parparita</name><uri>http://www.blogger.com/profile/12343650264888591427</uri><email>noreply@blogger.com</email></author><feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=PersistentInfo&amp;itemurl=http%3A%2F%2Fblog.persistent.info%2F2007%2F02%2Funderstanding-feed-reader-marketshare.html</feedburner:awareness><feedburner:origLink>http://blog.persistent.info/2007/02/understanding-feed-reader-marketshare.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU8BQ346cSp7ImA9WBFSF08.&quot;"><id>tag:blogger.com,1999:blog-6525469191850690957.post-2459319656080017225</id><published>2007-02-17T10:57:00.000-05:00</published><updated>2007-02-17T10:57:32.019-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-02-17T10:57:32.019-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Meta" /><title>Blogger Migration Part I: Getting Data Out of Movable Type</title><content type="html">&lt;p&gt;The first step in migrating away from Movable Type was to get all of my entries and comments in a structured format that could be parsed and uploaded to Blogger*. MT doesn't hold data hostage, there is a &lt;a href="http://www.sixapart.com/movabletype/docs/mtimport"&gt;documented import/export format&lt;/a&gt;. Six Apart considers the format "lossy", in that it doesn't save a complete snapshot of your blog. I decided that what it did contain was good enough, though it turn out that what it lacked (entry IDs and permalinks) did make things slightly more difficult. A search on &lt;a href="http://code.google.com"&gt;code.google.com&lt;/a&gt; for Python code to parse the format turned up &lt;a href="http://www.google.com/codesearch?hl=en&amp;q=+lang:python+CONVERT%5C+BREAKS+show:aZJvD9Ue1hE:9Qr2icleqqs:-L0XXC6N5ow&amp;sa=N&amp;cd=6&amp;ct=rc&amp;cs_p=:pserver:anonymous%40anoncvs.gnome.org:/cvs/gnome+blogs-web&amp;cs_f=nb/lib/transfusion.py#a0"&gt;Transfusion&lt;/a&gt; which does just that (searching for one of the magic strings in the format, &lt;a href="http://www.google.com/codesearch?as_q=CONVERT+BREAKS&amp;btnG=Search+Code&amp;hl=en&amp;as_lang=python&amp;as_license_restrict=i&amp;as_license=&amp;as_package=&amp;as_filename=&amp;as_case="&gt;CONVERT BREAKS&lt;/a&gt; specifically, was the easiest way to track this down).&lt;/p&gt;

&lt;p&gt;As I was skimming through the exported entries, I saw that they weren't quite HTML. I had used &lt;a href="http://bradchoate.com/weblog/2002/08/12/mtmacros"&gt;MTMacro&lt;/a&gt; to create various shorthand tags for linking to entries, reference to images, etc. Similarly, I used &lt;a href="http://voisen.org/archives/2003/03/06/syntax-highlighting-plug-in-now-available/"&gt;MTCodeBeautifier&lt;/a&gt; to pretty-print code samples. None of these were getting evaluated when exporting, and even if they had been, I probably would have wanted to tweak their output anyway (e.g. to change URLs). Generally, it seemed like the time I had spent customizing my Movable Type installation with &lt;a href="http://diveintomark.org/archives/2003/08/15/slugs"&gt;cruft-free&lt;/a&gt; URLs, plug-ins, etc. would be directly proportional to the time I would have to spend migrating away from it.&lt;/p&gt;

&lt;p&gt;One of the more prevalent macros I had used was one of the form &lt;code&gt;&amp;lt;entryLink id="NNN"&amp;gt;foo&amp;lt;/entryLink&amp;gt;&lt;/code&gt; so that I could link to my past entries. Unfortunately, since entry IDs were not included entry IDs issue, there was no easy way to turn these into actual links, since the exported information did not contain entry IDs or URLs. In the end, I ended up converting these by hand.&lt;/p&gt;

&lt;p&gt;That's it for the exporting part, part II will contain the Blogger import process and part III the template/design reasoning.&lt;/p&gt;

&lt;p&gt;* the other migration option that I was considering was &lt;a href="http://www.wordpress.org/"&gt;WordPress&lt;/a&gt;. However, the idea of having to do SQL queries to serve traffic didn't seem that appealing given my current provider's slow SQL performance. &lt;a href="http://www.wordpress.com/"&gt;WordPress.com&lt;/a&gt; would have been a hosted option, but if I was going to relinquish control of the installation, it might as well be to a Google product.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/PersistentInfo/~4/92088493"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.persistent.info/feeds/2459319656080017225/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.persistent.info/2007/02/blogger-migration-part-i-getting-data.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6525469191850690957/posts/default/2459319656080017225?v=2" /><link rel="self" type="application/atom+xml" href="http://blog.persistent.info/feeds/posts/default/2459319656080017225" /><link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/PersistentInfo/~3/92088493/blogger-migration-part-i-getting-data.html" title="Blogger Migration Part I: Getting Data Out of Movable Type" /><author><name>Mihai Parparita</name><uri>http://www.blogger.com/profile/12343650264888591427</uri><email>noreply@blogger.com</email></author><feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=PersistentInfo&amp;itemurl=http%3A%2F%2Fblog.persistent.info%2F2007%2F02%2Fblogger-migration-part-i-getting-data.html</feedburner:awareness><feedburner:origLink>http://blog.persistent.info/2007/02/blogger-migration-part-i-getting-data.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0IDQ3c8eSp7ImA9WBFSEUs.&quot;"><id>tag:blogger.com,1999:blog-6525469191850690957.post-3191152998943965595</id><published>2007-02-10T23:58:00.000-05:00</published><updated>2007-02-10T23:52:52.971-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-02-10T23:52:52.971-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Meta" /><title>Switched to Blogger</title><content type="html">&lt;p&gt;Partly because I was fed up with Movable Type's rebuild times, but also for &lt;a href="http://en.wikipedia.org/wiki/Eat_one's_own_dog_food"&gt;dog food&lt;/a&gt; reasons, I've moved my blog over to &lt;a href="http://www.blogger.com/"&gt;Blogger&lt;/a&gt; (&lt;a href="http://buzz.blogger.com/2007/01/blogger-custom-domains.html"&gt;custom domains&lt;/a&gt; was the final missing piece). Redirects should be in place and no links should break, but feed readers will most likely see a bunch of new entries (I didn't see an option in FeedBurner to suppress duplicates). Please leave a comment if you see anything amiss.&lt;/p&gt;

&lt;p&gt;I'll be writing up more details this coming week about the work that was necessary to migrate.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/PersistentInfo/~4/89223786"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.persistent.info/feeds/3191152998943965595/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.persistent.info/2007/02/switched-to-blogger.html#comment-form" title="9 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6525469191850690957/posts/default/3191152998943965595?v=2" /><link rel="self" type="application/atom+xml" href="http://blog.persistent.info/feeds/posts/default/3191152998943965595" /><link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/PersistentInfo/~3/89223786/switched-to-blogger.html" title="Switched to Blogger" /><author><name>Mihai Parparita</name><uri>http://www.blogger.com/profile/12343650264888591427</uri><email>noreply@blogger.com</email></author><feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=PersistentInfo&amp;itemurl=http%3A%2F%2Fblog.persistent.info%2F2007%2F02%2Fswitched-to-blogger.html</feedburner:awareness><feedburner:origLink>http://blog.persistent.info/2007/02/switched-to-blogger.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEEERn0zfyp7ImA9WBFSEUs.&quot;"><id>tag:blogger.com,1999:blog-6525469191850690957.post-1686923932009774772</id><published>2007-01-29T09:47:00.000-05:00</published><updated>2007-02-10T23:03:27.387-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-02-10T23:03:27.387-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Meta" /><title>More Efficient FeedBurner Visitor Tracking</title><content type="html">&lt;p&gt;I was quite happy to see that FeedBurner had integrated &lt;a href="http://blogs.feedburner.com/feedburner/archives/2007/01/a_360_degree_view_of_audience_1.php"&gt;site visitor tracking&lt;/a&gt; in addition to their already great feed usage statistics. Actually using it with my blog was just a matter of cutting and pasting some code into my template. Here's the snippet that I was offered for Movable Type:&lt;/p&gt;

&lt;blockquote&gt;&lt;code&gt;&amp;lt;script src="http://feeds.feedburner.com/~s/PersistentInfo?i=&amp;lt;$MTEntryPermalink$&amp;gt;" type="text/javascript" charset="utf-8"&amp;gt;&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/blockquote&gt;

&lt;p&gt;This seems reasonable, but it bothered me that the tracking URL varied for each entry. This meant that for my front page, 7 different (but nearly identical) pieces of JavaScript would have to be fetched, slowing down the rendering of my site. Others have &lt;a href="http://forums.feedburner.com/viewtopic.php?t=11200"&gt;complained&lt;/a&gt; too. I think a better way of implementing this would have been to have something like:&lt;/p&gt;

&lt;blockquote&gt;&lt;code&gt;&amp;lt;script src="http://tracking.feedburner.com/tracking.js" type=text/javascript" charset="utf-8"&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;script type="text/javascript"&amp;gt;FBTrack("PersistentInfo", "&amp;lt;$MTEntryPermalink$&amp;gt;");&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/blockquote&gt;

&lt;p&gt;That would have meant that the same tracking code can be used across all sites thus most users would have it cached (I think that's what Google Analytics relies on). Unfortunately, that's not something that I can change on my own.&lt;/p&gt;

&lt;p&gt;However, when running into a related problem (a FeedFlare was &lt;a href="http://forums.feedburner.com/viewtopic.php?t=11136"&gt;stuck on&lt;/a&gt;) it was pointed out to me that the &lt;code&gt;i=...&lt;/code&gt; part of the script URL can be removed if all that's desired is the visitor tracking and not per-entry features like FeedFlares. This means that at least across my entire site there is only one tracking script URL that visitors have to load. It turns out FeedBurner &lt;a href="http://forums.feedburner.com/viewtopic.php?t=11200"&gt;documents this&lt;/a&gt;, but only in the "Others..." category (the bottom "If you want to use StandardStats only" section).&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/PersistentInfo/~4/89211462"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.persistent.info/feeds/1686923932009774772/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.persistent.info/2007/01/more-efficient-feedburner-visitor.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6525469191850690957/posts/default/1686923932009774772?v=2" /><link rel="self" type="application/atom+xml" href="http://blog.persistent.info/feeds/posts/default/1686923932009774772" /><link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/PersistentInfo/~3/89211462/more-efficient-feedburner-visitor.html" title="More Efficient FeedBurner Visitor Tracking" /><author><name>Mihai Parparita</name><uri>http://www.blogger.com/profile/12343650264888591427</uri><email>noreply@blogger.com</email></author><feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=PersistentInfo&amp;itemurl=http%3A%2F%2Fblog.persistent.info%2F2007%2F01%2Fmore-efficient-feedburner-visitor.html</feedburner:awareness><feedburner:origLink>http://blog.persistent.info/2007/01/more-efficient-feedburner-visitor.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEINSHkycSp7ImA9WBFSEUs.&quot;"><id>tag:blogger.com,1999:blog-6525469191850690957.post-126495264018718153</id><published>2006-12-30T18:44:00.000-05:00</published><updated>2007-02-10T23:03:19.799-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-02-10T23:03:19.799-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Greasemonkey" /><title>Moving my Gmail Greasemonkey scripts to code.google.com</title><content type="html">&lt;p&gt;I wanted to experiment with &lt;a href="http://code.google.com/"&gt;code.google.com&lt;/a&gt;'s project hosting feature, and I thought an easy way to get started would be with my Gmail-related Greasemonkey scripts. &lt;a href="http://code.google.com/p/gmail-greasemonkey/"&gt;This&lt;/a&gt; is their new home. I'm not sure how far I'll go with the "project" part (e.g. whether I would ever give anyone else commit privileges, though patches are welcome), but this at least lets me familiarize myself with Subversion. &lt;/p&gt;&lt;p&gt;I've also decided to actually serve all the scripts from the repository, so that there isn't an extra publishing step when making changes (thus far I don't feel the need for stable versions). There is also &lt;a href="http://persistent.info/greasemonkey/svnlog.xml"&gt;a feed&lt;/a&gt; for all changes, so this should make it easy to stay up to date even if I don't explicitly blog about them. The feed is generated with an XSLT based on &lt;a href="http://norman.walsh.name/2005/02/12/svnfeed"&gt;Norman Walsh's&lt;/a&gt; transform.&lt;/p&gt;&lt;p&gt;I also took this opportunity to make a few improvements to the scripts. The macros one can now also select saved searches when using the "g" keyboard shortcut (contributed by another user). The saved searches script now namespaces the saved data by the current user's email address. This should enable it to work better when there are multiple Gmail users per computer or Google Apps for Your Domain is being used.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/PersistentInfo/~4/89211463"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.persistent.info/feeds/126495264018718153/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.persistent.info/2006/12/moving-my-gmail-greasemonkey-scripts-to.html#comment-form" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6525469191850690957/posts/default/126495264018718153?v=2" /><link rel="self" type="application/atom+xml" href="http://blog.persistent.info/feeds/posts/default/126495264018718153" /><link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/PersistentInfo/~3/89211463/moving-my-gmail-greasemonkey-scripts-to.html" title="Moving my Gmail Greasemonkey scripts to code.google.com" /><author><name>Mihai Parparita</name><uri>http://www.blogger.com/profile/12343650264888591427</uri><email>noreply@blogger.com</email></author><feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=PersistentInfo&amp;itemurl=http%3A%2F%2Fblog.persistent.info%2F2006%2F12%2Fmoving-my-gmail-greasemonkey-scripts-to.html</feedburner:awareness><feedburner:origLink>http://blog.persistent.info/2006/12/moving-my-gmail-greasemonkey-scripts-to.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEIDQX08fCp7ImA9WBFSEUs.&quot;"><id>tag:blogger.com,1999:blog-6525469191850690957.post-8382449645132288108</id><published>2006-11-08T10:14:00.000-05:00</published><updated>2007-02-10T23:02:50.374-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-02-10T23:02:50.374-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Greasemonkey" /><title>Greasemonkey Script Updates</title><content type="html">&lt;p&gt;There have been some reports that my &lt;a href="http://persistent.info/greasemonkey/gmail-macros.user.js"&gt;Gmail Macros&lt;/a&gt; Greasemonkey script no longer works. I started to look into fixing this, and figured that while I was at it, I should incorporate the improvements that others have made to the script back into the original one. &lt;a href="http://persistent.info/archives/2005/12/23/greasemonkey"&gt;Both&lt;/a&gt; &lt;a href="http://persistent.info/archives/2006/03/21/gmail-macros"&gt;posts&lt;/a&gt; about it have a growing number of comments, including patched versions with various tweaks. Additionally, there is a &lt;a href="http://groups-beta.google.com/group/gmail-power-users"&gt;Google Group&lt;/a&gt; dedicated to Gmail power users that seems to have made even more changes. &lt;a href="http://persistent.info/greasemonkey/gmail-macros.user.js"&gt;The script&lt;/a&gt; has been updated and now contains the following additional commands:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;b&lt;/b&gt;: Remove label&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;z&lt;/b&gt;: Mark unread&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;o&lt;/b&gt;: Expand/collapse all messages in a conversation&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;shift-x&lt;/b&gt; + &lt;b&gt;a&lt;/b&gt;/&lt;b&gt;n&lt;/b&gt;/&lt;b&gt;r&lt;/b&gt;/&lt;b&gt;u&lt;/b&gt;/&lt;b&gt;s&lt;/b&gt;/&lt;b&gt;t&lt;/b&gt;: Select all/none/read/unread/starred/unstarred&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;h&lt;/b&gt;: Show help (reference for built-in and the script's keyboard shortcuts)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks go to &lt;a href="http://gr.ayre.st/"&gt;Karl&lt;/a&gt;, &lt;a href="http://www.coralindia.com/"&gt;Anand&lt;/a&gt; and Michael (?) for these improvements. If I have missed anyone, please let me know.&lt;/p&gt;

&lt;p&gt;On a related note, my &lt;a href="http://persistent.info/archives/2006/10/13/google-reader-redux"&gt;Google Reader/Gmail&lt;/a&gt; integration script has spawned two variants, one by &lt;a href="http://web.mit.edu/rradez/www/software/gmail-reader-box.user.js"&gt;Rob Radez&lt;/a&gt; and another by &lt;a href="http://www.winstonyw.com/2006/11/03/greasemonkey-script-gmail-and-reader-integrator/"&gt;Winston&lt;/a&gt;. They went for slightly deeper integrations, if you like the original you may like these too.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/PersistentInfo/~4/89211464"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.persistent.info/feeds/8382449645132288108/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.persistent.info/2006/11/greasemonkey-script-updates.html#comment-form" title="28 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6525469191850690957/posts/default/8382449645132288108?v=2" /><link rel="self" type="application/atom+xml" href="http://blog.persistent.info/feeds/posts/default/8382449645132288108" /><link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/PersistentInfo/~3/89211464/greasemonkey-script-updates.html" title="Greasemonkey Script Updates" /><author><name>Mihai Parparita</name><uri>http://www.blogger.com/profile/12343650264888591427</uri><email>noreply@blogger.com</email></author><feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=PersistentInfo&amp;itemurl=http%3A%2F%2Fblog.persistent.info%2F2006%2F11%2Fgreasemonkey-script-updates.html</feedburner:awareness><feedburner:origLink>http://blog.persistent.info/2006/11/greasemonkey-script-updates.html</feedburner:origLink></entry><feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetFeedData?uri=PersistentInfo</feedburner:awareness></feed>
