Created
October 29, 2012 16:55
-
-
Save okofish/3974867 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (function (a) { | |
| a.browserTest = function (e, g) { | |
| var f = "unknown", | |
| d = "X", | |
| b = function (k, j) { | |
| for (var c = 0; c < j.length; c = c + 1) { | |
| k = k.replace(j[c][0], j[c][1]) | |
| } | |
| return k | |
| }, | |
| h = function (l, k, j, n) { | |
| var m = { | |
| name: b((k.exec(l) || [f, f])[1], j) | |
| }; | |
| m[m.name] = true; | |
| m.version = (n.exec(l) || [d, d, d, d])[3]; | |
| if (m.name.match(/safari/) && m.version > 400) { | |
| m.version = "2.0" | |
| } | |
| if (m.name === "presto") { | |
| m.version = (a.browser.version > 9.27) ? "futhark" : "linear_b" | |
| } | |
| m.versionNumber = parseFloat(m.version, 10) || 0; | |
| m.versionX = (m.version !== d) ? (m.version + "").substr(0, 1) : d; | |
| m.className = m.name + m.versionX; | |
| return m | |
| }; | |
| e = (e.match(/Opera|Navigator|Minefield|KHTML|Chrome/) ? b(e, [ | |
| [/(Firefox|MSIE|KHTML,\slike\sGecko|Konqueror)/, ""], | |
| ["Chrome Safari", "Chrome"], | |
| ["KHTML", "Konqueror"], | |
| ["Minefield", "Firefox"], | |
| ["Navigator", "Netscape"] | |
| ]) : e).toLowerCase(); | |
| a.browser = a.extend((!g) ? a.browser : {}, h(e, /(camino|chrome|firefox|netscape|konqueror|lynx|msie|opera|safari)/, [], /(camino|chrome|firefox|netscape|netscape6|opera|version|konqueror|lynx|msie|safari)(\/|\s)([a-z0-9\.\+]*?)(\;|dev|rel|\s|$)/)); | |
| a.layout = h(e, /(gecko|konqueror|msie|opera|webkit)/, [ | |
| ["konqueror", "khtml"], | |
| ["msie", "trident"], | |
| ["opera", "presto"] | |
| ], /(applewebkit|rv|konqueror|msie)(\:|\/|\s)([a-z0-9\.]*?)(\;|\)|\s)/); | |
| a.os = { | |
| name: (/(win|mac|linux|sunos|solaris|iphone)/.exec(navigator.platform.toLowerCase()) || [f])[0].replace("sunos", "solaris") | |
| }; | |
| if (!g) { | |
| a("html").addClass([a.os.name, a.browser.name, a.browser.className, a.layout.name, a.layout.className].join(" ")) | |
| } | |
| }; | |
| a.browserTest(navigator.userAgent) | |
| })(jQuery); | |
| (function (b) { | |
| b.hotkeys = { | |
| version: "0.8", | |
| specialKeys: { | |
| 8: "backspace", | |
| 9: "tab", | |
| 13: "return", | |
| 16: "shift", | |
| 17: "ctrl", | |
| 18: "alt", | |
| 19: "pause", | |
| 20: "capslock", | |
| 27: "esc", | |
| 32: "space", | |
| 33: "pageup", | |
| 34: "pagedown", | |
| 35: "end", | |
| 36: "home", | |
| 37: "left", | |
| 38: "up", | |
| 39: "right", | |
| 40: "down", | |
| 45: "insert", | |
| 46: "del", | |
| 96: "0", | |
| 97: "1", | |
| 98: "2", | |
| 99: "3", | |
| 100: "4", | |
| 101: "5", | |
| 102: "6", | |
| 103: "7", | |
| 104: "8", | |
| 105: "9", | |
| 106: "*", | |
| 107: "+", | |
| 109: "-", | |
| 110: ".", | |
| 111: "/", | |
| 112: "f1", | |
| 113: "f2", | |
| 114: "f3", | |
| 115: "f4", | |
| 116: "f5", | |
| 117: "f6", | |
| 118: "f7", | |
| 119: "f8", | |
| 120: "f9", | |
| 121: "f10", | |
| 122: "f11", | |
| 123: "f12", | |
| 144: "numlock", | |
| 145: "scroll", | |
| 191: "/", | |
| 224: "meta" | |
| }, | |
| shiftNums: { | |
| "`": "~", | |
| "1": "!", | |
| "2": "@", | |
| "3": "#", | |
| "4": "$", | |
| "5": "%", | |
| "6": "^", | |
| "7": "&", | |
| "8": "*", | |
| "9": "(", | |
| "0": ")", | |
| "-": "_", | |
| "=": "+", | |
| ";": ": ", | |
| "'": '"', | |
| ",": "<", | |
| ".": ">", | |
| "/": "?", | |
| "\\": "|" | |
| } | |
| }; | |
| function a(d) { | |
| if (typeof d.data !== "string") { | |
| return | |
| } | |
| var c = d.handler, | |
| e = d.data.toLowerCase().split(" "); | |
| d.handler = function (n) { | |
| if (this !== n.target && (/textarea|select/i.test(n.target.nodeName) || n.target.type === "text")) { | |
| return | |
| } | |
| var h = n.type !== "keypress" && b.hotkeys.specialKeys[n.which], | |
| o = String.fromCharCode(n.which).toLowerCase(), | |
| k, m = "", | |
| g = {}; | |
| if (n.altKey && h !== "alt") { | |
| m += "alt+" | |
| } | |
| if (n.ctrlKey && h !== "ctrl") { | |
| m += "ctrl+" | |
| } | |
| if (n.metaKey && !n.ctrlKey && h !== "meta") { | |
| m += "meta+" | |
| } | |
| if (n.shiftKey && h !== "shift") { | |
| m += "shift+" | |
| } | |
| if (h) { | |
| g[m + h] = true | |
| } else { | |
| g[m + o] = true; | |
| g[m + b.hotkeys.shiftNums[o]] = true; | |
| if (m === "shift+") { | |
| g[b.hotkeys.shiftNums[o]] = true | |
| } | |
| } | |
| for (var j = 0, f = e.length; j < f; j++) { | |
| if (g[e[j]]) { | |
| return c.apply(this, arguments) | |
| } | |
| } | |
| } | |
| } | |
| b.each(["keydown", "keyup", "keypress"], function () { | |
| b.event.special[this] = { | |
| add: a | |
| } | |
| }) | |
| })(jQuery); | |
| function ltrim(b) { | |
| if (b) { | |
| var a = /\s*((\S+\s*)*)/; | |
| return b.replace(a, "$1") | |
| } | |
| return "" | |
| } | |
| function rtrim(b) { | |
| if (b) { | |
| var a = /((\s*\S+)*)\s*/; | |
| return b.replace(a, "$1") | |
| } | |
| return "" | |
| } | |
| function trim(a) { | |
| if (a) { | |
| return ltrim(rtrim(a)) | |
| } | |
| return "" | |
| } | |
| function entityEncode(a) { | |
| a = a.replace(/&/g, "&"); | |
| a = a.replace(/</g, "<"); | |
| a = a.replace(/>/g, ">"); | |
| a = a.replace(/ /g, " "); | |
| if (/msie/i.test(navigator.userAgent)) { | |
| a = a.replace("\n", " <br />") | |
| } else { | |
| a = a.replace(/\x0D/g, " <br />") | |
| } | |
| return a | |
| } | |
| var TerminalShell = { | |
| commands: { | |
| help: function help(a) { | |
| a.print($("<h3>help</h3>")); | |
| cmd_list = $("<ul>"); | |
| $.each(this.commands, function (b, c) { | |
| cmd_list.append($("<li>").text(b)) | |
| }); | |
| a.print(cmd_list) | |
| }, | |
| clear: function (a) { | |
| a.clear() | |
| } | |
| }, | |
| fallback: null, | |
| process: function (a, b) { | |
| var d = b.split(" "); | |
| var c = d.shift(); | |
| d.unshift(a); | |
| if (c in this.commands) { | |
| this.commands[c].apply(this, d) | |
| } else { | |
| if (!(this.fallback && this.fallback(a, b))) { | |
| a.print('Unrecognized command. Type "help" for assistance.') | |
| } | |
| } | |
| } | |
| }; | |
| var Terminal = { | |
| buffer: "", | |
| pos: 0, | |
| history: [], | |
| historyPos: 0, | |
| promptActive: true, | |
| cursorBlinkState: true, | |
| _cursorBlinkTimeout: null, | |
| spinnerIndex: 0, | |
| _spinnerTimeout: null, | |
| output: TerminalShell, | |
| config: { | |
| scrollStep: 20, | |
| scrollSpeed: 100, | |
| bg_color: "#000", | |
| fg_color: "#FFF", | |
| cursor_blink_time: 700, | |
| cursor_style: "block", | |
| prompt: "guest@xkcd:/$ ", | |
| spinnerCharacters: ["[ ]", "[. ]", "[.. ]", "[...]"], | |
| spinnerSpeed: 250, | |
| typingSpeed: 50 | |
| }, | |
| sticky: { | |
| keys: { | |
| ctrl: false, | |
| alt: false, | |
| scroll: false | |
| }, | |
| set: function (a, b) { | |
| this.keys[a] = b; | |
| $("#" + a + "-indicator").toggle(this.keys[a]) | |
| }, | |
| toggle: function (a) { | |
| this.set(a, !this.keys[a]) | |
| }, | |
| reset: function (a) { | |
| this.set(a, false) | |
| }, | |
| resetAll: function (a) { | |
| $.each(this.keys, $.proxy(function (b, c) { | |
| this.reset(b) | |
| }, this)) | |
| } | |
| }, | |
| init: function () { | |
| $(document).keypress($.proxy(function (c) { | |
| if (!this.promptActive) { | |
| return | |
| } | |
| if (c.which >= 32 && c.which <= 126) { | |
| var b = String.fromCharCode(c.which); | |
| var a = b.toLowerCase() | |
| } else { | |
| return | |
| } | |
| if ($.browser.opera && !(/[\w\s]/.test(b))) { | |
| return | |
| } | |
| if (this.sticky.keys.ctrl) { | |
| if (a == "w") { | |
| this.deleteWord() | |
| } else { | |
| if (a == "h") { | |
| Terminal.deleteCharacter(false) | |
| } else { | |
| if (a == "l") { | |
| this.clear() | |
| } else { | |
| if (a == "a") { | |
| this.setPos(0) | |
| } else { | |
| if (a == "e") { | |
| this.setPos(this.buffer.length) | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } else { | |
| if (b) { | |
| this.addCharacter(b); | |
| c.preventDefault() | |
| } | |
| } | |
| }, this)).bind("keydown", "return", function (a) { | |
| if (Terminal.promptActive) { | |
| Terminal.processInputBuffer() | |
| } | |
| }).bind("keydown", "backspace", function (a) { | |
| a.preventDefault(); | |
| Terminal.deleteCharacter(a.shiftKey) | |
| }).bind("keydown", "del", function (a) { | |
| Terminal.deleteCharacter(true) | |
| }).bind("keydown", "left", function (a) { | |
| Terminal.moveCursor(-1) | |
| }).bind("keydown", "right", function (a) { | |
| Terminal.moveCursor(1) | |
| }).bind("keydown", "up", function (a) { | |
| a.preventDefault(); | |
| if (a.shiftKey || Terminal.sticky.keys.scroll) { | |
| Terminal.scrollLine(-1) | |
| } else { | |
| if (a.ctrlKey || Terminal.sticky.keys.ctrl) { | |
| Terminal.scrollPage(-1) | |
| } else { | |
| Terminal.moveHistory(-1) | |
| } | |
| } | |
| }).bind("keydown", "down", function (a) { | |
| a.preventDefault(); | |
| if (a.shiftKey || Terminal.sticky.keys.scroll) { | |
| Terminal.scrollLine(1) | |
| } else { | |
| if (a.ctrlKey || Terminal.sticky.keys.ctrl) { | |
| Terminal.scrollPage(1) | |
| } else { | |
| Terminal.moveHistory(1) | |
| } | |
| } | |
| }).bind("keydown", "pageup", function (a) { | |
| Terminal.scrollPage(-1) | |
| }).bind("keydown", "pagedown", function (a) { | |
| Terminal.scrollPage(1) | |
| }).bind("keydown", "home", function (a) { | |
| a.preventDefault(); | |
| if (a.ctrlKey || Terminal.sticky.keys.ctrl) { | |
| Terminal.jumpToTop() | |
| } else { | |
| Terminal.setPos(0) | |
| } | |
| }).bind("keydown", "end", function (a) { | |
| a.preventDefault(); | |
| if (a.ctrlKey || Terminal.sticky.keys.ctrl) { | |
| Terminal.jumpToBottom() | |
| } else { | |
| Terminal.setPos(Terminal.buffer.length) | |
| } | |
| }).bind("keydown", "tab", function (a) { | |
| a.preventDefault() | |
| }).keyup(function (b) { | |
| var a = $.hotkeys.specialKeys[b.which]; | |
| if (a in { | |
| ctrl: true, | |
| alt: true, | |
| scroll: true | |
| }) { | |
| Terminal.sticky.toggle(a) | |
| } else { | |
| if (!(a in { | |
| left: true, | |
| right: true, | |
| up: true, | |
| down: true | |
| })) { | |
| Terminal.sticky.resetAll() | |
| } | |
| } | |
| }); | |
| $(window).resize(function (a) { | |
| $("#screen").scrollTop($("#screen").attr("scrollHeight")) | |
| }); | |
| this.setCursorState(true); | |
| this.setWorking(false); | |
| $("#prompt").html(this.config.prompt); | |
| $("#screen").hide().fadeIn("fast", function () { | |
| $("#screen").triggerHandler("cli-load") | |
| }) | |
| }, | |
| setCursorState: function (b, a) { | |
| this.cursorBlinkState = b; | |
| if (this.config.cursor_style == "block") { | |
| if (b) { | |
| $("#cursor").css({ | |
| color: this.config.bg_color, | |
| backgroundColor: this.config.fg_color | |
| }) | |
| } else { | |
| $("#cursor").css({ | |
| color: this.config.fg_color, | |
| backgroundColor: this.config.bg_color | |
| }) | |
| } | |
| } else { | |
| if (b) { | |
| $("#cursor").css("textDecoration", "underline") | |
| } else { | |
| $("#cursor").css("textDecoration", "none") | |
| } | |
| } | |
| if (!a && this._cursorBlinkTimeout) { | |
| window.clearTimeout(this._cursorBlinkTimeout); | |
| this._cursorBlinkTimeout = null | |
| } | |
| this._cursorBlinkTimeout = window.setTimeout($.proxy(function () { | |
| this.setCursorState(!this.cursorBlinkState, true) | |
| }, this), this.config.cursor_blink_time) | |
| }, | |
| updateInputDisplay: function () { | |
| var c = "", | |
| b = " ", | |
| a = ""; | |
| if (this.pos < 0) { | |
| this.pos = 0 | |
| } | |
| if (this.pos > this.buffer.length) { | |
| this.pos = this.buffer.length | |
| } | |
| if (this.pos > 0) { | |
| c = this.buffer.substr(0, this.pos) | |
| } | |
| if (this.pos < this.buffer.length) { | |
| b = this.buffer.substr(this.pos, 1) | |
| } | |
| if (this.buffer.length - this.pos > 1) { | |
| a = this.buffer.substr(this.pos + 1, this.buffer.length - this.pos - 1) | |
| } | |
| $("#lcommand").text(c); | |
| $("#cursor").text(b); | |
| if (b == " ") { | |
| $("#cursor").html(" ") | |
| } | |
| $("#rcommand").text(a); | |
| $("#prompt").text(this.config.prompt); | |
| return | |
| }, | |
| clearInputBuffer: function () { | |
| this.buffer = ""; | |
| this.pos = 0; | |
| this.updateInputDisplay() | |
| }, | |
| clear: function () { | |
| $("#display").html("") | |
| }, | |
| addCharacter: function (b) { | |
| var c = this.buffer.substr(0, this.pos); | |
| var a = this.buffer.substr(this.pos, this.buffer.length - this.pos); | |
| this.buffer = c + b + a; | |
| this.pos++; | |
| this.updateInputDisplay(); | |
| this.setCursorState(true) | |
| }, | |
| deleteCharacter: function (a) { | |
| var d = a ? 1 : 0; | |
| if (this.pos >= (1 - d)) { | |
| var c = this.buffer.substr(0, this.pos - 1 + d); | |
| var b = this.buffer.substr(this.pos + d, this.buffer.length - this.pos - d); | |
| this.buffer = c + b; | |
| this.pos -= 1 - d; | |
| this.updateInputDisplay() | |
| } | |
| this.setCursorState(true) | |
| }, | |
| deleteWord: function () { | |
| if (this.pos > 0) { | |
| var a = this.pos; | |
| while (a > 0 && this.buffer.charAt(a) !== " ") { | |
| a-- | |
| } | |
| left = this.buffer.substr(0, a - 1); | |
| right = this.buffer.substr(a, this.buffer.length - this.pos); | |
| this.buffer = left + right; | |
| this.pos = a; | |
| this.updateInputDisplay() | |
| } | |
| this.setCursorState(true) | |
| }, | |
| moveCursor: function (a) { | |
| this.setPos(this.pos + a) | |
| }, | |
| setPos: function (a) { | |
| if ((a >= 0) && (a <= this.buffer.length)) { | |
| this.pos = a; | |
| Terminal.updateInputDisplay() | |
| } | |
| this.setCursorState(true) | |
| }, | |
| moveHistory: function (b) { | |
| var a = this.historyPos + b; | |
| if ((a >= 0) && (a <= this.history.length)) { | |
| if (a == this.history.length) { | |
| this.clearInputBuffer() | |
| } else { | |
| this.buffer = this.history[a] | |
| } | |
| this.pos = this.buffer.length; | |
| this.historyPos = a; | |
| this.updateInputDisplay(); | |
| this.jumpToBottom() | |
| } | |
| this.setCursorState(true) | |
| }, | |
| addHistory: function (a) { | |
| this.historyPos = this.history.push(a) | |
| }, | |
| jumpToBottom: function () { | |
| $("#screen").animate({ | |
| scrollTop: $("#screen").attr("scrollHeight") | |
| }, this.config.scrollSpeed, "linear") | |
| }, | |
| jumpToTop: function () { | |
| $("#screen").animate({ | |
| scrollTop: 0 | |
| }, this.config.scrollSpeed, "linear") | |
| }, | |
| scrollPage: function (a) { | |
| $("#screen").animate({ | |
| scrollTop: $("#screen").scrollTop() + a * $("#screen").height() | |
| }, this.config.scrollSpeed, "linear") | |
| }, | |
| scrollLine: function (a) { | |
| $("#screen").scrollTop($("#screen").scrollTop() + a * this.config.scrollStep) | |
| }, | |
| print: function (a) { | |
| if (!a) { | |
| $("#display").append($("<div>")) | |
| } else { | |
| if (typeof a == "string") { | |
| $("#display").append($("<p>").text(a)) | |
| } else { | |
| $("#display").append(a) | |
| } | |
| } | |
| this.jumpToBottom() | |
| }, | |
| processInputBuffer: function (a) { | |
| this.print($("<p>").addClass("command").text(this.config.prompt + this.buffer)); | |
| var a = trim(this.buffer); | |
| this.clearInputBuffer(); | |
| if (a.length == 0) { | |
| return false | |
| } | |
| this.addHistory(a); | |
| if (this.output) { | |
| return this.output.process(this, a) | |
| } else { | |
| return false | |
| } | |
| }, | |
| setPromptActive: function (a) { | |
| this.promptActive = a; | |
| $("#inputline").toggle(this.promptActive) | |
| }, | |
| setWorking: function (a) { | |
| if (a && !this._spinnerTimeout) { | |
| $("#display .command:last-child").add("#bottomline").first().append($("#spinner")); | |
| this._spinnerTimeout = window.setInterval($.proxy(function () { | |
| if (!$("#spinner").is(":visible")) { | |
| $("#spinner").fadeIn() | |
| } | |
| this.spinnerIndex = (this.spinnerIndex + 1) % this.config.spinnerCharacters.length; | |
| $("#spinner").text(this.config.spinnerCharacters[this.spinnerIndex]) | |
| }, this), this.config.spinnerSpeed); | |
| this.setPromptActive(false); | |
| $("#screen").triggerHandler("cli-busy") | |
| } else { | |
| if (!a && this._spinnerTimeout) { | |
| clearInterval(this._spinnerTimeout); | |
| this._spinnerTimeout = null; | |
| $("#spinner").fadeOut(); | |
| this.setPromptActive(true); | |
| $("#screen").triggerHandler("cli-ready") | |
| } | |
| } | |
| }, | |
| runCommand: function (e) { | |
| var b = 0; | |
| var d = false; | |
| this.promptActive = false; | |
| var a = window.setInterval($.proxy(function c() { | |
| if (b < e.length) { | |
| this.addCharacter(e.charAt(b)); | |
| b += 1 | |
| } else { | |
| clearInterval(a); | |
| this.promptActive = true; | |
| this.processInputBuffer() | |
| } | |
| }, this), this.config.typingSpeed) | |
| } | |
| }; | |
| $(document).ready(function () { | |
| $("#welcome").show(); | |
| document.onkeydown = document.onkeypress = function (a) { | |
| return $.hotkeys.specialKeys[a.keyCode] != "backspace" | |
| }; | |
| Terminal.init() | |
| }); | |
| function pathFilename(a) { | |
| match = /\/([^\/]+)$/.exec(a); | |
| if (match) { | |
| return match[1] | |
| } | |
| } | |
| function getRandomInt(b, a) { | |
| return Math.floor(Math.random() * (a - b + 1)) + b | |
| } | |
| function randomChoice(a) { | |
| return a[getRandomInt(0, a.length - 1)] | |
| } | |
| var xkcd = { | |
| latest: null, | |
| last: null, | |
| cache: {}, | |
| get: function (b, c, a) { | |
| if (b == null) { | |
| path = "http://xkcd.com/info.0.json" | |
| } else { | |
| if (Number(b)) { | |
| path = "http://xkcd.com/" + b + "/info.0.json" | |
| } else { | |
| a(false); | |
| return false | |
| } | |
| } | |
| if (b in this.cache) { | |
| this.last = this.cache[b]; | |
| c(this.cache[b]) | |
| } else { | |
| return $.ajax({ | |
| url: path, | |
| dataType: "json", | |
| success: $.proxy(function (d) { | |
| this.last = this.cache[b] = d; | |
| c(d) | |
| }, this), | |
| error: a | |
| }) | |
| } | |
| } | |
| }; | |
| var xkcdDisplay = TerminalShell.commands.display = function (b, c) { | |
| function a() { | |
| b.print($("<p>").addClass("error").text('display: unable to open image "' + c + '": No such file or directory.')); | |
| b.setWorking(false) | |
| } | |
| b.setWorking(true); | |
| if (c) { | |
| c = String(c); | |
| num = Number(c.match(/^\d+/)); | |
| filename = pathFilename(c) | |
| } else { | |
| num = xkcd.last.num | |
| } | |
| xkcd.get(num, function (d) { | |
| if (!filename || (filename == pathFilename(d.img))) { | |
| $("<img>").hide().load(function () { | |
| b.print($("<h3>").text(d.num + ": " + d.title)); | |
| $(this).fadeIn(); | |
| var e = $(this); | |
| if (d.link) { | |
| e = $("<a>").attr("href", d.link).append($(this)) | |
| } | |
| b.print(e); | |
| b.setWorking(false) | |
| }).attr({ | |
| src: d.img, | |
| alt: d.title, | |
| title: d.alt | |
| }).addClass("comic") | |
| } else { | |
| a() | |
| } | |
| }, a) | |
| }; | |
| TerminalShell.commands.next = function (a) { | |
| xkcdDisplay(a, xkcd.last.num + 1) | |
| }; | |
| TerminalShell.commands.previous = TerminalShell.commands.prev = function (a) { | |
| xkcdDisplay(a, xkcd.last.num - 1) | |
| }; | |
| TerminalShell.commands.first = function (a) { | |
| xkcdDisplay(a, 1) | |
| }; | |
| TerminalShell.commands.latest = TerminalShell.commands.last = function (a) { | |
| xkcdDisplay(a, xkcd.latest.num) | |
| }; | |
| TerminalShell.commands.random = function (a) { | |
| xkcdDisplay(a, getRandomInt(1, xkcd.latest.num)) | |
| }; | |
| TerminalShell.commands["goto"] = function (a, b) { | |
| $("#screen").one("cli-ready", function (c) { | |
| a.print('Did you mean "display"?') | |
| }); | |
| xkcdDisplay(a, 292) | |
| }; | |
| function linkFile(a) { | |
| return { | |
| type: "dir", | |
| enter: function () { | |
| window.location = a | |
| } | |
| } | |
| } | |
| Filesystem = { | |
| "welcome.txt": { | |
| type: "file", | |
| read: function (a) { | |
| a.print($("<h4>").text("Welcome to the unixkcd console.")); | |
| a.print('To navigate, enter "next", "prev", "first", or "last".'); | |
| a.print('Try "help" for more information.') | |
| } | |
| }, | |
| "license.txt": { | |
| type: "file", | |
| read: function (a) { | |
| a.print($("<p>").html('Client-side logic for Wordpress CLI theme :: <a href="http://thrind.xamai.ca/">R. McFarland, 2006, 2007, 2008</a>')); | |
| a.print($("<p>").html('jQuery rewrite and overhaul :: <a href="http://www.chromakode.com/">Chromakode, 2010</a>')); | |
| a.print(); | |
| $.each(["This program is free software; you can redistribute it and/or", "modify it under the terms of the GNU General Public License", "as published by the Free Software Foundation; either version 2", "of the License, or (at your option) any later version.", "", "This program is distributed in the hope that it will be useful,", "but WITHOUT ANY WARRANTY; without even the implied warranty of", "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the", "GNU General Public License for more details.", "", "You should have received a copy of the GNU General Public License", "along with this program; if not, write to the Free Software", "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."], function (c, b) { | |
| a.print(b) | |
| }) | |
| } | |
| } | |
| }; | |
| Filesystem.blog = Filesystem.blag = linkFile("http://blag.xkcd.com"); | |
| Filesystem.forums = Filesystem.fora = linkFile("http://forums.xkcd.com/"); | |
| Filesystem.store = linkFile("http://store.xkcd.com/"); | |
| Filesystem.about = linkFile("http://xkcd.com/about/"); | |
| TerminalShell.pwd = Filesystem; | |
| TerminalShell.commands.cd = function (a, b) { | |
| if (b in this.pwd) { | |
| if (this.pwd[b].type == "dir") { | |
| this.pwd[b].enter(a) | |
| } else { | |
| if (this.pwd[b].type == "file") { | |
| a.print("cd: " + b + ": Not a directory") | |
| } | |
| } | |
| } else { | |
| a.print("cd: " + b + ": No such file or directory") | |
| } | |
| }; | |
| TerminalShell.commands.ls = function (a, b) { | |
| name_list = $("<ul>"); | |
| $.each(this.pwd, function (c, d) { | |
| if (d.type == "dir") { | |
| c += "/" | |
| } | |
| name_list.append($("<li>").text(c)) | |
| }); | |
| a.print(name_list) | |
| }; | |
| TerminalShell.commands.cat = function (a, b) { | |
| if (b in this.pwd) { | |
| if (this.pwd[b].type == "file") { | |
| this.pwd[b].read(a) | |
| } else { | |
| if (this.pwd[b].type == "dir") { | |
| a.print("cat: " + b + ": Is a directory") | |
| } | |
| } | |
| } else { | |
| if (pathFilename(b) == "alt.txt") { | |
| a.setWorking(true); | |
| num = Number(b.match(/^\d+/)); | |
| xkcd.get(num, function (c) { | |
| a.print(c.alt); | |
| a.setWorking(false) | |
| }, function () { | |
| a.print($("<p>").addClass("error").text('cat: "' + b + '": No such file or directory.')); | |
| a.setWorking(false) | |
| }) | |
| } else { | |
| a.print("You're a kitty!") | |
| } | |
| } | |
| }; | |
| TerminalShell.commands.reddit = function (c, b) { | |
| b = Number(b); | |
| if (b) { | |
| a = "http://xkcd.com/" + b + "/" | |
| } else { | |
| var a = window.location | |
| } | |
| c.print($('<iframe src="http://www.reddit.com/static/button/button1.html?width=140&url=' + encodeURIComponent(a) + '&newwindow=1" height="22" width="140" scrolling="no" frameborder="0"></iframe>')) | |
| }; | |
| TerminalShell.commands["apt-get"] = function (c, d, a) { | |
| if ((a != "sudo") && (d in { | |
| update: true, | |
| upgrade: true, | |
| "dist-upgrade": true | |
| })) { | |
| c.print("E: Unable to lock the administration directory, are you root?") | |
| } else { | |
| if (d == "update") { | |
| c.print("Reading package lists... Done") | |
| } else { | |
| if (d == "upgrade") { | |
| if (($.browser.name == "msie") || ($.browser.name == "firefox" || $.browser.versionX < 3)) { | |
| c.print($("<p>").append($("<a>").attr("href", "http://abetterbrowser.org/").text("To complete installation, click here."))) | |
| } else { | |
| c.print("This looks pretty good to me.") | |
| } | |
| } else { | |
| if (d == "dist-upgrade") { | |
| var e = { | |
| win: "Windows", | |
| mac: "OS X", | |
| linux: "Linux" | |
| }; | |
| var b = $.os.name; | |
| if (b in e) { | |
| b = e[b] | |
| } else { | |
| b = "something fancy" | |
| } | |
| c.print("You are already running " + b + ".") | |
| } else { | |
| if (d == "moo") { | |
| c.print(" (__)"); | |
| c.print(" (oo)"); | |
| c.print(" /------\\/ "); | |
| c.print(" / | || "); | |
| c.print("* /\\---/\\ "); | |
| c.print(" ~~ ~~ "); | |
| c.print('...."Have you mooed today?"...') | |
| } else { | |
| if (!d) { | |
| c.print("This APT has Super Cow Powers.") | |
| } else { | |
| c.print("E: Invalid operation " + d) | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| }; | |
| TerminalShell.commands.sudo = function (a) { | |
| var c = Array.prototype.slice.call(arguments); | |
| c.shift(); | |
| if (c.join(" ") == "make me a sandwich") { | |
| a.print("Okay.") | |
| } else { | |
| var b = c.shift(); | |
| c.unshift(a); | |
| c.push("sudo"); | |
| if (b in TerminalShell.commands) { | |
| this.commands[b].apply(this, c) | |
| } else { | |
| a.print("sudo: " + b + ": command not found") | |
| } | |
| } | |
| }; | |
| function oneLiner(a, c, b) { | |
| if (c in b) { | |
| a.print(b[c]); | |
| return true | |
| } else { | |
| return false | |
| } | |
| } | |
| TerminalShell.commands.man = function (a, b) { | |
| pages = { | |
| last: "Man, last night was AWESOME.", | |
| help: "Man, help me out here.", | |
| next: "Request confirmed; you will be reincarnated as a man next.", | |
| cat: "You are now riding a half-man half-cat." | |
| }; | |
| if (!oneLiner(a, b, pages)) { | |
| a.print("Oh, I'm sure you can figure it out.") | |
| } | |
| }; | |
| Adventure = { | |
| rooms: { | |
| 0: { | |
| description: "You are at a computer using unixkcd.", | |
| exits: { | |
| west: 1, | |
| south: 10 | |
| } | |
| }, | |
| 1: { | |
| description: "Life is peaceful there.", | |
| exits: { | |
| east: 0, | |
| west: 2 | |
| } | |
| }, | |
| 2: { | |
| description: "In the open air.", | |
| exits: { | |
| east: 1, | |
| west: 3 | |
| } | |
| }, | |
| 3: { | |
| description: "Where the skies are blue.", | |
| exits: { | |
| east: 2, | |
| west: 4 | |
| } | |
| }, | |
| 4: { | |
| description: "This is what we're gonna do.", | |
| exits: { | |
| east: 3, | |
| west: 5 | |
| } | |
| }, | |
| 5: { | |
| description: "Sun in wintertime.", | |
| exits: { | |
| east: 4, | |
| west: 6 | |
| } | |
| }, | |
| 6: { | |
| description: "We will do just fine.", | |
| exits: { | |
| east: 5, | |
| west: 7 | |
| } | |
| }, | |
| 7: { | |
| description: "Where the skies are blue.", | |
| exits: { | |
| east: 6, | |
| west: 8 | |
| } | |
| }, | |
| 8: { | |
| description: "This is what we're gonna do.", | |
| exits: { | |
| east: 7 | |
| } | |
| }, | |
| 10: { | |
| description: "A dark hallway.", | |
| exits: { | |
| north: 0, | |
| south: 11 | |
| }, | |
| enter: function (a) { | |
| if (!Adventure.status.lamp) { | |
| a.print("You are eaten by a grue."); | |
| Adventure.status.alive = false; | |
| Adventure.goTo(a, 666) | |
| } | |
| } | |
| }, | |
| 11: { | |
| description: "Bed. This is where you sleep.", | |
| exits: { | |
| north: 10 | |
| } | |
| }, | |
| 666: { | |
| description: "You're dead!" | |
| } | |
| }, | |
| status: { | |
| alive: true, | |
| lamp: false | |
| }, | |
| goTo: function (a, b) { | |
| Adventure.location = Adventure.rooms[b]; | |
| Adventure.look(a); | |
| if (Adventure.location.enter) { | |
| Adventure.location.enter(a) | |
| } | |
| } | |
| }; | |
| Adventure.location = Adventure.rooms[0]; | |
| TerminalShell.commands.look = Adventure.look = function (b) { | |
| b.print(Adventure.location.description); | |
| if (Adventure.location.exits) { | |
| b.print(); | |
| var a = []; | |
| $.each(Adventure.location.exits, function (c, d) { | |
| a.push(c) | |
| }); | |
| b.print("Exits: " + a.join(", ")) | |
| } | |
| }; | |
| TerminalShell.commands.go = Adventure.go = function (a, b) { | |
| if (Adventure.location.exits && b in Adventure.location.exits) { | |
| Adventure.goTo(a, Adventure.location.exits[b]) | |
| } else { | |
| if (!b) { | |
| a.print("Go where?") | |
| } else { | |
| a.print("You cannot go " + b + ".") | |
| } | |
| } | |
| }; | |
| TerminalShell.commands.light = function (a, b) { | |
| if (b == "lamp") { | |
| if (!Adventure.status.lamp) { | |
| a.print("You set your lamp ablaze."); | |
| Adventure.status.lamp = true | |
| } else { | |
| a.print("Your lamp is already lit!") | |
| } | |
| } else { | |
| a.print("Light what?") | |
| } | |
| }; | |
| TerminalShell.commands.help = function (a) { | |
| a.print("You can do this.") | |
| }; | |
| TerminalShell.fallback = function (a, b) { | |
| oneliners = { | |
| "make me a sandwich": "What? Make it yourself.", | |
| "i read the source code": "<3", | |
| lpr: "PC LOAD LETTER", | |
| "hello joshua": "How about a nice game of Global Thermonuclear War?", | |
| xyzzy: "Nothing happens.", | |
| date: "March 22nd" | |
| }; | |
| oneliners.emacs = "You should really use vim."; | |
| oneliners.vi = oneliners.vim = "You should really use emacs."; | |
| b = b.toLowerCase(); | |
| if (!oneLiner(a, b, oneliners)) { | |
| if (b == "asl" || b == "a/s/l") { | |
| a.print(randomChoice(["2/AMD64/Server Rack", "328/M/Transylvania", "6/M/Battle School", "48/M/The White House", "7/F/Rapture", "Exactly your age/A gender you're attracted to/Far far away.", "7,831/F/Lothlórien", "42/M/FBI Field Office"])) | |
| } else { | |
| if (b == "find kitten") { | |
| a.print($('<iframe width="800" height="600" src="http://www.robotfindskitten.net/rfk.swf"></iframe>')) | |
| } else { | |
| if (b == "buy stuff") { | |
| Filesystem.store.enter() | |
| } else { | |
| return false | |
| } | |
| } | |
| } | |
| } | |
| return true | |
| }; | |
| $(document).ready(function () { | |
| Terminal.promptActive = false; | |
| $("#screen").bind("cli-load", function (a) { | |
| xkcd.get(null, function (b) { | |
| xkcd.latest = b; | |
| $("#screen").one("cli-ready", function (c) { | |
| Terminal.runCommand("cat welcome.txt") | |
| }); | |
| Terminal.runCommand("display " + xkcd.latest.num + "/" + pathFilename(xkcd.latest.img)) | |
| }) | |
| }) | |
| }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment