JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
829f7578f3dde9e6e2b7d1c428ef271d881dc566
[watch-my-terminal.git] / htmlterm.coffee
1 class HTMLTerminal
2         timeout: (ms, f) -> setTimeout(f, ms)
3         constructor: (jq_element, width, height) ->
4                 @parent_element = jq_element
5                 @redraw_wait = false
6                 @redraw_again = false
7                 @term = window.terminal.new width, height
8                 @palette = [
9                         # normal colours
10                         '2e3436',
11                         'cc0000',
12                         '4e9a06',
13                         'c4a000',
14                         '3465a4',
15                         '75507b',
16                         '06989a',
17                         'd3d7cf',
18
19                         # brighter versions (for bold, and 16-color sequences)
20                         '555753',
21                         'ef2929',
22                         '8ae234',
23                         'fce94f',
24                         '729fcf',
25                         'ad7fa8',
26                         '34e2e2',
27                         'eeeeec',
28
29                         # 256 colors
30                         '000000', '00005f', '000087', '0000af', '0000d7', '0000ff', '005f00', '005f5f',
31                         '005f87', '005faf', '005fd7', '005fff', '008700', '00875f', '008787', '0087af',
32                         '0087d7', '0087ff', '00af00', '00af5f', '00af87', '00afaf', '00afd7', '00afff',
33                         '00d700', '00d75f', '00d787', '00d7af', '00d7d7', '00d7ff', '00ff00', '00ff5f',
34                         '00ff87', '00ffaf', '00ffd7', '00ffff', '5f0000', '5f005f', '5f0087', '5f00af',
35                         '5f00d7', '5f00ff', '5f5f00', '5f5f5f', '5f5f87', '5f5faf', '5f5fd7', '5f5fff',
36                         '5f8700', '5f875f', '5f8787', '5f87af', '5f87d7', '5f87ff', '5faf00', '5faf5f',
37                         '5faf87', '5fafaf', '5fafd7', '5fafff', '5fd700', '5fd75f', '5fd787', '5fd7af',
38                         '5fd7d7', '5fd7ff', '5fff00', '5fff5f', '5fff87', '5fffaf', '5fffd7', '5fffff',
39                         '870000', '87005f', '870087', '8700af', '8700d7', '8700ff', '875f00', '875f5f',
40                         '875f87', '875faf', '875fd7', '875fff', '878700', '87875f', '878787', '8787af',
41                         '8787d7', '8787ff', '87af00', '87af5f', '87af87', '87afaf', '87afd7', '87afff',
42                         '87d700', '87d75f', '87d787', '87d7af', '87d7d7', '87d7ff', '87ff00', '87ff5f',
43                         '87ff87', '87ffaf', '87ffd7', '87ffff', 'af0000', 'af005f', 'af0087', 'af00af',
44                         'af00d7', 'af00ff', 'af5f00', 'af5f5f', 'af5f87', 'af5faf', 'af5fd7', 'af5fff',
45                         'af8700', 'af875f', 'af8787', 'af87af', 'af87d7', 'af87ff', 'afaf00', 'afaf5f',
46                         'afaf87', 'afafaf', 'afafd7', 'afafff', 'afd700', 'afd75f', 'afd787', 'afd7af',
47                         'afd7d7', 'afd7ff', 'afff00', 'afff5f', 'afff87', 'afffaf', 'afffd7', 'afffff',
48                         'd70000', 'd7005f', 'd70087', 'd700af', 'd700d7', 'd700ff', 'd75f00', 'd75f5f',
49                         'd75f87', 'd75faf', 'd75fd7', 'd75fff', 'd78700', 'd7875f', 'd78787', 'd787af',
50                         'd787d7', 'd787ff', 'd7af00', 'd7af5f', 'd7af87', 'd7afaf', 'd7afd7', 'd7afff',
51                         'd7d700', 'd7d75f', 'd7d787', 'd7d7af', 'd7d7d7', 'd7d7ff', 'd7ff00', 'd7ff5f',
52                         'd7ff87', 'd7ffaf', 'd7ffd7', 'd7ffff', 'ff0000', 'ff005f', 'ff0087', 'ff00af',
53                         'ff00d7', 'ff00ff', 'ff5f00', 'ff5f5f', 'ff5f87', 'ff5faf', 'ff5fd7', 'ff5fff',
54                         'ff8700', 'ff875f', 'ff8787', 'ff87af', 'ff87d7', 'ff87ff', 'ffaf00', 'ffaf5f',
55                         'ffaf87', 'ffafaf', 'ffafd7', 'ffafff', 'ffd700', 'ffd75f', 'ffd787', 'ffd7af',
56                         'ffd7d7', 'ffd7ff', 'ffff00', 'ffff5f', 'ffff87', 'ffffaf', 'ffffd7', 'ffffff',
57                         '080808', '121212', '1c1c1c', '262626', '303030', '3a3a3a', '444444', '4e4e4e',
58                         '585858', '626262', '6c6c6c', '767676', '808080', '8a8a8a', '949494', '9e9e9e',
59                         'a8a8a8', 'b2b2b2', 'bcbcbc', 'c6c6c6', 'd0d0d0', 'dadada', 'e4e4e4', 'eeeeee'
60                 ]
61
62                 @parent_element.css backgroundColor: "##{@palette[0]}", color: "##{@palette[7]}"
63
64         color_to_css: (i) ->
65                 # handle inverse bit
66                 if i & 0x080000
67                         index = ((i >> 8) & 0xff)
68                 else
69                         index = (i & 0xff)
70
71                 # lighten the basic 8 colors when they're bold
72                 if ((i & 0x10000) and index < 8)
73                         index += 8
74                 return 'color: #' + @palette[index] + '; '
75
76         bg_color_to_css: (i) ->
77                 # xor the inverse bit, to get color_to_css to use the bg color
78                 return 'background-' + @color_to_css(i ^ 0x080000)
79
80         stylize: (txt, style) ->
81                 return '' if txt.length is 0
82                 return $('<span>').text txt if style is 0x000007
83                 css = ''
84                 css += 'font-weight: bold; ' if style & 0x010000
85                 css += 'text-decoration: underline; ' if style & 0x020000
86                 css += 'font-style: italic; ' if style & 0x200000 # italic
87                 css += 'opacity: 0; ' if style & 0x100000 # invisible
88                 css += @color_to_css(style) if ((style & 0x0800ff) isnt 0x07)
89                 css += @bg_color_to_css(style) if (style & 0x08ff00)
90                 return $('<span style="'+css+'"></span>').text(txt)
91
92         redraw_now: ->
93                 console.log('redraw_now')
94                 @parent_element.empty()
95                 # cursor can be just off the right side, but we draw it on the last column in that case
96                 if @term.x >= @term.width
97                         cursor_x = @term.width - 1
98                 else
99                         cursor_x = @term.x
100                 # invert the cursor TODO: make it blink
101                 if @term.cursor_visible
102                         @term.attributes[@term.y][cursor_x] ^= 0x080000
103                 for i in [0...@term.text.length]
104                         div = $('<code>')
105                         txt = ''
106                         a = 0x000007
107                         for j in [0...@term.text[i].length]
108                                 if (@term.attributes[i][j] isnt a)
109                                         if (txt.length)
110                                                 div.append(@stylize(txt, a))
111                                                 txt = ''
112                                         a = @term.attributes[i][j]
113                                 txt += @term.text[i][j]
114                         if txt.length
115                                 div.append(@stylize(txt, a))
116                         @parent_element.append(div)
117                 if @term.cursor_visible
118                         @term.attributes[@term.y][cursor_x] ^= 0x080000
119
120         # limit to 50fps
121         redraw: ->
122                 console.log('redraw')
123                 if (@redraw_wait)
124                         @redraw_again = true
125                 else
126                         @redraw_now()
127                         @redraw_wait = true
128                         @redraw_again = false
129                         @timeout 20, =>
130                                 @redraw_wait = false
131                                 if (@redraw_again)
132                                         @redraw_again = false
133                                         @redraw()
134
135         update: (data) ->
136                 @term.update(data)
137                 @redraw()
138
139 window.htmlterm = (jq_element, width, height) ->
140         return new HTMLTerminal(jq_element, width, height)