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