Ubiquity search command tutorial

After enjoying using and developing for Ubiquity a great deal, I wanted to provided a brief howto for those wishing to get into Ubiquity command development. I wrote this after reading the command author tutorial (which you *must* read) and heavily consulting the source of the commands included in Ubiquity by default (which you *should* read). As you follow along, try the code provided in the command-editor which comes with Ubiquity.

In this tutorial, we are going to develop a search command that will retrieve word definitions from dict.org. For those who do not know, the DICT protocol (specified by RFC 2229) allows for the retrieval of word definitions over a network (maintained by The Dict Development Group) but they make a web interface available on the home page.

To create our command, we’ll need the following things:

  • Metadata: Ubiquity allows useful information to be embedded in the command itself. You can include data about the plugin such as it’s name, description and license along with the author’s name and contact info.
  • Search URL: This is the URL into which our search query will be embedded. You can figure it out by looking in your browser’s URL bar when you do a search or by dissecting the form which launches the search. In our case, I cheated by having Firefox add a keyword for the search field and then looking at it’s properties in my bookmarks organizer.
  • Icon: There is nothing wrong with a good presentation and it always helps to have an icon! For our example, I scraped the favicon URL from the dict.org home page’s source.

The standard way to create a Ubiquity command is with CmdUtils.CreateCommand() which takes an ordinary JavaScript object (written in object-literal syntax) containing key-value pairs defining your command. The definition for our dict command looks like this:

CmdUtils.CreateCommand({
        name: "dict",
            icon: "http://www.dict.org/favicon.ico",
            author: {name: "Jonathan E. Magen", homepage: "http://yonkeltron.com"},
            license: "GPL",
            description: "Retrieve word definitions from the <a href=\"http://dict.org\">Dict.org DICT server</a>",
            takes: {name: noun_arb_text},
            preview: function( pblock, directObject )
            {
                if (!directObject.text || directObject.text.length < 1) {
                    pblock.innerHTML = "Retrieves word definitions";
                    return;
                }

                pblock.innerHTML = "Retrieve word definitions for <i>" + directObject.text + "</i>";
            },
            execute: function( directObject )
            {
                var url = "http://www.dict.org/bin/Dict?Form=Dict2&Database=*&Query=";
                Utils.openUrlInBrowser(url + directObject.text);
            }
    });

At first glance there is a lot going on here, so take some time to look over the above snippet and check out some of the key features.

  • Metadata: As promised, the name, icon, author data, license and description are all there in plain sight with very little fanciness there. I chose to omit my email for fear of getting massively spammed but it can be included in there for those authors who wish to embed other contact info.
  • Argument declaration: takes: {name: noun_arb_text} is a neat little line which provides some info to Ubiquity’s natural language features. Essentially, it lets the parser know that the argument to the command is going to be some arbitrary noun in text form. There are other nouns of various flavors and I refer you to the source code examples and documentation mentioend earlier as this feature develops. Since Ubiquity is just smart like this, making this declaration lets Ubiquity know that any piece of text can be used as an argument. Therefore, highlighting a word and typing dict this will let Ubiquity know to lookup the definition for whatever word is highlighted.
  • The preview function: The preview function is used to provide a preview (shocker!) in the Ubiquity prompt pane before the command is executed. Since the argument to this can be either a string or a function, there can be an arbitrary amount of complexity here (for example, the Google map command uses the maps API to pre-fetch a smaller map showing you a dynamic preview). We’re going to take a very small advantage of that here and add a little prettiness to our command. As you can see, the preview function takes two arguments, pblock and directObject. The first one, pblock, is the HTML of the block where the preview is contained so anything done to that will immediately be reflected in the preview being displayed by Ubiquity for that command. The second, directObject, is the search term, in whatever form it has and is just what’s it’s called a direct object. If there isn’t anything in the directObject, the preview string is just a general usage statement. If there is something there, the preview string will indicate which word is going to be looked up.
  • The execute function: This is where the magic happens! The execute function takes only the directObject argument, splices it into the correct place in the search URL (in our case this is right at the end) and opens the URL in the browser using Utils.openUrlInBrowser().

