VT = Ansi interpreter + (embedded) screen buffer

openid
Marcin Kulik 13 years ago
parent a378358abf
commit 5d6ba15b19

@ -6,13 +6,8 @@
//
//= require jquery
//= require jquery_ujs
//= require utf8
//= require helpers
//= require vendor/underscore-min
//= require vendor/backbone-min
//= require backbone/ascii_io
//= require namespace
//= require terminal_view
//= require player_view
//= require ansi-interpreter
//= require player/player
//= require_tree .

@ -0,0 +1,8 @@
//= require ./namespace
//= require ./utf8
//= require ./screen_buffer
//= require ./terminal_view
//= require ./vt
//= require ./hud_view
//= require ./player_view
//= require_tree .

@ -2,17 +2,17 @@ class AsciiIo.PlayerView extends Backbone.View
initialize: (options) ->
@movie = new AsciiIo.Movie(options.data, options.timing)
@screenBuffer = new AsciiIo.ScreenBuffer(options.cols, options.lines)
@interpreter = new AsciiIo.AnsiInterpreter(@screenBuffer)
@terminalView = new AsciiIo.TerminalView(
cols: this.options.cols
lines: this.options.lines
)
@vt = new AsciiIo.VT(options.cols, options.lines, @terminalView)
@createChildViews()
@bindEvents()
createChildViews: ->
@terminalView = new AsciiIo.TerminalView(
cols: this.options.cols
lines: this.options.lines
)
@$el.append(@terminalView.$el)
@hudView = new AsciiIo.HudView()
@ -29,10 +29,10 @@ class AsciiIo.PlayerView extends Backbone.View
@movie.seek(percent)
@movie.on 'movie-frame', (frame) =>
@interpreter.feed(frame)
changes = @screenBuffer.changes()
@terminalView.render(changes)
@screenBuffer.clearChanges()
@vt.feed(frame)
# changes = @screenBuffer.changes()
# @terminalView.render(changes)
# @screenBuffer.clearChanges()
@movie.on 'movie-finished', =>
@terminalView.stopCursorBlink()

@ -7,6 +7,7 @@ class AsciiIo.ScreenBuffer
@alternateBuffer = []
@lineData = @normalBuffer
@dirtyLines = {}
@brush = AsciiIo.Brush.create({})
setBrush: (brush) ->
@brush = brush
@ -204,34 +205,19 @@ class AsciiIo.ScreenBuffer
@updateScreen()
fill: (line, col, n, char) ->
prefix = ""
postfix = ""
if @fg isnt undefined or @bg isnt undefined or @bright or @underline
prefix = "<span class=\""
brightOffset = (if @bright then 8 else 0)
if @fg isnt undefined
prefix += " fg" + (@fg + brightOffset)
else if @bright
prefix += " bright"
if @underline
prefix += " underline"
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
lineArr[col + i] = [char, @brush]
i++
changes: ->
{}
c = {}
for _, n of @dirtyLines
c[n] = @lineData[n]
c
clearChanges: ->
@dirtyLines = {}

@ -8,7 +8,7 @@ class AsciiIo.TerminalView extends Backbone.View
@createChildElements()
@showCursor true
@startCursorBlink()
# this.updateScreen();
# this.render();
#
@ -26,23 +26,53 @@ class AsciiIo.TerminalView extends Backbone.View
clearScreen: ->
# this.lineData.length = 0;
@cursorY = @cursorX = 0
# @cursorY = @cursorX = 0
@$el.find(".line").empty()
render: ->
for _, n of @dirtyLines
@renderLine n
render: (changes, cursorX, cursorY) ->
@$el.find('.cursor').removeClass('cursor')
# @dirtyLines = {}
for n, data of changes
c = if parseInt(n) is cursorY then cursorX else undefined
@renderLine n, data || [], c
renderLine: (n) ->
html = @getLine(n)
renderLine: (n, data, cursorX) ->
html = []
i = 0
if n is @cursorY
html = html.slice(0, @cursorX).concat([ "<span class=\"cursor\">" + (html[@cursorX] or "") + "</span>" ], html.slice(@cursorX + 1) or [])
for d in data
if d
[char, brush] = d
html[i] = @createSpan(char, brush, i is cursorX)
else
html[i] = ' '
i++
@$el.find(".line:eq(" + n + ")").html html.join("")
createSpan: (char, brush, hasCursor) ->
prefix = ""
postfix = ""
if hasCursor or brush.fg isnt undefined or brush.bg isnt undefined or brush.bright or brush.underline
prefix = "<span class=\""
brightOffset = (if brush.bright then 8 else 0)
if brush.fg isnt undefined
prefix += " fg" + (brush.fg + brightOffset)
else if brush.bright
prefix += " bright"
if brush.underline
prefix += " underline"
prefix += " bg" + brush.bg if brush.bg isnt undefined
prefix += " cursor" if hasCursor
prefix += "\">"
postfix = "</span>"
prefix + char + postfix
showCursor: (show) ->
if show
@$el.addClass "cursor-on"
@ -67,3 +97,5 @@ class AsciiIo.TerminalView extends Backbone.View
restartCursorBlink: ->
@stopCursorBlink()
@startCursorBlink()
visualBell: ->

