text:
/*

     TODO:
           add destroy method to terminal (cmd alrady have it)

           add support for - $(...).each(function() { ... });

           $.fn.pluginname = function(options) {
             var settings = $.extend({}, $.fn.pluginname.defaultOptions, options);

             return this.each(function() {
                var $this = $(this);
             });
             $.fn.pluginname.defaultOptions = {
             };
          };

          if (CTRL+D && ajax-call) {
            xhr.abort();
          }

          object as first arguments which maps commands arguments to methods
          context of functions will be the terminal instance.

          terminal({
            js: function(a, b, c) {
              this.echo(a + '__' + b + '__' + c);
            },
            mysql: function() {
              var query = Array.prototype.splice(argument, 0).join(' ');
            }
          });

          if you type 'js foo bar baz' it will call js('foo', 'bar', 'baz');

*/
// return true if value is in array
Array.prototype.has = function(val) {
    for (var i = this.length; i--;) {
        if (this[i] == val) {
            return true;
        }
    }
    return false;
};

// debug function
function get_stack(caller) {
    if (caller) {
        return [caller.toString().match(/.*\n.*\n/)].concat(get_stack(caller.caller));
    } else {
        return [];
    }
}

(function($, undefined) {

    // ----------------------------------------
    // START Live Query plugin
    // ----------------------------------------
    $.extend($.fn, {
	    livequery: function(type, fn, fn2) {
		    var self = this, q;

		    // Handle different call patterns
		    if ($.isFunction(type))
			    fn2 = fn, fn = type, type = undefined;

		    // See if Live Query already exists
		    $.each( $.livequery.queries, function(i, query) {
			    if ( self.selector == query.selector && self.context == query.context &&
				     type == query.type && (!fn || fn.$lqguid == query.fn.$lqguid) && (!fn2 || fn2.$lqguid == query.fn2.$lqguid) )
					// Found the query, exit the each loop
					return (q = query) && false;
		    });

		    // Create new Live Query if it wasn't found
		    q = q || new $.livequery(this.selector, this.context, type, fn, fn2);

		    // Make sure it is running
		    q.stopped = false;

		    // Run it immediately for the first time
		    q.run();

		    // Contnue the chain
		    return this;
	    },

	    expire: function(type, fn, fn2) {
		    var self = this, x =10;

		    // Handle different call patterns
		    if ($.isFunction(type))
			    fn2 = fn, fn = type, type = undefined;

		    // Find the Live Query based on arguments and stop it
		    $.each( $.livequery.queries, function(i, query) {
			    if ( self.selector == query.selector && self.context == query.context &&
				     (!type || type == query.type) && (!fn || fn.$lqguid == query.fn.$lqguid) && (!fn2 || fn2.$lqguid == query.fn2.$lqguid) && !this.stopped )
					$.livequery.stop(query.id);
		    });

		    // Continue the chain
		    return this;
	    }
    });

    $.livequery = function(selector, context, type, fn, fn2) {
	    this.selector = selector;
	    this.context  = context || document;
	    this.type     = type;
	    this.fn       = fn;
	    this.fn2      = fn2;
	    this.elements = [];
	    this.stopped  = false;

	    // The id is the index of the Live Query in $.livequery.queries
	    this.id = $.livequery.queries.push(this)-1;

	    // Mark the functions for matching later on
	    fn.$lqguid = fn.$lqguid || $.livequery.guid++;
	    if (fn2) fn2.$lqguid = fn2.$lqguid || $.livequery.guid++;

	    // Return the Live Query
	    return this;
    };

    $.livequery.prototype = {
	    stop: function() {
		    var query = this;

		    if ( this.type )
			    // Unbind all bound events
			    this.elements.unbind(this.type, this.fn);
		    else if (this.fn2)
			    // Call the second function for all matched elements
			    this.elements.each(function(i, el) {
				    query.fn2.apply(el);
			    });

		    // Clear out matched elements
		    this.elements = [];

		    // Stop the Live Query from running until restarted
		    this.stopped = true;
	    },

	    run: function() {
		    // Short-circuit if stopped
		    if ( this.stopped ) return;
		    var query = this;

		    var oEls = this.elements,
			els  = $(this.selector, this.context),
			nEls = els.not(oEls);

		    // Set elements to the latest set of matched elements
		    this.elements = els;

		    if (this.type) {
			    // Bind events to newly matched elements
			    nEls.bind(this.type, this.fn);

			    // Unbind events to elements no longer matched
			    if (oEls.length > 0)
				    $.each(oEls, function(i, el) {
					    if ( $.inArray(el, els) < 0 )
						    $.event.remove(el, query.type, query.fn);
				    });
		    }
		    else {
			    // Call the first function for newly matched elements
			    nEls.each(function() {
				    query.fn.apply(this);
			    });

			    // Call the second function for elements no longer matched
			    if ( this.fn2 && oEls.length > 0 )
				    $.each(oEls, function(i, el) {
					    if ( $.inArray(el, els) < 0 )
						    query.fn2.apply(el);
				    });
		    }
	    }
    };

    $.extend($.livequery, {
	    guid: 0,
	    queries: [],
	    queue: [],
	    running: false,
	    timeout: null,

	    checkQueue: function() {
		    if ( $.livequery.running && $.livequery.queue.length ) {
			    var length = $.livequery.queue.length;
			    // Run each Live Query currently in the queue
			    while ( length-- )
				    $.livequery.queries[ $.livequery.queue.shift() ].run();
		    }
	    },

	    pause: function() {
		    // Don't run anymore Live Queries until restarted
		    $.livequery.running = false;
	    },

	    play: function() {
		    // Restart Live Queries
		    $.livequery.running = true;
		    // Request a run of the Live Queries
		    $.livequery.run();
	    },

	    registerPlugin: function() {
		    $.each( arguments, function(i,n) {
			    // Short-circuit if the method doesn't exist
			    if (!$.fn[n]) return;

			    // Save a reference to the original method
			    var old = $.fn[n];

			    // Create a new method
			    $.fn[n] = function() {
				    // Call the original method
				    var r = old.apply(this, arguments);

				    // Request a run of the Live Queries
				    $.livequery.run();

				    // Return the original methods result
				    return r;
			    }
		    });
	    },

	    run: function(id) {
		    if (id != undefined) {
			    // Put the particular Live Query in the queue if it doesn't already exist
			    if ( $.inArray(id, $.livequery.queue) < 0 )
				    $.livequery.queue.push( id );
		    }
		    else
			    // Put each Live Query in the queue if it doesn't already exist
			    $.each( $.livequery.queries, function(id) {
				    if ( $.inArray(id, $.livequery.queue) < 0 )
					    $.livequery.queue.push( id );
			    });

		    // Clear timeout if it already exists
		    if ($.livequery.timeout) clearTimeout($.livequery.timeout);
		    // Create a timeout to check the queue and actually run the Live Queries
		    $.livequery.timeout = setTimeout($.livequery.checkQueue, 20);
	    },

	    stop: function(id) {
		    if (id != undefined)
			    // Stop are particular Live Query
			    $.livequery.queries[ id ].stop();
		    else
			    // Stop all Live Queries
			    $.each( $.livequery.queries, function(id) {
				    $.livequery.queries[ id ].stop();
			    });
	    }
    });

    // Register core DOM manipulation methods
    $.livequery.registerPlugin('append', 'prepend', 'after', 'before', 'wrap', 'attr', 'removeAttr', 'addClass', 'removeClass', 'toggleClass', 'empty', 'remove');

    // Run Live Queries when the Document is ready
    $(function() { $.livequery.play(); });

    // Save a reference to the original init method
    var init = $.prototype.init;

    // Create a new init method that exposes two new properties: selector and context
    $.prototype.init = function(a,c) {
	    // Call the original init and save the result
	    var r = init.apply(this, arguments);

	    // Copy over properties if they exist already
	    if (a && a.selector)
		    r.context = a.context, r.selector = a.selector;

	    // Set properties
	    if ( typeof a == 'string' )
		    r.context = c || document, r.selector = a;

	    // Return the result
	    return r;
    };

    // Give the init function the jQuery prototype for later instantiation
    // (needed after Rev 4091)
    $.prototype.init.prototype = $.prototype;
    // ----------------------------------------
    // START Storage plugin
    // ----------------------------------------
    // Private data
    var isLS = typeof window.localStorage !== 'undefined';
    // Private functions
    function wls(n, v) {
        var c;
        if (typeof n === 'string' && typeof v === 'string') {
            localStorage[n] = v;
            return true;
        } else if (typeof n === 'object' && typeof v === 'undefined') {
            for (c in n) {
                if (n.hasOwnProperty(c)) {
                    localStorage[c] = n[c];
                }
            }
            return true;
        }
        return false;
    }
    function wc(n, v) {
        var dt, e, c;
        dt = new Date();
        dt.setTime(dt.getTime() + 31536000000);
        e = '; expires=' + dt.toGMTString();
        if (typeof n === 'string' && typeof v === 'string') {
            document.cookie = n + '=' + v + e + '; path=/';
            return true;
        } else if (typeof n === 'object' && typeof v === 'undefined') {
            for (c in n) {
                if (n.hasOwnProperty(c)) {
                    document.cookie = c + '=' + n[c] + e + '; path=/';
                }
            }
            return true;
        }
        return false;
    }
    function rls(n) {
        return localStorage[n];
    }
    function rc(n) {
        var nn, ca, i, c;
        nn = n + '=';
        ca = document.cookie.split(';');
        for (i = 0; i < ca.length; i++) {
            c = ca[i];
            while (c.charAt(0) === ' ') {
                c = c.substring(1, c.length);
            }
            if (c.indexOf(nn) === 0) {
                return c.substring(nn.length, c.length);
            }
        }
        return null;
    }
    function dls(n) {
        return delete localStorage[n];
    }
    function dc(n) {
        return wc(n, '', -1);
    }
    /**
    * Public API
    * $.Storage.set("name", "value")
    * $.Storage.set({"name1":"value1", "name2":"value2", etc})
    * $.Storage.get("name")
    * $.Storage.remove("name")
    */
    $.extend({
        Storage: {
            set: isLS ? wls : wc,
            get: isLS ? rls : rc,
            remove: isLS ? dls : dc
        }
    });
    // ----------------------------------------
    // END Storage plugin
    // ----------------------------------------
    // START jQuery Timers
    // ----------------------------------------
    jQuery.fn.extend({
        everyTime: function(interval, label, fn, times, belay) {
            return this.each(function() {
                jQuery.timer.add(this, interval, label, fn, times, belay);
            });
        },
        oneTime: function(interval, label, fn) {
            return this.each(function() {
                jQuery.timer.add(this, interval, label, fn, 1);
            });
        },
        stopTime: function(label, fn) {
            return this.each(function() {
                jQuery.timer.remove(this, label, fn);
            });
        }
    });

    jQuery.extend({
        timer: {
            guid: 1,
            global: {},
            regex: /^([0-9]+)\s*(.*s)?$/,
            powers: {
                // Yeah this is major overkill...
                'ms': 1,
                'cs': 10,
                'ds': 100,
                's': 1000,
                'das': 10000,
                'hs': 100000,
                'ks': 1000000
            },
            timeParse: function(value) {
                if (value == undefined || value == null)
                    return null;
                var result = this.regex.exec(jQuery.trim(value.toString()));
                if (result[2]) {
                    var num = parseInt(result[1], 10);
                    var mult = this.powers[result[2]] || 1;
                    return num * mult;
                } else {
                    return value;
                }
            },
            add: function(element, interval, label, fn, times, belay) {
                var counter = 0;

                if (jQuery.isFunction(label)) {
                    if (!times)
                        times = fn;
                    fn = label;
                    label = interval;
                }

                interval = jQuery.timer.timeParse(interval);

                if (typeof interval != 'number' ||
                    isNaN(interval) ||
                    interval <= 0) {
                    return;
                }
                if (times && times.constructor != Number) {
                    belay = !!times;
                    times = 0;
                }

                times = times || 0;
                belay = belay || false;

                if (!element.$timers)
                    element.$timers = {};

                if (!element.$timers[label])
                    element.$timers[label] = {};

                fn.$timerID = fn.$timerID || this.guid++;

                var handler = function() {
                    if (belay && this.inProgress)
                        return;
                    this.inProgress = true;
                    if ((++counter > times && times !== 0) ||
                        fn.call(element, counter) === false)
                        jQuery.timer.remove(element, label, fn);
                    this.inProgress = false;
                };

                handler.$timerID = fn.$timerID;

                if (!element.$timers[label][fn.$timerID])
                    element.$timers[label][fn.$timerID] = window.setInterval(handler, interval);

                if (!this.global[label])
                    this.global[label] = [];
                this.global[label].push(element);

            },
            remove: function(element, label, fn) {
                var timers = element.$timers, ret;

                if (timers) {

                    if (!label) {
                        for (label in timers)
                            this.remove(element, label, fn);
                    } else if (timers[label]) {
                        if (fn) {
                            if (fn.$timerID) {
                                window.clearInterval(timers[label][fn.$timerID]);
                                delete timers[label][fn.$timerID];
                            }
                        } else {
                            for (var fn in timers[label]) {
                                window.clearInterval(timers[label][fn]);
                                delete timers[label][fn];
                            }
                        }

                        for (ret in timers[label]) break;
                        if (!ret) {
                            ret = null;
                            delete timers[label];
                        }
                    }

                    for (ret in timers) break;
                    if (!ret)
                        element.$timers = null;
                }
            }
        }
    });

    if (jQuery.browser.msie) {
        jQuery(window).one('unload', function() {
            var global = jQuery.timer.global;
            for (var label in global) {
                var els = global[label], i = els.length;
                while (--i)
                    jQuery.timer.remove(els[i], label);
            }
        });
    }

    // -----------------------------------------------------------------------
    /*
    function decodeHTML(str) {
        if (typeof str == 'string') {
            str = str.replace(/&/g, '&');
            str = str.replace(/</g, '<').replace(/>/g, '>');
            str = str.replace(/	/g, '\t');
            str = str.replace(/
/g, '\n').replace(/ /g, ' ');
            return str;
        } else {
            return '';
        }
    }
    */
    //split string to array of strings with the same length
    function str_parts(str, length) {
        var result = [];
        var len = str.length;
        if (len < length) {
            return [str];
        }
        for (var i = 0; i < len; i += length) {
            result.push(str.substring(i, i + length));
        }
        return result;
    }
    // -----------------------------------------------------------------------
    //barbaz

    var format_split_re = /(\[\[[biu]*;[^;]*;[^\]]*\][^\]]*\])/g;
    // this capture elements
    var format_re = /\[\[([biu]*);([^;]*);([^\]]*)\]([^\]]*)\]/g;
    //var format_re = /\[\[([biu]*);([^;]*);([^\]]*)\]([^\[][^\]]*|\[[^\]]*\][^\]]*)\]/g;
    var color_hex_re = /#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})/;
    function encodeHTML(str) {
        if (typeof str == 'string') {
            str = str.replace(/&(?!#[0-9]*;)/g, '&');
            str = str.replace(/</g, '<').replace(/>/g, '>');
            str = str.replace(/\n/g, '
'); // I don't think that it find this
            str = str.replace(/ /g, ' ');
            //str = str.replace(/---/g, '—');
            //str = str.replace(/\.\.\./g, '…');
            //str = str.replace(/sqrt\(([^\)]+)\)/g, "√$1")
            //str = str.replace(/sum\(([^\)]+)\)/g, "∑$1");
            str = str.replace(/\t/g, '    ');
            //support for formating foo[[u;;]bar]baz[[b;#fff;]quuz]zzz
            var splited = str.split(format_split_re);
            if (splited.length > 1) {
                str = $.map(splited, function(text) {
                    if (text[0] == '[') {
                        return text.replace(format_re, function(s, style, color, background, text) {
                            var style_str = '';
                            if (style.indexOf('b') != -1) {
                                style_str += 'font-weight:bold;';
                            }
                            if (style.indexOf('u') != -1) {
                                style_str += 'text-decoration:underline;';
                            }
                            if (style.indexOf('i') != -1) {
                                style_str += 'font-style:italic; ';
                            }

                            if (color.match(color_hex_re)) {
                                style_str += 'color:' + color + ';';
                            }
                            if (background.match(color_hex_re)) {
                                style_str += 'background-color:' + background;
                            }
                            str = '' + text + '';
                            return str;
                        });
                    } else {
                        return '' + text + '';
                    }
                }).join('');
            }
            return str;
        } else {
            return '';
        }
    }

    // -----------------------------------------------------------------------
    // CYCLE DATA STRUCTURE
    // -----------------------------------------------------------------------
    function Cycle(init) {
        var data = init ? [init] : [];
        var pos = 0;
        $.extend(this, {
            rotate: function() {
                if (data.length == 1) {
                    return data[0];
                } else {
                    if (pos == data.length - 1) {
                        pos = 0;
                    } else {
                        ++pos;
                    }
                    return data[pos];
                }
            },
            length: function() {
                return data.length;
            },
            set: function(item) {
                for (var i = data.length; i--;) {
                    if (data[i] === item) {
                        pos = i;
                        return;
                    }
                }
                this.append(item);
            },
            front: function() {
                return data[pos];
            },
            append: function(item) {
                data.push(item);
            }
        });
    }
    // -----------------------------------------------------------------------
    // :: BCYCLE DATA STRUCTURE // Two way cycle
    // -----------------------------------------------------------------------
    function BCycle(init) {
        var data = init instanceof Array ? init : init ? [init] : [];
        var pos = 0;
        $.extend(this, {
            left: function() {
                if (pos === 0) {
                    pos = data.length - 1;
                } else {
                    --pos;
                }
                return data[pos];
            },
            right: function() {
                if (pos == data.length - 1) {
                    pos = 0;
                } else {
                    ++pos;
                }
                return data[pos];
            },
            current: function() {
                return data[pos];
            },
            data: function() {
                return data;
            },
            reset: function() {
                pos = 0;
            },
            append: function(item) {
                data.push(item);
                this.reset();
            }});
    }
    // -----------------------------------------------------------------------
    // :: STACK DATA STRUCTURE
    // -----------------------------------------------------------------------
    function Stack(init) {
        var data = init ? [init] : [];
        $.extend(this, {
            size: function() {
                return data.length;
            },
            pop: function() {
                if (data.length === 0) {
                    return null;
                } else {
                    var value = data[data.length - 1];
                    data = data.slice(0, data.length - 1);
                    return value;
                }
            },
            push: function(value) {
                data = data.concat([value]);
                return value;
            },
            top: function() {
                return data.length > 0 ? data[data.length - 1] : null;
            }});
    }
    // serialize object myself (biwascheme or prototype library do something
    // wiked with JSON serialization for Arrays)
    $.json_stringify = function(object, level) {
        var result = '';
        level = level === undefined ? 1 : level;
        var type = typeof object;
        switch (type) {
        case 'function':
            result += object;
            break;
        case 'boolean':
            result += object ? 'true' : 'false';
            break;
        case 'object':
            if (object === null) {
                result += 'null';
            } else if (object instanceof Array) {
                result += '[';
                var len = object.length;
                for (var i = 0; i < len - 1; ++i) {
                    result += $.json_stringify(object[i], level + 1);
                }
                result += $.json_stringify(object[len - 1], level + 1) + ']';
            } else {
                result += '{';
                for (var property in object) {
                    if (object.hasOwnProperty(property)) {
                        result += '"' + property + '":' +
                            $.json_stringify(object[property], level + 1);
                    }
                }
                result += '}';
            }
            break;
        case 'string':
            var str = object;
            var repl = {
                '\\\\': '\\\\',
                '"': '\\"',
                '/': '\\/',
                '\\n': '\\n',
                '\\r': '\\r',
                '\\t': '\\t'};
            for (var i in repl) {
                if (repl.hasOwnProperty(i)) {
                    str = str.replace(new RegExp(i, 'g'), repl[i]);
                }
            }
            result += '"' + str + '"';
            break;
        case 'number':
            result += String(object);
            break;
        }
        result += (level > 1 ? ',' : '');
        // quick hacks below
        if (level == 1) {
            // fix last comma
            result = result.replace(/,([\]}])/g, '$1');
        }
        // fix comma before array or object
        return result.replace(/([\[{]),/g, '$1');
    };
    // -----------------------------------------------------------------------
    // :: HISTORY CLASS
    // -----------------------------------------------------------------------
    function History(name) {
        var enabled = true;
        if (typeof name === 'string' && name !== '') {
            name += '_';
        }
        var data = $.Storage.get(name + 'commands');
        var bc = new BCycle(data ? eval('(' + data + ')') : ['']);

        $.extend(this, {
            append: function(item) {
                if (enabled && bc.current() != item) {
                    bc.append(item);
                    $.Storage.set(name + 'commands', $.json_stringify(bc.data()));
                }
            },
            data: function() {
                return bc.data();
            },
            next: function() {
                return bc.right();
            },
            last: function() {
                bc.reset();
            },
            previous: function() {
                return bc.left();
            },
            clear: function() {
                bc = new BCycle();
                $.Storage.remove(name + 'commands');
            },
            enable: function() {
                enabled = true;
            },
            disable: function() {
                enabled = false;
            }});
    }
    // -----------------------------------------------------------------------
    // :: COMMAND LINE PLUGIN
    // -----------------------------------------------------------------------
    $.fn.cmd = function(options) {
        var self = this;
        self.addClass('cmd');
        self.append('' +
                    ' ');

        var clip = $('<textarea/>').addClass('clipboard').appendTo(self);
        if (options.width) {
            self.width(options.width);
        }
        var num_chars; // calculates by draw_prompt
        var prompt_len;

        var mask = options.mask || false;
        var command = '';
        var position = 0;
        var prompt;
        var enabled = options.enabled;
        var name, history;

        var blink = (function() {
            var cursor = self.find('.cursor');
            return function(i) {
                cursor.toggleClass('inverted');
            };
        })();
        var cursor = self.find('.cursor');
        function change_num_chars() {
            var W = self.width();
            var w = cursor.innerWidth();
            num_chars = Math.floor(W / w);
        }

        function get_splited_command_line(string) {
            var first = string.substring(0, num_chars - prompt_len - 1);
            var rest = string.substring(num_chars - prompt_len - 1);
            return [first].concat(str_parts(rest, num_chars));
        }
        var redraw = (function(self) {
            var cursor = self.find('.cursor');
            var before = cursor.prev();
            var after = cursor.next();

            function draw_cursor_line(string, position) {
                if (position == string.length) {
                    before.html(encodeHTML(string));
                    cursor.html(' ');
                    after.html('');
                } else if (position === 0) {
                    before.html('');
                    //fix for tilda in IE
                    cursor.html(encodeHTML(string.slice(0, 1)));
                    //cursor.html(encodeHTML(string[0]));
                    after.html(encodeHTML(string.slice(1)));
                } else {
                    var before_str = encodeHTML(string.slice(0, position));
                    before.html(before_str);
                    //fix for tilda in IE
                    var c = string.slice(position, position + 1);
                    //cursor.html(string[position]));
                    cursor.html(c == ' ' ? ' ' : encodeHTML(c));
                    if (position == string.lenght - 1) {
                        after.html('');
                    } else {
                        after.html(encodeHTML(string.slice(position + 1)));
                    }
                }
            }
            function div(string) {
                return '
' + encodeHTML(string) + '
';
            }
            function lines_after(lines) {
                var last_ins = after;
                $.each(lines, function(i, line) {
                    last_ins = $(div(line)).insertAfter(last_ins);
                });
            }
            function lines_before(lines) {
                $.each(lines, function(i, line) {
                    before.before(div(line));
                });
            }
            var count = 0;
            return function() {
                var string = mask ? command.replace(/./g, '*') : command;
                self.find('div').remove();
                before.html('');
                // long line
                if (string.length > num_chars - prompt_len - 1) {
                    //cursor in first line
                    var array = get_splited_command_line(string);
                    var first_len = array[0].length;
                    if (position < first_len) {
                        draw_cursor_line(array[0], position);
                        lines_after(array.slice(1));
                    } else if (position == first_len) {
                        before.before(div(array[0]));
                        draw_cursor_line(array[1], 0);
                        lines_after(array.slice(2));

                    } else {
                        var num_lines = array.length;
                        var offset = 0;
                        if (position < first_len) {
                            draw_cursor_line(array[0], position);
                            lines_after(array.slice(1));
                        } else if (position == first_len) {
                            before.before(div(array[0]));
                            draw_cursor_line(array[1], 0);
                            lines_after(array.slice(2));
                        } else {
                            var last = array.slice(-1)[0];
                            var from_last = string.length - position;
                            if (from_last <= last.length) {
                                lines_before(array.slice(0, -1));
                                var pos = last.length==from_last ? 0 : last.length-from_last;
                                draw_cursor_line(last, pos);
                            } else {
                                // in the middle
                                if (num_lines == 3) {
                                    before.before('
' + encodeHTML(array[0]) +
                                                  '
');
                                    draw_cursor_line(array[1], position-first_len-1);
                                    after.after('
' + encodeHTML(array[2]) +
                                                '
');
                                } else {
                                    // more lines cursor in the middle
                                    var line_index = Math.floor((position+prompt_len) / num_chars);
                                    var current = array[line_index];
                                    var sum = (function(array) {
                                        var sum = 0;
                                        for (var i=array.length; i--;) {
                                            sum += array[i].length;
                                        }
                                        return sum;
                                    })(array.slice(0, line_index));
                                    var pos = position-sum;
                                    // cursor on first character in line
                                    if (pos == num_chars) {
                                        pos = 0;
                                        current = array[++line_index];
                                    }
                                    var before_str = encodeHTML(current.slice(0, pos));
                                    draw_cursor_line(current, pos);
                                    lines_before(array.slice(0, line_index));
                                    lines_after(array.slice(line_index+1));
                                }
                            }
                        }
                    }
                } else {
                     if (string === '') {
                         before.html('');
                         cursor.html(' ');
                         after.html('');
                     } else {
                         draw_cursor_line(string, position);
                     }
                }
            };
        })(self);

        var draw_prompt = (function() {
            var prompt_node = self.find('.prompt');
            return function() {
                if (typeof prompt == 'string') {
                    prompt_len = prompt.length;
                    prompt_node.html(encodeHTML(prompt) + ' ');
                } else {
                    prompt(function(string) {
                        prompt_len = string.length;
                        prompt_node.html(encodeHTML(string) + ' ');
                    });
                }
                //change_num_chars();
            };
        })();
        // paste content to terminal using hidden textarea
        function paste() {
            clip.focus();
            //wait until Browser insert text to textarea
            self.oneTime(1, function() {
                self.insert(clip.val());
                clip.blur();
                clip.val('');
            });
        }
        function keydown_event(e) {
            //console.log('keydown ' + e.which);
            if (options.keydown && options.keydown(e) === false) {
                return false;
            }
            if (enabled) {
                var pos, len, result;
                if (e.keyCode == 13) {
                    if (history && command) {
                        history.append(command);
                    }
                    history.last();
                    var tmp = command;
                    self.set('');
                    if (typeof prompt == 'function') {
                        draw_prompt();
                    }
                    if (options.commands) {
                        options.commands(tmp);
                    }
                } else if (e.which == 32) { //space
                    self.insert(' ');
                } else if (e.which == 8) { //backspace
                    if (command !== '' && position > 0) {
                        command = command.slice(0, position - 1) +
                            command.slice(position, command.length);
                        --position;
                        redraw();
                    }
                } else if (e.which == 9 && !(e.ctrlKey || e.altKey)) { // TAB
                    self.insert('\t');
                } else if (e.which == 46 || (e.which == 68 && e.ctrlKey)) {
                    //DELETE or CTRL+D
                    if (command !== '' && position < command.length) {
                        command = command.slice(0, position) +
                            command.slice(position + 1, command.length);
                        redraw();
                    }
                    return true;
                } else if (history && e.which == 38 ||
                           (e.which == 80 && e.ctrlKey)) {
                    //UP ARROW or CTRL+P
                    self.set(history.previous());
                } else if (history && e.which == 40 ||
                           (e.which == 78 && e.ctrlKey)) {
                    //DOWN ARROW or CTRL+N
                    self.set(history.next());
                } else if (e.which == 27) { //escape
                    self.set('');
                } else if (e.which == 37 ||
                           (e.which == 66 && e.ctrlKey)) {
                    //CTRL+LEFT ARROW or CTRL+B
                    if (e.ctrlKey && e.which != 66) {
                        len = position - 1;
                        pos = 0;
                        if (command[len] == ' ') {
                            --len;
                        }
                        for (var i = len; i > 0; --i) {
                            if (command[i] == ' ' &&
                                command[i + 1] != ' ') {
                                pos = i + 1;
                                break;
                            }
                        }
                        self.position(pos);
                    } else {
                        //LEFT ARROW or CTRL+B
                        if (position > 0) {
                            --position;
                            redraw();
                        }
                    }
                } else if (e.which == 39 ||
                           (e.which == 70 && e.ctrlKey)) {
                    //RIGHT ARROW OR CTRL+F
                    if (e.ctrlKey && e.which != 70) {
                        // jump to beginig or end of the word
                        if (command[position] == ' ') {
                            ++position;
                        }
                        var match = command.slice(position).match(/[^ ] {2,}| +[^ ]?/);
                        if (!match || match[0].match(/^ +$/)) {
                            position = command.length;
                        } else {
                            if (match[0][0] != ' ') {
                                position += match.index + 1;
                            } else {
                                position += match.index + match[0].length - 1;
                                if (match[0][match[0].length-1] != ' ') {
                                    --position;
                                }
                            }
                        }
                        redraw();
                    } else {
                        if (position < command.length) {
                            ++position;
                            redraw();
                        }
                    }
                } else if (e.which == 123) { //F12 - Allow Firebug
                    return true;
                } else if (e.which == 36) { //HOME
                    self.position(0);
                } else if (e.which == 35) {
                    //END
                    self.position(command.length);
                } else if (e.ctrlKey || e.metaKey) {
                    if (e.shiftKey) { // CTRL+SHIFT+??
                        if (e.which == 84) {
                            //CTRL+SHIFT+T open closed tab
                            return true;
                        }
                    } else if (e.altKey) { //ALT+CTRL+??
                        //return true;
                    } else {
                        //NOTE: in opera charCode is undefined
                        if (e.which == 65) {
                            //CTRL+A
                            self.position(0);
                        } else if (e.which == 69) {
                            //CTRL+E
                            self.position(command.length);
                        } else if (e.which == 88 || e.which == 67 ||
                                   e.which == 87 || e.which == 84) {
                            //CTRL+X CTRL+C CTRL+W CTRL+T
                            return true;
                        } else if (e.which == 86) {
                            //CTRL+V
                            paste();
                            return true;
                        } else if (e.which == 75) {
                            //CTRL+K
                            if (position === 0) {
                                self.set('');
                            } else if (position != command.length) {
                                self.set(command.slice(0, position));
                            }
                        } else if (e.which == 17) { //CTRL+TAB switch tab
                            return true;
                        }
                    }
                } else if (e.altKey) {
                    //if (e.which == 18) { // press ALT
                    if (e.which == 68) { //ALT+D
                        self.set(command.slice(0, position) +
                                 command.slice(position).replace(/[^ ]+ |[^ ]+$/, ''),
                                 true);
                    }
                } else {
                    return true;
                }
                return false;
            } /*else {
                if ((e.altKey && e.which == 68) ||
                    (e.ctrlKey && [65, 66, 68, 69, 80, 78, 70].has(e.which)) ||
                    // 68 == D
                    [35, 36, 37, 38, 39, 40].has(e.which)) {
                    return false;
                }

            } */
        }

        $.extend(self, {
            name: function(string) {
                if (string !== undefined) {
                    name = string;
                    history = new History(string);
                } else {
                    return name;
                }
            },
            history: function() {
                return history;
            },
            set: function(string, stay) {
                if (string !== undefined) {
                    command = string;
                    if (!stay) {
                        position = command.length;
                    }
                    redraw();
                }
            },
            insert: function(string, stay) {
                if (position == command.length) {
                    command += string;
                } else if (position === 0) {
                    command = string + command;
                } else {
                    command = command.slice(0, position) +
                        string + command.slice(position);
                }
                if (!stay) {
                    position += string.length;
                }
                redraw();
            },
            get: function() {
                return command;
            },
            commands: function(commands) {
                if (commands) {
                    options.commands = commands;
                } else {
                    return commands;
                }
            },
            destroy: function() {
                $(document.documentElement).unbind('.commandline');
                self.find('.prompt').remove();
            },
            prompt: function(user_prompt) {
                if (user_prompt === undefined) {
                    return prompt;
                } else {
                    if (typeof user_prompt == 'string' ||
                        typeof user_prompt == 'function') {
                        prompt = user_prompt;
                    } else {
                        throw 'prompt must be a function or string';
                    }
                    draw_prompt();
                }
            },
            position: function(n) {
                if (typeof n == 'number') {
                    position = n < 0 ? 0 : n > command.length ? command.length : n;
                    redraw();
                } else {
                    return position;
                }
            },
            resize: function(num) {
                if (num) {
                    num_chars = num;
                } else {
                    change_num_chars();
                }
                redraw();
            },
            enable: function() {
                if (!enabled) {
                    self.everyTime(500, 'blink', blink);
                    enabled = true;
                }
            },
            isenabled: function() {
                return enabled;
            },
            disable: function() {
                if (enabled) {
                    self.stopTime('blink', blink);
                    self.find('.cursor').removeClass('inverted');
                    enabled = false;
                }
            },
            mask: function(display) {
                if (typeof display == 'boolean') {
                    mask = display;
                    redraw();
                } else {
                    return mask;
                }
            }
        });

        // INIT
        self.name(options.name || '');
        prompt = options.prompt || '>';
        draw_prompt();
        if (options.enabled === undefined || options.enabled === true) {
            self.enable();
        }
        // Keystrokes
        $(document.documentElement).keypress(function(e) {
            var result;
            if (e.ctrlKey && e.which == 99) {
                return true;
            }
            if (options.keypress) {
                result = options.keypress(e);
            }
            if (result === undefined || result) {
                if (enabled) {
                    if ([38, 32, 13, 0, 8].has(e.which) &&
                        e.keyCode != 123 && // for F12 which == 0
                        //!(e.which == 40 && e.shiftKey ||
                        !(e.which == 38 && e.shiftKey)) {
                        return false;
                    } else if (!e.ctrlKey && !(e.altKey && e.which == 100)) {
                        self.insert(String.fromCharCode(e.which));
                        return false;
                    }
                }
            } else {
                return result;
            }
            if (e.which == 100 && e.ctrlKey) {
                return false;
            }
        }).keydown(keydown_event);
        // characters
        return self;
    };
    // -----------------------------------------------------------------------
    // JSON-RPC CALL
    // -----------------------------------------------------------------------
    var requests = [];

    $.jrpc = function(url, id, method, params, success, error) {
        var request = $.json_stringify({
           'jsonrpc': '2.0', 'method': method,
            'params': params, 'id': id});
        //terminals.front().echo(request);
        return $.ajax({
            url: url,
            data: request,
            /*success: function(response) {
            terminals.front().echo(JSON.stringify(response));
            success(response);
            },*/
            success: success,
            error: error,
            contentType: 'application/json',
            dataType: 'json',
            beforeSend: function(jqXHR, settings) {
                requests.push(jqXHR);
            },
            async: true,
            cache: false,
            //timeout: 1,
            type: 'POST'});
    };

    // -----------------------------------------------------------------------
    // :: TERMINAL PLUGIN CODE
    // -----------------------------------------------------------------------
    var version = '0.3.6';
    var copyright = 'Copyright (c) 2011 Jakub Jankiewicz <http://jcubic.pl>';
    var version_string = 'version ' + version;
    //regex is for placing version string aligned to the right
    var reg = new RegExp(" {" + version_string.length + "}$");
    var signatures = [
        ['jQuery Terminal', '(c) 2011 jcubic'],
        ['JQuery Terminal Emulator v. ' + version,
         copyright.replace(/ *<.*>/, '')],
        ['JQuery Terminal Emulator version ' + version_string,
         copyright],
        ['      _______                 ________                        __',
         '     / / _  /_ ____________ _/__  ___/______________  _____  / /',
         ' __ / / // / // / _  / _/ // / / / _  / _/     / /  \\/ / _ \\/ /',
         '/  / / // / // / ___/ // // / / / ___/ // / / / / /\\  / // / /__',
         '\\___/____ \\\\__/____/_/ \\__ / /_/____/_//_/ /_/ /_/  \\/\\__\\_\\___/',
         '         \\/          /____/                                   '.replace(reg, '') +
         version_string,
         copyright],
        ['      __ _____                     ________                              __',
         '     / // _  /__ __ _____ ___ __ _/__  ___/__ ___ ______ __ __  __ ___  / /',
         ' __ / // // // // // _  // _// // / / // _  // _//     // //  \\/ // _ \\/ /',
         '/  / // // // // // ___// / / // / / // ___// / / / / // // /\\  // // / /__',
         '\\___//____ \\\\___//____//_/ _\\_  / /_//____//_/ /_/ /_//_//_/ /_/ \\__\\_\\___/',
         '          \\/              /____/                                          '.replace(reg, '') +
         version_string,
         copyright]
    ];

    var terminals = new Cycle(); //list of terminals global in this scope
    //stor all ajax request to cancel them on CTR+D [NOT WORKING]
    var requests = [];
    $.fn.terminal = function(init_eval, options) {

        var self = this;
        var lines = [];
        var output;
        var terminal_id = (function() {
            return terminals.length();
        })();
        var num_chars; // numer of chars in line
        var settings = {
            name: null,
            prompt: '>',
            history: true,
            exit: true,
            clear: true,
            enabled: true,
            login: null,
            onInit: null,
            onExit: null,
            keypress: null,
            keydown: null
        };
        if (options) {
            if (options.width) {
                self.width(options.width);
            }
            if (options.height) {
                self.height(options.height);
            }
            $.extend(settings, options);
        }
        var pause = !settings.enabled;

        if (self.length === 0) {
            throw 'Sorry, but terminal said that "' + self.selector +
                '" is not valid selector';
        }
        if (self.data('terminal')) {
            self.ajaxSend(function(e, xhr, opt) {
                requests.push(xhr);
            });
            return self.data('terminal');
        }
        output = $('
').addClass('terminal-output').appendTo(self);
        self.addClass('terminal').append('
');

        //calculate numbers of characters base on
        function get_num_chars() {
            var test = $('x').appendTo(self);
            var result = Math.floor(self.width() / test.width());
            test.remove();
            return result;
        }

        // display Exception on terminal
        function display_exception(e, label) {
            if (typeof e == 'string') {
                self.error('[' + label + ']: ' + e)
            } else {
                //display filename and line which throw exeption
                self.error('[' + label + ']: ' + e.fileName + ': ' +
                           e.message);
                self.pause();
                $.get(e.fileName, function(file) {
                    self.resume();
                    var num = e.lineNumber - 1;
                    self.error('[' + e.lineNumber + ']: ' +
                               file.split('\n')[num]);
                });
            }
        }

        //validating if object is string or function, call that function and
        //display exeption if any
        function valid(label, object) {
            try {
                if (typeof object == 'function') {
                    object(function() {
                        // don't care
                    });
                } else if (typeof object != 'string') {
                    var msg = label + ' must be string or function';
                    throw msg;
                }
            } catch (e) {
                display_exception(e, label.toUpperCase());
                return false;
            }
            return true;
        }

        function scroll_to_bottom() {
            var scrollHeight = self.prop ? self.prop('scrollHeight') :
                self.attr('scrollHeight');
            self.scrollTop(scrollHeight);
        }
        function draw_line(string) {
             var string = typeof string == 'string' ?
                string : String(string);
            var div;
            if (string.length > num_chars) {
                // string can have line break
                var array = string.split('\n');
                div = $('

');
                var len = array.length;
                for (var i = 0; i < len; ++i) {
                    if (array[i] === '' || array[i] == '\r') {
                        div.append('

');
                    } else {
                        // if line is longer then width
                        if (array[i].length > num_chars) {
                            var parts = str_parts(array[i], num_chars);
                            $.each(parts, function(i, string) {
                                $('
').html(encodeHTML(string)).
                                    appendTo(div);
                            });
                        } else {
                            $('
').html(encodeHTML(array[i])).
                                appendTo(div);
                        }
                    }
                }
            } else {
                div = $('
').html(encodeHTML(string));
            }
            output.append(div);
            div.width('100%');
            scroll_to_bottom();
            return div;
        }
        function show_greetings() {
            if (options.greetings === undefined) {
                self.echo(self.signature);
            } else if (options.greetings) {
                self.echo(options.greetings);
            }
        }
        function isScrolledIntoView(elem) {
            var docViewTop = $(window).scrollTop();
            var docViewBottom = docViewTop + $(window).height();

            var elemTop = $(elem).offset().top;
            var elemBottom = elemTop + $(elem).height();

            return ((elemBottom >= docViewTop) && (elemTop <= docViewBottom));
        }

        // ----------------------------------------------------------
        // TERMINAL METHODS
        // ----------------------------------------------------------

        $.extend(self, {
            clear: function() {
                output.html('');
                command_line.set('');
                lines = [];
                self.attr({ scrollTop: 0});
                return self;
            },
            paused: function() {
                return pause;
            },
            pause: function() {
                if (command_line) {
                    self.disable();
                    command_line.hide();
                }
                return self;
            },
            resume: function() {
                //console.log('resume on ' + options.prompt + '\n' +
                //            get_stack(arguments.callee.caller).join(''));
                if (command_line) {
                    self.enable();
                    command_line.show();
                    scroll_to_bottom();
                }
                return self;
            },
            cols: function() {
                return num_chars;
            },
            rows: function() {
                return lines.length;
            },
            history: function() {
                return command_line.history().data();
            },
            next: function() {
                if (terminals.length() == 1) {
                    return self;
                } else {
                    var offsetTop = self.offset().top;
                    var height = self.height();
                    var scrollTop = self.scrollTop();
                    if (!isScrolledIntoView(self)) {
                        self.enable();
                        $('html,body').animate({scrollTop: offsetTop-50}, 500);
                        return self;
                    } else {
                        terminals.front().disable();
                        var next = terminals.rotate().enable();
                        var x = next.offset().top - 50; // 100 provides buffer in viewport
                        $('html,body').animate({scrollTop: x}, 500);
                        return next;
                    }
                }
            },
            focus: function(toggle) {
                //console.log('focus on ' + options.prompt + '\n' +
                //            get_stack(arguments.callee.caller).join(''));
                self.oneTime(1, function() {
                    if (terminals.length() == 1) {
                        if (toggle === false) {
                            self.disable();
                        } else {
                            self.enable();
                        }
                    } else {
                        if (toggle === false) {
                            self.next();
                        } else {
                            terminals.front().disable();
                            terminals.set(self);
                            self.enable();
                        }

                    }
                });
                return self;
            },
            enable: function() {
                //console.log('enable: ' + options.prompt + '\n' +
                //            get_stack(arguments.callee.caller).join(''));
                if (num_chars === undefined) {
                    //enabling first time
                    self.resize();
                }
                if (pause) {
                    if (command_line) {
                        command_line.enable();
                        pause = false;
                    }
                }
                return self;
            },
            disable: function() {
                if (command_line) {
                    pause = true;
                    command_line.disable();
                }
                return self;
            },
            enabled: function() {
                return pause;
            },
            signature: function() {
                var cols = self.cols();
                var i = cols < 15 ? null : cols < 35 ? 0 : cols < 55 ? 1 : cols < 64 ? 2 : cols < 75 ? 3 : 4;
                if (i !== null) {
                    return signatures[i].join('\n') + '\n';
                } else {
                    return '';
                }
            },
            /* COMMAND LINE FUNCTIONS */
            get_command: function() {
                return command_line.get();
            },
            insert: function(string) {
                command_line.insert(string);
                return self;
            },
            set_prompt: function(prompt) {
                if (valid('prompt', prompt)) {
                    command_line.prompt(prompt);
                }
                return self;
            },
            set_command: function(command) {
                command_line.set(command);
                return self;
            },
            set_mask: function(display) {
                command_line.mask(display);
                return self;
            },
            get_output: function() {
                return $.map(lines, function(i, item) {
                    return typeof item == 'function' ? item() : item;
                }).get().join('\n');
            },
            resize: function(width, height) {
                if (width && height) {
                    self.width(width);
                    self.height(height);
                }
                num_chars = get_num_chars();
                command_line.resize(num_chars);
                var o = output.detach();
                output.html('');
                $.each(lines, function(i, line) {
                    draw_line(typeof line == 'function' ? line() : line);
                });
                self.prepend(o);
                scroll_to_bottom();
                return self;
            },
            echo: function(line) {
                lines.push(line);
                return draw_line(typeof line == 'function' ? line() : line);
            },
            error: function(message) {
                self.echo(message).addClass('error');
            },
            scroll: function(amount) {
                if (self.prop) {
                    if (amount > self.prop('scrollTop') && amount > 0) {
                        self.prop('scrollTop', 0);
                    }
                    var pos = self.prop('scrollTop');
                    self.prop('scrollTop', pos + amount);
                    return self;
                } else {
                    if (amount > self.attr('scrollTop') && amount > 0) {
                        self.attr('scrollTop', 0);
                    }
                    var pos = self.attr('scrollTop');
                    self.attr('scrollTop', pos + amount);
                    return self;
                }
            },
            logout: settings.login ? function() {
                while (interpreters.size() > 1) {
                    interpreters.pop();
                }
                logout();
                return self;
            } : function() {
                throw "You don't have login function";
            },
            token: settings.login ? function() {
                var name = settings.name;
                return $.Storage.get('token' + (name ? '_' + name : ''));
            } : null,
            login_name: settings.login ? function() {
                var name = settings.name;
                return $.Storage.get('login_' + (name ? '_' + name : ''));
            } : null,
            name: function() {
                return settings.name;
            },
            push: function(_eval, options) {
                if (!options.prompt || valid('prompt', options.prompt)) {
                    if (typeof _eval == 'string') {
                        var ueval = options['eval'];
                        _eval = make_json_rpc_eval_fun(ueval, self);
                    }
                    interpreters.push($.extend({'eval': _eval}, options));
                    /*
                        name: options.name,
                        'eval': _eval,
                        prompt: options.prompt,
                        login: options.login,
                        greetings: options.grettings,
                        onStart: options.onStart,
                        onExit: options.onExit});*/
                    prepare_top_interpreter();
                }
                return self;
            },
            pop: function(string) {
                if (string !== undefined) {
                    echo_command(string);
                }
                if (interpreters.top().name === settings.name) {
                    if (settings.login) {
                        logout();
                        if (typeof settings.onExit == 'function') {
                            settings.onExit(self);
                        }
                    }
                } else {
                    var current = interpreters.pop();
                    prepare_top_interpreter();
                    if (typeof current.onExit == 'function') {
                        current.onExit(self);
                    }
                }
                return self;

            }
        });

        //function constructor for eval
        function make_json_rpc_eval_fun(url, terminal) {
            var id = 1;
            var service = function(method, params) {
                terminal.pause();
                $.jrpc(url, id++, method, params, function(json) {
                    if (!json.error) {
                        if (typeof json.result == 'string') {
                            terminal.echo(json.result);
                        } else if (json.result instanceof Array) {
                            terminal.echo(json.result.join(' '));
                        } else if (typeof json.result == 'object') {
                            var string = '';
                            for (var f in json.result) {
                                if (json.result.hasOwnProperty(f)) {
                                    string += f + ': ' + json.result[f] + '\n';
                                }
                            }
                            terminal.echo(string);
                        }
                    } else {
                        terminal.error('[RPC] ' + json.error.message);
                    }
                    terminal.resume();
                }, function(xhr, status, error) {
                    terminal.error('[AJAX] ' + status +
                                   ' - Server reponse is: \n' +
                                   xhr.responseText);
                    terminal.resume();
                });
            };
            //this is eval function
            return function(command, terminal) {
                if (command === '') {
                    return;
                }
                var method, params;
                if (!command.match(/[^ ]* /)) {
                    method = command;
                    params = [];
                } else {
                    command = command.split(/ +/);
                    method = command[0];
                    params = command.slice(1);
                }
                if (!settings.login || method == 'help') {
                    service(method, params);
                } else {
                    var token = terminal.token();
                    if (token) {
                        service(method, [token].concat(params));
                    } else {
                        //should never happen
                        terminal.error('[AUTH] Access denied (no token)');
                    }
                }
            };
        }

        var url;
        switch(typeof init_eval) {
        case 'string':
            url = init_eval;
            // create json-rpc eval function
            init_eval = make_json_rpc_eval_fun(init_eval, self);
            break;
        case 'object':
            init_eval = (function(object) {
                // function that maps commands to object methods
                // it keeps terminal context
                return function(command, terminal) {
                    if (command == '') {
                        return;
                    }
                    command = command.split(/ */);
                    var method = command[0];
                    var params = command.slice(1);
                    var val = object[method];
                    if (typeof val == 'function') {
                        val.apply(self, params);
                    } else {
                        self.echo("Command '" + method + "' Not Found");
                    }

                };
            })(init_eval);
            break;
        }

        // create json-rpc authentication function
        if (url && typeof settings.login == 'string' || url) {
            settings.login = (function(method) {
                var id = 1;
                return function(user, passwd, callback) {
                    self.pause();
                    $.jrpc(url,
                           id++,
                           method,
                           [user, passwd],
                           function(response) {

                               self.resume();
                               if (!response.error && response.result) {
                                   callback(response.result);
                               } else {
                                   callback(null);
                               }
                           }, function(xhr, status, error) {
                               self.resume();
                               self.error('[AJAX\ Response: ' +
                                          status + '\n' +
                                          xhr.responseText);
                           });
                };
                //default name is login so you can pass true
            })(typeof settings.login == 'boolean' ? 'login' : settings.login);
        }

        //display prompt and last command
        function echo_command(command) {
            var prompt = command_line.prompt();
            if (command_line.mask()) {
                command = command.replace(/./g, '*');
            }
            if (typeof prompt == 'function') {
                prompt(function(string) {
                    self.echo(string + ' ' + command);
                });
            } else {
                self.echo(prompt + ' ' +command);
            }
        }

        // wrapper over eval it implements exit and catch all exeptions
        // from user code and display them on terminal
        function commands(command) {
            try {
                var interpreter = interpreters.top();

                if (command == 'exit' && settings.exit) {
                    if (interpreters.size() == 1) {
                        if (settings.login) {
                            logout();
                        } else {
                            var msg = 'You can exit from main interpeter';
                            self.echo(msg);
                        }
                    } else {
                        self.pop('exit');
                    }
                } else {
                    echo_command(command);
                    if (command == 'clear' && settings.clear) {
                        self.clear();
                    } else {
                        interpreter['eval'](command, self);
                    }
                }

            } catch (e) {
                display_exception(e, 'USER');
                throw e;
            }
        }

        // functions change prompt of command line to login to password
        // and call user login function with callback that set token
        // if user call it with value that is true
        function login() {
            var user = null;
            command_line.prompt('login:');
            // don't stor logins in history
            if (settings.history) {
                command_line.history().disable();
            }
            command_line.commands(function(command) {
                try {
                    echo_command(command);
                    if (!user) {
                        user = command;
                        command_line.prompt('password:');
                        command_line.mask(true);
                    } else {
                        command_line.mask(false);
                        self.pause();
                        settings.login(user, command, function(user_data) {
                            if (user_data) {
                                var name = settings.name;
                                name = (name ? '_' + name : '');
                                $.Storage.set('token' + name, user_data);
                                $.Storage.set('login' + name, user);
                                //restore commands and run interpreter
                                command_line.commands(commands);
                                // move this to one function init.
                                initialize();
                            } else {
                                self.error('Wrong password try again');
                                command_line.prompt('login:');
                                user = null;
                            }
                            self.resume();
                            if (settings.history) {
                                command_line.history().enable();
                            }
                        });
                    }
                } catch (e) {
                    display_exception(e, 'LOGIN', self);
                    throw e;
                }
            });
        }

        //logout function remove Storage, disable history and run login function
        //this function is call only when options.login function is defined
        //check for this is in self.pop method
        function logout() {
            var name = settings.name;
            name = (name ? '_' + name : '');
            $.Storage.remove('token' + name, null);
            $.Storage.remove('login' + name, null);
            if (settings.history) {
                command_line.history().disable();
            }
            login();
        }

        //function enable history, set prompt, run eval function
        function prepare_top_interpreter() {
            var interpreter = interpreters.top();
            var name = '';
            if (interpreter.name !== undefined &&
                interpreter.name !== '') {
                name += interpreter.name + '_';
            }
            name += terminal_id;
            command_line.name(name);
            command_line.prompt(interpreter.prompt);
            if (settings.history) {
                command_line.history().enable();
            }
            command_line.set('');
            if (typeof interpreter.onStart == 'function') {
                interpreter.onStart(self);
            }
        }

        function initialize() {
            prepare_top_interpreter();
            show_greetings();
            if (typeof settings.onInit == 'function') {
                settings.onInit(self);
            }
        }

        function key_press(e) {
            if (settings.keypress && settings.keypress(e, self) === false) {
                return false;
            }
            //console.log(e.charCode + '|' + e.which);
            if (!self.paused()) {
                // CTRL+D
                if (e.which == 100 && e.ctrlKey) {
                    if (settings.exit && command_line.get() === '') {
                        if (interpreters.size() > 1 || settings.login !== undefined) {
                            self.pop('');
                        } else {
                            self.resume();
                            self.echo('');
                        }
                    }
                    return false;
                } else if (e.which == 118 && e.ctrlKey) { // CTRL+V
                    self.oneTime(1, function() {
                        scroll_to_bottom();
                    });
                    return true;
                } else if (e.keyCode == 9 && e.ctrlKey) { // TAB
                    self.focus(false);
                } else if (e.keyCode == 34) { // PAGE DOWN
                    self.scroll(self.height());
                } else if (e.keyCode == 33) { // PAGE UP
                    self.scroll(-self.height());
                } else {
                    self.attr({scrollTop: self.attr('scrollHeight')});
                }
            } else {
                //this is not working - Keypress is not call when there is ajax requests - ???
                if (e.which == 100 && e.ctrlKey) {
                    for (var i=requests.length; i--;) {
                        var r = requests[i];
                        if (4 != r.readyState) {
                            try {
                                r.abort();
                            } catch(e) {
                                self.error('error in aborting ajax');
                            }
                        }
                    }
                    self.resume();
                    return false;
                }
            }
        }
        // INIT CODE
        if (valid('prompt', settings.prompt)) {
            var interpreters = new Stack({'name': settings.name,
                                          'eval': init_eval,
                                          'prompt': settings.prompt,
                                          'greetings': settings.greetings});

            var command_line = self.find('.terminal-output').next().cmd({
                prompt: settings.prompt,
                history: settings.history,
                width: '100%',
                keydown: settings.keydown ? function(e) {
                    return settings.keydown(e, self);
                } : null,
                keypress: key_press,
                commands: commands
            });
            self.livequery(function() {
                self.resize();
            });
            //self.resize();
            //num_chars = get_num_chars();
            terminals.append(self);
            //console.log(settings);
            if (settings.enabled === true) {
                self.focus();
            } else {
                //console.log('disable ' + settings.prompt);
                self.disable();
            }
            $(window).resize(self.resize);
            self.click(function() {
                self.focus();
            });
            if (self.token && !self.token() && self.login_name &&
                !self.login_name()) {
                login();
            } else {
                initialize();
            }
            if (typeof $.fn.init.prototype.mousewheel === 'function') {
                self.mousewheel(function(event, delta) {
                    //self.echo(dir(event));
                    if (delta > 0) {
                        self.scroll(-40);
                    } else {
                        self.scroll(40);
                    }
                    return false;
                }, true);
            }
        }
        self.data('terminal', self);
        return self;

    }; //terminal plugin

})(jQuery);


text:
Work Already
============

Work Already is a set of tools for building web tests for mixed HTTP/S and
WebSocket web applications that are built on Socket.IO, and where sessions are
shared between Socket.IO and Express.js or some other similar http.Server-based
framework.

Session-Aware Web Tests for Socket.IO Applications
--------------------------------------------------

So you've built a single page application with Express.js and Socket.IO,
wherein user sessions are created and managed by Express.js, and then shared
with Socket.IO. A client first hits a page served by Express.js, which
generates a session, and then passes on identifiers for that session when
connecting to one or more sockets as specified in the page Javascript.

Those identifiers can be cookies (as is often the case) or query parameters
on the namespace path for the Socket.IO connect call (as is preferred by
the Socket.IO developers).

With your application up and running, you'd like to run automated web tests
against your server, hitting both web pages and Socket.IO connections. This
is where you'll find that your options are actually somewhat limited - there
are not that many tools out there that can do this. Hence the existence of
this small package, Work Already.

Features worth noting in Work Already:

  * Set the order of HTTP/S requests and examine the responses.
  * Make Socket.IO connections that pass the right session information.
  * Emit on sockets and examine or expect server responses.
  * Run as a standalone test or integrate with Vows test suites.

IMPORTANT NOTE: This package works with 0.9.x versions of Socket.IO. It won't
do much for earlier or later version in its present form, as some hacking of
socket.io-client is required to make it play ball with sessions in a Node.js
environment.

Sharing Sessions Between Express.js and Socket.IO?
--------------------------------------------------

Very quickly, here is an example of a generic way to share sessions between
Express.js and Socket.IO by using cookies to pass around the session ID:

    var express = require("express");
    var io = require("socket.io");
    var SessionMemoryStore = require("connect/lib/middleware/session/memory");
    // Set up a minimal Express application, but ensure that the session store,
    // cookie parser, and session key are exposed and accessible.
    var app = express();
    var store = new SessionMemoryStore();
    var sessionKey = "sid";
    var cookieSecret = "cookieSecret";
    var cookieParser = express.cookieParser(cookieSecret);
    app.use(cookieParser);
    app.use(express.session({
      key: sessionKey,
      secret: cookieSecret,
      store: store
    }));
    var server = http.createServer(app).listen(10080);
    // Now set up Socket.IO.
    var socketFactory = io.listen(server);
    // And use the authorization hook to attach the session to the socket
    // handshake by reading the cookie and loading the session when a
    // socket connects. Using the authorization hook means that we can
    // deny access to socket connections that arrive without a session - i.e.
    // where the user didn't load a site page through Express first.
    socketFactory.set("authorization", function (data, callback) {
      if (data && data.headers && data.headers.cookie) {
        cookieParser(data, {}, function (error) {
          if (error) {
            callback("COOKIE_PARSE_ERROR", false);
            return;
          }
          var sessionId = data.signedCookies[sessionKey];
          store.get(sessionId, function (error, session) {
            // Add the sessionId. This will show up in
            // socket.handshake.sessionId.
            //
            // It's useful to set the ID and session separately because of
            // those fun times when you have an ID but no session - it makes
            // debugging that much easier.
            data.sessionId = sessionId;
            if (error) {
              callback("ERROR", false);
            } else if (!session) {
              callback("NO_SESSION", false);
            } else {
              // Add the session. This will show up in
              // socket.handshake.session.
              data.session = session;
              callback(null, true);
            }
          });
        });
      } else {
        callback("NO_COOKIE", false);
      }
    });

This is not, however, the recommended way of doing things. At present the
Socket.IO folk are leaning towards requiring authentication or identification
tokens (such as the session ID in some encrypted form) to be appended to the
namespace for the connection.

On the client:

    io.connect("/namespace?token=encryptedString");

On the server:

    socketFactory.set("authorization", function (data, callback) {
      var token = data.query.token;
      // Now figure out the session based on what was placed inside the token
      // and attach it to the data object.
      // ...
    });

See these pages for more on this topic:

  * [Socket.IO: Authorizing](https://github.com/LearnBoost/socket.io/wiki/Authorizing)
  * [Issue #344: User client on the server with a cookie](https://github.com/LearnBoost/socket.io-client/issues/344)
  * [With socket.io, how to handle authentication with a non-browser client?](http://stackoverflow.com/questions/13381540/with-socket-io-how-to-handle-authentication-with-a-non-browser-client)

The socket.io-client Package Doesn't Allow Cookies To Be Set
------------------------------------------------------------

The challenge for testing in a Node.js rather than browser environment - only
for the situation in which you are using cookies rather than the query string
to pass session identifiers - is that the socket.io-client package doesn't
permit the setting of cookie data in its requests.

The Work Already package works around this issue in a very crude way, but there
is little other option but to hack or rewrite the socket.io-client package code
in order to achieve this goal.

Example of Use
--------------

See /examples for examples of use, for both simple load tests, and Vows web tests like this one:

    var assert = require("assert");
    var vows = require("vows");
    var workAlready = require("work-already");
    var suite = vows.describe("Testing an Express / Socket.IO server.");
    var client = new workAlready.Client({
      server: {
        host: "localhost",
        port: 10080,
        protocol: "http"
      },
      sockets: {
        // If namespace is not specified in an action, then this is the namespace
        // used.
        defaultNamespace: ""
      }
    });
    // Load the main application page, which also obtains the necessary cookies
    // to pass along with the Socket.IO connection that follows.
    suite.addBatch({
      "Load main page via GET request": {
        topic: function () {
          client.action("/index.html", this.callback);
        },
        "page fetched": function (error, page) {
          // The last retrieved page is stored at client.page for perusal, as well
          // as being passed to this function.
          assert.isNull(error);
          assert.isObject(page);
          assert.isObject(client.page);
          assert.strictEqual(200, page.statusCode);
          assert.include(page.body, "some distinctive string");
        }
      }
    });
    // Establish a Socket.IO connection with the default namespace, passing over
    // the right cookies obtained in the prior request.
    suite.addBatch({
      "Connect via Socket.IO": {
        topic: function () {
          client.action({
            type: "connect",
            timeout: 500,
            // Optionally, set Socket.IO connection parameters.
            socketConfig: {
              "reconnect": true
            }
          }, this.callback);
        },
        "socket connected": function (error) {
          assert.isUndefined(error);
          assert.isObject(client.page.sockets);
          assert.isObject(client.page.sockets[client.config.sockets.defaultNamespace]);
        }
      }
    });
    // Perhaps the server sends an immediate response message via the socket
    // connection. If so, the next step is to wait on it.
    suite.addBatch({
      "Await emitted server response to connection": {
        topic: function () {
          client.action({
            type: "awaitEmit",
            eventType: "responseOnConnect",
            timeout: 500
          }, this.callback);
        },
        "event emitted": function (error, socketEvent) {
          assert.isNull(error);
          // The socketEvent is stashed in the client as well as being passed
          // to this function.
          assert.isObject(client.socketEvent);
          assert.strictEqual(client.socketEvent.namespace, client.config.sockets.defaultNamespace);
          assert.strictEqual(client.socketEvent.eventType, "responseOnConnect");
        }
      }
    });
    exports.suite = suite;

Client Configuration
--------------------

The client configuration options object passed to the constructor has the
following parameters:

    {
      // Optional ID, which defaults to something random. Useful when running
      // load tests, as it is prepended to log messages.
      id: "client-3423",
      // Optional log parameters.
      log: {
        level: "debug"
      },
      // Required parameters that tell the client which server to connect to.
      server: {
        host: "localhost",
        port: 10080,
        protocol: "http"
      },
      // Optional parameters to provide defaults for socket actions.
      sockets: {
        // If namespace is not specified in an action, then this is the namespace
        // used.
        defaultNamespace: ""
        // If timeout is not specified in a socket action, then this value is
        // used. The timeout is in milliseconds.
        defaultTimeout: 500
        // defaultTimeout can be a function, e.g.
        // defaultTimeout: function () { return 500; }
      }
    }

List of Actions
---------------

The following actions are available.

1) http

    // A general HTTP request action, defaulting to GET. By default the
    // response is written to client.page.
    client.action({
      type: "http",
      path: "/index.html",
      method: "GET",
      // An AJAX request requires client.page to exist, and the response is
      // stored to client.ajax.
      ajax: false,
      // Applied to the query string or POST body, depending on method.
      params: {
        name: "value"
      },
      // If true, then don't record the response.
      discardResponse: false
    }, function (error, page) {});

2) ajax

    // An alias to the http action for AJAX requests. An AJAX request requires
    // client.page to exist, i.e. that a page request precedes it. The
    // response to the AJAX request is stored to client.ajax.
    client.action({
      type: "ajax",
      path: "/index.html",
      method: "GET",
      // Applied to the query string or POST body, depending on method.
      params: {
        name: "value"
      }
    }, function (error, ajax) {});

3) get

    // An alias to a GET http action. The response is stored to client.page.
    client.action({
      type: "http",
      path: "/index.html",
      // Applied to the query string.
      params: {
        name: "value"
      }
    }, function (error, page) {});

4) post

    // An alias to a POST http action. Redirect to GET is followed and the
    // response is stored to client.page.
    client.action({
      type: "http",
      path: "/index.html",
      // Applied to the POST body.
      params: {
        name: "value"
      }
    }, function (error, page) {});

5) getStatic

    // Load all the static content linked in the the most recently loaded
    // page, currently stored to client.page. Useful for load testing.
    client.action({
      type: "loadStatic",
      // If true, cache loaded files.
      cache: true,
      // Only load URLs with these file extensions.
      extensions: [".js", ".css", ".jpg", ".png", ".gif"]
    }, function (error) {});

6) unload

    // Clear stored client.page, client.ajax, and client.socketEvent values.
    // Disconnect connected sockets.
    //
    // This action is called implicitly before a new page is loaded and
    // stored to client.page.
    client.action({
      type: "unload"
    }, function (error) {});

7) connect

    // Connect a Socket.IO instance. A page request must precede this, and
    // client.page must exist.
    client.action({
      type: "connect",
      // An optional connection namespace.
      namespace: "/namespace",
      // Optional timeout in milliseconds. This can be a function.
      timeout: 500,
      // Optional client socket configuration.
      socketConfig: {
        "reconnect": true
      }
    }, function (error) {});

8) emit

    // Emit on a connected client Socket.IO namespace.
    client.action({
      type: "emit",
      // An optional connection namespace.
      namespace: "/namespace",
      // Arguments for the emit() function call.
      args: ["eventType", data1, data2, ... ]
    }, function (error) {});

9) awaitEmit

    // Wait for an event from the server to be emitted by a connected
    // client Socket.IO namespace. Data for the emitted event is stored to
    // client.socketEvent.
    client.action({
      type: "awaitEmit",
      // An optional connection namespace.
      namespace: "/namespace",
      // The event type.
      eventType: "someEvent",
      // Optional timeout in milliseconds. This can be a function.
      timeout: 2000
    }, function (error, socketEvent) {});

10) confirmNoMatchingEmit

    // Wait to ensure that no event of the specified type is fired for
    // the duration of the timeout. Only take notice of events that are
    // matched by the provided match function.
    client.action({
      type: "confirmNoEmit",
      // An optional connection namespace.
      namespace: "/namespace"
      // The event type.
      eventType: "someEvent",
      // Optional timeout in milliseconds. This can be a function.
      timeout: 500
      // The match function is passed the same arguments as a listener. If it
      // returns true then the event is noticed, otherwise it is skipped.
      match: function (eventType, eventData ... ) { return true; }
    }, function (error, socketEvent) {});

11) confirmNoEmit

    // Wait to ensure that no event of the specified type is fired for
    // the duration of the timeout.
    client.action({
      type: "confirmNoEmit",
      // An optional connection namespace.
      namespace: "/namespace"
      // The event type.
      eventType: "someEvent",
      // Optional timeout in milliseconds. This can be a function.
      timeout: 500
    }, function (error, socketEvent) {});

12) connectAndAwaitEmit

    // If the server emits immediately on connection, this is the way to catch
    // that event. It is stored to client.socketEvent.
    client.action({
      type: "connectAndAwaitEmit",
      // An optional connection namespace.
      namespace: "/namespace"
      // The event type.
      eventType: "someEvent",
      // Optional timeout in milliseconds. This can be a function.
      connectTimeout: 500,
      // Optional timeout in milliseconds. This can be a function.
      awaitEmitTimeout: 500,
      // Optional client socket configuration.
      socketConfig: {
        "reconnect": true
      }
    }, function (error, socketEvent) {});

13) connectAndConfirmNoMatchingEmit

    // Connect and check to ensure that no event of a specific type is emitted
    // within the timeout period. The match function can be used to further
    // winnow down which events count.
    client.action({
      type: "connectAndConfirmNoMatchingEmit",
      // An optional connection namespace.
      namespace: "/namespace"
      // The event type.
      eventType: "someEvent",
      // Optional timeout in milliseconds. This can be a function.
      connectTimeout: 500,
      // Optional timeout in milliseconds. This can be a function.
      confirmNoEmitTimeout: 500,
      // The match function is passed the same arguments as a listener. If it
      // returns true then the event is noticed, otherwise it is skipped.
      match: function (eventType, eventData ... ) { return true; }
      // Optional client socket configuration.
      socketConfig: {
        "reconnect": true
      }
    }, function (error, socketEvent) {});

