Live Command-Line
From Ajax Patterns
There's an archived version of this pattern available, taken from the Ajax Pattern book draft, showing roughly how it appeared before the page became publicly editable.
Evidence: 0/3
Tags: Assistive Command-Line CLI Grammar Supportive
Contents |
Ajax/Javascript Programming and Usability in "Ajax Design Patterns" Book |
In A Blink
Diagram: Error message under search query
Goal Story
Frank is using an advanced query tool to run a report on current output. He begins entering an SQL-like query: "list all ". At this point, a suggestion list appears with all the things that can be listed, and he chooses "products". Continuing on, the query is now "list all products where " and a new list appears: "creationTime", "quality", and so on. He chooses creationTime. then enters the rest manually, preferring to ignore further suggestions. The query ends up as "list all products where creationTime is today and quality is faulty". There's a tick next to the query to indicate it's valid.
Problem
How can a command-line interface be supported?
Forces
- Point-and-click interfaces can only say so much: command-line interfaces are more expressive. For rich applications, command-lines are an empowering tool for expert users.
- Search engines are going beyond locating pages and becoming general-purpose artificial intelligence interfaces. The trend is towards a situation where you can ask a search engine about anything you need to know.
- Since artificial intelligence has a long way to go, these queries are likely to be structured according to some grammar. For example, you can have Google matching on synonyms with a tilde sign ("~"), so ~clothes matches terms like "fashion" and "shirts". But the downside is that users must know about this grammar in order to use it.
Solution
In command-line interfaces, monitor the command being composed and dynamically modifying the interface to support the interaction. The interface changes according to data, business logic, and application logic. When the command-line is to executed on the server, as is often the case, the browser usually delegates to the server to evaluate the partial command.
The command-line is the quintessential expert interface and it's worth bearing in mind that most users are "perpetual intermediates". That is, they learn enough to get by, and generally learn new things only as and when required. So, while a powerful command-line may be a superior choice in the long-run, most users simply don't have the time to spend learning it in advance.
The problem arises with traditional command lines because they present the user with a blank slate. Everything the user types must be based on prior, upfront, learning, and the only feedback occurs after the command-line has been executed. That's not only inefficient for learning, but downright dangerous for sufficiently powerful commands. The model is: human enters command, computer executes command.
The solution is to be more interactive: with a smarter, more proactive, command-line, the construction of a command - its quick evolution from nothingness to an executable string - becomes something of a human-computer collaboration. Examples include:
- Indicate if the command is valid before submitting it. If it's not valid, prevent it from executing and inform the user what's wrong and how it can be rectified.
- Offer to fix invalid commands.
- Offer Suggestions to help complete part of the command.
- Help the user predict what will happen when the command is executed. For a query, this entails hinting at the result, such as estimating number of matches.
- Provide graphical widgets to help the user construct the command. For example, build up a mathematical expression using a calculator-like interface to introduce numbers and functions. The query is still represented as plain-text, but the text need not be entered by hand.
- Provide graphical widgets to help the user refactor the command. For example, you could provide a "delete this" button next to each condition in a query.
- Provide visualisation tools to render the query in other formats. For example, certain numerical queries might be visualised graphically.
These benefits go for novices and experts alike. In the context of supporting novices, the technique has sometimes been referred to as a "training wheels" approach. Like training wheels on a bike, you get a feel for the more powerful interface while still being productive.
Often, the command goes to the server, so it usually makes sense for the server to advise on partial commands. A basic procedure is this:
- Use Submission Throttling to periodically upload the partial command string as an XMLHttpRequest Call.
- The server then processes the command and returns supporting information.
- The browser updates the user interface accordingly.
As an Ajax feature, this pattern is largely speculative: I'm not aware of any production-level Ajax applications, but the command-line interface is growing at the same time as Ajax; it's inevitable these things will collide, and as the discussion here suggests, there are plenty of synergies. One source of inspiration here is the evolution of IDEs over the past five years, particularly in the Java space. Environments like Eclipse and IntelliJ Idea internally represent source files as data structures, leading to features such as ongoing error detection, offers to fix errors, suggestions, powerful refactorings, alternative displays. All of this happens without ever having to compile the source code. As another source of inspiration, there was a recent experiment on training wheels for the command-line. The study had students learning about the Unix command line from either a book or a GUI "trainnig wheels" interface, similar to a Live Command-Line. People generally preferred the GUI approach and were more productive with it.
Decisions
Where will the partial command be analysed - browser or server?
It's possible to perform some kinds of analysis in the browser. For example, the browser can check the query against a constant regular expression. So should you try to support analysis in the browser or delegate to the server?
There are several advantages to analysing the command server-side:
- The analysis can take into account server-side data, external services, and server-side hardware resources.
- In most cases, the command will ultimately be processed there, so this allows related logic to be kept in the same place.
- Since the command is just a text string, it's in a convenient form for uploading and server-side processing, as well as keeping earlier results in a Browser-Side Cache.
The downsides are:
- Extra load on the server.
- Extra bandwidth required to download richer responses.
- Extra lag between user typing and browser responding.
How much information will the server provide?
Producing more information for partial commands will consume more server resources as well as taking a bit longer to download. You'll need to trade off supportive information against resources. For example:
- In supporting validation, you can often rule out many errors with a simple regular expression. But more complex errors, relating to the existence of business objects for example, will get past that filter. Do you try to catch those too? Doing so would improve usability at the expense of resources.
- In hinting at the command's result, there's a spectrum of precision. For a query, you can say "there might be results", "there are results", "there are 4123 results". In an extreme case, you can offer a Live Search and actually show the results.
Real-World Examples
I'm not aware of an all-encompassing Live Command Line demo. However, the examples in Live Search and Suggestion are special cases of Live Command Lines. There are also some Javascript terminal emulators around, though they don't provide Live Command Lines - see Web Shell and JS/UNIX Unix Shell.
YubNub
YubNub isn't Ajaxian, but noteworthy as the first explicit exploration of the "search as command line" meme. Yubnub lets users submit commands, which are then mapped into external queries. For example, if you type in " sum 10 20, you get the sum of 10 and 20, if you type in "ajax form", you get search results from ajaxpatterns.org for "form".
Refactoring Illustration
Assistive Search Demo
The Assistive Search Demo was inspired by services such as Google Search which are pushing towards a general-purpose command line. For example, Google provides specialised results for if you type in a stock quote, a postcode, or a mathematical calculation. The problem is that many users don't know these things exist. One approach is to wrap the functions in a neat graphical interface, but then users will never progress to the power and convenience of a command-line. So an alternative is to augment the command-line, an idea this demo illustrates.
There's a typical search engine form - a free-range text input with a Submit button. In addition, there are a few images below, one for each category that can be searched. Thus, the user is alerted as to the capabilities of the search. As you type, the categories Highlight and un-Highlight to help predict what kind of results will be returned. All of this information comes from the server-side: the browser application doesn't know anything about the categories. It calls the server and startup to discover the categories and corresponding images. A timer monitors the command-line, continuing to ask the server which categories it matches. The browser then highlights those categories.
The startup sequence loads the categories and kicks off the command-line monitoring loop. The server is required to have a corresponding image for each category. If it says there's a category "phone" category, then there will be an image at Images/phone.gif. The images are all downloaded and placed alongside each other.
window.onload = function() {
initialiseCategories();
requestValidCategoriesLoop();
...
}
}
function initialiseCategories() {
ajaxCaller.getPlainText("categories.php?queryType=getAllCategoriesCSV",
onAllCategoriesResponse);
}
function onAllCategoriesResponse(text, callingContext) {
allCategoryNames = text.split(",");
var categoriesFragment = document.createDocumentFragment();
for (i=0; i<allCategoryNames.length; i++) {
var categoryName = allCategoryNames[i];
var categoryImage = document.createElement("img");
categoryImage.id = categoryName;
categoryImage.src = "Images/"+categoryName+".gif";
categoriesFragment.appendChild(categoryImage);
}
document.getElementById("categories").appendChild(categoriesFragment);
}
The key to the Live Command-Line is the monitoring loop. Whenever a change occurs, it asks the server to return a list of all matching categories.
function requestValidCategoriesLoop() {
if (query()!=latestServerQuery) {
var vars = {
queryType: "getValidCategories",
queryText: escape(query())
}
ajaxCaller.get("categories.php", vars, onValidCategoriesResponse,
false, null);
latestServerQuery = query();
}
setTimeout('requestValidCategoriesLoop();', THROTTLE_PERIOD);
}
The server uses a bunch of heuristics to calculate the categories that are valid for this query. For instance, it decides if something belongs to the "people" category by looking up a collection of pronouns in the dictionary. A controller will ultimately return the categories as a comma-separated list.
function getValidCategories($queryText) {
logInfo("Queried for '$queryText'\n");
$cats = array();
eregi(".+", $queryText) && array_push($cats, 'web');
eregi("^[0-9\+][A-Z0-9 \-]*$", $queryText) && array_push($cats, 'phone');
eregi("^[0-9\.\+\/\* -]+$",$queryText) && array_push($cats, 'calculator');
isInTheNews($queryText) && array_push($cats, 'news');
isInWordList($queryText, "./pronouns") && array_push($cats, 'people');
isInWordList($queryText, "./words") && array_push($cats, 'dictionary');
return $cats;
}
Back in the browser, the category images are dynamically updated with a CSS class indicating whether or not they are valid, determined by checking if they were in the list. There's also an event handler to perform a search on a specific category, as long as its valid.
function onValidCategoriesResponse(text) {
var validCategoryNames = text.split(",");
// Create a data structure to make it faster to determine if a named
// category is valid. For each valid category, we add an associative array
// key into the array, with the key being the category name itself.
validCategoryHash = new Array();
for (i=0; i<validCategoryNames.length; i++) {
validCategoryHash[validCategoryNames[i]] = "exists";
}
// For all categories, show the category if it's in the valid category map
for (i=0; i<allCategoryNames.length; i++) {
var categoryName = allCategoryNames[i];
var categoryImage = $(categoryName);
if (validCategoryHash[categoryName]) {
categoryImage.onclick = onCategoryClicked;
categoryImage.className="valid";
categoryImage.title =
"Category '" + categoryName + "'" +" probably has results";
} else {
categoryImage.onclick = null;
categoryImage.className="invalid";
categoryImage.title =
"Category '" + categoryName + "'" + " has no results";
}
}
}
Alternatives
Point-And-Click
The command-line involves typing, while point-and-click is a simpler interface style based on showing available options and letting the user click on one of them.
Drag-And-Drop
Another means of issuing commands is with Drag-And-Drop, such as dragging an item into a trashcan to delete it.
Related Patterns
Submission Throttling
Instead of processing the command upon each keystroke, use Submission Throttling to analyse it on frequent intervals.
Status Area
Feedback such as input validation and result prediction is usually shown in a Status Area.
Highlight
Some parts of the command can be Highlighted to point out errors, incomplete text, and so on. Also, aspects of the Status Area can be Highlighted to help with prediction.
Progress Indicator
If it takes more than a second to process the command-line, consider showing a Progress Indicator.
Browser-Side Cache
Introduce a Browser-Side Cache to retain the server's analysis of partial command.
Fat Client
Consider creating a Fat Client which tries to handle as much of the analysis itself, thus reducing server calls.
Live Search
Live Search is an extreme version of Live Command Line applied to search, where the command is effectively executed while the user types.
Suggestion
Providing Suggestions is one characteristic of Live Command-Lines.
Visual Metaphor
In some bureaucracies, when you hand in a form for long-term processing, there's an immediate spot check performed upfront. That's one of the things a Live Command Line can do - a little straightforward screening to prevent any glaring errors being sent for execution.
Want to Know More?
- Yubnub An innovative interface that lets users search different sites based on a comand-line. Users are allowed to add new commands - is this "social command-line sharing"?
- Russell Beattie: "Search as Practial Artificial Intelligence"
- Jeff Attwood: "Google-Fu" "(T)he browser address bar is the new command line".
Acknowledgements
Jonathan Aquino of Yubnub notified me when the product first came out, and also added a GET-based query mechanism to support the deep links in the Real-World Examples.
Time your website with
WebWait - from the creator of AjaxPatterns.org