@ -1,7 +1,7 @@
class AsciiIo.AnsiInterpreter
class AsciiIo.VT
constructor: (screenBuffer) ->
@sb = screenBuffer
constructor: (cols, lines, @renderer) ->
@sb = new AsciiIo.ScreenBuffer(cols, lines)
@fg = @bg = undefined
@bright = false
@ -79,7 +79,7 @@ class AsciiIo.AnsiInterpreter
PATTERNS:
"\x00": (data) ->
"\x07": (data) -> @sb.bell()
"\x07": (data) -> @bell()
"\x08": (data) -> @sb.backspace()
"\x09": (data) -> # Moves the cursor to the next tab stop
"\x0a": (data) -> @sb.cursorDown 1
@ -127,9 +127,9 @@ class AsciiIo.AnsiInterpreter
# steady cursor
else if mode is "25"
if action is "h"
@sb.showCursor true
@renderer.showCursor true
else if action is "l"
@sb.showCursor false
@renderer.showCursor false
else if mode is "47"
if action is "h"
@sb.switchToAlternateBuffer()
@ -252,6 +252,10 @@ class AsciiIo.AnsiInterpreter
@sb.setBrush AsciiIo.Brush.create(props)
bell: ->
@renderer.visualBell()
# @trigger('bell')
compilePatterns: ->
@COMPILED_PATTERNS = ([new RegExp("^" + re), f] for re, f of @PATTERNS)
@ -270,4 +274,8 @@ class AsciiIo.AnsiInterpreter
break unless match
changes = @sb.changes()
@renderer.render(changes, @sb.cursorX, @sb.cursorY)
@sb.clearChanges()
data.length is 0

@ -0,0 +1,145 @@
/**
* @name jQuery FullScreen Plugin
* @author Martin Angelov
* @version 1.0
* @url http://tutorialzine.com/2012/02/enhance-your-website-fullscreen-api/
* @license MIT License
*/
(function($){
// Adding a new test to the jQuery support object
$.support.fullscreen = supportFullScreen();
// Creating the plugin
$.fn.fullScreen = function(props){
if(!$.support.fullscreen || this.length != 1){
// The plugin can be called only
// on one element at a time
return this;
}
if(fullScreenStatus()){
// if we are already in fullscreen, exit
cancelFullScreen();
return this;
}
// You can potentially pas two arguments a color
// for the background and a callback function
var options = $.extend({
'background' : '#111',
'callback' : function(){}
}, props);
// This temporary div is the element that is
// actually going to be enlarged in full screen
var fs = $('<div>',{
'css' : {
'overflow-y' : 'auto',
'background' : options.background,
'width' : '100%',
'height' : '100%'
}
});
var elem = this;
// You can use the .fullScreen class to
// apply styling to your element
elem.addClass('fullScreen');
// Inserting our element in the temporary
// div, after which we zoom it in fullscreen
fs.insertBefore(elem);
fs.append(elem);
requestFullScreen(fs.get(0));
fs.click(function(e){
if(e.target == this){
// If the black bar was clicked
cancelFullScreen();
}
});
elem.cancel = function(){
cancelFullScreen();
return elem;
};
onFullScreenEvent(function(fullScreen){
if(!fullScreen){
// We have exited full screen.
// Remove the class and destroy
// the temporary div
elem.removeClass('fullScreen').insertBefore(fs);
fs.remove();
}
// Calling the user supplied callback
options.callback(fullScreen);
});
return elem;
};
// These helper functions available only to our plugin scope.
function supportFullScreen(){
var doc = document.documentElement;
return ('requestFullscreen' in doc) ||
('mozRequestFullScreen' in doc && document.mozFullScreenEnabled) ||
('webkitRequestFullScreen' in doc);
}
function requestFullScreen(elem){
if (elem.requestFullscreen) {
elem.requestFullscreen();
}
else if (elem.mozRequestFullScreen) {
elem.mozRequestFullScreen();
}
else if (elem.webkitRequestFullScreen) {
elem.webkitRequestFullScreen();
}
}
function fullScreenStatus(){
return document.fullscreen ||
document.mozFullScreen ||
document.webkitIsFullScreen;
}
function cancelFullScreen(){
if (document.exitFullscreen) {
document.exitFullscreen();
}
else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
}
else if (document.webkitCancelFullScreen) {
document.webkitCancelFullScreen();
}
}
function onFullScreenEvent(callback){
$(document).on("fullscreenchange mozfullscreenchange webkitfullscreenchange", function(){
// The full screen status is automatically
// passed to our callback as an argument.
callback(fullScreenStatus());
});
}
})(jQuery);

