$ -> timeout = (ms, f) -> setTimeout(f, ms) term = null 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' ] $body = $('body') $body.css backgroundColor: "##{palette[0]}", color: "##{palette[7]}" socket = io.connect('http://localhost') 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) -> if (txt.length == 0 or style == 0x000007) return txt 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_wait = false redraw_again = false redraw_now = -> $body.children().remove() # 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)) $body.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) -> if (term) term.update(data) redraw() socket.on 'data', (data) -> update(data) socket.on 'init', (v) -> term = terminal.new(v.width, v.height) term.x = v.x term.y = v.y term.a = v.a term.text = v.text term.attributes = v.attributes term.cursor_visible = v.cursor_visible term.scroll_top = v.scroll_top term.scroll_bottom = v.scroll_bottom redraw()