Lots of good stuff \m/

openid
Marcin Kulik 13 years ago
parent 2d4bc140a1
commit a194067ab5

@ -1,22 +1,8 @@
class AsciiIo.VT class AsciiIo.VT
constructor: (@cols, @lines, @renderer) -> constructor: (@cols, @lines, @renderer) ->
@cursorX = 0
@cursorY = 0
@topMargin = 0
@bottomMargin = @lines - 1
@normalBuffer = []
@alternateBuffer = []
@lineData = @normalBuffer
@dirtyLines = {}
@brush = AsciiIo.Brush.create({})
@data = '' @data = ''
# @sb = new AsciiIo.ScreenBuffer(cols, lines) @resetTerminal()
@fg = @bg = undefined
@bright = false
@underline = false
@compilePatterns() @compilePatterns()
noop: -> noop: ->
@ -44,7 +30,7 @@ class AsciiIo.VT
"\x0a": (data) -> @lineFeed() "\x0a": (data) -> @lineFeed()
"\x0d": (data) -> @cr() "\x0d": (data) -> @carriageReturn()
"\x0e": (data) -> "\x0e": (data) ->
@ -91,12 +77,15 @@ class AsciiIo.VT
"\x00": (data) -> "\x00": (data) ->
"\x07": (data) -> @bell() "\x07": (data) -> @bell()
"\x08": (data) -> @backspace() "\x08": (data) -> @backspace()
"\x09": (data) -> # Moves the cursor to the next tab stop "\x09": (data) -> @goToNextHorizontalTabStop()
"\x0a": (data) -> @lineFeed() "\x0a": (data) -> @lineFeed()
"\x0d": (data) -> @cr() "\x0b": (data) -> @verticalTab()
"\x0c": (data) -> @formFeed()
"\x0d": (data) -> @carriageReturn()
"\x0e": (data) -> "\x0e": (data) ->
"\x0f": (data) -> "\x0f": (data) ->
"\x82": (data) -> # Reserved (?) "\x82": (data) -> # Reserved (?)
"\x85": (data) -> @setHorizontalTabStop()
"\x94": (data) -> # Cancel Character, ignore previous character "\x94": (data) -> # Cancel Character, ignore previous character
# 20 - 7e # 20 - 7e
@ -137,9 +126,9 @@ class AsciiIo.VT
# steady cursor # steady cursor
else if mode is "25" else if mode is "25"
if action is "h" if action is "h"
@renderer.showCursor true @showCursor()
else if action is "l" else if action is "l"
@renderer.showCursor false @hideCursor()
else if mode is "47" else if mode is "47"
if action is "h" if action is "h"
@switchToAlternateBuffer() @switchToAlternateBuffer()
@ -173,54 +162,92 @@ class AsciiIo.VT
"\x1b\\[>c": (data) -> # Secondary Device Attribute request (?) "\x1b\\[>c": (data) -> # Secondary Device Attribute request (?)
"\x1bc": -> @resetTerminal()
"\x1bP([^\\\\])*?\\\\": (data) -> # DCS, Device Control String "\x1bP([^\\\\])*?\\\\": (data) -> # DCS, Device Control String
"\x1bD": -> @index()
"\x1bE": -> @newLine()
"\x1bM": -> @reverseIndex()
"\x1bD": -> "\x1b7": (data) -> # save cursor pos and char attrs
console.log 'ya yebie' @saveTerminalState()
"\x1bM": -> "\x1b8": (data) -> # restore cursor pos and char attrs
@reverseIndex() @restoreTerminalState()
"\x1b\x37": (data) -> # save cursor pos and char attrs
@saveCursor()
"\x1b\x38": (data) -> # restore cursor pos and char attrs
@restoreCursor()
handleCSI: (term) -> handleCSI: (term) ->
switch term switch term
when "@" when "@"
@reserveCharacters @n @insertCharacters @n
when "A" when "A"
@cursorUp @n or 1 @priorRow @n
when "B" when "B"
@cursorDown @n or 1 @nextRow @n
when "C" when "C"
@cursorForward @n or 1 @nextColumn @n
when "D" when "D"
@cursorBack @n or 1 @priorColumn @n
when "E"
@nextRowFirstColumn @n
when "F"
@priorRowFirstColumn @n
when "G" when "G"
@setCursorColumn @n @goToColumn @n
when "H" when "H"
@setCursorPos @n or 1, @m or 1 @goToRowAndColumn @n, @m
when "I"
@goToNextHorizontalTabStop @n
when "J" when "J"
@eraseData @n or 0 if @n is 2
@eraseScreen()
else if @n is 1
@eraseFromScreenStart()
else
@eraseToScreenEnd()
when "K" when "K"
@eraseInLine @n or 0 if @n is 2
@eraseRow()
else if @n is 1
@eraseFromRowStart()
else
@eraseToRowEnd()
when "L" when "L"
@insertLines @n or 1 @insertLine @n or 1
when "M" when "M"
@deleteLines @n or 1 @deleteLine @n or 1
when "P" # DCH - Delete Character, from current position to end of field
@deleteCharacters @n or 1
when "S"
@scrollUp @n or 1
when "T"
@scrollDown @n or 1
when "X"
@eraseCharacters @n
when "Z"
@goToPriorHorizontalTabStop @n
when "b"
@repeatLastCharacter @n
when "d" # VPA - Vertical Position Absolute when "d" # VPA - Vertical Position Absolute
@setCursorLine(@n) @goToRow @n
when "f"
@goToRowAndColumn @n, @m
when "g"
if !@n or @n is 0
@clearHorizontalTabStop()
else if @n is 3
@clearAllHorizontalTabStops()
when "l" # l, Reset mode when "l" # l, Reset mode
console.log "(TODO) reset: " + @n console.log "(TODO) reset: " + @n
when "m" when "m"
@handleSGR @params @handleSGR @params
when "P" # DCH - Delete Character, from current position to end of field when "n"
@deleteCharacter @n or 1 @reportRowAndColumn()
when "r" # Set top and bottom margins (scroll region on VT100) when "r" # Set top and bottom margins (scroll region on VT100)
@setScrollRegion(@n, @m) @setScrollRegion @n or 0, @m or @lines - 1
when "s"
@saveCursor()
when "u"
@restoreCursor()
else else
throw "no handler for CSI term: " + term throw "no handler for CSI term: " + term
@ -298,9 +325,6 @@ class AsciiIo.VT
# ==== Screen buffer operations # ==== Screen buffer operations
setBrush: (brush) ->
@brush = brush
clearScreen: -> clearScreen: ->
@lineData.length = 0 @lineData.length = 0
@ -325,10 +349,6 @@ class AsciiIo.VT
@lineData = @alternateBuffer @lineData = @alternateBuffer
@updateScreen() @updateScreen()
setScrollRegion: (top, bottom) ->
@topMargin = top - 1
@bottomMargin = bottom - 1
updateLine: (n) -> updateLine: (n) ->
n = (if typeof n isnt "undefined" then n else @cursorY) n = (if typeof n isnt "undefined" then n else @cursorY)
@dirtyLines[n] = n @dirtyLines[n] = n
@ -336,152 +356,187 @@ class AsciiIo.VT
updateScreen: -> updateScreen: ->
@dirtyLines[n] = n for n in [0...@lines] @dirtyLines[n] = n for n in [0...@lines]
setCursorLine: (line) -> carriageReturn: ->
oldLine = @cursorY @goToFirstColumn()
@cursorY = line - 1
@updateLine oldLine backspace: ->
@updateLine() @priorColumn()
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++
setCursorColumn: (col) ->
@cursorX = col - 1
@updateLine() @updateLine()
setCursorPos: (line, col) -> clearLineData: (n) ->
@setCursorLine(line) @fill n, 0, @cols, " "
@setCursorColumn(col)
saveCursor: -> fill: (line, col, n, char) ->
@savedCol = @cursorX lineArr = @getLine(line)
@savedLine = @cursorY
restoreCursor: -> i = 0
oldLine = @cursorY while i < n
lineArr[col + i] = [char, @brush]
i++
@cursorY = @savedLine inScrollRegion: ->
@cursorX = @savedCol @cursorY >= @topMargin and @cursorY <= @bottomMargin
@updateLine oldLine changes: ->
@updateLine() c = {}
for _, n of @dirtyLines
c[n] = @lineData[n]
cursorLeft: -> c
if @cursorX > 0
@cursorX -= 1
@updateLine()
cursorRight: -> clearChanges: ->
if @cursorX < @cols @dirtyLines = {}
@cursorX += 1
@updateLine()
cursorUp: (n = 1) -> # === ANSI handlers
# ------ Cursor control
# ----- Scroll control
reverseIndex: ->
@goToPriorRow()
lineFeed: ->
@goToNextRow()
verticalTab: ->
@goToNextRow()
formFeed: ->
@goToNextRow()
index: ->
@goToNextRow()
newLine: ->
@goToNextRowFirstColumn()
# === Commands
# ----- Cursor control
priorRow: (n = 1) ->
for i in [0...n] for i in [0...n]
if @cursorY > 0 if @cursorY > 0
@cursorY -= 1 @cursorY -= 1
@updateLine @cursorY @updateLine @cursorY
@updateLine @cursorY + 1 @updateLine @cursorY + 1
cursorDown: (n = 1) -> nextRow: (n = 1) ->
for i in [0...n] for i in [0...n]
if @cursorY + 1 < @lines if @cursorY + 1 < @lines
@cursorY += 1 @cursorY += 1
@updateLine @cursorY - 1 @updateLine @cursorY - 1
@updateLine @cursorY @updateLine @cursorY
cursorForward: (n) -> nextColumn: (n = 1) ->
@cursorRight() for i in [0...n] @_cursorRight() for i in [0...n]
cursorBack: (n) -> priorColumn: (n = 1) ->
@cursorLeft() for i in [0...n] @_cursorLeft() for i in [0...n]
cr: -> _cursorLeft: ->
@cursorX = 0 if @cursorX > 0
@cursorX -= 1
@updateLine() @updateLine()
backspace: -> _cursorRight: ->
if @cursorX > 0 if @cursorX < @cols
@cursorLeft() @cursorX += 1
@updateLine() @updateLine()
print: (text) -> priorRowFirstColumn: (n = 1) ->
text = Utf8.decode(text) @carriageReturn()
@priorRow n
i = 0 nextRowFirstColumn: (n = 1) ->
while i < text.length @carriageReturn()
if @cursorX >= @cols @nextRow n
@cursorY += 1
@cursorX = 0
@fill @cursorY, @cursorX, 1, text[i] goToColumn: (col = 1) ->
@cursorX += 1 @cursorX = col - 1
i++ @updateLine()
goToRow: (line = 1) ->
oldLine = @cursorY
@cursorY = line - 1
@updateLine oldLine
@updateLine() @updateLine()
eraseData: (n) -> goToRowAndColumn: (line = 1, col = 1) ->
if n is 0 @goToRow line
@eraseInLine 0 @goToColumn col
l = @cursorY + 1 setHorizontalTabStop: ->
while l < @lines # @tabStops << @cursorX
@clearLineData l
@updateLine l
l++
else if n is 1 goToNextHorizontalTabStop: ->
l = 0
while l < @cursorY
@clearLineData l
@updateLine l
l++
@eraseInLine n goToPriorHorizontalTabStop: ->
else if n is 2 clearHorizontalTabStop: ->
l = 0
while l < @lines
@clearLineData l
@updateLine l
l++
eraseInLine: (n) -> clearAllHorizontalTabStops: ->
if n is 0
@fill @cursorY, @cursorX, @cols - @cursorX, " "
else if n is 1
@fill @cursorY, 0, @cursorX, " "
else if n is 2
@fill @cursorY, 0, @cols, " "
@updateLine() saveCursor: ->
@savedCol = @cursorX
@savedLine = @cursorY
clearLineData: (n) -> restoreCursor: ->
@fill n, 0, @cols, " " oldLine = @cursorY
deleteCharacter: (n) -> @cursorY = @savedLine
@getLine().splice(@cursorX, n) @cursorX = @savedCol
@updateLine oldLine
@updateLine() @updateLine()
reserveCharacters: (n) -> showCursor: ->
line = @getLine() @renderer.showCursor true
@lineData[@cursorY] = line.slice(0, @cursorX).concat(" ".times(n).split(""), line.slice(@cursorX, @cols - n))
hideCursor: ->
@renderer.showCursor false
goToFirstColumn: ->
@cursorX = 0
@updateLine() @updateLine()
lineFeed: -> # ----- Scroll control
@index()
index: -> setScrollRegion: (top, bottom) ->
if @cursorY + 1 < @lines @topMargin = top - 1
@cursorDown() @bottomMargin = bottom - 1
else
setLineWrap: (linewrap) ->
scrollUp: ->
# @lineData.splice l, 0, []
# @clearLineData l
@insertLine 1, 0
@updateScreen()
scrollDown: ->
@lineData.splice 0, 1 @lineData.splice 0, 1
@updateScreen() @updateScreen()
reverseIndex: -> insertLine: (n, l = @cursorY) ->
if @cursorY is 0 return unless @inScrollRegion()
@insertLines 1, 0
else
@cursorUp()
insertLines: (n, l = @cursorY) ->
i = 0 i = 0
while i < n while i < n
@lineData.splice l, 0, [] @lineData.splice l, 0, []
@ -493,7 +548,9 @@ class AsciiIo.VT
@updateScreen() @updateScreen()
deleteLines: (n, l = @cursorY) -> deleteLine: (n, l = @cursorY) ->
return unless @inScrollRegion()
@lineData.splice l, n @lineData.splice l, n
# expand lineData to max size # expand lineData to max size
@ -501,20 +558,132 @@ class AsciiIo.VT
@updateScreen() @updateScreen()
fill: (line, col, n, char) -> deleteCharacters: (n) ->
lineArr = @getLine(line) @getLine().splice(@cursorX, n)
@updateLine()
i = 0 insertCharacters: (n) ->
while i < n line = @getLine()
lineArr[col + i] = [char, @brush] @lineData[@cursorY] = line.slice(0, @cursorX).concat(" ".times(n).split(""), line.slice(@cursorX, @cols - n))
i++ @updateLine()
changes: -> goToPriorRow: ->
c = {} if @cursorY is @topMargin
for _, n of @dirtyLines @scrollUp()
c[n] = @lineData[n] else
@priorRow()
c # if @cursorY is 0
# @insertLine 1, 0
# else
# @priorRow()
clearChanges: -> goToNextRow: ->
# if @cursorY is @bottomMargin
# else
if @cursorY + 1 < @lines
@nextRow()
else
@scrollDown()
goToNextRowFirstColumn: ->
@carriageReturn()
@goToNextRow()
saveScrollRegion: ->
@savedTopMargin = @topMargin
@savedBottomMargin = @bottomMargin
restoreScrollRegion: ->
@topMargin = @savedTopMargin
@bottomMargin = @savedBottomMargin
# ----- Terminal control
resetTerminal: ->
@cursorX = 0
@cursorY = 0
@topMargin = 0
@bottomMargin = @lines - 1
@normalBuffer = []
@alternateBuffer = []
@lineData = @normalBuffer
@dirtyLines = {} @dirtyLines = {}
@brush = AsciiIo.Brush.create({})
@fg = @bg = undefined
@bright = false
@underline = false
@updateScreen()
saveTerminalState: ->
@saveCursor()
@saveScrollRegion()
@saveBrush()
restoreTerminalState: ->
@restoreBrush()
@restoreScrollRegion()
@restoreCursor()
reportRowAndColumn: ->
# ----- Attribute control
setBrush: (brush) ->
@brush = brush
saveBrush: ->
@savedBrush = @brush
restoreBrush: ->
@brush = @savedBrush
repeatLastCharacter: (n = 1) ->
# ----- Erase control
eraseScreen: ->
l = 0
while l < @lines
@clearLineData l
@updateLine l
l++
eraseFromScreenStart: ->
l = 0
while l < @cursorY
@clearLineData l
@updateLine l
l++
@eraseFromRowStart()
eraseToScreenEnd: ->
@eraseToRowEnd()
l = @cursorY + 1
while l < @lines
@clearLineData l
@updateLine l
l++
eraseRow: ->
@fill @cursorY, 0, @cols, " "
@updateLine()
eraseFromRowStart: ->
@fill @cursorY, 0, @cursorX, " "
@updateLine()
eraseToRowEnd: ->
@fill @cursorY, @cursorX, @cols - @cursorX, " "
@updateLine()
eraseCharacters: (n = 1) ->
@fill @cursorY, @cursorX, n, " "
@updateLine()
# http://www.shaels.net/index.php/propterm/documents

Loading…
Cancel
Save