This commit is contained in:
Florian Mounier
2015-04-16 14:42:17 +02:00
parent b03a3c836a
commit 23ffeb764e
5 changed files with 182 additions and 143 deletions

File diff suppressed because one or more lines are too long

View File

@@ -12,7 +12,7 @@
$ = document.querySelectorAll.bind(document);
document.addEventListener('DOMContentLoaded', function() {
var ctl, last_data, send, t_stop, term, ws, ws_url;
var ctl, last_data, queue, send, t_queue, t_stop, term, treat, ws, ws_url;
send = function(data) {
return ws.send('S' + data);
};
@@ -41,9 +41,18 @@
});
t_stop = null;
last_data = '';
t_queue = null;
queue = '';
ws.addEventListener('message', function(e) {
if (t_queue) {
clearTimeout(t_queue);
}
queue += e.data;
return t_queue = setTimeout(treat, 1);
});
treat = function() {
if (term.stop) {
last_data += e.data;
last_data += queue;
last_data = last_data.slice(-10 * 1024);
if (t_stop) {
if (t_stop) {
@@ -59,8 +68,9 @@
}, 100);
return;
}
return term.write(e.data);
});
term.write(queue);
return queue = '';
};
ws.addEventListener('close', function() {
console.log("WebSocket closed", arguments);
setTimeout(function() {
@@ -171,6 +181,7 @@
}
this.scrollback = 10000;
this.visualBell = 100;
this.shift = 0;
this.convertEol = false;
this.termName = 'xterm';
this.cursorBlink = true;
@@ -247,7 +258,7 @@
this.screen = [];
i = this.rows;
while (i--) {
this.screen.push(this.blank_line());
this.screen.push([this.blank_line(), true]);
}
this.setupStops();
return this.skipNextKey = null;
@@ -477,12 +488,15 @@
})(this));
};
Terminal.prototype.refresh = function(start, end) {
var attr, ch, classes, data, fg, html, i, j, k, l, line, m, out, ref, ref1, ref2, ref3, row, styles, x;
end = Math.min(end, this.screen.length - 1);
for (j = k = ref = start, ref1 = end; ref <= ref1 ? k <= ref1 : k >= ref1; j = ref <= ref1 ? ++k : --k) {
row = j;
line = this.screen[row];
Terminal.prototype.refresh = function() {
var attr, ch, classes, data, dirty, fg, html, i, j, k, l, len, line, m, new_out, out, ref, ref1, ref2, ref3, styles, x;
new_out = '';
ref = this.screen;
for (j = k = 0, len = ref.length; k < len; j = ++k) {
ref1 = ref[j], line = ref1[0], dirty = ref1[1];
if (!dirty) {
continue;
}
out = "";
if (j === this.y && !this.cursorHidden) {
x = this.x;
@@ -578,7 +592,16 @@
if (!this.equalAttr(attr, this.defAttr)) {
out += "</span>";
}
this.children[j].innerHTML = out;
if (this.children[j]) {
this.children[j].innerHTML = out;
} else {
new_out += "<div class=\"line\">" + out + "</div>";
}
this.screen[j][1] = false;
}
if (new_out !== '') {
this.element.innerHTML += new_out;
this.children = Array.prototype.slice.call(this.element.children, -this.rows);
}
ref3 = this.html;
for (l in ref3) {
@@ -633,25 +656,27 @@
Terminal.prototype.scroll = function() {
if (this.normal || this.scrollTop !== 0 || this.scrollBottom !== this.rows - 1) {
this.screen.splice(this.scrollBottom + 1, 0, this.blank_line());
this.screen.splice(this.scrollBottom + 1, 0, [this.blank_line(), true]);
this.screen.splice(this.scrollTop, 1);
this.y;
this.updateRange(this.scrollTop);
return this.updateRange(this.scrollBottom);
} else {
this.screen.shift();
this.screen.push(this.blank_line());
this.refreshStart = Math.max(this.refreshStart - 1, 0);
return this.new_line();
this.screen.push([this.blank_line(), true]);
return this.shift++;
}
};
Terminal.prototype.native_scroll_to = function(scroll) {
var last;
if (scroll == null) {
scroll = -1;
}
if (scroll === -1) {
return this.children.slice(-1)[0].scrollIntoView();
last = this.children.slice(-1)[0];
if ((last != null) && last !== '') {
return last.scrollIntoView();
}
} else {
return window.scrollTo(0, scroll);
}
@@ -661,18 +686,6 @@
return this.native_scroll_to(window.scrollY + disp * this.char_size.height);
};
Terminal.prototype.new_line = function() {
var div;
div = this.document.createElement('div');
div.className = 'line';
this.element.appendChild(div);
if (this.element.childElementCount > this.scrollback) {
this.element.children[0].remove();
}
this.children.shift();
return this.children.push(div);
};
Terminal.prototype.next_line = function() {
this.y++;
if (this.y > this.scrollBottom) {
@@ -683,8 +696,6 @@
Terminal.prototype.write = function(data) {
var ch, content, cs, html, i, l, pt, ref, ref1, type, valid;
this.refreshStart = this.y;
this.refreshEnd = this.y;
i = 0;
l = data.length;
while (i < l) {
@@ -729,19 +740,22 @@
ch = this.charset[ch];
}
if (this.x >= this.cols) {
this.screen[this.y][this.x] = this.cloneAttr(this.curAttr, '\u23CE');
this.screen[this.y][0][this.x] = this.cloneAttr(this.curAttr, '\u23CE');
this.screen[this.y][1] = true;
this.x = 0;
this.next_line();
}
this.updateRange(this.y);
this.screen[this.y][this.x] = this.cloneAttr(this.curAttr, ch);
this.screen[this.y][0][this.x] = this.cloneAttr(this.curAttr, ch);
this.screen[this.y][1][this.x] = true;
this.x++;
if (("\uff00" < ch && ch < "\uffef")) {
if (this.cols < 2 || this.x >= this.cols) {
this.screen[this.y][this.x - 1] = this.cloneAttr(this.curAttr, " ");
this.screen[this.y][0][this.x - 1] = this.cloneAttr(this.curAttr, " ");
this.screen[this.y][1] = true;
break;
}
this.screen[this.y][this.x] = this.cloneAttr(this.curAttr, " ");
this.screen[this.y][0][this.x] = this.cloneAttr(this.curAttr, " ");
this.screen[this.y][1][this.x] = true;
this.x++;
}
}
@@ -1486,15 +1500,15 @@
if (old_cols < this.cols) {
i = this.screen.length;
while (i--) {
while (this.screen[i].length < this.cols) {
this.screen[i].push(this.defAttr);
while (this.screen[i][0].length < this.cols) {
this.screen[i][0].push(this.defAttr);
}
}
} else if (old_cols > this.cols) {
i = this.screen.length;
while (i--) {
while (this.screen[i].length > this.cols) {
this.screen[i].pop();
while (this.screen[i][0].length > this.cols) {
this.screen[i][0].pop();
}
}
}
@@ -1504,7 +1518,7 @@
el = this.element;
while (j++ < this.rows) {
if (this.screen.length < this.rows) {
this.screen.push(this.blank_line());
this.screen.push([this.blank_line(), true]);
}
if (this.children.length < this.rows) {
line = this.document.createElement("div");
@@ -1534,7 +1548,7 @@
}
this.scrollTop = 0;
this.scrollBottom = this.rows - 1;
this.refresh(0, this.rows - 1);
this.refresh();
return this.normal = null;
};
@@ -1608,22 +1622,22 @@
Terminal.prototype.eraseRight = function(x, y) {
var line;
line = this.screen[y];
line = this.screen[y][0];
while (x < this.cols) {
line[x] = this.eraseAttr();
x++;
}
return this.updateRange(y);
return this.screen[y][1] = true;
};
Terminal.prototype.eraseLeft = function(x, y) {
var line;
line = this.screen[y];
line = this.screen[y][0];
x++;
while (x--) {
line[x] = this.eraseAttr();
}
return this.updateRange(y);
return this.screen[y][1] = true;
};
Terminal.prototype.eraseLine = function(y) {
@@ -1671,7 +1685,7 @@
var prevNode;
if (this.normal || this.scrollTop !== 0 || this.scrollBottom !== this.rows - 1) {
this.screen.splice(this.scrollBottom, 1);
this.screen.splice(this.scrollTop, 0, this.blank_line(true));
this.screen.splice(this.scrollTop, 0, [this.blank_line(true), true]);
this.maxRange();
} else {
prevNode = this.children[0].previousElementSibling;
@@ -1683,7 +1697,7 @@
this.new_line();
}
this.screen.pop();
this.screen.unshift(this.blank_line());
this.screen.unshift([this.blank_line(), true]);
}
this.maxRange();
return this.state = State.normal;
@@ -1919,7 +1933,7 @@
j = this.x;
results = [];
while (param-- && j < this.cols) {
this.screen[row].splice(j++, 0, this.eraseAttr());
this.screen[row].splice(j++, 0, [this.eraseAttr(), true]);
results.push(this.screen[row].pop());
}
return results;
@@ -1967,7 +1981,7 @@
param = 1;
}
while (param--) {
this.screen.splice(this.y, 0, this.blank_line(true));
this.screen.splice(this.y, 0, [this.blank_line(true), true]);
this.screen.splice(this.scrollBottom + 1, 1);
}
this.updateRange(this.y);
@@ -1982,7 +1996,7 @@
}
row = this.y;
while (param--) {
this.screen.push(this.blank_line(true));
this.screen.push([this.blank_line(true), true]);
this.screen.splice(this.y, 1);
}
this.updateRange(this.y);
@@ -1990,33 +2004,31 @@
};
Terminal.prototype.deleteChars = function(params) {
var param, results, row;
var param, row;
param = params[0];
if (param < 1) {
param = 1;
}
row = this.y;
results = [];
while (param--) {
this.screen[row].splice(this.x, 1);
results.push(this.screen[row].push(this.eraseAttr()));
this.screen[row][0].splice(this.x, 1);
this.screen[row][0].push(this.eraseAttr());
}
return results;
return this.screen[row][1] = true;
};
Terminal.prototype.eraseChars = function(params) {
var j, param, results, row;
var j, param, row;
param = params[0];
if (param < 1) {
param = 1;
}
row = this.y;
j = this.x;
results = [];
while (param-- && j < this.cols) {
results.push(this.screen[row][j++] = this.eraseAttr());
this.screen[row][0][j++] = this.eraseAttr();
}
return results;
return this.screen[row][1] = true;
};
Terminal.prototype.charPosAbsolute = function(params) {
@@ -2277,7 +2289,7 @@
param = params[0] || 1;
while (param--) {
this.screen.splice(this.scrollTop, 1);
this.screen.splice(this.scrollBottom, 0, this.blank_line());
this.screen.splice(this.scrollBottom, 0, [this.blank_line(), true]);
}
this.updateRange(this.scrollTop);
return this.updateRange(this.scrollBottom);
@@ -2288,7 +2300,7 @@
param = params[0] || 1;
while (param--) {
this.screen.splice(this.scrollBottom, 1);
this.screen.splice(this.scrollTop, 0, this.blank_line());
this.screen.splice(this.scrollTop, 0, [this.blank_line(), true]);
}
this.updateRange(this.scrollTop);
return this.updateRange(this.scrollBottom);
@@ -2309,15 +2321,14 @@
};
Terminal.prototype.repeatPrecedingCharacter = function(params) {
var ch, line, param, results;
var ch, line, param;
param = params[0] || 1;
line = this.screen[this.y];
line = this.screen[this.y][0];
ch = line[this.x - 1] || this.defAttr;
results = [];
while (param--) {
results.push(line[this.x++] = ch);
line[this.x++] = ch;
}
return results;
return this.screen[this.y][1] = true;
};
Terminal.prototype.tabClear = function(params) {
@@ -2378,7 +2389,8 @@
r = params[3];
attr = params[4];
while (t < b + 1) {
line = this.screen[t];
line = this.screen[t][0];
this.screen[t][1] = true;
i = l;
while (i < r) {
line[i] = this.cloneAttr(attr, line[i].ch);
@@ -2418,7 +2430,8 @@
b = params[3];
r = params[4];
while (t < b + 1) {
line = this.screen[t];
line = this.screen[t][0];
this.screen[t][1] = true;
i = l;
while (i < r) {
line[i] = this.cloneAttr(line[i][0], String.fromCharCode(ch));
@@ -2442,7 +2455,8 @@
b = params[2];
r = params[3];
while (t < b + 1) {
line = this.screen[t];
line = this.screen[t][0];
this.screen[t][1] = true;
i = l;
while (i < r) {
line[i] = this.eraseAttr();
@@ -2467,12 +2481,12 @@
while (param--) {
i = 0;
while (i < l) {
this.screen[i].splice(this.x + 1, 0, this.eraseAttr());
this.screen[i].pop();
this.screen[i][0].splice(this.x + 1, 0, this.eraseAttr());
this.screen[i][0].pop();
i++;
}
}
return this.maxRange();
return this.screen[i][1] = true;
};
Terminal.prototype.deleteColumns = function() {
@@ -2482,12 +2496,12 @@
while (param--) {
i = 0;
while (i < l) {
this.screen[i].splice(this.x, 1);
this.screen[i].push(this.eraseAttr());
this.screen[i][0].splice(this.x, 1);
this.screen[i][0].push(this.eraseAttr());
i++;
}
}
return this.maxRange();
return this.screen[i][1] = true;
};
Terminal.prototype.charsets = {

File diff suppressed because one or more lines are too long

View File

@@ -49,9 +49,17 @@ document.addEventListener 'DOMContentLoaded', ->
t_stop = null
last_data = ''
t_queue = null
queue = ''
ws.addEventListener 'message', (e) ->
clearTimeout t_queue if t_queue
queue += e.data
t_queue = setTimeout treat, 1
treat = ->
if term.stop
last_data += e.data
last_data += queue
last_data = last_data.slice(-10 * 1024) # Keep last 10kb
if t_stop
clearTimeout t_stop if t_stop
@@ -64,7 +72,8 @@ document.addEventListener 'DOMContentLoaded', ->
, 100
return
term.write e.data
term.write queue
queue = ''
ws.addEventListener 'close', ->
console.log "WebSocket closed", arguments

View File

@@ -84,7 +84,7 @@ class Terminal
@scrollback = 10000
@visualBell = 100
@shift = 0
@convertEol = false
@termName = 'xterm'
@cursorBlink = true
@@ -166,7 +166,7 @@ class Terminal
@prefix = ""
@screen = []
i = @rows
@screen.push @blank_line() while i--
@screen.push [@blank_line(), true] while i--
@setupStops()
@skipNextKey = null
@@ -388,12 +388,10 @@ class Terminal
sendButton ev
cancel ev
refresh: (start, end) ->
end = Math.min(end, @screen.length - 1)
for j in [start..end]
row = j
line = @screen[row]
refresh: ->
new_out = ''
for [line, dirty], j in @screen
continue unless dirty
out = ""
if j is @y and not @cursorHidden
@@ -471,7 +469,16 @@ class Terminal
out += "</span>" if i is x
attr = data
out += "</span>" unless @equalAttr attr, @defAttr
@children[j].innerHTML = out
if @children[j]
@children[j].innerHTML = out
else
new_out += "<div class=\"line\">#{out}</div>"
@screen[j][1] = false
if new_out isnt ''
@element.innerHTML += new_out
@children = Array.prototype.slice.call(@element.children, -@rows)
for l, html of @html
@children[l].innerHTML = ''
@@ -511,36 +518,39 @@ 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 @scrollBottom + 1, 0, @blank_line()
@screen.splice @scrollBottom + 1, 0, [@blank_line(), true]
@screen.splice @scrollTop, 1
@y
@updateRange @scrollTop
@updateRange @scrollBottom
else
@screen.shift()
@screen.push @blank_line()
@refreshStart = Math.max(@refreshStart - 1, 0)
@new_line()
# @screen.shift()
@screen.push [@blank_line(), true]
@shift++
# @refreshStart = Math.max(@refreshStart - 1, 0)
# @new_line()
native_scroll_to: (scroll=-1) ->
if scroll is -1
@children.slice(-1)[0].scrollIntoView()
last = @children.slice(-1)[0]
if last? and last isnt ''
last.scrollIntoView()
else
window.scrollTo 0, scroll
scroll_display: (disp) ->
@native_scroll_to window.scrollY + disp * @char_size.height
new_line: ->
div = @document.createElement('div')
div.className = 'line'
@element.appendChild(div)
if @element.childElementCount > @scrollback
@element.children[0].remove()
# new_line: ->
# # div = @document.createElement('div')
# # div.className = 'line'
# # @element.appendChild(div)
# while @element.childElementCount > @scrollback
# @element.firstChild.remove()
@children.shift()
@children.push(div)
# @children.shift()
# # @children.push('')
next_line: ->
@y++
@@ -549,8 +559,8 @@ class Terminal
@scroll()
write: (data) ->
@refreshStart = @y
@refreshEnd = @y
# @refreshStart = @y
# @refreshEnd = @y
i = 0
l = data.length
@@ -598,20 +608,22 @@ class Terminal
if ch >= " "
ch = @charset[ch] if @charset?[ch]
if @x >= @cols
@screen[@y][@x] = @cloneAttr @curAttr, '\u23CE'
@screen[@y][0][@x] = @cloneAttr @curAttr, '\u23CE'
@screen[@y][1] = true
@x = 0
@next_line()
@updateRange @y
@screen[@y][@x] = @cloneAttr @curAttr, ch
@screen[@y][0][@x] = @cloneAttr @curAttr, ch
@screen[@y][1][@x] = true
@x++
if "\uff00" < ch < "\uffef"
if @cols < 2 or @x >= @cols
@screen[@y][@x - 1] = @cloneAttr @curAttr, " "
@screen[@y][0][@x - 1] = @cloneAttr @curAttr, " "
@screen[@y][1] = true
break
@screen[@y][@x] = @cloneAttr @curAttr, " "
@screen[@y][0][@x] = @cloneAttr @curAttr, " "
@screen[@y][1][@x] = true
@x++
when State.escaped
@@ -1432,11 +1444,11 @@ class Terminal
# does xterm use the default attr?
i = @screen.length
while i--
@screen[i].push @defAttr while @screen[i].length < @cols
@screen[i][0].push @defAttr while @screen[i][0].length < @cols
else if old_cols > @cols
i = @screen.length
while i--
@screen[i].pop() while @screen[i].length > @cols
@screen[i][0].pop() while @screen[i][0].length > @cols
@setupStops old_cols
@@ -1445,7 +1457,7 @@ class Terminal
if j < @rows
el = @element
while j++ < @rows
@screen.push @blank_line() if @screen.length < @rows
@screen.push [@blank_line(), true] if @screen.length < @rows
if @children.length < @rows
line = @document.createElement("div")
line.className = 'line'
@@ -1465,7 +1477,7 @@ class Terminal
@scrollTop = 0
@scrollBottom = @rows - 1
@refresh 0, @rows - 1
@refresh()
# it's a real nightmare trying
# to resize the original
@@ -1506,20 +1518,20 @@ class Terminal
if x >= @cols then @cols - 1 else (if x < 0 then 0 else x)
eraseRight: (x, y) ->
line = @screen[y]
line = @screen[y][0]
# xterm
while x < @cols
line[x] = @eraseAttr()
x++
@updateRange y
@screen[y][1] = true
eraseLeft: (x, y) ->
line = @screen[y]
line = @screen[y][0]
# xterm
x++
line[x] = @eraseAttr() while x--
@updateRange y
@screen[y][1] = true
eraseLine: (y) ->
@eraseRight 0, y
@@ -1557,7 +1569,7 @@ class Terminal
if @normal or @scrollTop isnt 0 or @scrollBottom isnt @rows - 1
# inner scroll
@screen.splice @scrollBottom, 1
@screen.splice @scrollTop, 0, @blank_line(true)
@screen.splice @scrollTop, 0, [@blank_line(true), true]
@maxRange()
else
prevNode = @children[0].previousElementSibling
@@ -1568,7 +1580,7 @@ class Terminal
else
@new_line()
@screen.pop()
@screen.unshift @blank_line()
@screen.unshift [@blank_line(), true]
@maxRange()
@state = State.normal
@@ -1891,7 +1903,7 @@ class Terminal
j = @x
# xterm
while param-- and j < @cols
@screen[row].splice j++, 0, @eraseAttr()
@screen[row].splice j++, 0, [@eraseAttr(), true]
@screen[row].pop()
@@ -1932,7 +1944,7 @@ class Terminal
param = 1 if param < 1
while param--
@screen.splice @y, 0, @blank_line(true)
@screen.splice @y, 0, [@blank_line(true), true]
# blank_line(true) - xterm/linux behavior
@screen.splice @scrollBottom + 1, 1
@@ -1949,7 +1961,7 @@ class Terminal
while param--
# test: echo -e '\e[44m\e[1M\e[0m'
# blank_line(true) - xterm/linux behavior
@screen.push @blank_line(true)
@screen.push [@blank_line(true), true]
@screen.splice @y, 1
@updateRange @y
@@ -1963,8 +1975,9 @@ class Terminal
row = @y
# xterm
while param--
@screen[row].splice @x, 1
@screen[row].push @eraseAttr()
@screen[row][0].splice @x, 1
@screen[row][0].push @eraseAttr()
@screen[row][1] = true
# CSI Ps X
@@ -1975,8 +1988,8 @@ class Terminal
row = @y
j = @x
# xterm
@screen[row][j++] = @eraseAttr() while param-- and j < @cols
@screen[row][0][j++] = @eraseAttr() while param-- and j < @cols
@screen[row][1] = true
# CSI Pm ` Character Position Absolute
# [column] (default = [row,1]) (HPA).
@@ -2413,7 +2426,7 @@ class Terminal
param = params[0] or 1
while param--
@screen.splice @scrollTop, 1
@screen.splice @scrollBottom, 0, @blank_line()
@screen.splice @scrollBottom, 0, [@blank_line(), true]
@updateRange @scrollTop
@updateRange @scrollBottom
@@ -2424,7 +2437,7 @@ class Terminal
param = params[0] or 1
while param--
@screen.splice @scrollBottom, 1
@screen.splice @scrollTop, 0, @blank_line()
@screen.splice @scrollTop, 0, [@blank_line(), true]
@updateRange @scrollTop
@updateRange @scrollBottom
@@ -2461,10 +2474,10 @@ class Terminal
# CSI Ps b Repeat the preceding graphic character Ps times (REP).
repeatPrecedingCharacter: (params) ->
param = params[0] or 1
line = @screen[@y]
line = @screen[@y][0]
ch = line[@x - 1] or @defAttr
line[@x++] = ch while param--
@screen[@y][1] = true
# CSI Ps g Tab Clear (TBC).
# Ps = 0 -> Clear Current Column (default).
@@ -2635,7 +2648,8 @@ class Terminal
r = params[3]
attr = params[4]
while t < b + 1
line = @screen[t]
line = @screen[t][0]
@screen[t][1] = true
i = l
while i < r
line[i] = @cloneAttr attr, line[i].ch
@@ -2794,7 +2808,8 @@ class Terminal
b = params[3]
r = params[4]
while t < b + 1
line = @screen[t]
line = @screen[t][0]
@screen[t][1] = true
i = l
while i < r
line[i] = @cloneAttr line[i][0], String.fromCharCode(ch)
@@ -2831,7 +2846,8 @@ class Terminal
b = params[2]
r = params[3]
while t < b + 1
line = @screen[t]
line = @screen[t][0]
@screen[t][1] = true
i = l
while i < r
line[i] = @eraseAttr()
@@ -2914,10 +2930,10 @@ class Terminal
while param--
i = 0
while i < l
@screen[i].splice @x + 1, 0, @eraseAttr()
@screen[i].pop()
@screen[i][0].splice @x + 1, 0, @eraseAttr()
@screen[i][0].pop()
i++
@maxRange()
@screen[i][1] = true
# CSI P m SP ~
@@ -2929,10 +2945,10 @@ class Terminal
while param--
i = 0
while i < l
@screen[i].splice @x, 1
@screen[i].push @eraseAttr()
@screen[i][0].splice @x, 1
@screen[i][0].push @eraseAttr()
i++
@maxRange()
@screen[i][1] = true
# DEC Special Character and Line Drawing Set.
# http://vt100.net/docs/vt102-ug/table5-13.html