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
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
if a is 0x000007
# don't output spaces at the end, for better copy/paste
ns = txt.length - 1
while ns >= 0 and txt.charAt(ns) is ' '
ns -= 1
if ns >= 0
if ns < txt.length - 1
txt = txt.substr 0, ns + 1
div.append(@stylize(txt, a))
else
# if entire line is spaces
if txt.length is @term.width
div.append('
')
else
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)