rubyception 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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]]];