14) connectAndConfirmNoEmit

    // Connect and check to ensure that no event of a specific type is emitted
    // within the timeout period.
    client.action({
      type: "connectAndConfirmNoEmit",
      // An optional connection namespace.
      namespace: "/namespace"
      // The event type.
      eventType: "someEvent",
      // Optional timeout in milliseconds. This can be a function.
      connectTimeout: 500,
      // Optional timeout in milliseconds. This can be a function.
      confirmNoEmitTimeout: 500,
      // Optional client socket configuration.
      socketConfig: {
        "reconnect": true
      }
    }, function (error, socketEvent) {});

redpajama_set_name: RedPajamaGithub


text:
<form ng-submit='add()'>
 <input type="text" name="url" ng-model="url" id="url" value="http://" onfocus="">
<button type="submit">SUBMIT</button>
</form>

<div>{{html}}</div>


text:
*{margin: 0; padding: 0;}
ul,li{list-style-type: none;}
.center{text-align: center;}
.fl{float: left;}
.fr{float: right;}
.clrl{clear: left;}
.clrr{clear: right;}
.clear{clear: both;}

.arrow-right{
    display: inline-block;
    transform: rotate(-45deg) skewX(10deg);
    border-right: 0.005rem solid #cccccc;
    border-bottom:0.005rem solid #ccc;
}


