class HTMLTerminal
timeout: (ms, f) -> setTimeout(f, ms)
constructor: (jq_element, width, height) ->
@parent_element = jq_element
@redraw_wait = false
@redraw_again = false
@term = window.terminal.new width, height
@palette = [
# normal colours
'2e3436',
'cc0000',
'4e9a06',
'c4a000',
'3465a4',
'75507b',
'06989a',
'd3d7cf',
# brighter versions (for bold, and 16-color sequences)
'555753',
'ef2929',
'8ae234',
'fce94f',
'729fcf',
'ad7fa8',
'34e2e2',
'eeeeec',
# 256 colors
'000000', '00005f', '000087', '0000af', '0000d7', '0000ff', '005f00', '005f5f',
'005f87', '005faf', '005fd7', '005fff', '008700', '00875f', '008787', '0087af',
'0087d7', '0087ff', '00af00', '00af5f', '00af87', '00afaf', '00afd7', '00afff',
'00d700', '00d75f', '00d787', '00d7af', '00d7d7', '00d7ff', '00ff00', '00ff5f',
'00ff87', '00ffaf', '00ffd7', '00ffff', '5f0000', '5f005f', '5f0087', '5f00af',
'5f00d7', '5f00ff', '5f5f00', '5f5f5f', '5f5f87', '5f5faf', '5f5fd7', '5f5fff',
'5f8700', '5f875f', '5f8787', '5f87af', '5f87d7', '5f87ff', '5faf00', '5faf5f',
'5faf87', '5fafaf', '5fafd7', '5fafff', '5fd700', '5fd75f', '5fd787', '5fd7af',
'5fd7d7', '5fd7ff', '5fff00', '5fff5f', '5fff87', '5fffaf', '5fffd7', '5fffff',
'870000', '87005f', '870087', '8700af', '8700d7', '8700ff', '875f00', '875f5f',
'875f87', '875faf', '875fd7', '875fff', '878700', '87875f', '878787', '8787af',
'8787d7', '8787ff', '87af00', '87af5f', '87af87', '87afaf', '87afd7', '87afff',
'87d700', '87d75f', '87d787', '87d7af', '87d7d7', '87d7ff', '87ff00', '87ff5f',
'87ff87', '87ffaf', '87ffd7', '87ffff', 'af0000', 'af005f', 'af0087', 'af00af',
'af00d7', 'af00ff', 'af5f00', 'af5f5f', 'af5f87', 'af5faf', 'af5fd7', 'af5fff',
'af8700', 'af875f', 'af8787', 'af87af', 'af87d7', 'af87ff', 'afaf00', 'afaf5f',
'afaf87', 'afafaf', 'afafd7', 'afafff', 'afd700', 'afd75f', 'afd787', 'afd7af',
'afd7d7', 'afd7ff', 'afff00', 'afff5f', 'afff87', 'afffaf', 'afffd7', 'afffff',
'd70000', 'd7005f', 'd70087', 'd700af', 'd700d7', 'd700ff', 'd75f00', 'd75f5f',
'd75f87', 'd75faf', 'd75fd7', 'd75fff', 'd78700', 'd7875f', 'd78787', 'd787af',
'd787d7', 'd787ff', 'd7af00', 'd7af5f', 'd7af87', 'd7afaf', 'd7afd7', 'd7afff',
'd7d700', 'd7d75f', 'd7d787', 'd7d7af', 'd7d7d7', 'd7d7ff', 'd7ff00', 'd7ff5f',
'd7ff87', 'd7ffaf', 'd7ffd7', 'd7ffff', 'ff0000', 'ff005f', 'ff0087', 'ff00af',
'ff00d7', 'ff00ff', 'ff5f00', 'ff5f5f', 'ff5f87', 'ff5faf', 'ff5fd7', 'ff5fff',
'ff8700', 'ff875f', 'ff8787', 'ff87af', 'ff87d7', 'ff87ff', 'ffaf00', 'ffaf5f',
'ffaf87', 'ffafaf', 'ffafd7', 'ffafff', 'ffd700', 'ffd75f', 'ffd787', 'ffd7af',
'ffd7d7', 'ffd7ff', 'ffff00', 'ffff5f', 'ffff87', 'ffffaf', 'ffffd7', 'ffffff',
'080808', '121212', '1c1c1c', '262626', '303030', '3a3a3a', '444444', '4e4e4e',
'585858', '626262', '6c6c6c', '767676', '808080', '8a8a8a', '949494', '9e9e9e',
'a8a8a8', 'b2b2b2', 'bcbcbc', 'c6c6c6', 'd0d0d0', 'dadada', 'e4e4e4', 'eeeeee'
]
@parent_element.css backgroundColor: "##{@palette[0]}", color: "##{@palette[7]}"
@redraw()
color_to_css: (i) ->
# handle inverse bit
if i & 0x080000
index = ((i >> 8) & 0xff)
else
index = (i & 0xff)
# lighten the basic 8 colors when they're bold
if ((i & 0x10000) and index < 8)
index += 8
return 'color: #' + @palette[index] + '; '
bg_color_to_css: (i) ->
# xor the inverse bit, to get color_to_css to use the bg color
return 'background-' + @color_to_css(i ^ 0x080000)
stylize: (txt, style) ->
return '' if txt.length is 0
return $('').text txt if style is 0x000007
css = ''
css += 'font-weight: bold; ' if style & 0x010000
css += 'text-decoration: underline; ' if style & 0x020000
css += 'font-style: italic; ' if style & 0x200000 # italic
css += 'opacity: 0; ' if style & 0x100000 # invisible
css += @color_to_css(style) if ((style & 0x0800ff) isnt 0x07)
css += @bg_color_to_css(style) if (style & 0x08ff00)
return $('').text(txt)
redraw_now: ->
@parent_element.empty()
# cursor can be just off the right side, but we draw it on the last column in that case
if @term.x >= @term.width
cursor_x = @term.width - 1
else
cursor_x = @term.x
# invert the cursor TODO: make it blink
if @term.cursor_visible
@term.attributes[@term.y][cursor_x] ^= 0x080000
for i in [0...@term.text.length]
div = $('')
txt = ''
a = 0x000007
for j in [0...@term.text[i].length]
if (@term.attributes[i][j] isnt a)
if (txt.length)
div.append(@stylize(txt, a))
txt = ''
a = @term.attributes[i][j]
txt += @term.text[i][j]
if txt.length
div.append(@stylize(txt, a))
@parent_element.append(div)
if @term.cursor_visible
@term.attributes[@term.y][cursor_x] ^= 0x080000
# limit to 50fps
redraw: ->
if (@redraw_wait)
@redraw_again = true
else
@redraw_now()
@redraw_wait = true
@redraw_again = false
@timeout 20, =>
@redraw_wait = false
if (@redraw_again)
@redraw_again = false
@redraw()
update: (data) ->
@term.update(data)
@redraw()
window.htmlterm = (jq_element, width, height) ->
return new HTMLTerminal(jq_element, width, height)