See, this code isn’t so scary at all! In fact and indeed, it should be very easy to see that Ubiquity is actually quite flexible and clever.

Ubiquity comes with a number of helper functions which are very useful in command development. One such command is the makeSearchCommand() utility which provides a convenient wrapper around the more general CmdUitls.CreateCommand() function and takes fewer parameters. This helper function also makes certain assumptions about your search command and takes care of details for you, such as automagically declaring the argument as noun_arb_text and implementing the execute function for you based on the URL you provide. Using makeSearchCommand(), our command looks like this:

makeSearchCommand({
        name: "dict",
            author: {name: "Jonathan E. Magen", homepage: "http://yonkeltron.com"},
            license: "GPL",

            url: "http://www.dict.org/bin/Dict?Form=Dict2&Database=*&Query={QUERY}",
            icon: "http://www.dict.org/favicon.ico",
            description: "Retrieve word definitions from the <a href=\"http://dict.org\">Dict.org DICT server</a>",
            preview: function( pblock, directObject )
            {
                if (!directObject.text || directObject.text.length < 1) {
                    pblock.innerHTML = "Retrieves word definitions";
                    return;
                }

                pblock.innerHTML = "Retrieve word definitions for <i>" + directObject.text + "</i>";
            }
    });

The only major difference here is the passing of a the search URL with the {QUERY} at the end showing where Ubiquity should put the search term. The other parameters in the search URL for this example specify that this is a dict query and that results should be returned from all definition databases on the dict.org server.

This command definitons works exactly the same way as the one before it and has the same result. So, the moral of the story is that if you are creating a simple search helper command, then makeSearchCommand() is your friend.

I hope that this tutorial has helped to illustrate both the coolness of Ubiquity and the ease which one can develop commands for it. I eagerly encourage feedback in order to make this howto better and thank the Mozilla folks who gave us such a wonderful tool!

Facebook search for Ubiquity

I recently mentioned Ubiquity, Firefox’s new experimental command line for the browser. Anyway, I was tinkering about with the command author tutorial after the upgrade to 0.11 and browsing the source of the included commands when I decided to try my hand at authoring my own command. After messing about with some of the basics and testing things out, I came up with this, my own search command for Facebook. As of it’s current version, it’s actually very simple (making use of the excellent makeSearchCommand() helper function) and works just fine! Subscribe to it here for updates in the future.

Mozilla rolls out a browser command line called Ubiquity

As is being covered on sites and blogs across the webbernet, Mozilla labs released their first semi-usable beta of their new browser interface called Ubiquity. Unlike Goosh (the unofficial command shell for Google), Ubiquity is a command line interface which uses natural language to execute intelligent behaviors. The screenshots look absolutely fabulous and the concept is brilliant. There are some simple commands already implemented such as the map command which allows you to automagically pull up a Google map of a location and get directions. Some other commands of note let you retrieve information from Wikipedia, search using your engine of choice and get weather. The video shows some very impressive functionality and gives a taste of the natural language functionality that they seem to have in mind. The review over at Ars Technica has an excellent overview of what’s going on and makes the excellent point that the usefulness of this tool will increase dramatically if it can support pipes in the style of Unix and Linux shells (bash is my fav).

While I don’t like that every single article touts the newfound potential of “making your own mashup” with that characteristic fanboy enthusiasm, I think this is an exceptional innovation with some great promise. If we’re lucky, the average user will learn to love the efficiency, realizing that command-line interfaces are actually superior to graphical interfaces in many ways and not just some antiquated technology. Maybe I won’t get such strange looks whenever I pull up a shell…

Also of note, the Ubiquity 0.1 Author Tutorial gives a whole slew of wonderful examples for people wishing to develop their own commands using plain old JavaScript. Also, it would seem that Ubiquity bundles jQuery as a JS toolkit! How cool is that?