text:
package io.crate.operation.scalar;

import com.google.common.collect.ImmutableList;
import io.crate.analyze.symbol.Function;
import io.crate.analyze.symbol.Symbol;
import io.crate.metadata.FunctionIdent;
import io.crate.metadata.FunctionInfo;
import io.crate.metadata.Scalar;
import io.crate.operation.Input;
import io.crate.types.DataType;
import io.crate.types.DataTypes;
import io.crate.types.SetType;

import java.util.Set;

public class CollectionAverageFunction extends Scalar<Double, Set<Number>> {

    public static final String NAME = "collection_avg";
    private final FunctionInfo info;

    public static void register(ScalarFunctionModule mod) {
        for (DataType t : DataTypes.NUMERIC_PRIMITIVE_TYPES) {
            mod.register(
                    new CollectionAverageFunction(
                            new FunctionInfo(new FunctionIdent(
                                    NAME, ImmutableList.<DataType>of(new SetType(t))), DataTypes.DOUBLE))
            );
        }
    }

    public CollectionAverageFunction(FunctionInfo info) {
        this.info = info;
    }

    @Override
    public Double evaluate(Input<Set<Number>>... args) {
        // NOTE: always returning double ignoring the input type, maybe better implement type safe
        if (args[0].value() == null) {
            return null;
        }
        double sum = 0;
        long count = 0;
        for (Number value : args[0].value()) {
            sum += value.doubleValue();
            count++;
        }
        if (count > 0) {
            return sum / count;
        } else {
            return null;
        }
    }

