mirror of
https://github.com/paradoxxxzero/butterfly.git
synced 2026-05-26 15:13:36 +00:00
Rework refresh
This commit is contained in:
@@ -164,30 +164,22 @@
|
||||
}
|
||||
});
|
||||
|
||||
Terminal.on('change', function(lines) {
|
||||
var j, len1, line, results;
|
||||
results = [];
|
||||
for (j = 0, len1 = lines.length; j < len1; j++) {
|
||||
line = lines[j];
|
||||
if (indexOf.call(line.classList, 'extended') >= 0) {
|
||||
results.push(line.addEventListener('click', (function(line) {
|
||||
return function() {
|
||||
var after, before;
|
||||
if (indexOf.call(line.classList, 'expanded') >= 0) {
|
||||
return line.classList.remove('expanded');
|
||||
} else {
|
||||
before = line.getBoundingClientRect().height;
|
||||
line.classList.add('expanded');
|
||||
after = line.getBoundingClientRect().height;
|
||||
return document.body.scrollTop += after - before;
|
||||
}
|
||||
};
|
||||
})(line)));
|
||||
} else {
|
||||
results.push(void 0);
|
||||
}
|
||||
Terminal.on('change', function(line) {
|
||||
if (indexOf.call(line.classList, 'extended') >= 0) {
|
||||
return line.addEventListener('click', (function(line) {
|
||||
return function() {
|
||||
var after, before;
|
||||
if (indexOf.call(line.classList, 'expanded') >= 0) {
|
||||
return line.classList.remove('expanded');
|
||||
} else {
|
||||
before = line.getBoundingClientRect().height;
|
||||
line.classList.add('expanded');
|
||||
after = line.getBoundingClientRect().height;
|
||||
return document.body.scrollTop += after - before;
|
||||
}
|
||||
};
|
||||
})(line));
|
||||
}
|
||||
return results;
|
||||
});
|
||||
|
||||
walk = function(node, callback) {
|
||||
@@ -210,25 +202,19 @@
|
||||
return text.replace(urlPattern, '<a href="$&">$&</a>').replace(pseudoUrlPattern, '$1<a href="http://$2">$2</a>').replace(emailAddressPattern, '<a href="mailto:$&">$&</a>');
|
||||
};
|
||||
|
||||
Terminal.on('change', function(lines) {
|
||||
var j, len1, line, results;
|
||||
results = [];
|
||||
for (j = 0, len1 = lines.length; j < len1; j++) {
|
||||
line = lines[j];
|
||||
results.push(walk(line, function() {
|
||||
var linkified, newNode;
|
||||
if (this.nodeType === 3) {
|
||||
linkified = linkify(this.nodeValue);
|
||||
if (linkified !== this.nodeValue) {
|
||||
newNode = document.createElement('span');
|
||||
newNode.innerHTML = linkified;
|
||||
this.parentElement.replaceChild(newNode, this);
|
||||
return true;
|
||||
}
|
||||
Terminal.on('change', function(line) {
|
||||
return walk(line, function() {
|
||||
var linkified, newNode;
|
||||
if (this.nodeType === 3) {
|
||||
linkified = linkify(this.nodeValue);
|
||||
if (linkified !== this.nodeValue) {
|
||||
newNode = document.createElement('span');
|
||||
newNode.innerHTML = linkified;
|
||||
this.parentElement.replaceChild(newNode, this);
|
||||
return true;
|
||||
}
|
||||
}));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
document.addEventListener('keydown', function(e) {
|
||||
|
||||
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
@@ -1,6 +1,5 @@
|
||||
(function() {
|
||||
var $, State, Terminal, cancel, cols, openTs, quit, rows, s, uuid, ws,
|
||||
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; };
|
||||
|
||||
cols = rows = null;
|
||||
@@ -192,7 +191,7 @@
|
||||
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.scrollback = 10000;
|
||||
this.buffSize = 100000;
|
||||
this.visualBell = 100;
|
||||
this.convertEol = false;
|
||||
@@ -226,11 +225,18 @@
|
||||
};
|
||||
})(this));
|
||||
this.emit('load');
|
||||
this.active = null;
|
||||
Terminal.on('change', (function(_this) {
|
||||
return function(line) {
|
||||
if (line.classList.contains('active')) {
|
||||
return _this.active = line;
|
||||
}
|
||||
};
|
||||
})(this));
|
||||
}
|
||||
|
||||
Terminal.prototype.emit = function() {
|
||||
var args, fun, hook, k, len, ref, results;
|
||||
hook = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
|
||||
Terminal.prototype.emit = function(hook, obj) {
|
||||
var fun, k, len, ref, results;
|
||||
if (Terminal.hooks[hook] == null) {
|
||||
Terminal.hooks[hook] = [];
|
||||
}
|
||||
@@ -238,7 +244,11 @@
|
||||
results = [];
|
||||
for (k = 0, len = ref.length; k < len; k++) {
|
||||
fun = ref[k];
|
||||
results.push(fun.apply(this, args));
|
||||
results.push(setTimeout((function(f) {
|
||||
return function() {
|
||||
return f.call(this, obj);
|
||||
};
|
||||
})(fun), 10));
|
||||
}
|
||||
return results;
|
||||
};
|
||||
@@ -543,144 +553,162 @@
|
||||
})(this));
|
||||
};
|
||||
|
||||
Terminal.prototype.refresh = function(force) {
|
||||
var active, attr, ch, classes, cls, cursor, data, fg, group, i, j, k, len, len1, len2, len3, len4, line, lines, m, modified, n, newOut, o, out, q, ref, ref1, ref2, ref3, ref4, ref5, skipnext, styles, u, x;
|
||||
if (force == null) {
|
||||
force = false;
|
||||
Terminal.prototype._putChar = function(data, attr, i, x) {
|
||||
var ch, classes, fg, out, skipnext, styles;
|
||||
out = '';
|
||||
ch = data.ch;
|
||||
if (!this.equalAttr(data, attr)) {
|
||||
if (!this.equalAttr(attr, this.defAttr)) {
|
||||
out += "</span>";
|
||||
}
|
||||
if (!this.equalAttr(data, this.defAttr)) {
|
||||
classes = [];
|
||||
styles = [];
|
||||
out += "<span ";
|
||||
if (data.bold) {
|
||||
classes.push("bold");
|
||||
}
|
||||
if (data.underline) {
|
||||
classes.push("underline");
|
||||
}
|
||||
if (data.blink === 1) {
|
||||
classes.push("blink");
|
||||
}
|
||||
if (data.blink === 2) {
|
||||
classes.push("blink-fast");
|
||||
}
|
||||
if (data.inverse) {
|
||||
classes.push("reverse-video");
|
||||
}
|
||||
if (data.invisible) {
|
||||
classes.push("invisible");
|
||||
}
|
||||
if (data.italic) {
|
||||
classes.push("italic");
|
||||
}
|
||||
if (data.faint) {
|
||||
classes.push("faint");
|
||||
}
|
||||
if (data.crossed) {
|
||||
classes.push("crossed");
|
||||
}
|
||||
if (typeof data.fg === 'number') {
|
||||
fg = data.fg;
|
||||
if (data.bold && fg < 8) {
|
||||
fg += 8;
|
||||
}
|
||||
classes.push("fg-color-" + fg);
|
||||
}
|
||||
if (typeof data.fg === 'string') {
|
||||
styles.push("color: " + data.fg);
|
||||
}
|
||||
if (typeof data.bg === 'number') {
|
||||
classes.push("bg-color-" + data.bg);
|
||||
}
|
||||
if (typeof data.bg === 'string') {
|
||||
styles.push("background-color: " + data.bg);
|
||||
}
|
||||
out += "class=\"";
|
||||
out += classes.join(" ");
|
||||
out += "\"";
|
||||
if (styles.length) {
|
||||
out += " style=\"" + styles.join("; ") + "\"";
|
||||
}
|
||||
out += ">";
|
||||
}
|
||||
}
|
||||
ref = this.body.querySelectorAll(".cursor");
|
||||
for (k = 0, len = ref.length; k < len; k++) {
|
||||
cursor = ref[k];
|
||||
cursor.parentNode.replaceChild(this.document.createTextNode(cursor.textContent), cursor);
|
||||
if (i === x) {
|
||||
out += "<span class=\"" + (this.cursorState ? "reverse-video " : "") + "cursor\">";
|
||||
}
|
||||
ref1 = this.body.querySelectorAll(".line.active");
|
||||
for (m = 0, len1 = ref1.length; m < len1; m++) {
|
||||
active = ref1[m];
|
||||
active.classList.remove('active');
|
||||
if (ch.length > 1) {
|
||||
out += ch;
|
||||
} else {
|
||||
switch (ch) {
|
||||
case "&":
|
||||
out += "&";
|
||||
break;
|
||||
case "<":
|
||||
out += "<";
|
||||
break;
|
||||
case ">":
|
||||
out += ">";
|
||||
break;
|
||||
default:
|
||||
if (ch === " ") {
|
||||
out += '<span class="nbsp">\u2007</span>';
|
||||
} else if (ch <= " ") {
|
||||
out += " ";
|
||||
} else if (!this.forceWidth || ch <= "~") {
|
||||
out += ch;
|
||||
} else if (("\uff00" < ch && ch < "\uffef")) {
|
||||
skipnext = true;
|
||||
out += "<span style=\"display: inline-block; width: " + (2 * this.charSize.width) + "px\">" + ch + "</span>";
|
||||
} else {
|
||||
out += "<span style=\"display: inline-block; width: " + this.charSize.width + "px\">" + ch + "</span>";
|
||||
}
|
||||
}
|
||||
}
|
||||
newOut = '';
|
||||
modified = [];
|
||||
ref2 = this.screen;
|
||||
for (j = n = 0, len2 = ref2.length; n < len2; j = ++n) {
|
||||
line = ref2[j];
|
||||
if (i === x) {
|
||||
out += "</span>";
|
||||
}
|
||||
return out;
|
||||
};
|
||||
|
||||
Terminal.prototype._putLine = function(x, j, outs, line) {
|
||||
var cls;
|
||||
this.screen[j].dirty = false;
|
||||
if (this.children[j]) {
|
||||
this.children[j].innerHTML = outs.join('');
|
||||
this.emit('change', this.children[j]);
|
||||
if (x !== null) {
|
||||
this.children[j].classList.add('active');
|
||||
}
|
||||
if (line.extra) {
|
||||
this.children[j].classList.add('extended');
|
||||
}
|
||||
return null;
|
||||
} else {
|
||||
cls = ['line'];
|
||||
if (x !== null) {
|
||||
cls.push('active');
|
||||
}
|
||||
if (line.extra) {
|
||||
cls.push('extended');
|
||||
}
|
||||
return "<div class=\"" + (cls.join(' ')) + "\">" + (outs.join('')) + "</div>";
|
||||
}
|
||||
};
|
||||
|
||||
Terminal.prototype._replotScreen = function(force) {
|
||||
var attr, data, group, groups, i, j, k, len, line, m, out, outs, ref, ref1, skipnext, x;
|
||||
groups = [];
|
||||
ref = this.screen;
|
||||
for (j = k = 0, len = ref.length; k < len; j = ++k) {
|
||||
line = ref[j];
|
||||
if (!(line.dirty || force)) {
|
||||
continue;
|
||||
}
|
||||
out = "";
|
||||
x = null;
|
||||
if (j === this.y + this.shift && !this.cursorHidden) {
|
||||
x = this.x;
|
||||
} else {
|
||||
x = -Infinity;
|
||||
}
|
||||
attr = this.cloneAttr(this.defAttr);
|
||||
skipnext = false;
|
||||
for (i = o = 0, ref3 = this.cols - 1; 0 <= ref3 ? o <= ref3 : o >= ref3; i = 0 <= ref3 ? ++o : --o) {
|
||||
outs = [];
|
||||
for (i = m = 0, ref1 = this.cols - 1; 0 <= ref1 ? m <= ref1 : m >= ref1; i = 0 <= ref1 ? ++m : --m) {
|
||||
data = line.chars[i];
|
||||
if (data.html) {
|
||||
out += data.html;
|
||||
outs.push(data.html);
|
||||
break;
|
||||
}
|
||||
if (skipnext) {
|
||||
skipnext = false;
|
||||
continue;
|
||||
}
|
||||
ch = data.ch;
|
||||
if (!this.equalAttr(data, attr)) {
|
||||
if (!this.equalAttr(attr, this.defAttr)) {
|
||||
out += "</span>";
|
||||
}
|
||||
if (!this.equalAttr(data, this.defAttr)) {
|
||||
classes = [];
|
||||
styles = [];
|
||||
out += "<span ";
|
||||
if (data.bold) {
|
||||
classes.push("bold");
|
||||
}
|
||||
if (data.underline) {
|
||||
classes.push("underline");
|
||||
}
|
||||
if (data.blink === 1) {
|
||||
classes.push("blink");
|
||||
}
|
||||
if (data.blink === 2) {
|
||||
classes.push("blink-fast");
|
||||
}
|
||||
if (data.inverse) {
|
||||
classes.push("reverse-video");
|
||||
}
|
||||
if (data.invisible) {
|
||||
classes.push("invisible");
|
||||
}
|
||||
if (data.italic) {
|
||||
classes.push("italic");
|
||||
}
|
||||
if (data.faint) {
|
||||
classes.push("faint");
|
||||
}
|
||||
if (data.crossed) {
|
||||
classes.push("crossed");
|
||||
}
|
||||
if (typeof data.fg === 'number') {
|
||||
fg = data.fg;
|
||||
if (data.bold && fg < 8) {
|
||||
fg += 8;
|
||||
}
|
||||
classes.push("fg-color-" + fg);
|
||||
}
|
||||
if (typeof data.fg === 'string') {
|
||||
styles.push("color: " + data.fg);
|
||||
}
|
||||
if (typeof data.bg === 'number') {
|
||||
classes.push("bg-color-" + data.bg);
|
||||
}
|
||||
if (typeof data.bg === 'string') {
|
||||
styles.push("background-color: " + data.bg);
|
||||
}
|
||||
out += "class=\"";
|
||||
out += classes.join(" ");
|
||||
out += "\"";
|
||||
if (styles.length) {
|
||||
out += " style=\"" + styles.join("; ") + "\"";
|
||||
}
|
||||
out += ">";
|
||||
}
|
||||
}
|
||||
if (i === x) {
|
||||
out += "<span class=\"" + (this.cursorState ? "reverse-video " : "") + "cursor\">";
|
||||
}
|
||||
if (ch.length > 1) {
|
||||
out += ch;
|
||||
} else {
|
||||
switch (ch) {
|
||||
case "&":
|
||||
out += "&";
|
||||
break;
|
||||
case "<":
|
||||
out += "<";
|
||||
break;
|
||||
case ">":
|
||||
out += ">";
|
||||
break;
|
||||
default:
|
||||
if (ch === " ") {
|
||||
out += '<span class="nbsp">\u2007</span>';
|
||||
} else if (ch <= " ") {
|
||||
out += " ";
|
||||
} else if (!this.forceWidth || ch <= "~") {
|
||||
out += ch;
|
||||
} else if (("\uff00" < ch && ch < "\uffef")) {
|
||||
skipnext = true;
|
||||
out += "<span style=\"display: inline-block; width: " + (2 * this.charSize.width) + "px\">" + ch + "</span>";
|
||||
} else {
|
||||
out += "<span style=\"display: inline-block; width: " + this.charSize.width + "px\">" + ch + "</span>";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (i === x) {
|
||||
out += "</span>";
|
||||
}
|
||||
outs.push(this._putChar(data, attr, i, x));
|
||||
attr = data;
|
||||
}
|
||||
out = '';
|
||||
if (!this.equalAttr(attr, this.defAttr)) {
|
||||
out += "</span>";
|
||||
}
|
||||
@@ -690,53 +718,59 @@
|
||||
if (line.extra) {
|
||||
out += '<span class="extra">' + line.extra + '</span>';
|
||||
}
|
||||
if (this.children[j]) {
|
||||
this.children[j].innerHTML = out;
|
||||
modified.push(this.children[j]);
|
||||
if (x !== -Infinity) {
|
||||
this.children[j].classList.add('active');
|
||||
}
|
||||
if (line.extra) {
|
||||
this.children[j].classList.add('extended');
|
||||
}
|
||||
} else {
|
||||
cls = ['line'];
|
||||
if (x !== -Infinity) {
|
||||
cls.push('active');
|
||||
}
|
||||
if (line.extra) {
|
||||
cls.push('extended');
|
||||
}
|
||||
newOut += "<div class=\"" + (cls.join(' ')) + "\">" + out + "</div>";
|
||||
outs.push(out);
|
||||
group = this._putLine(x, j, outs, line);
|
||||
if (group) {
|
||||
groups.push(group);
|
||||
}
|
||||
this.screen[j].dirty = false;
|
||||
}
|
||||
if (newOut !== '') {
|
||||
group = this.document.createElement('div');
|
||||
group.className = 'group';
|
||||
group.innerHTML = newOut;
|
||||
modified.push(group);
|
||||
this.body.appendChild(group);
|
||||
this.screen = this.screen.slice(-this.rows);
|
||||
this.shift = 0;
|
||||
lines = document.querySelectorAll('.line');
|
||||
if (lines.length > this.scrollback) {
|
||||
ref4 = Array.prototype.slice.call(lines, 0, lines.length - this.scrollback);
|
||||
for (q = 0, len3 = ref4.length; q < len3; q++) {
|
||||
line = ref4[q];
|
||||
line.remove();
|
||||
}
|
||||
ref5 = document.querySelectorAll('.group:empty');
|
||||
for (u = 0, len4 = ref5.length; u < len4; u++) {
|
||||
group = ref5[u];
|
||||
group.remove();
|
||||
}
|
||||
lines = document.querySelectorAll('.line');
|
||||
if (groups.length) {
|
||||
return this._putGroup(groups);
|
||||
}
|
||||
};
|
||||
|
||||
Terminal.prototype._putGroup = function(groups) {
|
||||
var group, i, k, len, m, node, nodes, ref;
|
||||
group = this.document.createElement('div');
|
||||
group.className = 'group';
|
||||
group.innerHTML = groups.join('');
|
||||
if (true || groups.length > 1) {
|
||||
nodes = group.childNodes;
|
||||
node = group;
|
||||
} else {
|
||||
nodes = [group.firstChild];
|
||||
node = group.firstChild;
|
||||
}
|
||||
this.body.appendChild(node);
|
||||
for (k = 0, len = nodes.length; k < len; k++) {
|
||||
node = nodes[k];
|
||||
if (this.children.length >= this.rows) {
|
||||
this.children.pop();
|
||||
}
|
||||
this.children = Array.prototype.slice.call(lines, -this.rows);
|
||||
this.emit('change', node);
|
||||
this.children.push(node);
|
||||
}
|
||||
this.nativeScrollTo();
|
||||
return this.emit('change', modified);
|
||||
this.screen = this.screen.slice(-this.rows);
|
||||
this.shift = 0;
|
||||
if (this.body.childElementCount > this.scrollback) {
|
||||
this.body.style.display = 'none';
|
||||
for (i = m = 0, ref = this.body.childElementCount - this.scrollback; 0 <= ref ? m <= ref : m >= ref; i = 0 <= ref ? ++m : --m) {
|
||||
this.body.firstChild.remove();
|
||||
}
|
||||
return this.body.style.display = 'block';
|
||||
}
|
||||
};
|
||||
|
||||
Terminal.prototype.refresh = function(force) {
|
||||
var ref;
|
||||
if (force == null) {
|
||||
force = false;
|
||||
}
|
||||
if ((ref = this.active) != null) {
|
||||
ref.classList.remove('active');
|
||||
}
|
||||
this._replotScreen(force);
|
||||
return this.nativeScrollTo();
|
||||
};
|
||||
|
||||
Terminal.prototype._cursorBlink = function() {
|
||||
@@ -1747,6 +1781,7 @@
|
||||
j = oldRows;
|
||||
if (j < this.rows) {
|
||||
el = this.body;
|
||||
this.body.style.display = 'none';
|
||||
while (j++ < this.rows) {
|
||||
if (this.screen.length < this.rows) {
|
||||
this.screen.push(this.blankLine());
|
||||
@@ -1757,6 +1792,7 @@
|
||||
el.appendChild(line);
|
||||
this.children.push(line);
|
||||
}
|
||||
this.body.style.display = 'block';
|
||||
}
|
||||
} else if (j > this.rows) {
|
||||
while (j-- > this.rows) {
|
||||
|
||||
6
butterfly/static/main.min.js
vendored
6
butterfly/static/main.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -1,11 +1,10 @@
|
||||
Terminal.on 'change', (lines) ->
|
||||
for line in lines
|
||||
if 'extended' in line.classList
|
||||
line.addEventListener 'click', do (line) -> ->
|
||||
if 'expanded' in line.classList
|
||||
line.classList.remove 'expanded'
|
||||
else
|
||||
before = line.getBoundingClientRect().height
|
||||
line.classList.add 'expanded'
|
||||
after = line.getBoundingClientRect().height
|
||||
document.body.scrollTop += after - before
|
||||
Terminal.on 'change', (line) ->
|
||||
if 'extended' in line.classList
|
||||
line.addEventListener 'click', do (line) -> ->
|
||||
if 'expanded' in line.classList
|
||||
line.classList.remove 'expanded'
|
||||
else
|
||||
before = line.getBoundingClientRect().height
|
||||
line.classList.add 'expanded'
|
||||
after = line.getBoundingClientRect().height
|
||||
document.body.scrollTop += after - before
|
||||
|
||||
@@ -14,13 +14,12 @@ linkify = (text) ->
|
||||
.replace(pseudoUrlPattern, '$1<a href="http://$2">$2</a>')
|
||||
.replace(emailAddressPattern, '<a href="mailto:$&">$&</a>')
|
||||
|
||||
Terminal.on 'change', (lines) ->
|
||||
for line in lines
|
||||
walk line, ->
|
||||
if @nodeType is 3
|
||||
linkified = linkify @nodeValue
|
||||
if linkified isnt @nodeValue
|
||||
newNode = document.createElement('span')
|
||||
newNode.innerHTML = linkified
|
||||
@parentElement.replaceChild newNode, @
|
||||
true
|
||||
Terminal.on 'change', (line) ->
|
||||
walk line, ->
|
||||
if @nodeType is 3
|
||||
linkified = linkify @nodeValue
|
||||
if linkified isnt @nodeValue
|
||||
newNode = document.createElement('span')
|
||||
newNode.innerHTML = linkified
|
||||
@parentElement.replaceChild newNode, @
|
||||
true
|
||||
|
||||
@@ -84,7 +84,7 @@ class Terminal
|
||||
px = window.innerHeight % @charSize.height
|
||||
@body.style['padding-bottom'] = "#{px}px"
|
||||
|
||||
@scrollback = 1000000
|
||||
@scrollback = 10000
|
||||
@buffSize = 100000
|
||||
|
||||
@visualBell = 100
|
||||
@@ -114,12 +114,17 @@ class Terminal
|
||||
@initmouse()
|
||||
addEventListener 'load', => @resize()
|
||||
@emit 'load'
|
||||
@active = null
|
||||
Terminal.on 'change', (line) =>
|
||||
@active = line if line.classList.contains 'active'
|
||||
|
||||
emit: (hook, args...) ->
|
||||
emit: (hook, obj) ->
|
||||
unless Terminal.hooks[hook]?
|
||||
Terminal.hooks[hook] = []
|
||||
for fun in Terminal.hooks[hook]
|
||||
fun.apply(@, args)
|
||||
# fun.call(@, obj)
|
||||
setTimeout ((f) -> ->
|
||||
f.call(@, obj))(fun), 10
|
||||
|
||||
cloneAttr: (a, char=null) ->
|
||||
bg: a.bg
|
||||
@@ -415,157 +420,170 @@ class Terminal
|
||||
sendButton ev
|
||||
cancel ev
|
||||
|
||||
refresh: (force=false) ->
|
||||
for cursor in @body.querySelectorAll(".cursor")
|
||||
cursor.parentNode.replaceChild(
|
||||
@document.createTextNode(cursor.textContent), cursor)
|
||||
for active in @body.querySelectorAll(".line.active")
|
||||
active.classList.remove('active')
|
||||
_putChar: (data, attr, i, x) ->
|
||||
out = ''
|
||||
ch = data.ch
|
||||
unless @equalAttr data, attr
|
||||
out += "</span>" unless @equalAttr attr, @defAttr
|
||||
unless @equalAttr data, @defAttr
|
||||
classes = []
|
||||
styles = []
|
||||
out += "<span "
|
||||
|
||||
newOut = ''
|
||||
modified = []
|
||||
# bold
|
||||
classes.push "bold" if data.bold
|
||||
# underline
|
||||
classes.push "underline" if data.underline
|
||||
# blink
|
||||
classes.push "blink" if data.blink is 1
|
||||
classes.push "blink-fast" if data.blink is 2
|
||||
# inverse
|
||||
classes.push "reverse-video" if data.inverse
|
||||
# invisible
|
||||
classes.push "invisible" if data.invisible
|
||||
# italic
|
||||
classes.push "italic" if data.italic
|
||||
# faint
|
||||
classes.push "faint" if data.faint
|
||||
# crossed
|
||||
classes.push "crossed" if data.crossed
|
||||
|
||||
if typeof data.fg is 'number'
|
||||
fg = data.fg
|
||||
if data.bold and fg < 8
|
||||
fg += 8
|
||||
classes.push "fg-color-" + fg
|
||||
|
||||
if typeof data.fg is 'string'
|
||||
styles.push "color: " + data.fg
|
||||
|
||||
if typeof data.bg is 'number'
|
||||
classes.push "bg-color-" + data.bg
|
||||
|
||||
if typeof data.bg is 'string'
|
||||
styles.push "background-color: " + data.bg
|
||||
|
||||
out += "class=\""
|
||||
out += classes.join(" ")
|
||||
out += "\""
|
||||
if styles.length
|
||||
out += " style=\"" + styles.join("; ") + "\""
|
||||
out += ">"
|
||||
|
||||
out += "<span class=\"" + (
|
||||
if @cursorState then "reverse-video " else ""
|
||||
) + "cursor\">" if i is x
|
||||
|
||||
# This is a temporary dirty hack for raw html insertion
|
||||
if ch.length > 1
|
||||
out += ch
|
||||
else
|
||||
switch ch
|
||||
when "&"
|
||||
out += "&"
|
||||
when "<"
|
||||
out += "<"
|
||||
when ">"
|
||||
out += ">"
|
||||
else
|
||||
if ch == " "
|
||||
out += '<span class="nbsp">\u2007</span>'
|
||||
else if ch <= " "
|
||||
out += " "
|
||||
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 * @charSize.width}px\">#{ch}</span>"
|
||||
else
|
||||
out += "<span style=\"display: inline-block;
|
||||
width: #{@charSize.width}px\">#{ch}</span>"
|
||||
|
||||
out += "</span>" if i is x
|
||||
out
|
||||
|
||||
_putLine: (x, j, outs, line) ->
|
||||
@screen[j].dirty = false
|
||||
if @children[j]
|
||||
@children[j].innerHTML = outs.join('')
|
||||
@emit 'change', @children[j]
|
||||
if x isnt null
|
||||
@children[j].classList.add 'active'
|
||||
if line.extra
|
||||
@children[j].classList.add 'extended'
|
||||
null
|
||||
else
|
||||
cls = ['line']
|
||||
if x isnt null
|
||||
cls.push 'active'
|
||||
if line.extra
|
||||
cls.push 'extended'
|
||||
"<div class=\"#{cls.join(' ')}\">#{outs.join('')}</div>"
|
||||
|
||||
_replotScreen: (force) ->
|
||||
groups = []
|
||||
for line, j in @screen
|
||||
continue unless line.dirty or force
|
||||
out = ""
|
||||
|
||||
if j is @y + @shift and not @cursorHidden
|
||||
x = @x
|
||||
else
|
||||
x = -Infinity
|
||||
|
||||
x = null
|
||||
x = @x if j is @y + @shift and not @cursorHidden
|
||||
attr = @cloneAttr @defAttr
|
||||
skipnext = false
|
||||
outs = []
|
||||
for i in [0..@cols - 1]
|
||||
data = line.chars[i]
|
||||
if data.html
|
||||
out += data.html
|
||||
outs.push data.html
|
||||
break
|
||||
if skipnext
|
||||
skipnext = false
|
||||
continue
|
||||
|
||||
ch = data.ch
|
||||
unless @equalAttr data, attr
|
||||
out += "</span>" unless @equalAttr attr, @defAttr
|
||||
unless @equalAttr data, @defAttr
|
||||
classes = []
|
||||
styles = []
|
||||
out += "<span "
|
||||
|
||||
# bold
|
||||
classes.push "bold" if data.bold
|
||||
# underline
|
||||
classes.push "underline" if data.underline
|
||||
# blink
|
||||
classes.push "blink" if data.blink is 1
|
||||
classes.push "blink-fast" if data.blink is 2
|
||||
# inverse
|
||||
classes.push "reverse-video" if data.inverse
|
||||
# invisible
|
||||
classes.push "invisible" if data.invisible
|
||||
# italic
|
||||
classes.push "italic" if data.italic
|
||||
# faint
|
||||
classes.push "faint" if data.faint
|
||||
# crossed
|
||||
classes.push "crossed" if data.crossed
|
||||
|
||||
if typeof data.fg is 'number'
|
||||
fg = data.fg
|
||||
if data.bold and fg < 8
|
||||
fg += 8
|
||||
classes.push "fg-color-" + fg
|
||||
|
||||
if typeof data.fg is 'string'
|
||||
styles.push "color: " + data.fg
|
||||
|
||||
if typeof data.bg is 'number'
|
||||
classes.push "bg-color-" + data.bg
|
||||
|
||||
if typeof data.bg is 'string'
|
||||
styles.push "background-color: " + data.bg
|
||||
|
||||
out += "class=\""
|
||||
out += classes.join(" ")
|
||||
out += "\""
|
||||
if styles.length
|
||||
out += " style=\"" + styles.join("; ") + "\""
|
||||
out += ">"
|
||||
|
||||
out += "<span class=\"" + (
|
||||
if @cursorState then "reverse-video " else ""
|
||||
) + "cursor\">" if i is x
|
||||
|
||||
# This is a temporary dirty hack for raw html insertion
|
||||
if ch.length > 1
|
||||
out += ch
|
||||
else
|
||||
switch ch
|
||||
when "&"
|
||||
out += "&"
|
||||
when "<"
|
||||
out += "<"
|
||||
when ">"
|
||||
out += ">"
|
||||
else
|
||||
if ch == " "
|
||||
out += '<span class="nbsp">\u2007</span>'
|
||||
else if ch <= " "
|
||||
out += " "
|
||||
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 * @charSize.width}px\">#{ch}</span>"
|
||||
else
|
||||
out += "<span style=\"display: inline-block;
|
||||
width: #{@charSize.width}px\">#{ch}</span>"
|
||||
|
||||
out += "</span>" if i is x
|
||||
outs.push @_putChar data, attr, i, x
|
||||
attr = data
|
||||
|
||||
out = ''
|
||||
out += "</span>" unless @equalAttr attr, @defAttr
|
||||
out += '\u23CE' if line.wrap
|
||||
if line.extra
|
||||
out += '<span class="extra">' + line.extra + '</span>'
|
||||
if @children[j]
|
||||
@children[j].innerHTML = out
|
||||
modified.push @children[j]
|
||||
if x isnt -Infinity
|
||||
@children[j].classList.add 'active'
|
||||
if line.extra
|
||||
@children[j].classList.add 'extended'
|
||||
else
|
||||
cls = ['line']
|
||||
if x isnt -Infinity
|
||||
cls.push 'active'
|
||||
if line.extra
|
||||
cls.push 'extended'
|
||||
newOut += "<div class=\"#{cls.join(' ')}\">#{out}</div>"
|
||||
@screen[j].dirty = false
|
||||
outs.push out
|
||||
|
||||
if newOut isnt ''
|
||||
group = @document.createElement('div')
|
||||
group.className = 'group'
|
||||
group.innerHTML = newOut
|
||||
modified.push group
|
||||
@body.appendChild group
|
||||
@screen = @screen.slice(-@rows)
|
||||
@shift = 0
|
||||
group = @_putLine x, j, outs, line
|
||||
groups.push group if group
|
||||
@_putGroup groups if groups.length
|
||||
|
||||
lines = document.querySelectorAll('.line')
|
||||
if lines.length > @scrollback
|
||||
for line in Array.prototype.slice.call(
|
||||
lines, 0, lines.length - @scrollback)
|
||||
line.remove()
|
||||
for group in document.querySelectorAll('.group:empty')
|
||||
group.remove()
|
||||
lines = document.querySelectorAll('.line')
|
||||
@children = Array.prototype.slice.call(
|
||||
lines, -@rows)
|
||||
_putGroup: (groups) ->
|
||||
group = @document.createElement('div')
|
||||
group.className = 'group'
|
||||
group.innerHTML = groups.join('')
|
||||
|
||||
if true or groups.length > 1
|
||||
nodes = group.childNodes
|
||||
node = group
|
||||
else
|
||||
nodes = [group.firstChild]
|
||||
node = group.firstChild
|
||||
@body.appendChild node
|
||||
for node in nodes
|
||||
if @children.length >= @rows
|
||||
@children.pop()
|
||||
@emit 'change', node
|
||||
@children.push node
|
||||
@screen = @screen.slice(-@rows)
|
||||
@shift = 0
|
||||
|
||||
if @body.childElementCount > @scrollback
|
||||
@body.style.display = 'none'
|
||||
for i in [0..@body.childElementCount - @scrollback]
|
||||
@body.firstChild.remove()
|
||||
@body.style.display = 'block'
|
||||
|
||||
refresh: (force=false) ->
|
||||
@active?.classList.remove('active')
|
||||
@_replotScreen(force)
|
||||
@nativeScrollTo()
|
||||
@emit 'change', modified
|
||||
|
||||
_cursorBlink: ->
|
||||
@cursorState ^= 1
|
||||
@@ -1607,6 +1625,7 @@ class Terminal
|
||||
j = oldRows
|
||||
if j < @rows
|
||||
el = @body
|
||||
@body.style.display = 'none'
|
||||
while j++ < @rows
|
||||
@screen.push @blankLine() if @screen.length < @rows
|
||||
if @children.length < @rows
|
||||
@@ -1614,6 +1633,7 @@ class Terminal
|
||||
line.className = 'line'
|
||||
el.appendChild line
|
||||
@children.push line
|
||||
@body.style.display = 'block'
|
||||
else if j > @rows
|
||||
while j-- > @rows
|
||||
@screen.pop() if @screen.length > @rows
|
||||
|
||||
Reference in New Issue
Block a user