horatio
Version:
A javascript compiler for the Shakespeare Programming Language
1,490 lines (1,356 loc) • 48.5 kB
JavaScript
// Generated by CoffeeScript 1.6.3
/*
Copyrights 2011, the repl.it project.
Licensed under the MIT license
*/
(function() {
var $, Ansi, CLASS_ANSI, CLASS_BLURRED, CLASS_CURSOR, CLASS_HEADER, CLASS_INPUT, CLASS_OLD_PROMPT, CLASS_PREFIX, CLASS_PROMPT, DEFAULT_INDENT_WIDTH, DEFAULT_PROMPT_CONINUE_LABEL, DEFAULT_PROMPT_LABEL, EMPTY_DIV, EMPTY_SELECTOR, EMPTY_SPAN, ESCAPE_CHAR, ESCAPE_SYNTAX, E_KEYPRESS, JQConsole, KEY_BACKSPACE, KEY_DELETE, KEY_DOWN, KEY_END, KEY_ENTER, KEY_HOME, KEY_LEFT, KEY_PAGE_DOWN, KEY_PAGE_UP, KEY_RIGHT, KEY_TAB, KEY_UP, NEWLINE, STATE_INPUT, STATE_OUTPUT, STATE_PROMPT, spanHtml,
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__slice = [].slice;
$ = jQuery;
STATE_INPUT = 0;
STATE_OUTPUT = 1;
STATE_PROMPT = 2;
KEY_ENTER = 13;
KEY_TAB = 9;
KEY_DELETE = 46;
KEY_BACKSPACE = 8;
KEY_LEFT = 37;
KEY_RIGHT = 39;
KEY_UP = 38;
KEY_DOWN = 40;
KEY_HOME = 36;
KEY_END = 35;
KEY_PAGE_UP = 33;
KEY_PAGE_DOWN = 34;
CLASS_PREFIX = 'jqconsole-';
CLASS_CURSOR = "" + CLASS_PREFIX + "cursor";
CLASS_HEADER = "" + CLASS_PREFIX + "header";
CLASS_PROMPT = "" + CLASS_PREFIX + "prompt";
CLASS_OLD_PROMPT = "" + CLASS_PREFIX + "old-prompt";
CLASS_INPUT = "" + CLASS_PREFIX + "input";
CLASS_BLURRED = "" + CLASS_PREFIX + "blurred";
E_KEYPRESS = 'keypress';
EMPTY_SPAN = '<span/>';
EMPTY_DIV = '<div/>';
EMPTY_SELECTOR = ':empty';
NEWLINE = '\n';
DEFAULT_PROMPT_LABEL = '>>> ';
DEFAULT_PROMPT_CONINUE_LABEL = '... ';
DEFAULT_INDENT_WIDTH = 2;
CLASS_ANSI = "" + CLASS_PREFIX + "ansi-";
ESCAPE_CHAR = '\x1B';
ESCAPE_SYNTAX = /\[(\d*)(?:;(\d*))*m/;
Ansi = (function() {
Ansi.prototype.COLORS = ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white'];
function Ansi() {
this.stylize = __bind(this.stylize, this);
this._closeSpan = __bind(this._closeSpan, this);
this._openSpan = __bind(this._openSpan, this);
this.getClasses = __bind(this.getClasses, this);
this._style = __bind(this._style, this);
this._color = __bind(this._color, this);
this._remove = __bind(this._remove, this);
this._append = __bind(this._append, this);
this.klasses = [];
}
Ansi.prototype._append = function(klass) {
klass = "" + CLASS_ANSI + klass;
if (this.klasses.indexOf(klass) === -1) {
return this.klasses.push(klass);
}
};
Ansi.prototype._remove = function() {
var cls, klass, klasses, _i, _len, _results;
klasses = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
_results = [];
for (_i = 0, _len = klasses.length; _i < _len; _i++) {
klass = klasses[_i];
if (klass === 'fonts' || klass === 'color' || klass === 'background-color') {
_results.push(this.klasses = (function() {
var _j, _len1, _ref, _results1;
_ref = this.klasses;
_results1 = [];
for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) {
cls = _ref[_j];
if (cls.indexOf(klass) !== CLASS_ANSI.length) {
_results1.push(cls);
}
}
return _results1;
}).call(this));
} else {
klass = "" + CLASS_ANSI + klass;
_results.push(this.klasses = (function() {
var _j, _len1, _ref, _results1;
_ref = this.klasses;
_results1 = [];
for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) {
cls = _ref[_j];
if (cls !== klass) {
_results1.push(cls);
}
}
return _results1;
}).call(this));
}
}
return _results;
};
Ansi.prototype._color = function(i) {
return this.COLORS[i];
};
Ansi.prototype._style = function(code) {
if (code === '') {
code = 0;
}
code = parseInt(code);
if (isNaN(code)) {
return;
}
switch (code) {
case 0:
return this.klasses = [];
case 1:
return this._append('bold');
case 2:
return this._append('lighter');
case 3:
return this._append('italic');
case 4:
return this._append('underline');
case 5:
return this._append('blink');
case 6:
return this._append('blink-rapid');
case 8:
return this._append('hidden');
case 9:
return this._append('line-through');
case 10:
return this._remove('fonts');
case 11:
case 12:
case 13:
case 14:
case 15:
case 16:
case 17:
case 18:
case 19:
this._remove('fonts');
return this._append("fonts-" + (code - 10));
case 20:
return this._append('fraktur');
case 21:
return this._remove('bold', 'lighter');
case 22:
return this._remove('bold', 'lighter');
case 23:
return this._remove('italic', 'fraktur');
case 24:
return this._remove('underline');
case 25:
return this._remove('blink', 'blink-rapid');
case 28:
return this._remove('hidden');
case 29:
return this._remove('line-through');
case 30:
case 31:
case 32:
case 33:
case 34:
case 35:
case 36:
case 37:
this._remove('color');
return this._append('color-' + this._color(code - 30));
case 39:
return this._remove('color');
case 40:
case 41:
case 42:
case 43:
case 44:
case 45:
case 46:
case 47:
this._remove('background-color');
return this._append('background-color-' + this._color(code - 40));
case 49:
return this._remove('background-color');
case 51:
return this._append('framed');
case 53:
return this._append('overline');
case 54:
return this._remove('framed');
case 55:
return this._remove('overline');
}
};
Ansi.prototype.getClasses = function() {
return this.klasses.join(' ');
};
Ansi.prototype._openSpan = function(text) {
return "<span class=\"" + (this.getClasses()) + "\">" + text;
};
Ansi.prototype._closeSpan = function(text) {
return "" + text + "</span>";
};
Ansi.prototype.stylize = function(text) {
var code, d, i, _i, _len, _ref;
text = this._openSpan(text);
i = 0;
while ((i = text.indexOf(ESCAPE_CHAR, i)) && i !== -1) {
if (d = text.slice(i).match(ESCAPE_SYNTAX)) {
_ref = d.slice(1);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
code = _ref[_i];
this._style(code);
}
text = this._closeSpan(text.slice(0, i)) + this._openSpan(text.slice(i + 1 + d[0].length));
} else {
i++;
}
}
return this._closeSpan(text);
};
return Ansi;
})();
spanHtml = function(klass, content) {
return "<span class=\"" + klass + "\">" + (content || '') + "</span>";
};
JQConsole = (function() {
function JQConsole(outer_container, header, prompt_label, prompt_continue_label) {
this._HideComposition = __bind(this._HideComposition, this);
this._ShowComposition = __bind(this._ShowComposition, this);
this._UpdateComposition = __bind(this._UpdateComposition, this);
this._EndComposition = __bind(this._EndComposition, this);
this._StartComposition = __bind(this._StartComposition, this);
this._CheckComposition = __bind(this._CheckComposition, this);
this._ProcessMatch = __bind(this._ProcessMatch, this);
this._HandleKey = __bind(this._HandleKey, this);
this._HandleChar = __bind(this._HandleChar, this);
this.isMobile = !!navigator.userAgent.match(/iPhone|iPad|iPod|Android/i);
this.isIos = !!navigator.userAgent.match(/iPhone|iPad|iPod/i);
this.isAndroid = !!navigator.userAgent.match(/Android/i);
this.$window = $(window);
this.header = header || '';
this.prompt_label_main = typeof prompt_label === 'string' ? prompt_label : DEFAULT_PROMPT_LABEL;
this.prompt_label_continue = prompt_continue_label || DEFAULT_PROMPT_CONINUE_LABEL;
this.indent_width = DEFAULT_INDENT_WIDTH;
this.state = STATE_OUTPUT;
this.input_queue = [];
this.input_callback = null;
this.multiline_callback = null;
this.history = [];
this.history_index = 0;
this.history_new = '';
this.history_active = false;
this.shortcuts = {};
this.$container = $('<div/>').appendTo(outer_container);
this.$container.css({
'top': 0,
'left': 0,
'right': 0,
'bottom': 0,
'position': 'absolute',
'overflow': 'auto'
});
this.$console = $('<pre class="jqconsole"/>').appendTo(this.$container);
this.$console.css({
'margin': 0,
'position': 'relative',
'min-height': '100%',
'box-sizing': 'border-box',
'-moz-box-sizing': 'border-box',
'-webkit-box-sizing': 'border-box'
});
this.$console_focused = true;
this.$input_container = $(EMPTY_DIV).appendTo(this.$container);
this.$input_container.css({
position: 'absolute',
width: 1,
height: 0,
overflow: 'hidden'
});
this.$input_source = this.isAndroid ? $('<input/>') : $('<textarea/>');
this.$input_source.attr({
wrap: 'off',
autocapitalize: 'off',
autocorrect: 'off',
spellcheck: 'false',
autocomplete: 'off'
});
this.$input_source.css({
position: 'absolute',
width: 2
});
this.$input_source.appendTo(this.$input_container);
this.$composition = $(EMPTY_DIV);
this.$composition.addClass("" + CLASS_PREFIX + "composition");
this.$composition.css({
display: 'inline',
position: 'relative'
});
this.matchings = {
openings: {},
closings: {},
clss: []
};
this.ansi = new Ansi();
this._InitPrompt();
this._SetupEvents();
this.Write(this.header, CLASS_HEADER);
$(outer_container).data('jqconsole', this);
}
JQConsole.prototype.ResetHistory = function() {
return this.SetHistory([]);
};
JQConsole.prototype.ResetShortcuts = function() {
return this.shortcuts = {};
};
JQConsole.prototype.ResetMatchings = function() {
return this.matchings = {
openings: {},
closings: {},
clss: []
};
};
JQConsole.prototype.Reset = function() {
if (this.state !== STATE_OUTPUT) {
this.ClearPromptText(true);
}
this.state = STATE_OUTPUT;
this.input_queue = [];
this.input_callback = null;
this.multiline_callback = null;
this.ResetHistory();
this.ResetShortcuts();
this.ResetMatchings();
this.$prompt.detach();
this.$input_container.detach();
this.$console.html('');
this.$prompt.appendTo(this.$console);
this.$input_container.appendTo(this.$container);
this.Write(this.header, CLASS_HEADER);
return void 0;
};
JQConsole.prototype.GetHistory = function() {
return this.history;
};
JQConsole.prototype.SetHistory = function(history) {
this.history = history.slice();
return this.history_index = this.history.length;
};
/*------------------------ Shortcut Methods -----------------------------*/
JQConsole.prototype._CheckKeyCode = function(key_code) {
if (isNaN(key_code)) {
key_code = key_code.charCodeAt(0);
} else {
key_code = parseInt(key_code, 10);
}
if (!((0 < key_code && key_code < 256)) || isNaN(key_code)) {
throw new Error('Key code must be a number between 0 and 256 exclusive.');
}
return key_code;
};
JQConsole.prototype._LetterCaseHelper = function(key_code, callback) {
callback(key_code);
if ((65 <= key_code && key_code <= 90)) {
callback(key_code + 32);
}
if ((97 <= key_code && key_code <= 122)) {
return callback(key_code - 32);
}
};
JQConsole.prototype.RegisterShortcut = function(key_code, callback) {
var addShortcut,
_this = this;
key_code = this._CheckKeyCode(key_code);
if (typeof callback !== 'function') {
throw new Error('Callback must be a function, not ' + callback + '.');
}
addShortcut = function(key) {
if (!(key in _this.shortcuts)) {
_this.shortcuts[key] = [];
}
return _this.shortcuts[key].push(callback);
};
this._LetterCaseHelper(key_code, addShortcut);
return void 0;
};
JQConsole.prototype.UnRegisterShortcut = function(key_code, handler) {
var removeShortcut,
_this = this;
key_code = this._CheckKeyCode(key_code);
removeShortcut = function(key) {
if (key in _this.shortcuts) {
if (handler) {
return _this.shortcuts[key].splice(_this.shortcuts[key].indexOf(handler), 1);
} else {
return delete _this.shortcuts[key];
}
}
};
this._LetterCaseHelper(key_code, removeShortcut);
return void 0;
};
/*---------------------- END Shortcut Methods ---------------------------*/
JQConsole.prototype.GetColumn = function() {
var lines;
this.$prompt_right.detach();
this.$prompt_cursor.text('');
lines = this.$console.text().split(NEWLINE);
this.$prompt_cursor.html(' ');
this.$prompt_cursor.after(this.$prompt_right);
return lines[lines.length - 1].length;
};
JQConsole.prototype.GetLine = function() {
return this.$console.text().split(NEWLINE).length - 1;
};
JQConsole.prototype.ClearPromptText = function(clear_label) {
if (this.state === STATE_OUTPUT) {
throw new Error('ClearPromptText() is not allowed in output state.');
}
this.$prompt_before.html('');
this.$prompt_after.html('');
this.$prompt_label.text(clear_label ? '' : this._SelectPromptLabel(false));
this.$prompt_left.text('');
this.$prompt_right.text('');
return void 0;
};
JQConsole.prototype.GetPromptText = function(full) {
var after, before, current, getPromptLines, text;
if (this.state === STATE_OUTPUT) {
throw new Error('GetPromptText() is not allowed in output state.');
}
if (full) {
this.$prompt_cursor.text('');
text = this.$prompt.text();
this.$prompt_cursor.html(' ');
return text;
} else {
getPromptLines = function(node) {
var buffer;
buffer = [];
node.children().each(function() {
return buffer.push($(this).children().last().text());
});
return buffer.join(NEWLINE);
};
before = getPromptLines(this.$prompt_before);
if (before) {
before += NEWLINE;
}
current = this.$prompt_left.text() + this.$prompt_right.text();
after = getPromptLines(this.$prompt_after);
if (after) {
after = NEWLINE + after;
}
return before + current + after;
}
};
JQConsole.prototype.SetPromptText = function(text) {
if (this.state === STATE_OUTPUT) {
throw new Error('SetPromptText() is not allowed in output state.');
}
this.ClearPromptText(false);
this._AppendPromptText(text);
this._ScrollToEnd();
return void 0;
};
JQConsole.prototype.SetPromptLabel = function(main_label, continue_label) {
this.prompt_label_main = main_label;
if (continue_label != null) {
this.prompt_label_continue = continue_label;
}
return void 0;
};
JQConsole.prototype.Write = function(text, cls, escape) {
var span;
if (escape == null) {
escape = true;
}
if (escape) {
text = this.ansi.stylize($(EMPTY_SPAN).text(text).html());
}
span = $(EMPTY_SPAN).html(text);
if (cls != null) {
span.addClass(cls);
}
return this.Append(span);
};
JQConsole.prototype.Append = function(node) {
var $node;
$node = $(node).insertBefore(this.$prompt);
this._ScrollToEnd();
this.$prompt_cursor.detach().insertAfter(this.$prompt_left);
return $node;
};
JQConsole.prototype.Input = function(input_callback) {
var current_async_multiline, current_history_active, current_input_callback, current_multiline_callback,
_this = this;
if (this.state === STATE_PROMPT) {
current_input_callback = this.input_callback;
current_multiline_callback = this.multiline_callback;
current_history_active = this.history_active;
current_async_multiline = this.async_multiline;
this.AbortPrompt();
this.input_queue.unshift(function() {
return _this.Prompt(current_history_active, current_input_callback, current_multiline_callback, current_async_multiline);
});
} else if (this.state !== STATE_OUTPUT) {
this.input_queue.push(function() {
return _this.Input(input_callback);
});
return;
}
this.history_active = false;
this.input_callback = input_callback;
this.multiline_callback = null;
this.state = STATE_INPUT;
this.$prompt.attr('class', CLASS_INPUT);
this.$prompt_label.text(this._SelectPromptLabel(false));
this.Focus();
this._ScrollToEnd();
return void 0;
};
JQConsole.prototype.Prompt = function(history_enabled, result_callback, multiline_callback, async_multiline) {
var _this = this;
if (this.state !== STATE_OUTPUT) {
this.input_queue.push(function() {
return _this.Prompt(history_enabled, result_callback, multiline_callback, async_multiline);
});
return;
}
this.history_active = history_enabled;
this.input_callback = result_callback;
this.multiline_callback = multiline_callback;
this.async_multiline = async_multiline;
this.state = STATE_PROMPT;
this.$prompt.attr('class', CLASS_PROMPT + ' ' + this.ansi.getClasses());
this.$prompt_label.text(this._SelectPromptLabel(false));
this.Focus();
this._ScrollToEnd();
return void 0;
};
JQConsole.prototype.AbortPrompt = function() {
if (this.state !== STATE_PROMPT) {
throw new Error('Cannot abort prompt when not in prompt state.');
}
this.Write(this.GetPromptText(true) + NEWLINE, CLASS_OLD_PROMPT);
this.ClearPromptText(true);
this.state = STATE_OUTPUT;
this.input_callback = this.multiline_callback = null;
this._CheckInputQueue();
return void 0;
};
JQConsole.prototype.Focus = function() {
if (!this.IsDisabled()) {
this.$input_source.focus();
}
return void 0;
};
JQConsole.prototype.SetIndentWidth = function(width) {
return this.indent_width = width;
};
JQConsole.prototype.GetIndentWidth = function() {
return this.indent_width;
};
JQConsole.prototype.RegisterMatching = function(open, close, cls) {
var match_config;
match_config = {
opening_char: open,
closing_char: close,
cls: cls
};
this.matchings.clss.push(cls);
this.matchings.openings[open] = match_config;
return this.matchings.closings[close] = match_config;
};
JQConsole.prototype.UnRegisterMatching = function(open, close) {
var cls;
cls = this.matchings.openings[open].cls;
delete this.matchings.openings[open];
delete this.matchings.closings[close];
return this.matchings.clss.splice(this.matchings.clss.indexOf(cls), 1);
};
JQConsole.prototype.Dump = function() {
var $elems, elem;
$elems = this.$console.find("." + CLASS_HEADER).nextUntil("." + CLASS_PROMPT).addBack();
return ((function() {
var _i, _len, _results;
_results = [];
for (_i = 0, _len = $elems.length; _i < _len; _i++) {
elem = $elems[_i];
if ($(elem).is("." + CLASS_OLD_PROMPT)) {
_results.push($(elem).text().replace(/^\s+/, '>>> '));
} else {
_results.push($(elem).text());
}
}
return _results;
})()).join('');
};
JQConsole.prototype.GetState = function() {
if (this.state === STATE_INPUT) {
return 'input';
} else if (this.state === STATE_OUTPUT) {
return 'output';
} else {
return 'prompt';
}
};
JQConsole.prototype.Disable = function() {
this.$input_source.attr('disabled', true);
return this.$input_source.blur();
};
JQConsole.prototype.Enable = function() {
return this.$input_source.attr('disabled', false);
};
JQConsole.prototype.IsDisabled = function() {
return Boolean(this.$input_source.attr('disabled'));
};
JQConsole.prototype.MoveToStart = function(all_lines) {
this._MoveTo(all_lines, true);
return void 0;
};
JQConsole.prototype.MoveToEnd = function(all_lines) {
this._MoveTo(all_lines, false);
return void 0;
};
JQConsole.prototype.Clear = function() {
this.$console.find("." + CLASS_HEADER).nextUntil("." + CLASS_PROMPT).addBack().text('');
this.$prompt_cursor.detach();
return this.$prompt_after.before(this.$prompt_cursor);
};
/*------------------------ Private Methods -------------------------------*/
JQConsole.prototype._CheckInputQueue = function() {
if (this.input_queue.length) {
return this.input_queue.shift()();
}
};
JQConsole.prototype._InitPrompt = function() {
this.$prompt = $(spanHtml(CLASS_INPUT)).appendTo(this.$console);
this.$prompt_before = $(EMPTY_SPAN).appendTo(this.$prompt);
this.$prompt_current = $(EMPTY_SPAN).appendTo(this.$prompt);
this.$prompt_after = $(EMPTY_SPAN).appendTo(this.$prompt);
this.$prompt_label = $(EMPTY_SPAN).appendTo(this.$prompt_current);
this.$prompt_left = $(EMPTY_SPAN).appendTo(this.$prompt_current);
this.$prompt_right = $(EMPTY_SPAN).appendTo(this.$prompt_current);
this.$prompt_right.css({
position: 'relative'
});
this.$prompt_cursor = $(spanHtml(CLASS_CURSOR, ' '));
this.$prompt_cursor.insertBefore(this.$prompt_right);
this.$prompt_cursor.css({
color: 'transparent',
display: 'inline',
zIndex: 0
});
if (!this.isMobile) {
return this.$prompt_cursor.css('position', 'absolute');
}
};
JQConsole.prototype._SetupEvents = function() {
var _this = this;
if (this.isMobile) {
this.$console.click(function(e) {
e.preventDefault();
return _this.Focus();
});
} else {
this.$console.mouseup(function(e) {
var fn;
if (e.which === 2) {
return _this.Focus();
} else {
fn = function() {
if (!window.getSelection().toString()) {
e.preventDefault();
return _this.Focus();
}
};
return setTimeout(fn, 0);
}
});
}
this.$input_source.focus(function() {
var hideTextInput, removeClass;
_this._ScrollToEnd();
_this.$console_focused = true;
_this.$console.removeClass(CLASS_BLURRED);
removeClass = function() {
if (_this.$console_focused) {
return _this.$console.removeClass(CLASS_BLURRED);
}
};
setTimeout(removeClass, 100);
hideTextInput = function() {
if (_this.isIos && _this.$console_focused) {
return _this.$input_source.hide();
}
};
return setTimeout(hideTextInput, 500);
});
this.$input_source.blur(function() {
var addClass;
_this.$console_focused = false;
if (_this.isIos) {
_this.$input_source.show();
}
addClass = function() {
if (!_this.$console_focused) {
return _this.$console.addClass(CLASS_BLURRED);
}
};
return setTimeout(addClass, 100);
});
this.$input_source.bind('paste', function() {
var handlePaste;
handlePaste = function() {
if (_this.in_composition) {
return;
}
_this._AppendPromptText(_this.$input_source.val());
_this.$input_source.val('');
return _this.Focus();
};
return setTimeout(handlePaste, 0);
});
this.$input_source.keypress(this._HandleChar);
this.$input_source.keydown(this._HandleKey);
this.$input_source.keydown(this._CheckComposition);
this.$input_source.bind('compositionstart', this._StartComposition);
this.$input_source.bind('compositionend', function(e) {
return setTimeout((function() {
return _this._EndComposition(e);
}), 0);
});
if (this.isAndroid) {
this.$input_source.bind('input', this._StartComposition);
return this.$input_source.bind('input', this._UpdateComposition);
} else {
return this.$input_source.bind('text', this._UpdateComposition);
}
};
JQConsole.prototype._HandleChar = function(event) {
var char_code;
if (this.state === STATE_OUTPUT || event.metaKey || event.ctrlKey) {
return true;
}
char_code = event.which;
if (char_code === 8 || char_code === 9 || char_code === 13) {
return false;
}
this.$prompt_left.text(this.$prompt_left.text() + String.fromCharCode(char_code));
this._ScrollToEnd();
return false;
};
JQConsole.prototype._HandleKey = function(event) {
var key;
if (this.state === STATE_OUTPUT) {
return true;
}
key = event.keyCode || event.which;
setTimeout($.proxy(this._CheckMatchings, this), 0);
if (event.altKey) {
return true;
} else if (event.ctrlKey || event.metaKey) {
return this._HandleCtrlShortcut(key);
} else if (event.shiftKey) {
switch (key) {
case KEY_ENTER:
this._HandleEnter(true);
break;
case KEY_TAB:
this._Unindent();
break;
case KEY_UP:
this._MoveUp();
break;
case KEY_DOWN:
this._MoveDown();
break;
case KEY_PAGE_UP:
this._ScrollPage('up');
break;
case KEY_PAGE_DOWN:
this._ScrollPage('down');
break;
default:
return true;
}
return false;
} else {
switch (key) {
case KEY_ENTER:
this._HandleEnter(false);
break;
case KEY_TAB:
this._Indent();
break;
case KEY_DELETE:
this._Delete(false);
break;
case KEY_BACKSPACE:
this._Backspace(false);
break;
case KEY_LEFT:
this._MoveLeft(false);
break;
case KEY_RIGHT:
this._MoveRight(false);
break;
case KEY_UP:
this._HistoryPrevious();
break;
case KEY_DOWN:
this._HistoryNext();
break;
case KEY_HOME:
this.MoveToStart(false);
break;
case KEY_END:
this.MoveToEnd(false);
break;
case KEY_PAGE_UP:
this._ScrollPage('up');
break;
case KEY_PAGE_DOWN:
this._ScrollPage('down');
break;
default:
return true;
}
return false;
}
};
JQConsole.prototype._HandleCtrlShortcut = function(key) {
var handler, _i, _len, _ref;
switch (key) {
case KEY_DELETE:
this._Delete(true);
break;
case KEY_BACKSPACE:
this._Backspace(true);
break;
case KEY_LEFT:
this._MoveLeft(true);
break;
case KEY_RIGHT:
this._MoveRight(true);
break;
case KEY_UP:
this._MoveUp();
break;
case KEY_DOWN:
this._MoveDown();
break;
case KEY_END:
this.MoveToEnd(true);
break;
case KEY_HOME:
this.MoveToStart(true);
break;
default:
if (key in this.shortcuts) {
_ref = this.shortcuts[key];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
handler = _ref[_i];
handler.call(this);
}
return false;
} else {
return true;
}
}
return false;
};
JQConsole.prototype._HandleEnter = function(shift) {
var continuation, text,
_this = this;
this._EndComposition();
if (shift) {
return this._InsertNewLine(true);
} else {
text = this.GetPromptText();
continuation = function(indent) {
var callback, cls_suffix, _, _i, _ref, _results;
if (indent !== false) {
_this.MoveToEnd(true);
_this._InsertNewLine(true);
_results = [];
for (_ = _i = 0, _ref = Math.abs(indent); 0 <= _ref ? _i < _ref : _i > _ref; _ = 0 <= _ref ? ++_i : --_i) {
if (indent > 0) {
_results.push(_this._Indent());
} else {
_results.push(_this._Unindent());
}
}
return _results;
} else {
cls_suffix = _this.state === STATE_INPUT ? 'input' : 'prompt';
_this.Write(_this.GetPromptText(true) + NEWLINE, ("" + CLASS_PREFIX + "old-") + cls_suffix);
_this.ClearPromptText(true);
if (_this.history_active) {
if (!_this.history.length || _this.history[_this.history.length - 1] !== text) {
_this.history.push(text);
}
_this.history_index = _this.history.length;
}
_this.state = STATE_OUTPUT;
callback = _this.input_callback;
_this.input_callback = null;
if (callback) {
callback(text);
}
return _this._CheckInputQueue();
}
};
if (this.multiline_callback) {
if (this.async_multiline) {
return this.multiline_callback(text, continuation);
} else {
return continuation(this.multiline_callback(text));
}
} else {
return continuation(false);
}
}
};
JQConsole.prototype._GetDirectionals = function(back) {
var $prompt_opposite, $prompt_rel_opposite, $prompt_relative, $prompt_which, MoveDirection, MoveToLimit, where_append, which_end;
$prompt_which = back ? this.$prompt_left : this.$prompt_right;
$prompt_opposite = back ? this.$prompt_right : this.$prompt_left;
$prompt_relative = back ? this.$prompt_before : this.$prompt_after;
$prompt_rel_opposite = back ? this.$prompt_after : this.$prompt_before;
MoveToLimit = back ? $.proxy(this.MoveToStart, this) : $.proxy(this.MoveToEnd, this);
MoveDirection = back ? $.proxy(this._MoveLeft, this) : $.proxy(this._MoveRight, this);
which_end = back ? 'last' : 'first';
where_append = back ? 'prependTo' : 'appendTo';
return {
$prompt_which: $prompt_which,
$prompt_opposite: $prompt_opposite,
$prompt_relative: $prompt_relative,
$prompt_rel_opposite: $prompt_rel_opposite,
MoveToLimit: MoveToLimit,
MoveDirection: MoveDirection,
which_end: which_end,
where_append: where_append
};
};
JQConsole.prototype._VerticalMove = function(up) {
var $prompt_opposite, $prompt_relative, $prompt_which, MoveDirection, MoveToLimit, pos, text, _ref;
_ref = this._GetDirectionals(up), $prompt_which = _ref.$prompt_which, $prompt_opposite = _ref.$prompt_opposite, $prompt_relative = _ref.$prompt_relative, MoveToLimit = _ref.MoveToLimit, MoveDirection = _ref.MoveDirection;
if ($prompt_relative.is(EMPTY_SELECTOR)) {
return;
}
pos = this.$prompt_left.text().length;
MoveToLimit();
MoveDirection();
text = $prompt_which.text();
$prompt_opposite.text(up ? text.slice(pos) : text.slice(0, pos));
return $prompt_which.text(up ? text.slice(0, pos) : text.slice(pos));
};
JQConsole.prototype._MoveUp = function() {
return this._VerticalMove(true);
};
JQConsole.prototype._MoveDown = function() {
return this._VerticalMove();
};
JQConsole.prototype._HorizontalMove = function(whole_word, back) {
var $opposite_line, $prompt_opposite, $prompt_rel_opposite, $prompt_relative, $prompt_which, $which_line, len, regexp, text, tmp, where_append, which_end, word, _ref;
_ref = this._GetDirectionals(back), $prompt_which = _ref.$prompt_which, $prompt_opposite = _ref.$prompt_opposite, $prompt_relative = _ref.$prompt_relative, $prompt_rel_opposite = _ref.$prompt_rel_opposite, which_end = _ref.which_end, where_append = _ref.where_append;
regexp = back ? /\w*\W*$/ : /^\w*\W*/;
text = $prompt_which.text();
if (text) {
if (whole_word) {
word = text.match(regexp);
if (!word) {
return;
}
word = word[0];
tmp = $prompt_opposite.text();
$prompt_opposite.text(back ? word + tmp : tmp + word);
len = word.length;
return $prompt_which.text(back ? text.slice(0, -len) : text.slice(len));
} else {
tmp = $prompt_opposite.text();
$prompt_opposite.text(back ? text.slice(-1) + tmp : tmp + text[0]);
return $prompt_which.text(back ? text.slice(0, -1) : text.slice(1));
}
} else if (!$prompt_relative.is(EMPTY_SELECTOR)) {
$which_line = $(EMPTY_SPAN)[where_append]($prompt_rel_opposite);
$which_line.append($(EMPTY_SPAN).text(this.$prompt_label.text()));
$which_line.append($(EMPTY_SPAN).text($prompt_opposite.text()));
$opposite_line = $prompt_relative.children()[which_end]().detach();
this.$prompt_label.text($opposite_line.children().first().text());
$prompt_which.text($opposite_line.children().last().text());
return $prompt_opposite.text('');
}
};
JQConsole.prototype._MoveLeft = function(whole_word) {
return this._HorizontalMove(whole_word, true);
};
JQConsole.prototype._MoveRight = function(whole_word) {
return this._HorizontalMove(whole_word);
};
JQConsole.prototype._MoveTo = function(all_lines, back) {
var $prompt_opposite, $prompt_relative, $prompt_which, MoveDirection, MoveToLimit, _ref, _results;
_ref = this._GetDirectionals(back), $prompt_which = _ref.$prompt_which, $prompt_opposite = _ref.$prompt_opposite, $prompt_relative = _ref.$prompt_relative, MoveToLimit = _ref.MoveToLimit, MoveDirection = _ref.MoveDirection;
if (all_lines) {
_results = [];
while (!($prompt_relative.is(EMPTY_SELECTOR) && $prompt_which.text() === '')) {
MoveToLimit(false);
_results.push(MoveDirection(false));
}
return _results;
} else {
$prompt_opposite.text(this.$prompt_left.text() + this.$prompt_right.text());
return $prompt_which.text('');
}
};
JQConsole.prototype._Delete = function(whole_word) {
var $lower_line, text, word;
text = this.$prompt_right.text();
if (text) {
if (whole_word) {
word = text.match(/^\w*\W*/);
if (!word) {
return;
}
word = word[0];
return this.$prompt_right.text(text.slice(word.length));
} else {
return this.$prompt_right.text(text.slice(1));
}
} else if (!this.$prompt_after.is(EMPTY_SELECTOR)) {
$lower_line = this.$prompt_after.children().first().detach();
return this.$prompt_right.text($lower_line.children().last().text());
}
};
JQConsole.prototype._Backspace = function(whole_word) {
var $upper_line, text, word;
setTimeout($.proxy(this._ScrollToEnd, this), 0);
text = this.$prompt_left.text();
if (text) {
if (whole_word) {
word = text.match(/\w*\W*$/);
if (!word) {
return;
}
word = word[0];
return this.$prompt_left.text(text.slice(0, -word.length));
} else {
return this.$prompt_left.text(text.slice(0, -1));
}
} else if (!this.$prompt_before.is(EMPTY_SELECTOR)) {
$upper_line = this.$prompt_before.children().last().detach();
this.$prompt_label.text($upper_line.children().first().text());
return this.$prompt_left.text($upper_line.children().last().text());
}
};
JQConsole.prototype._Indent = function() {
var _;
return this.$prompt_left.prepend(((function() {
var _i, _ref, _results;
_results = [];
for (_ = _i = 1, _ref = this.indent_width; 1 <= _ref ? _i <= _ref : _i >= _ref; _ = 1 <= _ref ? ++_i : --_i) {
_results.push(' ');
}
return _results;
}).call(this)).join(''));
};
JQConsole.prototype._Unindent = function() {
var line_text, _, _i, _ref, _results;
line_text = this.$prompt_left.text() + this.$prompt_right.text();
_results = [];
for (_ = _i = 1, _ref = this.indent_width; 1 <= _ref ? _i <= _ref : _i >= _ref; _ = 1 <= _ref ? ++_i : --_i) {
if (!/^ /.test(line_text)) {
break;
}
if (this.$prompt_left.text()) {
this.$prompt_left.text(this.$prompt_left.text().slice(1));
} else {
this.$prompt_right.text(this.$prompt_right.text().slice(1));
}
_results.push(line_text = line_text.slice(1));
}
return _results;
};
JQConsole.prototype._InsertNewLine = function(indent) {
var $old_line, match, old_prompt;
if (indent == null) {
indent = false;
}
old_prompt = this._SelectPromptLabel(!this.$prompt_before.is(EMPTY_SELECTOR));
$old_line = $(EMPTY_SPAN).appendTo(this.$prompt_before);
$old_line.append($(EMPTY_SPAN).text(old_prompt));
$old_line.append($(EMPTY_SPAN).text(this.$prompt_left.text()));
this.$prompt_label.text(this._SelectPromptLabel(true));
if (indent && (match = this.$prompt_left.text().match(/^\s+/))) {
this.$prompt_left.text(match[0]);
} else {
this.$prompt_left.text('');
}
return this._ScrollToEnd();
};
JQConsole.prototype._AppendPromptText = function(text) {
var line, lines, _i, _len, _ref, _results;
lines = text.split(NEWLINE);
this.$prompt_left.text(this.$prompt_left.text() + lines[0]);
_ref = lines.slice(1);
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
line = _ref[_i];
this._InsertNewLine();
_results.push(this.$prompt_left.text(line));
}
return _results;
};
JQConsole.prototype._ScrollPage = function(dir) {
var target;
target = this.$container[0].scrollTop;
if (dir === 'up') {
target -= this.$container.height();
} else {
target += this.$container.height();
}
return this.$container.stop().animate({
scrollTop: target
}, 'fast');
};
JQConsole.prototype._ScrollToEnd = function() {
var pos;
this.$container.scrollTop(this.$container[0].scrollHeight);
pos = this.$prompt_cursor.position();
this.$input_container.css({
left: pos.left,
top: pos.top
});
return setTimeout(this.ScrollWindowToPrompt.bind(this), 50);
};
JQConsole.prototype.ScrollWindowToPrompt = function() {
var doc_height, line_height, optimal_pos, pos, screen_left, screen_top;
line_height = this.$prompt_cursor.height();
screen_top = this.$window.scrollTop();
screen_left = this.$window.scrollLeft();
doc_height = document.documentElement.clientHeight;
pos = this.$prompt_cursor.offset();
optimal_pos = pos.top - (2 * line_height);
if (this.isMobile && (typeof orientation !== "undefined" && orientation !== null)) {
if (screen_top < pos.top || screen_top > pos.top) {
return this.$window.scrollTop(optimal_pos);
}
} else {
if (screen_top + doc_height < pos.top) {
return this.$window.scrollTop(pos.top - doc_height + line_height);
} else if (screen_top > optimal_pos) {
return this.$window.scrollTop(pos.top);
}
}
};
JQConsole.prototype._SelectPromptLabel = function(continuation) {
if (this.state === STATE_PROMPT) {
if (continuation) {
return ' \n' + this.prompt_label_continue;
} else {
return this.prompt_label_main;
}
} else {
if (continuation) {
return '\n ';
} else {
return ' ';
}
}
};
JQConsole.prototype._Wrap = function($elem, index, cls) {
var html, text;
text = $elem.html();
html = text.slice(0, index) + spanHtml(cls, text[index]) + text.slice(index + 1);
return $elem.html(html);
};
JQConsole.prototype._WalkCharacters = function(text, char, opposing_char, current_count, back) {
var ch, index, read_char;
index = back ? text.length : 0;
text = text.split('');
read_char = function() {
var ret, _i, _ref, _ref1;
if (back) {
_ref = text, text = 2 <= _ref.length ? __slice.call(_ref, 0, _i = _ref.length - 1) : (_i = 0, []), ret = _ref[_i++];
} else {
_ref1 = text, ret = _ref1[0], text = 2 <= _ref1.length ? __slice.call(_ref1, 1) : [];
}
if (ret) {
index = index + (back ? -1 : +1);
}
return ret;
};
while (ch = read_char()) {
if (ch === char) {
current_count++;
} else if (ch === opposing_char) {
current_count--;
}
if (current_count === 0) {
return {
index: index,
current_count: current_count
};
}
}
return {
index: -1,
current_count: current_count
};
};
JQConsole.prototype._ProcessMatch = function(config, back, before_char) {
var $collection, $prompt_relative, $prompt_which, char, current_count, found, index, opposing_char, text, _ref, _ref1, _ref2,
_this = this;
_ref = back ? [config['closing_char'], config['opening_char']] : [config['opening_char'], config['closing_char']], char = _ref[0], opposing_char = _ref[1];
_ref1 = this._GetDirectionals(back), $prompt_which = _ref1.$prompt_which, $prompt_relative = _ref1.$prompt_relative;
current_count = 1;
found = false;
text = $prompt_which.html();
if (!back) {
text = text.slice(1);
}
if (before_char && back) {
text = text.slice(0, -1);
}
_ref2 = this._WalkCharacters(text, char, opposing_char, current_count, back), index = _ref2.index, current_count = _ref2.current_count;
if (index > -1) {
this._Wrap($prompt_which, index, config.cls);
found = true;
} else {
$collection = $prompt_relative.children();
$collection = back ? Array.prototype.reverse.call($collection) : $collection;
$collection.each(function(i, elem) {
var $elem, _ref3;
$elem = $(elem).children().last();
text = $elem.html();
_ref3 = _this._WalkCharacters(text, char, opposing_char, current_count, back), index = _ref3.index, current_count = _ref3.current_count;
if (index > -1) {
if (!back) {
index--;
}
_this._Wrap($elem, index, config.cls);
found = true;
return false;
}
});
}
return found;
};
JQConsole.prototype._CheckMatchings = function(before_char) {
var cls, config, current_char, found, _i, _len, _ref;
current_char = before_char ? this.$prompt_left.text().slice(this.$prompt_left.text().length - 1) : this.$prompt_right.text()[0];
_ref = this.matchings.clss;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
cls = _ref[_i];
$('.' + cls, this.$console).contents().unwrap();
}
if (config = this.matchings.closings[current_char]) {
found = this._ProcessMatch(config, true, before_char);
} else if (config = this.matchings.openings[current_char]) {
found = this._ProcessMatch(config, false, before_char);
} else if (!before_char) {
this._CheckMatchings(true);
}
if (before_char) {
if (found) {
return this._Wrap(this.$prompt_left, this.$prompt_left.html().length - 1, config.cls);
}
} else {
if (found) {
return this._Wrap(this.$prompt_right, 0, config.cls);
}
}
};
JQConsole.prototype._HistoryPrevious = function() {
if (!this.history_active) {
return;
}
if (this.history_index <= 0) {
return;
}
if (this.history_index === this.history.length) {
this.history_new = this.GetPromptText();
}
return this.SetPromptText(this.history[--this.history_index]);
};
JQConsole.prototype._HistoryNext = function() {
if (!this.history_active) {
return;
}
if (this.history_index >= this.history.length) {
return;
}
if (this.history_index === this.history.length - 1) {
this.history_index++;
return this.SetPromptText(this.history_new);
} else {
return this.SetPromptText(this.history[++this.history_index]);
}
};
JQConsole.prototype._CheckComposition = function(e) {
var key;
key = e.keyCode || e.which;
if (key === 229) {
if (this.in_composition) {
return this._UpdateComposition();
} else {
return this._StartComposition();
}
}
};
JQConsole.prototype._StartComposition = function() {
if (this.in_composition) {
return;
}
this.in_composition = true;
this._ShowComposition();
return setTimeout(this._UpdateComposition, 0);
};
JQConsole.prototype._EndComposition = function() {
if (!this.in_composition) {
return;
}
this._HideComposition();
this.$prompt_left.text(this.$prompt_left.text() + this.$composition.text());
this.$composition.text('');
this.$input_source.val('');
return this.in_composition = false;
};
JQConsole.prototype._UpdateComposition = function(e) {
var cb,
_this = this;
cb = function() {
if (!_this.in_composition) {
return;
}
return _this.$composition.text(_this.$input_source.val());
};
return setTimeout(cb, 0);
};
JQConsole.prototype._ShowComposition = function() {
this.$composition.css('height', this.$prompt_cursor.height());
this.$composition.empty();
return this.$composition.appendTo(this.$prompt_left);
};
JQConsole.prototype._HideComposition = function() {
return this.$composition.detach();
};
return JQConsole;
})();
$.fn.jqconsole = function(header, prompt_main, prompt_continue) {
return new JQConsole(this, header, prompt_main, prompt_continue);
};
$.fn.jqconsole.JQConsole = JQConsole;
$.fn.jqconsole.Ansi = Ansi;
}).call(this);