mirror of
https://github.com/paradoxxxzero/butterfly.git
synced 2026-05-26 15:13:36 +00:00
Insert mode + coding style
This commit is contained in:
@@ -23,15 +23,18 @@
|
||||
/* THIS NEEDS the python `libsass` library to be installed.
|
||||
/* You can also copy the imported files in those dirs, they will be imported prioritarily.
|
||||
|
||||
@import font /* You can change this file to import any webfont
|
||||
/* You can change this file to import any webfont:
|
||||
@import font
|
||||
|
||||
/* You can comment / uncomment the following to enable/disable terminal effects.
|
||||
@import light_fx
|
||||
@import text_fx /* Comment this one to remove the blurry text
|
||||
/* Comment this one to remove the blurry text:
|
||||
@import text_fx
|
||||
/* @import all_fx
|
||||
|
||||
@import colors
|
||||
@import 16_colors /* The color theme is defined in this one
|
||||
/* The color theme is defined in this one:
|
||||
@import 16_colors
|
||||
@import 256_colors
|
||||
|
||||
@import layout
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
(function() {
|
||||
var Selection, alt, cancel, copy, ctrl, first, next_leaf, previous_leaf, selection, set_alarm, virtual_input,
|
||||
var Selection, alt, cancel, copy, ctrl, first, nextLeaf, previousLeaf, selection, setAlarm, virtualInput,
|
||||
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
|
||||
|
||||
set_alarm = function(notification) {
|
||||
setAlarm = function(notification) {
|
||||
var alarm;
|
||||
alarm = function(data) {
|
||||
var note;
|
||||
@@ -39,10 +39,10 @@
|
||||
}
|
||||
if (Notification && Notification.permission === 'default') {
|
||||
Notification.requestPermission(function() {
|
||||
return set_alarm(Notification.permission === 'granted');
|
||||
return setAlarm(Notification.permission === 'granted');
|
||||
});
|
||||
} else {
|
||||
set_alarm(Notification.permission === 'granted');
|
||||
setAlarm(Notification.permission === 'granted');
|
||||
}
|
||||
return cancel(e);
|
||||
});
|
||||
@@ -90,7 +90,7 @@
|
||||
return false;
|
||||
};
|
||||
|
||||
previous_leaf = function(node) {
|
||||
previousLeaf = function(node) {
|
||||
var previous;
|
||||
previous = node.previousSibling;
|
||||
if (!previous) {
|
||||
@@ -105,7 +105,7 @@
|
||||
return previous;
|
||||
};
|
||||
|
||||
next_leaf = function(node) {
|
||||
nextLeaf = function(node) {
|
||||
var next;
|
||||
next = node.nextSibling;
|
||||
if (!next) {
|
||||
@@ -127,11 +127,11 @@
|
||||
}
|
||||
|
||||
Selection.prototype.reset = function() {
|
||||
var fake_range, ref, results;
|
||||
var fakeRange, ref, results;
|
||||
this.selection = getSelection();
|
||||
fake_range = document.createRange();
|
||||
fake_range.setStart(this.selection.anchorNode, this.selection.anchorOffset);
|
||||
fake_range.setEnd(this.selection.focusNode, this.selection.focusOffset);
|
||||
fakeRange = document.createRange();
|
||||
fakeRange.setStart(this.selection.anchorNode, this.selection.anchorOffset);
|
||||
fakeRange.setEnd(this.selection.focusNode, this.selection.focusOffset);
|
||||
this.start = {
|
||||
node: this.selection.anchorNode,
|
||||
offset: this.selection.anchorOffset
|
||||
@@ -140,17 +140,17 @@
|
||||
node: this.selection.focusNode,
|
||||
offset: this.selection.focusOffset
|
||||
};
|
||||
if (fake_range.collapsed) {
|
||||
if (fakeRange.collapsed) {
|
||||
ref = [this.end, this.start], this.start = ref[0], this.end = ref[1];
|
||||
}
|
||||
this.start_line = this.start.node;
|
||||
while (!this.start_line.classList || indexOf.call(this.start_line.classList, 'line') < 0) {
|
||||
this.start_line = this.start_line.parentNode;
|
||||
this.startLine = this.start.node;
|
||||
while (!this.startLine.classList || indexOf.call(this.startLine.classList, 'line') < 0) {
|
||||
this.startLine = this.startLine.parentNode;
|
||||
}
|
||||
this.end_line = this.end.node;
|
||||
this.endLine = this.end.node;
|
||||
results = [];
|
||||
while (!this.end_line.classList || indexOf.call(this.end_line.classList, 'line') < 0) {
|
||||
results.push(this.end_line = this.end_line.parentNode);
|
||||
while (!this.endLine.classList || indexOf.call(this.endLine.classList, 'line') < 0) {
|
||||
results.push(this.endLine = this.endLine.parentNode);
|
||||
}
|
||||
return results;
|
||||
};
|
||||
@@ -178,7 +178,7 @@
|
||||
|
||||
Selection.prototype.go = function(n) {
|
||||
var index;
|
||||
index = butterfly.children.indexOf(this.start_line) + n;
|
||||
index = butterfly.children.indexOf(this.startLine) + n;
|
||||
if (!((0 <= index && index < butterfly.children.length))) {
|
||||
return;
|
||||
}
|
||||
@@ -188,7 +188,7 @@
|
||||
return;
|
||||
}
|
||||
}
|
||||
return this.select_line(index);
|
||||
return this.selectLine(index);
|
||||
};
|
||||
|
||||
Selection.prototype.apply = function() {
|
||||
@@ -200,30 +200,30 @@
|
||||
return this.selection.addRange(range);
|
||||
};
|
||||
|
||||
Selection.prototype.select_line = function(index) {
|
||||
var line, line_end, line_start;
|
||||
Selection.prototype.selectLine = function(index) {
|
||||
var line, lineEnd, lineStart;
|
||||
line = butterfly.children[index];
|
||||
line_start = {
|
||||
lineStart = {
|
||||
node: line.firstChild,
|
||||
offset: 0
|
||||
};
|
||||
line_end = {
|
||||
lineEnd = {
|
||||
node: line.lastChild,
|
||||
offset: line.lastChild.textContent.length
|
||||
};
|
||||
this.start = this.walk(line_start, /\S/);
|
||||
return this.end = this.walk(line_end, /\S/, true);
|
||||
this.start = this.walk(lineStart, /\S/);
|
||||
return this.end = this.walk(lineEnd, /\S/, true);
|
||||
};
|
||||
|
||||
Selection.prototype.collapsed = function(start, end) {
|
||||
var fake_range;
|
||||
fake_range = document.createRange();
|
||||
fake_range.setStart(start.node, start.offset);
|
||||
fake_range.setEnd(end.node, end.offset);
|
||||
return fake_range.collapsed;
|
||||
var fakeRange;
|
||||
fakeRange = document.createRange();
|
||||
fakeRange.setStart(start.node, start.offset);
|
||||
fakeRange.setEnd(end.node, end.offset);
|
||||
return fakeRange.collapsed;
|
||||
};
|
||||
|
||||
Selection.prototype.shrink_right = function() {
|
||||
Selection.prototype.shrinkRight = function() {
|
||||
var end, node;
|
||||
node = this.walk(this.end, /\s/, true);
|
||||
end = this.walk(node, /\S/, true);
|
||||
@@ -232,7 +232,7 @@
|
||||
}
|
||||
};
|
||||
|
||||
Selection.prototype.shrink_left = function() {
|
||||
Selection.prototype.shrinkLeft = function() {
|
||||
var node, start;
|
||||
node = this.walk(this.start, /\s/);
|
||||
start = this.walk(node, /\S/);
|
||||
@@ -241,13 +241,13 @@
|
||||
}
|
||||
};
|
||||
|
||||
Selection.prototype.expand_right = function() {
|
||||
Selection.prototype.expandRight = function() {
|
||||
var node;
|
||||
node = this.walk(this.end, /\S/);
|
||||
return this.end = this.walk(node, /\s/);
|
||||
};
|
||||
|
||||
Selection.prototype.expand_left = function() {
|
||||
Selection.prototype.expandLeft = function() {
|
||||
var node;
|
||||
node = this.walk(this.start, /\S/, true);
|
||||
return this.start = this.walk(node, /\s/, true);
|
||||
@@ -275,7 +275,7 @@
|
||||
};
|
||||
}
|
||||
}
|
||||
node = previous_leaf(node);
|
||||
node = previousLeaf(node);
|
||||
text = node.textContent;
|
||||
i = text.length;
|
||||
}
|
||||
@@ -289,7 +289,7 @@
|
||||
};
|
||||
}
|
||||
}
|
||||
node = next_leaf(node);
|
||||
node = nextLeaf(node);
|
||||
text = node.textContent;
|
||||
i = 0;
|
||||
}
|
||||
@@ -323,13 +323,13 @@
|
||||
selection.down();
|
||||
}
|
||||
} else if (e.keyCode === 39) {
|
||||
selection.shrink_left();
|
||||
selection.shrinkLeft();
|
||||
} else if (e.keyCode === 38) {
|
||||
selection.expand_left();
|
||||
selection.expandLeft();
|
||||
} else if (e.keyCode === 37) {
|
||||
selection.shrink_right();
|
||||
selection.shrinkRight();
|
||||
} else if (e.keyCode === 40) {
|
||||
selection.expand_right();
|
||||
selection.expandRight();
|
||||
} else {
|
||||
return cancel(e);
|
||||
}
|
||||
@@ -340,7 +340,7 @@
|
||||
}
|
||||
if (!selection && e.ctrlKey && e.shiftKey && e.keyCode === 38) {
|
||||
selection = new Selection();
|
||||
selection.select_line(butterfly.y - 1);
|
||||
selection.selectLine(butterfly.y - 1);
|
||||
selection.apply();
|
||||
return cancel(e);
|
||||
}
|
||||
@@ -369,7 +369,7 @@
|
||||
});
|
||||
|
||||
document.addEventListener('dblclick', function(e) {
|
||||
var anchorNode, anchorOffset, new_range, range, sel;
|
||||
var anchorNode, anchorOffset, newRange, range, sel;
|
||||
if (e.ctrlKey || e.altkey) {
|
||||
return;
|
||||
}
|
||||
@@ -382,10 +382,10 @@
|
||||
range.setEnd(sel.focusNode, sel.focusOffset);
|
||||
if (range.collapsed) {
|
||||
sel.removeAllRanges();
|
||||
new_range = document.createRange();
|
||||
new_range.setStart(sel.focusNode, sel.focusOffset);
|
||||
new_range.setEnd(sel.anchorNode, sel.anchorOffset);
|
||||
sel.addRange(new_range);
|
||||
newRange = document.createRange();
|
||||
newRange.setStart(sel.focusNode, sel.focusOffset);
|
||||
newRange.setEnd(sel.anchorNode, sel.anchorOffset);
|
||||
sel.addRange(newRange);
|
||||
}
|
||||
while (!(sel.toString().match(/\s/) || !sel.toString())) {
|
||||
sel.modify('extend', 'forward', 'character');
|
||||
@@ -405,17 +405,17 @@
|
||||
ctrl = false;
|
||||
alt = false;
|
||||
first = true;
|
||||
virtual_input = document.createElement('input');
|
||||
virtual_input.type = 'password';
|
||||
virtual_input.style.position = 'fixed';
|
||||
virtual_input.style.top = 0;
|
||||
virtual_input.style.left = 0;
|
||||
virtual_input.style.border = 'none';
|
||||
virtual_input.style.outline = 'none';
|
||||
virtual_input.style.opacity = 0;
|
||||
virtual_input.value = '0';
|
||||
document.body.appendChild(virtual_input);
|
||||
virtual_input.addEventListener('blur', function() {
|
||||
virtualInput = document.createElement('input');
|
||||
virtualInput.type = 'password';
|
||||
virtualInput.style.position = 'fixed';
|
||||
virtualInput.style.top = 0;
|
||||
virtualInput.style.left = 0;
|
||||
virtualInput.style.border = 'none';
|
||||
virtualInput.style.outline = 'none';
|
||||
virtualInput.style.opacity = 0;
|
||||
virtualInput.value = '0';
|
||||
document.body.appendChild(virtualInput);
|
||||
virtualInput.addEventListener('blur', function() {
|
||||
return setTimeout(((function(_this) {
|
||||
return function() {
|
||||
return _this.focus();
|
||||
@@ -423,7 +423,7 @@
|
||||
})(this)), 10);
|
||||
});
|
||||
addEventListener('click', function() {
|
||||
return virtual_input.focus();
|
||||
return virtualInput.focus();
|
||||
});
|
||||
addEventListener('touchstart', function(e) {
|
||||
if (e.touches.length === 2) {
|
||||
@@ -436,11 +436,11 @@
|
||||
return alt = true;
|
||||
}
|
||||
});
|
||||
virtual_input.addEventListener('keydown', function(e) {
|
||||
virtualInput.addEventListener('keydown', function(e) {
|
||||
butterfly.keyDown(e);
|
||||
return true;
|
||||
});
|
||||
virtual_input.addEventListener('input', function(e) {
|
||||
virtualInput.addEventListener('input', function(e) {
|
||||
var len;
|
||||
len = this.value.length;
|
||||
if (len === 0) {
|
||||
|
||||
2
butterfly/static/ext.min.js
vendored
2
butterfly/static/ext.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -11,6 +11,12 @@
|
||||
/* 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, see <http://www.gnu.org/licenses/>. */
|
||||
/* Theses are the various imported style files */
|
||||
/* You can put this file in /etc/butterfly/style.sass or ~/.butterfly/style.sass */
|
||||
/* To customize the style of your terminal. */
|
||||
/* THIS NEEDS the python `libsass` library to be installed. */
|
||||
/* You can also copy the imported files in those dirs, they will be imported prioritarily. */
|
||||
/* You can change this file to import any webfont: */
|
||||
/* *-* coding: utf-8 *-* */
|
||||
/* This file is part of butterfly */
|
||||
/* butterfly Copyright (C) 2014 Florian Mounier */
|
||||
@@ -63,6 +69,7 @@ body {
|
||||
font-family: "SourceCodePro";
|
||||
line-height: 1.2; }
|
||||
|
||||
/* You can comment / uncomment the following to enable/disable terminal effects. */
|
||||
/* *-* coding: utf-8 *-* */
|
||||
/* This file is part of butterfly */
|
||||
/* butterfly Copyright (C) 2014 Florian Mounier */
|
||||
@@ -116,14 +123,11 @@ body {
|
||||
body.locked::-webkit-scrollbar-thumb:hover {
|
||||
background: rgba(255, 0, 0, 0.8); }
|
||||
|
||||
/* Comment this one to remove the blurry text: */
|
||||
body {
|
||||
text-shadow: 0 0 6px rgba(255, 255, 255, 0.5); }
|
||||
|
||||
body.copied {
|
||||
transform: scale(1.05); }
|
||||
body.pasted {
|
||||
transform: scale(.95); }
|
||||
|
||||
/* @import all_fx */
|
||||
/* *-* coding: utf-8 *-* */
|
||||
/* This file is part of butterfly */
|
||||
/* butterfly Copyright (C) 2014 Florian Mounier */
|
||||
@@ -144,6 +148,7 @@ html, body {
|
||||
background-color: #110f13;
|
||||
color: #f4ead5; }
|
||||
|
||||
/* The color theme is defined in this one: */
|
||||
/* *-* coding: utf-8 *-* */
|
||||
/* This file is part of butterfly */
|
||||
/* butterfly Copyright (C) 2014 Florian Mounier */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
(function() {
|
||||
var $, State, Terminal, cancel, cols, open_ts, quit, rows, s,
|
||||
var $, State, Terminal, cancel, cols, openTs, quit, rows, s,
|
||||
slice = [].slice,
|
||||
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
|
||||
|
||||
@@ -7,12 +7,12 @@
|
||||
|
||||
quit = false;
|
||||
|
||||
open_ts = (new Date()).getTime();
|
||||
openTs = (new Date()).getTime();
|
||||
|
||||
$ = document.querySelectorAll.bind(document);
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var ctl, last_data, queue, send, t_queue, term, treat, ws, ws_url;
|
||||
var ctl, lastData, queue, send, t_queue, term, treat, ws, wsUrl;
|
||||
send = function(data) {
|
||||
return ws.send('S' + data);
|
||||
};
|
||||
@@ -25,21 +25,21 @@
|
||||
}
|
||||
};
|
||||
if (location.protocol === 'https:') {
|
||||
ws_url = 'wss://';
|
||||
wsUrl = 'wss://';
|
||||
} else {
|
||||
ws_url = 'ws://';
|
||||
wsUrl = 'ws://';
|
||||
}
|
||||
ws_url += document.location.host + '/ws' + location.pathname;
|
||||
ws = new WebSocket(ws_url);
|
||||
wsUrl += document.location.host + '/ws' + location.pathname;
|
||||
ws = new WebSocket(wsUrl);
|
||||
ws.addEventListener('open', function() {
|
||||
console.log("WebSocket open", arguments);
|
||||
ws.send('R' + term.cols + ',' + term.rows);
|
||||
return open_ts = (new Date()).getTime();
|
||||
return openTs = (new Date()).getTime();
|
||||
});
|
||||
ws.addEventListener('error', function() {
|
||||
return console.log("WebSocket error", arguments);
|
||||
});
|
||||
last_data = '';
|
||||
lastData = '';
|
||||
t_queue = null;
|
||||
queue = '';
|
||||
ws.addEventListener('message', function(e) {
|
||||
@@ -50,7 +50,7 @@
|
||||
if (term.stop) {
|
||||
queue = queue.slice(-10 * 1024);
|
||||
}
|
||||
if (queue.length > term.buff_size) {
|
||||
if (queue.length > term.buffSize) {
|
||||
return treat();
|
||||
} else {
|
||||
return t_queue = setTimeout(treat, 1);
|
||||
@@ -72,7 +72,7 @@
|
||||
return term.body.classList.add('dead');
|
||||
}, 1);
|
||||
quit = true;
|
||||
if ((new Date()).getTime() - open_ts > 60 * 1000) {
|
||||
if ((new Date()).getTime() - openTs > 60 * 1000) {
|
||||
return open('', '_self').close();
|
||||
}
|
||||
});
|
||||
@@ -148,8 +148,8 @@
|
||||
this.ctl = ctl1 != null ? ctl1 : function() {};
|
||||
this.document = this.parent.ownerDocument;
|
||||
this.body = this.document.getElementsByTagName('body')[0];
|
||||
this.html_escapes_enabled = this.body.getAttribute('data-allow-html') === 'yes';
|
||||
this.force_width = this.body.getAttribute('data-force-unicode-width') === 'yes';
|
||||
this.htmlEscapesEnabled = this.body.getAttribute('data-allow-html') === 'yes';
|
||||
this.forceWidth = this.body.getAttribute('data-force-unicode-width') === 'yes';
|
||||
this.body.className = 'terminal focus';
|
||||
this.body.style.outline = 'none';
|
||||
this.body.setAttribute('tabindex', 0);
|
||||
@@ -158,21 +158,21 @@
|
||||
div.className = 'line';
|
||||
this.body.appendChild(div);
|
||||
this.children = [div];
|
||||
this.compute_char_size();
|
||||
this.cols = Math.floor(this.body.clientWidth / this.char_size.width);
|
||||
this.rows = Math.floor(window.innerHeight / this.char_size.height);
|
||||
px = window.innerHeight % this.char_size.height;
|
||||
this.computeCharSize();
|
||||
this.cols = Math.floor(this.body.clientWidth / this.charSize.width);
|
||||
this.rows = Math.floor(window.innerHeight / this.charSize.height);
|
||||
px = window.innerHeight % this.charSize.height;
|
||||
this.body.style['padding-bottom'] = px + "px";
|
||||
this.scrollback = 1000000;
|
||||
this.buff_size = 100000;
|
||||
this.buffSize = 100000;
|
||||
this.visualBell = 100;
|
||||
this.convertEol = false;
|
||||
this.termName = 'xterm';
|
||||
this.cursorBlink = true;
|
||||
this.cursorState = 0;
|
||||
this.stop = false;
|
||||
this.last_cc = 0;
|
||||
this.reset_vars();
|
||||
this.lastcc = 0;
|
||||
this.resetVars();
|
||||
this.focus();
|
||||
this.startBlink();
|
||||
addEventListener('keydown', this.keyDown.bind(this));
|
||||
@@ -211,7 +211,17 @@
|
||||
return a.bg === b.bg && a.fg === b.fg && a.bold === b.bold && a.underline === b.underline && a.blink === b.blink && a.inverse === b.inverse && a.invisible === b.invisible;
|
||||
};
|
||||
|
||||
Terminal.prototype.reset_vars = function() {
|
||||
Terminal.prototype.putChar = function(c) {
|
||||
if (this.insertMode) {
|
||||
this.screen[this.y + this.shift][0].splice(this.x, 0, this.cloneAttr(this.curAttr, c));
|
||||
this.screen[this.y + this.shift][0].pop();
|
||||
} else {
|
||||
this.screen[this.y + this.shift][0][this.x] = this.cloneAttr(this.curAttr, c);
|
||||
}
|
||||
return this.screen[this.y + this.shift][1] = true;
|
||||
};
|
||||
|
||||
Terminal.prototype.resetVars = function() {
|
||||
var i;
|
||||
this.x = 0;
|
||||
this.y = 0;
|
||||
@@ -248,22 +258,22 @@
|
||||
i = this.rows;
|
||||
this.shift = 0;
|
||||
while (i--) {
|
||||
this.screen.push([this.blank_line(), true]);
|
||||
this.screen.push([this.blankLine(), true]);
|
||||
}
|
||||
this.setupStops();
|
||||
return this.skipNextKey = null;
|
||||
};
|
||||
|
||||
Terminal.prototype.compute_char_size = function() {
|
||||
var test_span;
|
||||
test_span = document.createElement('span');
|
||||
test_span.textContent = '0123456789';
|
||||
this.children[0].appendChild(test_span);
|
||||
this.char_size = {
|
||||
width: test_span.getBoundingClientRect().width / 10,
|
||||
Terminal.prototype.computeCharSize = function() {
|
||||
var testSpan;
|
||||
testSpan = document.createElement('span');
|
||||
testSpan.textContent = '0123456789';
|
||||
this.children[0].appendChild(testSpan);
|
||||
this.charSize = {
|
||||
width: testSpan.getBoundingClientRect().width / 10,
|
||||
height: this.children[0].getBoundingClientRect().height
|
||||
};
|
||||
return this.children[0].removeChild(test_span);
|
||||
return this.children[0].removeChild(testSpan);
|
||||
};
|
||||
|
||||
Terminal.prototype.eraseAttr = function() {
|
||||
@@ -474,7 +484,7 @@
|
||||
};
|
||||
|
||||
Terminal.prototype.refresh = function(force) {
|
||||
var attr, ch, classes, cursor, data, dirty, fg, group, i, j, k, len, len1, len2, len3, line, lines, m, new_out, o, out, q, ref, ref1, ref2, ref3, ref4, ref5, skipnext, styles, u, x;
|
||||
var attr, ch, classes, cursor, data, dirty, fg, group, i, j, k, len, len1, len2, len3, line, lines, m, newOut, o, out, q, ref, ref1, ref2, ref3, ref4, ref5, skipnext, styles, u, x;
|
||||
if (force == null) {
|
||||
force = false;
|
||||
}
|
||||
@@ -483,7 +493,7 @@
|
||||
cursor = ref[k];
|
||||
cursor.parentNode.replaceChild(this.document.createTextNode(cursor.textContent), cursor);
|
||||
}
|
||||
new_out = '';
|
||||
newOut = '';
|
||||
ref1 = this.screen;
|
||||
for (j = m = 0, len1 = ref1.length; m < len1; j = ++m) {
|
||||
ref2 = ref1[j], line = ref2[0], dirty = ref2[1];
|
||||
@@ -578,13 +588,13 @@
|
||||
out += '<span class="nbsp">\u2007</span>';
|
||||
} else if (ch <= " ") {
|
||||
out += " ";
|
||||
} else if (!this.force_width || ch <= "~") {
|
||||
} else if (!this.forceWidth || ch <= "~") {
|
||||
out += ch;
|
||||
} else if (("\uff00" < ch && ch < "\uffef")) {
|
||||
skipnext = true;
|
||||
out += "<span style=\"display: inline-block; width: " + (2 * this.char_size.width) + "px\">" + ch + "</span>";
|
||||
out += "<span style=\"display: inline-block; width: " + (2 * this.charSize.width) + "px\">" + ch + "</span>";
|
||||
} else {
|
||||
out += "<span style=\"display: inline-block; width: " + this.char_size.width + "px\">" + ch + "</span>";
|
||||
out += "<span style=\"display: inline-block; width: " + this.charSize.width + "px\">" + ch + "</span>";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -599,14 +609,14 @@
|
||||
if (this.children[j]) {
|
||||
this.children[j].innerHTML = out;
|
||||
} else {
|
||||
new_out += "<div class=\"line\">" + out + "</div>";
|
||||
newOut += "<div class=\"line\">" + out + "</div>";
|
||||
}
|
||||
this.screen[j][1] = false;
|
||||
}
|
||||
if (new_out !== '') {
|
||||
if (newOut !== '') {
|
||||
group = this.document.createElement('div');
|
||||
group.className = 'group';
|
||||
group.innerHTML = new_out;
|
||||
group.innerHTML = newOut;
|
||||
this.body.appendChild(group);
|
||||
this.screen = this.screen.slice(-this.rows);
|
||||
this.shift = 0;
|
||||
@@ -627,7 +637,7 @@
|
||||
this.children = Array.prototype.slice.call(lines, -this.rows);
|
||||
}
|
||||
if (!this.scrollLock) {
|
||||
return this.native_scroll_to();
|
||||
return this.nativeScrollTo();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -676,7 +686,7 @@
|
||||
Terminal.prototype.scroll = function() {
|
||||
var i, k, ref, ref1, results;
|
||||
if (this.normal || this.scrollTop !== 0 || this.scrollBottom !== this.rows - 1) {
|
||||
this.screen.splice(this.shift + this.scrollBottom + 1, 0, [this.blank_line(), true]);
|
||||
this.screen.splice(this.shift + this.scrollBottom + 1, 0, [this.blankLine(), true]);
|
||||
this.screen.splice(this.shift + this.scrollTop, 1);
|
||||
results = [];
|
||||
for (i = k = ref = this.scrollTop, ref1 = this.scrollBottom; ref <= ref1 ? k <= ref1 : k >= ref1; i = ref <= ref1 ? ++k : --k) {
|
||||
@@ -684,14 +694,14 @@
|
||||
}
|
||||
return results;
|
||||
} else {
|
||||
this.screen.push([this.blank_line(), true]);
|
||||
this.screen.push([this.blankLine(), true]);
|
||||
return this.shift++;
|
||||
}
|
||||
};
|
||||
|
||||
Terminal.prototype.unscroll = function() {
|
||||
var i, k, ref, ref1, results;
|
||||
this.screen.splice(this.shift + this.scrollTop, 0, [this.blank_line(true), true]);
|
||||
this.screen.splice(this.shift + this.scrollTop, 0, [this.blankLine(true), true]);
|
||||
this.screen.splice(this.shift + this.scrollBottom + 1, 1);
|
||||
results = [];
|
||||
for (i = k = ref = this.scrollTop, ref1 = this.scrollBottom; ref <= ref1 ? k <= ref1 : k >= ref1; i = ref <= ref1 ? ++k : --k) {
|
||||
@@ -700,18 +710,18 @@
|
||||
return results;
|
||||
};
|
||||
|
||||
Terminal.prototype.native_scroll_to = function(scroll) {
|
||||
Terminal.prototype.nativeScrollTo = function(scroll) {
|
||||
if (scroll == null) {
|
||||
scroll = 2000000000;
|
||||
}
|
||||
return window.scrollTo(0, scroll);
|
||||
};
|
||||
|
||||
Terminal.prototype.scroll_display = function(disp) {
|
||||
return this.native_scroll_to(window.scrollY + disp * this.char_size.height);
|
||||
Terminal.prototype.scrollDisplay = function(disp) {
|
||||
return this.nativeScrollTo(window.scrollY + disp * this.charSize.height);
|
||||
};
|
||||
|
||||
Terminal.prototype.next_line = function() {
|
||||
Terminal.prototype.nextLine = function() {
|
||||
this.y++;
|
||||
if (this.y > this.scrollBottom) {
|
||||
this.y--;
|
||||
@@ -719,7 +729,7 @@
|
||||
}
|
||||
};
|
||||
|
||||
Terminal.prototype.prev_line = function() {
|
||||
Terminal.prototype.prevLine = function() {
|
||||
this.y--;
|
||||
if (this.y < this.scrollTop) {
|
||||
this.y++;
|
||||
@@ -742,7 +752,7 @@
|
||||
case "\n":
|
||||
case "\x0b":
|
||||
case "\x0c":
|
||||
this.next_line();
|
||||
this.nextLine();
|
||||
break;
|
||||
case "\r":
|
||||
this.x = 0;
|
||||
@@ -770,22 +780,18 @@
|
||||
ch = this.charset[ch];
|
||||
}
|
||||
if (this.x >= this.cols) {
|
||||
this.screen[this.y + this.shift][0][this.x] = this.cloneAttr(this.curAttr, '\u23CE');
|
||||
this.screen[this.y + this.shift][1] = true;
|
||||
this.putChar('\u23CE');
|
||||
this.x = 0;
|
||||
this.next_line();
|
||||
this.nextLine();
|
||||
}
|
||||
this.screen[this.y + this.shift][0][this.x] = this.cloneAttr(this.curAttr, ch);
|
||||
this.screen[this.y + this.shift][1] = true;
|
||||
this.putChar(ch);
|
||||
this.x++;
|
||||
if (this.force_width && ("\uff00" < ch && ch < "\uffef")) {
|
||||
if (this.forceWidth && ("\uff00" < ch && ch < "\uffef")) {
|
||||
if (this.cols < 2 || this.x >= this.cols) {
|
||||
this.screen[this.y + this.shift][0][this.x - 1] = this.cloneAttr(this.curAttr, " ");
|
||||
this.screen[this.y + this.shift][1] = true;
|
||||
this.putChar(" ");
|
||||
break;
|
||||
}
|
||||
this.screen[this.y + this.shift][0][this.x] = this.cloneAttr(this.curAttr, " ");
|
||||
this.screen[this.y + this.shift][1] = true;
|
||||
this.putChar(" ");
|
||||
this.x++;
|
||||
}
|
||||
}
|
||||
@@ -1168,7 +1174,7 @@
|
||||
}
|
||||
switch (type) {
|
||||
case "HTML":
|
||||
if (!this.html_escapes_enabled) {
|
||||
if (!this.htmlEscapesEnabled) {
|
||||
console.log("HTML escapes are disabled");
|
||||
break;
|
||||
}
|
||||
@@ -1321,7 +1327,7 @@
|
||||
break;
|
||||
}
|
||||
if (ev.ctrlKey) {
|
||||
this.scroll_display(-1);
|
||||
this.scrollDisplay(-1);
|
||||
return cancel(ev);
|
||||
} else {
|
||||
key = "\x1b[A";
|
||||
@@ -1333,7 +1339,7 @@
|
||||
break;
|
||||
}
|
||||
if (ev.ctrlKey) {
|
||||
this.scroll_display(1);
|
||||
this.scrollDisplay(1);
|
||||
return cancel(ev);
|
||||
} else {
|
||||
key = "\x1b[B";
|
||||
@@ -1361,7 +1367,7 @@
|
||||
break;
|
||||
case 33:
|
||||
if (ev.shiftKey) {
|
||||
this.scroll_display(-(this.rows - 1));
|
||||
this.scrollDisplay(-(this.rows - 1));
|
||||
return cancel(ev);
|
||||
} else {
|
||||
key = "\x1b[5~";
|
||||
@@ -1369,7 +1375,7 @@
|
||||
break;
|
||||
case 34:
|
||||
if (ev.shiftKey) {
|
||||
this.scroll_display(this.rows - 1);
|
||||
this.scrollDisplay(this.rows - 1);
|
||||
return cancel(ev);
|
||||
} else {
|
||||
key = "\x1b[6~";
|
||||
@@ -1424,7 +1430,7 @@
|
||||
if (ev.keyCode >= 65 && ev.keyCode <= 90) {
|
||||
if (ev.keyCode === 67) {
|
||||
t = (new Date()).getTime();
|
||||
if ((t - this.last_cc) < 500 && !this.stop) {
|
||||
if ((t - this.lastcc) < 500 && !this.stop) {
|
||||
id = setTimeout(function() {});
|
||||
while (id--) {
|
||||
if (id !== this.t_bell && id !== this.t_queue && id !== this.t_blink) {
|
||||
@@ -1436,7 +1442,7 @@
|
||||
} else if (this.stop) {
|
||||
return true;
|
||||
}
|
||||
this.last_cc = t;
|
||||
this.lastcc = t;
|
||||
}
|
||||
key = String.fromCharCode(ev.keyCode - 64);
|
||||
} else if (ev.keyCode === 32) {
|
||||
@@ -1543,32 +1549,32 @@
|
||||
};
|
||||
|
||||
Terminal.prototype.resize = function(x, y) {
|
||||
var el, i, j, line, old_cols, old_rows, px;
|
||||
var el, i, j, line, oldCols, oldRows, px;
|
||||
if (x == null) {
|
||||
x = null;
|
||||
}
|
||||
if (y == null) {
|
||||
y = null;
|
||||
}
|
||||
old_cols = this.cols;
|
||||
old_rows = this.rows;
|
||||
this.compute_char_size();
|
||||
this.cols = x || Math.floor(this.body.clientWidth / this.char_size.width);
|
||||
this.rows = y || Math.floor(window.innerHeight / this.char_size.height);
|
||||
px = window.innerHeight % this.char_size.height;
|
||||
oldCols = this.cols;
|
||||
oldRows = this.rows;
|
||||
this.computeCharSize();
|
||||
this.cols = x || Math.floor(this.body.clientWidth / this.charSize.width);
|
||||
this.rows = y || Math.floor(window.innerHeight / this.charSize.height);
|
||||
px = window.innerHeight % this.charSize.height;
|
||||
this.body.style['padding-bottom'] = px + "px";
|
||||
if ((!x && !y) && old_cols === this.cols && old_rows === this.rows) {
|
||||
if ((!x && !y) && oldCols === this.cols && oldRows === this.rows) {
|
||||
return;
|
||||
}
|
||||
this.ctl('Resize', this.cols, this.rows);
|
||||
if (old_cols < this.cols) {
|
||||
if (oldCols < this.cols) {
|
||||
i = this.screen.length;
|
||||
while (i--) {
|
||||
while (this.screen[i][0].length < this.cols) {
|
||||
this.screen[i][0].push(this.defAttr);
|
||||
}
|
||||
}
|
||||
} else if (old_cols > this.cols) {
|
||||
} else if (oldCols > this.cols) {
|
||||
i = this.screen.length;
|
||||
while (i--) {
|
||||
while (this.screen[i][0].length > this.cols) {
|
||||
@@ -1576,13 +1582,13 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
this.setupStops(old_cols);
|
||||
j = old_rows;
|
||||
this.setupStops(oldCols);
|
||||
j = oldRows;
|
||||
if (j < this.rows) {
|
||||
el = this.body;
|
||||
while (j++ < this.rows) {
|
||||
if (this.screen.length < this.rows) {
|
||||
this.screen.push([this.blank_line(), true]);
|
||||
this.screen.push([this.blankLine(), true]);
|
||||
}
|
||||
if (this.children.length < this.rows) {
|
||||
line = this.document.createElement("div");
|
||||
@@ -1695,7 +1701,7 @@
|
||||
return this.eraseRight(0, y);
|
||||
};
|
||||
|
||||
Terminal.prototype.blank_line = function(cur) {
|
||||
Terminal.prototype.blankLine = function(cur) {
|
||||
var attr, i, line;
|
||||
attr = (cur ? this.eraseAttr() : this.defAttr);
|
||||
line = [];
|
||||
@@ -1728,17 +1734,17 @@
|
||||
};
|
||||
|
||||
Terminal.prototype.index = function() {
|
||||
this.next_line();
|
||||
this.nextLine();
|
||||
return this.state = State.normal;
|
||||
};
|
||||
|
||||
Terminal.prototype.reverseIndex = function() {
|
||||
this.prev_line();
|
||||
this.prevLine();
|
||||
return this.state = State.normal;
|
||||
};
|
||||
|
||||
Terminal.prototype.reset = function() {
|
||||
this.reset_vars();
|
||||
this.resetVars();
|
||||
return this.refresh(true);
|
||||
};
|
||||
|
||||
@@ -2014,7 +2020,7 @@
|
||||
param = 1;
|
||||
}
|
||||
while (param--) {
|
||||
this.screen.splice(this.y + this.shift, 0, [this.blank_line(true), true]);
|
||||
this.screen.splice(this.y + this.shift, 0, [this.blankLine(true), true]);
|
||||
this.screen.splice(this.scrollBottom + 1 + this.shift, 1);
|
||||
}
|
||||
results = [];
|
||||
@@ -2031,7 +2037,7 @@
|
||||
param = 1;
|
||||
}
|
||||
while (param--) {
|
||||
this.screen.splice(this.scrollBottom + this.shift, 0, [this.blank_line(true), true]);
|
||||
this.screen.splice(this.scrollBottom + this.shift, 0, [this.blankLine(true), true]);
|
||||
this.screen.splice(this.y + this.shift, 1);
|
||||
if (!(this.normal || this.scrollTop !== 0 || this.scrollBottom !== this.rows - 1)) {
|
||||
this.children[this.y + this.shift].remove();
|
||||
@@ -2353,7 +2359,7 @@
|
||||
param = params[0] || 1;
|
||||
while (param--) {
|
||||
this.screen.splice(this.scrollTop, 1);
|
||||
this.screen.splice(this.scrollBottom, 0, [this.blank_line(), true]);
|
||||
this.screen.splice(this.scrollBottom, 0, [this.blankLine(), true]);
|
||||
}
|
||||
results = [];
|
||||
for (i = k = ref = this.scrollTop, ref1 = this.scrollBottom; ref <= ref1 ? k <= ref1 : k >= ref1; i = ref <= ref1 ? ++k : --k) {
|
||||
@@ -2367,7 +2373,7 @@
|
||||
param = params[0] || 1;
|
||||
while (param--) {
|
||||
this.screen.splice(this.scrollBottom, 1);
|
||||
this.screen.splice(this.scrollTop, 0, [this.blank_line(), true]);
|
||||
this.screen.splice(this.scrollTop, 0, [this.blankLine(), true]);
|
||||
}
|
||||
results = [];
|
||||
for (i = k = ref = this.scrollTop, ref1 = this.scrollBottom; ref <= ref1 ? k <= ref1 : k >= ref1; i = ref <= ref1 ? ++k : --k) {
|
||||
|
||||
4
butterfly/static/main.min.js
vendored
4
butterfly/static/main.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -1,4 +1,4 @@
|
||||
set_alarm = (notification) ->
|
||||
setAlarm = (notification) ->
|
||||
alarm = (data) ->
|
||||
butterfly.body.classList.remove 'alarm'
|
||||
note = "New activity on butterfly terminal [#{ butterfly.title }]"
|
||||
@@ -29,8 +29,8 @@ document.addEventListener 'keydown', (e) ->
|
||||
|
||||
if Notification and Notification.permission is 'default'
|
||||
Notification.requestPermission ->
|
||||
set_alarm(Notification.permission is 'granted')
|
||||
setAlarm(Notification.permission is 'granted')
|
||||
else
|
||||
set_alarm(Notification.permission is 'granted')
|
||||
setAlarm(Notification.permission is 'granted')
|
||||
|
||||
cancel(e)
|
||||
|
||||
@@ -22,7 +22,7 @@ cancel = (ev) ->
|
||||
ev.cancelBubble = true
|
||||
false
|
||||
|
||||
previous_leaf = (node) ->
|
||||
previousLeaf = (node) ->
|
||||
previous = node.previousSibling
|
||||
if not previous
|
||||
previous = node.parentNode.previousSibling
|
||||
@@ -32,7 +32,7 @@ previous_leaf = (node) ->
|
||||
previous = previous.lastChild
|
||||
previous
|
||||
|
||||
next_leaf = (node) ->
|
||||
nextLeaf = (node) ->
|
||||
next = node.nextSibling
|
||||
if not next
|
||||
next = node.parentNode.nextSibling
|
||||
@@ -49,9 +49,9 @@ class Selection
|
||||
|
||||
reset: ->
|
||||
@selection = getSelection()
|
||||
fake_range = document.createRange()
|
||||
fake_range.setStart(@selection.anchorNode, @selection.anchorOffset)
|
||||
fake_range.setEnd(@selection.focusNode, @selection.focusOffset)
|
||||
fakeRange = document.createRange()
|
||||
fakeRange.setStart(@selection.anchorNode, @selection.anchorOffset)
|
||||
fakeRange.setEnd(@selection.focusNode, @selection.focusOffset)
|
||||
@start =
|
||||
node: @selection.anchorNode
|
||||
offset: @selection.anchorOffset
|
||||
@@ -59,16 +59,16 @@ class Selection
|
||||
node: @selection.focusNode
|
||||
offset: @selection.focusOffset
|
||||
|
||||
if fake_range.collapsed
|
||||
if fakeRange.collapsed
|
||||
[@start, @end] = [@end, @start]
|
||||
|
||||
@start_line = @start.node
|
||||
while not @start_line.classList or 'line' not in @start_line.classList
|
||||
@start_line = @start_line.parentNode
|
||||
@startLine = @start.node
|
||||
while not @startLine.classList or 'line' not in @startLine.classList
|
||||
@startLine = @startLine.parentNode
|
||||
|
||||
@end_line = @end.node
|
||||
while not @end_line.classList or 'line' not in @end_line.classList
|
||||
@end_line = @end_line.parentNode
|
||||
@endLine = @end.node
|
||||
while not @endLine.classList or 'line' not in @endLine.classList
|
||||
@endLine = @endLine.parentNode
|
||||
|
||||
clear: ->
|
||||
@selection.removeAllRanges()
|
||||
@@ -87,14 +87,14 @@ class Selection
|
||||
@go +1
|
||||
|
||||
go: (n) ->
|
||||
index = butterfly.children.indexOf(@start_line) + n
|
||||
index = butterfly.children.indexOf(@startLine) + n
|
||||
return unless 0 <= index < butterfly.children.length
|
||||
|
||||
until butterfly.children[index].textContent.match /\S/
|
||||
index += n
|
||||
return unless 0 <= index < butterfly.children.length
|
||||
|
||||
@select_line index
|
||||
@selectLine index
|
||||
|
||||
apply: ->
|
||||
@clear()
|
||||
@@ -103,42 +103,42 @@ class Selection
|
||||
range.setEnd @end.node, @end.offset
|
||||
@selection.addRange range
|
||||
|
||||
select_line: (index) ->
|
||||
selectLine: (index) ->
|
||||
line = butterfly.children[index]
|
||||
line_start =
|
||||
lineStart =
|
||||
node: line.firstChild
|
||||
offset: 0
|
||||
|
||||
line_end =
|
||||
lineEnd =
|
||||
node: line.lastChild
|
||||
offset: line.lastChild.textContent.length
|
||||
|
||||
@start = @walk line_start, /\S/
|
||||
@end = @walk line_end, /\S/, true
|
||||
@start = @walk lineStart, /\S/
|
||||
@end = @walk lineEnd, /\S/, true
|
||||
|
||||
collapsed: (start, end) ->
|
||||
fake_range = document.createRange()
|
||||
fake_range.setStart(start.node, start.offset)
|
||||
fake_range.setEnd(end.node, end.offset)
|
||||
fake_range.collapsed
|
||||
fakeRange = document.createRange()
|
||||
fakeRange.setStart(start.node, start.offset)
|
||||
fakeRange.setEnd(end.node, end.offset)
|
||||
fakeRange.collapsed
|
||||
|
||||
shrink_right: ->
|
||||
shrinkRight: ->
|
||||
node = @walk @end, /\s/, true
|
||||
end = @walk node, /\S/, true
|
||||
if not @collapsed(@start, end)
|
||||
@end = end
|
||||
|
||||
shrink_left: ->
|
||||
shrinkLeft: ->
|
||||
node = @walk @start, /\s/
|
||||
start = @walk node, /\S/
|
||||
if not @collapsed(start, @end)
|
||||
@start = start
|
||||
|
||||
expand_right: ->
|
||||
expandRight: ->
|
||||
node = @walk @end, /\S/
|
||||
@end = @walk node, /\s/
|
||||
|
||||
expand_left: ->
|
||||
expandLeft: ->
|
||||
node = @walk @start, /\S/, true
|
||||
@start = @walk node, /\s/, true
|
||||
|
||||
@@ -155,7 +155,7 @@ class Selection
|
||||
while i > 0
|
||||
if text[--i].match til
|
||||
return node: node, offset: i + 1
|
||||
node = previous_leaf node
|
||||
node = previousLeaf node
|
||||
text = node.textContent
|
||||
i = text.length
|
||||
else
|
||||
@@ -163,7 +163,7 @@ class Selection
|
||||
while i < text.length
|
||||
if text[i++].match til
|
||||
return node: node, offset: i - 1
|
||||
node = next_leaf node
|
||||
node = nextLeaf node
|
||||
text = node.textContent
|
||||
i = 0
|
||||
|
||||
@@ -189,13 +189,13 @@ document.addEventListener 'keydown', (e) ->
|
||||
else if e.keyCode == 40
|
||||
selection.down()
|
||||
else if e.keyCode == 39
|
||||
selection.shrink_left()
|
||||
selection.shrinkLeft()
|
||||
else if e.keyCode == 38
|
||||
selection.expand_left()
|
||||
selection.expandLeft()
|
||||
else if e.keyCode == 37
|
||||
selection.shrink_right()
|
||||
selection.shrinkRight()
|
||||
else if e.keyCode == 40
|
||||
selection.expand_right()
|
||||
selection.expandRight()
|
||||
else
|
||||
return cancel e
|
||||
|
||||
@@ -205,7 +205,7 @@ document.addEventListener 'keydown', (e) ->
|
||||
# Start selection mode with shift up
|
||||
if not selection and e.ctrlKey and e.shiftKey and e.keyCode == 38
|
||||
selection = new Selection()
|
||||
selection.select_line butterfly.y - 1
|
||||
selection.selectLine butterfly.y - 1
|
||||
selection.apply()
|
||||
return cancel e
|
||||
true
|
||||
@@ -235,10 +235,10 @@ document.addEventListener 'dblclick', (e) ->
|
||||
range.setEnd(sel.focusNode, sel.focusOffset)
|
||||
if range.collapsed
|
||||
sel.removeAllRanges()
|
||||
new_range = document.createRange()
|
||||
new_range.setStart(sel.focusNode, sel.focusOffset)
|
||||
new_range.setEnd(sel.anchorNode, sel.anchorOffset)
|
||||
sel.addRange(new_range)
|
||||
newRange = document.createRange()
|
||||
newRange.setStart(sel.focusNode, sel.focusOffset)
|
||||
newRange.setEnd(sel.anchorNode, sel.anchorOffset)
|
||||
sel.addRange(newRange)
|
||||
|
||||
until sel.toString().match(/\s/) or not sel.toString()
|
||||
sel.modify 'extend', 'forward', 'character'
|
||||
|
||||
@@ -21,22 +21,22 @@ if /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i
|
||||
ctrl = false
|
||||
alt = false
|
||||
first = true
|
||||
virtual_input = document.createElement 'input'
|
||||
virtual_input.type = 'password'
|
||||
virtual_input.style.position = 'fixed'
|
||||
virtual_input.style.top = 0
|
||||
virtual_input.style.left = 0
|
||||
virtual_input.style.border = 'none'
|
||||
virtual_input.style.outline = 'none'
|
||||
virtual_input.style.opacity = 0
|
||||
virtual_input.value = '0'
|
||||
document.body.appendChild virtual_input
|
||||
virtualInput = document.createElement 'input'
|
||||
virtualInput.type = 'password'
|
||||
virtualInput.style.position = 'fixed'
|
||||
virtualInput.style.top = 0
|
||||
virtualInput.style.left = 0
|
||||
virtualInput.style.border = 'none'
|
||||
virtualInput.style.outline = 'none'
|
||||
virtualInput.style.opacity = 0
|
||||
virtualInput.value = '0'
|
||||
document.body.appendChild virtualInput
|
||||
|
||||
virtual_input.addEventListener 'blur', ->
|
||||
virtualInput.addEventListener 'blur', ->
|
||||
setTimeout((=> @focus()), 10)
|
||||
|
||||
addEventListener 'click', ->
|
||||
virtual_input.focus()
|
||||
virtualInput.focus()
|
||||
|
||||
addEventListener 'touchstart', (e) ->
|
||||
if e.touches.length == 2
|
||||
@@ -48,11 +48,11 @@ if /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i
|
||||
ctrl = true
|
||||
alt = true
|
||||
|
||||
virtual_input.addEventListener 'keydown', (e) ->
|
||||
virtualInput.addEventListener 'keydown', (e) ->
|
||||
butterfly.keyDown(e)
|
||||
return true
|
||||
|
||||
virtual_input.addEventListener 'input', (e) ->
|
||||
virtualInput.addEventListener 'input', (e) ->
|
||||
len = @value.length
|
||||
|
||||
if len == 0
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
cols = rows = null
|
||||
quit = false
|
||||
open_ts = (new Date()).getTime()
|
||||
openTs = (new Date()).getTime()
|
||||
|
||||
$ = document.querySelectorAll.bind(document)
|
||||
|
||||
@@ -32,22 +32,22 @@ document.addEventListener 'DOMContentLoaded', ->
|
||||
ws.send 'R' + params
|
||||
|
||||
if location.protocol == 'https:'
|
||||
ws_url = 'wss://'
|
||||
wsUrl = 'wss://'
|
||||
else
|
||||
ws_url = 'ws://'
|
||||
wsUrl = 'ws://'
|
||||
|
||||
ws_url += document.location.host + '/ws' + location.pathname
|
||||
ws = new WebSocket ws_url
|
||||
wsUrl += document.location.host + '/ws' + location.pathname
|
||||
ws = new WebSocket wsUrl
|
||||
|
||||
ws.addEventListener 'open', ->
|
||||
console.log "WebSocket open", arguments
|
||||
ws.send 'R' + term.cols + ',' + term.rows
|
||||
open_ts = (new Date()).getTime()
|
||||
openTs = (new Date()).getTime()
|
||||
|
||||
ws.addEventListener 'error', ->
|
||||
console.log "WebSocket error", arguments
|
||||
|
||||
last_data = ''
|
||||
lastData = ''
|
||||
t_queue = null
|
||||
|
||||
queue = ''
|
||||
@@ -57,7 +57,7 @@ document.addEventListener 'DOMContentLoaded', ->
|
||||
if term.stop
|
||||
queue = queue.slice -10 * 1024
|
||||
|
||||
if queue.length > term.buff_size
|
||||
if queue.length > term.buffSize
|
||||
treat()
|
||||
else
|
||||
t_queue = setTimeout treat, 1
|
||||
@@ -79,7 +79,7 @@ document.addEventListener 'DOMContentLoaded', ->
|
||||
, 1
|
||||
quit = true
|
||||
# Don't autoclose if websocket didn't last 1 minute
|
||||
if (new Date()).getTime() - open_ts > 60 * 1000
|
||||
if (new Date()).getTime() - openTs > 60 * 1000
|
||||
open('','_self').close()
|
||||
|
||||
term = new Terminal document.body, send, ctl
|
||||
|
||||
@@ -51,8 +51,8 @@ class Terminal
|
||||
# Global elements
|
||||
@document = @parent.ownerDocument
|
||||
@body = @document.getElementsByTagName('body')[0]
|
||||
@html_escapes_enabled = @body.getAttribute('data-allow-html') is 'yes'
|
||||
@force_width = @body.getAttribute(
|
||||
@htmlEscapesEnabled = @body.getAttribute('data-allow-html') is 'yes'
|
||||
@forceWidth = @body.getAttribute(
|
||||
'data-force-unicode-width') is 'yes'
|
||||
|
||||
# Main terminal element
|
||||
@@ -67,14 +67,14 @@ class Terminal
|
||||
@body.appendChild(div)
|
||||
@children = [div]
|
||||
|
||||
@compute_char_size()
|
||||
@cols = Math.floor(@body.clientWidth / @char_size.width)
|
||||
@rows = Math.floor(window.innerHeight / @char_size.height)
|
||||
px = window.innerHeight % @char_size.height
|
||||
@computeCharSize()
|
||||
@cols = Math.floor(@body.clientWidth / @charSize.width)
|
||||
@rows = Math.floor(window.innerHeight / @charSize.height)
|
||||
px = window.innerHeight % @charSize.height
|
||||
@body.style['padding-bottom'] = "#{px}px"
|
||||
|
||||
@scrollback = 1000000
|
||||
@buff_size = 100000
|
||||
@buffSize = 100000
|
||||
|
||||
@visualBell = 100
|
||||
@convertEol = false
|
||||
@@ -82,8 +82,8 @@ class Terminal
|
||||
@cursorBlink = true
|
||||
@cursorState = 0
|
||||
@stop = false
|
||||
@last_cc = 0
|
||||
@reset_vars()
|
||||
@lastcc = 0
|
||||
@resetVars()
|
||||
|
||||
@focus()
|
||||
|
||||
@@ -118,7 +118,16 @@ class Terminal
|
||||
a.underline is b.underline and a.blink is b.blink and
|
||||
a.inverse is b.inverse and a.invisible is b.invisible)
|
||||
|
||||
reset_vars: ->
|
||||
putChar: (c) ->
|
||||
if @insertMode
|
||||
@screen[@y + @shift][0].splice(@x, 0, @cloneAttr @curAttr, c)
|
||||
@screen[@y + @shift][0].pop()
|
||||
else
|
||||
@screen[@y + @shift][0][@x] = @cloneAttr @curAttr, c
|
||||
|
||||
@screen[@y + @shift][1] = true
|
||||
|
||||
resetVars: ->
|
||||
@x = 0
|
||||
@y = 0
|
||||
@cursorHidden = false
|
||||
@@ -160,18 +169,18 @@ class Terminal
|
||||
@screen = []
|
||||
i = @rows
|
||||
@shift = 0
|
||||
@screen.push [@blank_line(), true] while i--
|
||||
@screen.push [@blankLine(), true] while i--
|
||||
@setupStops()
|
||||
@skipNextKey = null
|
||||
|
||||
compute_char_size: ->
|
||||
test_span = document.createElement('span')
|
||||
test_span.textContent = '0123456789'
|
||||
@children[0].appendChild(test_span)
|
||||
@char_size =
|
||||
width: test_span.getBoundingClientRect().width / 10
|
||||
computeCharSize: ->
|
||||
testSpan = document.createElement('span')
|
||||
testSpan.textContent = '0123456789'
|
||||
@children[0].appendChild(testSpan)
|
||||
@charSize =
|
||||
width: testSpan.getBoundingClientRect().width / 10
|
||||
height: @children[0].getBoundingClientRect().height
|
||||
@children[0].removeChild(test_span)
|
||||
@children[0].removeChild(testSpan)
|
||||
|
||||
eraseAttr: ->
|
||||
erased = @cloneAttr @defAttr
|
||||
@@ -379,7 +388,7 @@ class Terminal
|
||||
for cursor in @body.querySelectorAll(".cursor")
|
||||
cursor.parentNode.replaceChild(
|
||||
@document.createTextNode(cursor.textContent), cursor)
|
||||
new_out = ''
|
||||
newOut = ''
|
||||
for [line, dirty], j in @screen
|
||||
continue unless dirty or force
|
||||
out = ""
|
||||
@@ -461,15 +470,15 @@ class Terminal
|
||||
out += '<span class="nbsp">\u2007</span>'
|
||||
else if ch <= " "
|
||||
out += " "
|
||||
else if not @force_width or ch <= "~" # Ascii chars
|
||||
else if not @forceWidth or ch <= "~" # Ascii chars
|
||||
out += ch
|
||||
else if "\uff00" < ch < "\uffef"
|
||||
skipnext = true
|
||||
out += "<span style=\"display: inline-block;
|
||||
width: #{2 * @char_size.width}px\">#{ch}</span>"
|
||||
width: #{2 * @charSize.width}px\">#{ch}</span>"
|
||||
else
|
||||
out += "<span style=\"display: inline-block;
|
||||
width: #{@char_size.width}px\">#{ch}</span>"
|
||||
width: #{@charSize.width}px\">#{ch}</span>"
|
||||
|
||||
out += "</span>" if i is x
|
||||
attr = data
|
||||
@@ -477,13 +486,13 @@ class Terminal
|
||||
if @children[j]
|
||||
@children[j].innerHTML = out
|
||||
else
|
||||
new_out += "<div class=\"line\">#{out}</div>"
|
||||
newOut += "<div class=\"line\">#{out}</div>"
|
||||
@screen[j][1] = false
|
||||
|
||||
if new_out isnt ''
|
||||
if newOut isnt ''
|
||||
group = @document.createElement('div')
|
||||
group.className = 'group'
|
||||
group.innerHTML = new_out
|
||||
group.innerHTML = newOut
|
||||
@body.appendChild group
|
||||
@screen = @screen.slice(-@rows)
|
||||
@shift = 0
|
||||
@@ -499,7 +508,7 @@ class Terminal
|
||||
@children = Array.prototype.slice.call(
|
||||
lines, -@rows)
|
||||
|
||||
@native_scroll_to() unless @scrollLock
|
||||
@nativeScrollTo() unless @scrollLock
|
||||
|
||||
_cursorBlink: ->
|
||||
@cursorState ^= 1
|
||||
@@ -534,36 +543,36 @@ class Terminal
|
||||
# Use emulated scroll in alternate buffer or when scroll region is defined
|
||||
if @normal or @scrollTop isnt 0 or @scrollBottom isnt @rows - 1
|
||||
# inner scroll
|
||||
@screen.splice @shift + @scrollBottom + 1, 0, [@blank_line(), true]
|
||||
@screen.splice @shift + @scrollBottom + 1, 0, [@blankLine(), true]
|
||||
@screen.splice @shift + @scrollTop, 1
|
||||
|
||||
for i in [@scrollTop..@scrollBottom]
|
||||
@screen[i + @shift][1] = true
|
||||
else
|
||||
@screen.push [@blank_line(), true]
|
||||
@screen.push [@blankLine(), true]
|
||||
@shift++
|
||||
|
||||
unscroll: ->
|
||||
@screen.splice @shift + @scrollTop , 0, [@blank_line(true), true]
|
||||
@screen.splice @shift + @scrollTop , 0, [@blankLine(true), true]
|
||||
@screen.splice @shift + @scrollBottom + 1, 1
|
||||
|
||||
for i in [@scrollTop..@scrollBottom]
|
||||
@screen[i + @shift][1] = true
|
||||
|
||||
|
||||
native_scroll_to: (scroll=2000000000) -> # ~ Max ff number
|
||||
nativeScrollTo: (scroll=2000000000) -> # ~ Max ff number
|
||||
window.scrollTo 0, scroll
|
||||
|
||||
scroll_display: (disp) ->
|
||||
@native_scroll_to window.scrollY + disp * @char_size.height
|
||||
scrollDisplay: (disp) ->
|
||||
@nativeScrollTo window.scrollY + disp * @charSize.height
|
||||
|
||||
next_line: ->
|
||||
nextLine: ->
|
||||
@y++
|
||||
if @y > @scrollBottom
|
||||
@y--
|
||||
@scroll()
|
||||
|
||||
prev_line: ->
|
||||
prevLine: ->
|
||||
@y--
|
||||
if @y < @scrollTop
|
||||
@y++
|
||||
@@ -585,7 +594,7 @@ class Terminal
|
||||
# '\n', '\v', '\f'
|
||||
when "\n", "\x0b", "\x0c"
|
||||
# @x = 0 if @convertEol
|
||||
@next_line()
|
||||
@nextLine()
|
||||
|
||||
# '\r'
|
||||
when "\r"
|
||||
@@ -616,22 +625,18 @@ class Terminal
|
||||
if ch >= " "
|
||||
ch = @charset[ch] if @charset?[ch]
|
||||
if @x >= @cols
|
||||
@screen[@y + @shift][0][@x] = @cloneAttr @curAttr, '\u23CE'
|
||||
@screen[@y + @shift][1] = true
|
||||
@putChar '\u23CE'
|
||||
@x = 0
|
||||
@next_line()
|
||||
@nextLine()
|
||||
|
||||
@screen[@y + @shift][0][@x] = @cloneAttr @curAttr, ch
|
||||
@screen[@y + @shift][1] = true
|
||||
@putChar ch
|
||||
@x++
|
||||
if @force_width and "\uff00" < ch < "\uffef"
|
||||
if @forceWidth and "\uff00" < ch < "\uffef"
|
||||
if @cols < 2 or @x >= @cols
|
||||
@screen[@y + @shift][0][@x - 1] = @cloneAttr @curAttr, " "
|
||||
@screen[@y + @shift][1] = true
|
||||
@putChar " "
|
||||
break
|
||||
|
||||
@screen[@y + @shift][0][@x] = @cloneAttr @curAttr, " "
|
||||
@screen[@y + @shift][1] = true
|
||||
@putChar " "
|
||||
@x++
|
||||
|
||||
when State.escaped
|
||||
@@ -1075,7 +1080,7 @@ class Terminal
|
||||
|
||||
switch type
|
||||
when "HTML"
|
||||
unless @html_escapes_enabled
|
||||
unless @htmlEscapesEnabled
|
||||
console.log "HTML escapes are disabled"
|
||||
break
|
||||
|
||||
@@ -1238,7 +1243,7 @@ class Terminal
|
||||
key = "\x1bOA"
|
||||
break
|
||||
if ev.ctrlKey
|
||||
@scroll_display -1
|
||||
@scrollDisplay -1
|
||||
return cancel(ev)
|
||||
else
|
||||
key = "\x1b[A"
|
||||
@@ -1249,7 +1254,7 @@ class Terminal
|
||||
key = "\x1bOB"
|
||||
break
|
||||
if ev.ctrlKey
|
||||
@scroll_display 1
|
||||
@scrollDisplay 1
|
||||
return cancel(ev)
|
||||
else
|
||||
key = "\x1b[B"
|
||||
@@ -1279,7 +1284,7 @@ class Terminal
|
||||
# page up
|
||||
when 33
|
||||
if ev.shiftKey
|
||||
@scroll_display -(@rows - 1)
|
||||
@scrollDisplay -(@rows - 1)
|
||||
return cancel(ev)
|
||||
else
|
||||
key = "\x1b[5~"
|
||||
@@ -1287,7 +1292,7 @@ class Terminal
|
||||
# page down
|
||||
when 34
|
||||
if ev.shiftKey
|
||||
@scroll_display @rows - 1
|
||||
@scrollDisplay @rows - 1
|
||||
return cancel(ev)
|
||||
else
|
||||
key = "\x1b[6~"
|
||||
@@ -1355,7 +1360,7 @@ class Terminal
|
||||
if ev.keyCode >= 65 and ev.keyCode <= 90
|
||||
if ev.keyCode is 67
|
||||
t = (new Date()).getTime()
|
||||
if (t - @last_cc) < 500 and not @stop
|
||||
if (t - @lastcc) < 500 and not @stop
|
||||
id = (setTimeout ->)
|
||||
(clearTimeout id if id not in [
|
||||
@t_bell, @t_queue, @t_blink]) while id--
|
||||
@@ -1363,7 +1368,7 @@ class Terminal
|
||||
@stop = true
|
||||
else if @stop
|
||||
return true
|
||||
@last_cc = t
|
||||
@lastcc = t
|
||||
key = String.fromCharCode(ev.keyCode - 64)
|
||||
else if ev.keyCode is 32
|
||||
|
||||
@@ -1461,38 +1466,38 @@ class Terminal
|
||||
), @visualBell
|
||||
|
||||
resize: (x=null, y=null) ->
|
||||
old_cols = @cols
|
||||
old_rows = @rows
|
||||
@compute_char_size()
|
||||
@cols = x or Math.floor(@body.clientWidth / @char_size.width)
|
||||
@rows = y or Math.floor(window.innerHeight / @char_size.height)
|
||||
px = window.innerHeight % @char_size.height
|
||||
oldCols = @cols
|
||||
oldRows = @rows
|
||||
@computeCharSize()
|
||||
@cols = x or Math.floor(@body.clientWidth / @charSize.width)
|
||||
@rows = y or Math.floor(window.innerHeight / @charSize.height)
|
||||
px = window.innerHeight % @charSize.height
|
||||
@body.style['padding-bottom'] = "#{px}px"
|
||||
|
||||
if (not x and not y) and old_cols == @cols and old_rows == @rows
|
||||
if (not x and not y) and oldCols == @cols and oldRows == @rows
|
||||
return
|
||||
|
||||
@ctl 'Resize', @cols, @rows
|
||||
|
||||
# resize cols
|
||||
if old_cols < @cols
|
||||
if oldCols < @cols
|
||||
# does xterm use the default attr?
|
||||
i = @screen.length
|
||||
while i--
|
||||
@screen[i][0].push @defAttr while @screen[i][0].length < @cols
|
||||
else if old_cols > @cols
|
||||
else if oldCols > @cols
|
||||
i = @screen.length
|
||||
while i--
|
||||
@screen[i][0].pop() while @screen[i][0].length > @cols
|
||||
|
||||
@setupStops old_cols
|
||||
@setupStops oldCols
|
||||
|
||||
# resize rows
|
||||
j = old_rows
|
||||
j = oldRows
|
||||
if j < @rows
|
||||
el = @body
|
||||
while j++ < @rows
|
||||
@screen.push [@blank_line(), true] if @screen.length < @rows
|
||||
@screen.push [@blankLine(), true] if @screen.length < @rows
|
||||
if @children.length < @rows
|
||||
line = @document.createElement("div")
|
||||
line.className = 'line'
|
||||
@@ -1562,7 +1567,7 @@ class Terminal
|
||||
eraseLine: (y) ->
|
||||
@eraseRight 0, y
|
||||
|
||||
blank_line: (cur) ->
|
||||
blankLine: (cur) ->
|
||||
attr = (if cur then @eraseAttr() else @defAttr)
|
||||
line = []
|
||||
i = 0
|
||||
@@ -1587,17 +1592,17 @@ class Terminal
|
||||
|
||||
# ESC D Index (IND is 0x84).
|
||||
index: ->
|
||||
@next_line()
|
||||
@nextLine()
|
||||
@state = State.normal
|
||||
|
||||
# ESC M Reverse Index (RI is 0x8d).
|
||||
reverseIndex: ->
|
||||
@prev_line()
|
||||
@prevLine()
|
||||
@state = State.normal
|
||||
|
||||
# ESC c Full Reset (RIS).
|
||||
reset: ->
|
||||
@reset_vars()
|
||||
@resetVars()
|
||||
@refresh(true)
|
||||
|
||||
# ESC H Tab Set (HTS is 0x88).
|
||||
@@ -1956,8 +1961,8 @@ class Terminal
|
||||
param = 1 if param < 1
|
||||
|
||||
while param--
|
||||
@screen.splice @y + @shift, 0, [@blank_line(true), true]
|
||||
# blank_line(true) - xterm/linux behavior
|
||||
@screen.splice @y + @shift, 0, [@blankLine(true), true]
|
||||
# blankLine(true) - xterm/linux behavior
|
||||
@screen.splice @scrollBottom + 1 + @shift, 1
|
||||
|
||||
for i in [@y + @shift..@screen.length - 1]
|
||||
@@ -1971,8 +1976,8 @@ class Terminal
|
||||
|
||||
while param--
|
||||
# test: echo -e '\e[44m\e[1M\e[0m'
|
||||
# blank_line(true) - xterm/linux behavior
|
||||
@screen.splice @scrollBottom + @shift, 0, [@blank_line(true), true]
|
||||
# blankLine(true) - xterm/linux behavior
|
||||
@screen.splice @scrollBottom + @shift, 0, [@blankLine(true), true]
|
||||
@screen.splice @y + @shift, 1
|
||||
unless @normal or @scrollTop isnt 0 or @scrollBottom isnt @rows - 1
|
||||
@children[@y + @shift].remove()
|
||||
@@ -2455,7 +2460,7 @@ class Terminal
|
||||
param = params[0] or 1
|
||||
while param--
|
||||
@screen.splice @scrollTop, 1
|
||||
@screen.splice @scrollBottom, 0, [@blank_line(), true]
|
||||
@screen.splice @scrollBottom, 0, [@blankLine(), true]
|
||||
|
||||
for i in [@scrollTop..@scrollBottom]
|
||||
@screen[i + @shift][1] = true
|
||||
@@ -2466,7 +2471,7 @@ class Terminal
|
||||
param = params[0] or 1
|
||||
while param--
|
||||
@screen.splice @scrollBottom, 1
|
||||
@screen.splice @scrollTop, 0, [@blank_line(), true]
|
||||
@screen.splice @scrollTop, 0, [@blankLine(), true]
|
||||
|
||||
for i in [@scrollTop..@scrollBottom]
|
||||
@screen[i + @shift][1] = true
|
||||
|
||||
Reference in New Issue
Block a user