TkDiff for Subversion on OS X

Slightly less sentimental post today.

TkDiff is my graphical diff I normally use. Subversion is what I use most often as version control outside of work (a Perforce zone). OS X is what runs on my laptop.

I spent longer than I'd like to figure this out by Googling it, so here's a quick note on how to use TkDiff as the SVN diff program on OS X for future searchers.
  1. Download and install TkDiff from Sourceforge.
  2. Edit ~/.svn/config
  3. Set the diff-cmd variable to point at TkDiff with the following line.
diff-cmd = /Applications/TkDiff.app/Contents/Resources/Scripts/tkdiff.tcl

Then, when you run svn diff, it'll run in TkDiff.

Now you know. Go build stuff.

 

George Carlin's address book

Though currently dead himself, George Carlin had this bit about when it was appropriate to remove a dead person's entry from your address book. Right after the death might be sensible (really, you're never going to call it again), but also heartless and dismissive of the person's memory. But to never do so is to be unrealistic, forever stuck in the denial stage of grief.

He conveys the thought more humorously than I can (or have here). We all have our preferred mediums. His is stand-up, mine: a blog.

The act of deleting a number from my phone is momentary, deliberate. "Do you really want to delete this contact?", my phone asks. The big caution-red "delete" button imparts the permanency of its pressing.



Four years ago I packed my car full of belongings and headed west. San Francisco feels a world away from rural Wisconsin. Not just culturally. Geographically.

The distance isn't terrible. This modern world has phones, instant messages, emails, even video chats. But people still fly. And I still do, back home, to what seem like marathon visiting sessions. Hours in the car to connect the towns where my relatives live.

When saying goodbyes and heading out doors, there was always a cold little voice: This could be the last visit. Only the Fates really knew. I worried each time.

The goodbyes have generally been followed with hellos on later visits. But early this year, a goodbye went unpaired. Paging through names in my phone, my grandma's name sticks out when happening through the Gs. In the summers, my brothers and I spent weeks at a time at her house in Reedsberg.

A few nights ago, I had a bad dream. I was rushing to get home before she died. It left me shaken. I'd been through my grieving for months. It had not been on my mind. Sometimes your mind wanders down paths you've not been down lately.

I hadn't been watching the calendar, but it was the six month anniversary of her death in February.



Adam's grandmother died close to when mine did. He told a bittersweet anecdote about her. I didn't write anything. Couldn't really bring myself to. I flew home, went to the funeral, and came back. The following week I left the country on vacation.

George Carlin said he kept his dead friends' numbers for six weeks. I'm at six months. The number, I'm sure, has been disconnected or reassigned. I think I'll leave it for now.

 


This isn't how it was supposed to end.

 

Art work

I put a lot of effort into my job, and at some level, it's a creative outlet. Still, I sometimes want to put my into little side projects.

I've got a bit of nostalgia for cursor-position-based programs, software like xeyes, Jewel Thief, and Neko the Cat.

Anyway, Alex was in town last week (securing an apartment before moving out), and I was chatting about it with him. Last night, I had a few free hours and just coded it up. I made the first part, but I need more help.

First, click through:


Might not work in IE. I'll fix it later.

I want to make a bigger art project out of this, so I'd like to get more people on Flickr to take eye-tracking photos of themselves and combine them into one big cool page. I put up a page with the instructions. Anything is fine — snapping the photos with your phone is plenty fine.

Thanks for your help.

 

JavaScript on Rhino on Java on App Engine

I've got a limited amount of free time, and there's a lot of stuff in this world to play around with. When I'm trying to put together little demos and things, I tend to use Python on the server side -- it's a succinct, loosely type language with a lot of time and typing-saving features. Also, it's an interpreted language; App Engine's development server automatically catches change you make to a file, so my development cycle is just type-save-reload (leaving little time for swordplay).

Some of those language features' advantages start not to be advantages when your app gets more complex, however. When writing a large application, features like type checking, interface definition, and member access permissions become essential. While they introduce a lot of verbosity, they do make the problem of writing a large, complex, and (hopefully) fast app easier.

It's little surprise, then, that the second runtime the App Engine team released is Java (sadly, not Fortran).

For certain tasks, I'll even admit I like Java. It has its time and place. But what gets me excited about the App Engine announcement is that there are a lot of scripting language implementations that are written for Java. Two that should get web folks excited are JRuby and, for JavaScript, Rhino.

I'm excited about the latter. Rhino on App Engine means that I can quickly script apps in probably my most productive language, JavaScript. So I took some time yesterday mashing up the embedded Rhino examples with App Engine's "Hello World!" example.

The two classes, hopefully in a working state, are here, sans all the import statements:

