/**@license * __ _____ ________ __ * / // _ /__ __ _____ ___ __ _/__ ___/__ ___ ______ __ __ __ ___ / / * __ / // // // // // _ // _// // / / // _ // _// // // \/ // _ \/ / * / / // // // // // ___// / / // / / // ___// / / / / // // /\ // // / /__ * \___//____ \\___//____//_/ _\_ / /_//____//_/ /_/ /_//_//_/ /_/ \__\_\___/ * \/ /____/ version 0.8.8 * http://terminal.jcubic.pl * * Licensed under GNU LGPL Version 3 license * Copyright (c) 2011-2013 Jakub Jankiewicz * * Includes: * * Storage plugin Distributed under the MIT License * Copyright (c) 2010 Dave Schindler * * jQuery Timers licenced with the WTFPL * * * Cross-Browser Split 1.1.1 * Copyright 2007-2012 Steven Levithan * Available under the MIT License * * sprintf.js * Copyright (c) 2007-2013 Alexandru Marasteanu * licensed under 3 clause BSD license * * Date: Thu, 10 Jul 2014 17:20:49 +0000 * */ (function(ctx) { var sprintf = function() { if (!sprintf.cache.hasOwnProperty(arguments[0])) { sprintf.cache[arguments[0]] = sprintf.parse(arguments[0]); } return sprintf.format.call(null, sprintf.cache[arguments[0]], arguments); }; sprintf.format = function(parse_tree, argv) { var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length; for (i = 0; i < tree_length; i++) { node_type = get_type(parse_tree[i]); if (node_type === 'string') { output.push(parse_tree[i]); } else if (node_type === 'array') { match = parse_tree[i]; // convenience purposes only if (match[2]) { // keyword argument arg = argv[cursor]; for (k = 0; k < match[2].length; k++) { if (!arg.hasOwnProperty(match[2][k])) { throw(sprintf('[sprintf] property "%s" does not exist', match[2][k])); } arg = arg[match[2][k]]; } } else if (match[1]) { // positional argument (explicit) arg = argv[match[1]]; } else { // positional argument (implicit) arg = argv[cursor++]; } if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) { throw(sprintf('[sprintf] expecting number but found %s', get_type(arg))); } switch (match[8]) { case 'b': arg = arg.toString(2); break; case 'c': arg = String.fromCharCode(arg); break; case 'd': arg = parseInt(arg, 10); break; case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break; case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break; case 'o': arg = arg.toString(8); break; case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break; case 'u': arg = arg >>> 0; break; case 'x': arg = arg.toString(16); break; case 'X': arg = arg.toString(16).toUpperCase(); break; } arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg); pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' '; pad_length = match[6] - String(arg).length; pad = match[6] ? str_repeat(pad_character, pad_length) : ''; output.push(match[5] ? arg + pad : pad + arg); } } return output.join(''); }; sprintf.cache = {}; sprintf.parse = function(fmt) { var _fmt = fmt, match = [], parse_tree = [], arg_names = 0; while (_fmt) { if ((match = /^[^\x25]+/.exec(_fmt)) !== null) { parse_tree.push(match[0]); } else if ((match = /^\x25{2}/.exec(_fmt)) !== null) { parse_tree.push('%'); } else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) { if (match[2]) { arg_names |= 1; var field_list = [], replacement_field = match[2], field_match = []; if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) { field_list.push(field_match[1]); while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') { if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) { field_list.push(field_match[1]); } else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) { field_list.push(field_match[1]); } else { throw('[sprintf] huh?'); } } } else { throw('[sprintf] huh?'); } match[2] = field_list; } else { arg_names |= 2; } if (arg_names === 3) { throw('[sprintf] mixing positional and named placeholders is not (yet) supported'); } parse_tree.push(match); } else { throw('[sprintf] huh?'); } _fmt = _fmt.substring(match[0].length); } return parse_tree; }; var vsprintf = function(fmt, argv, _argv) { _argv = argv.slice(0); _argv.splice(0, 0, fmt); return sprintf.apply(null, _argv); }; /** * helpers */ function get_type(variable) { return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase(); } function str_repeat(input, multiplier) { for (var output = []; multiplier > 0; output[--multiplier] = input) {/* do nothing */} return output.join(''); } /** * export to either browser or node.js */ ctx.sprintf = sprintf; ctx.vsprintf = vsprintf; })(typeof exports != "undefined" ? exports : window); (function($, undefined) { "use strict"; // ----------------------------------------------------------------------- // :: map object to object // ----------------------------------------------------------------------- $.omap = function(o, fn) { var result = {}; $.each(o, function(k, v) { result[k] = fn.call(o, k, v); }); return result; }; // ----------------------------------------------------------------------- // :: 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 } }); // ----------------------------------------------------------------------- // :: 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 && handler.inProgress) { return; } handler.inProgress = true; if ((++counter > times && times !== 0) || fn.call(element, counter) === false) { jQuery.timer.remove(element, label, fn); } handler.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 (var lab in timers) { if (timers.hasOwnProperty(lab)) { this.remove(element, lab, 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]) { if (timers[label].hasOwnProperty(_fn)) { window.clearInterval(timers[label][_fn]); delete timers[label][_fn]; } } } for (ret in timers[label]) { if (timers[label].hasOwnProperty(ret)) { break; } } if (!ret) { ret = null; delete timers[label]; } } for (ret in timers) { if (timers.hasOwnProperty(ret)) { break; } } if (!ret) { element.$timers = null; } } } } }); if (/(msie) ([\w.]+)/.exec(navigator.userAgent.toLowerCase())) { jQuery(window).one('unload', function() { var global = jQuery.timer.global; for (var label in global) { if (global.hasOwnProperty(label)) { var els = global[label], i = els.length; while (--i) { jQuery.timer.remove(els[i], label); } } } }); } // ----------------------------------------------------------------------- // :: CROSS BROWSER SPLIT // ----------------------------------------------------------------------- (function(undef) { // prevent double include if (!String.prototype.split.toString().match(/\[native/)) { return; } var nativeSplit = String.prototype.split, compliantExecNpcg = /()??/.exec("")[1] === undef, // NPCG: nonparticipating capturing group self; self = function (str, separator, limit) { // If `separator` is not a regex, use `nativeSplit` if (Object.prototype.toString.call(separator) !== "[object RegExp]") { return nativeSplit.call(str, separator, limit); } var output = [], flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.extended ? "x" : "") + // Proposed for ES6 (separator.sticky ? "y" : ""), // Firefox 3+ lastLastIndex = 0, // Make `global` and avoid `lastIndex` issues by working with a copy separator2, match, lastIndex, lastLength; separator = new RegExp(separator.source, flags + "g"); str += ""; // Type-convert if (!compliantExecNpcg) { // Doesn't need flags gy, but they don't hurt separator2 = new RegExp("^" + separator.source + "$(?!\\s)", flags); } /* Values for `limit`, per the spec: * If undefined: 4294967295 // Math.pow(2, 32) - 1 * If 0, Infinity, or NaN: 0 * If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296; * If negative number: 4294967296 - Math.floor(Math.abs(limit)) * If other: Type-convert, then use the above rules */ // ? Math.pow(2, 32) - 1 : ToUint32(limit) limit = limit === undef ? -1 >>> 0 : limit >>> 0; while (match = separator.exec(str)) { // `separator.lastIndex` is not reliable cross-browser lastIndex = match.index + match[0].length; if (lastIndex > lastLastIndex) { output.push(str.slice(lastLastIndex, match.index)); // Fix browsers whose `exec` methods don't consistently return `undefined` for // nonparticipating capturing groups if (!compliantExecNpcg && match.length > 1) { match[0].replace(separator2, function () { for (var i = 1; i < arguments.length - 2; i++) { if (arguments[i] === undef) { match[i] = undef; } } }); } if (match.length > 1 && match.index < str.length) { Array.prototype.push.apply(output, match.slice(1)); } lastLength = match[0].length; lastLastIndex = lastIndex; if (output.length >= limit) { break; } } if (separator.lastIndex === match.index) { separator.lastIndex++; // Avoid an infinite loop } } if (lastLastIndex === str.length) { if (lastLength || !separator.test("")) { output.push(""); } } else { output.push(str.slice(lastLastIndex)); } return output.length > limit ? output.slice(0, limit) : output; }; // For convenience String.prototype.split = function (separator, limit) { return self(this, separator, limit); }; return self; })(); // ----------------------------------------------------------------------- // :: 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; } // ----------------------------------------------------------------------- // :: CYCLE DATA STRUCTURE // ----------------------------------------------------------------------- function Cycle(init) { var data = init ? [init] : []; var pos = 0; $.extend(this, { get: function() { return data; }, 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); } }); } // ----------------------------------------------------------------------- // :: STACK DATA STRUCTURE // ----------------------------------------------------------------------- function Stack(init) { var data = init ? [init] : []; $.extend(this, { map: function(fn) { return $.map(data, fn); }, 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 // :: wicked with JSON serialization for Arrays) // ----------------------------------------------------------------------- $.json_stringify = function(object, level) { var result = '', i; 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 (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 (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, size) { var enabled = true; var storage_key = ''; if (typeof name === 'string' && name !== '') { storage_key = name + '_'; } storage_key += 'commands'; var data = $.Storage.get(storage_key); data = data ? $.parseJSON(data) : []; var pos = data.length-1; $.extend(this, { append: function(item) { if (enabled) { if (data[data.length-1] !== item) { data.push(item); if (size && data.length > size) { data = data.slice(-size); } pos = data.length-1; $.Storage.set(storage_key, $.json_stringify(data)); } } }, data: function() { return data; }, reset: function() { pos = data.length-1; }, last: function() { return data[length-1]; }, end: function() { return pos === data.length-1; }, position: function() { return pos; }, current: function() { return data[pos]; }, next: function() { if (pos < data.length-1) { ++pos; } if (pos !== -1) { return data[pos]; } }, previous: function() { var old = pos; if (pos > 0) { --pos; } if (old !== -1) { return data[pos]; } }, clear: function() { data = []; this.purge(); }, enabled: function() { return enabled; }, enable: function() { enabled = true; }, purge: function() { $.Storage.remove(storage_key); }, disable: function() { enabled = false; } }); } // ----------------------------------------------------------------------- // :: COMMAND LINE PLUGIN // ----------------------------------------------------------------------- $.fn.cmd = function(options) { var self = this; var maybe_data = self.data('cmd'); if (maybe_data) { return maybe_data; } self.addClass('cmd'); self.append('' + ' '); var clip = $('