    @Override
    public FunctionInfo info() {
        return info;
    }

    @Override
    public Symbol normalizeSymbol(Function function) {
        return function;
    }
}


text:
namespace BEmu
{
	const char* ServiceRefData::name() const
	{
		return "//blp/refdata";
	}

	Request ServiceRefData::createRequest(const char* operation) const
	{
		boost::shared_ptr<RequestPtr> reqp(this->createRequestPtr(operation));
		Request result(reqp);
		return result;
	}

	boost::shared_ptr<RequestPtr> ServiceRefData::createRequestPtr(const char* operation) const
	{
		if(strncmp(operation, "HistoricalDataRequest", 21) == 0)
		{
			boost::shared_ptr<RequestPtr> result(new HistoricalDataRequest::HistoricRequest());
			return result;
		}
		else if(strncmp(operation, "ReferenceDataRequest", 21) == 0)
		{
			boost::shared_ptr<RequestPtr> result(new ReferenceDataRequest::ReferenceRequest());
			return result;
		}
		else if(strncmp(operation, "IntradayTickRequest", 20) == 0)
		{
			boost::shared_ptr<RequestPtr> result(new IntradayTickRequest::IntradayTickRequest(*this));
			return result;
		}
		else if(strncmp(operation, "IntradayBarRequest", 19) == 0)
		{
			boost::shared_ptr<RequestPtr> result(new IntradayBarRequest::IntradayBarRequest(*this));
			return result;
		}
		else
		{
			throw serviceRefDataEx;
		}
	}
}


text:
package com.iluwatar;

/**
 *
 * Decorator pattern is more flexible alternative to subclassing. The decorator
 * class implements the same interface as the target and uses composition to
 * "decorate" calls to the target.
 *
 * Using decorator pattern it is possible to change class behavior during
 * runtime, as the example shows.
 *
 */
public class App {

	public static void main(String[] args) {

		// simple troll
		System.out.println("A simple looking troll approaches.");
		Hostile troll = new Troll();
		troll.attack();
		troll.fleeBattle();

		// change the behavior of the simple troll by adding a decorator
		System.out.println("\nA smart looking troll surprises you.");
		Hostile smart = new SmartTroll(troll);
		smart.attack();
		smart.fleeBattle();
	}
}