public class Response extends ScriptableObject {
public Response() {
out = new StringWriter();
}

@Override
public String getClassName() { return "Response"; }

public void jsFunction_write(String str) {
out.write(str);
}
public StringWriter out;
}

public class RhinoServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws IOException {
res.setContentType("text/plain");

Context cx = Context.enter();
try {
Scriptable scope = cx.initStandardObjects();

ScriptableObject.defineClass(scope, Response.class);
Scriptable response = cx.newObject(scope, "Response");
ScriptableObject.putProperty(scope, "response", response);

FileReader reader = new FileReader("hellorhino.js");
Object result = cx.evaluateReader(scope, reader, path, 1, null);

Response javaResponse = (Response) cx.jsToJava(
response, Response.class);
res.getWriter().write(javaResponse.out.toString());
} catch (Exception ex) {
res.setStatus(500);
res.getWriter().println(ex.toString());
} finally {
Context.exit();
}
}
}

Basically, I'm just exposing to the JavaScript environment an object, in the global scope, named "request" with one method: "write". Obviously, as a more robust framework, you could expose more of the underlying App Engine APIs, or even make the Java objects available for scripting.

Anyway, in this way, you can start writing your server side logic in JavaScript. So in this example, hellorhino.js is just:

var words = ['Hello', 'World!'];
response.write(words.join(' '));

Cool stuff. This is really the first I've ever worked with Rhino, but I hope to spend some more of my free cycles on this and come up with a more general system for working server-side in JavaScript on App Engine. There's a lot of potential here.

 

JSON Proxy

Brett works on Google App Engine. As such, he persistently badgers me to build App Engine apps. This dates back to long before App Engine existed externally.

I've made a few, the simplest of which actually got popular.

Anyway, I recently put up another one: JSON Proxy

Cross-domain JSONP (or "JSON with callbacks") has long been an interest of mine. It's interesting that many sites are offering JSON as an output type for their web APIs. Flickr, Twitter, and GData APIs all do.

Having such APIs is great -- it allows client-side code to pull data as JavaScript object literals across domains, skirting the same origin policy of XMLHttpRequest (just make sure you never serve private user data with this method). For example, on this page, I'm using a URL formed with the Twitter API to fill the Tweets section in the sidebar (a callback called twitterCallback is called with a JSON object of my tweets).

Unfortunately, there no recourse if some web service lacks JSON as an output type. Some sort of proxy is required. The Google AJAX Feed API allows fetching of RSS and Atom feeds, which is very useful (the XML-to-JSON transformation is better defined in this case).

So, I wrote a proxy for an even more general case: any XML, and accepts a callback parameter, which allows you to fetch any GET-accessible XML resource as a JSON object. The App Engine app fetches the XML content, transforms it to JSON, and sends it out, wrapped in a callback if requested.

proxy illustration

This allows some cool stuff. I came up with the example of all-client-side Amazon search through their Amazon Web Services API.

Anyway, I've written a better and more technical writeup, and have posted the source.

I would love it if somebody would come up with a really innovative application of the proxy.

Enjoy!

 

Debugging JavaScript on Android

I've been messing around with the Android emulator, particularly with its browser. Debugging just JavaScript wasn't well covered in the documentation, and I spent a little while getting it set up. I wanted to publish it here so it shows up in others' web searches -- I'll look into adding some of this to the official docs at work.

Anyway, to get you started: You can use either an actual Android device or an emulator. Install the Android SDK.

Then, you can use the Android Debug Bridge to connect to your device or emulator.

The key thing to note is that browser debug output will be tagged with WebCore. So, if you're only interested in browser debug output, start adb filtering debug output for everything but those tags. The command line is:
adb logcat WebCore:V *:S
Which means "show all debug output tagged with WebCore, and silence everything else" (see their documentation for more information).

You can do some sniffing around by looking at the window object in the browser:
var terms = [];
for (key in window) {
terms.push(key + ': ' + window[key] );
}
terms.sort();
for (var i = 0; i < terms.length; i++) {
document.write('<p>' + terms[i] + '</p>');
}
You'll notice a bunch of goodies in there (and a few interesting ones I'll investigate later). But, particularly, you'll notice a reference to window.console. Loop over that and you'll see:



Turns out it there's a console object with a subset of the methods from Firebug's console, though they just take a single string for the argument (not multiple arguments). The method names all produce debug output at the "D" level. So, this code:
console.error('1');
console.info('2');
console.log('3');
console.warn('4');
Produces this output:
D/WebCore (  165): Console: 1 line: 0 source: http://...
D/WebCore ( 165): Console: 2 line: 0 source: http://...
D/WebCore ( 165): Console: 3 line: 0 source: http://...
D/WebCore ( 165): Console: 4 line: 0 source: http://...
In addition, any JavaScript errors will also show up in the output. Good stuff.

Now you know.