twiddler-utils 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,12 @@
1
+ /* Hide controls */
2
+
3
+ body {
4
+ color: #000000;
5
+ background-color: #ffffff;
6
+ }
7
+
8
+ /* Hide controls */
9
+
10
+ div.filters {
11
+ display: none;
12
+ }
@@ -0,0 +1,42 @@
1
+ function toggleCode( id ) {
2
+ if ( document.getElementById ) {
3
+ elem = document.getElementById( id );
4
+ } else if ( document.all ) {
5
+ elem = eval( "document.all." + id );
6
+ } else {
7
+ return false;
8
+ }
9
+
10
+ elemStyle = elem.style;
11
+
12
+ if ( elemStyle.display != "block" ) {
13
+ elemStyle.display = "block";
14
+ } else {
15
+ elemStyle.display = "none";
16
+ }
17
+
18
+ return true;
19
+ }
20
+
21
+ function restripe() {
22
+ i = 0;
23
+ $('table#report_table tbody tr').each(function(){
24
+ if (this.style.display != "none") {
25
+ i += 1;
26
+ classes = this.className.split(" ");
27
+ if ($.inArray("even",classes) != -1) {
28
+ classes.splice($.inArray("even",classes),1);
29
+ } else if ($.inArray("odd",classes) != -1) {
30
+ classes.splice($.inArray("odd",classes),1);
31
+ }
32
+ if (i % 2 === 0) {
33
+ this.className = classes.join(" ") + " odd";
34
+ } else {
35
+ this.className = classes.join(" ") + " even";
36
+ }
37
+ }
38
+ });
39
+ }
40
+
41
+ // Fix IE's lack of support for indexOf (!)
42
+ if (!Array.indexOf) { Array.prototype.indexOf = function(obj){ for(var i=0; i<this.length; i++){ if(this[i]==obj){return i;} } return -1; }}
@@ -0,0 +1,270 @@
1
+ /* @group General */
2
+
3
+ body {
4
+ font-family: Verdana, Helvetica, Arial, Sans-Serif;
5
+ font-size: 12px;
6
+ color: #4C4C4C;
7
+ background-color: #F4F2ED;
8
+ padding: 1em;
9
+ }
10
+
11
+ a:link {
12
+ color: #191919;
13
+ }
14
+
15
+ a:visited {
16
+ color: #191919;
17
+ }
18
+
19
+ pre, code {
20
+ color: #000000;
21
+ font-family: "Bitstream Vera Sans Mono","Monaco","Courier New",monospace;
22
+ font-size: 95%;
23
+ line-height: 1.3em;
24
+ margin-top: 0;
25
+ margin-bottom: 0;
26
+ padding: 0;
27
+ word-wrap: break-word;
28
+ }
29
+
30
+ h1, h2, h3, h4, h5, h6 {
31
+ margin: 0em 0em 1em 0em;
32
+ color: #666666;
33
+ }
34
+
35
+ h1 {
36
+ display: block;
37
+ font-size: 2em;
38
+ letter-spacing: -1px;
39
+ }
40
+
41
+ h2 {
42
+ margin-top: -1em;
43
+ }
44
+
45
+ fieldset {
46
+ display: inline;
47
+ border: 0px;
48
+ padding: 0px;
49
+ margin-right: 1em;
50
+ }
51
+
52
+ div.filters {
53
+ margin-bottom: 1em;
54
+ }
55
+
56
+ .hidden {
57
+ display: none;
58
+ }
59
+
60
+ /* @end */
61
+
62
+ /* @group Cross-References */
63
+
64
+ span.cross-ref-title {
65
+ font-size: 140%;
66
+ }
67
+
68
+ span.cross-ref a {
69
+ text-decoration: none;
70
+ }
71
+
72
+ span.cross-ref {
73
+ background-color:#f3f7fa;
74
+ border: 1px dashed #333;
75
+ margin: 1em;
76
+ padding: 0.5em;
77
+ overflow: hidden;
78
+ }
79
+
80
+ a.crossref-toggle {
81
+ text-decoration: none;
82
+ }
83
+
84
+ /* @end */
85
+
86
+ /* @group Report Table */
87
+
88
+ div.report_table_wrapper {
89
+ min-width: 900px;
90
+ }
91
+
92
+ table.report {
93
+ border-collapse: collapse;
94
+ border: 1px solid #666666;
95
+ width: 100%;
96
+ margin-bottom: 1em;
97
+ }
98
+
99
+ table.report tr {
100
+ line-height: 1.75em;
101
+ }
102
+
103
+ table.report th {
104
+ background: #666666;
105
+ color: #ffffff;
106
+ text-align: right;
107
+ text-transform: uppercase;
108
+ font-size: .8em;
109
+ font-weight: bold;
110
+ padding: 0em .5em;
111
+ border: 1px solid #666666;
112
+ }
113
+
114
+ table.report tfoot tr {
115
+ background: #dddddd;
116
+ font-weight: bold;
117
+ padding: .5em;
118
+ border: 1px solid #666666;
119
+ }
120
+
121
+ th.left_align, td.left_align {
122
+ text-align: left !important;
123
+ }
124
+
125
+ th.right_align, td.right_align {
126
+ text-align: right;
127
+ padding-right: 2em !important;
128
+ }
129
+
130
+ table.report th.header:hover {
131
+ cursor: pointer;
132
+ text-decoration: underline;
133
+ }
134
+
135
+ table.report th.headerSortUp:after{
136
+ content: "\25BC";
137
+ margin-left: 1em;
138
+ }
139
+
140
+ table.report th.headerSortDown:after {
141
+ content: "\25B2";
142
+ margin-left: 1em;
143
+ }
144
+
145
+ table.report tr.summary_row {
146
+ background: #cccccc;
147
+ border: 1px solid #cccccc;
148
+ }
149
+
150
+ table.report tr.summary_row td {
151
+ padding-left: .2em !important;
152
+ color: #333333;
153
+ font-weight: bold;
154
+ }
155
+
156
+ table.report td {
157
+ padding: .2em .5em .2em .5em;
158
+ }
159
+
160
+ table.report td a {
161
+ text-decoration: none;
162
+ }
163
+
164
+ table.report tbody tr:hover {
165
+ background: #cccccc !important;
166
+ }
167
+
168
+ table.report tr.summary_row td {
169
+ border-bottom: 1px solid #aaaaaa;
170
+ }
171
+
172
+ table.report tr {
173
+ background-color: #eeeeee;
174
+ }
175
+
176
+ table.report tr.odd {
177
+ background-color: #dddddd;
178
+ }
179
+
180
+ /* @end */
181
+
182
+ /* @group Percentage Graphs */
183
+
184
+ div.percent_graph_legend {
185
+ width: 5.5em;
186
+ float: left;
187
+ margin: .5em 1em .5em 0em;
188
+ height: 1em;
189
+ line-height: 1em;
190
+ }
191
+
192
+ div.percent_graph {
193
+ height: 1em;
194
+ border: #333333 1px solid;
195
+ empty-cells: show;
196
+ padding: 0px;
197
+ border-collapse: collapse;
198
+ width: 100px !important;
199
+ float: left;
200
+ margin: .5em 1em .5em 0em;
201
+ }
202
+
203
+ div.percent_graph div {
204
+ float: left;
205
+ height: 1em;
206
+ padding: 0px !important;
207
+ }
208
+
209
+ div.percent_graph div.covered {
210
+ background: #649632;
211
+ }
212
+
213
+ div.percent_graph div.uncovered {
214
+ background: #a92730;
215
+ }
216
+
217
+ div.percent_graph div.NA {
218
+ background: #eaeaea;
219
+ }
220
+
221
+ /* @end */
222
+
223
+ /* @group Details page */
224
+
225
+ table.details {
226
+ margin-top: 1em;
227
+ border-collapse: collapse;
228
+ width: 100%;
229
+ border: 1px solid #666666;
230
+ }
231
+
232
+ table.details tr {
233
+ line-height: 1.75em;
234
+ }
235
+
236
+ table.details td {
237
+ padding: .25em;
238
+ }
239
+
240
+ span.inferred, span.inferred1, span.marked, span.marked1, span.uncovered, span.uncovered1 {
241
+ display: block;
242
+ padding: .25em;
243
+ }
244
+
245
+ tr.inferred td, span.inferred {
246
+ background-color: #e0dedb;
247
+ }
248
+
249
+ tr.inferred1 td, span.inferred1 {
250
+ background-color: #e0dedb;
251
+ }
252
+
253
+ tr.marked td, span.marked, span.marked1 {
254
+ background-color: #bed2be;
255
+ }
256
+
257
+ tr.uncovered td, span.uncovered {
258
+ background-color: #ce8b8c;
259
+ }
260
+
261
+ tr.uncovered1 td, span.uncovered1 {
262
+ background-color: #ce8b8c;
263
+ }
264
+
265
+ div.key {
266
+ border: 1px solid #666666;
267
+ margin: 1em 0em;
268
+ }
269
+
270
+ /* @end */
@@ -0,0 +1,414 @@
1
+ module Twiddler
2
+ class Config
3
+ class KeyTable
4
+ class KeyData
5
+ ModAliases = Hash.new{|h,k| k}.merge!(
6
+ "rsft" => "shift",
7
+ "lsft" => "shift",
8
+ "rctl" => "control",
9
+ "lctl" => "control",
10
+ "lalt" => "alt",
11
+ "ralt" => "alt",
12
+ "lgui" => "gui",
13
+ "rgui" => "gui"
14
+ )
15
+
16
+ def initialize(num, name)
17
+ @code = num
18
+ @data = { :unmod => name }
19
+ @tags = {}
20
+ end
21
+ attr_reader :code
22
+
23
+ def tag(name)
24
+ @tags[name.to_sym] = true
25
+ end
26
+
27
+ def tag?(name)
28
+ @tags.has_key?(name)
29
+ end
30
+
31
+ def modified(mod, value)
32
+ @data[normalized(mod)] = value
33
+ end
34
+
35
+ def string(mod=nil)
36
+ return @data[:unmod] if mod.nil? or mod.empty?
37
+ if data = @data[normalized(mod)]
38
+ return data
39
+ else
40
+ return "#{mod}-#{@data[:unmod]}"
41
+ end
42
+ end
43
+
44
+ def has_mod?(mod)
45
+ @data.has_key?(normalized(mod))
46
+ end
47
+
48
+ def ===(chord)
49
+ chord.single? and chord[0][0] == @code
50
+ end
51
+
52
+ def self.normalized(mod)
53
+ unless Array === mod
54
+ mod = mod.split("-")
55
+ end
56
+ return mod.map{|i| ModAliases[i.downcase]}.sort.join("-")
57
+ end
58
+
59
+ def normalized(mod)
60
+ self.class.normalized(mod)
61
+ end
62
+ end
63
+
64
+ def initialize
65
+ @data = Hash.new{|h,k| KeyData.new(k, "U/#{k.inspect}")}
66
+ @ordered = []
67
+ @current_tags = {}
68
+ end
69
+
70
+ def normalized(stroke)
71
+ mods = KeyData::normalized(stroke[1])
72
+ return [stroke[0], mods]
73
+ end
74
+
75
+ def unknowns(list)
76
+ return list.reject do |item|
77
+ @data.has_key?(item)
78
+ end
79
+ end
80
+
81
+ def start_tag(name)
82
+ @current_tags[name.to_sym] = true
83
+ end
84
+
85
+ def end_tag(name)
86
+ @current_tags.delete(name.to_sym)
87
+ end
88
+
89
+ def clear_tags
90
+ @current_tags.clear
91
+ end
92
+
93
+ def tagged(name)
94
+ @ordered.find_all do |key|
95
+ key.tag?(name)
96
+ end
97
+ end
98
+
99
+ def is_tagged?(idx, tag)
100
+ @data[idx].tag?(tag)
101
+ end
102
+
103
+ def [](idx, mod=nil)
104
+ return @data[idx].string(mod)
105
+ end
106
+
107
+ def []=(idx, value)
108
+ if @data.has_key?(idx)
109
+ @ordered.delete(@data[idx])
110
+ end
111
+ data = KeyData.new(idx, value)
112
+ @current_tags.each_key do |name|
113
+ data.tag(name)
114
+ end
115
+ @data[idx] = data
116
+ @ordered << data
117
+ end
118
+
119
+ include Enumerable
120
+ def each(&block)
121
+ @ordered.each(&block)
122
+ end
123
+
124
+ def mod(idx, mod, value)
125
+ @data[idx].modified(mod, value)
126
+ end
127
+ end
128
+
129
+ def self.keytable
130
+ @table ||=
131
+ begin
132
+ table = KeyTable.new
133
+
134
+ table.start_tag(:normal)
135
+ table.start_tag(:letters)
136
+ (("a".."z").to_a).each_with_index do |ltr, idx|
137
+ table[idx+4] = ltr
138
+ end
139
+ (("A".."Z").to_a).each_with_index do |ltr, idx|
140
+ table.mod(idx+4, "shift", ltr)
141
+ end
142
+ table.end_tag(:letters)
143
+ table.start_tag(:numbers)
144
+
145
+ (("1".."9").to_a + ["0"]).each_with_index do |num, idx|
146
+ table[idx+30] = num
147
+ end
148
+ %w[! @ # $ % ^ & * ( )].each_with_index do |shift_num, idx|
149
+ table.mod(idx+30, "shift", shift_num)
150
+ end
151
+ table.end_tag(:numbers)
152
+
153
+ table.start_tag(:punctuation)
154
+ table[45] = "-"
155
+ table.mod(45, "shift", "_")
156
+ table[46] = "="
157
+ table.mod(46, "shift", "+")
158
+ table[47] = "["
159
+ table.mod(47, "shift", "{")
160
+ table[48] = "]"
161
+ table.mod(48, "shift", "}")
162
+ table[49] = "\\"
163
+ table.mod(49, "shift", "|")
164
+ table[56] = "/"
165
+ table.mod(56, "shift", "?")
166
+ table[51] = ";"
167
+ table.mod(51, "shift", ":")
168
+ table[52] = "'"
169
+ table.mod(52, "shift", "\"")
170
+ table[53] = "`"
171
+ table.mod(53, "shift", "~")
172
+ table[54] = ","
173
+ table.mod(54, "shift", "<")
174
+ table[55] = "."
175
+ table.mod(55, "shift", ">")
176
+ table[73] = "~"
177
+ table.clear_tags
178
+
179
+ table.start_tag(:special)
180
+ table[40] = "<Rtrn>"
181
+ table[41] = "<Esc>"
182
+ table[42] = "<Bksp>"
183
+ table[43] = "<Tab>"
184
+ table[44] = "<Spc>"
185
+ table[57] = "<Cplk>"
186
+ table[71] = "<Scrlk>"
187
+ table[74] = "<Home>"
188
+ table[75] = "<PgUp>"
189
+ table[76] = "<Delete>"
190
+ table[77] = "<End>"
191
+ table[78] = "<PgDn>"
192
+ table[79] = "<Right>"
193
+ table[80] = "<Left>"
194
+ table[81] = "<Down>"
195
+ table[82] = "<Up>"
196
+ table[83] = "<Nmlk>"
197
+
198
+ table.start_tag(:fkeys)
199
+ ("1".."12").to_a.each_with_index do |fkey, idx|
200
+ table[idx+58] = "F" + fkey
201
+ end
202
+ table.end_tag(:fkeys)
203
+
204
+ table.start_tag(:hardware_control)
205
+ table[-2] = "<<Mass Storage Mode>>"
206
+ table[-3] = "<<Upgrade Mode>>"
207
+ table[-4] = "<<Disable Mouse Mode>>"
208
+ table[-5] = "<<Enable Mouse Mode>>"
209
+ table.clear_tags
210
+
211
+ table
212
+ end
213
+ end
214
+
215
+ class Chord
216
+ def initialize
217
+ @rows = [:open, :open, :open, :open]
218
+ @mods = {:num => false,
219
+ :shift => false, :ctrl => false, :alt => false}
220
+ end
221
+
222
+ attr_reader :rows, :mods
223
+
224
+ def extract_key(bits, idx, mod, range)
225
+ @rows[idx] = case bits[range]
226
+ when /1.../; :left
227
+ when /.1../; :middle
228
+ when /..1./; :right
229
+ else :open
230
+ end
231
+ @mods[mod] = (bits[range.last] == ?1)
232
+
233
+ end
234
+
235
+ def keydata=(bits)
236
+ extract_key(bits, 0, :num, 4..7)
237
+ extract_key(bits, 1, :alt, 0..3)
238
+ extract_key(bits, 2, :ctrl, 12..15)
239
+ extract_key(bits, 3, :shift, 8..11)
240
+ end
241
+
242
+ def render_keys
243
+ mods =
244
+ (@mods[:num] ? "N" : "") +
245
+ (@mods[:alt] ? "A" : "") +
246
+ (@mods[:ctrl] ? "C" : "") +
247
+ (@mods[:shift] ? "S" : "")
248
+ if mods.empty?
249
+ mods = "O"
250
+ end
251
+
252
+ chord = rows.map do |row|
253
+ case row
254
+ when :open; "O"
255
+ when :left; "L"
256
+ when :right; "R"
257
+ when :middle; "M"
258
+ else "wtf?"
259
+ end
260
+ end.join("")
261
+
262
+ return "#{mods} #{chord}"
263
+ end
264
+
265
+ def render_action
266
+ ""
267
+ end
268
+
269
+ def render
270
+ "#{render_keys} => #{render_action}"
271
+ end
272
+ end
273
+
274
+ class KeyChord < Chord
275
+ ModKeys = %w{RGui RAlt RSft RCtl LGui LAlt LSft LCtl}
276
+
277
+ def initialize
278
+ super
279
+ @keystrokes = []
280
+ end
281
+
282
+ attr_reader :keystrokes
283
+
284
+ def [](idx)
285
+ @keystrokes[idx]
286
+ end
287
+
288
+ def single?
289
+ @keystrokes.length == 1
290
+ end
291
+
292
+ def add_keystroke(mod_bits, idx)
293
+ mods = ModKeys.zip(mod_bits.split('')).delete_if{|mod,bit| bit != "1"}.map{|mod,bit| mod}
294
+ @keystrokes << [idx, mods]
295
+ end
296
+
297
+ def keytable
298
+ Config.keytable
299
+ end
300
+
301
+ def render_action
302
+ output = []
303
+ (@keystrokes || []).each do |code, mods|
304
+ output << keytable[code, mods]
305
+ end
306
+
307
+ return output.join()
308
+ end
309
+ end
310
+
311
+ class MouseChord < Chord
312
+
313
+ def initialize
314
+ super
315
+ @mods = {
316
+ :ctrl => false,
317
+ :alt => false,
318
+ :shift => false,
319
+ :double => false,
320
+ :toggle => false
321
+ }
322
+ @buttons = {
323
+ :left => false,
324
+ :middle => false,
325
+ :right => false
326
+ }
327
+ end
328
+
329
+ attr_reader :mods, :buttons
330
+
331
+ def data=(bits)
332
+ if bits[0] == ?1
333
+ @mods[:ctrl] = true
334
+ end
335
+ if bits[1] == ?1
336
+ @mods[:alt] = true
337
+ end
338
+ if bits[2] == ?1
339
+ @mods[:shift] = true
340
+ end
341
+ if bits[3] == ?1
342
+ @mods[:double] = true
343
+ end
344
+ if bits[4] == ?1
345
+ @mods[:toggle] = true
346
+ end
347
+ if bits[5] == ?1
348
+ @buttons[:middle] = true
349
+ end
350
+ if bits[6] == ?1
351
+ @buttons[:right] = true
352
+ end
353
+ if bits[7] == ?1
354
+ @buttons[:left] = true
355
+ end
356
+ end
357
+
358
+ def render_action
359
+ action = ""
360
+ if @mods[:ctrl]
361
+ action << "Ctl-"
362
+ end
363
+ if @mods[:alt]
364
+ action << "Alt-"
365
+ end
366
+ if @mods[:shift]
367
+ action << "Shf-"
368
+ end
369
+ if @mods[:double]
370
+ action << "Dbl-"
371
+ end
372
+ if @mods[:toggle]
373
+ action << "Tgl-"
374
+ end
375
+ if @buttons[:middle]
376
+ action << "M"
377
+ end
378
+ if @buttons[:right]
379
+ action << "R"
380
+ end
381
+ if @buttons[:left]
382
+ action << "L"
383
+ end
384
+ return action
385
+ end
386
+ end
387
+
388
+
389
+ def initialize()
390
+ @mouse = []
391
+ @keyboard = []
392
+ @configs = {}
393
+ end
394
+
395
+ def keytable
396
+ self.class.keytable
397
+ end
398
+
399
+ attr_reader :mouse, :keyboard, :configs
400
+
401
+ def inspect
402
+ "<Twiddler::Config: \n " +
403
+ "Config: #{@configs.inspect}\n " +
404
+ @keyboard.map do |chord|
405
+ chord.render
406
+ end.join("\n ") +
407
+ "\n ---\n " +
408
+ @mouse.map do |chord|
409
+ chord.render
410
+ end.join("\n ") + "\n" +
411
+ ">"
412
+ end
413
+ end
414
+ end