Coffized terminal.js
parent
d380577b2f
commit
a57cd2a241
@ -1,346 +0,0 @@
|
||||
SP.Terminal = function(cols, lines) {
|
||||
this.element = $(".player .term");
|
||||
|
||||
this.cols = cols;
|
||||
this.lines = lines;
|
||||
|
||||
this.cursorX = 0;
|
||||
this.cursorY = 0;
|
||||
|
||||
this.normalBuffer = [];
|
||||
this.alternateBuffer = [];
|
||||
this.lineData = this.normalBuffer;
|
||||
this.dirtyLines = [];
|
||||
|
||||
this.fg = this.bg = undefined;
|
||||
|
||||
this.createChildElements();
|
||||
this.showCursor(true);
|
||||
|
||||
// this.updateScreen();
|
||||
// this.render();
|
||||
|
||||
// this.renderLine(0); // we only need 1 line
|
||||
// this.element.css({ width: this.element.width(), height: this.element.height() });
|
||||
};
|
||||
|
||||
SP.Terminal.prototype = {
|
||||
createChildElements: function() {
|
||||
for (var i = 0; i < this.lines; i++) {
|
||||
var row = $('<span class="line">');
|
||||
this.element.append(row);
|
||||
this.element.append("\n");
|
||||
}
|
||||
},
|
||||
|
||||
getLine: function(n) {
|
||||
n = (typeof n != "undefined" ? n : this.cursorY);
|
||||
|
||||
if (n >= this.lines)
|
||||
throw 'cant getLine ' + n;
|
||||
|
||||
var line = this.lineData[n];
|
||||
|
||||
if (typeof line == 'undefined') {
|
||||
line = this.lineData[n] = [];
|
||||
this.fill(n, 0, this.cols, ' ');
|
||||
}
|
||||
|
||||
return line;
|
||||
},
|
||||
|
||||
clearScreen: function() {
|
||||
// this.lineData.length = 0;
|
||||
this.cursorY = this.cursorX = 0;
|
||||
this.element.find(".line").empty();
|
||||
},
|
||||
|
||||
switchToNormalBuffer: function() {
|
||||
this.lineData = this.normalBuffer;
|
||||
this.updateScreen();
|
||||
},
|
||||
|
||||
switchToAlternateBuffer: function() {
|
||||
this.lineData = this.alternateBuffer;
|
||||
this.updateScreen();
|
||||
},
|
||||
|
||||
renderLine: function(n) {
|
||||
var html = this.getLine(n);
|
||||
|
||||
if (n == this.cursorY) {
|
||||
html = html.slice(0, this.cursorX).concat(['<span class="cursor">' + (html[this.cursorX] || '') + "</span>"], html.slice(this.cursorX + 1) || []);
|
||||
}
|
||||
|
||||
this.element.find(".line:eq(" + n + ")").html(html.join(''));
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var updated = [];
|
||||
|
||||
for (var i=0; i<this.dirtyLines.length; i++) {
|
||||
var n = this.dirtyLines[i];
|
||||
if (updated.indexOf(n) == -1) {
|
||||
this.renderLine(n);
|
||||
updated.push(n);
|
||||
}
|
||||
}
|
||||
|
||||
this.dirtyLines = [];
|
||||
},
|
||||
|
||||
updateLine: function(n) {
|
||||
n = (typeof n != "undefined" ? n : this.cursorY);
|
||||
this.dirtyLines.push(n);
|
||||
},
|
||||
|
||||
updateScreen: function() {
|
||||
this.dirtyLines = [];
|
||||
|
||||
for (var l=0; l<this.lines; l++) {
|
||||
this.dirtyLines.push(l);
|
||||
}
|
||||
},
|
||||
|
||||
showCursor: function(show) {
|
||||
if (show) {
|
||||
this.element.addClass('cursor-on');
|
||||
} else {
|
||||
this.element.removeClass('cursor-on');
|
||||
}
|
||||
},
|
||||
|
||||
setSGR: function(codes) {
|
||||
if (codes.length == 0) {
|
||||
codes = [0];
|
||||
}
|
||||
|
||||
for (var i=0; i<codes.length; i++) {
|
||||
var n = codes[i];
|
||||
|
||||
if (n === 0) {
|
||||
this.fg = this.bg = undefined;
|
||||
this.bright = false;
|
||||
} else if (n == 1) {
|
||||
this.bright = true;
|
||||
} else if (n >= 30 && n <= 37) {
|
||||
this.fg = n - 30;
|
||||
} else if (n >= 40 && n <= 47) {
|
||||
this.bg = n - 40;
|
||||
} else if (n == 38) {
|
||||
this.fg = codes[i+2];
|
||||
i += 2;
|
||||
} else if (n == 48) {
|
||||
this.bg = codes[i+2];
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
setCursorPos: function(line, col) {
|
||||
line -= 1;
|
||||
col -= 1;
|
||||
var oldLine = this.cursorY;
|
||||
this.cursorY = line;
|
||||
this.cursorX = col;
|
||||
this.updateLine(oldLine);
|
||||
this.updateLine();
|
||||
},
|
||||
|
||||
saveCursor: function() {
|
||||
this.savedCol = this.cursorX;
|
||||
this.savedLine = this.cursorY;
|
||||
},
|
||||
|
||||
restoreCursor: function() {
|
||||
var oldLine = this.cursorY;
|
||||
|
||||
this.cursorY = this.savedLine;
|
||||
this.cursorX = this.savedCol;
|
||||
|
||||
this.updateLine(oldLine);
|
||||
this.updateLine();
|
||||
},
|
||||
|
||||
cursorLeft: function() {
|
||||
if (this.cursorX > 0) {
|
||||
this.cursorX -= 1;
|
||||
this.updateLine();
|
||||
}
|
||||
},
|
||||
|
||||
cursorRight: function() {
|
||||
if (this.cursorX < this.cols) {
|
||||
this.cursorX += 1;
|
||||
this.updateLine();
|
||||
}
|
||||
},
|
||||
|
||||
cursorUp: function() {
|
||||
if (this.cursorY > 0) {
|
||||
this.cursorY -= 1;
|
||||
this.updateLine(this.cursorY);
|
||||
this.updateLine(this.cursorY+1);
|
||||
}
|
||||
},
|
||||
|
||||
cursorDown: function() {
|
||||
if (this.cursorY + 1 < this.lines) {
|
||||
this.cursorY += 1;
|
||||
this.updateLine(this.cursorY-1);
|
||||
this.updateLine(this.cursorY);
|
||||
} else {
|
||||
this.lineData.splice(0, 1);
|
||||
this.updateScreen();
|
||||
}
|
||||
},
|
||||
|
||||
cursorForward: function(n) {
|
||||
for (var i=0; i<n; i++) this.cursorRight();
|
||||
},
|
||||
|
||||
cursorBack: function(n) {
|
||||
for (var i=0; i<n; i++) this.cursorLeft();
|
||||
},
|
||||
|
||||
cr: function() {
|
||||
this.cursorX = 0;
|
||||
this.updateLine();
|
||||
},
|
||||
|
||||
bs: function() {
|
||||
if (this.cursorX > 0) {
|
||||
this.getLine()[this.cursorX - 1] = ' ';
|
||||
this.cursorX -= 1;
|
||||
this.updateLine();
|
||||
}
|
||||
},
|
||||
|
||||
print: function(text) {
|
||||
text = Utf8.decode(text);
|
||||
|
||||
for (var i=0; i<text.length; i++) {
|
||||
if (this.cursorX >= this.cols) {
|
||||
this.cursorY += 1;
|
||||
this.cursorX = 0;
|
||||
}
|
||||
|
||||
this.fill(this.cursorY, this.cursorX, 1, text[i]);
|
||||
this.cursorX += 1;
|
||||
}
|
||||
|
||||
this.updateLine();
|
||||
},
|
||||
|
||||
eraseData: function(n) {
|
||||
if (n == 0) {
|
||||
this.eraseInLine(0);
|
||||
for (var l=this.cursorY+1; l<this.lines; l++) {
|
||||
this.clearLineData(l);
|
||||
this.updateLine(l);
|
||||
}
|
||||
} else if (n == 1) {
|
||||
for (var l=0; l<this.cursorY; l++) {
|
||||
this.clearLineData(l);
|
||||
this.updateLine(l);
|
||||
}
|
||||
this.eraseInLine(n);
|
||||
} else if (n == 2) {
|
||||
for (var l=0; l<this.lines; l++) {
|
||||
this.clearLineData(l);
|
||||
this.updateLine(l);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
eraseInLine: function(n) {
|
||||
if (n == 0) {
|
||||
this.fill(this.cursorY, this.cursorX, this.cols - this.cursorX, ' ');
|
||||
this.updateLine();
|
||||
} else if (n == 1) {
|
||||
this.fill(this.cursorY, 0, this.cursorX, ' ');
|
||||
this.updateLine();
|
||||
} else if (n == 2) {
|
||||
this.fill(this.cursorY, 0, this.cols, ' ');
|
||||
this.updateLine();
|
||||
}
|
||||
},
|
||||
|
||||
clearLineData: function(n) {
|
||||
this.fill(n, 0, this.cols, ' ');
|
||||
},
|
||||
|
||||
reserveCharacters: function(n) {
|
||||
var line = this.getLine();
|
||||
this.lineData[this.cursorY] = line.slice(0, this.cursorX).concat(" ".times(n).split(''), line.slice(this.cursorX, this.cols - n));
|
||||
this.updateLine();
|
||||
},
|
||||
|
||||
ri: function(n) {
|
||||
for (var i=0; i<n; i++) {
|
||||
if (this.cursorY == 0) {
|
||||
this.insertLines(0, n);
|
||||
} else {
|
||||
this.cursorUp();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
insertLines: function(l, n) {
|
||||
for (var i=0; i<n; i++) {
|
||||
this.lineData.splice(l, 0, []);
|
||||
this.clearLineData(l);
|
||||
}
|
||||
|
||||
this.lineData.length = this.lines;
|
||||
|
||||
this.updateScreen();
|
||||
},
|
||||
|
||||
fill: function(line, col, n, char) {
|
||||
var prefix = '', postfix = '';
|
||||
|
||||
if (this.fg !== undefined || this.bg !== undefined || this.bright) {
|
||||
prefix = '<span class="';
|
||||
var brightOffset = this.bright ? 8 : 0;
|
||||
|
||||
if (this.fg !== undefined) {
|
||||
prefix += ' fg' + (this.fg + brightOffset);
|
||||
} else if (this.bright) {
|
||||
prefix += ' bright';
|
||||
}
|
||||
|
||||
if (this.bg !== undefined) {
|
||||
prefix += ' bg' + this.bg;
|
||||
}
|
||||
|
||||
prefix += '">';
|
||||
postfix = '</span>';
|
||||
}
|
||||
|
||||
var char = prefix + char + postfix;
|
||||
|
||||
var lineArr = this.getLine(line);
|
||||
|
||||
for (var i=0; i<n; i++) {
|
||||
lineArr[col+i] = char;
|
||||
}
|
||||
},
|
||||
|
||||
blinkCursor: function() {
|
||||
var cursor = this.element.find(".cursor");
|
||||
if (cursor.hasClass("inverted")) {
|
||||
cursor.removeClass("inverted");
|
||||
} else {
|
||||
cursor.addClass("inverted");
|
||||
}
|
||||
},
|
||||
|
||||
restartCursorBlink: function() {
|
||||
if (this.cursorTimerId) {
|
||||
clearInterval(this.cursorTimerId);
|
||||
this.cursorTimerId = null;
|
||||
}
|
||||
this.cursorTimerId = setInterval(this.blinkCursor.bind(this), 500);
|
||||
}
|
||||
};
|
@ -0,0 +1,306 @@
|
||||
class AsciiIo.Terminal
|
||||
constructor: (cols, lines) ->
|
||||
@element = $(".player .term")
|
||||
@cols = cols
|
||||
@lines = lines
|
||||
@cursorX = 0
|
||||
@cursorY = 0
|
||||
@normalBuffer = []
|
||||
@alternateBuffer = []
|
||||
@lineData = @normalBuffer
|
||||
@dirtyLines = []
|
||||
@fg = @bg = undefined
|
||||
|
||||
@createChildElements()
|
||||
@showCursor true
|
||||
|
||||
# this.updateScreen();
|
||||
# this.render();
|
||||
#
|
||||
# this.renderLine(0); // we only need 1 line
|
||||
# this.element.css({ width: this.element.width(), height: this.element.height() });
|
||||
|
||||
createChildElements: ->
|
||||
i = 0
|
||||
|
||||
while i < @lines
|
||||
row = $("<span class=\"line\">")
|
||||
@element.append row
|
||||
@element.append "\n"
|
||||
i++
|
||||
|
||||
getLine: (n) ->
|
||||
n = (if typeof n isnt "undefined" then n else @cursorY)
|
||||
|
||||
throw "cant getLine " + n if n >= @lines
|
||||
|
||||
line = @lineData[n]
|
||||
|
||||
if typeof line is "undefined"
|
||||
line = @lineData[n] = []
|
||||
@fill n, 0, @cols, " "
|
||||
|
||||
line
|
||||
|
||||
clearScreen: ->
|
||||
# this.lineData.length = 0;
|
||||
@cursorY = @cursorX = 0
|
||||
@element.find(".line").empty()
|
||||
|
||||
switchToNormalBuffer: ->
|
||||
@lineData = @normalBuffer
|
||||
@updateScreen()
|
||||
|
||||
switchToAlternateBuffer: ->
|
||||
@lineData = @alternateBuffer
|
||||
@updateScreen()
|
||||
|
||||
renderLine: (n) ->
|
||||
html = @getLine(n)
|
||||
|
||||
if n is @cursorY
|
||||
html = html.slice(0, @cursorX).concat([ "<span class=\"cursor\">" + (html[@cursorX] or "") + "</span>" ], html.slice(@cursorX + 1) or [])
|
||||
|
||||
@element.find(".line:eq(" + n + ")").html html.join("")
|
||||
|
||||
render: ->
|
||||
updated = []
|
||||
|
||||
i = 0
|
||||
while i < @dirtyLines.length
|
||||
n = @dirtyLines[i]
|
||||
if updated.indexOf(n) is -1
|
||||
@renderLine n
|
||||
updated.push n
|
||||
i++
|
||||
|
||||
@dirtyLines = []
|
||||
|
||||
updateLine: (n) ->
|
||||
n = (if typeof n isnt "undefined" then n else @cursorY)
|
||||
@dirtyLines.push n
|
||||
|
||||
updateScreen: ->
|
||||
@dirtyLines = []
|
||||
|
||||
l = 0
|
||||
while l < @lines
|
||||
@dirtyLines.push l
|
||||
l++
|
||||
|
||||
showCursor: (show) ->
|
||||
if show
|
||||
@element.addClass "cursor-on"
|
||||
else
|
||||
@element.removeClass "cursor-on"
|
||||
|
||||
setSGR: (codes) ->
|
||||
codes = [0] if codes.length is 0
|
||||
|
||||
i = 0
|
||||
while i < codes.length
|
||||
n = codes[i]
|
||||
|
||||
if n is 0
|
||||
@fg = @bg = undefined
|
||||
@bright = false
|
||||
else if n is 1
|
||||
@bright = true
|
||||
else if n >= 30 and n <= 37
|
||||
@fg = n - 30
|
||||
else if n >= 40 and n <= 47
|
||||
@bg = n - 40
|
||||
else if n is 38
|
||||
@fg = codes[i + 2]
|
||||
i += 2
|
||||
else if n is 48
|
||||
@bg = codes[i + 2]
|
||||
i += 2
|
||||
i++
|
||||
|
||||
setCursorPos: (line, col) ->
|
||||
line -= 1
|
||||
col -= 1
|
||||
oldLine = @cursorY
|
||||
@cursorY = line
|
||||
@cursorX = col
|
||||
@updateLine oldLine
|
||||
@updateLine()
|
||||
|
||||
saveCursor: ->
|
||||
@savedCol = @cursorX
|
||||
@savedLine = @cursorY
|
||||
|
||||
restoreCursor: ->
|
||||
oldLine = @cursorY
|
||||
|
||||
@cursorY = @savedLine
|
||||
@cursorX = @savedCol
|
||||
|
||||
@updateLine oldLine
|
||||
@updateLine()
|
||||
|
||||
cursorLeft: ->
|
||||
if @cursorX > 0
|
||||
@cursorX -= 1
|
||||
@updateLine()
|
||||
|
||||
cursorRight: ->
|
||||
if @cursorX < @cols
|
||||
@cursorX += 1
|
||||
@updateLine()
|
||||
|
||||
cursorUp: ->
|
||||
if @cursorY > 0
|
||||
@cursorY -= 1
|
||||
@updateLine @cursorY
|
||||
@updateLine @cursorY + 1
|
||||
|
||||
cursorDown: ->
|
||||
if @cursorY + 1 < @lines
|
||||
@cursorY += 1
|
||||
@updateLine @cursorY - 1
|
||||
@updateLine @cursorY
|
||||
else
|
||||
@lineData.splice 0, 1
|
||||
@updateScreen()
|
||||
|
||||
cursorForward: (n) ->
|
||||
i = 0
|
||||
while i < n
|
||||
@cursorRight()
|
||||
i++
|
||||
|
||||
cursorBack: (n) ->
|
||||
i = 0
|
||||
while i < n
|
||||
@cursorLeft()
|
||||
i++
|
||||
|
||||
cr: ->
|
||||
@cursorX = 0
|
||||
@updateLine()
|
||||
|
||||
bs: ->
|
||||
if @cursorX > 0
|
||||
@getLine()[@cursorX - 1] = " "
|
||||
@cursorX -= 1
|
||||
@updateLine()
|
||||
|
||||
print: (text) ->
|
||||
text = Utf8.decode(text)
|
||||
|
||||
i = 0
|
||||
while i < text.length
|
||||
if @cursorX >= @cols
|
||||
@cursorY += 1
|
||||
@cursorX = 0
|
||||
|
||||
@fill @cursorY, @cursorX, 1, text[i]
|
||||
@cursorX += 1
|
||||
i++
|
||||
|
||||
@updateLine()
|
||||
|
||||
eraseData: (n) ->
|
||||
if n is 0
|
||||
@eraseInLine 0
|
||||
|
||||
l = @cursorY + 1
|
||||
while l < @lines
|
||||
@clearLineData l
|
||||
@updateLine l
|
||||
l++
|
||||
|
||||
else if n is 1
|
||||
l = 0
|
||||
while l < @cursorY
|
||||
@clearLineData l
|
||||
@updateLine l
|
||||
l++
|
||||
|
||||
@eraseInLine n
|
||||
|
||||
else if n is 2
|
||||
l = 0
|
||||
while l < @lines
|
||||
@clearLineData l
|
||||
@updateLine l
|
||||
l++
|
||||
|
||||
eraseInLine: (n) ->
|
||||
if n is 0
|
||||
@fill @cursorY, @cursorX, @cols - @cursorX, " "
|
||||
@updateLine()
|
||||
else if n is 1
|
||||
@fill @cursorY, 0, @cursorX, " "
|
||||
@updateLine()
|
||||
else if n is 2
|
||||
@fill @cursorY, 0, @cols, " "
|
||||
@updateLine()
|
||||
|
||||
clearLineData: (n) ->
|
||||
@fill n, 0, @cols, " "
|
||||
|
||||
reserveCharacters: (n) ->
|
||||
line = @getLine()
|
||||
@lineData[@cursorY] = line.slice(0, @cursorX).concat(" ".times(n).split(""), line.slice(@cursorX, @cols - n))
|
||||
@updateLine()
|
||||
|
||||
ri: (n) ->
|
||||
i = 0
|
||||
while i < n
|
||||
if @cursorY is 0
|
||||
@insertLines 0, n
|
||||
else
|
||||
@cursorUp()
|
||||
i++
|
||||
|
||||
insertLines: (l, n) ->
|
||||
i = 0
|
||||
while i < n
|
||||
@lineData.splice l, 0, []
|
||||
@clearLineData l
|
||||
i++
|
||||
|
||||
@lineData.length = @lines
|
||||
@updateScreen()
|
||||
|
||||
fill: (line, col, n, char) ->
|
||||
prefix = ""
|
||||
postfix = ""
|
||||
|
||||
if @fg isnt undefined or @bg isnt undefined or @bright
|
||||
prefix = "<span class=\""
|
||||
brightOffset = (if @bright then 8 else 0)
|
||||
|
||||
if @fg isnt undefined
|
||||
prefix += " fg" + (@fg + brightOffset)
|
||||
else if @bright
|
||||
prefix += " bright"
|
||||
|
||||
prefix += " bg" + @bg if @bg isnt undefined
|
||||
prefix += "\">"
|
||||
postfix = "</span>"
|
||||
|
||||
char = prefix + char + postfix
|
||||
lineArr = @getLine(line)
|
||||
|
||||
i = 0
|
||||
while i < n
|
||||
lineArr[col + i] = char
|
||||
i++
|
||||
|
||||
blinkCursor: ->
|
||||
cursor = @element.find(".cursor")
|
||||
if cursor.hasClass("inverted")
|
||||
cursor.removeClass "inverted"
|
||||
else
|
||||
cursor.addClass "inverted"
|
||||
|
||||
restartCursorBlink: ->
|
||||
if @cursorTimerId
|
||||
clearInterval @cursorTimerId
|
||||
@cursorTimerId = null
|
||||
|
||||
@cursorTimerId = setInterval(@blinkCursor.bind(this), 500)
|
Loading…
Reference in New Issue