A couple of years ago I made a live Bash demo using JavaScript and Q. Those not familiary with Q should get aquainted as the that Javscript library has some awesome functionality for asynchronous promises.
Click here for a fully functional open source demo..
HTML
<script src="//cdnjs.cloudflare.com/ajax/libs/q.js/1.0.0/q.js"></script> <div id="wnd"></div> <div id="log"></div> <textarea rows="11" cols="50"> % cat example.c #include <stdio.h> int main() { printf("Goodbye Cruel World!\n"); return 0; } % make example.c -o example % ./example Goodbye Cruel World! </textarea>
CSS
body { background: black; } #wnd { background: #232; border-radius: .2em; white-space: pre-wrap; padding: .5em; font-family: "Consolas", "Ubuntu Mono", "Monaco", monospace; color: white; } .prompt { color: #99aaee; } .cmd { color: #9e9e9C; }
JQuery
var prompt; function setPrompt(usr, domain) { prompt = usr + '@' + domain + ' %'; } function addOutput(s) { $('<div>').text(s).appendTo(wnd); return Q.delay(100); // return addPrompt(); } function addInput(s) { var l = $('.prompt:last'); var e = $('<span>').addClass('cmd').appendTo(l); return addLettersRecursive(e, s); } function addPrompt() { var l = $('<div>').text(prompt).addClass('prompt').appendTo(wnd); return Q.delay(900); } function addLettersRecursive(container, s) { container.append(s.charAt(0)); // dangerous 😦 var row_complete = Q.defer(); Q.delay(100).then(function() { if (s.length <= 1) { row_complete.resolve(); } addLettersRecursive(container, s.substr(1)).then(function() { row_complete.resolve(); }) }); return row_complete.promise; } $( document ).ready(function() { $('textarea').hide(); setPrompt('inge', 'sparkledb.net'); var lines = $('textarea').val().split('\n'); var promise = new Q(); promise = promise.then(function() { lines.forEach( function(item) { if (item[0] == '%') { promise = promise.then(function() { return addPrompt(); }) promise = promise.then(function() { return addInput(item.substr(1)); }) } else { promise = promise.then(function() { return addOutput(item); }) } }) }) promise.done(); });