Modern algorithms textbooks often devote entire chapters to shortest path algorithms, so I was surprised to see that the citation said it was only a page. I thought it might have been a misprint and I pulled up the original CACM article from the ACM website. Not only was Floyd's article less than a page, it was only about 1/4 of a column of a page. It was only 21 lines, including title and comments!
Floyd's article was published back in 1962, when men were men, computers filled buildings, and the CACM published an Algorithms column consisting mainly of short algorithms submitted by readers. The private sector seemed more involved in basic computer research then than they are now; there are algorithms in this issue submitted by researchers at Control Data, Burroughs, Sperry, and the US Steel Applied Research Lab. As for the code, I thought it was a Pascal-like pseudocode, but it turns out to be ALGOL-60.
Ah, the good old days...
The trick is to wrap the bad column names in double quotes. In other words, instead of using
SELECT foo, bar, order FROM baz;
which returns an error, use
SELECT foo, bar, "order" FROM baz;
In fact, looking through the schemas it appears that RoR wraps all the column names in quotes. I suppose this must be so that RoR developers can name their fields anything they want without having to worry about the underlying implementation in SQLite.
The first thing you need to do is create a directory for your extension. I put mine in ~/extensions/backlog. In that directory we're going to put 4 files:
chrome.manifest tells Firefox where the files are for the extension. This is right out of the Mozilla documentation.
content backlog content/
overlay chrome://browser/content/browser.xul chrome://backlog/content/overlay.xul
install.rdf tells Firefox meta information about the extension:
<?xml version="1.0"?>
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
<Description about="urn:mozilla:install-manifest">
<em:id>backlog@viscog.cs.drexel.edu</em:id>
<em:name>Back Log</em:name>
<em:version>1.0</em:version>
<em:description>Add history log entries when hitting back button</em:description>
<em:creator>Walt Mankowski</em:creator>
<em:homepageURL>http://kb.mozillazine.org/Getting_started_with_extension_develop ment</em:homepageURL>
<em:targetApplication>
<Description>
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
<em:minVersion>3.0</em:minVersion>
<em:maxVersion>3.0.*</em:maxVersion>
</Description>
</em:targetApplication>
</Description>
</RDF>
Most of that is boilerplate. The most important field is em:id, because that's how you'll identify it to Firefox later on. Note that it has to be in the form of an email address, though it doesn't actually have to be a valid email address. In this extension it's important that em:minVersion is set to 3.0, since I'm using a Firefox 3.0 feature to do the logging.
content/overlay.xul tells Firefox what part of the browser we want to extend. In the tutorials they do things like add "Hello, world" somewhere in the browser window. Here I want to leave the window itself alone and just add some javascript.
<?xml version="1.0"?>
<overlay id="backlog-overlay"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script src="overlay.js"/>
</overlay>
content/overlay.js is the javascript code that does the logging when the forward and back buttons are pressed.
window.addEventListener("load", function() { Backlog.onLoad(); }, false);
var Backlog = {
onLoad: function() {
// initialization code
var appcontent = document.getElementById("appcontent"); // browser
if (appcontent)
appcontent.addEventListener("pageshow", Backlog.onPageShow, true);
},
onPageShow: function(aEvent) {
var doc = aEvent.target;// doc is document that triggered "onPageShow" event
// this service is Firefox's API for logging history events
var historyService = Components.classes["@mozilla.org/browser/nav-history-service;1"]
.getService(Components.interfaces.nsIGlobalHistory2);
if (aEvent.persisted)// page pulled from cache, so log it
historyService.addURI(doc.documentURIObject, false, true, null);
}
};
When the overlay is loaded, I add a listener for the pageshow event. This event is triggered both when a new page is displayed (e.g. when clicking on a hyperlink) and when a page is pulled out of the cache via the forward or back buttons. When the event occurs, I check the persisted flag. This is set to true when the page is in the session history, i.e. we've already seen the page once, and now we're seeing it again with Forward or Back. Firefox normally doesn't add these pages again to its history database, but that's exactly what I wrote this extension to do. To write the URI out history, I call addURI() in the nsIGlobalHistory2 service.
It's possible to package up extensions so that they install automatically, but since I only need this to run on a single box I didn't bother. Instead I just followed the instructions for testing extensions. It turns out that while extensions themselves contain lots of ugly XML and javascript code, testing them is really easy. Just go to your Firefox profile directory. (On my box it's ~/.mozilla/firefox/.default.) Then go one level deeper to the extensions directory. In that directory, create a file whose name is the id of the extension ("backlog@viscog.cs.drexel.edu" in this case). The file should contain a single line containing thee root path of the extension ("~/extensions/backlog"). Finally restart Firefox, and you should see a message saying that it's found a new extension. If you decide to disable the extension, just remove the file from the extensions directory and restart Firefox.
It turned out to be only about 10 lines of javascript, but of course coming up with the right 10 lines of javascript, and figuring out how to package them into an extension, took all day.
I'll try to post more details once I get a chance to clean out all my debugging code and hopefully make a more minimal version than what I have.
(defun compilation-build-compilation-error-regexp-alist() (lambda()))
It's so obvious I don't know why it took me so long to figure it out.
This afternoon my labmates asked me to settle an argument. They handed me some headphones and asked me who was singing. I put them on and heard what sounded like Aerosmith doing Dream On. I listened for a bit to make sure it really was Aerosmith, then ventured "umm...Steve Tyler?"
"How did you know that?" asked the woman who just lost the bet. "It doesn't sound anything like him!"
"Are you kidding? It's one of the most popular rock songs in history. I thought everyone knew that was Aerosmith."
"I didn't recognize it at all. You mean you've really heard it before?"
"Only about 1000 times." All before you were born!
Kids nowadays, with their hip hop and their iPods, I tell ya...
Someone on Drexel's ethernet has an iTunes share called (roughly) "Harps are for angels, God plays guitar"and it's full of nothing but Joe Satriani tunes.
"That's it Gromit cheeeeese We'll go somewhere where there's cheese!"