XUL is an application framework from Mozilla (Firefox and Thunderbird are XUL applications with C++ extensions). I recently learned that you can run command-line programs from within script sections of XUL, which makes it significantly more useful for me. Of course, there are security restrictions; the XUL file needs to load from a local file (or be signed).
What I really like about it is that the UI is declarative, you can just type it up, preview it in the browser and hit reload to see changes. With the error console and other developer tools, you can use the same development tools and techniques from the web. Add the flexibility of JavaScript and you've got a really powerful base. There are some issues with particular 3rd party JavaScript libraries (such as jQuery), but it's not a big stumbling block.
Here is a toy application, yet another Twitter client. You'd run it with (for instance) firefox -chrome test.xul. If it executed commands, it would need a line that said netscape.security.PrivilegeManager.enablePrivilege ("UniversalXPConnect"); (the example does output with AJAX instead).
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<!--
Twitter updater implemented in XUL
-->
<window
id="win"
title="XUL Twitter"
orient="vertical"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="updateLabel()"
>
<script>
var max = 140;
var uid = 'guymac';
var pwd = '******';
var twitUpdate = 'http://twitter.com/statuses/update.xml';
var twitCloser = 'http://twitter.com/account/end_session';
function updateLabel()
{
var lbl = document.getElementById('lbl');
var txt = document.getElementById('txt');
var rem = max - txt.textLength;
lbl.textContent = rem + ' char' + (rem > 1 ? 's' : '' ) + ' remaining';
txt.disabled = !(rem >= 1);
}
function postTweet()
{
var lbl = document.getElementById('lbl');
try
{
var req = new XMLHttpRequest();
req.open("POST", twitUpdate, false, uid, pwd);
req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
req.send('status=' + document.getElementById('txt').value);
if (req.status != 200) throw req.statusText;
lbl.textContent = 'Twitter Updated!';
}
catch (ex)
{
lbl.textContent = 'Update failed (' + ex + ')';
}
var req = new XMLHttpRequest();
req.open("GET", twitCloser, false, uid, pwd);
req.send(null);
}
</script>
<textbox
id="txt"
maxlength="140"
size="140"
multiline="true"
oninput="updateLabel()"
/>
<label id="lbl"/>
<hbox>
<button label="Post" oncommand="postTweet()"/>
<button label="Close" oncommand="window.close()"/>
</hbox>
</window>