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)