@ -2,6 +2,11 @@
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/
.asciicast {
width: 100%;
background-color: #222
}
.player {
/* border: 1px solid #777;*/
/* background-color: #333;*/

@ -1,16 +1,19 @@
describe AsciiIo.AnsiInterpreter, ->
interpreter = screenBuffer = data = undefined
describe AsciiIo.VT, ->
vt = renderer = data = undefined
cols = 80
lines = 24
isSwallowed = (d) ->
screenBuffer = {} # will throw 'undefined is not a function'
interpreter = new AsciiIo.AnsiInterpreter(screenBuffer)
expect(interpreter.feed(d || data)).toEqual(true)
# vt = new AsciiIo.VT(cols, lines, renderer)
vt.sb = {} # will throw 'undefined is not a function'
expect(vt.feed(d || data)).toEqual(true)
beforeEach ->
screenBuffer = new AsciiIo.ScreenBuffer(cols, lines)
interpreter = new AsciiIo.AnsiInterpreter(screenBuffer)
console.log 'kurwa'
console.log AsciiIo.TerminalView
renderer = new AsciiIo.TerminalView({ cols: cols, lines: lines })
vt = new AsciiIo.VT(cols, lines, renderer)
console.log vt
data = ''
describe '#feed', ->
@ -21,30 +24,30 @@ describe AsciiIo.AnsiInterpreter, ->
describe 'x07', ->
it 'calls bell', ->
data += '\x07'
spyOn screenBuffer, 'bell'
interpreter.feed(data)
expect(screenBuffer.bell).toHaveBeenCalled()
spyOn vt, 'bell'
vt.feed(data)
expect(vt.bell).toHaveBeenCalled()
describe 'x08', ->
it 'calls backspace', ->
data += '\x08'
spyOn screenBuffer, 'backspace'
interpreter.feed(data)
expect(screenBuffer.backspace).toHaveBeenCalled()
spyOn vt.sb, 'backspace'
vt.feed(data)
expect(vt.sb.backspace).toHaveBeenCalled()
describe 'x0a', ->
it 'calls cursorDown(1)', ->
data += '\x0a'
spyOn screenBuffer, 'cursorDown'
interpreter.feed(data)
expect(screenBuffer.cursorDown).toHaveBeenCalledWith(1)
spyOn vt.sb, 'cursorDown'
vt.feed(data)
expect(vt.sb.cursorDown).toHaveBeenCalledWith(1)
describe 'x0d', ->
it 'calls cr', ->
data += '\x0d'
spyOn screenBuffer, 'cr'
interpreter.feed(data)
expect(screenBuffer.cr).toHaveBeenCalled()
spyOn vt.sb, 'cr'
vt.feed(data)
expect(vt.sb.cr).toHaveBeenCalled()
describe 'other', ->
it "is swallowed", ->
@ -56,23 +59,23 @@ describe AsciiIo.AnsiInterpreter, ->
describe 'from ASCII range (0x20-0x7e)', ->
it 'calls print', ->
data += '\x20foobar\x7e'
spyOn screenBuffer, 'print'
interpreter.feed(data)
expect(screenBuffer.print).toHaveBeenCalledWith(data)
spyOn vt.sb, 'print'
vt.feed(data)
expect(vt.sb.print).toHaveBeenCalledWith(data)
describe 'from Unicode', ->
it 'calls print', ->
data += '\xe2ab\xe2ZZ'
spyOn screenBuffer, 'print'
interpreter.feed(data)
expect(screenBuffer.print).toHaveBeenCalledWith(data)
spyOn vt.sb, 'print'
vt.feed(data)
expect(vt.sb.print).toHaveBeenCalledWith(data)
describe 'from Unicode (really ???)', ->
it 'calls print', ->
data += '\xc2a\xc4b\xc5c'
spyOn screenBuffer, 'print'
interpreter.feed(data)
expect(screenBuffer.print).toHaveBeenCalledWith(data)
spyOn vt.sb, 'print'
vt.feed(data)
expect(vt.sb.print).toHaveBeenCalledWith(data)
describe 'escape sequence', ->
@ -90,11 +93,11 @@ describe AsciiIo.AnsiInterpreter, ->
# it 'aaa', ->
# data += '[1\x1b\x0dm'
# spyOn screenBuffer, 'cr'
# spyOn screenBuffer, 'setSGR'
# interpreter.feed(data)
# expect(screenBuffer.cr).toHaveBeenCalled()
# expect(screenBuffer.setSGR).toHaveBeenCalledWith([1])
# spyOn vt.sb, 'cr'
# spyOn vt.sb, 'setSGR'
# vt.feed(data)
# expect(vt.sb.cr).toHaveBeenCalled()
# expect(vt.sb.setSGR).toHaveBeenCalledWith([1])
describe 'with intermediate', ->
# Intermediate = 20-2F !"#$%&'()*+,-./
@ -130,18 +133,18 @@ describe AsciiIo.AnsiInterpreter, ->
data += '7'
it 'saves cursor', ->
spyOn screenBuffer, 'saveCursor'
interpreter.feed(data)
expect(screenBuffer.saveCursor).toHaveBeenCalled()
spyOn vt.sb, 'saveCursor'
vt.feed(data)
expect(vt.sb.saveCursor).toHaveBeenCalled()
describe '8', ->
beforeEach ->
data += '8'
it 'restores cursor', ->
spyOn screenBuffer, 'restoreCursor'
interpreter.feed(data)
expect(screenBuffer.restoreCursor).toHaveBeenCalled()
spyOn vt.sb, 'restoreCursor'
vt.feed(data)
expect(vt.sb.restoreCursor).toHaveBeenCalled()
describe '=', ->
beforeEach ->
@ -167,9 +170,9 @@ describe AsciiIo.AnsiInterpreter, ->
data += 'M'
it 'goes up 1 line', ->
spyOn screenBuffer, 'ri'
interpreter.feed(data)
expect(screenBuffer.ri).toHaveBeenCalled()
spyOn vt.sb, 'ri'
vt.feed(data)
expect(vt.sb.ri).toHaveBeenCalled()
describe 'P', ->
# Device Control String, terminated by ST
@ -182,9 +185,9 @@ describe AsciiIo.AnsiInterpreter, ->
describe ']', ->
# Operating system command
beforeEach ->
screenBuffer = {} # will throw 'undefined is not a function'
interpreter = new AsciiIo.AnsiInterpreter(screenBuffer)
# beforeEach ->
# vt = new AsciiIo.VT(cols, lines, renderer)
# vt.sb = {} # will throw 'undefined is not a function'
describe '0;...BELL', ->
beforeEach ->
@ -227,192 +230,192 @@ describe AsciiIo.AnsiInterpreter, ->
describe 'buffering', ->
# it 'allows parsing in chunks', ->
# spyOn interpreter, 'handleSGR'
# interpreter.feed(data)
# interpreter.feed('m')
# expect(interpreter.handleSGR).toHaveBeenCalled()
# spyOn vt, 'handleSGR'
# vt.feed(data)
# vt.feed('m')
# expect(vt.handleSGR).toHaveBeenCalled()
describe '@', ->
it 'calls reserveCharacters', ->
data += '3@'
spyOn screenBuffer, 'reserveCharacters'
interpreter.feed(data)
expect(screenBuffer.reserveCharacters).toHaveBeenCalledWith(3)
spyOn vt.sb, 'reserveCharacters'
vt.feed(data)
expect(vt.sb.reserveCharacters).toHaveBeenCalledWith(3)
describe 'A', ->
it 'calls cursorUp(1) if no number given', ->
data += 'A'
spyOn screenBuffer, 'cursorUp'
interpreter.feed(data)
expect(screenBuffer.cursorUp).toHaveBeenCalledWith(1)
spyOn vt.sb, 'cursorUp'
vt.feed(data)
expect(vt.sb.cursorUp).toHaveBeenCalledWith(1)
it 'calls cursorUp(n) if number given', ->
data += '3A'
spyOn screenBuffer, 'cursorUp'
interpreter.feed(data)
expect(screenBuffer.cursorUp).toHaveBeenCalledWith(3)
spyOn vt.sb, 'cursorUp'
vt.feed(data)
expect(vt.sb.cursorUp).toHaveBeenCalledWith(3)
describe 'B', ->
it 'calls cursorDown(1) if no number given', ->
data += 'B'
spyOn screenBuffer, 'cursorDown'
interpreter.feed(data)
expect(screenBuffer.cursorDown).toHaveBeenCalledWith(1)
spyOn vt.sb, 'cursorDown'
vt.feed(data)
expect(vt.sb.cursorDown).toHaveBeenCalledWith(1)
it 'calls cursorDown(n) if number given', ->
data += '3B'
spyOn screenBuffer, 'cursorDown'
interpreter.feed(data)
expect(screenBuffer.cursorDown).toHaveBeenCalledWith(3)
spyOn vt.sb, 'cursorDown'
vt.feed(data)
expect(vt.sb.cursorDown).toHaveBeenCalledWith(3)
describe 'C', ->
it 'calls cursorForward(1) if no number given', ->
data += 'C'
spyOn screenBuffer, 'cursorForward'
interpreter.feed(data)
expect(screenBuffer.cursorForward).toHaveBeenCalledWith(1)
spyOn vt.sb, 'cursorForward'
vt.feed(data)
expect(vt.sb.cursorForward).toHaveBeenCalledWith(1)
it 'calls cursorForward(n) if number given', ->
data += '3C'
spyOn screenBuffer, 'cursorForward'
interpreter.feed(data)
expect(screenBuffer.cursorForward).toHaveBeenCalledWith(3)
spyOn vt.sb, 'cursorForward'
vt.feed(data)
expect(vt.sb.cursorForward).toHaveBeenCalledWith(3)
describe 'D', ->
it 'calls cursorBack(1) if no number given', ->
data += 'D'
spyOn screenBuffer, 'cursorBack'
interpreter.feed(data)
expect(screenBuffer.cursorBack).toHaveBeenCalledWith(1)
spyOn vt.sb, 'cursorBack'
vt.feed(data)
expect(vt.sb.cursorBack).toHaveBeenCalledWith(1)
it 'calls cursorBack(n) if number given', ->
data += '3D'
spyOn screenBuffer, 'cursorBack'
interpreter.feed(data)
expect(screenBuffer.cursorBack).toHaveBeenCalledWith(3)
spyOn vt.sb, 'cursorBack'
vt.feed(data)
expect(vt.sb.cursorBack).toHaveBeenCalledWith(3)
describe 'G', ->
it 'calls setCursorColumn(n)', ->
data += '3G'
spyOn screenBuffer, 'setCursorColumn'
interpreter.feed(data)
expect(screenBuffer.setCursorColumn).toHaveBeenCalledWith(3)
spyOn vt.sb, 'setCursorColumn'
vt.feed(data)
expect(vt.sb.setCursorColumn).toHaveBeenCalledWith(3)
describe 'H', ->
it 'calls setCursorPos(n, m) when n and m given', ->
data += '3;4H'
spyOn screenBuffer, 'setCursorPos'
interpreter.feed(data)
expect(screenBuffer.setCursorPos).toHaveBeenCalledWith(3, 4)
spyOn vt.sb, 'setCursorPos'
vt.feed(data)
expect(vt.sb.setCursorPos).toHaveBeenCalledWith(3, 4)
it 'calls setCursorPos(1, m) when no n given', ->
data += ';3H'
spyOn screenBuffer, 'setCursorPos'
interpreter.feed(data)
expect(screenBuffer.setCursorPos).toHaveBeenCalledWith(1, 3)
spyOn vt.sb, 'setCursorPos'
vt.feed(data)
expect(vt.sb.setCursorPos).toHaveBeenCalledWith(1, 3)
it 'calls setCursorPos(n, 1) when no m given', ->
data += '3;H'
spyOn screenBuffer, 'setCursorPos'
interpreter.feed(data)
expect(screenBuffer.setCursorPos).toHaveBeenCalledWith(3, 1)
spyOn vt.sb, 'setCursorPos'
vt.feed(data)
expect(vt.sb.setCursorPos).toHaveBeenCalledWith(3, 1)
it 'calls setCursorPos(n, 1) when no m given (no semicolon)', ->
data += '3H'
spyOn screenBuffer, 'setCursorPos'
interpreter.feed(data)
expect(screenBuffer.setCursorPos).toHaveBeenCalledWith(3, 1)
spyOn vt.sb, 'setCursorPos'
vt.feed(data)
expect(vt.sb.setCursorPos).toHaveBeenCalledWith(3, 1)
it 'calls setCursorPos(1, 1) when no n nor m given', ->
data += 'H'
spyOn screenBuffer, 'setCursorPos'
interpreter.feed(data)
expect(screenBuffer.setCursorPos).toHaveBeenCalledWith(1, 1)
spyOn vt.sb, 'setCursorPos'
vt.feed(data)
expect(vt.sb.setCursorPos).toHaveBeenCalledWith(1, 1)
describe 'J', ->
it 'calls eraseData(0) when no n given', ->
data += 'J'
spyOn screenBuffer, 'eraseData'
interpreter.feed(data)
expect(screenBuffer.eraseData).toHaveBeenCalledWith(0)
spyOn vt.sb, 'eraseData'
vt.feed(data)
expect(vt.sb.eraseData).toHaveBeenCalledWith(0)
it 'calls eraseData(n) when n given', ->
data += '3J'
spyOn screenBuffer, 'eraseData'
interpreter.feed(data)
expect(screenBuffer.eraseData).toHaveBeenCalledWith(3)
spyOn vt.sb, 'eraseData'
vt.feed(data)
expect(vt.sb.eraseData).toHaveBeenCalledWith(3)
describe 'K', ->
it 'calls eraseInLine(0) when no n given', ->
data += 'K'
spyOn screenBuffer, 'eraseInLine'
interpreter.feed(data)
expect(screenBuffer.eraseInLine).toHaveBeenCalledWith(0)
spyOn vt.sb, 'eraseInLine'
vt.feed(data)
expect(vt.sb.eraseInLine).toHaveBeenCalledWith(0)
it 'calls eraseInLine(n) when n given', ->
data += '3K'
spyOn screenBuffer, 'eraseInLine'
interpreter.feed(data)
expect(screenBuffer.eraseInLine).toHaveBeenCalledWith(3)
spyOn vt.sb, 'eraseInLine'
vt.feed(data)
expect(vt.sb.eraseInLine).toHaveBeenCalledWith(3)
describe 'L', ->
it 'calls insertLines(1) when no n given', ->
data += 'L'
spyOn screenBuffer, 'insertLines'
interpreter.feed(data)
expect(screenBuffer.insertLines).toHaveBeenCalledWith(1)
spyOn vt.sb, 'insertLines'
vt.feed(data)
expect(vt.sb.insertLines).toHaveBeenCalledWith(1)
it 'calls insertLines(n) when n given', ->
data += '3L'
spyOn screenBuffer, 'insertLines'
interpreter.feed(data)
expect(screenBuffer.insertLines).toHaveBeenCalledWith(3)
spyOn vt.sb, 'insertLines'
vt.feed(data)
expect(vt.sb.insertLines).toHaveBeenCalledWith(3)
describe 'M', ->
it 'calls deleteLines(1) when no n given', ->
data += 'M'
spyOn screenBuffer, 'deleteLines'
interpreter.feed(data)
expect(screenBuffer.deleteLines).toHaveBeenCalledWith(1)
spyOn vt.sb, 'deleteLines'
vt.feed(data)
expect(vt.sb.deleteLines).toHaveBeenCalledWith(1)
it 'calls deleteLines(n) when n given', ->
data += '3M'
spyOn screenBuffer, 'deleteLines'
interpreter.feed(data)
expect(screenBuffer.deleteLines).toHaveBeenCalledWith(3)
spyOn vt.sb, 'deleteLines'
vt.feed(data)
expect(vt.sb.deleteLines).toHaveBeenCalledWith(3)
describe 'd', ->
it 'calls setCursorLine(n)', ->
data += '3d'
spyOn screenBuffer, 'setCursorLine'
interpreter.feed(data)
expect(screenBuffer.setCursorLine).toHaveBeenCalledWith(3)
spyOn vt.sb, 'setCursorLine'
vt.feed(data)
expect(vt.sb.setCursorLine).toHaveBeenCalledWith(3)
describe 'm', ->
it 'calls handleSGR([n, m, ...]) when n and m given', ->
data += '1;4;33m'
spyOn interpreter, 'handleSGR'
interpreter.feed(data)
expect(interpreter.handleSGR).toHaveBeenCalledWith([1, 4, 33])
spyOn vt, 'handleSGR'
vt.feed(data)
expect(vt.handleSGR).toHaveBeenCalledWith([1, 4, 33])
it 'calls handleSGR([]) when no n nor m given', ->
data += 'm'
spyOn interpreter, 'handleSGR'
interpreter.feed(data)
expect(interpreter.handleSGR).toHaveBeenCalledWith([])
spyOn vt, 'handleSGR'
vt.feed(data)
expect(vt.handleSGR).toHaveBeenCalledWith([])
describe 'P', ->
it 'calls deleteCharacter(1) when no n given', ->
data += 'P'
spyOn screenBuffer, 'deleteCharacter'
interpreter.feed(data)
expect(screenBuffer.deleteCharacter).toHaveBeenCalledWith(1)
spyOn vt.sb, 'deleteCharacter'
vt.feed(data)
expect(vt.sb.deleteCharacter).toHaveBeenCalledWith(1)
it 'calls deleteCharacter(n) when n given', ->
data += '3P'
spyOn screenBuffer, 'deleteCharacter'
interpreter.feed(data)
expect(screenBuffer.deleteCharacter).toHaveBeenCalledWith(3)
spyOn vt.sb, 'deleteCharacter'
vt.feed(data)
expect(vt.sb.deleteCharacter).toHaveBeenCalledWith(3)
describe 'c', ->
beforeEach ->
@ -445,158 +448,158 @@ describe AsciiIo.AnsiInterpreter, ->
data += '25h'
it 'shows cursor', ->
spyOn screenBuffer, 'showCursor'
interpreter.feed(data)
expect(screenBuffer.showCursor).toHaveBeenCalledWith(true)
spyOn vt.renderer, 'showCursor'
vt.feed(data)
expect(vt.renderer.showCursor).toHaveBeenCalledWith(true)
describe '25l', ->
beforeEach ->
data += '25l'
it 'hides cursor', ->
spyOn screenBuffer, 'showCursor'
interpreter.feed(data)
expect(screenBuffer.showCursor).toHaveBeenCalledWith(false)
spyOn vt.renderer, 'showCursor'
vt.feed(data)
expect(vt.renderer.showCursor).toHaveBeenCalledWith(false)
describe '47h', ->
beforeEach ->
data += '47h'
it 'switches to alternate buffer', ->
spyOn screenBuffer, 'switchToAlternateBuffer'
interpreter.feed(data)
expect(screenBuffer.switchToAlternateBuffer).toHaveBeenCalled()
spyOn vt.sb, 'switchToAlternateBuffer'
vt.feed(data)
expect(vt.sb.switchToAlternateBuffer).toHaveBeenCalled()
describe '47l', ->
beforeEach ->
data += '47l'
it 'switches to normal buffer', ->
spyOn screenBuffer, 'switchToNormalBuffer'
interpreter.feed(data)
expect(screenBuffer.switchToNormalBuffer).toHaveBeenCalled()
spyOn vt.sb, 'switchToNormalBuffer'
vt.feed(data)
expect(vt.sb.switchToNormalBuffer).toHaveBeenCalled()
describe '1049h', ->
beforeEach ->
data += '1049h'
it 'saves cursor position, switches to alternate buffer and clear screen', ->
spyOn screenBuffer, 'saveCursor'
spyOn screenBuffer, 'switchToAlternateBuffer'
spyOn screenBuffer, 'clear'
interpreter.feed(data)
expect(screenBuffer.saveCursor).toHaveBeenCalled()
expect(screenBuffer.switchToAlternateBuffer).toHaveBeenCalled()
expect(screenBuffer.clear).toHaveBeenCalled()
spyOn vt.sb, 'saveCursor'
spyOn vt.sb, 'switchToAlternateBuffer'
spyOn vt.sb, 'clear'
vt.feed(data)
expect(vt.sb.saveCursor).toHaveBeenCalled()
expect(vt.sb.switchToAlternateBuffer).toHaveBeenCalled()
expect(vt.sb.clear).toHaveBeenCalled()
describe '1049l', ->
beforeEach ->
data += '1049l'
it 'clears screen, switches to normal buffer and restores cursor position', ->
spyOn screenBuffer, 'clear'
spyOn screenBuffer, 'switchToNormalBuffer'
spyOn screenBuffer, 'restoreCursor'
interpreter.feed(data)
expect(screenBuffer.clear).toHaveBeenCalled()
expect(screenBuffer.switchToNormalBuffer).toHaveBeenCalled()
expect(screenBuffer.restoreCursor).toHaveBeenCalled()
spyOn vt.sb, 'clear'
spyOn vt.sb, 'switchToNormalBuffer'
spyOn vt.sb, 'restoreCursor'
vt.feed(data)
expect(vt.sb.clear).toHaveBeenCalled()
expect(vt.sb.switchToNormalBuffer).toHaveBeenCalled()
expect(vt.sb.restoreCursor).toHaveBeenCalled()
describe '#handleSGR', ->
numbers = undefined
it 'resets brush for 0', ->
spyOn screenBuffer, 'setBrush'
spyOn vt.sb, 'setBrush'
numbers = [31]
interpreter.handleSGR(numbers)
vt.handleSGR(numbers)
expectedBrush = AsciiIo.Brush.create({ fg: 1 })
expect(screenBuffer.setBrush).toHaveBeenCalledWith(expectedBrush)
expect(vt.sb.setBrush).toHaveBeenCalledWith(expectedBrush)
numbers = [0]
interpreter.handleSGR(numbers)
vt.handleSGR(numbers)
expectedBrush = AsciiIo.Brush.create({})
expect(screenBuffer.setBrush).toHaveBeenCalledWith(expectedBrush)
expect(vt.sb.setBrush).toHaveBeenCalledWith(expectedBrush)
it 'sets bright attr for 1', ->
numbers = [1]
spyOn screenBuffer, 'setBrush'
interpreter.handleSGR(numbers)
spyOn vt.sb, 'setBrush'
vt.handleSGR(numbers)
expectedBrush = AsciiIo.Brush.create({ bright: true })
expect(screenBuffer.setBrush).toHaveBeenCalledWith(expectedBrush)
expect(vt.sb.setBrush).toHaveBeenCalledWith(expectedBrush)
it 'sets underline attr for 4', ->
numbers = [4]
spyOn screenBuffer, 'setBrush'
interpreter.handleSGR(numbers)
spyOn vt.sb, 'setBrush'
vt.handleSGR(numbers)
expectedBrush = AsciiIo.Brush.create({ underline: true })
expect(screenBuffer.setBrush).toHaveBeenCalledWith(expectedBrush)
expect(vt.sb.setBrush).toHaveBeenCalledWith(expectedBrush)
it 'unsets underline attr for 24', ->
spyOn screenBuffer, 'setBrush'
spyOn vt.sb, 'setBrush'
numbers = [31, 4]
interpreter.handleSGR(numbers)
vt.handleSGR(numbers)
expectedBrush = AsciiIo.Brush.create({ fg: 1, underline: true })
expect(screenBuffer.setBrush).toHaveBeenCalledWith(expectedBrush)
expect(vt.sb.setBrush).toHaveBeenCalledWith(expectedBrush)
numbers = [24]
interpreter.handleSGR(numbers)
vt.handleSGR(numbers)
expectedBrush = AsciiIo.Brush.create({ fg: 1 })
expect(screenBuffer.setBrush).toHaveBeenCalledWith(expectedBrush)
expect(vt.sb.setBrush).toHaveBeenCalledWith(expectedBrush)
it 'sets foreground for 30-37', ->
numbers = [32]
spyOn screenBuffer, 'setBrush'
interpreter.handleSGR(numbers)
spyOn vt.sb, 'setBrush'
vt.handleSGR(numbers)
expectedBrush = AsciiIo.Brush.create({ fg: 2 })
expect(screenBuffer.setBrush).toHaveBeenCalledWith(expectedBrush)
expect(vt.sb.setBrush).toHaveBeenCalledWith(expectedBrush)
it 'sets foreground for 38;5;x', ->
numbers = [38, 5, 100]
spyOn screenBuffer, 'setBrush'
interpreter.handleSGR(numbers)
spyOn vt.sb, 'setBrush'
vt.handleSGR(numbers)
expectedBrush = AsciiIo.Brush.create({ fg: 100 })
expect(screenBuffer.setBrush).toHaveBeenCalledWith(expectedBrush)
expect(vt.sb.setBrush).toHaveBeenCalledWith(expectedBrush)
it 'unsets foreground for 39', ->
spyOn screenBuffer, 'setBrush'
spyOn vt.sb, 'setBrush'
numbers = [32]
interpreter.handleSGR(numbers)
vt.handleSGR(numbers)
expectedBrush = AsciiIo.Brush.create({ fg: 2 })
expect(screenBuffer.setBrush).toHaveBeenCalledWith(expectedBrush)
expect(vt.sb.setBrush).toHaveBeenCalledWith(expectedBrush)
numbers = [39]
interpreter.handleSGR(numbers)
vt.handleSGR(numbers)
expectedBrush = AsciiIo.Brush.create({})
expect(screenBuffer.setBrush).toHaveBeenCalledWith(expectedBrush)
expect(vt.sb.setBrush).toHaveBeenCalledWith(expectedBrush)
it 'sets background for 40-47', ->
numbers = [42]
spyOn screenBuffer, 'setBrush'
interpreter.handleSGR(numbers)
spyOn vt.sb, 'setBrush'
vt.handleSGR(numbers)
expectedBrush = AsciiIo.Brush.create({ bg: 2 })
expect(screenBuffer.setBrush).toHaveBeenCalledWith(expectedBrush)
expect(vt.sb.setBrush).toHaveBeenCalledWith(expectedBrush)
it 'sets background for 48;5;x', ->
numbers = [48, 5, 200]
spyOn screenBuffer, 'setBrush'
interpreter.handleSGR(numbers)
spyOn vt.sb, 'setBrush'
vt.handleSGR(numbers)
expectedBrush = AsciiIo.Brush.create({ bg: 200 })
expect(screenBuffer.setBrush).toHaveBeenCalledWith(expectedBrush)
expect(vt.sb.setBrush).toHaveBeenCalledWith(expectedBrush)
it 'unsets background for 49', ->
spyOn screenBuffer, 'setBrush'
spyOn vt.sb, 'setBrush'
numbers = [42]
interpreter.handleSGR(numbers)
vt.handleSGR(numbers)
expectedBrush = AsciiIo.Brush.create({ bg: 2 })
expect(screenBuffer.setBrush).toHaveBeenCalledWith(expectedBrush)
expect(vt.sb.setBrush).toHaveBeenCalledWith(expectedBrush)
numbers = [49]
interpreter.handleSGR(numbers)
vt.handleSGR(numbers)
expectedBrush = AsciiIo.Brush.create({})
expect(screenBuffer.setBrush).toHaveBeenCalledWith(expectedBrush)
expect(vt.sb.setBrush).toHaveBeenCalledWith(expectedBrush)
Loading…
Cancel
Save