rubyception 0.1.1 → 0.2.0

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.
Files changed (39) hide show
  1. data/README.md +26 -6
  2. data/app/assets/images/rubyception/entry_collapse.png +0 -0
  3. data/app/assets/images/rubyception/entry_expand.png +0 -0
  4. data/app/assets/javascripts/rubyception/application.coffee +1 -3
  5. data/app/assets/javascripts/rubyception/routers/log.coffee +4 -2
  6. data/app/assets/javascripts/rubyception/syntax_highlighting.js +543 -0
  7. data/app/assets/javascripts/rubyception/views/backtrace_lines/index.coffee +0 -1
  8. data/app/assets/javascripts/rubyception/views/entries/entry.coffee +30 -11
  9. data/app/assets/stylesheets/rubyception/application.sass +1 -2
  10. data/app/assets/stylesheets/rubyception/entries.sass +54 -5
  11. data/app/assets/stylesheets/rubyception/lines.sass +10 -7
  12. data/app/assets/stylesheets/rubyception/syntax_highlighting.css +138 -0
  13. data/app/controllers/rubyception/templates_controller.rb +12 -0
  14. data/app/helpers/rubyception/application_helper.rb +19 -0
  15. data/app/models/rubyception/entry.rb +37 -2
  16. data/app/views/layouts/rubyception/application.haml +1 -0
  17. data/app/views/rubyception/entries/_entry.haml +14 -7
  18. data/app/views/rubyception/lines/action_view/_render_partial.haml +2 -2
  19. data/app/views/rubyception/lines/action_view/_render_template.haml +2 -2
  20. data/app/views/rubyception/lines/active_record/_identity.haml +2 -2
  21. data/app/views/rubyception/lines/active_record/_sql.haml +3 -3
  22. data/app/views/rubyception/templates/index.js.erb +4 -0
  23. data/config/initializers/sass.rb +1 -2
  24. data/config/initializers/templates.rb +5 -0
  25. data/config/routes.rb +1 -0
  26. data/config/{templating.yml → templates.yml} +7 -7
  27. data/lib/rubyception/engine.rb +27 -0
  28. data/lib/rubyception/version.rb +1 -1
  29. metadata +10 -13
  30. data/app/assets/javascripts/rubyception/shBrushSql.js +0 -66
  31. data/app/assets/javascripts/rubyception/shCore.js +0 -17
  32. data/app/assets/javascripts/rubyception/template.js +0 -1
  33. data/app/assets/stylesheets/rubyception/shCore.css +0 -226
  34. data/app/assets/stylesheets/rubyception/shThemeDefault.css +0 -117
  35. data/app/controllers/rubyception/templating_controller.rb +0 -22
  36. data/config/initializers/websocket_server.rb +0 -22
  37. data/lib/rubyception/templating.rb +0 -48
  38. data/lib/tasks/rubyception_tasks.rake +0 -4
  39. data/lib/tasks/templates.rake +0 -7
data/README.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  A realtime log viewer for Rails (released under the MIT license)
4
4
 
5
+ --------------------
6
+
7
+ This shows a normal log entry
8
+ ![screenshot 1](https://s3.amazonaws.com/tye/rubyception1.png)
9
+
10
+ This entry has an exception. The backtrace file names are clickable and will open in MacVim. Soon support for TextMate & other editors will be added.
11
+ ![screenshot 2](https://s3.amazonaws.com/tye/rubyception2.png)
12
+
5
13
  ## Features
6
14
 
7
15
  * Real-time updating of the log file using Websocket
@@ -9,27 +17,39 @@ A realtime log viewer for Rails (released under the MIT license)
9
17
 
10
18
  ## Installation
11
19
 
12
- Add to your gemfile:
20
+ Add to your gemfile **in the development group**:
13
21
  ```ruby
14
- gem 'rubyception'
22
+ group :development do
23
+ gem 'rubyception'
24
+ end
15
25
  ```
16
26
  Run:
17
27
  ```
18
28
  bundle install
19
29
  ```
20
- Add to your routes:
30
+
31
+ Add to your `config/routes.rb`:
21
32
  ```ruby
22
- match 'rubyception' => 'rubyception/application#index'
33
+ mount Rubyception::Engine => '/rubyception'
23
34
  ```
24
- Open your app and go to:<br>
35
+ Run your rails server and go to:<br>
25
36
  `http://localhost:3000/rubyception`<br>
26
37
  Your log entries will appear on the rubyception page in realtime. You
27
38
  must be using a browser that supports Websockets.
28
39
 
40
+ ## Using in Production
41
+ Rubyception is not intended to be used in a production environment. If
42
+ you need exception handling in production I recommend
43
+ [Airbrake](http://airbrake.io/pages/home),
44
+ [Exceptional](http://www.exceptional.io/) or
45
+ [NewRelic](https://newrelic.com/).
46
+
29
47
  ## Hotkeys
30
48
  `up` or `k` Move selection up<br>
31
49
  `down` or `j` Move selection down<br>
32
50
  `enter` Expand selected entry<br>
33
51
  `G` Go to last entry<br>
34
52
  `gg` Go to first entry<br>
35
- `42gg` or `42G` Go to 42nd entry<br>
53
+ `42gg` or `42G` Go to 42nd entry<br>
54
+ `p` Toggles between inline and nested parameters view if you have a log
55
+ entry open<br>
@@ -5,12 +5,10 @@
5
5
  #= require rubyception/lib/inflections
6
6
  #= require rubyception/lib/jenny
7
7
  #= require rubyception/lib/mousetrap
8
- #= require rubyception/template
9
8
  #= require rubyception/init
10
9
  #= require_tree ./routers
11
10
  #= require_tree ./views
12
11
  #= require_tree ./collections
13
12
  #= require_tree ./models
14
13
  #= require rubyception/app
15
- #= require rubyception/shCore
16
- #= require rubyception/shBrushSql
14
+ #= require rubyception/syntax_highlighting
@@ -28,10 +28,12 @@ class App.Routers.Log extends Backbone.Router
28
28
  @collection.add data
29
29
  default: ->
30
30
  @index()
31
+ toggle_params: =>
32
+ expanded_entry = $('.entry.selected.open')
33
+ if expanded_entry.length > 0
34
+ expanded_entry.find('.params').toggleClass 'nested'
31
35
  toggle_side: =>
32
36
  $('.wrapper').toggleClass 'filter'
33
- toggle_params: =>
34
- $('body').toggleClass 'pretty_params'
35
37
  hotkeys: =>
36
38
  m = Mousetrap
37
39
  m.bind '\\ n' , @toggle_side
@@ -0,0 +1,543 @@
1
+ /*
2
+ SHJS - Syntax Highlighting in JavaScript
3
+ Copyright (C) 2007, 2008 gnombat@users.sourceforge.net
4
+ License: http://shjs.sourceforge.net/doc/gplv3.html
5
+ */
6
+
7
+ if (! this.sh_languages) {
8
+ this.sh_languages = {};
9
+ }
10
+ var sh_requests = {};
11
+
12
+ function sh_isEmailAddress(url) {
13
+ if (/^mailto:/.test(url)) {
14
+ return false;
15
+ }
16
+ return url.indexOf('@') !== -1;
17
+ }
18
+
19
+ function sh_setHref(tags, numTags, inputString) {
20
+ var url = inputString.substring(tags[numTags - 2].pos, tags[numTags - 1].pos);
21
+ if (url.length >= 2 && url.charAt(0) === '<' && url.charAt(url.length - 1) === '>') {
22
+ url = url.substr(1, url.length - 2);
23
+ }
24
+ if (sh_isEmailAddress(url)) {
25
+ url = 'mailto:' + url;
26
+ }
27
+ tags[numTags - 2].node.href = url;
28
+ }
29
+
30
+ /*
31
+ Konqueror has a bug where the regular expression /$/g will not match at the end
32
+ of a line more than once:
33
+
34
+ var regex = /$/g;
35
+ var match;
36
+
37
+ var line = '1234567890';
38
+ regex.lastIndex = 10;
39
+ match = regex.exec(line);
40
+
41
+ var line2 = 'abcde';
42
+ regex.lastIndex = 5;
43
+ match = regex.exec(line2); // fails
44
+ */
45
+ function sh_konquerorExec(s) {
46
+ var result = [''];
47
+ result.index = s.length;
48
+ result.input = s;
49
+ return result;
50
+ }
51
+
52
+ /**
53
+ Highlights all elements containing source code in a text string. The return
54
+ value is an array of objects, each representing an HTML start or end tag. Each
55
+ object has a property named pos, which is an integer representing the text
56
+ offset of the tag. Every start tag also has a property named node, which is the
57
+ DOM element started by the tag. End tags do not have this property.
58
+ @param inputString a text string
59
+ @param language a language definition object
60
+ @return an array of tag objects
61
+ */
62
+ function sh_highlightString(inputString, language) {
63
+ if (/Konqueror/.test(navigator.userAgent)) {
64
+ if (! language.konquered) {
65
+ for (var s = 0; s < language.length; s++) {
66
+ for (var p = 0; p < language[s].length; p++) {
67
+ var r = language[s][p][0];
68
+ if (r.source === '$') {
69
+ r.exec = sh_konquerorExec;
70
+ }
71
+ }
72
+ }
73
+ language.konquered = true;
74
+ }
75
+ }
76
+
77
+ var a = document.createElement('a');
78
+ var span = document.createElement('span');
79
+
80
+ // the result
81
+ var tags = [];
82
+ var numTags = 0;
83
+
84
+ // each element is a pattern object from language
85
+ var patternStack = [];
86
+
87
+ // the current position within inputString
88
+ var pos = 0;
89
+
90
+ // the name of the current style, or null if there is no current style
91
+ var currentStyle = null;
92
+
93
+ var output = function(s, style) {
94
+ var length = s.length;
95
+ // this is more than just an optimization - we don't want to output empty <span></span> elements
96
+ if (length === 0) {
97
+ return;
98
+ }
99
+ if (! style) {
100
+ var stackLength = patternStack.length;
101
+ if (stackLength !== 0) {
102
+ var pattern = patternStack[stackLength - 1];
103
+ // check whether this is a state or an environment
104
+ if (! pattern[3]) {
105
+ // it's not a state - it's an environment; use the style for this environment
106
+ style = pattern[1];
107
+ }
108
+ }
109
+ }
110
+ if (currentStyle !== style) {
111
+ if (currentStyle) {
112
+ tags[numTags++] = {pos: pos};
113
+ if (currentStyle === 'sh_url') {
114
+ sh_setHref(tags, numTags, inputString);
115
+ }
116
+ }
117
+ if (style) {
118
+ var clone;
119
+ if (style === 'sh_url') {
120
+ clone = a.cloneNode(false);
121
+ }
122
+ else {
123
+ clone = span.cloneNode(false);
124
+ }
125
+ clone.className = style;
126
+ tags[numTags++] = {node: clone, pos: pos};
127
+ }
128
+ }
129
+ pos += length;
130
+ currentStyle = style;
131
+ };
132
+
133
+ var endOfLinePattern = /\r\n|\r|\n/g;
134
+ endOfLinePattern.lastIndex = 0;
135
+ var inputStringLength = inputString.length;
136
+ while (pos < inputStringLength) {
137
+ var start = pos;
138
+ var end;
139
+ var startOfNextLine;
140
+ var endOfLineMatch = endOfLinePattern.exec(inputString);
141
+ if (endOfLineMatch === null) {
142
+ end = inputStringLength;
143
+ startOfNextLine = inputStringLength;
144
+ }
145
+ else {
146
+ end = endOfLineMatch.index;
147
+ startOfNextLine = endOfLinePattern.lastIndex;
148
+ }
149
+
150
+ var line = inputString.substring(start, end);
151
+
152
+ var matchCache = [];
153
+ for (;;) {
154
+ var posWithinLine = pos - start;
155
+
156
+ var stateIndex;
157
+ var stackLength = patternStack.length;
158
+ if (stackLength === 0) {
159
+ stateIndex = 0;
160
+ }
161
+ else {
162
+ // get the next state
163
+ stateIndex = patternStack[stackLength - 1][2];
164
+ }
165
+
166
+ var state = language[stateIndex];
167
+ var numPatterns = state.length;
168
+ var mc = matchCache[stateIndex];
169
+ if (! mc) {
170
+ mc = matchCache[stateIndex] = [];
171
+ }
172
+ var bestMatch = null;
173
+ var bestPatternIndex = -1;
174
+ for (var i = 0; i < numPatterns; i++) {
175
+ var match;
176
+ if (i < mc.length && (mc[i] === null || posWithinLine <= mc[i].index)) {
177
+ match = mc[i];
178
+ }
179
+ else {
180
+ var regex = state[i][0];
181
+ regex.lastIndex = posWithinLine;
182
+ match = regex.exec(line);
183
+ mc[i] = match;
184
+ }
185
+ if (match !== null && (bestMatch === null || match.index < bestMatch.index)) {
186
+ bestMatch = match;
187
+ bestPatternIndex = i;
188
+ if (match.index === posWithinLine) {
189
+ break;
190
+ }
191
+ }
192
+ }
193
+
194
+ if (bestMatch === null) {
195
+ output(line.substring(posWithinLine), null);
196
+ break;
197
+ }
198
+ else {
199
+ // got a match
200
+ if (bestMatch.index > posWithinLine) {
201
+ output(line.substring(posWithinLine, bestMatch.index), null);
202
+ }
203
+
204
+ var pattern = state[bestPatternIndex];
205
+
206
+ var newStyle = pattern[1];
207
+ var matchedString;
208
+ if (newStyle instanceof Array) {
209
+ for (var subexpression = 0; subexpression < newStyle.length; subexpression++) {
210
+ matchedString = bestMatch[subexpression + 1];
211
+ output(matchedString, newStyle[subexpression]);
212
+ }
213
+ }
214
+ else {
215
+ matchedString = bestMatch[0];
216
+ output(matchedString, newStyle);
217
+ }
218
+
219
+ switch (pattern[2]) {
220
+ case -1:
221
+ // do nothing
222
+ break;
223
+ case -2:
224
+ // exit
225
+ patternStack.pop();
226
+ break;
227
+ case -3:
228
+ // exitall
229
+ patternStack.length = 0;
230
+ break;
231
+ default:
232
+ // this was the start of a delimited pattern or a state/environment
233
+ patternStack.push(pattern);
234
+ break;
235
+ }
236
+ }
237
+ }
238
+
239
+ // end of the line
240
+ if (currentStyle) {
241
+ tags[numTags++] = {pos: pos};
242
+ if (currentStyle === 'sh_url') {
243
+ sh_setHref(tags, numTags, inputString);
244
+ }
245
+ currentStyle = null;
246
+ }
247
+ pos = startOfNextLine;
248
+ }
249
+
250
+ return tags;
251
+ }
252
+
253
+ ////////////////////////////////////////////////////////////////////////////////
254
+ // DOM-dependent functions
255
+
256
+ function sh_getClasses(element) {
257
+ var result = [];
258
+ var htmlClass = element.className;
259
+ if (htmlClass && htmlClass.length > 0) {
260
+ var htmlClasses = htmlClass.split(' ');
261
+ for (var i = 0; i < htmlClasses.length; i++) {
262
+ if (htmlClasses[i].length > 0) {
263
+ result.push(htmlClasses[i]);
264
+ }
265
+ }
266
+ }
267
+ return result;
268
+ }
269
+
270
+ function sh_addClass(element, name) {
271
+ var htmlClasses = sh_getClasses(element);
272
+ for (var i = 0; i < htmlClasses.length; i++) {
273
+ if (name.toLowerCase() === htmlClasses[i].toLowerCase()) {
274
+ return;
275
+ }
276
+ }
277
+ htmlClasses.push(name);
278
+ element.className = htmlClasses.join(' ');
279
+ }
280
+
281
+ /**
282
+ Extracts the tags from an HTML DOM NodeList.
283
+ @param nodeList a DOM NodeList
284
+ @param result an object with text, tags and pos properties
285
+ */
286
+ function sh_extractTagsFromNodeList(nodeList, result) {
287
+ var length = nodeList.length;
288
+ for (var i = 0; i < length; i++) {
289
+ var node = nodeList.item(i);
290
+ switch (node.nodeType) {
291
+ case 1:
292
+ if (node.nodeName.toLowerCase() === 'br') {
293
+ var terminator;
294
+ if (/MSIE/.test(navigator.userAgent)) {
295
+ terminator = '\r';
296
+ }
297
+ else {
298
+ terminator = '\n';
299
+ }
300
+ result.text.push(terminator);
301
+ result.pos++;
302
+ }
303
+ else {
304
+ result.tags.push({node: node.cloneNode(false), pos: result.pos});
305
+ sh_extractTagsFromNodeList(node.childNodes, result);
306
+ result.tags.push({pos: result.pos});
307
+ }
308
+ break;
309
+ case 3:
310
+ case 4:
311
+ result.text.push(node.data);
312
+ result.pos += node.length;
313
+ break;
314
+ }
315
+ }
316
+ }
317
+
318
+ /**
319
+ Extracts the tags from the text of an HTML element. The extracted tags will be
320
+ returned as an array of tag objects. See sh_highlightString for the format of
321
+ the tag objects.
322
+ @param element a DOM element
323
+ @param tags an empty array; the extracted tag objects will be returned in it
324
+ @return the text of the element
325
+ @see sh_highlightString
326
+ */
327
+ function sh_extractTags(element, tags) {
328
+ var result = {};
329
+ result.text = [];
330
+ result.tags = tags;
331
+ result.pos = 0;
332
+ sh_extractTagsFromNodeList(element.childNodes, result);
333
+ return result.text.join('');
334
+ }
335
+
336
+ /**
337
+ Merges the original tags from an element with the tags produced by highlighting.
338
+ @param originalTags an array containing the original tags
339
+ @param highlightTags an array containing the highlighting tags - these must not overlap
340
+ @result an array containing the merged tags
341
+ */
342
+ function sh_mergeTags(originalTags, highlightTags) {
343
+ var numOriginalTags = originalTags.length;
344
+ if (numOriginalTags === 0) {
345
+ return highlightTags;
346
+ }
347
+
348
+ var numHighlightTags = highlightTags.length;
349
+ if (numHighlightTags === 0) {
350
+ return originalTags;
351
+ }
352
+
353
+ var result = [];
354
+ var originalIndex = 0;
355
+ var highlightIndex = 0;
356
+
357
+ while (originalIndex < numOriginalTags && highlightIndex < numHighlightTags) {
358
+ var originalTag = originalTags[originalIndex];
359
+ var highlightTag = highlightTags[highlightIndex];
360
+
361
+ if (originalTag.pos <= highlightTag.pos) {
362
+ result.push(originalTag);
363
+ originalIndex++;
364
+ }
365
+ else {
366
+ result.push(highlightTag);
367
+ if (highlightTags[highlightIndex + 1].pos <= originalTag.pos) {
368
+ highlightIndex++;
369
+ result.push(highlightTags[highlightIndex]);
370
+ highlightIndex++;
371
+ }
372
+ else {
373
+ // new end tag
374
+ result.push({pos: originalTag.pos});
375
+
376
+ // new start tag
377
+ highlightTags[highlightIndex] = {node: highlightTag.node.cloneNode(false), pos: originalTag.pos};
378
+ }
379
+ }
380
+ }
381
+
382
+ while (originalIndex < numOriginalTags) {
383
+ result.push(originalTags[originalIndex]);
384
+ originalIndex++;
385
+ }
386
+
387
+ while (highlightIndex < numHighlightTags) {
388
+ result.push(highlightTags[highlightIndex]);
389
+ highlightIndex++;
390
+ }
391
+
392
+ return result;
393
+ }
394
+
395
+ /**
396
+ Inserts tags into text.
397
+ @param tags an array of tag objects
398
+ @param text a string representing the text
399
+ @return a DOM DocumentFragment representing the resulting HTML
400
+ */
401
+ function sh_insertTags(tags, text) {
402
+ var doc = document;
403
+
404
+ var result = document.createDocumentFragment();
405
+ var tagIndex = 0;
406
+ var numTags = tags.length;
407
+ var textPos = 0;
408
+ var textLength = text.length;
409
+ var currentNode = result;
410
+
411
+ // output one tag or text node every iteration
412
+ while (textPos < textLength || tagIndex < numTags) {
413
+ var tag;
414
+ var tagPos;
415
+ if (tagIndex < numTags) {
416
+ tag = tags[tagIndex];
417
+ tagPos = tag.pos;
418
+ }
419
+ else {
420
+ tagPos = textLength;
421
+ }
422
+
423
+ if (tagPos <= textPos) {
424
+ // output the tag
425
+ if (tag.node) {
426
+ // start tag
427
+ var newNode = tag.node;
428
+ currentNode.appendChild(newNode);
429
+ currentNode = newNode;
430
+ }
431
+ else {
432
+ // end tag
433
+ currentNode = currentNode.parentNode;
434
+ }
435
+ tagIndex++;
436
+ }
437
+ else {
438
+ // output text
439
+ currentNode.appendChild(doc.createTextNode(text.substring(textPos, tagPos)));
440
+ textPos = tagPos;
441
+ }
442
+ }
443
+
444
+ return result;
445
+ }
446
+
447
+ /**
448
+ Highlights an element containing source code. Upon completion of this function,
449
+ the element will have been placed in the "sh_sourceCode" class.
450
+ @param element a DOM <pre> element containing the source code to be highlighted
451
+ @param language a language definition object
452
+ */
453
+ function sh_highlightElement(element, language) {
454
+ sh_addClass(element, 'sh_sourceCode');
455
+ var originalTags = [];
456
+ var inputString = sh_extractTags(element, originalTags);
457
+ var highlightTags = sh_highlightString(inputString, language);
458
+ var tags = sh_mergeTags(originalTags, highlightTags);
459
+ var documentFragment = sh_insertTags(tags, inputString);
460
+ while (element.hasChildNodes()) {
461
+ element.removeChild(element.firstChild);
462
+ }
463
+ element.appendChild(documentFragment);
464
+ }
465
+
466
+ function sh_getXMLHttpRequest() {
467
+ if (window.ActiveXObject) {
468
+ return new ActiveXObject('Msxml2.XMLHTTP');
469
+ }
470
+ else if (window.XMLHttpRequest) {
471
+ return new XMLHttpRequest();
472
+ }
473
+ throw 'No XMLHttpRequest implementation available';
474
+ }
475
+
476
+ function sh_load(language, element, prefix, suffix) {
477
+ if (language in sh_requests) {
478
+ sh_requests[language].push(element);
479
+ return;
480
+ }
481
+ sh_requests[language] = [element];
482
+ var request = sh_getXMLHttpRequest();
483
+ var url = prefix + 'sh_' + language + suffix;
484
+ request.open('GET', url, true);
485
+ request.onreadystatechange = function () {
486
+ if (request.readyState === 4) {
487
+ try {
488
+ if (! request.status || request.status === 200) {
489
+ eval(request.responseText);
490
+ var elements = sh_requests[language];
491
+ for (var i = 0; i < elements.length; i++) {
492
+ sh_highlightElement(elements[i], sh_languages[language]);
493
+ }
494
+ }
495
+ else {
496
+ throw 'HTTP error: status ' + request.status;
497
+ }
498
+ }
499
+ finally {
500
+ request = null;
501
+ }
502
+ }
503
+ };
504
+ request.send(null);
505
+ }
506
+
507
+ /**
508
+ Highlights all elements containing source code on the current page. Elements
509
+ containing source code must be "pre" elements with a "class" attribute of
510
+ "sh_LANGUAGE", where LANGUAGE is a valid language identifier; e.g., "sh_java"
511
+ identifies the element as containing "java" language source code.
512
+ */
513
+ function sh_highlightDocument(prefix, suffix) {
514
+ var nodeList = document.getElementsByTagName('pre');
515
+ for (var i = 0; i < nodeList.length; i++) {
516
+ var element = nodeList.item(i);
517
+ var htmlClasses = sh_getClasses(element);
518
+ if (_.include(htmlClasses, 'sh_sourceCode')) {
519
+ continue;
520
+ }
521
+ for (var j = 0; j < htmlClasses.length; j++) {
522
+ var htmlClass = htmlClasses[j].toLowerCase();
523
+ if (htmlClass === 'sh_sourcecode') {
524
+ continue;
525
+ }
526
+ if (htmlClass.substr(0, 3) === 'sh_') {
527
+ var language = htmlClass.substring(3);
528
+ if (language in sh_languages) {
529
+ sh_highlightElement(element, sh_languages[language]);
530
+ }
531
+ else if (typeof(prefix) === 'string' && typeof(suffix) === 'string') {
532
+ sh_load(language, element, prefix, suffix);
533
+ }
534
+ else {
535
+ throw 'Found <pre> element with class="' + htmlClass + '", but no such language exists';
536
+ }
537
+ break;
538
+ }
539
+ }
540
+ }
541
+ }
542
+
543
+ if(!this.sh_languages){this.sh_languages={}}sh_languages.sql=[[[/\b(?:VARCHAR|TINYINT|TEXT|DATE|SMALLINT|MEDIUMINT|INT|BIGINT|FLOAT|DOUBLE|DECIMAL|DATETIME|TIMESTAMP|TIME|YEAR|UNSIGNED|CHAR|TINYBLOB|TINYTEXT|BLOB|MEDIUMBLOB|MEDIUMTEXT|LONGBLOB|LONGTEXT|ENUM|BOOL|BINARY|VARBINARY)\b/gi,"sh_type",-1],[/\b(?:ALL|ASC|AS|ALTER|AND|ADD|AUTO_INCREMENT|BETWEEN|BINARY|BOTH|BY|BOOLEAN|CHANGE|CHECK|COLUMNS|COLUMN|CROSS|CREATE|DATABASES|DATABASE|DATA|DELAYED|DESCRIBE|DESC|DISTINCT|DELETE|DROP|DEFAULT|ENCLOSED|ESCAPED|EXISTS|EXPLAIN|FIELDS|FIELD|FLUSH|FOR|FOREIGN|FUNCTION|FROM|GROUP|GRANT|HAVING|IGNORE|INDEX|INFILE|INSERT|INNER|INTO|IDENTIFIED|IN|IS|IF|JOIN|KEYS|KILL|KEY|LEADING|LIKE|LIMIT|LINES|LOAD|LOCAL|LOCK|LOW_PRIORITY|LEFT|LANGUAGE|MODIFY|NATURAL|NOT|NULL|NEXTVAL|OPTIMIZE|OPTION|OPTIONALLY|ORDER|OUTFILE|OR|OUTER|ON|PROCEDURE|PROCEDURAL|PRIMARY|READ|REFERENCES|REGEXP|RENAME|REPLACE|RETURN|REVOKE|RLIKE|RIGHT|SHOW|SONAME|STATUS|STRAIGHT_JOIN|SELECT|SETVAL|SET|TABLES|TERMINATED|TO|TRAILING|TRUNCATE|TABLE|TEMPORARY|TRIGGER|TRUSTED|UNIQUE|UNLOCK|USE|USING|UPDATE|VALUES|VARIABLES|VIEW|WITH|WRITE|WHERE|ZEROFILL|TYPE|XOR)\b/gi,"sh_keyword",-1],[/"/g,"sh_string",1],[/'/g,"sh_string",2],[/`/g,"sh_string",3],[/#/g,"sh_comment",4],[/\/\/\//g,"sh_comment",5],[/\/\//g,"sh_comment",4],[/\/\*\*/g,"sh_comment",11],[/\/\*/g,"sh_comment",12],[/--/g,"sh_comment",4],[/~|!|%|\^|\*|\(|\)|-|\+|=|\[|\]|\\|:|;|,|\.|\/|\?|&|<|>|\|/g,"sh_symbol",-1],[/\b[+-]?(?:(?:0x[A-Fa-f0-9]+)|(?:(?:[\d]*\.)?[\d]+(?:[eE][+-]?[\d]+)?))u?(?:(?:int(?:8|16|32|64))|L)?\b/g,"sh_number",-1]],[[/"/g,"sh_string",-2],[/\\./g,"sh_specialchar",-1]],[[/'/g,"sh_string",-2],[/\\./g,"sh_specialchar",-1]],[[/`/g,"sh_string",-2],[/\\./g,"sh_specialchar",-1]],[[/$/g,null,-2]],[[/$/g,null,-2],[/(?:<?)[A-Za-z0-9_\.\/\-_~]+@[A-Za-z0-9_\.\/\-_~]+(?:>?)|(?:<?)[A-Za-z0-9_]+:\/\/[A-Za-z0-9_\.\/\-_~]+(?:>?)/g,"sh_url",-1],[/<\?xml/g,"sh_preproc",6,1],[/<!DOCTYPE/g,"sh_preproc",8,1],[/<!--/g,"sh_comment",9],[/<(?:\/)?[A-Za-z](?:[A-Za-z0-9_:.-]*)(?:\/)?>/g,"sh_keyword",-1],[/<(?:\/)?[A-Za-z](?:[A-Za-z0-9_:.-]*)/g,"sh_keyword",10,1],[/&(?:[A-Za-z0-9]+);/g,"sh_preproc",-1],[/<(?:\/)?[A-Za-z][A-Za-z0-9]*(?:\/)?>/g,"sh_keyword",-1],[/<(?:\/)?[A-Za-z][A-Za-z0-9]*/g,"sh_keyword",10,1],[/@[A-Za-z]+/g,"sh_type",-1],[/(?:TODO|FIXME|BUG)(?:[:]?)/g,"sh_todo",-1]],[[/\?>/g,"sh_preproc",-2],[/([^=" \t>]+)([ \t]*)(=?)/g,["sh_type","sh_normal","sh_symbol"],-1],[/"/g,"sh_string",7]],[[/\\(?:\\|")/g,null,-1],[/"/g,"sh_string",-2]],[[/>/g,"sh_preproc",-2],[/([^=" \t>]+)([ \t]*)(=?)/g,["sh_type","sh_normal","sh_symbol"],-1],[/"/g,"sh_string",7]],[[/-->/g,"sh_comment",-2],[/<!--/g,"sh_comment",9]],[[/(?:\/)?>/g,"sh_keyword",-2],[/([^=" \t>]+)([ \t]*)(=?)/g,["sh_type","sh_normal","sh_symbol"],-1],[/"/g,"sh_string",7]],[[/\*\//g,"sh_comment",-2],[/(?:<?)[A-Za-z0-9_\.\/\-_~]+@[A-Za-z0-9_\.\/\-_~]+(?:>?)|(?:<?)[A-Za-z0-9_]+:\/\/[A-Za-z0-9_\.\/\-_~]+(?:>?)/g,"sh_url",-1],[/<\?xml/g,"sh_preproc",6,1],[/<!DOCTYPE/g,"sh_preproc",8,1],[/<!--/g,"sh_comment",9],[/<(?:\/)?[A-Za-z](?:[A-Za-z0-9_:.-]*)(?:\/)?>/g,"sh_keyword",-1],[/<(?:\/)?[A-Za-z](?:[A-Za-z0-9_:.-]*)/g,"sh_keyword",10,1],[/&(?:[A-Za-z0-9]+);/g,"sh_preproc",-1],[/<(?:\/)?[A-Za-z][A-Za-z0-9]*(?:\/)?>/g,"sh_keyword",-1],[/<(?:\/)?[A-Za-z][A-Za-z0-9]*/g,"sh_keyword",10,1],[/@[A-Za-z]+/g,"sh_type",-1],[/(?:TODO|FIXME|BUG)(?:[:]?)/g,"sh_todo",-1]],[[/\*\//g,"sh_comment",-2],[/(?:<?)[A-Za-z0-9_\.\/\-_~]+@[A-Za-z0-9_\.\/\-_~]+(?:>?)|(?:<?)[A-Za-z0-9_]+:\/\/[A-Za-z0-9_\.\/\-_~]+(?:>?)/g,"sh_url",-1],[/(?:TODO|FIXME|BUG)(?:[:]?)/g,"sh_todo",-1]]];