Răsfoiți Sursa

Merge pull request #1647 from sharelatex/as-upgrade-ace-1.4.3

Upgrade Ace to v1.4.3

GitOrigin-RevId: 810350080a6b89fd9817ebcacde7e9817097d99a
Paulo Jorge Reis 7 ani în urmă
părinte
comite
d613d7e1a2
100 a modificat fișierele cu 54223 adăugiri și 1 ștergeri
  1. 1 1
      services/web/app/coffee/infrastructure/PackageVersions.coffee
  2. 6925 0
      services/web/public/js/ace-1.4.3/ace.js
  3. 324 0
      services/web/public/js/ace-1.4.3/ext-beautify.js
  4. 278 0
      services/web/public/js/ace-1.4.3/ext-elastic_tabstops_lite.js
  5. 1227 0
      services/web/public/js/ace-1.4.3/ext-emmet.js
  6. 10 0
      services/web/public/js/ace-1.4.3/ext-error_marker.js
  7. 189 0
      services/web/public/js/ace-1.4.3/ext-keybinding_menu.js
  8. 1994 0
      services/web/public/js/ace-1.4.3/ext-language_tools.js
  9. 65 0
      services/web/public/js/ace-1.4.3/ext-linking.js
  10. 234 0
      services/web/public/js/ace-1.4.3/ext-modelist.js
  11. 756 0
      services/web/public/js/ace-1.4.3/ext-options.js
  12. 125 0
      services/web/public/js/ace-1.4.3/ext-rtl.js
  13. 514 0
      services/web/public/js/ace-1.4.3/ext-searchbox.js
  14. 777 0
      services/web/public/js/ace-1.4.3/ext-settings_menu.js
  15. 75 0
      services/web/public/js/ace-1.4.3/ext-spellcheck.js
  16. 208 0
      services/web/public/js/ace-1.4.3/ext-split.js
  17. 230 0
      services/web/public/js/ace-1.4.3/ext-static_highlight.js
  18. 57 0
      services/web/public/js/ace-1.4.3/ext-statusbar.js
  19. 564 0
      services/web/public/js/ace-1.4.3/ext-textarea.js
  20. 66 0
      services/web/public/js/ace-1.4.3/ext-themelist.js
  21. 210 0
      services/web/public/js/ace-1.4.3/ext-whitespace.js
  22. 1170 0
      services/web/public/js/ace-1.4.3/keybinding-emacs.js
  23. 426 0
      services/web/public/js/ace-1.4.3/keybinding-sublime.js
  24. 5666 0
      services/web/public/js/ace-1.4.3/keybinding-vim.js
  25. 222 0
      services/web/public/js/ace-1.4.3/mode-abap.js
  26. 269 0
      services/web/public/js/ace-1.4.3/mode-abc.js
  27. 12 0
      services/web/public/js/ace-1.4.3/mode-actionscript.js
  28. 138 0
      services/web/public/js/ace-1.4.3/mode-ada.js
  29. 364 0
      services/web/public/js/ace-1.4.3/mode-apache_conf.js
  30. 458 0
      services/web/public/js/ace-1.4.3/mode-apex.js
  31. 279 0
      services/web/public/js/ace-1.4.3/mode-applescript.js
  32. 350 0
      services/web/public/js/ace-1.4.3/mode-asciidoc.js
  33. 422 0
      services/web/public/js/ace-1.4.3/mode-asl.js
  34. 10 0
      services/web/public/js/ace-1.4.3/mode-assembly_x86.js
  35. 8 0
      services/web/public/js/ace-1.4.3/mode-autohotkey.js
  36. 231 0
      services/web/public/js/ace-1.4.3/mode-batchfile.js
  37. 335 0
      services/web/public/js/ace-1.4.3/mode-bro.js
  38. 294 0
      services/web/public/js/ace-1.4.3/mode-c9search.js
  39. 56 0
      services/web/public/js/ace-1.4.3/mode-c_cpp.js
  40. 211 0
      services/web/public/js/ace-1.4.3/mode-cirru.js
  41. 315 0
      services/web/public/js/ace-1.4.3/mode-clojure.js
  42. 102 0
      services/web/public/js/ace-1.4.3/mode-cobol.js
  43. 400 0
      services/web/public/js/ace-1.4.3/mode-coffee.js
  44. 797 0
      services/web/public/js/ace-1.4.3/mode-coldfusion.js
  45. 503 0
      services/web/public/js/ace-1.4.3/mode-csharp.js
  46. 2902 0
      services/web/public/js/ace-1.4.3/mode-csound_document.js
  47. 2925 0
      services/web/public/js/ace-1.4.3/mode-csound_orchestra.js
  48. 454 0
      services/web/public/js/ace-1.4.3/mode-csound_score.js
  49. 60 0
      services/web/public/js/ace-1.4.3/mode-csp.js
  50. 6 0
      services/web/public/js/ace-1.4.3/mode-css.js
  51. 797 0
      services/web/public/js/ace-1.4.3/mode-curly.js
  52. 521 0
      services/web/public/js/ace-1.4.3/mode-d.js
  53. 56 0
      services/web/public/js/ace-1.4.3/mode-dart.js
  54. 147 0
      services/web/public/js/ace-1.4.3/mode-diff.js
  55. 797 0
      services/web/public/js/ace-1.4.3/mode-django.js
  56. 500 0
      services/web/public/js/ace-1.4.3/mode-dockerfile.js
  57. 418 0
      services/web/public/js/ace-1.4.3/mode-dot.js
  58. 498 0
      services/web/public/js/ace-1.4.3/mode-drools.js
  59. 166 0
      services/web/public/js/ace-1.4.3/mode-edifact.js
  60. 136 0
      services/web/public/js/ace-1.4.3/mode-eiffel.js
  61. 6 0
      services/web/public/js/ace-1.4.3/mode-ejs.js
  62. 502 0
      services/web/public/js/ace-1.4.3/mode-elixir.js
  63. 307 0
      services/web/public/js/ace-1.4.3/mode-elm.js
  64. 1010 0
      services/web/public/js/ace-1.4.3/mode-erlang.js
  65. 298 0
      services/web/public/js/ace-1.4.3/mode-forth.js
  66. 431 0
      services/web/public/js/ace-1.4.3/mode-fortran.js
  67. 317 0
      services/web/public/js/ace-1.4.3/mode-fsharp.js
  68. 259 0
      services/web/public/js/ace-1.4.3/mode-fsl.js
  69. 6 0
      services/web/public/js/ace-1.4.3/mode-ftl.js
  70. 94 0
      services/web/public/js/ace-1.4.3/mode-gcode.js
  71. 171 0
      services/web/public/js/ace-1.4.3/mode-gherkin.js
  72. 60 0
      services/web/public/js/ace-1.4.3/mode-gitignore.js
  73. 56 0
      services/web/public/js/ace-1.4.3/mode-glsl.js
  74. 931 0
      services/web/public/js/ace-1.4.3/mode-gobstones.js
  75. 414 0
      services/web/public/js/ace-1.4.3/mode-golang.js
  76. 214 0
      services/web/public/js/ace-1.4.3/mode-graphqlschema.js
  77. 989 0
      services/web/public/js/ace-1.4.3/mode-groovy.js
  78. 6 0
      services/web/public/js/ace-1.4.3/mode-haml.js
  79. 797 0
      services/web/public/js/ace-1.4.3/mode-handlebars.js
  80. 380 0
      services/web/public/js/ace-1.4.3/mode-haskell.js
  81. 142 0
      services/web/public/js/ace-1.4.3/mode-haskell_cabal.js
  82. 387 0
      services/web/public/js/ace-1.4.3/mode-haxe.js
  83. 354 0
      services/web/public/js/ace-1.4.3/mode-hjson.js
  84. 797 0
      services/web/public/js/ace-1.4.3/mode-html.js
  85. 6 0
      services/web/public/js/ace-1.4.3/mode-html_elixir.js
  86. 6 0
      services/web/public/js/ace-1.4.3/mode-html_ruby.js
  87. 163 0
      services/web/public/js/ace-1.4.3/mode-ini.js
  88. 254 0
      services/web/public/js/ace-1.4.3/mode-io.js
  89. 347 0
      services/web/public/js/ace-1.4.3/mode-jack.js
  90. 6 0
      services/web/public/js/ace-1.4.3/mode-jade.js
  91. 1037 0
      services/web/public/js/ace-1.4.3/mode-java.js
  92. 798 0
      services/web/public/js/ace-1.4.3/mode-javascript.js
  93. 327 0
      services/web/public/js/ace-1.4.3/mode-json.js
  94. 1545 0
      services/web/public/js/ace-1.4.3/mode-jsoniq.js
  95. 6 0
      services/web/public/js/ace-1.4.3/mode-jsp.js
  96. 326 0
      services/web/public/js/ace-1.4.3/mode-jssm.js
  97. 412 0
      services/web/public/js/ace-1.4.3/mode-jsx.js
  98. 304 0
      services/web/public/js/ace-1.4.3/mode-julia.js
  99. 796 0
      services/web/public/js/ace-1.4.3/mode-kotlin.js
  100. 712 0
      services/web/public/js/ace-1.4.3/mode-latex.js

+ 1 - 1
services/web/app/coffee/infrastructure/PackageVersions.coffee

@@ -1,7 +1,7 @@
 version = {
 	"pdfjs": "2.0.943"
 	"moment": "2.9.0"
-	"ace": "1.2.9" # Upgrade instructions: https://github.com/overleaf/write_latex/wiki/Upgrading-Ace
+	"ace": "1.4.3" # Upgrade instructions: https://github.com/overleaf/write_latex/wiki/Upgrading-Ace
 	"fineuploader": "5.15.4"
 }
 

Fișier diff suprimat deoarece este prea mare
+ 6925 - 0
services/web/public/js/ace-1.4.3/ace.js


+ 324 - 0
services/web/public/js/ace-1.4.3/ext-beautify.js

@@ -0,0 +1,324 @@
+ace.define("ace/ext/beautify",[], function(require, exports, module) {
+"use strict";
+var TokenIterator = require("../token_iterator").TokenIterator;
+
+function is(token, type) {
+    return token.type.lastIndexOf(type + ".xml") > -1;
+}
+exports.singletonTags = ["area", "base", "br", "col", "command", "embed", "hr", "html", "img", "input", "keygen", "link", "meta", "param", "source", "track", "wbr"];
+exports.blockTags = ["article", "aside", "blockquote", "body", "div", "dl", "fieldset", "footer", "form", "head", "header", "html", "nav", "ol", "p", "script", "section", "style", "table", "tbody", "tfoot", "thead", "ul"];
+
+exports.beautify = function(session) {
+    var iterator = new TokenIterator(session, 0, 0);
+    var token = iterator.getCurrentToken();
+    var tabString = session.getTabString();
+    var singletonTags = exports.singletonTags;
+    var blockTags = exports.blockTags;
+    var nextToken;
+    var breakBefore = false;
+    var spaceBefore = false;
+    var spaceAfter = false;
+    var code = "";
+    var value = "";
+    var tagName = "";
+    var depth = 0;
+    var lastDepth = 0;
+    var lastIndent = 0;
+    var indent = 0;
+    var unindent = 0;
+    var roundDepth = 0;
+    var curlyDepth = 0;
+    var row;
+    var curRow = 0;
+    var rowsToAdd = 0;
+    var rowTokens = [];
+    var abort = false;
+    var i;
+    var indentNextLine = false;
+    var inTag = false;
+    var inCSS = false;
+    var inBlock = false;
+    var levels = {0: 0};
+    var parents = [];
+
+    var trimNext = function() {
+        if (nextToken && nextToken.value && nextToken.type !== 'string.regexp')
+            nextToken.value = nextToken.value.trim();
+    };
+
+    var trimLine = function() {
+        code = code.replace(/ +$/, "");
+    };
+
+    var trimCode = function() {
+        code = code.trimRight();
+        breakBefore = false;
+    };
+
+    while (token !== null) {
+        curRow = iterator.getCurrentTokenRow();
+        rowTokens = iterator.$rowTokens;
+        nextToken = iterator.stepForward();
+
+        if (typeof token !== "undefined") {
+            value = token.value;
+            unindent = 0;
+            inCSS = (tagName === "style" || session.$modeId === "ace/mode/css");
+            if (is(token, "tag-open")) {
+                inTag = true;
+                if (nextToken)
+                    inBlock = (blockTags.indexOf(nextToken.value) !== -1);
+                if (value === "</") {
+                    if (inBlock && !breakBefore && rowsToAdd < 1)
+                        rowsToAdd++;
+
+                    if (inCSS)
+                        rowsToAdd = 1;
+
+                    unindent = 1;
+                    inBlock = false;
+                }
+            } else if (is(token, "tag-close")) {
+                inTag = false;
+            } else if (is(token, "comment.start")) {
+                inBlock = true;
+            } else if (is(token, "comment.end")) {
+                inBlock = false;
+            }
+            if (!inTag && !rowsToAdd && token.type === "paren.rparen" && token.value.substr(0, 1) === "}") {
+                rowsToAdd++;
+            }
+            if (curRow !== row) {
+                rowsToAdd = curRow;
+
+                if (row)
+                    rowsToAdd -= row;
+            }
+
+            if (rowsToAdd) {
+                trimCode();
+                for (; rowsToAdd > 0; rowsToAdd--)
+                    code += "\n";
+
+                breakBefore = true;
+                if (!is(token, "comment") && !token.type.match(/^(comment|string)$/))
+                   value = value.trimLeft();
+            }
+
+            if (value) {
+                if (token.type === "keyword" && value.match(/^(if|else|elseif|for|foreach|while|switch)$/)) {
+                    parents[depth] = value;
+
+                    trimNext();
+                    spaceAfter = true;
+                    if (value.match(/^(else|elseif)$/)) {
+                        if (code.match(/\}[\s]*$/)) {
+                            trimCode();
+                            spaceBefore = true;
+                        }
+                    }
+                } else if (token.type === "paren.lparen") {
+                    trimNext();
+                    if (value.substr(-1) === "{") {
+                        spaceAfter = true;
+                        indentNextLine = false;
+
+                        if(!inTag)
+                            rowsToAdd = 1;
+                    }
+                    if (value.substr(0, 1) === "{") {
+                        spaceBefore = true;
+                        if (code.substr(-1) !== '[' && code.trimRight().substr(-1) === '[') {
+                            trimCode();
+                            spaceBefore = false;
+                        } else if (code.trimRight().substr(-1) === ')') {
+                            trimCode();
+                        } else {
+                            trimLine();
+                        }
+                    }
+                } else if (token.type === "paren.rparen") {
+                    unindent = 1;
+                    if (value.substr(0, 1) === "}") {
+                        if (parents[depth-1] === 'case')
+                            unindent++;
+
+                        if (code.trimRight().substr(-1) === '{') {
+                            trimCode();
+                        } else {
+                            spaceBefore = true;
+
+                            if (inCSS)
+                                rowsToAdd+=2;
+                        }
+                    }
+                    if (value.substr(0, 1) === "]") {
+                        if (code.substr(-1) !== '}' && code.trimRight().substr(-1) === '}') {
+                            spaceBefore = false;
+                            indent++;
+                            trimCode();
+                        }
+                    }
+                    if (value.substr(0, 1) === ")") {
+                        if (code.substr(-1) !== '(' && code.trimRight().substr(-1) === '(') {
+                            spaceBefore = false;
+                            indent++;
+                            trimCode();
+                        }
+                    }
+
+                    trimLine();
+                } else if ((token.type === "keyword.operator" || token.type === "keyword") && value.match(/^(=|==|===|!=|!==|&&|\|\||and|or|xor|\+=|.=|>|>=|<|<=|=>)$/)) {
+                    trimCode();
+                    trimNext();
+                    spaceBefore = true;
+                    spaceAfter = true;
+                } else if (token.type === "punctuation.operator" && value === ';') {
+                    trimCode();
+                    trimNext();
+                    spaceAfter = true;
+
+                    if (inCSS)
+                        rowsToAdd++;
+                } else if (token.type === "punctuation.operator" && value.match(/^(:|,)$/)) {
+                    trimCode();
+                    trimNext();
+                    if (value.match(/^(,)$/) && curlyDepth>0 && roundDepth===0) {
+                        rowsToAdd++;
+                    } else {
+                        spaceAfter = true;
+                        breakBefore = false;
+                    }
+                } else if (token.type === "support.php_tag" && value === "?>" && !breakBefore) {
+                    trimCode();
+                    spaceBefore = true;
+                } else if (is(token, "attribute-name") && code.substr(-1).match(/^\s$/)) {
+                    spaceBefore = true;
+                } else if (is(token, "attribute-equals")) {
+                    trimLine();
+                    trimNext();
+                } else if (is(token, "tag-close")) {
+                    trimLine();
+                    if(value === "/>")
+                        spaceBefore = true;
+                }
+                if (breakBefore && !(token.type.match(/^(comment)$/) && !value.substr(0, 1).match(/^[/#]$/)) && !(token.type.match(/^(string)$/) && !value.substr(0, 1).match(/^['"]$/))) {
+
+                    indent = lastIndent;
+
+                    if(depth > lastDepth) {
+                        indent++;
+
+                        for (i=depth; i > lastDepth; i--)
+                            levels[i] = indent;
+                    } else if(depth < lastDepth)
+                        indent = levels[depth];
+
+                    lastDepth = depth;
+                    lastIndent = indent;
+
+                    if(unindent)
+                        indent -= unindent;
+
+                    if (indentNextLine && !roundDepth) {
+                        indent++;
+                        indentNextLine = false;
+                    }
+
+                    for (i = 0; i < indent; i++)
+                        code += tabString;
+                }
+
+
+                if (token.type === "keyword" && value.match(/^(case|default)$/)) {
+                    parents[depth] = value;
+                    depth++;
+                }
+
+
+                if (token.type === "keyword" && value.match(/^(break)$/)) {
+                    if(parents[depth-1] && parents[depth-1].match(/^(case|default)$/)) {
+                        depth--;
+                    }
+                }
+                if (token.type === "paren.lparen") {
+                    roundDepth += (value.match(/\(/g) || []).length;
+                    curlyDepth += (value.match(/\{/g) || []).length;
+                    depth += value.length;
+                }
+
+                if (token.type === "keyword" && value.match(/^(if|else|elseif|for|while)$/)) {
+                    indentNextLine = true;
+                    roundDepth = 0;
+                } else if (!roundDepth && value.trim() && token.type !== "comment")
+                    indentNextLine = false;
+
+                if (token.type === "paren.rparen") {
+                    roundDepth -= (value.match(/\)/g) || []).length;
+                    curlyDepth -= (value.match(/\}/g) || []).length;
+
+                    for (i = 0; i < value.length; i++) {
+                        depth--;
+                        if(value.substr(i, 1)==='}' && parents[depth]==='case') {
+                            depth--;
+                        }
+                    }
+                }
+                if (spaceBefore && !breakBefore) {
+                    trimLine();
+                    if (code.substr(-1) !== "\n")
+                        code += " ";
+                }
+
+                code += value;
+
+                if (spaceAfter)
+                    code += " ";
+
+                breakBefore = false;
+                spaceBefore = false;
+                spaceAfter = false;
+                if ((is(token, "tag-close") && (inBlock || blockTags.indexOf(tagName) !== -1)) || (is(token, "doctype") && value === ">")) {
+                    if (inBlock && nextToken && nextToken.value === "</")
+                        rowsToAdd = -1;
+                    else
+                        rowsToAdd = 1;
+                }
+                if (is(token, "tag-open") && value === "</") {
+                    depth--;
+                } else if (is(token, "tag-open") && value === "<" && singletonTags.indexOf(nextToken.value) === -1) {
+                    depth++;
+                } else if (is(token, "tag-name")) {
+                    tagName = value;
+                } else if (is(token, "tag-close") && value === "/>" && singletonTags.indexOf(tagName) === -1){
+                    depth--;
+                }
+
+                row = curRow;
+            }
+        }
+
+        token = nextToken;
+    }
+
+    code = code.trim();
+    session.doc.setValue(code);
+};
+
+exports.commands = [{
+    name: "beautify",
+    exec: function(editor) {
+        exports.beautify(editor.session);
+    },
+    bindKey: "Ctrl-Shift-B"
+}];
+
+});
+                (function() {
+                    ace.require(["ace/ext/beautify"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 278 - 0
services/web/public/js/ace-1.4.3/ext-elastic_tabstops_lite.js

@@ -0,0 +1,278 @@
+ace.define("ace/ext/elastic_tabstops_lite",[], function(require, exports, module) {
+"use strict";
+
+var ElasticTabstopsLite = function(editor) {
+    this.$editor = editor;
+    var self = this;
+    var changedRows = [];
+    var recordChanges = false;
+    this.onAfterExec = function() {
+        recordChanges = false;
+        self.processRows(changedRows);
+        changedRows = [];
+    };
+    this.onExec = function() {
+        recordChanges = true;
+    };
+    this.onChange = function(delta) {
+        if (recordChanges) {
+            if (changedRows.indexOf(delta.start.row) == -1)
+                changedRows.push(delta.start.row);
+            if (delta.end.row != delta.start.row)
+                changedRows.push(delta.end.row);
+        }
+    };
+};
+
+(function() {
+    this.processRows = function(rows) {
+        this.$inChange = true;
+        var checkedRows = [];
+
+        for (var r = 0, rowCount = rows.length; r < rowCount; r++) {
+            var row = rows[r];
+
+            if (checkedRows.indexOf(row) > -1)
+                continue;
+
+            var cellWidthObj = this.$findCellWidthsForBlock(row);
+            var cellWidths = this.$setBlockCellWidthsToMax(cellWidthObj.cellWidths);
+            var rowIndex = cellWidthObj.firstRow;
+
+            for (var w = 0, l = cellWidths.length; w < l; w++) {
+                var widths = cellWidths[w];
+                checkedRows.push(rowIndex);
+                this.$adjustRow(rowIndex, widths);
+                rowIndex++;
+            }
+        }
+        this.$inChange = false;
+    };
+
+    this.$findCellWidthsForBlock = function(row) {
+        var cellWidths = [], widths;
+        var rowIter = row;
+        while (rowIter >= 0) {
+            widths = this.$cellWidthsForRow(rowIter);
+            if (widths.length == 0)
+                break;
+
+            cellWidths.unshift(widths);
+            rowIter--;
+        }
+        var firstRow = rowIter + 1;
+        rowIter = row;
+        var numRows = this.$editor.session.getLength();
+
+        while (rowIter < numRows - 1) {
+            rowIter++;
+
+            widths = this.$cellWidthsForRow(rowIter);
+            if (widths.length == 0)
+                break;
+
+            cellWidths.push(widths);
+        }
+
+        return { cellWidths: cellWidths, firstRow: firstRow };
+    };
+
+    this.$cellWidthsForRow = function(row) {
+        var selectionColumns = this.$selectionColumnsForRow(row);
+
+        var tabs = [-1].concat(this.$tabsForRow(row));
+        var widths = tabs.map(function(el) { return 0; } ).slice(1);
+        var line = this.$editor.session.getLine(row);
+
+        for (var i = 0, len = tabs.length - 1; i < len; i++) {
+            var leftEdge = tabs[i]+1;
+            var rightEdge = tabs[i+1];
+
+            var rightmostSelection = this.$rightmostSelectionInCell(selectionColumns, rightEdge);
+            var cell = line.substring(leftEdge, rightEdge);
+            widths[i] = Math.max(cell.replace(/\s+$/g,'').length, rightmostSelection - leftEdge);
+        }
+
+        return widths;
+    };
+
+    this.$selectionColumnsForRow = function(row) {
+        var selections = [], cursor = this.$editor.getCursorPosition();
+        if (this.$editor.session.getSelection().isEmpty()) {
+            if (row == cursor.row)
+                selections.push(cursor.column);
+        }
+
+        return selections;
+    };
+
+    this.$setBlockCellWidthsToMax = function(cellWidths) {
+        var startingNewBlock = true, blockStartRow, blockEndRow, maxWidth;
+        var columnInfo = this.$izip_longest(cellWidths);
+
+        for (var c = 0, l = columnInfo.length; c < l; c++) {
+            var column = columnInfo[c];
+            if (!column.push) {
+                console.error(column);
+                continue;
+            }
+            column.push(NaN);
+
+            for (var r = 0, s = column.length; r < s; r++) {
+                var width = column[r];
+                if (startingNewBlock) {
+                    blockStartRow = r;
+                    maxWidth = 0;
+                    startingNewBlock = false;
+                }
+                if (isNaN(width)) {
+                    blockEndRow = r;
+
+                    for (var j = blockStartRow; j < blockEndRow; j++) {
+                        cellWidths[j][c] = maxWidth;
+                    }
+                    startingNewBlock = true;
+                }
+
+                maxWidth = Math.max(maxWidth, width);
+            }
+        }
+
+        return cellWidths;
+    };
+
+    this.$rightmostSelectionInCell = function(selectionColumns, cellRightEdge) {
+        var rightmost = 0;
+
+        if (selectionColumns.length) {
+            var lengths = [];
+            for (var s = 0, length = selectionColumns.length; s < length; s++) {
+                if (selectionColumns[s] <= cellRightEdge)
+                    lengths.push(s);
+                else
+                    lengths.push(0);
+            }
+            rightmost = Math.max.apply(Math, lengths);
+        }
+
+        return rightmost;
+    };
+
+    this.$tabsForRow = function(row) {
+        var rowTabs = [], line = this.$editor.session.getLine(row),
+            re = /\t/g, match;
+
+        while ((match = re.exec(line)) != null) {
+            rowTabs.push(match.index);
+        }
+
+        return rowTabs;
+    };
+
+    this.$adjustRow = function(row, widths) {
+        var rowTabs = this.$tabsForRow(row);
+
+        if (rowTabs.length == 0)
+            return;
+
+        var bias = 0, location = -1;
+        var expandedSet = this.$izip(widths, rowTabs);
+
+        for (var i = 0, l = expandedSet.length; i < l; i++) {
+            var w = expandedSet[i][0], it = expandedSet[i][1];
+            location += 1 + w;
+            it += bias;
+            var difference = location - it;
+
+            if (difference == 0)
+                continue;
+
+            var partialLine = this.$editor.session.getLine(row).substr(0, it );
+            var strippedPartialLine = partialLine.replace(/\s*$/g, "");
+            var ispaces = partialLine.length - strippedPartialLine.length;
+
+            if (difference > 0) {
+                this.$editor.session.getDocument().insertInLine({row: row, column: it + 1}, Array(difference + 1).join(" ") + "\t");
+                this.$editor.session.getDocument().removeInLine(row, it, it + 1);
+
+                bias += difference;
+            }
+
+            if (difference < 0 && ispaces >= -difference) {
+                this.$editor.session.getDocument().removeInLine(row, it + difference, it);
+                bias += difference;
+            }
+        }
+    };
+    this.$izip_longest = function(iterables) {
+        if (!iterables[0])
+            return [];
+        var longest = iterables[0].length;
+        var iterablesLength = iterables.length;
+
+        for (var i = 1; i < iterablesLength; i++) {
+            var iLength = iterables[i].length;
+            if (iLength > longest)
+                longest = iLength;
+        }
+
+        var expandedSet = [];
+
+        for (var l = 0; l < longest; l++) {
+            var set = [];
+            for (var i = 0; i < iterablesLength; i++) {
+                if (iterables[i][l] === "")
+                    set.push(NaN);
+                else
+                    set.push(iterables[i][l]);
+            }
+
+            expandedSet.push(set);
+        }
+
+
+        return expandedSet;
+    };
+    this.$izip = function(widths, tabs) {
+        var size = widths.length >= tabs.length ? tabs.length : widths.length;
+
+        var expandedSet = [];
+        for (var i = 0; i < size; i++) {
+            var set = [ widths[i], tabs[i] ];
+            expandedSet.push(set);
+        }
+        return expandedSet;
+    };
+
+}).call(ElasticTabstopsLite.prototype);
+
+exports.ElasticTabstopsLite = ElasticTabstopsLite;
+
+var Editor = require("../editor").Editor;
+require("../config").defineOptions(Editor.prototype, "editor", {
+    useElasticTabstops: {
+        set: function(val) {
+            if (val) {
+                if (!this.elasticTabstops)
+                    this.elasticTabstops = new ElasticTabstopsLite(this);
+                this.commands.on("afterExec", this.elasticTabstops.onAfterExec);
+                this.commands.on("exec", this.elasticTabstops.onExec);
+                this.on("change", this.elasticTabstops.onChange);
+            } else if (this.elasticTabstops) {
+                this.commands.removeListener("afterExec", this.elasticTabstops.onAfterExec);
+                this.commands.removeListener("exec", this.elasticTabstops.onExec);
+                this.removeListener("change", this.elasticTabstops.onChange);
+            }
+        }
+    }
+});
+
+});
+                (function() {
+                    ace.require(["ace/ext/elastic_tabstops_lite"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 1227 - 0
services/web/public/js/ace-1.4.3/ext-emmet.js

@@ -0,0 +1,1227 @@
+ace.define("ace/snippets",[], function(require, exports, module) {
+"use strict";
+var oop = require("./lib/oop");
+var EventEmitter = require("./lib/event_emitter").EventEmitter;
+var lang = require("./lib/lang");
+var Range = require("./range").Range;
+var Anchor = require("./anchor").Anchor;
+var HashHandler = require("./keyboard/hash_handler").HashHandler;
+var Tokenizer = require("./tokenizer").Tokenizer;
+var comparePoints = Range.comparePoints;
+
+var SnippetManager = function() {
+    this.snippetMap = {};
+    this.snippetNameMap = {};
+};
+
+(function() {
+    oop.implement(this, EventEmitter);
+    
+    this.getTokenizer = function() {
+        function TabstopToken(str, _, stack) {
+            str = str.substr(1);
+            if (/^\d+$/.test(str) && !stack.inFormatString)
+                return [{tabstopId: parseInt(str, 10)}];
+            return [{text: str}];
+        }
+        function escape(ch) {
+            return "(?:[^\\\\" + ch + "]|\\\\.)";
+        }
+        SnippetManager.$tokenizer = new Tokenizer({
+            start: [
+                {regex: /:/, onMatch: function(val, state, stack) {
+                    if (stack.length && stack[0].expectIf) {
+                        stack[0].expectIf = false;
+                        stack[0].elseBranch = stack[0];
+                        return [stack[0]];
+                    }
+                    return ":";
+                }},
+                {regex: /\\./, onMatch: function(val, state, stack) {
+                    var ch = val[1];
+                    if (ch == "}" && stack.length) {
+                        val = ch;
+                    }else if ("`$\\".indexOf(ch) != -1) {
+                        val = ch;
+                    } else if (stack.inFormatString) {
+                        if (ch == "n")
+                            val = "\n";
+                        else if (ch == "t")
+                            val = "\n";
+                        else if ("ulULE".indexOf(ch) != -1) {
+                            val = {changeCase: ch, local: ch > "a"};
+                        }
+                    }
+
+                    return [val];
+                }},
+                {regex: /}/, onMatch: function(val, state, stack) {
+                    return [stack.length ? stack.shift() : val];
+                }},
+                {regex: /\$(?:\d+|\w+)/, onMatch: TabstopToken},
+                {regex: /\$\{[\dA-Z_a-z]+/, onMatch: function(str, state, stack) {
+                    var t = TabstopToken(str.substr(1), state, stack);
+                    stack.unshift(t[0]);
+                    return t;
+                }, next: "snippetVar"},
+                {regex: /\n/, token: "newline", merge: false}
+            ],
+            snippetVar: [
+                {regex: "\\|" + escape("\\|") + "*\\|", onMatch: function(val, state, stack) {
+                    stack[0].choices = val.slice(1, -1).split(",");
+                }, next: "start"},
+                {regex: "/(" + escape("/") + "+)/(?:(" + escape("/") + "*)/)(\\w*):?",
+                 onMatch: function(val, state, stack) {
+                    var ts = stack[0];
+                    ts.fmtString = val;
+
+                    val = this.splitRegex.exec(val);
+                    ts.guard = val[1];
+                    ts.fmt = val[2];
+                    ts.flag = val[3];
+                    return "";
+                }, next: "start"},
+                {regex: "`" + escape("`") + "*`", onMatch: function(val, state, stack) {
+                    stack[0].code = val.splice(1, -1);
+                    return "";
+                }, next: "start"},
+                {regex: "\\?", onMatch: function(val, state, stack) {
+                    if (stack[0])
+                        stack[0].expectIf = true;
+                }, next: "start"},
+                {regex: "([^:}\\\\]|\\\\.)*:?", token: "", next: "start"}
+            ],
+            formatString: [
+                {regex: "/(" + escape("/") + "+)/", token: "regex"},
+                {regex: "", onMatch: function(val, state, stack) {
+                    stack.inFormatString = true;
+                }, next: "start"}
+            ]
+        });
+        SnippetManager.prototype.getTokenizer = function() {
+            return SnippetManager.$tokenizer;
+        };
+        return SnippetManager.$tokenizer;
+    };
+
+    this.tokenizeTmSnippet = function(str, startState) {
+        return this.getTokenizer().getLineTokens(str, startState).tokens.map(function(x) {
+            return x.value || x;
+        });
+    };
+
+    this.$getDefaultValue = function(editor, name) {
+        if (/^[A-Z]\d+$/.test(name)) {
+            var i = name.substr(1);
+            return (this.variables[name[0] + "__"] || {})[i];
+        }
+        if (/^\d+$/.test(name)) {
+            return (this.variables.__ || {})[name];
+        }
+        name = name.replace(/^TM_/, "");
+
+        if (!editor)
+            return;
+        var s = editor.session;
+        switch(name) {
+            case "CURRENT_WORD":
+                var r = s.getWordRange();
+            case "SELECTION":
+            case "SELECTED_TEXT":
+                return s.getTextRange(r);
+            case "CURRENT_LINE":
+                return s.getLine(editor.getCursorPosition().row);
+            case "PREV_LINE": // not possible in textmate
+                return s.getLine(editor.getCursorPosition().row - 1);
+            case "LINE_INDEX":
+                return editor.getCursorPosition().column;
+            case "LINE_NUMBER":
+                return editor.getCursorPosition().row + 1;
+            case "SOFT_TABS":
+                return s.getUseSoftTabs() ? "YES" : "NO";
+            case "TAB_SIZE":
+                return s.getTabSize();
+            case "FILENAME":
+            case "FILEPATH":
+                return "";
+            case "FULLNAME":
+                return "Ace";
+        }
+    };
+    this.variables = {};
+    this.getVariableValue = function(editor, varName) {
+        if (this.variables.hasOwnProperty(varName))
+            return this.variables[varName](editor, varName) || "";
+        return this.$getDefaultValue(editor, varName) || "";
+    };
+    this.tmStrFormat = function(str, ch, editor) {
+        var flag = ch.flag || "";
+        var re = ch.guard;
+        re = new RegExp(re, flag.replace(/[^gi]/, ""));
+        var fmtTokens = this.tokenizeTmSnippet(ch.fmt, "formatString");
+        var _self = this;
+        var formatted = str.replace(re, function() {
+            _self.variables.__ = arguments;
+            var fmtParts = _self.resolveVariables(fmtTokens, editor);
+            var gChangeCase = "E";
+            for (var i  = 0; i < fmtParts.length; i++) {
+                var ch = fmtParts[i];
+                if (typeof ch == "object") {
+                    fmtParts[i] = "";
+                    if (ch.changeCase && ch.local) {
+                        var next = fmtParts[i + 1];
+                        if (next && typeof next == "string") {
+                            if (ch.changeCase == "u")
+                                fmtParts[i] = next[0].toUpperCase();
+                            else
+                                fmtParts[i] = next[0].toLowerCase();
+                            fmtParts[i + 1] = next.substr(1);
+                        }
+                    } else if (ch.changeCase) {
+                        gChangeCase = ch.changeCase;
+                    }
+                } else if (gChangeCase == "U") {
+                    fmtParts[i] = ch.toUpperCase();
+                } else if (gChangeCase == "L") {
+                    fmtParts[i] = ch.toLowerCase();
+                }
+            }
+            return fmtParts.join("");
+        });
+        this.variables.__ = null;
+        return formatted;
+    };
+
+    this.resolveVariables = function(snippet, editor) {
+        var result = [];
+        for (var i = 0; i < snippet.length; i++) {
+            var ch = snippet[i];
+            if (typeof ch == "string") {
+                result.push(ch);
+            } else if (typeof ch != "object") {
+                continue;
+            } else if (ch.skip) {
+                gotoNext(ch);
+            } else if (ch.processed < i) {
+                continue;
+            } else if (ch.text) {
+                var value = this.getVariableValue(editor, ch.text);
+                if (value && ch.fmtString)
+                    value = this.tmStrFormat(value, ch);
+                ch.processed = i;
+                if (ch.expectIf == null) {
+                    if (value) {
+                        result.push(value);
+                        gotoNext(ch);
+                    }
+                } else {
+                    if (value) {
+                        ch.skip = ch.elseBranch;
+                    } else
+                        gotoNext(ch);
+                }
+            } else if (ch.tabstopId != null) {
+                result.push(ch);
+            } else if (ch.changeCase != null) {
+                result.push(ch);
+            }
+        }
+        function gotoNext(ch) {
+            var i1 = snippet.indexOf(ch, i + 1);
+            if (i1 != -1)
+                i = i1;
+        }
+        return result;
+    };
+
+    this.insertSnippetForSelection = function(editor, snippetText) {
+        var cursor = editor.getCursorPosition();
+        var line = editor.session.getLine(cursor.row);
+        var tabString = editor.session.getTabString();
+        var indentString = line.match(/^\s*/)[0];
+        
+        if (cursor.column < indentString.length)
+            indentString = indentString.slice(0, cursor.column);
+
+        snippetText = snippetText.replace(/\r/g, "");
+        var tokens = this.tokenizeTmSnippet(snippetText);
+        tokens = this.resolveVariables(tokens, editor);
+        tokens = tokens.map(function(x) {
+            if (x == "\n")
+                return x + indentString;
+            if (typeof x == "string")
+                return x.replace(/\t/g, tabString);
+            return x;
+        });
+        var tabstops = [];
+        tokens.forEach(function(p, i) {
+            if (typeof p != "object")
+                return;
+            var id = p.tabstopId;
+            var ts = tabstops[id];
+            if (!ts) {
+                ts = tabstops[id] = [];
+                ts.index = id;
+                ts.value = "";
+            }
+            if (ts.indexOf(p) !== -1)
+                return;
+            ts.push(p);
+            var i1 = tokens.indexOf(p, i + 1);
+            if (i1 === -1)
+                return;
+
+            var value = tokens.slice(i + 1, i1);
+            var isNested = value.some(function(t) {return typeof t === "object";});
+            if (isNested && !ts.value) {
+                ts.value = value;
+            } else if (value.length && (!ts.value || typeof ts.value !== "string")) {
+                ts.value = value.join("");
+            }
+        });
+        tabstops.forEach(function(ts) {ts.length = 0;});
+        var expanding = {};
+        function copyValue(val) {
+            var copy = [];
+            for (var i = 0; i < val.length; i++) {
+                var p = val[i];
+                if (typeof p == "object") {
+                    if (expanding[p.tabstopId])
+                        continue;
+                    var j = val.lastIndexOf(p, i - 1);
+                    p = copy[j] || {tabstopId: p.tabstopId};
+                }
+                copy[i] = p;
+            }
+            return copy;
+        }
+        for (var i = 0; i < tokens.length; i++) {
+            var p = tokens[i];
+            if (typeof p != "object")
+                continue;
+            var id = p.tabstopId;
+            var i1 = tokens.indexOf(p, i + 1);
+            if (expanding[id]) {
+                if (expanding[id] === p)
+                    expanding[id] = null;
+                continue;
+            }
+            
+            var ts = tabstops[id];
+            var arg = typeof ts.value == "string" ? [ts.value] : copyValue(ts.value);
+            arg.unshift(i + 1, Math.max(0, i1 - i));
+            arg.push(p);
+            expanding[id] = p;
+            tokens.splice.apply(tokens, arg);
+
+            if (ts.indexOf(p) === -1)
+                ts.push(p);
+        }
+        var row = 0, column = 0;
+        var text = "";
+        tokens.forEach(function(t) {
+            if (typeof t === "string") {
+                var lines = t.split("\n");
+                if (lines.length > 1){
+                    column = lines[lines.length - 1].length;
+                    row += lines.length - 1;
+                } else
+                    column += t.length;
+                text += t;
+            } else {
+                if (!t.start)
+                    t.start = {row: row, column: column};
+                else
+                    t.end = {row: row, column: column};
+            }
+        });
+        var range = editor.getSelectionRange();
+        var end = editor.session.replace(range, text);
+
+        var tabstopManager = new TabstopManager(editor);
+        var selectionId = editor.inVirtualSelectionMode && editor.selection.index;
+        tabstopManager.addTabstops(tabstops, range.start, end, selectionId);
+    };
+    
+    this.insertSnippet = function(editor, snippetText) {
+        var self = this;
+        if (editor.inVirtualSelectionMode)
+            return self.insertSnippetForSelection(editor, snippetText);
+        
+        editor.forEachSelection(function() {
+            self.insertSnippetForSelection(editor, snippetText);
+        }, null, {keepOrder: true});
+        
+        if (editor.tabstopManager)
+            editor.tabstopManager.tabNext();
+    };
+
+    this.$getScope = function(editor) {
+        var scope = editor.session.$mode.$id || "";
+        scope = scope.split("/").pop();
+        if (scope === "html" || scope === "php") {
+            if (scope === "php" && !editor.session.$mode.inlinePhp) 
+                scope = "html";
+            var c = editor.getCursorPosition();
+            var state = editor.session.getState(c.row);
+            if (typeof state === "object") {
+                state = state[0];
+            }
+            if (state.substring) {
+                if (state.substring(0, 3) == "js-")
+                    scope = "javascript";
+                else if (state.substring(0, 4) == "css-")
+                    scope = "css";
+                else if (state.substring(0, 4) == "php-")
+                    scope = "php";
+            }
+        }
+        
+        return scope;
+    };
+
+    this.getActiveScopes = function(editor) {
+        var scope = this.$getScope(editor);
+        var scopes = [scope];
+        var snippetMap = this.snippetMap;
+        if (snippetMap[scope] && snippetMap[scope].includeScopes) {
+            scopes.push.apply(scopes, snippetMap[scope].includeScopes);
+        }
+        scopes.push("_");
+        return scopes;
+    };
+
+    this.expandWithTab = function(editor, options) {
+        var self = this;
+        var result = editor.forEachSelection(function() {
+            return self.expandSnippetForSelection(editor, options);
+        }, null, {keepOrder: true});
+        if (result && editor.tabstopManager)
+            editor.tabstopManager.tabNext();
+        return result;
+    };
+    
+    this.expandSnippetForSelection = function(editor, options) {
+        var cursor = editor.getCursorPosition();
+        var line = editor.session.getLine(cursor.row);
+        var before = line.substring(0, cursor.column);
+        var after = line.substr(cursor.column);
+
+        var snippetMap = this.snippetMap;
+        var snippet;
+        this.getActiveScopes(editor).some(function(scope) {
+            var snippets = snippetMap[scope];
+            if (snippets)
+                snippet = this.findMatchingSnippet(snippets, before, after);
+            return !!snippet;
+        }, this);
+        if (!snippet)
+            return false;
+        if (options && options.dryRun)
+            return true;
+        editor.session.doc.removeInLine(cursor.row,
+            cursor.column - snippet.replaceBefore.length,
+            cursor.column + snippet.replaceAfter.length
+        );
+
+        this.variables.M__ = snippet.matchBefore;
+        this.variables.T__ = snippet.matchAfter;
+        this.insertSnippetForSelection(editor, snippet.content);
+
+        this.variables.M__ = this.variables.T__ = null;
+        return true;
+    };
+
+    this.findMatchingSnippet = function(snippetList, before, after) {
+        for (var i = snippetList.length; i--;) {
+            var s = snippetList[i];
+            if (s.startRe && !s.startRe.test(before))
+                continue;
+            if (s.endRe && !s.endRe.test(after))
+                continue;
+            if (!s.startRe && !s.endRe)
+                continue;
+
+            s.matchBefore = s.startRe ? s.startRe.exec(before) : [""];
+            s.matchAfter = s.endRe ? s.endRe.exec(after) : [""];
+            s.replaceBefore = s.triggerRe ? s.triggerRe.exec(before)[0] : "";
+            s.replaceAfter = s.endTriggerRe ? s.endTriggerRe.exec(after)[0] : "";
+            return s;
+        }
+    };
+
+    this.snippetMap = {};
+    this.snippetNameMap = {};
+    this.register = function(snippets, scope) {
+        var snippetMap = this.snippetMap;
+        var snippetNameMap = this.snippetNameMap;
+        var self = this;
+        
+        if (!snippets) 
+            snippets = [];
+        
+        function wrapRegexp(src) {
+            if (src && !/^\^?\(.*\)\$?$|^\\b$/.test(src))
+                src = "(?:" + src + ")";
+
+            return src || "";
+        }
+        function guardedRegexp(re, guard, opening) {
+            re = wrapRegexp(re);
+            guard = wrapRegexp(guard);
+            if (opening) {
+                re = guard + re;
+                if (re && re[re.length - 1] != "$")
+                    re = re + "$";
+            } else {
+                re = re + guard;
+                if (re && re[0] != "^")
+                    re = "^" + re;
+            }
+            return new RegExp(re);
+        }
+
+        function addSnippet(s) {
+            if (!s.scope)
+                s.scope = scope || "_";
+            scope = s.scope;
+            if (!snippetMap[scope]) {
+                snippetMap[scope] = [];
+                snippetNameMap[scope] = {};
+            }
+
+            var map = snippetNameMap[scope];
+            if (s.name) {
+                var old = map[s.name];
+                if (old)
+                    self.unregister(old);
+                map[s.name] = s;
+            }
+            snippetMap[scope].push(s);
+
+            if (s.tabTrigger && !s.trigger) {
+                if (!s.guard && /^\w/.test(s.tabTrigger))
+                    s.guard = "\\b";
+                s.trigger = lang.escapeRegExp(s.tabTrigger);
+            }
+            
+            if (!s.trigger && !s.guard && !s.endTrigger && !s.endGuard)
+                return;
+            
+            s.startRe = guardedRegexp(s.trigger, s.guard, true);
+            s.triggerRe = new RegExp(s.trigger);
+
+            s.endRe = guardedRegexp(s.endTrigger, s.endGuard, true);
+            s.endTriggerRe = new RegExp(s.endTrigger);
+        }
+
+        if (snippets && snippets.content)
+            addSnippet(snippets);
+        else if (Array.isArray(snippets))
+            snippets.forEach(addSnippet);
+        
+        this._signal("registerSnippets", {scope: scope});
+    };
+    this.unregister = function(snippets, scope) {
+        var snippetMap = this.snippetMap;
+        var snippetNameMap = this.snippetNameMap;
+
+        function removeSnippet(s) {
+            var nameMap = snippetNameMap[s.scope||scope];
+            if (nameMap && nameMap[s.name]) {
+                delete nameMap[s.name];
+                var map = snippetMap[s.scope||scope];
+                var i = map && map.indexOf(s);
+                if (i >= 0)
+                    map.splice(i, 1);
+            }
+        }
+        if (snippets.content)
+            removeSnippet(snippets);
+        else if (Array.isArray(snippets))
+            snippets.forEach(removeSnippet);
+    };
+    this.parseSnippetFile = function(str) {
+        str = str.replace(/\r/g, "");
+        var list = [], snippet = {};
+        var re = /^#.*|^({[\s\S]*})\s*$|^(\S+) (.*)$|^((?:\n*\t.*)+)/gm;
+        var m;
+        while (m = re.exec(str)) {
+            if (m[1]) {
+                try {
+                    snippet = JSON.parse(m[1]);
+                    list.push(snippet);
+                } catch (e) {}
+            } if (m[4]) {
+                snippet.content = m[4].replace(/^\t/gm, "");
+                list.push(snippet);
+                snippet = {};
+            } else {
+                var key = m[2], val = m[3];
+                if (key == "regex") {
+                    var guardRe = /\/((?:[^\/\\]|\\.)*)|$/g;
+                    snippet.guard = guardRe.exec(val)[1];
+                    snippet.trigger = guardRe.exec(val)[1];
+                    snippet.endTrigger = guardRe.exec(val)[1];
+                    snippet.endGuard = guardRe.exec(val)[1];
+                } else if (key == "snippet") {
+                    snippet.tabTrigger = val.match(/^\S*/)[0];
+                    if (!snippet.name)
+                        snippet.name = val;
+                } else {
+                    snippet[key] = val;
+                }
+            }
+        }
+        return list;
+    };
+    this.getSnippetByName = function(name, editor) {
+        var snippetMap = this.snippetNameMap;
+        var snippet;
+        this.getActiveScopes(editor).some(function(scope) {
+            var snippets = snippetMap[scope];
+            if (snippets)
+                snippet = snippets[name];
+            return !!snippet;
+        }, this);
+        return snippet;
+    };
+
+}).call(SnippetManager.prototype);
+
+
+var TabstopManager = function(editor) {
+    if (editor.tabstopManager)
+        return editor.tabstopManager;
+    editor.tabstopManager = this;
+    this.$onChange = this.onChange.bind(this);
+    this.$onChangeSelection = lang.delayedCall(this.onChangeSelection.bind(this)).schedule;
+    this.$onChangeSession = this.onChangeSession.bind(this);
+    this.$onAfterExec = this.onAfterExec.bind(this);
+    this.attach(editor);
+};
+(function() {
+    this.attach = function(editor) {
+        this.index = 0;
+        this.ranges = [];
+        this.tabstops = [];
+        this.$openTabstops = null;
+        this.selectedTabstop = null;
+
+        this.editor = editor;
+        this.editor.on("change", this.$onChange);
+        this.editor.on("changeSelection", this.$onChangeSelection);
+        this.editor.on("changeSession", this.$onChangeSession);
+        this.editor.commands.on("afterExec", this.$onAfterExec);
+        this.editor.keyBinding.addKeyboardHandler(this.keyboardHandler);
+    };
+    this.detach = function() {
+        this.tabstops.forEach(this.removeTabstopMarkers, this);
+        this.ranges = null;
+        this.tabstops = null;
+        this.selectedTabstop = null;
+        this.editor.removeListener("change", this.$onChange);
+        this.editor.removeListener("changeSelection", this.$onChangeSelection);
+        this.editor.removeListener("changeSession", this.$onChangeSession);
+        this.editor.commands.removeListener("afterExec", this.$onAfterExec);
+        this.editor.keyBinding.removeKeyboardHandler(this.keyboardHandler);
+        this.editor.tabstopManager = null;
+        this.editor = null;
+    };
+
+    this.onChange = function(delta) {
+        var changeRange = delta;
+        var isRemove = delta.action[0] == "r";
+        var start = delta.start;
+        var end = delta.end;
+        var startRow = start.row;
+        var endRow = end.row;
+        var lineDif = endRow - startRow;
+        var colDiff = end.column - start.column;
+
+        if (isRemove) {
+            lineDif = -lineDif;
+            colDiff = -colDiff;
+        }
+        if (!this.$inChange && isRemove) {
+            var ts = this.selectedTabstop;
+            var changedOutside = ts && !ts.some(function(r) {
+                return comparePoints(r.start, start) <= 0 && comparePoints(r.end, end) >= 0;
+            });
+            if (changedOutside)
+                return this.detach();
+        }
+        var ranges = this.ranges;
+        for (var i = 0; i < ranges.length; i++) {
+            var r = ranges[i];
+            if (r.end.row < start.row)
+                continue;
+
+            if (isRemove && comparePoints(start, r.start) < 0 && comparePoints(end, r.end) > 0) {
+                this.removeRange(r);
+                i--;
+                continue;
+            }
+
+            if (r.start.row == startRow && r.start.column > start.column)
+                r.start.column += colDiff;
+            if (r.end.row == startRow && r.end.column >= start.column)
+                r.end.column += colDiff;
+            if (r.start.row >= startRow)
+                r.start.row += lineDif;
+            if (r.end.row >= startRow)
+                r.end.row += lineDif;
+
+            if (comparePoints(r.start, r.end) > 0)
+                this.removeRange(r);
+        }
+        if (!ranges.length)
+            this.detach();
+    };
+    this.updateLinkedFields = function() {
+        var ts = this.selectedTabstop;
+        if (!ts || !ts.hasLinkedRanges)
+            return;
+        this.$inChange = true;
+        var session = this.editor.session;
+        var text = session.getTextRange(ts.firstNonLinked);
+        for (var i = ts.length; i--;) {
+            var range = ts[i];
+            if (!range.linked)
+                continue;
+            var fmt = exports.snippetManager.tmStrFormat(text, range.original);
+            session.replace(range, fmt);
+        }
+        this.$inChange = false;
+    };
+    this.onAfterExec = function(e) {
+        if (e.command && !e.command.readOnly)
+            this.updateLinkedFields();
+    };
+    this.onChangeSelection = function() {
+        if (!this.editor)
+            return;
+        var lead = this.editor.selection.lead;
+        var anchor = this.editor.selection.anchor;
+        var isEmpty = this.editor.selection.isEmpty();
+        for (var i = this.ranges.length; i--;) {
+            if (this.ranges[i].linked)
+                continue;
+            var containsLead = this.ranges[i].contains(lead.row, lead.column);
+            var containsAnchor = isEmpty || this.ranges[i].contains(anchor.row, anchor.column);
+            if (containsLead && containsAnchor)
+                return;
+        }
+        this.detach();
+    };
+    this.onChangeSession = function() {
+        this.detach();
+    };
+    this.tabNext = function(dir) {
+        var max = this.tabstops.length;
+        var index = this.index + (dir || 1);
+        index = Math.min(Math.max(index, 1), max);
+        if (index == max)
+            index = 0;
+        this.selectTabstop(index);
+        if (index === 0)
+            this.detach();
+    };
+    this.selectTabstop = function(index) {
+        this.$openTabstops = null;
+        var ts = this.tabstops[this.index];
+        if (ts)
+            this.addTabstopMarkers(ts);
+        this.index = index;
+        ts = this.tabstops[this.index];
+        if (!ts || !ts.length)
+            return;
+        
+        this.selectedTabstop = ts;
+        if (!this.editor.inVirtualSelectionMode) {        
+            var sel = this.editor.multiSelect;
+            sel.toSingleRange(ts.firstNonLinked.clone());
+            for (var i = ts.length; i--;) {
+                if (ts.hasLinkedRanges && ts[i].linked)
+                    continue;
+                sel.addRange(ts[i].clone(), true);
+            }
+            if (sel.ranges[0])
+                sel.addRange(sel.ranges[0].clone());
+        } else {
+            this.editor.selection.setRange(ts.firstNonLinked);
+        }
+        
+        this.editor.keyBinding.addKeyboardHandler(this.keyboardHandler);
+    };
+    this.addTabstops = function(tabstops, start, end) {
+        if (!this.$openTabstops)
+            this.$openTabstops = [];
+        if (!tabstops[0]) {
+            var p = Range.fromPoints(end, end);
+            moveRelative(p.start, start);
+            moveRelative(p.end, start);
+            tabstops[0] = [p];
+            tabstops[0].index = 0;
+        }
+
+        var i = this.index;
+        var arg = [i + 1, 0];
+        var ranges = this.ranges;
+        tabstops.forEach(function(ts, index) {
+            var dest = this.$openTabstops[index] || ts;
+                
+            for (var i = ts.length; i--;) {
+                var p = ts[i];
+                var range = Range.fromPoints(p.start, p.end || p.start);
+                movePoint(range.start, start);
+                movePoint(range.end, start);
+                range.original = p;
+                range.tabstop = dest;
+                ranges.push(range);
+                if (dest != ts)
+                    dest.unshift(range);
+                else
+                    dest[i] = range;
+                if (p.fmtString) {
+                    range.linked = true;
+                    dest.hasLinkedRanges = true;
+                } else if (!dest.firstNonLinked)
+                    dest.firstNonLinked = range;
+            }
+            if (!dest.firstNonLinked)
+                dest.hasLinkedRanges = false;
+            if (dest === ts) {
+                arg.push(dest);
+                this.$openTabstops[index] = dest;
+            }
+            this.addTabstopMarkers(dest);
+        }, this);
+        
+        if (arg.length > 2) {
+            if (this.tabstops.length)
+                arg.push(arg.splice(2, 1)[0]);
+            this.tabstops.splice.apply(this.tabstops, arg);
+        }
+    };
+
+    this.addTabstopMarkers = function(ts) {
+        var session = this.editor.session;
+        ts.forEach(function(range) {
+            if  (!range.markerId)
+                range.markerId = session.addMarker(range, "ace_snippet-marker", "text");
+        });
+    };
+    this.removeTabstopMarkers = function(ts) {
+        var session = this.editor.session;
+        ts.forEach(function(range) {
+            session.removeMarker(range.markerId);
+            range.markerId = null;
+        });
+    };
+    this.removeRange = function(range) {
+        var i = range.tabstop.indexOf(range);
+        range.tabstop.splice(i, 1);
+        i = this.ranges.indexOf(range);
+        this.ranges.splice(i, 1);
+        this.editor.session.removeMarker(range.markerId);
+        if (!range.tabstop.length) {
+            i = this.tabstops.indexOf(range.tabstop);
+            if (i != -1)
+                this.tabstops.splice(i, 1);
+            if (!this.tabstops.length)
+                this.detach();
+        }
+    };
+
+    this.keyboardHandler = new HashHandler();
+    this.keyboardHandler.bindKeys({
+        "Tab": function(ed) {
+            if (exports.snippetManager && exports.snippetManager.expandWithTab(ed)) {
+                return;
+            }
+
+            ed.tabstopManager.tabNext(1);
+        },
+        "Shift-Tab": function(ed) {
+            ed.tabstopManager.tabNext(-1);
+        },
+        "Esc": function(ed) {
+            ed.tabstopManager.detach();
+        },
+        "Return": function(ed) {
+            return false;
+        }
+    });
+}).call(TabstopManager.prototype);
+
+
+
+var changeTracker = {};
+changeTracker.onChange = Anchor.prototype.onChange;
+changeTracker.setPosition = function(row, column) {
+    this.pos.row = row;
+    this.pos.column = column;
+};
+changeTracker.update = function(pos, delta, $insertRight) {
+    this.$insertRight = $insertRight;
+    this.pos = pos; 
+    this.onChange(delta);
+};
+
+var movePoint = function(point, diff) {
+    if (point.row == 0)
+        point.column += diff.column;
+    point.row += diff.row;
+};
+
+var moveRelative = function(point, start) {
+    if (point.row == start.row)
+        point.column -= start.column;
+    point.row -= start.row;
+};
+
+
+require("./lib/dom").importCssString("\
+.ace_snippet-marker {\
+    -moz-box-sizing: border-box;\
+    box-sizing: border-box;\
+    background: rgba(194, 193, 208, 0.09);\
+    border: 1px dotted rgba(211, 208, 235, 0.62);\
+    position: absolute;\
+}");
+
+exports.snippetManager = new SnippetManager();
+
+
+var Editor = require("./editor").Editor;
+(function() {
+    this.insertSnippet = function(content, options) {
+        return exports.snippetManager.insertSnippet(this, content, options);
+    };
+    this.expandSnippet = function(options) {
+        return exports.snippetManager.expandWithTab(this, options);
+    };
+}).call(Editor.prototype);
+
+});
+
+ace.define("ace/ext/emmet",[], function(require, exports, module) {
+"use strict";
+var HashHandler = require("ace/keyboard/hash_handler").HashHandler;
+var Editor = require("ace/editor").Editor;
+var snippetManager = require("ace/snippets").snippetManager;
+var Range = require("ace/range").Range;
+var emmet, emmetPath;
+function AceEmmetEditor() {}
+
+AceEmmetEditor.prototype = {
+    setupContext: function(editor) {
+        this.ace = editor;
+        this.indentation = editor.session.getTabString();
+        if (!emmet)
+            emmet = window.emmet;
+        var resources = emmet.resources || emmet.require("resources");
+        resources.setVariable("indentation", this.indentation);
+        this.$syntax = null;
+        this.$syntax = this.getSyntax();
+    },
+    getSelectionRange: function() {
+        var range = this.ace.getSelectionRange();
+        var doc = this.ace.session.doc;
+        return {
+            start: doc.positionToIndex(range.start),
+            end: doc.positionToIndex(range.end)
+        };
+    },
+    createSelection: function(start, end) {
+        var doc = this.ace.session.doc;
+        this.ace.selection.setRange({
+            start: doc.indexToPosition(start),
+            end: doc.indexToPosition(end)
+        });
+    },
+    getCurrentLineRange: function() {
+        var ace = this.ace;
+        var row = ace.getCursorPosition().row;
+        var lineLength = ace.session.getLine(row).length;
+        var index = ace.session.doc.positionToIndex({row: row, column: 0});
+        return {
+            start: index,
+            end: index + lineLength
+        };
+    },
+    getCaretPos: function(){
+        var pos = this.ace.getCursorPosition();
+        return this.ace.session.doc.positionToIndex(pos);
+    },
+    setCaretPos: function(index){
+        var pos = this.ace.session.doc.indexToPosition(index);
+        this.ace.selection.moveToPosition(pos);
+    },
+    getCurrentLine: function() {
+        var row = this.ace.getCursorPosition().row;
+        return this.ace.session.getLine(row);
+    },
+    replaceContent: function(value, start, end, noIndent) {
+        if (end == null)
+            end = start == null ? this.getContent().length : start;
+        if (start == null)
+            start = 0;        
+        
+        var editor = this.ace;
+        var doc = editor.session.doc;
+        var range = Range.fromPoints(doc.indexToPosition(start), doc.indexToPosition(end));
+        editor.session.remove(range);
+        
+        range.end = range.start;
+        
+        value = this.$updateTabstops(value);
+        snippetManager.insertSnippet(editor, value);
+    },
+    getContent: function(){
+        return this.ace.getValue();
+    },
+    getSyntax: function() {
+        if (this.$syntax)
+            return this.$syntax;
+        var syntax = this.ace.session.$modeId.split("/").pop();
+        if (syntax == "html" || syntax == "php") {
+            var cursor = this.ace.getCursorPosition();
+            var state = this.ace.session.getState(cursor.row);
+            if (typeof state != "string")
+                state = state[0];
+            if (state) {
+                state = state.split("-");
+                if (state.length > 1)
+                    syntax = state[0];
+                else if (syntax == "php")
+                    syntax = "html";
+            }
+        }
+        return syntax;
+    },
+    getProfileName: function() {
+        var resources = emmet.resources || emmet.require("resources");
+        switch (this.getSyntax()) {
+          case "css": return "css";
+          case "xml":
+          case "xsl":
+            return "xml";
+          case "html":
+            var profile = resources.getVariable("profile");
+            if (!profile)
+                profile = this.ace.session.getLines(0,2).join("").search(/<!DOCTYPE[^>]+XHTML/i) != -1 ? "xhtml": "html";
+            return profile;
+          default:
+            var mode = this.ace.session.$mode;
+            return mode.emmetConfig && mode.emmetConfig.profile || "xhtml";
+        }
+    },
+    prompt: function(title) {
+        return prompt(title);
+    },
+    getSelection: function() {
+        return this.ace.session.getTextRange();
+    },
+    getFilePath: function() {
+        return "";
+    },
+    $updateTabstops: function(value) {
+        var base = 1000;
+        var zeroBase = 0;
+        var lastZero = null;
+        var ts = emmet.tabStops || emmet.require('tabStops');
+        var resources = emmet.resources || emmet.require("resources");
+        var settings = resources.getVocabulary("user");
+        var tabstopOptions = {
+            tabstop: function(data) {
+                var group = parseInt(data.group, 10);
+                var isZero = group === 0;
+                if (isZero)
+                    group = ++zeroBase;
+                else
+                    group += base;
+
+                var placeholder = data.placeholder;
+                if (placeholder) {
+                    placeholder = ts.processText(placeholder, tabstopOptions);
+                }
+
+                var result = '${' + group + (placeholder ? ':' + placeholder : '') + '}';
+
+                if (isZero) {
+                    lastZero = [data.start, result];
+                }
+
+                return result;
+            },
+            escape: function(ch) {
+                if (ch == '$') return '\\$';
+                if (ch == '\\') return '\\\\';
+                return ch;
+            }
+        };
+
+        value = ts.processText(value, tabstopOptions);
+
+        if (settings.variables['insert_final_tabstop'] && !/\$\{0\}$/.test(value)) {
+            value += '${0}';
+        } else if (lastZero) {
+            var common = emmet.utils ? emmet.utils.common : emmet.require('utils');
+            value = common.replaceSubstring(value, '${0}', lastZero[0], lastZero[1]);
+        }
+        
+        return value;
+    }
+};
+
+
+var keymap = {
+    expand_abbreviation: {"mac": "ctrl+alt+e", "win": "alt+e"},
+    match_pair_outward: {"mac": "ctrl+d", "win": "ctrl+,"},
+    match_pair_inward: {"mac": "ctrl+j", "win": "ctrl+shift+0"},
+    matching_pair: {"mac": "ctrl+alt+j", "win": "alt+j"},
+    next_edit_point: "alt+right",
+    prev_edit_point: "alt+left",
+    toggle_comment: {"mac": "command+/", "win": "ctrl+/"},
+    split_join_tag: {"mac": "shift+command+'", "win": "shift+ctrl+`"},
+    remove_tag: {"mac": "command+'", "win": "shift+ctrl+;"},
+    evaluate_math_expression: {"mac": "shift+command+y", "win": "shift+ctrl+y"},
+    increment_number_by_1: "ctrl+up",
+    decrement_number_by_1: "ctrl+down",
+    increment_number_by_01: "alt+up",
+    decrement_number_by_01: "alt+down",
+    increment_number_by_10: {"mac": "alt+command+up", "win": "shift+alt+up"},
+    decrement_number_by_10: {"mac": "alt+command+down", "win": "shift+alt+down"},
+    select_next_item: {"mac": "shift+command+.", "win": "shift+ctrl+."},
+    select_previous_item: {"mac": "shift+command+,", "win": "shift+ctrl+,"},
+    reflect_css_value: {"mac": "shift+command+r", "win": "shift+ctrl+r"},
+
+    encode_decode_data_url: {"mac": "shift+ctrl+d", "win": "ctrl+'"},
+    expand_abbreviation_with_tab: "Tab",
+    wrap_with_abbreviation: {"mac": "shift+ctrl+a", "win": "shift+ctrl+a"}
+};
+
+var editorProxy = new AceEmmetEditor();
+exports.commands = new HashHandler();
+exports.runEmmetCommand = function runEmmetCommand(editor) {
+    try {
+        editorProxy.setupContext(editor);
+        var actions = emmet.actions || emmet.require("actions");
+    
+        if (this.action == "expand_abbreviation_with_tab") {
+            if (!editor.selection.isEmpty())
+                return false;
+            var pos = editor.selection.lead;
+            var token = editor.session.getTokenAt(pos.row, pos.column);
+            if (token && /\btag\b/.test(token.type))
+                return false;
+        }
+        
+        if (this.action == "wrap_with_abbreviation") {
+            return setTimeout(function() {
+                actions.run("wrap_with_abbreviation", editorProxy);
+            }, 0);
+        }
+        
+        var result = actions.run(this.action, editorProxy);
+    } catch(e) {
+        if (!emmet) {
+            exports.load(runEmmetCommand.bind(this, editor));
+            return true;
+        }
+        editor._signal("changeStatus", typeof e == "string" ? e : e.message);
+        console.log(e);
+        result = false;
+    }
+    return result;
+};
+
+for (var command in keymap) {
+    exports.commands.addCommand({
+        name: "emmet:" + command,
+        action: command,
+        bindKey: keymap[command],
+        exec: exports.runEmmetCommand,
+        multiSelectAction: "forEach"
+    });
+}
+
+exports.updateCommands = function(editor, enabled) {
+    if (enabled) {
+        editor.keyBinding.addKeyboardHandler(exports.commands);
+    } else {
+        editor.keyBinding.removeKeyboardHandler(exports.commands);
+    }
+};
+
+exports.isSupportedMode = function(mode) {
+    if (!mode) return false;
+    if (mode.emmetConfig) return true;
+    var id = mode.$id || mode;
+    return /css|less|scss|sass|stylus|html|php|twig|ejs|handlebars/.test(id);
+};
+
+exports.isAvailable = function(editor, command) {
+    if (/(evaluate_math_expression|expand_abbreviation)$/.test(command))
+        return true;
+    var mode = editor.session.$mode;
+    var isSupported = exports.isSupportedMode(mode);
+    if (isSupported && mode.$modes) {
+        try {
+            editorProxy.setupContext(editor);
+            if (/js|php/.test(editorProxy.getSyntax()))
+                isSupported = false;
+        } catch(e) {}
+    }
+    return isSupported;
+};
+
+var onChangeMode = function(e, target) {
+    var editor = target;
+    if (!editor)
+        return;
+    var enabled = exports.isSupportedMode(editor.session.$mode);
+    if (e.enableEmmet === false)
+        enabled = false;
+    if (enabled)
+        exports.load();
+    exports.updateCommands(editor, enabled);
+};
+
+exports.load = function(cb) {
+    if (typeof emmetPath == "string") {
+        require("ace/config").loadModule(emmetPath, function() {
+            emmetPath = null;
+            cb && cb();
+        });
+    }
+};
+
+exports.AceEmmetEditor = AceEmmetEditor;
+require("ace/config").defineOptions(Editor.prototype, "editor", {
+    enableEmmet: {
+        set: function(val) {
+            this[val ? "on" : "removeListener"]("changeMode", onChangeMode);
+            onChangeMode({enableEmmet: !!val}, this);
+        },
+        value: true
+    }
+});
+
+exports.setCore = function(e) {
+    if (typeof e == "string")
+       emmetPath = e;
+    else
+       emmet = e;
+};
+});
+                (function() {
+                    ace.require(["ace/ext/emmet"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 10 - 0
services/web/public/js/ace-1.4.3/ext-error_marker.js

@@ -0,0 +1,10 @@
+
+;
+                (function() {
+                    ace.require(["ace/ext/error_marker"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 189 - 0
services/web/public/js/ace-1.4.3/ext-keybinding_menu.js

@@ -0,0 +1,189 @@
+ace.define("ace/ext/menu_tools/overlay_page",[], function(require, exports, module) {
+'use strict';
+var dom = require("../../lib/dom");
+var cssText = "#ace_settingsmenu, #kbshortcutmenu {\
+background-color: #F7F7F7;\
+color: black;\
+box-shadow: -5px 4px 5px rgba(126, 126, 126, 0.55);\
+padding: 1em 0.5em 2em 1em;\
+overflow: auto;\
+position: absolute;\
+margin: 0;\
+bottom: 0;\
+right: 0;\
+top: 0;\
+z-index: 9991;\
+cursor: default;\
+}\
+.ace_dark #ace_settingsmenu, .ace_dark #kbshortcutmenu {\
+box-shadow: -20px 10px 25px rgba(126, 126, 126, 0.25);\
+background-color: rgba(255, 255, 255, 0.6);\
+color: black;\
+}\
+.ace_optionsMenuEntry:hover {\
+background-color: rgba(100, 100, 100, 0.1);\
+transition: all 0.3s\
+}\
+.ace_closeButton {\
+background: rgba(245, 146, 146, 0.5);\
+border: 1px solid #F48A8A;\
+border-radius: 50%;\
+padding: 7px;\
+position: absolute;\
+right: -8px;\
+top: -8px;\
+z-index: 100000;\
+}\
+.ace_closeButton{\
+background: rgba(245, 146, 146, 0.9);\
+}\
+.ace_optionsMenuKey {\
+color: darkslateblue;\
+font-weight: bold;\
+}\
+.ace_optionsMenuCommand {\
+color: darkcyan;\
+font-weight: normal;\
+}\
+.ace_optionsMenuEntry input, .ace_optionsMenuEntry button {\
+vertical-align: middle;\
+}\
+.ace_optionsMenuEntry button[ace_selected_button=true] {\
+background: #e7e7e7;\
+box-shadow: 1px 0px 2px 0px #adadad inset;\
+border-color: #adadad;\
+}\
+.ace_optionsMenuEntry button {\
+background: white;\
+border: 1px solid lightgray;\
+margin: 0px;\
+}\
+.ace_optionsMenuEntry button:hover{\
+background: #f0f0f0;\
+}";
+dom.importCssString(cssText);
+module.exports.overlayPage = function overlayPage(editor, contentElement, top, right, bottom, left) {
+    top = top ? 'top: ' + top + ';' : '';
+    bottom = bottom ? 'bottom: ' + bottom + ';' : '';
+    right = right ? 'right: ' + right + ';' : '';
+    left = left ? 'left: ' + left + ';' : '';
+
+    var closer = document.createElement('div');
+    var contentContainer = document.createElement('div');
+
+    function documentEscListener(e) {
+        if (e.keyCode === 27) {
+            closer.click();
+        }
+    }
+
+    closer.style.cssText = 'margin: 0; padding: 0; ' +
+        'position: fixed; top:0; bottom:0; left:0; right:0;' +
+        'z-index: 9990; ' +
+        'background-color: rgba(0, 0, 0, 0.3);';
+    closer.addEventListener('click', function() {
+        document.removeEventListener('keydown', documentEscListener);
+        closer.parentNode.removeChild(closer);
+        editor.focus();
+        closer = null;
+    });
+    document.addEventListener('keydown', documentEscListener);
+
+    contentContainer.style.cssText = top + right + bottom + left;
+    contentContainer.addEventListener('click', function(e) {
+        e.stopPropagation();
+    });
+
+    var wrapper = dom.createElement("div");
+    wrapper.style.position = "relative";
+    
+    var closeButton = dom.createElement("div");
+    closeButton.className = "ace_closeButton";
+    closeButton.addEventListener('click', function() {
+        closer.click();
+    });
+    
+    wrapper.appendChild(closeButton);
+    contentContainer.appendChild(wrapper);
+    
+    contentContainer.appendChild(contentElement);
+    closer.appendChild(contentContainer);
+    document.body.appendChild(closer);
+    editor.blur();
+};
+
+});
+
+ace.define("ace/ext/menu_tools/get_editor_keyboard_shortcuts",[], function(require, exports, module) {
+"use strict";
+var keys = require("../../lib/keys");
+module.exports.getEditorKeybordShortcuts = function(editor) {
+    var KEY_MODS = keys.KEY_MODS;
+    var keybindings = [];
+    var commandMap = {};
+    editor.keyBinding.$handlers.forEach(function(handler) {
+        var ckb = handler.commandKeyBinding;
+        for (var i in ckb) {
+            var key = i.replace(/(^|-)\w/g, function(x) { return x.toUpperCase(); });
+            var commands = ckb[i];
+            if (!Array.isArray(commands))
+                commands = [commands];
+            commands.forEach(function(command) {
+                if (typeof command != "string")
+                    command  = command.name;
+                if (commandMap[command]) {
+                    commandMap[command].key += "|" + key;
+                } else {
+                    commandMap[command] = {key: key, command: command};
+                    keybindings.push(commandMap[command]);
+                }         
+            });
+        }
+    });
+    return keybindings;
+};
+
+});
+
+ace.define("ace/ext/keybinding_menu",[], function(require, exports, module) {
+    "use strict";
+    var Editor = require("ace/editor").Editor;
+    function showKeyboardShortcuts (editor) {
+        if(!document.getElementById('kbshortcutmenu')) {
+            var overlayPage = require('./menu_tools/overlay_page').overlayPage;
+            var getEditorKeybordShortcuts = require('./menu_tools/get_editor_keyboard_shortcuts').getEditorKeybordShortcuts;
+            var kb = getEditorKeybordShortcuts(editor);
+            var el = document.createElement('div');
+            var commands = kb.reduce(function(previous, current) {
+                return previous + '<div class="ace_optionsMenuEntry"><span class="ace_optionsMenuCommand">' 
+                    + current.command + '</span> : '
+                    + '<span class="ace_optionsMenuKey">' + current.key + '</span></div>';
+            }, '');
+
+            el.id = 'kbshortcutmenu';
+            el.innerHTML = '<h1>Keyboard Shortcuts</h1>' + commands + '</div>';
+            overlayPage(editor, el, '0', '0', '0', null);
+        }
+    }
+    module.exports.init = function(editor) {
+        Editor.prototype.showKeyboardShortcuts = function() {
+            showKeyboardShortcuts(this);
+        };
+        editor.commands.addCommands([{
+            name: "showKeyboardShortcuts",
+            bindKey: {win: "Ctrl-Alt-h", mac: "Command-Alt-h"},
+            exec: function(editor, line) {
+                editor.showKeyboardShortcuts();
+            }
+        }]);
+    };
+
+});
+                (function() {
+                    ace.require(["ace/ext/keybinding_menu"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 1994 - 0
services/web/public/js/ace-1.4.3/ext-language_tools.js

@@ -0,0 +1,1994 @@
+ace.define("ace/snippets",[], function(require, exports, module) {
+"use strict";
+var oop = require("./lib/oop");
+var EventEmitter = require("./lib/event_emitter").EventEmitter;
+var lang = require("./lib/lang");
+var Range = require("./range").Range;
+var Anchor = require("./anchor").Anchor;
+var HashHandler = require("./keyboard/hash_handler").HashHandler;
+var Tokenizer = require("./tokenizer").Tokenizer;
+var comparePoints = Range.comparePoints;
+
+var SnippetManager = function() {
+    this.snippetMap = {};
+    this.snippetNameMap = {};
+};
+
+(function() {
+    oop.implement(this, EventEmitter);
+    
+    this.getTokenizer = function() {
+        function TabstopToken(str, _, stack) {
+            str = str.substr(1);
+            if (/^\d+$/.test(str) && !stack.inFormatString)
+                return [{tabstopId: parseInt(str, 10)}];
+            return [{text: str}];
+        }
+        function escape(ch) {
+            return "(?:[^\\\\" + ch + "]|\\\\.)";
+        }
+        SnippetManager.$tokenizer = new Tokenizer({
+            start: [
+                {regex: /:/, onMatch: function(val, state, stack) {
+                    if (stack.length && stack[0].expectIf) {
+                        stack[0].expectIf = false;
+                        stack[0].elseBranch = stack[0];
+                        return [stack[0]];
+                    }
+                    return ":";
+                }},
+                {regex: /\\./, onMatch: function(val, state, stack) {
+                    var ch = val[1];
+                    if (ch == "}" && stack.length) {
+                        val = ch;
+                    }else if ("`$\\".indexOf(ch) != -1) {
+                        val = ch;
+                    } else if (stack.inFormatString) {
+                        if (ch == "n")
+                            val = "\n";
+                        else if (ch == "t")
+                            val = "\n";
+                        else if ("ulULE".indexOf(ch) != -1) {
+                            val = {changeCase: ch, local: ch > "a"};
+                        }
+                    }
+
+                    return [val];
+                }},
+                {regex: /}/, onMatch: function(val, state, stack) {
+                    return [stack.length ? stack.shift() : val];
+                }},
+                {regex: /\$(?:\d+|\w+)/, onMatch: TabstopToken},
+                {regex: /\$\{[\dA-Z_a-z]+/, onMatch: function(str, state, stack) {
+                    var t = TabstopToken(str.substr(1), state, stack);
+                    stack.unshift(t[0]);
+                    return t;
+                }, next: "snippetVar"},
+                {regex: /\n/, token: "newline", merge: false}
+            ],
+            snippetVar: [
+                {regex: "\\|" + escape("\\|") + "*\\|", onMatch: function(val, state, stack) {
+                    stack[0].choices = val.slice(1, -1).split(",");
+                }, next: "start"},
+                {regex: "/(" + escape("/") + "+)/(?:(" + escape("/") + "*)/)(\\w*):?",
+                 onMatch: function(val, state, stack) {
+                    var ts = stack[0];
+                    ts.fmtString = val;
+
+                    val = this.splitRegex.exec(val);
+                    ts.guard = val[1];
+                    ts.fmt = val[2];
+                    ts.flag = val[3];
+                    return "";
+                }, next: "start"},
+                {regex: "`" + escape("`") + "*`", onMatch: function(val, state, stack) {
+                    stack[0].code = val.splice(1, -1);
+                    return "";
+                }, next: "start"},
+                {regex: "\\?", onMatch: function(val, state, stack) {
+                    if (stack[0])
+                        stack[0].expectIf = true;
+                }, next: "start"},
+                {regex: "([^:}\\\\]|\\\\.)*:?", token: "", next: "start"}
+            ],
+            formatString: [
+                {regex: "/(" + escape("/") + "+)/", token: "regex"},
+                {regex: "", onMatch: function(val, state, stack) {
+                    stack.inFormatString = true;
+                }, next: "start"}
+            ]
+        });
+        SnippetManager.prototype.getTokenizer = function() {
+            return SnippetManager.$tokenizer;
+        };
+        return SnippetManager.$tokenizer;
+    };
+
+    this.tokenizeTmSnippet = function(str, startState) {
+        return this.getTokenizer().getLineTokens(str, startState).tokens.map(function(x) {
+            return x.value || x;
+        });
+    };
+
+    this.$getDefaultValue = function(editor, name) {
+        if (/^[A-Z]\d+$/.test(name)) {
+            var i = name.substr(1);
+            return (this.variables[name[0] + "__"] || {})[i];
+        }
+        if (/^\d+$/.test(name)) {
+            return (this.variables.__ || {})[name];
+        }
+        name = name.replace(/^TM_/, "");
+
+        if (!editor)
+            return;
+        var s = editor.session;
+        switch(name) {
+            case "CURRENT_WORD":
+                var r = s.getWordRange();
+            case "SELECTION":
+            case "SELECTED_TEXT":
+                return s.getTextRange(r);
+            case "CURRENT_LINE":
+                return s.getLine(editor.getCursorPosition().row);
+            case "PREV_LINE": // not possible in textmate
+                return s.getLine(editor.getCursorPosition().row - 1);
+            case "LINE_INDEX":
+                return editor.getCursorPosition().column;
+            case "LINE_NUMBER":
+                return editor.getCursorPosition().row + 1;
+            case "SOFT_TABS":
+                return s.getUseSoftTabs() ? "YES" : "NO";
+            case "TAB_SIZE":
+                return s.getTabSize();
+            case "FILENAME":
+            case "FILEPATH":
+                return "";
+            case "FULLNAME":
+                return "Ace";
+        }
+    };
+    this.variables = {};
+    this.getVariableValue = function(editor, varName) {
+        if (this.variables.hasOwnProperty(varName))
+            return this.variables[varName](editor, varName) || "";
+        return this.$getDefaultValue(editor, varName) || "";
+    };
+    this.tmStrFormat = function(str, ch, editor) {
+        var flag = ch.flag || "";
+        var re = ch.guard;
+        re = new RegExp(re, flag.replace(/[^gi]/, ""));
+        var fmtTokens = this.tokenizeTmSnippet(ch.fmt, "formatString");
+        var _self = this;
+        var formatted = str.replace(re, function() {
+            _self.variables.__ = arguments;
+            var fmtParts = _self.resolveVariables(fmtTokens, editor);
+            var gChangeCase = "E";
+            for (var i  = 0; i < fmtParts.length; i++) {
+                var ch = fmtParts[i];
+                if (typeof ch == "object") {
+                    fmtParts[i] = "";
+                    if (ch.changeCase && ch.local) {
+                        var next = fmtParts[i + 1];
+                        if (next && typeof next == "string") {
+                            if (ch.changeCase == "u")
+                                fmtParts[i] = next[0].toUpperCase();
+                            else
+                                fmtParts[i] = next[0].toLowerCase();
+                            fmtParts[i + 1] = next.substr(1);
+                        }
+                    } else if (ch.changeCase) {
+                        gChangeCase = ch.changeCase;
+                    }
+                } else if (gChangeCase == "U") {
+                    fmtParts[i] = ch.toUpperCase();
+                } else if (gChangeCase == "L") {
+                    fmtParts[i] = ch.toLowerCase();
+                }
+            }
+            return fmtParts.join("");
+        });
+        this.variables.__ = null;
+        return formatted;
+    };
+
+    this.resolveVariables = function(snippet, editor) {
+        var result = [];
+        for (var i = 0; i < snippet.length; i++) {
+            var ch = snippet[i];
+            if (typeof ch == "string") {
+                result.push(ch);
+            } else if (typeof ch != "object") {
+                continue;
+            } else if (ch.skip) {
+                gotoNext(ch);
+            } else if (ch.processed < i) {
+                continue;
+            } else if (ch.text) {
+                var value = this.getVariableValue(editor, ch.text);
+                if (value && ch.fmtString)
+                    value = this.tmStrFormat(value, ch);
+                ch.processed = i;
+                if (ch.expectIf == null) {
+                    if (value) {
+                        result.push(value);
+                        gotoNext(ch);
+                    }
+                } else {
+                    if (value) {
+                        ch.skip = ch.elseBranch;
+                    } else
+                        gotoNext(ch);
+                }
+            } else if (ch.tabstopId != null) {
+                result.push(ch);
+            } else if (ch.changeCase != null) {
+                result.push(ch);
+            }
+        }
+        function gotoNext(ch) {
+            var i1 = snippet.indexOf(ch, i + 1);
+            if (i1 != -1)
+                i = i1;
+        }
+        return result;
+    };
+
+    this.insertSnippetForSelection = function(editor, snippetText) {
+        var cursor = editor.getCursorPosition();
+        var line = editor.session.getLine(cursor.row);
+        var tabString = editor.session.getTabString();
+        var indentString = line.match(/^\s*/)[0];
+        
+        if (cursor.column < indentString.length)
+            indentString = indentString.slice(0, cursor.column);
+
+        snippetText = snippetText.replace(/\r/g, "");
+        var tokens = this.tokenizeTmSnippet(snippetText);
+        tokens = this.resolveVariables(tokens, editor);
+        tokens = tokens.map(function(x) {
+            if (x == "\n")
+                return x + indentString;
+            if (typeof x == "string")
+                return x.replace(/\t/g, tabString);
+            return x;
+        });
+        var tabstops = [];
+        tokens.forEach(function(p, i) {
+            if (typeof p != "object")
+                return;
+            var id = p.tabstopId;
+            var ts = tabstops[id];
+            if (!ts) {
+                ts = tabstops[id] = [];
+                ts.index = id;
+                ts.value = "";
+            }
+            if (ts.indexOf(p) !== -1)
+                return;
+            ts.push(p);
+            var i1 = tokens.indexOf(p, i + 1);
+            if (i1 === -1)
+                return;
+
+            var value = tokens.slice(i + 1, i1);
+            var isNested = value.some(function(t) {return typeof t === "object";});
+            if (isNested && !ts.value) {
+                ts.value = value;
+            } else if (value.length && (!ts.value || typeof ts.value !== "string")) {
+                ts.value = value.join("");
+            }
+        });
+        tabstops.forEach(function(ts) {ts.length = 0;});
+        var expanding = {};
+        function copyValue(val) {
+            var copy = [];
+            for (var i = 0; i < val.length; i++) {
+                var p = val[i];
+                if (typeof p == "object") {
+                    if (expanding[p.tabstopId])
+                        continue;
+                    var j = val.lastIndexOf(p, i - 1);
+                    p = copy[j] || {tabstopId: p.tabstopId};
+                }
+                copy[i] = p;
+            }
+            return copy;
+        }
+        for (var i = 0; i < tokens.length; i++) {
+            var p = tokens[i];
+            if (typeof p != "object")
+                continue;
+            var id = p.tabstopId;
+            var i1 = tokens.indexOf(p, i + 1);
+            if (expanding[id]) {
+                if (expanding[id] === p)
+                    expanding[id] = null;
+                continue;
+            }
+            
+            var ts = tabstops[id];
+            var arg = typeof ts.value == "string" ? [ts.value] : copyValue(ts.value);
+            arg.unshift(i + 1, Math.max(0, i1 - i));
+            arg.push(p);
+            expanding[id] = p;
+            tokens.splice.apply(tokens, arg);
+
+            if (ts.indexOf(p) === -1)
+                ts.push(p);
+        }
+        var row = 0, column = 0;
+        var text = "";
+        tokens.forEach(function(t) {
+            if (typeof t === "string") {
+                var lines = t.split("\n");
+                if (lines.length > 1){
+                    column = lines[lines.length - 1].length;
+                    row += lines.length - 1;
+                } else
+                    column += t.length;
+                text += t;
+            } else {
+                if (!t.start)
+                    t.start = {row: row, column: column};
+                else
+                    t.end = {row: row, column: column};
+            }
+        });
+        var range = editor.getSelectionRange();
+        var end = editor.session.replace(range, text);
+
+        var tabstopManager = new TabstopManager(editor);
+        var selectionId = editor.inVirtualSelectionMode && editor.selection.index;
+        tabstopManager.addTabstops(tabstops, range.start, end, selectionId);
+    };
+    
+    this.insertSnippet = function(editor, snippetText) {
+        var self = this;
+        if (editor.inVirtualSelectionMode)
+            return self.insertSnippetForSelection(editor, snippetText);
+        
+        editor.forEachSelection(function() {
+            self.insertSnippetForSelection(editor, snippetText);
+        }, null, {keepOrder: true});
+        
+        if (editor.tabstopManager)
+            editor.tabstopManager.tabNext();
+    };
+
+    this.$getScope = function(editor) {
+        var scope = editor.session.$mode.$id || "";
+        scope = scope.split("/").pop();
+        if (scope === "html" || scope === "php") {
+            if (scope === "php" && !editor.session.$mode.inlinePhp) 
+                scope = "html";
+            var c = editor.getCursorPosition();
+            var state = editor.session.getState(c.row);
+            if (typeof state === "object") {
+                state = state[0];
+            }
+            if (state.substring) {
+                if (state.substring(0, 3) == "js-")
+                    scope = "javascript";
+                else if (state.substring(0, 4) == "css-")
+                    scope = "css";
+                else if (state.substring(0, 4) == "php-")
+                    scope = "php";
+            }
+        }
+        
+        return scope;
+    };
+
+    this.getActiveScopes = function(editor) {
+        var scope = this.$getScope(editor);
+        var scopes = [scope];
+        var snippetMap = this.snippetMap;
+        if (snippetMap[scope] && snippetMap[scope].includeScopes) {
+            scopes.push.apply(scopes, snippetMap[scope].includeScopes);
+        }
+        scopes.push("_");
+        return scopes;
+    };
+
+    this.expandWithTab = function(editor, options) {
+        var self = this;
+        var result = editor.forEachSelection(function() {
+            return self.expandSnippetForSelection(editor, options);
+        }, null, {keepOrder: true});
+        if (result && editor.tabstopManager)
+            editor.tabstopManager.tabNext();
+        return result;
+    };
+    
+    this.expandSnippetForSelection = function(editor, options) {
+        var cursor = editor.getCursorPosition();
+        var line = editor.session.getLine(cursor.row);
+        var before = line.substring(0, cursor.column);
+        var after = line.substr(cursor.column);
+
+        var snippetMap = this.snippetMap;
+        var snippet;
+        this.getActiveScopes(editor).some(function(scope) {
+            var snippets = snippetMap[scope];
+            if (snippets)
+                snippet = this.findMatchingSnippet(snippets, before, after);
+            return !!snippet;
+        }, this);
+        if (!snippet)
+            return false;
+        if (options && options.dryRun)
+            return true;
+        editor.session.doc.removeInLine(cursor.row,
+            cursor.column - snippet.replaceBefore.length,
+            cursor.column + snippet.replaceAfter.length
+        );
+
+        this.variables.M__ = snippet.matchBefore;
+        this.variables.T__ = snippet.matchAfter;
+        this.insertSnippetForSelection(editor, snippet.content);
+
+        this.variables.M__ = this.variables.T__ = null;
+        return true;
+    };
+
+    this.findMatchingSnippet = function(snippetList, before, after) {
+        for (var i = snippetList.length; i--;) {
+            var s = snippetList[i];
+            if (s.startRe && !s.startRe.test(before))
+                continue;
+            if (s.endRe && !s.endRe.test(after))
+                continue;
+            if (!s.startRe && !s.endRe)
+                continue;
+
+            s.matchBefore = s.startRe ? s.startRe.exec(before) : [""];
+            s.matchAfter = s.endRe ? s.endRe.exec(after) : [""];
+            s.replaceBefore = s.triggerRe ? s.triggerRe.exec(before)[0] : "";
+            s.replaceAfter = s.endTriggerRe ? s.endTriggerRe.exec(after)[0] : "";
+            return s;
+        }
+    };
+
+    this.snippetMap = {};
+    this.snippetNameMap = {};
+    this.register = function(snippets, scope) {
+        var snippetMap = this.snippetMap;
+        var snippetNameMap = this.snippetNameMap;
+        var self = this;
+        
+        if (!snippets) 
+            snippets = [];
+        
+        function wrapRegexp(src) {
+            if (src && !/^\^?\(.*\)\$?$|^\\b$/.test(src))
+                src = "(?:" + src + ")";
+
+            return src || "";
+        }
+        function guardedRegexp(re, guard, opening) {
+            re = wrapRegexp(re);
+            guard = wrapRegexp(guard);
+            if (opening) {
+                re = guard + re;
+                if (re && re[re.length - 1] != "$")
+                    re = re + "$";
+            } else {
+                re = re + guard;
+                if (re && re[0] != "^")
+                    re = "^" + re;
+            }
+            return new RegExp(re);
+        }
+
+        function addSnippet(s) {
+            if (!s.scope)
+                s.scope = scope || "_";
+            scope = s.scope;
+            if (!snippetMap[scope]) {
+                snippetMap[scope] = [];
+                snippetNameMap[scope] = {};
+            }
+
+            var map = snippetNameMap[scope];
+            if (s.name) {
+                var old = map[s.name];
+                if (old)
+                    self.unregister(old);
+                map[s.name] = s;
+            }
+            snippetMap[scope].push(s);
+
+            if (s.tabTrigger && !s.trigger) {
+                if (!s.guard && /^\w/.test(s.tabTrigger))
+                    s.guard = "\\b";
+                s.trigger = lang.escapeRegExp(s.tabTrigger);
+            }
+            
+            if (!s.trigger && !s.guard && !s.endTrigger && !s.endGuard)
+                return;
+            
+            s.startRe = guardedRegexp(s.trigger, s.guard, true);
+            s.triggerRe = new RegExp(s.trigger);
+
+            s.endRe = guardedRegexp(s.endTrigger, s.endGuard, true);
+            s.endTriggerRe = new RegExp(s.endTrigger);
+        }
+
+        if (snippets && snippets.content)
+            addSnippet(snippets);
+        else if (Array.isArray(snippets))
+            snippets.forEach(addSnippet);
+        
+        this._signal("registerSnippets", {scope: scope});
+    };
+    this.unregister = function(snippets, scope) {
+        var snippetMap = this.snippetMap;
+        var snippetNameMap = this.snippetNameMap;
+
+        function removeSnippet(s) {
+            var nameMap = snippetNameMap[s.scope||scope];
+            if (nameMap && nameMap[s.name]) {
+                delete nameMap[s.name];
+                var map = snippetMap[s.scope||scope];
+                var i = map && map.indexOf(s);
+                if (i >= 0)
+                    map.splice(i, 1);
+            }
+        }
+        if (snippets.content)
+            removeSnippet(snippets);
+        else if (Array.isArray(snippets))
+            snippets.forEach(removeSnippet);
+    };
+    this.parseSnippetFile = function(str) {
+        str = str.replace(/\r/g, "");
+        var list = [], snippet = {};
+        var re = /^#.*|^({[\s\S]*})\s*$|^(\S+) (.*)$|^((?:\n*\t.*)+)/gm;
+        var m;
+        while (m = re.exec(str)) {
+            if (m[1]) {
+                try {
+                    snippet = JSON.parse(m[1]);
+                    list.push(snippet);
+                } catch (e) {}
+            } if (m[4]) {
+                snippet.content = m[4].replace(/^\t/gm, "");
+                list.push(snippet);
+                snippet = {};
+            } else {
+                var key = m[2], val = m[3];
+                if (key == "regex") {
+                    var guardRe = /\/((?:[^\/\\]|\\.)*)|$/g;
+                    snippet.guard = guardRe.exec(val)[1];
+                    snippet.trigger = guardRe.exec(val)[1];
+                    snippet.endTrigger = guardRe.exec(val)[1];
+                    snippet.endGuard = guardRe.exec(val)[1];
+                } else if (key == "snippet") {
+                    snippet.tabTrigger = val.match(/^\S*/)[0];
+                    if (!snippet.name)
+                        snippet.name = val;
+                } else {
+                    snippet[key] = val;
+                }
+            }
+        }
+        return list;
+    };
+    this.getSnippetByName = function(name, editor) {
+        var snippetMap = this.snippetNameMap;
+        var snippet;
+        this.getActiveScopes(editor).some(function(scope) {
+            var snippets = snippetMap[scope];
+            if (snippets)
+                snippet = snippets[name];
+            return !!snippet;
+        }, this);
+        return snippet;
+    };
+
+}).call(SnippetManager.prototype);
+
+
+var TabstopManager = function(editor) {
+    if (editor.tabstopManager)
+        return editor.tabstopManager;
+    editor.tabstopManager = this;
+    this.$onChange = this.onChange.bind(this);
+    this.$onChangeSelection = lang.delayedCall(this.onChangeSelection.bind(this)).schedule;
+    this.$onChangeSession = this.onChangeSession.bind(this);
+    this.$onAfterExec = this.onAfterExec.bind(this);
+    this.attach(editor);
+};
+(function() {
+    this.attach = function(editor) {
+        this.index = 0;
+        this.ranges = [];
+        this.tabstops = [];
+        this.$openTabstops = null;
+        this.selectedTabstop = null;
+
+        this.editor = editor;
+        this.editor.on("change", this.$onChange);
+        this.editor.on("changeSelection", this.$onChangeSelection);
+        this.editor.on("changeSession", this.$onChangeSession);
+        this.editor.commands.on("afterExec", this.$onAfterExec);
+        this.editor.keyBinding.addKeyboardHandler(this.keyboardHandler);
+    };
+    this.detach = function() {
+        this.tabstops.forEach(this.removeTabstopMarkers, this);
+        this.ranges = null;
+        this.tabstops = null;
+        this.selectedTabstop = null;
+        this.editor.removeListener("change", this.$onChange);
+        this.editor.removeListener("changeSelection", this.$onChangeSelection);
+        this.editor.removeListener("changeSession", this.$onChangeSession);
+        this.editor.commands.removeListener("afterExec", this.$onAfterExec);
+        this.editor.keyBinding.removeKeyboardHandler(this.keyboardHandler);
+        this.editor.tabstopManager = null;
+        this.editor = null;
+    };
+
+    this.onChange = function(delta) {
+        var changeRange = delta;
+        var isRemove = delta.action[0] == "r";
+        var start = delta.start;
+        var end = delta.end;
+        var startRow = start.row;
+        var endRow = end.row;
+        var lineDif = endRow - startRow;
+        var colDiff = end.column - start.column;
+
+        if (isRemove) {
+            lineDif = -lineDif;
+            colDiff = -colDiff;
+        }
+        if (!this.$inChange && isRemove) {
+            var ts = this.selectedTabstop;
+            var changedOutside = ts && !ts.some(function(r) {
+                return comparePoints(r.start, start) <= 0 && comparePoints(r.end, end) >= 0;
+            });
+            if (changedOutside)
+                return this.detach();
+        }
+        var ranges = this.ranges;
+        for (var i = 0; i < ranges.length; i++) {
+            var r = ranges[i];
+            if (r.end.row < start.row)
+                continue;
+
+            if (isRemove && comparePoints(start, r.start) < 0 && comparePoints(end, r.end) > 0) {
+                this.removeRange(r);
+                i--;
+                continue;
+            }
+
+            if (r.start.row == startRow && r.start.column > start.column)
+                r.start.column += colDiff;
+            if (r.end.row == startRow && r.end.column >= start.column)
+                r.end.column += colDiff;
+            if (r.start.row >= startRow)
+                r.start.row += lineDif;
+            if (r.end.row >= startRow)
+                r.end.row += lineDif;
+
+            if (comparePoints(r.start, r.end) > 0)
+                this.removeRange(r);
+        }
+        if (!ranges.length)
+            this.detach();
+    };
+    this.updateLinkedFields = function() {
+        var ts = this.selectedTabstop;
+        if (!ts || !ts.hasLinkedRanges)
+            return;
+        this.$inChange = true;
+        var session = this.editor.session;
+        var text = session.getTextRange(ts.firstNonLinked);
+        for (var i = ts.length; i--;) {
+            var range = ts[i];
+            if (!range.linked)
+                continue;
+            var fmt = exports.snippetManager.tmStrFormat(text, range.original);
+            session.replace(range, fmt);
+        }
+        this.$inChange = false;
+    };
+    this.onAfterExec = function(e) {
+        if (e.command && !e.command.readOnly)
+            this.updateLinkedFields();
+    };
+    this.onChangeSelection = function() {
+        if (!this.editor)
+            return;
+        var lead = this.editor.selection.lead;
+        var anchor = this.editor.selection.anchor;
+        var isEmpty = this.editor.selection.isEmpty();
+        for (var i = this.ranges.length; i--;) {
+            if (this.ranges[i].linked)
+                continue;
+            var containsLead = this.ranges[i].contains(lead.row, lead.column);
+            var containsAnchor = isEmpty || this.ranges[i].contains(anchor.row, anchor.column);
+            if (containsLead && containsAnchor)
+                return;
+        }
+        this.detach();
+    };
+    this.onChangeSession = function() {
+        this.detach();
+    };
+    this.tabNext = function(dir) {
+        var max = this.tabstops.length;
+        var index = this.index + (dir || 1);
+        index = Math.min(Math.max(index, 1), max);
+        if (index == max)
+            index = 0;
+        this.selectTabstop(index);
+        if (index === 0)
+            this.detach();
+    };
+    this.selectTabstop = function(index) {
+        this.$openTabstops = null;
+        var ts = this.tabstops[this.index];
+        if (ts)
+            this.addTabstopMarkers(ts);
+        this.index = index;
+        ts = this.tabstops[this.index];
+        if (!ts || !ts.length)
+            return;
+        
+        this.selectedTabstop = ts;
+        if (!this.editor.inVirtualSelectionMode) {        
+            var sel = this.editor.multiSelect;
+            sel.toSingleRange(ts.firstNonLinked.clone());
+            for (var i = ts.length; i--;) {
+                if (ts.hasLinkedRanges && ts[i].linked)
+                    continue;
+                sel.addRange(ts[i].clone(), true);
+            }
+            if (sel.ranges[0])
+                sel.addRange(sel.ranges[0].clone());
+        } else {
+            this.editor.selection.setRange(ts.firstNonLinked);
+        }
+        
+        this.editor.keyBinding.addKeyboardHandler(this.keyboardHandler);
+    };
+    this.addTabstops = function(tabstops, start, end) {
+        if (!this.$openTabstops)
+            this.$openTabstops = [];
+        if (!tabstops[0]) {
+            var p = Range.fromPoints(end, end);
+            moveRelative(p.start, start);
+            moveRelative(p.end, start);
+            tabstops[0] = [p];
+            tabstops[0].index = 0;
+        }
+
+        var i = this.index;
+        var arg = [i + 1, 0];
+        var ranges = this.ranges;
+        tabstops.forEach(function(ts, index) {
+            var dest = this.$openTabstops[index] || ts;
+                
+            for (var i = ts.length; i--;) {
+                var p = ts[i];
+                var range = Range.fromPoints(p.start, p.end || p.start);
+                movePoint(range.start, start);
+                movePoint(range.end, start);
+                range.original = p;
+                range.tabstop = dest;
+                ranges.push(range);
+                if (dest != ts)
+                    dest.unshift(range);
+                else
+                    dest[i] = range;
+                if (p.fmtString) {
+                    range.linked = true;
+                    dest.hasLinkedRanges = true;
+                } else if (!dest.firstNonLinked)
+                    dest.firstNonLinked = range;
+            }
+            if (!dest.firstNonLinked)
+                dest.hasLinkedRanges = false;
+            if (dest === ts) {
+                arg.push(dest);
+                this.$openTabstops[index] = dest;
+            }
+            this.addTabstopMarkers(dest);
+        }, this);
+        
+        if (arg.length > 2) {
+            if (this.tabstops.length)
+                arg.push(arg.splice(2, 1)[0]);
+            this.tabstops.splice.apply(this.tabstops, arg);
+        }
+    };
+
+    this.addTabstopMarkers = function(ts) {
+        var session = this.editor.session;
+        ts.forEach(function(range) {
+            if  (!range.markerId)
+                range.markerId = session.addMarker(range, "ace_snippet-marker", "text");
+        });
+    };
+    this.removeTabstopMarkers = function(ts) {
+        var session = this.editor.session;
+        ts.forEach(function(range) {
+            session.removeMarker(range.markerId);
+            range.markerId = null;
+        });
+    };
+    this.removeRange = function(range) {
+        var i = range.tabstop.indexOf(range);
+        range.tabstop.splice(i, 1);
+        i = this.ranges.indexOf(range);
+        this.ranges.splice(i, 1);
+        this.editor.session.removeMarker(range.markerId);
+        if (!range.tabstop.length) {
+            i = this.tabstops.indexOf(range.tabstop);
+            if (i != -1)
+                this.tabstops.splice(i, 1);
+            if (!this.tabstops.length)
+                this.detach();
+        }
+    };
+
+    this.keyboardHandler = new HashHandler();
+    this.keyboardHandler.bindKeys({
+        "Tab": function(ed) {
+            if (exports.snippetManager && exports.snippetManager.expandWithTab(ed)) {
+                return;
+            }
+
+            ed.tabstopManager.tabNext(1);
+        },
+        "Shift-Tab": function(ed) {
+            ed.tabstopManager.tabNext(-1);
+        },
+        "Esc": function(ed) {
+            ed.tabstopManager.detach();
+        },
+        "Return": function(ed) {
+            return false;
+        }
+    });
+}).call(TabstopManager.prototype);
+
+
+
+var changeTracker = {};
+changeTracker.onChange = Anchor.prototype.onChange;
+changeTracker.setPosition = function(row, column) {
+    this.pos.row = row;
+    this.pos.column = column;
+};
+changeTracker.update = function(pos, delta, $insertRight) {
+    this.$insertRight = $insertRight;
+    this.pos = pos; 
+    this.onChange(delta);
+};
+
+var movePoint = function(point, diff) {
+    if (point.row == 0)
+        point.column += diff.column;
+    point.row += diff.row;
+};
+
+var moveRelative = function(point, start) {
+    if (point.row == start.row)
+        point.column -= start.column;
+    point.row -= start.row;
+};
+
+
+require("./lib/dom").importCssString("\
+.ace_snippet-marker {\
+    -moz-box-sizing: border-box;\
+    box-sizing: border-box;\
+    background: rgba(194, 193, 208, 0.09);\
+    border: 1px dotted rgba(211, 208, 235, 0.62);\
+    position: absolute;\
+}");
+
+exports.snippetManager = new SnippetManager();
+
+
+var Editor = require("./editor").Editor;
+(function() {
+    this.insertSnippet = function(content, options) {
+        return exports.snippetManager.insertSnippet(this, content, options);
+    };
+    this.expandSnippet = function(options) {
+        return exports.snippetManager.expandWithTab(this, options);
+    };
+}).call(Editor.prototype);
+
+});
+
+ace.define("ace/autocomplete/popup",[], function(require, exports, module) {
+"use strict";
+
+var Renderer = require("../virtual_renderer").VirtualRenderer;
+var Editor = require("../editor").Editor;
+var Range = require("../range").Range;
+var event = require("../lib/event");
+var lang = require("../lib/lang");
+var dom = require("../lib/dom");
+
+var $singleLineEditor = function(el) {
+    var renderer = new Renderer(el);
+
+    renderer.$maxLines = 4;
+
+    var editor = new Editor(renderer);
+
+    editor.setHighlightActiveLine(false);
+    editor.setShowPrintMargin(false);
+    editor.renderer.setShowGutter(false);
+    editor.renderer.setHighlightGutterLine(false);
+
+    editor.$mouseHandler.$focusTimeout = 0;
+    editor.$highlightTagPending = true;
+
+    return editor;
+};
+
+var AcePopup = function(parentNode) {
+    var el = dom.createElement("div");
+    var popup = new $singleLineEditor(el);
+
+    if (parentNode)
+        parentNode.appendChild(el);
+    el.style.display = "none";
+    popup.renderer.content.style.cursor = "default";
+    popup.renderer.setStyle("ace_autocomplete");
+
+    popup.setOption("displayIndentGuides", false);
+    popup.setOption("dragDelay", 150);
+
+    var noop = function(){};
+
+    popup.focus = noop;
+    popup.$isFocused = true;
+
+    popup.renderer.$cursorLayer.restartTimer = noop;
+    popup.renderer.$cursorLayer.element.style.opacity = 0;
+
+    popup.renderer.$maxLines = 8;
+    popup.renderer.$keepTextAreaAtCursor = false;
+
+    popup.setHighlightActiveLine(false);
+    popup.session.highlight("");
+    popup.session.$searchHighlight.clazz = "ace_highlight-marker";
+
+    popup.on("mousedown", function(e) {
+        var pos = e.getDocumentPosition();
+        popup.selection.moveToPosition(pos);
+        selectionMarker.start.row = selectionMarker.end.row = pos.row;
+        e.stop();
+    });
+
+    var lastMouseEvent;
+    var hoverMarker = new Range(-1,0,-1,Infinity);
+    var selectionMarker = new Range(-1,0,-1,Infinity);
+    selectionMarker.id = popup.session.addMarker(selectionMarker, "ace_active-line", "fullLine");
+    popup.setSelectOnHover = function(val) {
+        if (!val) {
+            hoverMarker.id = popup.session.addMarker(hoverMarker, "ace_line-hover", "fullLine");
+        } else if (hoverMarker.id) {
+            popup.session.removeMarker(hoverMarker.id);
+            hoverMarker.id = null;
+        }
+    };
+    popup.setSelectOnHover(false);
+    popup.on("mousemove", function(e) {
+        if (!lastMouseEvent) {
+            lastMouseEvent = e;
+            return;
+        }
+        if (lastMouseEvent.x == e.x && lastMouseEvent.y == e.y) {
+            return;
+        }
+        lastMouseEvent = e;
+        lastMouseEvent.scrollTop = popup.renderer.scrollTop;
+        var row = lastMouseEvent.getDocumentPosition().row;
+        if (hoverMarker.start.row != row) {
+            if (!hoverMarker.id)
+                popup.setRow(row);
+            setHoverMarker(row);
+        }
+    });
+    popup.renderer.on("beforeRender", function() {
+        if (lastMouseEvent && hoverMarker.start.row != -1) {
+            lastMouseEvent.$pos = null;
+            var row = lastMouseEvent.getDocumentPosition().row;
+            if (!hoverMarker.id)
+                popup.setRow(row);
+            setHoverMarker(row, true);
+        }
+    });
+    popup.renderer.on("afterRender", function() {
+        var row = popup.getRow();
+        var t = popup.renderer.$textLayer;
+        var selected = t.element.childNodes[row - t.config.firstRow];
+        if (selected !== t.selectedNode && t.selectedNode)
+            dom.removeCssClass(t.selectedNode, "ace_selected");
+        t.selectedNode = selected;
+        if (selected)
+            dom.addCssClass(selected, "ace_selected");
+    });
+    var hideHoverMarker = function() { setHoverMarker(-1); };
+    var setHoverMarker = function(row, suppressRedraw) {
+        if (row !== hoverMarker.start.row) {
+            hoverMarker.start.row = hoverMarker.end.row = row;
+            if (!suppressRedraw)
+                popup.session._emit("changeBackMarker");
+            popup._emit("changeHoverMarker");
+        }
+    };
+    popup.getHoveredRow = function() {
+        return hoverMarker.start.row;
+    };
+
+    event.addListener(popup.container, "mouseout", hideHoverMarker);
+    popup.on("hide", hideHoverMarker);
+    popup.on("changeSelection", hideHoverMarker);
+
+    popup.session.doc.getLength = function() {
+        return popup.data.length;
+    };
+    popup.session.doc.getLine = function(i) {
+        var data = popup.data[i];
+        if (typeof data == "string")
+            return data;
+        return (data && data.value) || "";
+    };
+
+    var bgTokenizer = popup.session.bgTokenizer;
+    bgTokenizer.$tokenizeRow = function(row) {
+        var data = popup.data[row];
+        var tokens = [];
+        if (!data)
+            return tokens;
+        if (typeof data == "string")
+            data = {value: data};
+        var caption = data.caption || data.value || data.name;
+
+        function addToken(value, className) {
+            value && tokens.push({
+                type: (data.className || "") + (className || ""), 
+                value: value
+            });
+        }
+        
+        var lower = caption.toLowerCase();
+        var filterText = (popup.filterText || "").toLowerCase();
+        var lastIndex = 0;
+        var lastI = 0;
+        for (var i = 0; i <= filterText.length; i++) {
+            if (i != lastI && (data.matchMask & (1 << i) || i == filterText.length)) {
+                var sub = filterText.slice(lastI, i);
+                lastI = i;
+                var index = lower.indexOf(sub, lastIndex);
+                if (index == -1) continue;
+                addToken(caption.slice(lastIndex, index), "");
+                lastIndex = index + sub.length;
+                addToken(caption.slice(index, lastIndex), "completion-highlight");
+            }
+        }
+        addToken(caption.slice(lastIndex, caption.length), "");
+        
+        if (data.meta)
+            tokens.push({type: "completion-meta", value: data.meta});
+
+        return tokens;
+    };
+    bgTokenizer.$updateOnChange = noop;
+    bgTokenizer.start = noop;
+
+    popup.session.$computeWidth = function() {
+        return this.screenWidth = 0;
+    };
+    popup.isOpen = false;
+    popup.isTopdown = false;
+    popup.autoSelect = true;
+    popup.filterText = "";
+
+    popup.data = [];
+    popup.setData = function(list, filterText) {
+        popup.filterText = filterText || "";
+        popup.setValue(lang.stringRepeat("\n", list.length), -1);
+        popup.data = list || [];
+        popup.setRow(0);
+    };
+    popup.getData = function(row) {
+        return popup.data[row];
+    };
+
+    popup.getRow = function() {
+        return selectionMarker.start.row;
+    };
+    popup.setRow = function(line) {
+        line = Math.max(this.autoSelect ? 0 : -1, Math.min(this.data.length, line));
+        if (selectionMarker.start.row != line) {
+            popup.selection.clearSelection();
+            selectionMarker.start.row = selectionMarker.end.row = line || 0;
+            popup.session._emit("changeBackMarker");
+            popup.moveCursorTo(line || 0, 0);
+            if (popup.isOpen)
+                popup._signal("select");
+        }
+    };
+
+    popup.on("changeSelection", function() {
+        if (popup.isOpen)
+            popup.setRow(popup.selection.lead.row);
+        popup.renderer.scrollCursorIntoView();
+    });
+
+    popup.hide = function() {
+        this.container.style.display = "none";
+        this._signal("hide");
+        popup.isOpen = false;
+    };
+    popup.show = function(pos, lineHeight, topdownOnly) {
+        var el = this.container;
+        var screenHeight = window.innerHeight;
+        var screenWidth = window.innerWidth;
+        var renderer = this.renderer;
+        var maxH = renderer.$maxLines * lineHeight * 1.4;
+        var top = pos.top + this.$borderSize;
+        var allowTopdown = top > screenHeight / 2 && !topdownOnly;
+        if (allowTopdown && top + lineHeight + maxH > screenHeight) {
+            renderer.$maxPixelHeight = top - 2 * this.$borderSize;
+            el.style.top = "";
+            el.style.bottom = screenHeight - top + "px";
+            popup.isTopdown = false;
+        } else {
+            top += lineHeight;
+            renderer.$maxPixelHeight = screenHeight - top - 0.2 * lineHeight;
+            el.style.top = top + "px";
+            el.style.bottom = "";
+            popup.isTopdown = true;
+        }
+
+        el.style.display = "";
+
+        var left = pos.left;
+        if (left + el.offsetWidth > screenWidth)
+            left = screenWidth - el.offsetWidth;
+
+        el.style.left = left + "px";
+
+        this._signal("show");
+        lastMouseEvent = null;
+        popup.isOpen = true;
+    };
+
+    popup.getTextLeftOffset = function() {
+        return this.$borderSize + this.renderer.$padding + this.$imageSize;
+    };
+
+    popup.$imageSize = 0;
+    popup.$borderSize = 1;
+
+    return popup;
+};
+
+dom.importCssString("\
+.ace_editor.ace_autocomplete .ace_marker-layer .ace_active-line {\
+    background-color: #CAD6FA;\
+    z-index: 1;\
+}\
+.ace_dark.ace_editor.ace_autocomplete .ace_marker-layer .ace_active-line {\
+    background-color: #3a674e;\
+}\
+.ace_editor.ace_autocomplete .ace_line-hover {\
+    border: 1px solid #abbffe;\
+    margin-top: -1px;\
+    background: rgba(233,233,253,0.4);\
+    position: absolute;\
+    z-index: 2;\
+}\
+.ace_dark.ace_editor.ace_autocomplete .ace_line-hover {\
+    border: 1px solid rgba(109, 150, 13, 0.8);\
+    background: rgba(58, 103, 78, 0.62);\
+}\
+.ace_completion-meta {\
+    opacity: 0.5;\
+    margin: 0.9em;\
+}\
+.ace_editor.ace_autocomplete .ace_completion-highlight{\
+    color: #2d69c7;\
+}\
+.ace_dark.ace_editor.ace_autocomplete .ace_completion-highlight{\
+    color: #93ca12;\
+}\
+.ace_editor.ace_autocomplete {\
+    width: 300px;\
+    z-index: 200000;\
+    border: 1px lightgray solid;\
+    position: fixed;\
+    box-shadow: 2px 3px 5px rgba(0,0,0,.2);\
+    line-height: 1.4;\
+    background: #fefefe;\
+    color: #111;\
+}\
+.ace_dark.ace_editor.ace_autocomplete {\
+    border: 1px #484747 solid;\
+    box-shadow: 2px 3px 5px rgba(0, 0, 0, 0.51);\
+    line-height: 1.4;\
+    background: #25282c;\
+    color: #c1c1c1;\
+}", "autocompletion.css");
+
+exports.AcePopup = AcePopup;
+
+});
+
+ace.define("ace/autocomplete/util",[], function(require, exports, module) {
+"use strict";
+
+exports.parForEach = function(array, fn, callback) {
+    var completed = 0;
+    var arLength = array.length;
+    if (arLength === 0)
+        callback();
+    for (var i = 0; i < arLength; i++) {
+        fn(array[i], function(result, err) {
+            completed++;
+            if (completed === arLength)
+                callback(result, err);
+        });
+    }
+};
+
+var ID_REGEX = /[a-zA-Z_0-9\$\-\u00A2-\uFFFF]/;
+
+exports.retrievePrecedingIdentifier = function(text, pos, regex) {
+    regex = regex || ID_REGEX;
+    var buf = [];
+    for (var i = pos-1; i >= 0; i--) {
+        if (regex.test(text[i]))
+            buf.push(text[i]);
+        else
+            break;
+    }
+    return buf.reverse().join("");
+};
+
+exports.retrieveFollowingIdentifier = function(text, pos, regex) {
+    regex = regex || ID_REGEX;
+    var buf = [];
+    for (var i = pos; i < text.length; i++) {
+        if (regex.test(text[i]))
+            buf.push(text[i]);
+        else
+            break;
+    }
+    return buf;
+};
+
+exports.getCompletionPrefix = function (editor) {
+    var pos = editor.getCursorPosition();
+    var line = editor.session.getLine(pos.row);
+    var prefix;
+    editor.completers.forEach(function(completer) {
+        if (completer.identifierRegexps) {
+            completer.identifierRegexps.forEach(function(identifierRegex) {
+                if (!prefix && identifierRegex)
+                    prefix = this.retrievePrecedingIdentifier(line, pos.column, identifierRegex);
+            }.bind(this));
+        }
+    }.bind(this));
+    return prefix || this.retrievePrecedingIdentifier(line, pos.column);
+};
+
+});
+
+ace.define("ace/autocomplete",[], function(require, exports, module) {
+"use strict";
+
+var HashHandler = require("./keyboard/hash_handler").HashHandler;
+var AcePopup = require("./autocomplete/popup").AcePopup;
+var util = require("./autocomplete/util");
+var event = require("./lib/event");
+var lang = require("./lib/lang");
+var dom = require("./lib/dom");
+var snippetManager = require("./snippets").snippetManager;
+
+var Autocomplete = function() {
+    this.autoInsert = false;
+    this.autoSelect = true;
+    this.exactMatch = false;
+    this.gatherCompletionsId = 0;
+    this.keyboardHandler = new HashHandler();
+    this.keyboardHandler.bindKeys(this.commands);
+
+    this.blurListener = this.blurListener.bind(this);
+    this.changeListener = this.changeListener.bind(this);
+    this.mousedownListener = this.mousedownListener.bind(this);
+    this.mousewheelListener = this.mousewheelListener.bind(this);
+
+    this.changeTimer = lang.delayedCall(function() {
+        this.updateCompletions(true);
+    }.bind(this));
+
+    this.tooltipTimer = lang.delayedCall(this.updateDocTooltip.bind(this), 50);
+};
+
+(function() {
+
+    this.$init = function() {
+        this.popup = new AcePopup(document.body || document.documentElement);
+        this.popup.on("click", function(e) {
+            this.insertMatch();
+            e.stop();
+        }.bind(this));
+        this.popup.focus = this.editor.focus.bind(this.editor);
+        this.popup.on("show", this.tooltipTimer.bind(null, null));
+        this.popup.on("select", this.tooltipTimer.bind(null, null));
+        this.popup.on("changeHoverMarker", this.tooltipTimer.bind(null, null));
+        return this.popup;
+    };
+
+    this.getPopup = function() {
+        return this.popup || this.$init();
+    };
+
+    this.openPopup = function(editor, prefix, keepPopupPosition) {
+        if (!this.popup)
+            this.$init();
+
+        this.popup.autoSelect = this.autoSelect;
+
+        this.popup.setData(this.completions.filtered, this.completions.filterText);
+
+        editor.keyBinding.addKeyboardHandler(this.keyboardHandler);
+        
+        var renderer = editor.renderer;
+        this.popup.setRow(this.autoSelect ? 0 : -1);
+        if (!keepPopupPosition) {
+            this.popup.setTheme(editor.getTheme());
+            this.popup.setFontSize(editor.getFontSize());
+
+            var lineHeight = renderer.layerConfig.lineHeight;
+
+            var pos = renderer.$cursorLayer.getPixelPosition(this.base, true);
+            pos.left -= this.popup.getTextLeftOffset();
+
+            var rect = editor.container.getBoundingClientRect();
+            pos.top += rect.top - renderer.layerConfig.offset;
+            pos.left += rect.left - editor.renderer.scrollLeft;
+            pos.left += renderer.gutterWidth;
+
+            this.popup.show(pos, lineHeight);
+        } else if (keepPopupPosition && !prefix) {
+            this.detach();
+        }
+    };
+
+    this.detach = function() {
+        this.editor.keyBinding.removeKeyboardHandler(this.keyboardHandler);
+        this.editor.off("changeSelection", this.changeListener);
+        this.editor.off("blur", this.blurListener);
+        this.editor.off("mousedown", this.mousedownListener);
+        this.editor.off("mousewheel", this.mousewheelListener);
+        this.changeTimer.cancel();
+        this.hideDocTooltip();
+
+        this.gatherCompletionsId += 1;
+        if (this.popup && this.popup.isOpen)
+            this.popup.hide();
+
+        if (this.base)
+            this.base.detach();
+        this.activated = false;
+        this.completions = this.base = null;
+    };
+
+    this.changeListener = function(e) {
+        var cursor = this.editor.selection.lead;
+        if (cursor.row != this.base.row || cursor.column < this.base.column) {
+            this.detach();
+        }
+        if (this.activated)
+            this.changeTimer.schedule();
+        else
+            this.detach();
+    };
+
+    this.blurListener = function(e) {
+        var el = document.activeElement;
+        var text = this.editor.textInput.getElement();
+        var fromTooltip = e.relatedTarget && this.tooltipNode && this.tooltipNode.contains(e.relatedTarget);
+        var container = this.popup && this.popup.container;
+        if (el != text && el.parentNode != container && !fromTooltip
+            && el != this.tooltipNode && e.relatedTarget != text
+        ) {
+            this.detach();
+        }
+    };
+
+    this.mousedownListener = function(e) {
+        this.detach();
+    };
+
+    this.mousewheelListener = function(e) {
+        this.detach();
+    };
+
+    this.goTo = function(where) {
+        var row = this.popup.getRow();
+        var max = this.popup.session.getLength() - 1;
+
+        switch(where) {
+            case "up": row = row <= 0 ? max : row - 1; break;
+            case "down": row = row >= max ? -1 : row + 1; break;
+            case "start": row = 0; break;
+            case "end": row = max; break;
+        }
+
+        this.popup.setRow(row);
+    };
+
+    this.insertMatch = function(data, options) {
+        if (!data)
+            data = this.popup.getData(this.popup.getRow());
+        if (!data)
+            return false;
+
+        if (data.completer && data.completer.insertMatch) {
+            data.completer.insertMatch(this.editor, data);
+        } else {
+            if (this.completions.filterText) {
+                var ranges = this.editor.selection.getAllRanges();
+                for (var i = 0, range; range = ranges[i]; i++) {
+                    range.start.column -= this.completions.filterText.length;
+                    this.editor.session.remove(range);
+                }
+            }
+            if (data.snippet)
+                snippetManager.insertSnippet(this.editor, data.snippet);
+            else
+                this.editor.execCommand("insertstring", data.value || data);
+        }
+        this.detach();
+    };
+
+
+    this.commands = {
+        "Up": function(editor) { editor.completer.goTo("up"); },
+        "Down": function(editor) { editor.completer.goTo("down"); },
+        "Ctrl-Up|Ctrl-Home": function(editor) { editor.completer.goTo("start"); },
+        "Ctrl-Down|Ctrl-End": function(editor) { editor.completer.goTo("end"); },
+
+        "Esc": function(editor) { editor.completer.detach(); },
+        "Return": function(editor) { return editor.completer.insertMatch(); },
+        "Shift-Return": function(editor) { editor.completer.insertMatch(null, {deleteSuffix: true}); },
+        "Tab": function(editor) {
+            var result = editor.completer.insertMatch();
+            if (!result && !editor.tabstopManager)
+                editor.completer.goTo("down");
+            else
+                return result;
+        },
+
+        "PageUp": function(editor) { editor.completer.popup.gotoPageUp(); },
+        "PageDown": function(editor) { editor.completer.popup.gotoPageDown(); }
+    };
+
+    this.gatherCompletions = function(editor, callback) {
+        var session = editor.getSession();
+        var pos = editor.getCursorPosition();
+
+        var prefix = util.getCompletionPrefix(editor);
+
+        this.base = session.doc.createAnchor(pos.row, pos.column - prefix.length);
+        this.base.$insertRight = true;
+
+        var matches = [];
+        var total = editor.completers.length;
+        editor.completers.forEach(function(completer, i) {
+            completer.getCompletions(editor, session, pos, prefix, function(err, results) {
+                if (!err && results)
+                    matches = matches.concat(results);
+                callback(null, {
+                    prefix: util.getCompletionPrefix(editor),
+                    matches: matches,
+                    finished: (--total === 0)
+                });
+            });
+        });
+        return true;
+    };
+
+    this.showPopup = function(editor) {
+        if (this.editor)
+            this.detach();
+
+        this.activated = true;
+
+        this.editor = editor;
+        if (editor.completer != this) {
+            if (editor.completer)
+                editor.completer.detach();
+            editor.completer = this;
+        }
+
+        editor.on("changeSelection", this.changeListener);
+        editor.on("blur", this.blurListener);
+        editor.on("mousedown", this.mousedownListener);
+        editor.on("mousewheel", this.mousewheelListener);
+
+        this.updateCompletions();
+    };
+
+    this.updateCompletions = function(keepPopupPosition) {
+        if (keepPopupPosition && this.base && this.completions) {
+            var pos = this.editor.getCursorPosition();
+            var prefix = this.editor.session.getTextRange({start: this.base, end: pos});
+            if (prefix == this.completions.filterText)
+                return;
+            this.completions.setFilter(prefix);
+            if (!this.completions.filtered.length)
+                return this.detach();
+            if (this.completions.filtered.length == 1
+            && this.completions.filtered[0].value == prefix
+            && !this.completions.filtered[0].snippet)
+                return this.detach();
+            this.openPopup(this.editor, prefix, keepPopupPosition);
+            return;
+        }
+        var _id = this.gatherCompletionsId;
+        this.gatherCompletions(this.editor, function(err, results) {
+            var detachIfFinished = function() {
+                if (!results.finished) return;
+                return this.detach();
+            }.bind(this);
+
+            var prefix = results.prefix;
+            var matches = results && results.matches;
+
+            if (!matches || !matches.length)
+                return detachIfFinished();
+            if (prefix.indexOf(results.prefix) !== 0 || _id != this.gatherCompletionsId)
+                return;
+
+            this.completions = new FilteredList(matches);
+
+            if (this.exactMatch)
+                this.completions.exactMatch = true;
+
+            this.completions.setFilter(prefix);
+            var filtered = this.completions.filtered;
+            if (!filtered.length)
+                return detachIfFinished();
+            if (filtered.length == 1 && filtered[0].value == prefix && !filtered[0].snippet)
+                return detachIfFinished();
+            if (this.autoInsert && filtered.length == 1 && results.finished)
+                return this.insertMatch(filtered[0]);
+
+            this.openPopup(this.editor, prefix, keepPopupPosition);
+        }.bind(this));
+    };
+
+    this.cancelContextMenu = function() {
+        this.editor.$mouseHandler.cancelContextMenu();
+    };
+
+    this.updateDocTooltip = function() {
+        var popup = this.popup;
+        var all = popup.data;
+        var selected = all && (all[popup.getHoveredRow()] || all[popup.getRow()]);
+        var doc = null;
+        if (!selected || !this.editor || !this.popup.isOpen)
+            return this.hideDocTooltip();
+        this.editor.completers.some(function(completer) {
+            if (completer.getDocTooltip)
+                doc = completer.getDocTooltip(selected);
+            return doc;
+        });
+        if (!doc)
+            doc = selected;
+
+        if (typeof doc == "string")
+            doc = {docText: doc};
+        if (!doc || !(doc.docHTML || doc.docText))
+            return this.hideDocTooltip();
+        this.showDocTooltip(doc);
+    };
+
+    this.showDocTooltip = function(item) {
+        if (!this.tooltipNode) {
+            this.tooltipNode = dom.createElement("div");
+            this.tooltipNode.className = "ace_tooltip ace_doc-tooltip";
+            this.tooltipNode.style.margin = 0;
+            this.tooltipNode.style.pointerEvents = "auto";
+            this.tooltipNode.tabIndex = -1;
+            this.tooltipNode.onblur = this.blurListener.bind(this);
+            this.tooltipNode.onclick = this.onTooltipClick.bind(this);
+        }
+
+        var tooltipNode = this.tooltipNode;
+        if (item.docHTML) {
+            tooltipNode.innerHTML = item.docHTML;
+        } else if (item.docText) {
+            tooltipNode.textContent = item.docText;
+        }
+
+        if (!tooltipNode.parentNode)
+            document.body.appendChild(tooltipNode);
+        var popup = this.popup;
+        var rect = popup.container.getBoundingClientRect();
+        tooltipNode.style.top = popup.container.style.top;
+        tooltipNode.style.bottom = popup.container.style.bottom;
+
+        tooltipNode.style.display = "block";
+        if (window.innerWidth - rect.right < 320) {
+            if (rect.left < 320) {
+                if(popup.isTopdown) {
+                    tooltipNode.style.top = rect.bottom + "px";
+                    tooltipNode.style.left = rect.left + "px";
+                    tooltipNode.style.right = "";
+                    tooltipNode.style.bottom = "";
+                } else {
+                    tooltipNode.style.top = popup.container.offsetTop - tooltipNode.offsetHeight + "px";
+                    tooltipNode.style.left = rect.left + "px";
+                    tooltipNode.style.right = "";
+                    tooltipNode.style.bottom = "";
+                }
+            } else {
+                tooltipNode.style.right = window.innerWidth - rect.left + "px";
+                tooltipNode.style.left = "";
+            }
+        } else {
+            tooltipNode.style.left = (rect.right + 1) + "px";
+            tooltipNode.style.right = "";
+        }
+    };
+
+    this.hideDocTooltip = function() {
+        this.tooltipTimer.cancel();
+        if (!this.tooltipNode) return;
+        var el = this.tooltipNode;
+        if (!this.editor.isFocused() && document.activeElement == el)
+            this.editor.focus();
+        this.tooltipNode = null;
+        if (el.parentNode)
+            el.parentNode.removeChild(el);
+    };
+    
+    this.onTooltipClick = function(e) {
+        var a = e.target;
+        while (a && a != this.tooltipNode) {
+            if (a.nodeName == "A" && a.href) {
+                a.rel = "noreferrer";
+                a.target = "_blank";
+                break;
+            }
+            a = a.parentNode;
+        }
+    };
+
+}).call(Autocomplete.prototype);
+
+Autocomplete.startCommand = {
+    name: "startAutocomplete",
+    exec: function(editor) {
+        if (!editor.completer)
+            editor.completer = new Autocomplete();
+        editor.completer.autoInsert = false;
+        editor.completer.autoSelect = true;
+        editor.completer.showPopup(editor);
+        editor.completer.cancelContextMenu();
+    },
+    bindKey: "Ctrl-Space|Ctrl-Shift-Space|Alt-Space"
+};
+
+var FilteredList = function(array, filterText) {
+    this.all = array;
+    this.filtered = array;
+    this.filterText = filterText || "";
+    this.exactMatch = false;
+};
+(function(){
+    this.setFilter = function(str) {
+        if (str.length > this.filterText && str.lastIndexOf(this.filterText, 0) === 0)
+            var matches = this.filtered;
+        else
+            var matches = this.all;
+
+        this.filterText = str;
+        matches = this.filterCompletions(matches, this.filterText);
+        matches = matches.sort(function(a, b) {
+            return b.exactMatch - a.exactMatch || b.$score - a.$score 
+                || (a.caption || a.value) < (b.caption || b.value);
+        });
+        var prev = null;
+        matches = matches.filter(function(item){
+            var caption = item.snippet || item.caption || item.value;
+            if (caption === prev) return false;
+            prev = caption;
+            return true;
+        });
+
+        this.filtered = matches;
+    };
+    this.filterCompletions = function(items, needle) {
+        var results = [];
+        var upper = needle.toUpperCase();
+        var lower = needle.toLowerCase();
+        loop: for (var i = 0, item; item = items[i]; i++) {
+            var caption = item.caption || item.value || item.snippet;
+            if (!caption) continue;
+            var lastIndex = -1;
+            var matchMask = 0;
+            var penalty = 0;
+            var index, distance;
+
+            if (this.exactMatch) {
+                if (needle !== caption.substr(0, needle.length))
+                    continue loop;
+            } else {
+                var fullMatchIndex = caption.toLowerCase().indexOf(lower);
+                if (fullMatchIndex > -1) {
+                    penalty = fullMatchIndex;
+                } else {
+                    for (var j = 0; j < needle.length; j++) {
+                        var i1 = caption.indexOf(lower[j], lastIndex + 1);
+                        var i2 = caption.indexOf(upper[j], lastIndex + 1);
+                        index = (i1 >= 0) ? ((i2 < 0 || i1 < i2) ? i1 : i2) : i2;
+                        if (index < 0)
+                            continue loop;
+                        distance = index - lastIndex - 1;
+                        if (distance > 0) {
+                            if (lastIndex === -1)
+                                penalty += 10;
+                            penalty += distance;
+                            matchMask = matchMask | (1 << j);
+                        }
+                        lastIndex = index;
+                    }
+                }
+            }
+            item.matchMask = matchMask;
+            item.exactMatch = penalty ? 0 : 1;
+            item.$score = (item.score || 0) - penalty;
+            results.push(item);
+        }
+        return results;
+    };
+}).call(FilteredList.prototype);
+
+exports.Autocomplete = Autocomplete;
+exports.FilteredList = FilteredList;
+
+});
+
+ace.define("ace/autocomplete/text_completer",[], function(require, exports, module) {
+    var Range = require("../range").Range;
+    
+    var splitRegex = /[^a-zA-Z_0-9\$\-\u00C0-\u1FFF\u2C00-\uD7FF\w]+/;
+
+    function getWordIndex(doc, pos) {
+        var textBefore = doc.getTextRange(Range.fromPoints({row: 0, column:0}, pos));
+        return textBefore.split(splitRegex).length - 1;
+    }
+    function wordDistance(doc, pos) {
+        var prefixPos = getWordIndex(doc, pos);
+        var words = doc.getValue().split(splitRegex);
+        var wordScores = Object.create(null);
+        
+        var currentWord = words[prefixPos];
+
+        words.forEach(function(word, idx) {
+            if (!word || word === currentWord) return;
+
+            var distance = Math.abs(prefixPos - idx);
+            var score = words.length - distance;
+            if (wordScores[word]) {
+                wordScores[word] = Math.max(score, wordScores[word]);
+            } else {
+                wordScores[word] = score;
+            }
+        });
+        return wordScores;
+    }
+
+    exports.getCompletions = function(editor, session, pos, prefix, callback) {
+        var wordScore = wordDistance(session, pos);
+        var wordList = Object.keys(wordScore);
+        callback(null, wordList.map(function(word) {
+            return {
+                caption: word,
+                value: word,
+                score: wordScore[word],
+                meta: "local"
+            };
+        }));
+    };
+});
+
+ace.define("ace/ext/language_tools",[], function(require, exports, module) {
+"use strict";
+
+var snippetManager = require("../snippets").snippetManager;
+var Autocomplete = require("../autocomplete").Autocomplete;
+var config = require("../config");
+var lang = require("../lib/lang");
+var util = require("../autocomplete/util");
+
+var textCompleter = require("../autocomplete/text_completer");
+var keyWordCompleter = {
+    getCompletions: function(editor, session, pos, prefix, callback) {
+        if (session.$mode.completer) {
+            return session.$mode.completer.getCompletions(editor, session, pos, prefix, callback);
+        }
+        var state = editor.session.getState(pos.row);
+        var completions = session.$mode.getCompletions(state, session, pos, prefix);
+        callback(null, completions);
+    }
+};
+
+var snippetCompleter = {
+    getCompletions: function(editor, session, pos, prefix, callback) {
+        var scopes = [];
+        var token = session.getTokenAt(pos.row, pos.column);
+        if (token && token.type.match(/(tag-name|tag-open|tag-whitespace|attribute-name|attribute-value)\.xml$/))
+            scopes.push('html-tag');
+        else
+            scopes = snippetManager.getActiveScopes(editor);
+
+        var snippetMap = snippetManager.snippetMap;
+        var completions = [];
+        scopes.forEach(function(scope) {
+            var snippets = snippetMap[scope] || [];
+            for (var i = snippets.length; i--;) {
+                var s = snippets[i];
+                var caption = s.name || s.tabTrigger;
+                if (!caption)
+                    continue;
+                completions.push({
+                    caption: caption,
+                    snippet: s.content,
+                    meta: s.tabTrigger && !s.name ? s.tabTrigger + "\u21E5 " : "snippet",
+                    type: "snippet"
+                });
+            }
+        }, this);
+        callback(null, completions);
+    },
+    getDocTooltip: function(item) {
+        if (item.type == "snippet" && !item.docHTML) {
+            item.docHTML = [
+                "<b>", lang.escapeHTML(item.caption), "</b>", "<hr></hr>",
+                lang.escapeHTML(item.snippet)
+            ].join("");
+        }
+    }
+};
+
+var completers = [snippetCompleter, textCompleter, keyWordCompleter];
+exports.setCompleters = function(val) {
+    completers.length = 0;
+    if (val) completers.push.apply(completers, val);
+};
+exports.addCompleter = function(completer) {
+    completers.push(completer);
+};
+exports.textCompleter = textCompleter;
+exports.keyWordCompleter = keyWordCompleter;
+exports.snippetCompleter = snippetCompleter;
+
+var expandSnippet = {
+    name: "expandSnippet",
+    exec: function(editor) {
+        return snippetManager.expandWithTab(editor);
+    },
+    bindKey: "Tab"
+};
+
+var onChangeMode = function(e, editor) {
+    loadSnippetsForMode(editor.session.$mode);
+};
+
+var loadSnippetsForMode = function(mode) {
+    var id = mode.$id;
+    if (!snippetManager.files)
+        snippetManager.files = {};
+    loadSnippetFile(id);
+    if (mode.modes)
+        mode.modes.forEach(loadSnippetsForMode);
+};
+
+var loadSnippetFile = function(id) {
+    if (!id || snippetManager.files[id])
+        return;
+    var snippetFilePath = id.replace("mode", "snippets");
+    snippetManager.files[id] = {};
+    config.loadModule(snippetFilePath, function(m) {
+        if (m) {
+            snippetManager.files[id] = m;
+            if (!m.snippets && m.snippetText)
+                m.snippets = snippetManager.parseSnippetFile(m.snippetText);
+            snippetManager.register(m.snippets || [], m.scope);
+            if (m.includeScopes) {
+                snippetManager.snippetMap[m.scope].includeScopes = m.includeScopes;
+                m.includeScopes.forEach(function(x) {
+                    loadSnippetFile("ace/mode/" + x);
+                });
+            }
+        }
+    });
+};
+
+var doLiveAutocomplete = function(e) {
+    var editor = e.editor;
+    var hasCompleter = editor.completer && editor.completer.activated;
+    if (e.command.name === "backspace") {
+        if (hasCompleter && !util.getCompletionPrefix(editor))
+            editor.completer.detach();
+    }
+    else if (e.command.name === "insertstring") {
+        var prefix = util.getCompletionPrefix(editor);
+        if (prefix && !hasCompleter) {
+            if (!editor.completer) {
+                editor.completer = new Autocomplete();
+            }
+            editor.completer.autoInsert = false;
+            editor.completer.showPopup(editor);
+        }
+    }
+};
+
+var Editor = require("../editor").Editor;
+require("../config").defineOptions(Editor.prototype, "editor", {
+    enableBasicAutocompletion: {
+        set: function(val) {
+            if (val) {
+                if (!this.completers)
+                    this.completers = Array.isArray(val)? val: completers;
+                this.commands.addCommand(Autocomplete.startCommand);
+            } else {
+                this.commands.removeCommand(Autocomplete.startCommand);
+            }
+        },
+        value: false
+    },
+    enableLiveAutocompletion: {
+        set: function(val) {
+            if (val) {
+                if (!this.completers)
+                    this.completers = Array.isArray(val)? val: completers;
+                this.commands.on('afterExec', doLiveAutocomplete);
+            } else {
+                this.commands.removeListener('afterExec', doLiveAutocomplete);
+            }
+        },
+        value: false
+    },
+    enableSnippets: {
+        set: function(val) {
+            if (val) {
+                this.commands.addCommand(expandSnippet);
+                this.on("changeMode", onChangeMode);
+                onChangeMode(null, this);
+            } else {
+                this.commands.removeCommand(expandSnippet);
+                this.off("changeMode", onChangeMode);
+            }
+        },
+        value: false
+    }
+});
+});
+                (function() {
+                    ace.require(["ace/ext/language_tools"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 65 - 0
services/web/public/js/ace-1.4.3/ext-linking.js

@@ -0,0 +1,65 @@
+ace.define("ace/ext/linking",[], function(require, exports, module) {
+
+var Editor = require("ace/editor").Editor;
+
+require("../config").defineOptions(Editor.prototype, "editor", {
+    enableLinking: {
+        set: function(val) {
+            if (val) {
+                this.on("click", onClick);
+                this.on("mousemove", onMouseMove);
+            } else {
+                this.off("click", onClick);
+                this.off("mousemove", onMouseMove);
+            }
+        },
+        value: false
+    }
+});
+
+exports.previousLinkingHover = false;
+
+function onMouseMove(e) {
+    var editor = e.editor;
+    var ctrl = e.getAccelKey();
+
+    if (ctrl) {
+        var editor = e.editor;
+        var docPos = e.getDocumentPosition();
+        var session = editor.session;
+        var token = session.getTokenAt(docPos.row, docPos.column);
+
+        if (exports.previousLinkingHover && exports.previousLinkingHover != token) {
+            editor._emit("linkHoverOut");
+        }
+        editor._emit("linkHover", {position: docPos, token: token});
+        exports.previousLinkingHover = token;
+    } else if (exports.previousLinkingHover) {
+        editor._emit("linkHoverOut");
+        exports.previousLinkingHover = false;
+    }
+}
+
+function onClick(e) {
+    var ctrl = e.getAccelKey();
+    var button = e.getButton();
+
+    if (button == 0 && ctrl) {
+        var editor = e.editor;
+        var docPos = e.getDocumentPosition();
+        var session = editor.session;
+        var token = session.getTokenAt(docPos.row, docPos.column);
+
+        editor._emit("linkClick", {position: docPos, token: token});
+    }
+}
+
+});
+                (function() {
+                    ace.require(["ace/ext/linking"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 234 - 0
services/web/public/js/ace-1.4.3/ext-modelist.js

@@ -0,0 +1,234 @@
+ace.define("ace/ext/modelist",[], function(require, exports, module) {
+"use strict";
+
+var modes = [];
+function getModeForPath(path) {
+    var mode = modesByName.text;
+    var fileName = path.split(/[\/\\]/).pop();
+    for (var i = 0; i < modes.length; i++) {
+        if (modes[i].supportsFile(fileName)) {
+            mode = modes[i];
+            break;
+        }
+    }
+    return mode;
+}
+
+var Mode = function(name, caption, extensions) {
+    this.name = name;
+    this.caption = caption;
+    this.mode = "ace/mode/" + name;
+    this.extensions = extensions;
+    var re;
+    if (/\^/.test(extensions)) {
+        re = extensions.replace(/\|(\^)?/g, function(a, b){
+            return "$|" + (b ? "^" : "^.*\\.");
+        }) + "$";
+    } else {
+        re = "^.*\\.(" + extensions + ")$";
+    }
+
+    this.extRe = new RegExp(re, "gi");
+};
+
+Mode.prototype.supportsFile = function(filename) {
+    return filename.match(this.extRe);
+};
+var supportedModes = {
+    ABAP:        ["abap"],
+    ABC:         ["abc"],
+    ActionScript:["as"],
+    ADA:         ["ada|adb"],
+    Apache_Conf: ["^htaccess|^htgroups|^htpasswd|^conf|htaccess|htgroups|htpasswd"],
+    AsciiDoc:    ["asciidoc|adoc"],
+    ASL:         ["dsl|asl"],
+    Assembly_x86:["asm|a"],
+    AutoHotKey:  ["ahk"],
+    Apex:        ["apex|cls|trigger|tgr"],
+    BatchFile:   ["bat|cmd"],
+    Bro:         ["bro"],
+    C_Cpp:       ["cpp|c|cc|cxx|h|hh|hpp|ino"],
+    C9Search:    ["c9search_results"],
+    Cirru:       ["cirru|cr"],
+    Clojure:     ["clj|cljs"],
+    Cobol:       ["CBL|COB"],
+    coffee:      ["coffee|cf|cson|^Cakefile"],
+    ColdFusion:  ["cfm"],
+    CSharp:      ["cs"],
+    Csound_Document: ["csd"],
+    Csound_Orchestra: ["orc"],
+    Csound_Score: ["sco"],
+    CSS:         ["css"],
+    Curly:       ["curly"],
+    D:           ["d|di"],
+    Dart:        ["dart"],
+    Diff:        ["diff|patch"],
+    Dockerfile:  ["^Dockerfile"],
+    Dot:         ["dot"],
+    Drools:      ["drl"],
+    Edifact:     ["edi"],
+    Eiffel:      ["e|ge"],
+    EJS:         ["ejs"],
+    Elixir:      ["ex|exs"],
+    Elm:         ["elm"],
+    Erlang:      ["erl|hrl"],
+    Forth:       ["frt|fs|ldr|fth|4th"],
+    Fortran:     ["f|f90"],
+    FSharp:      ["fsi|fs|ml|mli|fsx|fsscript"],
+    FSL:         ["fsl"],
+    FTL:         ["ftl"],
+    Gcode:       ["gcode"],
+    Gherkin:     ["feature"],
+    Gitignore:   ["^.gitignore"],
+    Glsl:        ["glsl|frag|vert"],
+    Gobstones:   ["gbs"],
+    golang:      ["go"],
+    GraphQLSchema: ["gql"],
+    Groovy:      ["groovy"],
+    HAML:        ["haml"],
+    Handlebars:  ["hbs|handlebars|tpl|mustache"],
+    Haskell:     ["hs"],
+    Haskell_Cabal: ["cabal"],
+    haXe:        ["hx"],
+    Hjson:       ["hjson"],
+    HTML:        ["html|htm|xhtml|vue|we|wpy"],
+    HTML_Elixir: ["eex|html.eex"],
+    HTML_Ruby:   ["erb|rhtml|html.erb"],
+    INI:         ["ini|conf|cfg|prefs"],
+    Io:          ["io"],
+    Jack:        ["jack"],
+    Jade:        ["jade|pug"],
+    Java:        ["java"],
+    JavaScript:  ["js|jsm|jsx"],
+    JSON:        ["json"],
+    JSONiq:      ["jq"],
+    JSP:         ["jsp"],
+    JSSM:        ["jssm|jssm_state"],
+    JSX:         ["jsx"],
+    Julia:       ["jl"],
+    Kotlin:      ["kt|kts"],
+    LaTeX:       ["tex|latex|ltx|bib"],
+    LESS:        ["less"],
+    Liquid:      ["liquid"],
+    Lisp:        ["lisp"],
+    LiveScript:  ["ls"],
+    LogiQL:      ["logic|lql"],
+    LSL:         ["lsl"],
+    Lua:         ["lua"],
+    LuaPage:     ["lp"],
+    Lucene:      ["lucene"],
+    Makefile:    ["^Makefile|^GNUmakefile|^makefile|^OCamlMakefile|make"],
+    Markdown:    ["md|markdown"],
+    Mask:        ["mask"],
+    MATLAB:      ["matlab"],
+    Maze:        ["mz"],
+    MEL:         ["mel"],
+    MIXAL:       ["mixal"],
+    MUSHCode:    ["mc|mush"],
+    MySQL:       ["mysql"],
+    Nix:         ["nix"],
+    NSIS:        ["nsi|nsh"],
+    ObjectiveC:  ["m|mm"],
+    OCaml:       ["ml|mli"],
+    Pascal:      ["pas|p"],
+    Perl:        ["pl|pm"],
+    Perl6:       ["p6|pl6|pm6"],
+    pgSQL:       ["pgsql"],
+    PHP_Laravel_blade: ["blade.php"],
+    PHP:         ["php|inc|phtml|shtml|php3|php4|php5|phps|phpt|aw|ctp|module"],
+    Puppet:      ["epp|pp"],
+    Pig:         ["pig"],
+    Powershell:  ["ps1"],
+    Praat:       ["praat|praatscript|psc|proc"],
+    Prolog:      ["plg|prolog"],
+    Properties:  ["properties"],
+    Protobuf:    ["proto"],
+    Python:      ["py"],
+    R:           ["r"],
+    Razor:       ["cshtml|asp"],
+    RDoc:        ["Rd"],
+    Red:         ["red|reds"],
+    RHTML:       ["Rhtml"],
+    RST:         ["rst"],
+    Ruby:        ["rb|ru|gemspec|rake|^Guardfile|^Rakefile|^Gemfile"],
+    Rust:        ["rs"],
+    SASS:        ["sass"],
+    SCAD:        ["scad"],
+    Scala:       ["scala"],
+    Scheme:      ["scm|sm|rkt|oak|scheme"],
+    SCSS:        ["scss"],
+    SH:          ["sh|bash|^.bashrc"],
+    SJS:         ["sjs"],
+    Slim:        ["slim|skim"],
+    Smarty:      ["smarty|tpl"],
+    snippets:    ["snippets"],
+    Soy_Template:["soy"],
+    Space:       ["space"],
+    SQL:         ["sql"],
+    SQLServer:   ["sqlserver"],
+    Stylus:      ["styl|stylus"],
+    SVG:         ["svg"],
+    Swift:       ["swift"],
+    Tcl:         ["tcl"],
+    Terraform:   ["tf", "tfvars", "terragrunt"],
+    Tex:         ["tex"],
+    Text:        ["txt"],
+    Textile:     ["textile"],
+    Toml:        ["toml"],
+    TSX:         ["tsx"],
+    Twig:        ["latte|twig|swig"],
+    Typescript:  ["ts|typescript|str"],
+    Vala:        ["vala"],
+    VBScript:    ["vbs|vb"],
+    Velocity:    ["vm"],
+    Verilog:     ["v|vh|sv|svh"],
+    VHDL:        ["vhd|vhdl"],
+    Visualforce: ["vfp|component|page"],
+    Wollok:      ["wlk|wpgm|wtest"],
+    XML:         ["xml|rdf|rss|wsdl|xslt|atom|mathml|mml|xul|xbl|xaml"],
+    XQuery:      ["xq"],
+    YAML:        ["yaml|yml"],
+    Django:      ["html"]
+};
+
+var nameOverrides = {
+    ObjectiveC: "Objective-C",
+    CSharp: "C#",
+    golang: "Go",
+    C_Cpp: "C and C++",
+    Csound_Document: "Csound Document",
+    Csound_Orchestra: "Csound",
+    Csound_Score: "Csound Score",
+    coffee: "CoffeeScript",
+    HTML_Ruby: "HTML (Ruby)",
+    HTML_Elixir: "HTML (Elixir)",
+    FTL: "FreeMarker",
+    PHP_Laravel_blade: "PHP (Blade Template)",
+    Perl6: "Perl 6",
+    AutoHotKey: "AutoHotkey / AutoIt"
+};
+var modesByName = {};
+for (var name in supportedModes) {
+    var data = supportedModes[name];
+    var displayName = (nameOverrides[name] || name).replace(/_/g, " ");
+    var filename = name.toLowerCase();
+    var mode = new Mode(filename, displayName, data[0]);
+    modesByName[filename] = mode;
+    modes.push(mode);
+}
+
+module.exports = {
+    getModeForPath: getModeForPath,
+    modes: modes,
+    modesByName: modesByName
+};
+
+});
+                (function() {
+                    ace.require(["ace/ext/modelist"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 756 - 0
services/web/public/js/ace-1.4.3/ext-options.js

@@ -0,0 +1,756 @@
+ace.define("ace/ext/menu_tools/overlay_page",[], function(require, exports, module) {
+'use strict';
+var dom = require("../../lib/dom");
+var cssText = "#ace_settingsmenu, #kbshortcutmenu {\
+background-color: #F7F7F7;\
+color: black;\
+box-shadow: -5px 4px 5px rgba(126, 126, 126, 0.55);\
+padding: 1em 0.5em 2em 1em;\
+overflow: auto;\
+position: absolute;\
+margin: 0;\
+bottom: 0;\
+right: 0;\
+top: 0;\
+z-index: 9991;\
+cursor: default;\
+}\
+.ace_dark #ace_settingsmenu, .ace_dark #kbshortcutmenu {\
+box-shadow: -20px 10px 25px rgba(126, 126, 126, 0.25);\
+background-color: rgba(255, 255, 255, 0.6);\
+color: black;\
+}\
+.ace_optionsMenuEntry:hover {\
+background-color: rgba(100, 100, 100, 0.1);\
+transition: all 0.3s\
+}\
+.ace_closeButton {\
+background: rgba(245, 146, 146, 0.5);\
+border: 1px solid #F48A8A;\
+border-radius: 50%;\
+padding: 7px;\
+position: absolute;\
+right: -8px;\
+top: -8px;\
+z-index: 100000;\
+}\
+.ace_closeButton{\
+background: rgba(245, 146, 146, 0.9);\
+}\
+.ace_optionsMenuKey {\
+color: darkslateblue;\
+font-weight: bold;\
+}\
+.ace_optionsMenuCommand {\
+color: darkcyan;\
+font-weight: normal;\
+}\
+.ace_optionsMenuEntry input, .ace_optionsMenuEntry button {\
+vertical-align: middle;\
+}\
+.ace_optionsMenuEntry button[ace_selected_button=true] {\
+background: #e7e7e7;\
+box-shadow: 1px 0px 2px 0px #adadad inset;\
+border-color: #adadad;\
+}\
+.ace_optionsMenuEntry button {\
+background: white;\
+border: 1px solid lightgray;\
+margin: 0px;\
+}\
+.ace_optionsMenuEntry button:hover{\
+background: #f0f0f0;\
+}";
+dom.importCssString(cssText);
+module.exports.overlayPage = function overlayPage(editor, contentElement, top, right, bottom, left) {
+    top = top ? 'top: ' + top + ';' : '';
+    bottom = bottom ? 'bottom: ' + bottom + ';' : '';
+    right = right ? 'right: ' + right + ';' : '';
+    left = left ? 'left: ' + left + ';' : '';
+
+    var closer = document.createElement('div');
+    var contentContainer = document.createElement('div');
+
+    function documentEscListener(e) {
+        if (e.keyCode === 27) {
+            closer.click();
+        }
+    }
+
+    closer.style.cssText = 'margin: 0; padding: 0; ' +
+        'position: fixed; top:0; bottom:0; left:0; right:0;' +
+        'z-index: 9990; ' +
+        'background-color: rgba(0, 0, 0, 0.3);';
+    closer.addEventListener('click', function() {
+        document.removeEventListener('keydown', documentEscListener);
+        closer.parentNode.removeChild(closer);
+        editor.focus();
+        closer = null;
+    });
+    document.addEventListener('keydown', documentEscListener);
+
+    contentContainer.style.cssText = top + right + bottom + left;
+    contentContainer.addEventListener('click', function(e) {
+        e.stopPropagation();
+    });
+
+    var wrapper = dom.createElement("div");
+    wrapper.style.position = "relative";
+    
+    var closeButton = dom.createElement("div");
+    closeButton.className = "ace_closeButton";
+    closeButton.addEventListener('click', function() {
+        closer.click();
+    });
+    
+    wrapper.appendChild(closeButton);
+    contentContainer.appendChild(wrapper);
+    
+    contentContainer.appendChild(contentElement);
+    closer.appendChild(contentContainer);
+    document.body.appendChild(closer);
+    editor.blur();
+};
+
+});
+
+ace.define("ace/ext/modelist",[], function(require, exports, module) {
+"use strict";
+
+var modes = [];
+function getModeForPath(path) {
+    var mode = modesByName.text;
+    var fileName = path.split(/[\/\\]/).pop();
+    for (var i = 0; i < modes.length; i++) {
+        if (modes[i].supportsFile(fileName)) {
+            mode = modes[i];
+            break;
+        }
+    }
+    return mode;
+}
+
+var Mode = function(name, caption, extensions) {
+    this.name = name;
+    this.caption = caption;
+    this.mode = "ace/mode/" + name;
+    this.extensions = extensions;
+    var re;
+    if (/\^/.test(extensions)) {
+        re = extensions.replace(/\|(\^)?/g, function(a, b){
+            return "$|" + (b ? "^" : "^.*\\.");
+        }) + "$";
+    } else {
+        re = "^.*\\.(" + extensions + ")$";
+    }
+
+    this.extRe = new RegExp(re, "gi");
+};
+
+Mode.prototype.supportsFile = function(filename) {
+    return filename.match(this.extRe);
+};
+var supportedModes = {
+    ABAP:        ["abap"],
+    ABC:         ["abc"],
+    ActionScript:["as"],
+    ADA:         ["ada|adb"],
+    Apache_Conf: ["^htaccess|^htgroups|^htpasswd|^conf|htaccess|htgroups|htpasswd"],
+    AsciiDoc:    ["asciidoc|adoc"],
+    ASL:         ["dsl|asl"],
+    Assembly_x86:["asm|a"],
+    AutoHotKey:  ["ahk"],
+    Apex:        ["apex|cls|trigger|tgr"],
+    BatchFile:   ["bat|cmd"],
+    Bro:         ["bro"],
+    C_Cpp:       ["cpp|c|cc|cxx|h|hh|hpp|ino"],
+    C9Search:    ["c9search_results"],
+    Cirru:       ["cirru|cr"],
+    Clojure:     ["clj|cljs"],
+    Cobol:       ["CBL|COB"],
+    coffee:      ["coffee|cf|cson|^Cakefile"],
+    ColdFusion:  ["cfm"],
+    CSharp:      ["cs"],
+    Csound_Document: ["csd"],
+    Csound_Orchestra: ["orc"],
+    Csound_Score: ["sco"],
+    CSS:         ["css"],
+    Curly:       ["curly"],
+    D:           ["d|di"],
+    Dart:        ["dart"],
+    Diff:        ["diff|patch"],
+    Dockerfile:  ["^Dockerfile"],
+    Dot:         ["dot"],
+    Drools:      ["drl"],
+    Edifact:     ["edi"],
+    Eiffel:      ["e|ge"],
+    EJS:         ["ejs"],
+    Elixir:      ["ex|exs"],
+    Elm:         ["elm"],
+    Erlang:      ["erl|hrl"],
+    Forth:       ["frt|fs|ldr|fth|4th"],
+    Fortran:     ["f|f90"],
+    FSharp:      ["fsi|fs|ml|mli|fsx|fsscript"],
+    FSL:         ["fsl"],
+    FTL:         ["ftl"],
+    Gcode:       ["gcode"],
+    Gherkin:     ["feature"],
+    Gitignore:   ["^.gitignore"],
+    Glsl:        ["glsl|frag|vert"],
+    Gobstones:   ["gbs"],
+    golang:      ["go"],
+    GraphQLSchema: ["gql"],
+    Groovy:      ["groovy"],
+    HAML:        ["haml"],
+    Handlebars:  ["hbs|handlebars|tpl|mustache"],
+    Haskell:     ["hs"],
+    Haskell_Cabal: ["cabal"],
+    haXe:        ["hx"],
+    Hjson:       ["hjson"],
+    HTML:        ["html|htm|xhtml|vue|we|wpy"],
+    HTML_Elixir: ["eex|html.eex"],
+    HTML_Ruby:   ["erb|rhtml|html.erb"],
+    INI:         ["ini|conf|cfg|prefs"],
+    Io:          ["io"],
+    Jack:        ["jack"],
+    Jade:        ["jade|pug"],
+    Java:        ["java"],
+    JavaScript:  ["js|jsm|jsx"],
+    JSON:        ["json"],
+    JSONiq:      ["jq"],
+    JSP:         ["jsp"],
+    JSSM:        ["jssm|jssm_state"],
+    JSX:         ["jsx"],
+    Julia:       ["jl"],
+    Kotlin:      ["kt|kts"],
+    LaTeX:       ["tex|latex|ltx|bib"],
+    LESS:        ["less"],
+    Liquid:      ["liquid"],
+    Lisp:        ["lisp"],
+    LiveScript:  ["ls"],
+    LogiQL:      ["logic|lql"],
+    LSL:         ["lsl"],
+    Lua:         ["lua"],
+    LuaPage:     ["lp"],
+    Lucene:      ["lucene"],
+    Makefile:    ["^Makefile|^GNUmakefile|^makefile|^OCamlMakefile|make"],
+    Markdown:    ["md|markdown"],
+    Mask:        ["mask"],
+    MATLAB:      ["matlab"],
+    Maze:        ["mz"],
+    MEL:         ["mel"],
+    MIXAL:       ["mixal"],
+    MUSHCode:    ["mc|mush"],
+    MySQL:       ["mysql"],
+    Nix:         ["nix"],
+    NSIS:        ["nsi|nsh"],
+    ObjectiveC:  ["m|mm"],
+    OCaml:       ["ml|mli"],
+    Pascal:      ["pas|p"],
+    Perl:        ["pl|pm"],
+    Perl6:       ["p6|pl6|pm6"],
+    pgSQL:       ["pgsql"],
+    PHP_Laravel_blade: ["blade.php"],
+    PHP:         ["php|inc|phtml|shtml|php3|php4|php5|phps|phpt|aw|ctp|module"],
+    Puppet:      ["epp|pp"],
+    Pig:         ["pig"],
+    Powershell:  ["ps1"],
+    Praat:       ["praat|praatscript|psc|proc"],
+    Prolog:      ["plg|prolog"],
+    Properties:  ["properties"],
+    Protobuf:    ["proto"],
+    Python:      ["py"],
+    R:           ["r"],
+    Razor:       ["cshtml|asp"],
+    RDoc:        ["Rd"],
+    Red:         ["red|reds"],
+    RHTML:       ["Rhtml"],
+    RST:         ["rst"],
+    Ruby:        ["rb|ru|gemspec|rake|^Guardfile|^Rakefile|^Gemfile"],
+    Rust:        ["rs"],
+    SASS:        ["sass"],
+    SCAD:        ["scad"],
+    Scala:       ["scala"],
+    Scheme:      ["scm|sm|rkt|oak|scheme"],
+    SCSS:        ["scss"],
+    SH:          ["sh|bash|^.bashrc"],
+    SJS:         ["sjs"],
+    Slim:        ["slim|skim"],
+    Smarty:      ["smarty|tpl"],
+    snippets:    ["snippets"],
+    Soy_Template:["soy"],
+    Space:       ["space"],
+    SQL:         ["sql"],
+    SQLServer:   ["sqlserver"],
+    Stylus:      ["styl|stylus"],
+    SVG:         ["svg"],
+    Swift:       ["swift"],
+    Tcl:         ["tcl"],
+    Terraform:   ["tf", "tfvars", "terragrunt"],
+    Tex:         ["tex"],
+    Text:        ["txt"],
+    Textile:     ["textile"],
+    Toml:        ["toml"],
+    TSX:         ["tsx"],
+    Twig:        ["latte|twig|swig"],
+    Typescript:  ["ts|typescript|str"],
+    Vala:        ["vala"],
+    VBScript:    ["vbs|vb"],
+    Velocity:    ["vm"],
+    Verilog:     ["v|vh|sv|svh"],
+    VHDL:        ["vhd|vhdl"],
+    Visualforce: ["vfp|component|page"],
+    Wollok:      ["wlk|wpgm|wtest"],
+    XML:         ["xml|rdf|rss|wsdl|xslt|atom|mathml|mml|xul|xbl|xaml"],
+    XQuery:      ["xq"],
+    YAML:        ["yaml|yml"],
+    Django:      ["html"]
+};
+
+var nameOverrides = {
+    ObjectiveC: "Objective-C",
+    CSharp: "C#",
+    golang: "Go",
+    C_Cpp: "C and C++",
+    Csound_Document: "Csound Document",
+    Csound_Orchestra: "Csound",
+    Csound_Score: "Csound Score",
+    coffee: "CoffeeScript",
+    HTML_Ruby: "HTML (Ruby)",
+    HTML_Elixir: "HTML (Elixir)",
+    FTL: "FreeMarker",
+    PHP_Laravel_blade: "PHP (Blade Template)",
+    Perl6: "Perl 6",
+    AutoHotKey: "AutoHotkey / AutoIt"
+};
+var modesByName = {};
+for (var name in supportedModes) {
+    var data = supportedModes[name];
+    var displayName = (nameOverrides[name] || name).replace(/_/g, " ");
+    var filename = name.toLowerCase();
+    var mode = new Mode(filename, displayName, data[0]);
+    modesByName[filename] = mode;
+    modes.push(mode);
+}
+
+module.exports = {
+    getModeForPath: getModeForPath,
+    modes: modes,
+    modesByName: modesByName
+};
+
+});
+
+ace.define("ace/ext/themelist",[], function(require, exports, module) {
+"use strict";
+
+var themeData = [
+    ["Chrome"         ],
+    ["Clouds"         ],
+    ["Crimson Editor" ],
+    ["Dawn"           ],
+    ["Dreamweaver"    ],
+    ["Eclipse"        ],
+    ["GitHub"         ],
+    ["IPlastic"       ],
+    ["Solarized Light"],
+    ["TextMate"       ],
+    ["Tomorrow"       ],
+    ["XCode"          ],
+    ["Kuroir"],
+    ["KatzenMilch"],
+    ["SQL Server"           ,"sqlserver"               , "light"],
+    ["Ambiance"             ,"ambiance"                ,  "dark"],
+    ["Chaos"                ,"chaos"                   ,  "dark"],
+    ["Clouds Midnight"      ,"clouds_midnight"         ,  "dark"],
+    ["Dracula"              ,""                        ,  "dark"],
+    ["Cobalt"               ,"cobalt"                  ,  "dark"],
+    ["Gruvbox"              ,"gruvbox"                 ,  "dark"],
+    ["Green on Black"       ,"gob"                     ,  "dark"],
+    ["idle Fingers"         ,"idle_fingers"            ,  "dark"],
+    ["krTheme"              ,"kr_theme"                ,  "dark"],
+    ["Merbivore"            ,"merbivore"               ,  "dark"],
+    ["Merbivore Soft"       ,"merbivore_soft"          ,  "dark"],
+    ["Mono Industrial"      ,"mono_industrial"         ,  "dark"],
+    ["Monokai"              ,"monokai"                 ,  "dark"],
+    ["Pastel on dark"       ,"pastel_on_dark"          ,  "dark"],
+    ["Solarized Dark"       ,"solarized_dark"          ,  "dark"],
+    ["Terminal"             ,"terminal"                ,  "dark"],
+    ["Tomorrow Night"       ,"tomorrow_night"          ,  "dark"],
+    ["Tomorrow Night Blue"  ,"tomorrow_night_blue"     ,  "dark"],
+    ["Tomorrow Night Bright","tomorrow_night_bright"   ,  "dark"],
+    ["Tomorrow Night 80s"   ,"tomorrow_night_eighties" ,  "dark"],
+    ["Twilight"             ,"twilight"                ,  "dark"],
+    ["Vibrant Ink"          ,"vibrant_ink"             ,  "dark"]
+];
+
+
+exports.themesByName = {};
+exports.themes = themeData.map(function(data) {
+    var name = data[1] || data[0].replace(/ /g, "_").toLowerCase();
+    var theme = {
+        caption: data[0],
+        theme: "ace/theme/" + name,
+        isDark: data[2] == "dark",
+        name: name
+    };
+    exports.themesByName[name] = theme;
+    return theme;
+});
+
+});
+
+ace.define("ace/ext/options",[], function(require, exports, module) {
+"use strict";
+var overlayPage = require('./menu_tools/overlay_page').overlayPage;
+
+ 
+var dom = require("../lib/dom");
+var oop = require("../lib/oop");
+var EventEmitter = require("../lib/event_emitter").EventEmitter;
+var buildDom = dom.buildDom;
+
+var modelist = require("./modelist");
+var themelist = require("./themelist");
+
+var themes = { Bright: [], Dark: [] };
+themelist.themes.forEach(function(x) {
+    themes[x.isDark ? "Dark" : "Bright"].push({ caption: x.caption, value: x.theme });
+});
+
+var modes = modelist.modes.map(function(x){ 
+    return { caption: x.caption, value: x.mode }; 
+});
+
+
+var optionGroups = {
+    Main: {
+        Mode: {
+            path: "mode",
+            type: "select",
+            items: modes
+        },
+        Theme: {
+            path: "theme",
+            type: "select",
+            items: themes
+        },
+        "Keybinding": {
+            type: "buttonBar",
+            path: "keyboardHandler",
+            items: [
+                { caption : "Ace", value : null },
+                { caption : "Vim", value : "ace/keyboard/vim" },
+                { caption : "Emacs", value : "ace/keyboard/emacs" },
+                { caption : "Sublime", value : "ace/keyboard/sublime" }
+            ]
+        },
+        "Font Size": {
+            path: "fontSize",
+            type: "number",
+            defaultValue: 12,
+            defaults: [
+                {caption: "12px", value: 12},
+                {caption: "24px", value: 24}
+            ]
+        },
+        "Soft Wrap": {
+            type: "buttonBar",
+            path: "wrap",
+            items: [
+               { caption : "Off",  value : "off" },
+               { caption : "View", value : "free" },
+               { caption : "margin", value : "printMargin" },
+               { caption : "40",   value : "40" }
+            ]
+        },
+        "Cursor Style": {
+            path: "cursorStyle",
+            items: [
+               { caption : "Ace",    value : "ace" },
+               { caption : "Slim",   value : "slim" },
+               { caption : "Smooth", value : "smooth" },
+               { caption : "Smooth And Slim", value : "smooth slim" },
+               { caption : "Wide",   value : "wide" }
+            ]
+        },
+        "Folding": {
+            path: "foldStyle",
+            items: [
+                { caption : "Manual", value : "manual" },
+                { caption : "Mark begin", value : "markbegin" },
+                { caption : "Mark begin and end", value : "markbeginend" }
+            ]
+        },
+        "Soft Tabs": [{
+            path: "useSoftTabs"
+        }, {
+            path: "tabSize",
+            type: "number",
+            values: [2, 3, 4, 8, 16]
+        }],
+        "Overscroll": {
+            type: "buttonBar",
+            path: "scrollPastEnd",
+            items: [
+               { caption : "None",  value : 0 },
+               { caption : "Half",   value : 0.5 },
+               { caption : "Full",   value : 1 }
+            ]
+        }
+    },
+    More: {
+        "Atomic soft tabs": {
+            path: "navigateWithinSoftTabs"
+        },
+        "Enable Behaviours": {
+            path: "behavioursEnabled"
+        },
+        "Full Line Selection": {
+            type: "checkbox",
+            values: "text|line",
+            path: "selectionStyle"
+        },
+        "Highlight Active Line": {
+            path: "highlightActiveLine"
+        },
+        "Show Invisibles": {
+            path: "showInvisibles"
+        },
+        "Show Indent Guides": {
+            path: "displayIndentGuides"
+        },
+        "Persistent Scrollbar": [{
+            path: "hScrollBarAlwaysVisible"
+        }, {
+            path: "vScrollBarAlwaysVisible"
+        }],
+        "Animate scrolling": {
+            path: "animatedScroll"
+        },
+        "Show Gutter": {
+            path: "showGutter"
+        },
+        "Show Line Numbers": {
+            path: "showLineNumbers"
+        },
+        "Relative Line Numbers": {
+            path: "relativeLineNumbers"
+        },
+        "Fixed Gutter Width": {
+            path: "fixedWidthGutter"
+        },
+        "Show Print Margin": [{
+            path: "showPrintMargin"
+        }, {
+            type: "number",
+            path: "printMarginColumn"
+        }],
+        "Indented Soft Wrap": {
+            path: "indentedSoftWrap"
+        },
+        "Highlight selected word": {
+            path: "highlightSelectedWord"
+        },
+        "Fade Fold Widgets": {
+            path: "fadeFoldWidgets"
+        },
+        "Use textarea for IME": {
+            path: "useTextareaForIME"
+        },
+        "Merge Undo Deltas": {
+            path: "mergeUndoDeltas",
+            items: [
+               { caption : "Always",  value : "always" },
+               { caption : "Never",   value : "false" },
+               { caption : "Timed",   value : "true" }
+            ]
+        },
+        "Elastic Tabstops": {
+            path: "useElasticTabstops"
+        },
+        "Incremental Search": {
+            path: "useIncrementalSearch"
+        },
+        "Read-only": {
+            path: "readOnly"
+        },
+        "Copy without selection": {
+            path: "copyWithEmptySelection"
+        },
+        "Live Autocompletion": {
+            path: "enableLiveAutocompletion"
+        }
+    }
+};
+
+
+var OptionPanel = function(editor, element) {
+    this.editor = editor;
+    this.container = element || document.createElement("div");
+    this.groups = [];
+    this.options = {};
+};
+
+(function() {
+    
+    oop.implement(this, EventEmitter);
+    
+    this.add = function(config) {
+        if (config.Main)
+            oop.mixin(optionGroups.Main, config.Main);
+        if (config.More)
+            oop.mixin(optionGroups.More, config.More);
+    };
+    
+    this.render = function() {
+        this.container.innerHTML = "";
+        buildDom(["table", {id: "controls"}, 
+            this.renderOptionGroup(optionGroups.Main),
+            ["tr", null, ["td", {colspan: 2},
+                ["table", {id: "more-controls"}, 
+                    this.renderOptionGroup(optionGroups.More)
+                ]
+            ]]
+        ], this.container);
+    };
+    
+    this.renderOptionGroup = function(group) {
+        return Object.keys(group).map(function(key, i) {
+            var item = group[key];
+            if (!item.position)
+                item.position = i / 10000;
+            if (!item.label)
+                item.label = key;
+            return item;
+        }).sort(function(a, b) {
+            return a.position - b.position;
+        }).map(function(item) {
+            return this.renderOption(item.label, item);
+        }, this);
+    };
+    
+    this.renderOptionControl = function(key, option) {
+        var self = this;
+        if (Array.isArray(option)) {
+            return option.map(function(x) {
+                return self.renderOptionControl(key, x);
+            });
+        }
+        var control;
+        
+        var value = self.getOption(option);
+        
+        if (option.values && option.type != "checkbox") {
+            if (typeof option.values == "string")
+                option.values = option.values.split("|");
+            option.items = option.values.map(function(v) {
+                return { value: v, name: v };
+            });
+        }
+        
+        if (option.type == "buttonBar") {
+            control = ["div", option.items.map(function(item) {
+                return ["button", { 
+                    value: item.value, 
+                    ace_selected_button: value == item.value, 
+                    onclick: function() {
+                        self.setOption(option, item.value);
+                        var nodes = this.parentNode.querySelectorAll("[ace_selected_button]");
+                        for (var i = 0; i < nodes.length; i++) {
+                            nodes[i].removeAttribute("ace_selected_button");
+                        }
+                        this.setAttribute("ace_selected_button", true);
+                    } 
+                }, item.desc || item.caption || item.name];
+            })];
+        } else if (option.type == "number") {
+            control = ["input", {type: "number", value: value || option.defaultValue, style:"width:3em", oninput: function() {
+                self.setOption(option, parseInt(this.value));
+            }}];
+            if (option.defaults) {
+                control = [control, option.defaults.map(function(item) {
+                    return ["button", {onclick: function() {
+                        var input = this.parentNode.firstChild;
+                        input.value = item.value;
+                        input.oninput();
+                    }}, item.caption];
+                })];
+            }
+        } else if (option.items) {
+            var buildItems = function(items) {
+                return items.map(function(item) {
+                    return ["option", { value: item.value || item.name }, item.desc || item.caption || item.name];
+                });
+            };
+            
+            var items = Array.isArray(option.items) 
+                ? buildItems(option.items)
+                : Object.keys(option.items).map(function(key) {
+                    return ["optgroup", {"label": key}, buildItems(option.items[key])];
+                });
+            control = ["select", { id: key, value: value, onchange: function() {
+                self.setOption(option, this.value);
+            } }, items];
+        } else {
+            if (typeof option.values == "string")
+                option.values = option.values.split("|");
+            if (option.values) value = value == option.values[1];
+            control = ["input", { type: "checkbox", id: key, checked: value || null, onchange: function() {
+                var value = this.checked;
+                if (option.values) value = option.values[value ? 1 : 0];
+                self.setOption(option, value);
+            }}];
+            if (option.type == "checkedNumber") {
+                control = [control, []];
+            }
+        }
+        return control;
+    };
+    
+    this.renderOption = function(key, option) {
+        if (option.path && !option.onchange && !this.editor.$options[option.path])
+            return;
+        this.options[option.path] = option;
+        var safeKey = "-" + option.path;
+        var control = this.renderOptionControl(safeKey, option);
+        return ["tr", {class: "ace_optionsMenuEntry"}, ["td",
+            ["label", {for: safeKey}, key]
+        ], ["td", control]];
+    };
+    
+    this.setOption = function(option, value) {
+        if (typeof option == "string")
+            option = this.options[option];
+        if (value == "false") value = false;
+        if (value == "true") value = true;
+        if (value == "null") value = null;
+        if (value == "undefined") value = undefined;
+        if (typeof value == "string" && parseFloat(value).toString() == value)
+            value = parseFloat(value);
+        if (option.onchange)
+            option.onchange(value);
+        else if (option.path)
+            this.editor.setOption(option.path, value);
+        this._signal("setOption", {name: option.path, value: value});
+    };
+    
+    this.getOption = function(option) {
+        if (option.getValue)
+            return option.getValue();
+        return this.editor.getOption(option.path);
+    };
+    
+}).call(OptionPanel.prototype);
+
+exports.OptionPanel = OptionPanel;
+
+});
+                (function() {
+                    ace.require(["ace/ext/options"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 125 - 0
services/web/public/js/ace-1.4.3/ext-rtl.js

@@ -0,0 +1,125 @@
+ace.define("ace/ext/rtl",[], function(require, exports, module) {
+"use strict";
+var dom = require("ace/lib/dom");
+var lang = require("ace/lib/lang");
+
+var commands = [{
+    name: "leftToRight",
+    bindKey: { win: "Ctrl-Alt-Shift-L", mac: "Command-Alt-Shift-L" },
+    exec: function(editor) {
+        editor.session.$bidiHandler.setRtlDirection(editor, false);
+    },
+    readOnly: true
+}, {
+    name: "rightToLeft",
+    bindKey: { win: "Ctrl-Alt-Shift-R",  mac: "Command-Alt-Shift-R" },
+    exec: function(editor) {
+        editor.session.$bidiHandler.setRtlDirection(editor, true);
+    },
+    readOnly: true
+}];
+
+var Editor = require("../editor").Editor;
+require("../config").defineOptions(Editor.prototype, "editor", {
+    rtlText: {
+        set: function(val) {
+            if (val) {
+                this.on("change", onChange);
+                this.on("changeSelection", onChangeSelection);
+                this.renderer.on("afterRender", updateLineDirection);
+                this.commands.on("exec", onCommandEmitted);
+                this.commands.addCommands(commands);
+            } else {
+                this.off("change", onChange);
+                this.off("changeSelection", onChangeSelection);
+                this.renderer.off("afterRender", updateLineDirection);
+                this.commands.off("exec", onCommandEmitted);
+                this.commands.removeCommands(commands);
+                clearTextLayer(this.renderer);
+            }
+            this.renderer.updateFull();
+        }
+    },
+    rtl: {
+        set: function(val) {
+            this.session.$bidiHandler.$isRtl = val;
+            if (val) {
+                this.setOption("rtlText", false);
+                this.renderer.on("afterRender", updateLineDirection);
+                this.session.$bidiHandler.seenBidi = true;
+            } else {
+                this.renderer.off("afterRender", updateLineDirection);
+                clearTextLayer(this.renderer);
+            }
+            this.renderer.updateFull();
+        }
+    }
+});
+function onChangeSelection(e, editor) {
+    var lead = editor.getSelection().lead;
+    if (editor.session.$bidiHandler.isRtlLine(lead.row)) {
+        if (lead.column === 0) {
+            if (editor.session.$bidiHandler.isMoveLeftOperation && lead.row > 0) {
+                editor.getSelection().moveCursorTo(lead.row - 1, editor.session.getLine(lead.row - 1).length);
+            } else {
+                if (editor.getSelection().isEmpty())
+                    lead.column += 1;
+                else
+                    lead.setPosition(lead.row, lead.column + 1);
+            }
+        }
+    }
+}
+
+function onCommandEmitted(commadEvent) {
+    commadEvent.editor.session.$bidiHandler.isMoveLeftOperation = /gotoleft|selectleft|backspace|removewordleft/.test(commadEvent.command.name);
+}
+function onChange(delta, editor) {
+    var session = editor.session;
+    session.$bidiHandler.currentRow = null;
+    if (session.$bidiHandler.isRtlLine(delta.start.row) && delta.action === 'insert' && delta.lines.length > 1) {
+        for (var row = delta.start.row; row < delta.end.row; row++) {
+            if (session.getLine(row + 1).charAt(0) !== session.$bidiHandler.RLE)
+                session.doc.$lines[row + 1] = session.$bidiHandler.RLE + session.getLine(row + 1);
+        }
+    }
+}
+
+function updateLineDirection(e, renderer) {
+    var session = renderer.session;
+    var $bidiHandler = session.$bidiHandler;
+    var cells = renderer.$textLayer.$lines.cells;
+    var width = renderer.layerConfig.width - renderer.layerConfig.padding + "px";
+    cells.forEach(function(cell) {
+        var style = cell.element.style;
+        if ($bidiHandler && $bidiHandler.isRtlLine(cell.row)) {
+            style.direction = "rtl";
+            style.textAlign = "right";
+            style.width = width;
+        } else {
+            style.direction = "";
+            style.textAlign = "";
+            style.width = "";
+        }
+    });
+}
+
+function clearTextLayer(renderer) {
+    var lines = renderer.$textLayer.$lines;
+    lines.cells.forEach(clear);
+    lines.cellCache.forEach(clear);
+    function clear(cell) {
+        var style = cell.element.style;
+        style.direction = style.textAlign = style.width = "";
+    }
+}
+
+});
+                (function() {
+                    ace.require(["ace/ext/rtl"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 514 - 0
services/web/public/js/ace-1.4.3/ext-searchbox.js

@@ -0,0 +1,514 @@
+ace.define("ace/ext/searchbox",[], function(require, exports, module) {
+"use strict";
+
+var dom = require("../lib/dom");
+var lang = require("../lib/lang");
+var event = require("../lib/event");
+var searchboxCss = "\
+.ace_search {\
+background-color: #ddd;\
+color: #666;\
+border: 1px solid #cbcbcb;\
+border-top: 0 none;\
+overflow: hidden;\
+margin: 0;\
+padding: 4px 6px 0 4px;\
+position: absolute;\
+top: 0;\
+z-index: 99;\
+white-space: normal;\
+}\
+.ace_search.left {\
+border-left: 0 none;\
+border-radius: 0px 0px 5px 0px;\
+left: 0;\
+}\
+.ace_search.right {\
+border-radius: 0px 0px 0px 5px;\
+border-right: 0 none;\
+right: 0;\
+}\
+.ace_search_form, .ace_replace_form {\
+margin: 0 20px 4px 0;\
+overflow: hidden;\
+line-height: 1.9;\
+}\
+.ace_replace_form {\
+margin-right: 0;\
+}\
+.ace_search_form.ace_nomatch {\
+outline: 1px solid red;\
+}\
+.ace_search_field {\
+border-radius: 3px 0 0 3px;\
+background-color: white;\
+color: black;\
+border: 1px solid #cbcbcb;\
+border-right: 0 none;\
+outline: 0;\
+padding: 0;\
+font-size: inherit;\
+margin: 0;\
+line-height: inherit;\
+padding: 0 6px;\
+min-width: 17em;\
+vertical-align: top;\
+min-height: 1.8em;\
+box-sizing: content-box;\
+}\
+.ace_searchbtn {\
+border: 1px solid #cbcbcb;\
+line-height: inherit;\
+display: inline-block;\
+padding: 0 6px;\
+background: #fff;\
+border-right: 0 none;\
+border-left: 1px solid #dcdcdc;\
+cursor: pointer;\
+margin: 0;\
+position: relative;\
+color: #666;\
+}\
+.ace_searchbtn:last-child {\
+border-radius: 0 3px 3px 0;\
+border-right: 1px solid #cbcbcb;\
+}\
+.ace_searchbtn:disabled {\
+background: none;\
+cursor: default;\
+}\
+.ace_searchbtn:hover {\
+background-color: #eef1f6;\
+}\
+.ace_searchbtn.prev, .ace_searchbtn.next {\
+padding: 0px 0.7em\
+}\
+.ace_searchbtn.prev:after, .ace_searchbtn.next:after {\
+content: \"\";\
+border: solid 2px #888;\
+width: 0.5em;\
+height: 0.5em;\
+border-width:  2px 0 0 2px;\
+display:inline-block;\
+transform: rotate(-45deg);\
+}\
+.ace_searchbtn.next:after {\
+border-width: 0 2px 2px 0 ;\
+}\
+.ace_searchbtn_close {\
+background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAcCAYAAABRVo5BAAAAZ0lEQVR42u2SUQrAMAhDvazn8OjZBilCkYVVxiis8H4CT0VrAJb4WHT3C5xU2a2IQZXJjiQIRMdkEoJ5Q2yMqpfDIo+XY4k6h+YXOyKqTIj5REaxloNAd0xiKmAtsTHqW8sR2W5f7gCu5nWFUpVjZwAAAABJRU5ErkJggg==) no-repeat 50% 0;\
+border-radius: 50%;\
+border: 0 none;\
+color: #656565;\
+cursor: pointer;\
+font: 16px/16px Arial;\
+padding: 0;\
+height: 14px;\
+width: 14px;\
+top: 9px;\
+right: 7px;\
+position: absolute;\
+}\
+.ace_searchbtn_close:hover {\
+background-color: #656565;\
+background-position: 50% 100%;\
+color: white;\
+}\
+.ace_button {\
+margin-left: 2px;\
+cursor: pointer;\
+-webkit-user-select: none;\
+-moz-user-select: none;\
+-o-user-select: none;\
+-ms-user-select: none;\
+user-select: none;\
+overflow: hidden;\
+opacity: 0.7;\
+border: 1px solid rgba(100,100,100,0.23);\
+padding: 1px;\
+box-sizing:    border-box!important;\
+color: black;\
+}\
+.ace_button:hover {\
+background-color: #eee;\
+opacity:1;\
+}\
+.ace_button:active {\
+background-color: #ddd;\
+}\
+.ace_button.checked {\
+border-color: #3399ff;\
+opacity:1;\
+}\
+.ace_search_options{\
+margin-bottom: 3px;\
+text-align: right;\
+-webkit-user-select: none;\
+-moz-user-select: none;\
+-o-user-select: none;\
+-ms-user-select: none;\
+user-select: none;\
+clear: both;\
+}\
+.ace_search_counter {\
+float: left;\
+font-family: arial;\
+padding: 0 8px;\
+}";
+var HashHandler = require("../keyboard/hash_handler").HashHandler;
+var keyUtil = require("../lib/keys");
+
+var MAX_COUNT = 999;
+
+dom.importCssString(searchboxCss, "ace_searchbox");
+
+var SearchBox = function(editor, range, showReplaceForm) {
+    var div = dom.createElement("div");
+    dom.buildDom(["div", {class:"ace_search right"},
+        ["span", {action: "hide", class: "ace_searchbtn_close"}],
+        ["div", {class: "ace_search_form"},
+            ["input", {class: "ace_search_field", placeholder: "Search for", spellcheck: "false"}],
+            ["span", {action: "findPrev", class: "ace_searchbtn prev"}, "\u200b"],
+            ["span", {action: "findNext", class: "ace_searchbtn next"}, "\u200b"],
+            ["span", {action: "findAll", class: "ace_searchbtn", title: "Alt-Enter"}, "All"]
+        ],
+        ["div", {class: "ace_replace_form"},
+            ["input", {class: "ace_search_field", placeholder: "Replace with", spellcheck: "false"}],
+            ["span", {action: "replaceAndFindNext", class: "ace_searchbtn"}, "Replace"],
+            ["span", {action: "replaceAll", class: "ace_searchbtn"}, "All"]
+        ],
+        ["div", {class: "ace_search_options"},
+            ["span", {action: "toggleReplace", class: "ace_button", title: "Toggle Replace mode",
+                style: "float:left;margin-top:-2px;padding:0 5px;"}, "+"],
+            ["span", {class: "ace_search_counter"}],
+            ["span", {action: "toggleRegexpMode", class: "ace_button", title: "RegExp Search"}, ".*"],
+            ["span", {action: "toggleCaseSensitive", class: "ace_button", title: "CaseSensitive Search"}, "Aa"],
+            ["span", {action: "toggleWholeWords", class: "ace_button", title: "Whole Word Search"}, "\\b"],
+            ["span", {action: "searchInSelection", class: "ace_button", title: "Search In Selection"}, "S"]
+        ]
+    ], div);
+    this.element = div.firstChild;
+    
+    this.setSession = this.setSession.bind(this);
+
+    this.$init();
+    this.setEditor(editor);
+};
+
+(function() {
+    this.setEditor = function(editor) {
+        editor.searchBox = this;
+        editor.renderer.scroller.appendChild(this.element);
+        this.editor = editor;
+    };
+    
+    this.setSession = function(e) {
+        this.searchRange = null;
+        this.$syncOptions(true);
+    };
+
+    this.$initElements = function(sb) {
+        this.searchBox = sb.querySelector(".ace_search_form");
+        this.replaceBox = sb.querySelector(".ace_replace_form");
+        this.searchOption = sb.querySelector("[action=searchInSelection]");
+        this.replaceOption = sb.querySelector("[action=toggleReplace]");
+        this.regExpOption = sb.querySelector("[action=toggleRegexpMode]");
+        this.caseSensitiveOption = sb.querySelector("[action=toggleCaseSensitive]");
+        this.wholeWordOption = sb.querySelector("[action=toggleWholeWords]");
+        this.searchInput = this.searchBox.querySelector(".ace_search_field");
+        this.replaceInput = this.replaceBox.querySelector(".ace_search_field");
+        this.searchCounter = sb.querySelector(".ace_search_counter");
+    };
+    
+    this.$init = function() {
+        var sb = this.element;
+        
+        this.$initElements(sb);
+        
+        var _this = this;
+        event.addListener(sb, "mousedown", function(e) {
+            setTimeout(function(){
+                _this.activeInput.focus();
+            }, 0);
+            event.stopPropagation(e);
+        });
+        event.addListener(sb, "click", function(e) {
+            var t = e.target || e.srcElement;
+            var action = t.getAttribute("action");
+            if (action && _this[action])
+                _this[action]();
+            else if (_this.$searchBarKb.commands[action])
+                _this.$searchBarKb.commands[action].exec(_this);
+            event.stopPropagation(e);
+        });
+
+        event.addCommandKeyListener(sb, function(e, hashId, keyCode) {
+            var keyString = keyUtil.keyCodeToString(keyCode);
+            var command = _this.$searchBarKb.findKeyCommand(hashId, keyString);
+            if (command && command.exec) {
+                command.exec(_this);
+                event.stopEvent(e);
+            }
+        });
+
+        this.$onChange = lang.delayedCall(function() {
+            _this.find(false, false);
+        });
+
+        event.addListener(this.searchInput, "input", function() {
+            _this.$onChange.schedule(20);
+        });
+        event.addListener(this.searchInput, "focus", function() {
+            _this.activeInput = _this.searchInput;
+            _this.searchInput.value && _this.highlight();
+        });
+        event.addListener(this.replaceInput, "focus", function() {
+            _this.activeInput = _this.replaceInput;
+            _this.searchInput.value && _this.highlight();
+        });
+    };
+    this.$closeSearchBarKb = new HashHandler([{
+        bindKey: "Esc",
+        name: "closeSearchBar",
+        exec: function(editor) {
+            editor.searchBox.hide();
+        }
+    }]);
+    this.$searchBarKb = new HashHandler();
+    this.$searchBarKb.bindKeys({
+        "Ctrl-f|Command-f": function(sb) {
+            var isReplace = sb.isReplace = !sb.isReplace;
+            sb.replaceBox.style.display = isReplace ? "" : "none";
+            sb.replaceOption.checked = false;
+            sb.$syncOptions();
+            sb.searchInput.focus();
+        },
+        "Ctrl-H|Command-Option-F": function(sb) {
+            if (sb.editor.getReadOnly())
+                return;
+            sb.replaceOption.checked = true;
+            sb.$syncOptions();
+            sb.replaceInput.focus();
+        },
+        "Ctrl-G|Command-G": function(sb) {
+            sb.findNext();
+        },
+        "Ctrl-Shift-G|Command-Shift-G": function(sb) {
+            sb.findPrev();
+        },
+        "esc": function(sb) {
+            setTimeout(function() { sb.hide();});
+        },
+        "Return": function(sb) {
+            if (sb.activeInput == sb.replaceInput)
+                sb.replace();
+            sb.findNext();
+        },
+        "Shift-Return": function(sb) {
+            if (sb.activeInput == sb.replaceInput)
+                sb.replace();
+            sb.findPrev();
+        },
+        "Alt-Return": function(sb) {
+            if (sb.activeInput == sb.replaceInput)
+                sb.replaceAll();
+            sb.findAll();
+        },
+        "Tab": function(sb) {
+            (sb.activeInput == sb.replaceInput ? sb.searchInput : sb.replaceInput).focus();
+        }
+    });
+
+    this.$searchBarKb.addCommands([{
+        name: "toggleRegexpMode",
+        bindKey: {win: "Alt-R|Alt-/", mac: "Ctrl-Alt-R|Ctrl-Alt-/"},
+        exec: function(sb) {
+            sb.regExpOption.checked = !sb.regExpOption.checked;
+            sb.$syncOptions();
+        }
+    }, {
+        name: "toggleCaseSensitive",
+        bindKey: {win: "Alt-C|Alt-I", mac: "Ctrl-Alt-R|Ctrl-Alt-I"},
+        exec: function(sb) {
+            sb.caseSensitiveOption.checked = !sb.caseSensitiveOption.checked;
+            sb.$syncOptions();
+        }
+    }, {
+        name: "toggleWholeWords",
+        bindKey: {win: "Alt-B|Alt-W", mac: "Ctrl-Alt-B|Ctrl-Alt-W"},
+        exec: function(sb) {
+            sb.wholeWordOption.checked = !sb.wholeWordOption.checked;
+            sb.$syncOptions();
+        }
+    }, {
+        name: "toggleReplace",
+        exec: function(sb) {
+            sb.replaceOption.checked = !sb.replaceOption.checked;
+            sb.$syncOptions();
+        }
+    }, {
+        name: "searchInSelection",
+        exec: function(sb) {
+            sb.searchOption.checked = !sb.searchRange;
+            sb.setSearchRange(sb.searchOption.checked && sb.editor.getSelectionRange());
+            sb.$syncOptions();
+        }
+    }]);
+    
+    this.setSearchRange = function(range) {
+        this.searchRange = range;
+        if (range) {
+            this.searchRangeMarker = this.editor.session.addMarker(range, "ace_active-line");
+        } else if (this.searchRangeMarker) {
+            this.editor.session.removeMarker(this.searchRangeMarker);
+            this.searchRangeMarker = null;
+        }
+    };
+
+    this.$syncOptions = function(preventScroll) {
+        dom.setCssClass(this.replaceOption, "checked", this.searchRange);
+        dom.setCssClass(this.searchOption, "checked", this.searchOption.checked);
+        this.replaceOption.textContent = this.replaceOption.checked ? "-" : "+";
+        dom.setCssClass(this.regExpOption, "checked", this.regExpOption.checked);
+        dom.setCssClass(this.wholeWordOption, "checked", this.wholeWordOption.checked);
+        dom.setCssClass(this.caseSensitiveOption, "checked", this.caseSensitiveOption.checked);
+        var readOnly = this.editor.getReadOnly();
+        this.replaceOption.style.display = readOnly ? "none" : "";
+        this.replaceBox.style.display = this.replaceOption.checked && !readOnly ? "" : "none";
+        this.find(false, false, preventScroll);
+    };
+
+    this.highlight = function(re) {
+        this.editor.session.highlight(re || this.editor.$search.$options.re);
+        this.editor.renderer.updateBackMarkers();
+    };
+    this.find = function(skipCurrent, backwards, preventScroll) {
+        var range = this.editor.find(this.searchInput.value, {
+            skipCurrent: skipCurrent,
+            backwards: backwards,
+            wrap: true,
+            regExp: this.regExpOption.checked,
+            caseSensitive: this.caseSensitiveOption.checked,
+            wholeWord: this.wholeWordOption.checked,
+            preventScroll: preventScroll,
+            range: this.searchRange
+        });
+        var noMatch = !range && this.searchInput.value;
+        dom.setCssClass(this.searchBox, "ace_nomatch", noMatch);
+        this.editor._emit("findSearchBox", { match: !noMatch });
+        this.highlight();
+        this.updateCounter();
+    };
+    this.updateCounter = function() {
+        var editor = this.editor;
+        var regex = editor.$search.$options.re;
+        var all = 0;
+        var before = 0;
+        if (regex) {
+            var value = this.searchRange
+                ? editor.session.getTextRange(this.searchRange)
+                : editor.getValue();
+            
+            var offset = editor.session.doc.positionToIndex(editor.selection.anchor);
+            if (this.searchRange)
+                offset -= editor.session.doc.positionToIndex(this.searchRange.start);
+                
+            var last = regex.lastIndex = 0;
+            var m;
+            while ((m = regex.exec(value))) {
+                all++;
+                last = m.index;
+                if (last <= offset)
+                    before++;
+                if (all > MAX_COUNT)
+                    break;
+                if (!m[0]) {
+                    regex.lastIndex = last += 1;
+                    if (last >= value.length)
+                        break;
+                }
+            }
+        }
+        this.searchCounter.textContent = before + " of " + (all > MAX_COUNT ? MAX_COUNT + "+" : all);
+    };
+    this.findNext = function() {
+        this.find(true, false);
+    };
+    this.findPrev = function() {
+        this.find(true, true);
+    };
+    this.findAll = function(){
+        var range = this.editor.findAll(this.searchInput.value, {            
+            regExp: this.regExpOption.checked,
+            caseSensitive: this.caseSensitiveOption.checked,
+            wholeWord: this.wholeWordOption.checked
+        });
+        var noMatch = !range && this.searchInput.value;
+        dom.setCssClass(this.searchBox, "ace_nomatch", noMatch);
+        this.editor._emit("findSearchBox", { match: !noMatch });
+        this.highlight();
+        this.hide();
+    };
+    this.replace = function() {
+        if (!this.editor.getReadOnly())
+            this.editor.replace(this.replaceInput.value);
+    };    
+    this.replaceAndFindNext = function() {
+        if (!this.editor.getReadOnly()) {
+            this.editor.replace(this.replaceInput.value);
+            this.findNext();
+        }
+    };
+    this.replaceAll = function() {
+        if (!this.editor.getReadOnly())
+            this.editor.replaceAll(this.replaceInput.value);
+    };
+
+    this.hide = function() {
+        this.active = false;
+        this.setSearchRange(null);
+        this.editor.off("changeSession", this.setSession);
+        
+        this.element.style.display = "none";
+        this.editor.keyBinding.removeKeyboardHandler(this.$closeSearchBarKb);
+        this.editor.focus();
+    };
+    this.show = function(value, isReplace) {
+        this.active = true;
+        this.editor.on("changeSession", this.setSession);
+        this.element.style.display = "";
+        this.replaceOption.checked = isReplace;
+        
+        if (value)
+            this.searchInput.value = value;
+        
+        this.searchInput.focus();
+        this.searchInput.select();
+
+        this.editor.keyBinding.addKeyboardHandler(this.$closeSearchBarKb);
+        
+        this.$syncOptions(true);
+    };
+
+    this.isFocused = function() {
+        var el = document.activeElement;
+        return el == this.searchInput || el == this.replaceInput;
+    };
+}).call(SearchBox.prototype);
+
+exports.SearchBox = SearchBox;
+
+exports.Search = function(editor, isReplace) {
+    var sb = editor.searchBox || new SearchBox(editor);
+    sb.show(editor.session.getTextRange(), isReplace);
+};
+
+});
+                (function() {
+                    ace.require(["ace/ext/searchbox"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 777 - 0
services/web/public/js/ace-1.4.3/ext-settings_menu.js

@@ -0,0 +1,777 @@
+ace.define("ace/ext/menu_tools/overlay_page",[], function(require, exports, module) {
+'use strict';
+var dom = require("../../lib/dom");
+var cssText = "#ace_settingsmenu, #kbshortcutmenu {\
+background-color: #F7F7F7;\
+color: black;\
+box-shadow: -5px 4px 5px rgba(126, 126, 126, 0.55);\
+padding: 1em 0.5em 2em 1em;\
+overflow: auto;\
+position: absolute;\
+margin: 0;\
+bottom: 0;\
+right: 0;\
+top: 0;\
+z-index: 9991;\
+cursor: default;\
+}\
+.ace_dark #ace_settingsmenu, .ace_dark #kbshortcutmenu {\
+box-shadow: -20px 10px 25px rgba(126, 126, 126, 0.25);\
+background-color: rgba(255, 255, 255, 0.6);\
+color: black;\
+}\
+.ace_optionsMenuEntry:hover {\
+background-color: rgba(100, 100, 100, 0.1);\
+transition: all 0.3s\
+}\
+.ace_closeButton {\
+background: rgba(245, 146, 146, 0.5);\
+border: 1px solid #F48A8A;\
+border-radius: 50%;\
+padding: 7px;\
+position: absolute;\
+right: -8px;\
+top: -8px;\
+z-index: 100000;\
+}\
+.ace_closeButton{\
+background: rgba(245, 146, 146, 0.9);\
+}\
+.ace_optionsMenuKey {\
+color: darkslateblue;\
+font-weight: bold;\
+}\
+.ace_optionsMenuCommand {\
+color: darkcyan;\
+font-weight: normal;\
+}\
+.ace_optionsMenuEntry input, .ace_optionsMenuEntry button {\
+vertical-align: middle;\
+}\
+.ace_optionsMenuEntry button[ace_selected_button=true] {\
+background: #e7e7e7;\
+box-shadow: 1px 0px 2px 0px #adadad inset;\
+border-color: #adadad;\
+}\
+.ace_optionsMenuEntry button {\
+background: white;\
+border: 1px solid lightgray;\
+margin: 0px;\
+}\
+.ace_optionsMenuEntry button:hover{\
+background: #f0f0f0;\
+}";
+dom.importCssString(cssText);
+module.exports.overlayPage = function overlayPage(editor, contentElement, top, right, bottom, left) {
+    top = top ? 'top: ' + top + ';' : '';
+    bottom = bottom ? 'bottom: ' + bottom + ';' : '';
+    right = right ? 'right: ' + right + ';' : '';
+    left = left ? 'left: ' + left + ';' : '';
+
+    var closer = document.createElement('div');
+    var contentContainer = document.createElement('div');
+
+    function documentEscListener(e) {
+        if (e.keyCode === 27) {
+            closer.click();
+        }
+    }
+
+    closer.style.cssText = 'margin: 0; padding: 0; ' +
+        'position: fixed; top:0; bottom:0; left:0; right:0;' +
+        'z-index: 9990; ' +
+        'background-color: rgba(0, 0, 0, 0.3);';
+    closer.addEventListener('click', function() {
+        document.removeEventListener('keydown', documentEscListener);
+        closer.parentNode.removeChild(closer);
+        editor.focus();
+        closer = null;
+    });
+    document.addEventListener('keydown', documentEscListener);
+
+    contentContainer.style.cssText = top + right + bottom + left;
+    contentContainer.addEventListener('click', function(e) {
+        e.stopPropagation();
+    });
+
+    var wrapper = dom.createElement("div");
+    wrapper.style.position = "relative";
+    
+    var closeButton = dom.createElement("div");
+    closeButton.className = "ace_closeButton";
+    closeButton.addEventListener('click', function() {
+        closer.click();
+    });
+    
+    wrapper.appendChild(closeButton);
+    contentContainer.appendChild(wrapper);
+    
+    contentContainer.appendChild(contentElement);
+    closer.appendChild(contentContainer);
+    document.body.appendChild(closer);
+    editor.blur();
+};
+
+});
+
+ace.define("ace/ext/modelist",[], function(require, exports, module) {
+"use strict";
+
+var modes = [];
+function getModeForPath(path) {
+    var mode = modesByName.text;
+    var fileName = path.split(/[\/\\]/).pop();
+    for (var i = 0; i < modes.length; i++) {
+        if (modes[i].supportsFile(fileName)) {
+            mode = modes[i];
+            break;
+        }
+    }
+    return mode;
+}
+
+var Mode = function(name, caption, extensions) {
+    this.name = name;
+    this.caption = caption;
+    this.mode = "ace/mode/" + name;
+    this.extensions = extensions;
+    var re;
+    if (/\^/.test(extensions)) {
+        re = extensions.replace(/\|(\^)?/g, function(a, b){
+            return "$|" + (b ? "^" : "^.*\\.");
+        }) + "$";
+    } else {
+        re = "^.*\\.(" + extensions + ")$";
+    }
+
+    this.extRe = new RegExp(re, "gi");
+};
+
+Mode.prototype.supportsFile = function(filename) {
+    return filename.match(this.extRe);
+};
+var supportedModes = {
+    ABAP:        ["abap"],
+    ABC:         ["abc"],
+    ActionScript:["as"],
+    ADA:         ["ada|adb"],
+    Apache_Conf: ["^htaccess|^htgroups|^htpasswd|^conf|htaccess|htgroups|htpasswd"],
+    AsciiDoc:    ["asciidoc|adoc"],
+    ASL:         ["dsl|asl"],
+    Assembly_x86:["asm|a"],
+    AutoHotKey:  ["ahk"],
+    Apex:        ["apex|cls|trigger|tgr"],
+    BatchFile:   ["bat|cmd"],
+    Bro:         ["bro"],
+    C_Cpp:       ["cpp|c|cc|cxx|h|hh|hpp|ino"],
+    C9Search:    ["c9search_results"],
+    Cirru:       ["cirru|cr"],
+    Clojure:     ["clj|cljs"],
+    Cobol:       ["CBL|COB"],
+    coffee:      ["coffee|cf|cson|^Cakefile"],
+    ColdFusion:  ["cfm"],
+    CSharp:      ["cs"],
+    Csound_Document: ["csd"],
+    Csound_Orchestra: ["orc"],
+    Csound_Score: ["sco"],
+    CSS:         ["css"],
+    Curly:       ["curly"],
+    D:           ["d|di"],
+    Dart:        ["dart"],
+    Diff:        ["diff|patch"],
+    Dockerfile:  ["^Dockerfile"],
+    Dot:         ["dot"],
+    Drools:      ["drl"],
+    Edifact:     ["edi"],
+    Eiffel:      ["e|ge"],
+    EJS:         ["ejs"],
+    Elixir:      ["ex|exs"],
+    Elm:         ["elm"],
+    Erlang:      ["erl|hrl"],
+    Forth:       ["frt|fs|ldr|fth|4th"],
+    Fortran:     ["f|f90"],
+    FSharp:      ["fsi|fs|ml|mli|fsx|fsscript"],
+    FSL:         ["fsl"],
+    FTL:         ["ftl"],
+    Gcode:       ["gcode"],
+    Gherkin:     ["feature"],
+    Gitignore:   ["^.gitignore"],
+    Glsl:        ["glsl|frag|vert"],
+    Gobstones:   ["gbs"],
+    golang:      ["go"],
+    GraphQLSchema: ["gql"],
+    Groovy:      ["groovy"],
+    HAML:        ["haml"],
+    Handlebars:  ["hbs|handlebars|tpl|mustache"],
+    Haskell:     ["hs"],
+    Haskell_Cabal: ["cabal"],
+    haXe:        ["hx"],
+    Hjson:       ["hjson"],
+    HTML:        ["html|htm|xhtml|vue|we|wpy"],
+    HTML_Elixir: ["eex|html.eex"],
+    HTML_Ruby:   ["erb|rhtml|html.erb"],
+    INI:         ["ini|conf|cfg|prefs"],
+    Io:          ["io"],
+    Jack:        ["jack"],
+    Jade:        ["jade|pug"],
+    Java:        ["java"],
+    JavaScript:  ["js|jsm|jsx"],
+    JSON:        ["json"],
+    JSONiq:      ["jq"],
+    JSP:         ["jsp"],
+    JSSM:        ["jssm|jssm_state"],
+    JSX:         ["jsx"],
+    Julia:       ["jl"],
+    Kotlin:      ["kt|kts"],
+    LaTeX:       ["tex|latex|ltx|bib"],
+    LESS:        ["less"],
+    Liquid:      ["liquid"],
+    Lisp:        ["lisp"],
+    LiveScript:  ["ls"],
+    LogiQL:      ["logic|lql"],
+    LSL:         ["lsl"],
+    Lua:         ["lua"],
+    LuaPage:     ["lp"],
+    Lucene:      ["lucene"],
+    Makefile:    ["^Makefile|^GNUmakefile|^makefile|^OCamlMakefile|make"],
+    Markdown:    ["md|markdown"],
+    Mask:        ["mask"],
+    MATLAB:      ["matlab"],
+    Maze:        ["mz"],
+    MEL:         ["mel"],
+    MIXAL:       ["mixal"],
+    MUSHCode:    ["mc|mush"],
+    MySQL:       ["mysql"],
+    Nix:         ["nix"],
+    NSIS:        ["nsi|nsh"],
+    ObjectiveC:  ["m|mm"],
+    OCaml:       ["ml|mli"],
+    Pascal:      ["pas|p"],
+    Perl:        ["pl|pm"],
+    Perl6:       ["p6|pl6|pm6"],
+    pgSQL:       ["pgsql"],
+    PHP_Laravel_blade: ["blade.php"],
+    PHP:         ["php|inc|phtml|shtml|php3|php4|php5|phps|phpt|aw|ctp|module"],
+    Puppet:      ["epp|pp"],
+    Pig:         ["pig"],
+    Powershell:  ["ps1"],
+    Praat:       ["praat|praatscript|psc|proc"],
+    Prolog:      ["plg|prolog"],
+    Properties:  ["properties"],
+    Protobuf:    ["proto"],
+    Python:      ["py"],
+    R:           ["r"],
+    Razor:       ["cshtml|asp"],
+    RDoc:        ["Rd"],
+    Red:         ["red|reds"],
+    RHTML:       ["Rhtml"],
+    RST:         ["rst"],
+    Ruby:        ["rb|ru|gemspec|rake|^Guardfile|^Rakefile|^Gemfile"],
+    Rust:        ["rs"],
+    SASS:        ["sass"],
+    SCAD:        ["scad"],
+    Scala:       ["scala"],
+    Scheme:      ["scm|sm|rkt|oak|scheme"],
+    SCSS:        ["scss"],
+    SH:          ["sh|bash|^.bashrc"],
+    SJS:         ["sjs"],
+    Slim:        ["slim|skim"],
+    Smarty:      ["smarty|tpl"],
+    snippets:    ["snippets"],
+    Soy_Template:["soy"],
+    Space:       ["space"],
+    SQL:         ["sql"],
+    SQLServer:   ["sqlserver"],
+    Stylus:      ["styl|stylus"],
+    SVG:         ["svg"],
+    Swift:       ["swift"],
+    Tcl:         ["tcl"],
+    Terraform:   ["tf", "tfvars", "terragrunt"],
+    Tex:         ["tex"],
+    Text:        ["txt"],
+    Textile:     ["textile"],
+    Toml:        ["toml"],
+    TSX:         ["tsx"],
+    Twig:        ["latte|twig|swig"],
+    Typescript:  ["ts|typescript|str"],
+    Vala:        ["vala"],
+    VBScript:    ["vbs|vb"],
+    Velocity:    ["vm"],
+    Verilog:     ["v|vh|sv|svh"],
+    VHDL:        ["vhd|vhdl"],
+    Visualforce: ["vfp|component|page"],
+    Wollok:      ["wlk|wpgm|wtest"],
+    XML:         ["xml|rdf|rss|wsdl|xslt|atom|mathml|mml|xul|xbl|xaml"],
+    XQuery:      ["xq"],
+    YAML:        ["yaml|yml"],
+    Django:      ["html"]
+};
+
+var nameOverrides = {
+    ObjectiveC: "Objective-C",
+    CSharp: "C#",
+    golang: "Go",
+    C_Cpp: "C and C++",
+    Csound_Document: "Csound Document",
+    Csound_Orchestra: "Csound",
+    Csound_Score: "Csound Score",
+    coffee: "CoffeeScript",
+    HTML_Ruby: "HTML (Ruby)",
+    HTML_Elixir: "HTML (Elixir)",
+    FTL: "FreeMarker",
+    PHP_Laravel_blade: "PHP (Blade Template)",
+    Perl6: "Perl 6",
+    AutoHotKey: "AutoHotkey / AutoIt"
+};
+var modesByName = {};
+for (var name in supportedModes) {
+    var data = supportedModes[name];
+    var displayName = (nameOverrides[name] || name).replace(/_/g, " ");
+    var filename = name.toLowerCase();
+    var mode = new Mode(filename, displayName, data[0]);
+    modesByName[filename] = mode;
+    modes.push(mode);
+}
+
+module.exports = {
+    getModeForPath: getModeForPath,
+    modes: modes,
+    modesByName: modesByName
+};
+
+});
+
+ace.define("ace/ext/themelist",[], function(require, exports, module) {
+"use strict";
+
+var themeData = [
+    ["Chrome"         ],
+    ["Clouds"         ],
+    ["Crimson Editor" ],
+    ["Dawn"           ],
+    ["Dreamweaver"    ],
+    ["Eclipse"        ],
+    ["GitHub"         ],
+    ["IPlastic"       ],
+    ["Solarized Light"],
+    ["TextMate"       ],
+    ["Tomorrow"       ],
+    ["XCode"          ],
+    ["Kuroir"],
+    ["KatzenMilch"],
+    ["SQL Server"           ,"sqlserver"               , "light"],
+    ["Ambiance"             ,"ambiance"                ,  "dark"],
+    ["Chaos"                ,"chaos"                   ,  "dark"],
+    ["Clouds Midnight"      ,"clouds_midnight"         ,  "dark"],
+    ["Dracula"              ,""                        ,  "dark"],
+    ["Cobalt"               ,"cobalt"                  ,  "dark"],
+    ["Gruvbox"              ,"gruvbox"                 ,  "dark"],
+    ["Green on Black"       ,"gob"                     ,  "dark"],
+    ["idle Fingers"         ,"idle_fingers"            ,  "dark"],
+    ["krTheme"              ,"kr_theme"                ,  "dark"],
+    ["Merbivore"            ,"merbivore"               ,  "dark"],
+    ["Merbivore Soft"       ,"merbivore_soft"          ,  "dark"],
+    ["Mono Industrial"      ,"mono_industrial"         ,  "dark"],
+    ["Monokai"              ,"monokai"                 ,  "dark"],
+    ["Pastel on dark"       ,"pastel_on_dark"          ,  "dark"],
+    ["Solarized Dark"       ,"solarized_dark"          ,  "dark"],
+    ["Terminal"             ,"terminal"                ,  "dark"],
+    ["Tomorrow Night"       ,"tomorrow_night"          ,  "dark"],
+    ["Tomorrow Night Blue"  ,"tomorrow_night_blue"     ,  "dark"],
+    ["Tomorrow Night Bright","tomorrow_night_bright"   ,  "dark"],
+    ["Tomorrow Night 80s"   ,"tomorrow_night_eighties" ,  "dark"],
+    ["Twilight"             ,"twilight"                ,  "dark"],
+    ["Vibrant Ink"          ,"vibrant_ink"             ,  "dark"]
+];
+
+
+exports.themesByName = {};
+exports.themes = themeData.map(function(data) {
+    var name = data[1] || data[0].replace(/ /g, "_").toLowerCase();
+    var theme = {
+        caption: data[0],
+        theme: "ace/theme/" + name,
+        isDark: data[2] == "dark",
+        name: name
+    };
+    exports.themesByName[name] = theme;
+    return theme;
+});
+
+});
+
+ace.define("ace/ext/options",[], function(require, exports, module) {
+"use strict";
+var overlayPage = require('./menu_tools/overlay_page').overlayPage;
+
+ 
+var dom = require("../lib/dom");
+var oop = require("../lib/oop");
+var EventEmitter = require("../lib/event_emitter").EventEmitter;
+var buildDom = dom.buildDom;
+
+var modelist = require("./modelist");
+var themelist = require("./themelist");
+
+var themes = { Bright: [], Dark: [] };
+themelist.themes.forEach(function(x) {
+    themes[x.isDark ? "Dark" : "Bright"].push({ caption: x.caption, value: x.theme });
+});
+
+var modes = modelist.modes.map(function(x){ 
+    return { caption: x.caption, value: x.mode }; 
+});
+
+
+var optionGroups = {
+    Main: {
+        Mode: {
+            path: "mode",
+            type: "select",
+            items: modes
+        },
+        Theme: {
+            path: "theme",
+            type: "select",
+            items: themes
+        },
+        "Keybinding": {
+            type: "buttonBar",
+            path: "keyboardHandler",
+            items: [
+                { caption : "Ace", value : null },
+                { caption : "Vim", value : "ace/keyboard/vim" },
+                { caption : "Emacs", value : "ace/keyboard/emacs" },
+                { caption : "Sublime", value : "ace/keyboard/sublime" }
+            ]
+        },
+        "Font Size": {
+            path: "fontSize",
+            type: "number",
+            defaultValue: 12,
+            defaults: [
+                {caption: "12px", value: 12},
+                {caption: "24px", value: 24}
+            ]
+        },
+        "Soft Wrap": {
+            type: "buttonBar",
+            path: "wrap",
+            items: [
+               { caption : "Off",  value : "off" },
+               { caption : "View", value : "free" },
+               { caption : "margin", value : "printMargin" },
+               { caption : "40",   value : "40" }
+            ]
+        },
+        "Cursor Style": {
+            path: "cursorStyle",
+            items: [
+               { caption : "Ace",    value : "ace" },
+               { caption : "Slim",   value : "slim" },
+               { caption : "Smooth", value : "smooth" },
+               { caption : "Smooth And Slim", value : "smooth slim" },
+               { caption : "Wide",   value : "wide" }
+            ]
+        },
+        "Folding": {
+            path: "foldStyle",
+            items: [
+                { caption : "Manual", value : "manual" },
+                { caption : "Mark begin", value : "markbegin" },
+                { caption : "Mark begin and end", value : "markbeginend" }
+            ]
+        },
+        "Soft Tabs": [{
+            path: "useSoftTabs"
+        }, {
+            path: "tabSize",
+            type: "number",
+            values: [2, 3, 4, 8, 16]
+        }],
+        "Overscroll": {
+            type: "buttonBar",
+            path: "scrollPastEnd",
+            items: [
+               { caption : "None",  value : 0 },
+               { caption : "Half",   value : 0.5 },
+               { caption : "Full",   value : 1 }
+            ]
+        }
+    },
+    More: {
+        "Atomic soft tabs": {
+            path: "navigateWithinSoftTabs"
+        },
+        "Enable Behaviours": {
+            path: "behavioursEnabled"
+        },
+        "Full Line Selection": {
+            type: "checkbox",
+            values: "text|line",
+            path: "selectionStyle"
+        },
+        "Highlight Active Line": {
+            path: "highlightActiveLine"
+        },
+        "Show Invisibles": {
+            path: "showInvisibles"
+        },
+        "Show Indent Guides": {
+            path: "displayIndentGuides"
+        },
+        "Persistent Scrollbar": [{
+            path: "hScrollBarAlwaysVisible"
+        }, {
+            path: "vScrollBarAlwaysVisible"
+        }],
+        "Animate scrolling": {
+            path: "animatedScroll"
+        },
+        "Show Gutter": {
+            path: "showGutter"
+        },
+        "Show Line Numbers": {
+            path: "showLineNumbers"
+        },
+        "Relative Line Numbers": {
+            path: "relativeLineNumbers"
+        },
+        "Fixed Gutter Width": {
+            path: "fixedWidthGutter"
+        },
+        "Show Print Margin": [{
+            path: "showPrintMargin"
+        }, {
+            type: "number",
+            path: "printMarginColumn"
+        }],
+        "Indented Soft Wrap": {
+            path: "indentedSoftWrap"
+        },
+        "Highlight selected word": {
+            path: "highlightSelectedWord"
+        },
+        "Fade Fold Widgets": {
+            path: "fadeFoldWidgets"
+        },
+        "Use textarea for IME": {
+            path: "useTextareaForIME"
+        },
+        "Merge Undo Deltas": {
+            path: "mergeUndoDeltas",
+            items: [
+               { caption : "Always",  value : "always" },
+               { caption : "Never",   value : "false" },
+               { caption : "Timed",   value : "true" }
+            ]
+        },
+        "Elastic Tabstops": {
+            path: "useElasticTabstops"
+        },
+        "Incremental Search": {
+            path: "useIncrementalSearch"
+        },
+        "Read-only": {
+            path: "readOnly"
+        },
+        "Copy without selection": {
+            path: "copyWithEmptySelection"
+        },
+        "Live Autocompletion": {
+            path: "enableLiveAutocompletion"
+        }
+    }
+};
+
+
+var OptionPanel = function(editor, element) {
+    this.editor = editor;
+    this.container = element || document.createElement("div");
+    this.groups = [];
+    this.options = {};
+};
+
+(function() {
+    
+    oop.implement(this, EventEmitter);
+    
+    this.add = function(config) {
+        if (config.Main)
+            oop.mixin(optionGroups.Main, config.Main);
+        if (config.More)
+            oop.mixin(optionGroups.More, config.More);
+    };
+    
+    this.render = function() {
+        this.container.innerHTML = "";
+        buildDom(["table", {id: "controls"}, 
+            this.renderOptionGroup(optionGroups.Main),
+            ["tr", null, ["td", {colspan: 2},
+                ["table", {id: "more-controls"}, 
+                    this.renderOptionGroup(optionGroups.More)
+                ]
+            ]]
+        ], this.container);
+    };
+    
+    this.renderOptionGroup = function(group) {
+        return Object.keys(group).map(function(key, i) {
+            var item = group[key];
+            if (!item.position)
+                item.position = i / 10000;
+            if (!item.label)
+                item.label = key;
+            return item;
+        }).sort(function(a, b) {
+            return a.position - b.position;
+        }).map(function(item) {
+            return this.renderOption(item.label, item);
+        }, this);
+    };
+    
+    this.renderOptionControl = function(key, option) {
+        var self = this;
+        if (Array.isArray(option)) {
+            return option.map(function(x) {
+                return self.renderOptionControl(key, x);
+            });
+        }
+        var control;
+        
+        var value = self.getOption(option);
+        
+        if (option.values && option.type != "checkbox") {
+            if (typeof option.values == "string")
+                option.values = option.values.split("|");
+            option.items = option.values.map(function(v) {
+                return { value: v, name: v };
+            });
+        }
+        
+        if (option.type == "buttonBar") {
+            control = ["div", option.items.map(function(item) {
+                return ["button", { 
+                    value: item.value, 
+                    ace_selected_button: value == item.value, 
+                    onclick: function() {
+                        self.setOption(option, item.value);
+                        var nodes = this.parentNode.querySelectorAll("[ace_selected_button]");
+                        for (var i = 0; i < nodes.length; i++) {
+                            nodes[i].removeAttribute("ace_selected_button");
+                        }
+                        this.setAttribute("ace_selected_button", true);
+                    } 
+                }, item.desc || item.caption || item.name];
+            })];
+        } else if (option.type == "number") {
+            control = ["input", {type: "number", value: value || option.defaultValue, style:"width:3em", oninput: function() {
+                self.setOption(option, parseInt(this.value));
+            }}];
+            if (option.defaults) {
+                control = [control, option.defaults.map(function(item) {
+                    return ["button", {onclick: function() {
+                        var input = this.parentNode.firstChild;
+                        input.value = item.value;
+                        input.oninput();
+                    }}, item.caption];
+                })];
+            }
+        } else if (option.items) {
+            var buildItems = function(items) {
+                return items.map(function(item) {
+                    return ["option", { value: item.value || item.name }, item.desc || item.caption || item.name];
+                });
+            };
+            
+            var items = Array.isArray(option.items) 
+                ? buildItems(option.items)
+                : Object.keys(option.items).map(function(key) {
+                    return ["optgroup", {"label": key}, buildItems(option.items[key])];
+                });
+            control = ["select", { id: key, value: value, onchange: function() {
+                self.setOption(option, this.value);
+            } }, items];
+        } else {
+            if (typeof option.values == "string")
+                option.values = option.values.split("|");
+            if (option.values) value = value == option.values[1];
+            control = ["input", { type: "checkbox", id: key, checked: value || null, onchange: function() {
+                var value = this.checked;
+                if (option.values) value = option.values[value ? 1 : 0];
+                self.setOption(option, value);
+            }}];
+            if (option.type == "checkedNumber") {
+                control = [control, []];
+            }
+        }
+        return control;
+    };
+    
+    this.renderOption = function(key, option) {
+        if (option.path && !option.onchange && !this.editor.$options[option.path])
+            return;
+        this.options[option.path] = option;
+        var safeKey = "-" + option.path;
+        var control = this.renderOptionControl(safeKey, option);
+        return ["tr", {class: "ace_optionsMenuEntry"}, ["td",
+            ["label", {for: safeKey}, key]
+        ], ["td", control]];
+    };
+    
+    this.setOption = function(option, value) {
+        if (typeof option == "string")
+            option = this.options[option];
+        if (value == "false") value = false;
+        if (value == "true") value = true;
+        if (value == "null") value = null;
+        if (value == "undefined") value = undefined;
+        if (typeof value == "string" && parseFloat(value).toString() == value)
+            value = parseFloat(value);
+        if (option.onchange)
+            option.onchange(value);
+        else if (option.path)
+            this.editor.setOption(option.path, value);
+        this._signal("setOption", {name: option.path, value: value});
+    };
+    
+    this.getOption = function(option) {
+        if (option.getValue)
+            return option.getValue();
+        return this.editor.getOption(option.path);
+    };
+    
+}).call(OptionPanel.prototype);
+
+exports.OptionPanel = OptionPanel;
+
+});
+
+ace.define("ace/ext/settings_menu",[], function(require, exports, module) {
+"use strict";
+var OptionPanel = require("ace/ext/options").OptionPanel;
+var overlayPage = require('./menu_tools/overlay_page').overlayPage;
+function showSettingsMenu(editor) {
+    if (!document.getElementById('ace_settingsmenu')) {
+        var options = new OptionPanel(editor);
+        options.render();
+        options.container.id = "ace_settingsmenu";
+        overlayPage(editor, options.container, '0', '0', '0');
+        options.container.querySelector("select,input,button,checkbox").focus();
+    }
+}
+module.exports.init = function(editor) {
+    var Editor = require("ace/editor").Editor;
+    Editor.prototype.showSettingsMenu = function() {
+        showSettingsMenu(this);
+    };
+};
+});
+                (function() {
+                    ace.require(["ace/ext/settings_menu"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 75 - 0
services/web/public/js/ace-1.4.3/ext-spellcheck.js

@@ -0,0 +1,75 @@
+ace.define("ace/ext/spellcheck",[], function(require, exports, module) {
+"use strict";
+var event = require("../lib/event");
+
+exports.contextMenuHandler = function(e){
+    var host = e.target;
+    var text = host.textInput.getElement();
+    if (!host.selection.isEmpty())
+        return;
+    var c = host.getCursorPosition();
+    var r = host.session.getWordRange(c.row, c.column);
+    var w = host.session.getTextRange(r);
+
+    host.session.tokenRe.lastIndex = 0;
+    if (!host.session.tokenRe.test(w))
+        return;
+    var PLACEHOLDER = "\x01\x01";
+    var value = w + " " + PLACEHOLDER;
+    text.value = value;
+    text.setSelectionRange(w.length, w.length + 1);
+    text.setSelectionRange(0, 0);
+    text.setSelectionRange(0, w.length);
+
+    var afterKeydown = false;
+    event.addListener(text, "keydown", function onKeydown() {
+        event.removeListener(text, "keydown", onKeydown);
+        afterKeydown = true;
+    });
+
+    host.textInput.setInputHandler(function(newVal) {
+        console.log(newVal , value, text.selectionStart, text.selectionEnd);
+        if (newVal == value)
+            return '';
+        if (newVal.lastIndexOf(value, 0) === 0)
+            return newVal.slice(value.length);
+        if (newVal.substr(text.selectionEnd) == value)
+            return newVal.slice(0, -value.length);
+        if (newVal.slice(-2) == PLACEHOLDER) {
+            var val = newVal.slice(0, -2);
+            if (val.slice(-1) == " ") {
+                if (afterKeydown)
+                    return val.substring(0, text.selectionEnd);
+                val = val.slice(0, -1);
+                host.session.replace(r, val);
+                return "";
+            }
+        }
+
+        return newVal;
+    });
+};
+var Editor = require("../editor").Editor;
+require("../config").defineOptions(Editor.prototype, "editor", {
+    spellcheck: {
+        set: function(val) {
+            var text = this.textInput.getElement();
+            text.spellcheck = !!val;
+            if (!val)
+                this.removeListener("nativecontextmenu", exports.contextMenuHandler);
+            else
+                this.on("nativecontextmenu", exports.contextMenuHandler);
+        },
+        value: true
+    }
+});
+
+});
+                (function() {
+                    ace.require(["ace/ext/spellcheck"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 208 - 0
services/web/public/js/ace-1.4.3/ext-split.js

@@ -0,0 +1,208 @@
+ace.define("ace/split",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("./lib/oop");
+var lang = require("./lib/lang");
+var EventEmitter = require("./lib/event_emitter").EventEmitter;
+
+var Editor = require("./editor").Editor;
+var Renderer = require("./virtual_renderer").VirtualRenderer;
+var EditSession = require("./edit_session").EditSession;
+
+
+var Split = function(container, theme, splits) {
+    this.BELOW = 1;
+    this.BESIDE = 0;
+
+    this.$container = container;
+    this.$theme = theme;
+    this.$splits = 0;
+    this.$editorCSS = "";
+    this.$editors = [];
+    this.$orientation = this.BESIDE;
+
+    this.setSplits(splits || 1);
+    this.$cEditor = this.$editors[0];
+
+
+    this.on("focus", function(editor) {
+        this.$cEditor = editor;
+    }.bind(this));
+};
+
+(function(){
+
+    oop.implement(this, EventEmitter);
+
+    this.$createEditor = function() {
+        var el = document.createElement("div");
+        el.className = this.$editorCSS;
+        el.style.cssText = "position: absolute; top:0px; bottom:0px";
+        this.$container.appendChild(el);
+        var editor = new Editor(new Renderer(el, this.$theme));
+
+        editor.on("focus", function() {
+            this._emit("focus", editor);
+        }.bind(this));
+
+        this.$editors.push(editor);
+        editor.setFontSize(this.$fontSize);
+        return editor;
+    };
+
+    this.setSplits = function(splits) {
+        var editor;
+        if (splits < 1) {
+            throw "The number of splits have to be > 0!";
+        }
+
+        if (splits == this.$splits) {
+            return;
+        } else if (splits > this.$splits) {
+            while (this.$splits < this.$editors.length && this.$splits < splits) {
+                editor = this.$editors[this.$splits];
+                this.$container.appendChild(editor.container);
+                editor.setFontSize(this.$fontSize);
+                this.$splits ++;
+            }
+            while (this.$splits < splits) {
+                this.$createEditor();
+                this.$splits ++;
+            }
+        } else {
+            while (this.$splits > splits) {
+                editor = this.$editors[this.$splits - 1];
+                this.$container.removeChild(editor.container);
+                this.$splits --;
+            }
+        }
+        this.resize();
+    };
+    this.getSplits = function() {
+        return this.$splits;
+    };
+    this.getEditor = function(idx) {
+        return this.$editors[idx];
+    };
+    this.getCurrentEditor = function() {
+        return this.$cEditor;
+    };
+    this.focus = function() {
+        this.$cEditor.focus();
+    };
+    this.blur = function() {
+        this.$cEditor.blur();
+    };
+    this.setTheme = function(theme) {
+        this.$editors.forEach(function(editor) {
+            editor.setTheme(theme);
+        });
+    };
+    this.setKeyboardHandler = function(keybinding) {
+        this.$editors.forEach(function(editor) {
+            editor.setKeyboardHandler(keybinding);
+        });
+    };
+    this.forEach = function(callback, scope) {
+        this.$editors.forEach(callback, scope);
+    };
+
+
+    this.$fontSize = "";
+    this.setFontSize = function(size) {
+        this.$fontSize = size;
+        this.forEach(function(editor) {
+           editor.setFontSize(size);
+        });
+    };
+
+    this.$cloneSession = function(session) {
+        var s = new EditSession(session.getDocument(), session.getMode());
+
+        var undoManager = session.getUndoManager();
+        s.setUndoManager(undoManager);
+        s.setTabSize(session.getTabSize());
+        s.setUseSoftTabs(session.getUseSoftTabs());
+        s.setOverwrite(session.getOverwrite());
+        s.setBreakpoints(session.getBreakpoints());
+        s.setUseWrapMode(session.getUseWrapMode());
+        s.setUseWorker(session.getUseWorker());
+        s.setWrapLimitRange(session.$wrapLimitRange.min,
+                            session.$wrapLimitRange.max);
+        s.$foldData = session.$cloneFoldData();
+
+        return s;
+    };
+    this.setSession = function(session, idx) {
+        var editor;
+        if (idx == null) {
+            editor = this.$cEditor;
+        } else {
+            editor = this.$editors[idx];
+        }
+        var isUsed = this.$editors.some(function(editor) {
+           return editor.session === session;
+        });
+
+        if (isUsed) {
+            session = this.$cloneSession(session);
+        }
+        editor.setSession(session);
+        return session;
+    };
+    this.getOrientation = function() {
+        return this.$orientation;
+    };
+    this.setOrientation = function(orientation) {
+        if (this.$orientation == orientation) {
+            return;
+        }
+        this.$orientation = orientation;
+        this.resize();
+    };
+    this.resize = function() {
+        var width = this.$container.clientWidth;
+        var height = this.$container.clientHeight;
+        var editor;
+
+        if (this.$orientation == this.BESIDE) {
+            var editorWidth = width / this.$splits;
+            for (var i = 0; i < this.$splits; i++) {
+                editor = this.$editors[i];
+                editor.container.style.width = editorWidth + "px";
+                editor.container.style.top = "0px";
+                editor.container.style.left = i * editorWidth + "px";
+                editor.container.style.height = height + "px";
+                editor.resize();
+            }
+        } else {
+            var editorHeight = height / this.$splits;
+            for (var i = 0; i < this.$splits; i++) {
+                editor = this.$editors[i];
+                editor.container.style.width = width + "px";
+                editor.container.style.top = i * editorHeight + "px";
+                editor.container.style.left = "0px";
+                editor.container.style.height = editorHeight + "px";
+                editor.resize();
+            }
+        }
+    };
+
+}).call(Split.prototype);
+
+exports.Split = Split;
+});
+
+ace.define("ace/ext/split",[], function(require, exports, module) {
+"use strict";
+module.exports = require("../split");
+
+});
+                (function() {
+                    ace.require(["ace/ext/split"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 230 - 0
services/web/public/js/ace-1.4.3/ext-static_highlight.js

@@ -0,0 +1,230 @@
+ace.define("ace/ext/static_highlight",[], function(require, exports, module) {
+"use strict";
+
+var EditSession = require("../edit_session").EditSession;
+var TextLayer = require("../layer/text").Text;
+var baseStyles = ".ace_static_highlight {\
+font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', 'Droid Sans Mono', monospace;\
+font-size: 12px;\
+white-space: pre-wrap\
+}\
+.ace_static_highlight .ace_gutter {\
+width: 2em;\
+text-align: right;\
+padding: 0 3px 0 0;\
+margin-right: 3px;\
+contain: none;\
+}\
+.ace_static_highlight.ace_show_gutter .ace_line {\
+padding-left: 2.6em;\
+}\
+.ace_static_highlight .ace_line { position: relative; }\
+.ace_static_highlight .ace_gutter-cell {\
+-moz-user-select: -moz-none;\
+-khtml-user-select: none;\
+-webkit-user-select: none;\
+user-select: none;\
+top: 0;\
+bottom: 0;\
+left: 0;\
+position: absolute;\
+}\
+.ace_static_highlight .ace_gutter-cell:before {\
+content: counter(ace_line, decimal);\
+counter-increment: ace_line;\
+}\
+.ace_static_highlight {\
+counter-reset: ace_line;\
+}\
+";
+var config = require("../config");
+var dom = require("../lib/dom");
+var escapeHTML = require("../lib/lang").escapeHTML;
+
+function Element(type) {
+    this.type = type;
+    this.style = {};
+    this.textContent = "";
+}
+Element.prototype.cloneNode = function() {
+    return this;
+};
+Element.prototype.appendChild = function(child) {
+    this.textContent += child.toString();
+};
+Element.prototype.toString = function() {
+    var stringBuilder = [];
+    if (this.type != "fragment") {
+        stringBuilder.push("<", this.type);
+        if (this.className)
+            stringBuilder.push(" class='", this.className, "'");
+        var styleStr = [];
+        for (var key in this.style) {
+            styleStr.push(key, ":", this.style[key]);
+        }
+        if (styleStr.length)
+            stringBuilder.push(" style='", styleStr.join(""), "'");
+        stringBuilder.push(">");
+    }
+
+    if (this.textContent) {
+        stringBuilder.push(this.textContent);
+    }
+
+    if (this.type != "fragment") {
+        stringBuilder.push("</", this.type, ">");
+    }
+    
+    return stringBuilder.join("");
+};
+
+
+var simpleDom = {
+    createTextNode: function(textContent, element) {
+        return escapeHTML(textContent);
+    },
+    createElement: function(type) {
+        return new Element(type);
+    },
+    createFragment: function() {
+        return new Element("fragment");
+    }
+};
+
+var SimpleTextLayer = function() {
+    this.config = {};
+    this.dom = simpleDom;
+};
+SimpleTextLayer.prototype = TextLayer.prototype;
+
+var highlight = function(el, opts, callback) {
+    var m = el.className.match(/lang-(\w+)/);
+    var mode = opts.mode || m && ("ace/mode/" + m[1]);
+    if (!mode)
+        return false;
+    var theme = opts.theme || "ace/theme/textmate";
+    
+    var data = "";
+    var nodes = [];
+
+    if (el.firstElementChild) {
+        var textLen = 0;
+        for (var i = 0; i < el.childNodes.length; i++) {
+            var ch = el.childNodes[i];
+            if (ch.nodeType == 3) {
+                textLen += ch.data.length;
+                data += ch.data;
+            } else {
+                nodes.push(textLen, ch);
+            }
+        }
+    } else {
+        data = el.textContent;
+        if (opts.trim)
+            data = data.trim();
+    }
+    
+    highlight.render(data, mode, theme, opts.firstLineNumber, !opts.showGutter, function (highlighted) {
+        dom.importCssString(highlighted.css, "ace_highlight");
+        el.innerHTML = highlighted.html;
+        var container = el.firstChild.firstChild;
+        for (var i = 0; i < nodes.length; i += 2) {
+            var pos = highlighted.session.doc.indexToPosition(nodes[i]);
+            var node = nodes[i + 1];
+            var lineEl = container.children[pos.row];
+            lineEl && lineEl.appendChild(node);
+        }
+        callback && callback();
+    });
+};
+highlight.render = function(input, mode, theme, lineStart, disableGutter, callback) {
+    var waiting = 1;
+    var modeCache = EditSession.prototype.$modes;
+    if (typeof theme == "string") {
+        waiting++;
+        config.loadModule(['theme', theme], function(m) {
+            theme = m;
+            --waiting || done();
+        });
+    }
+    var modeOptions;
+    if (mode && typeof mode === "object" && !mode.getTokenizer) {
+        modeOptions = mode;
+        mode = modeOptions.path;
+    }
+    if (typeof mode == "string") {
+        waiting++;
+        config.loadModule(['mode', mode], function(m) {
+            if (!modeCache[mode] || modeOptions)
+                modeCache[mode] = new m.Mode(modeOptions);
+            mode = modeCache[mode];
+            --waiting || done();
+        });
+    }
+    function done() {
+        var result = highlight.renderSync(input, mode, theme, lineStart, disableGutter);
+        return callback ? callback(result) : result;
+    }
+    return --waiting || done();
+};
+highlight.renderSync = function(input, mode, theme, lineStart, disableGutter) {
+    lineStart = parseInt(lineStart || 1, 10);
+
+    var session = new EditSession("");
+    session.setUseWorker(false);
+    session.setMode(mode);
+
+    var textLayer = new SimpleTextLayer();
+    textLayer.setSession(session);
+    Object.keys(textLayer.$tabStrings).forEach(function(k) {
+        if (typeof textLayer.$tabStrings[k] == "string") {
+            var el = simpleDom.createFragment();
+            el.textContent = textLayer.$tabStrings[k];
+            textLayer.$tabStrings[k] = el;
+        }
+    });
+
+    session.setValue(input);
+    var length =  session.getLength();
+    
+    var outerEl = simpleDom.createElement("div");
+    outerEl.className = theme.cssClass;
+    
+    var innerEl = simpleDom.createElement("div");
+    innerEl.className = "ace_static_highlight" + (disableGutter ? "" : " ace_show_gutter");
+    innerEl.style["counter-reset"] = "ace_line " + (lineStart - 1);
+
+    for (var ix = 0; ix < length; ix++) {
+        var lineEl = simpleDom.createElement("div");
+        lineEl.className = "ace_line";
+        
+        if (!disableGutter) {
+            var gutterEl = simpleDom.createElement("span");
+            gutterEl.className ="ace_gutter ace_gutter-cell";
+            gutterEl.textContent = "";
+            lineEl.appendChild(gutterEl);
+        }
+        textLayer.$renderLine(lineEl, ix, false);
+        lineEl.textContent += "\n";
+        innerEl.appendChild(lineEl);
+    }
+    outerEl.appendChild(innerEl);
+
+    return {
+        css: baseStyles + theme.cssText,
+        html: outerEl.toString(),
+        session: session
+    };
+};
+
+module.exports = highlight;
+module.exports.highlight = highlight;
+});
+                (function() {
+                    ace.require(["ace/ext/static_highlight"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 57 - 0
services/web/public/js/ace-1.4.3/ext-statusbar.js

@@ -0,0 +1,57 @@
+ace.define("ace/ext/statusbar",[], function(require, exports, module) {
+"use strict";
+var dom = require("ace/lib/dom");
+var lang = require("ace/lib/lang");
+
+var StatusBar = function(editor, parentNode) {
+    this.element = dom.createElement("div");
+    this.element.className = "ace_status-indicator";
+    this.element.style.cssText = "display: inline-block;";
+    parentNode.appendChild(this.element);
+
+    var statusUpdate = lang.delayedCall(function(){
+        this.updateStatus(editor);
+    }.bind(this)).schedule.bind(null, 100);
+    
+    editor.on("changeStatus", statusUpdate);
+    editor.on("changeSelection", statusUpdate);
+    editor.on("keyboardActivity", statusUpdate);
+};
+
+(function(){
+    this.updateStatus = function(editor) {
+        var status = [];
+        function add(str, separator) {
+            str && status.push(str, separator || "|");
+        }
+
+        add(editor.keyBinding.getStatusText(editor));
+        if (editor.commands.recording)
+            add("REC");
+        
+        var sel = editor.selection;
+        var c = sel.lead;
+        
+        if (!sel.isEmpty()) {
+            var r = editor.getSelectionRange();
+            add("(" + (r.end.row - r.start.row) + ":"  +(r.end.column - r.start.column) + ")", " ");
+        }
+        add(c.row + ":" + c.column, " ");        
+        if (sel.rangeCount)
+            add("[" + sel.rangeCount + "]", " ");
+        status.pop();
+        this.element.textContent = status.join("");
+    };
+}).call(StatusBar.prototype);
+
+exports.StatusBar = StatusBar;
+
+});
+                (function() {
+                    ace.require(["ace/ext/statusbar"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 564 - 0
services/web/public/js/ace-1.4.3/ext-textarea.js

@@ -0,0 +1,564 @@
+ace.define("ace/theme/textmate",[], function(require, exports, module) {
+"use strict";
+
+exports.isDark = false;
+exports.cssClass = "ace-tm";
+exports.cssText = ".ace-tm .ace_gutter {\
+background: #f0f0f0;\
+color: #333;\
+}\
+.ace-tm .ace_print-margin {\
+width: 1px;\
+background: #e8e8e8;\
+}\
+.ace-tm .ace_fold {\
+background-color: #6B72E6;\
+}\
+.ace-tm {\
+background-color: #FFFFFF;\
+color: black;\
+}\
+.ace-tm .ace_cursor {\
+color: black;\
+}\
+.ace-tm .ace_invisible {\
+color: rgb(191, 191, 191);\
+}\
+.ace-tm .ace_storage,\
+.ace-tm .ace_keyword {\
+color: blue;\
+}\
+.ace-tm .ace_constant {\
+color: rgb(197, 6, 11);\
+}\
+.ace-tm .ace_constant.ace_buildin {\
+color: rgb(88, 72, 246);\
+}\
+.ace-tm .ace_constant.ace_language {\
+color: rgb(88, 92, 246);\
+}\
+.ace-tm .ace_constant.ace_library {\
+color: rgb(6, 150, 14);\
+}\
+.ace-tm .ace_invalid {\
+background-color: rgba(255, 0, 0, 0.1);\
+color: red;\
+}\
+.ace-tm .ace_support.ace_function {\
+color: rgb(60, 76, 114);\
+}\
+.ace-tm .ace_support.ace_constant {\
+color: rgb(6, 150, 14);\
+}\
+.ace-tm .ace_support.ace_type,\
+.ace-tm .ace_support.ace_class {\
+color: rgb(109, 121, 222);\
+}\
+.ace-tm .ace_keyword.ace_operator {\
+color: rgb(104, 118, 135);\
+}\
+.ace-tm .ace_string {\
+color: rgb(3, 106, 7);\
+}\
+.ace-tm .ace_comment {\
+color: rgb(76, 136, 107);\
+}\
+.ace-tm .ace_comment.ace_doc {\
+color: rgb(0, 102, 255);\
+}\
+.ace-tm .ace_comment.ace_doc.ace_tag {\
+color: rgb(128, 159, 191);\
+}\
+.ace-tm .ace_constant.ace_numeric {\
+color: rgb(0, 0, 205);\
+}\
+.ace-tm .ace_variable {\
+color: rgb(49, 132, 149);\
+}\
+.ace-tm .ace_xml-pe {\
+color: rgb(104, 104, 91);\
+}\
+.ace-tm .ace_entity.ace_name.ace_function {\
+color: #0000A2;\
+}\
+.ace-tm .ace_heading {\
+color: rgb(12, 7, 255);\
+}\
+.ace-tm .ace_list {\
+color:rgb(185, 6, 144);\
+}\
+.ace-tm .ace_meta.ace_tag {\
+color:rgb(0, 22, 142);\
+}\
+.ace-tm .ace_string.ace_regex {\
+color: rgb(255, 0, 0)\
+}\
+.ace-tm .ace_marker-layer .ace_selection {\
+background: rgb(181, 213, 255);\
+}\
+.ace-tm.ace_multiselect .ace_selection.ace_start {\
+box-shadow: 0 0 3px 0px white;\
+}\
+.ace-tm .ace_marker-layer .ace_step {\
+background: rgb(252, 255, 0);\
+}\
+.ace-tm .ace_marker-layer .ace_stack {\
+background: rgb(164, 229, 101);\
+}\
+.ace-tm .ace_marker-layer .ace_bracket {\
+margin: -1px 0 0 -1px;\
+border: 1px solid rgb(192, 192, 192);\
+}\
+.ace-tm .ace_marker-layer .ace_active-line {\
+background: rgba(0, 0, 0, 0.07);\
+}\
+.ace-tm .ace_gutter-active-line {\
+background-color : #dcdcdc;\
+}\
+.ace-tm .ace_marker-layer .ace_selected-word {\
+background: rgb(250, 250, 255);\
+border: 1px solid rgb(200, 200, 250);\
+}\
+.ace-tm .ace_indent-guide {\
+background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==\") right repeat-y;\
+}\
+";
+exports.$id = "ace/theme/textmate";
+
+var dom = require("../lib/dom");
+dom.importCssString(exports.cssText, exports.cssClass);
+});
+
+ace.define("ace/ext/textarea",[], function(require, exports, module) {
+"use strict";
+
+var event = require("../lib/event");
+var UA = require("../lib/useragent");
+var net = require("../lib/net");
+var ace = require("../ace");
+
+require("../theme/textmate");
+
+module.exports = exports = ace;
+var getCSSProperty = function(element, container, property) {
+    var ret = element.style[property];
+
+    if (!ret) {
+        if (window.getComputedStyle) {
+            ret = window.getComputedStyle(element, '').getPropertyValue(property);
+        } else {
+            ret = element.currentStyle[property];
+        }
+    }
+
+    if (!ret || ret == 'auto' || ret == 'intrinsic') {
+        ret = container.style[property];
+    }
+    return ret;
+};
+
+function applyStyles(elm, styles) {
+    for (var style in styles) {
+        elm.style[style] = styles[style];
+    }
+}
+
+function setupContainer(element, getValue) {
+    if (element.type != 'textarea') {
+        throw new Error("Textarea required!");
+    }
+
+    var parentNode = element.parentNode;
+    var container = document.createElement('div');
+    var resizeEvent = function() {
+        var style = 'position:relative;';
+        [
+            'margin-top', 'margin-left', 'margin-right', 'margin-bottom'
+        ].forEach(function(item) {
+            style += item + ':' +
+                        getCSSProperty(element, container, item) + ';';
+        });
+        var width = getCSSProperty(element, container, 'width') || (element.clientWidth + "px");
+        var height = getCSSProperty(element, container, 'height')  || (element.clientHeight + "px");
+        style += 'height:' + height + ';width:' + width + ';';
+        style += 'display:inline-block;';
+        container.setAttribute('style', style);
+    };
+    event.addListener(window, 'resize', resizeEvent);
+    resizeEvent();
+    parentNode.insertBefore(container, element.nextSibling);
+    while (parentNode !== document) {
+        if (parentNode.tagName.toUpperCase() === 'FORM') {
+            var oldSumit = parentNode.onsubmit;
+            parentNode.onsubmit = function(evt) {
+                element.value = getValue();
+                if (oldSumit) {
+                    oldSumit.call(this, evt);
+                }
+            };
+            break;
+        }
+        parentNode = parentNode.parentNode;
+    }
+    return container;
+}
+
+exports.transformTextarea = function(element, options) {
+    var isFocused = element.autofocus || document.activeElement == element;
+    var session;
+    var container = setupContainer(element, function() {
+        return session.getValue();
+    });
+    element.style.display = 'none';
+    container.style.background = 'white';
+    var editorDiv = document.createElement("div");
+    applyStyles(editorDiv, {
+        top: "0px",
+        left: "0px",
+        right: "0px",
+        bottom: "0px",
+        border: "1px solid gray",
+        position: "absolute"
+    });
+    container.appendChild(editorDiv);
+
+    var settingOpener = document.createElement("div");
+    applyStyles(settingOpener, {
+        position: "absolute",
+        right: "0px",
+        bottom: "0px",
+        cursor: "nw-resize",
+        border: "solid 9px",
+        borderColor: "lightblue gray gray #ceade6",
+        zIndex: 101
+    });
+
+    var settingDiv = document.createElement("div");
+    var settingDivStyles = {
+        top: "0px",
+        left: "20%",
+        right: "0px",
+        bottom: "0px",
+        position: "absolute",
+        padding: "5px",
+        zIndex: 100,
+        color: "white",
+        display: "none",
+        overflow: "auto",
+        fontSize: "14px",
+        boxShadow: "-5px 2px 3px gray"
+    };
+    if (!UA.isOldIE) {
+        settingDivStyles.backgroundColor = "rgba(0, 0, 0, 0.6)";
+    } else {
+        settingDivStyles.backgroundColor = "#333";
+    }
+
+    applyStyles(settingDiv, settingDivStyles);
+    container.appendChild(settingDiv);
+
+    options = options || exports.defaultOptions;
+    var editor = ace.edit(editorDiv);
+    session = editor.getSession();
+
+    session.setValue(element.value || element.innerHTML);
+    if (isFocused)
+        editor.focus();
+    container.appendChild(settingOpener);
+    setupApi(editor, editorDiv, settingDiv, ace, options);
+    setupSettingPanel(settingDiv, settingOpener, editor);
+
+    var state = "";
+    event.addListener(settingOpener, "mousemove", function(e) {
+        var rect = this.getBoundingClientRect();
+        var x = e.clientX - rect.left, y = e.clientY - rect.top;
+        if (x + y < (rect.width + rect.height)/2) {
+            this.style.cursor = "pointer";
+            state = "toggle";
+        } else {
+            state = "resize";
+            this.style.cursor = "nw-resize";
+        }
+    });
+
+    event.addListener(settingOpener, "mousedown", function(e) {
+        e.preventDefault();
+        if (state == "toggle") {
+            editor.setDisplaySettings();
+            return;
+        }
+        container.style.zIndex = 100000;
+        var rect = container.getBoundingClientRect();
+        var startX = rect.width  + rect.left - e.clientX;
+        var startY = rect.height  + rect.top - e.clientY;
+        event.capture(settingOpener, function(e) {
+            container.style.width = e.clientX - rect.left + startX + "px";
+            container.style.height = e.clientY - rect.top + startY + "px";
+            editor.resize();
+        }, function() {});
+    });
+
+    return editor;
+};
+
+function load(url, module, callback) {
+    net.loadScript(url, function() {
+        require([module], callback);
+    });
+}
+
+function setupApi(editor, editorDiv, settingDiv, ace, options) {
+    var session = editor.getSession();
+    var renderer = editor.renderer;
+
+    function toBool(value) {
+        return value === "true" || value == true;
+    }
+
+    editor.setDisplaySettings = function(display) {
+        if (display == null)
+            display = settingDiv.style.display == "none";
+        if (display) {
+            settingDiv.style.display = "block";
+            settingDiv.hideButton.focus();
+            editor.on("focus", function onFocus() {
+                editor.removeListener("focus", onFocus);
+                settingDiv.style.display = "none";
+            });
+        } else {
+            editor.focus();
+        }
+    };
+
+    editor.$setOption = editor.setOption;
+    editor.$getOption = editor.getOption;
+    editor.setOption = function(key, value) {
+        switch (key) {
+            case "mode":
+                editor.$setOption("mode", "ace/mode/" + value);
+            break;
+            case "theme":
+                editor.$setOption("theme", "ace/theme/" + value);
+            break;
+            case "keybindings":
+                switch (value) {
+                    case "vim":
+                        editor.setKeyboardHandler("ace/keyboard/vim");
+                        break;
+                    case "emacs":
+                        editor.setKeyboardHandler("ace/keyboard/emacs");
+                        break;
+                    default:
+                        editor.setKeyboardHandler(null);
+                }
+            break;
+
+            case "wrap":
+            case "fontSize":
+                editor.$setOption(key, value);
+            break;
+            
+            default:
+                editor.$setOption(key, toBool(value));
+        }
+    };
+
+    editor.getOption = function(key) {
+        switch (key) {
+            case "mode":
+                return editor.$getOption("mode").substr("ace/mode/".length);
+            break;
+
+            case "theme":
+                return editor.$getOption("theme").substr("ace/theme/".length);
+            break;
+
+            case "keybindings":
+                var value = editor.getKeyboardHandler();
+                switch (value && value.$id) {
+                    case "ace/keyboard/vim":
+                        return "vim";
+                    case "ace/keyboard/emacs":
+                        return "emacs";
+                    default:
+                        return "ace";
+                }
+            break;
+
+            default:
+                return editor.$getOption(key);
+        }
+    };
+
+    editor.setOptions(options);
+    return editor;
+}
+
+function setupSettingPanel(settingDiv, settingOpener, editor) {
+    var BOOL = null;
+
+    var desc = {
+        mode:            "Mode:",
+        wrap:            "Soft Wrap:",
+        theme:           "Theme:",
+        fontSize:        "Font Size:",
+        showGutter:      "Display Gutter:",
+        keybindings:     "Keyboard",
+        showPrintMargin: "Show Print Margin:",
+        useSoftTabs:     "Use Soft Tabs:",
+        showInvisibles:  "Show Invisibles"
+    };
+
+    var optionValues = {
+        mode: {
+            text:       "Plain",
+            javascript: "JavaScript",
+            xml:        "XML",
+            html:       "HTML",
+            css:        "CSS",
+            scss:       "SCSS",
+            python:     "Python",
+            php:        "PHP",
+            java:       "Java",
+            ruby:       "Ruby",
+            c_cpp:      "C/C++",
+            coffee:     "CoffeeScript",
+            json:       "json",
+            perl:       "Perl",
+            clojure:    "Clojure",
+            ocaml:      "OCaml",
+            csharp:     "C#",
+            haxe:       "haXe",
+            svg:        "SVG",
+            textile:    "Textile",
+            groovy:     "Groovy",
+            liquid:     "Liquid",
+            Scala:      "Scala"
+        },
+        theme: {
+            clouds:           "Clouds",
+            clouds_midnight:  "Clouds Midnight",
+            cobalt:           "Cobalt",
+            crimson_editor:   "Crimson Editor",
+            dawn:             "Dawn",
+            gob:              "Green on Black",
+            eclipse:          "Eclipse",
+            idle_fingers:     "Idle Fingers",
+            kr_theme:         "Kr Theme",
+            merbivore:        "Merbivore",
+            merbivore_soft:   "Merbivore Soft",
+            mono_industrial:  "Mono Industrial",
+            monokai:          "Monokai",
+            pastel_on_dark:   "Pastel On Dark",
+            solarized_dark:   "Solarized Dark",
+            solarized_light:  "Solarized Light",
+            textmate:         "Textmate",
+            twilight:         "Twilight",
+            vibrant_ink:      "Vibrant Ink"
+        },
+        showGutter: BOOL,
+        fontSize: {
+            "10px": "10px",
+            "11px": "11px",
+            "12px": "12px",
+            "14px": "14px",
+            "16px": "16px"
+        },
+        wrap: {
+            off:    "Off",
+            40:     "40",
+            80:     "80",
+            free:   "Free"
+        },
+        keybindings: {
+            ace: "ace",
+            vim: "vim",
+            emacs: "emacs"
+        },
+        showPrintMargin:    BOOL,
+        useSoftTabs:        BOOL,
+        showInvisibles:     BOOL
+    };
+
+    var table = [];
+    table.push("<table><tr><th>Setting</th><th>Value</th></tr>");
+
+    function renderOption(builder, option, obj, cValue) {
+        if (!obj) {
+            builder.push(
+                "<input type='checkbox' title='", option, "' ",
+                    cValue + "" == "true" ? "checked='true'" : "",
+               "'></input>"
+            );
+            return;
+        }
+        builder.push("<select title='" + option + "'>");
+        for (var value in obj) {
+            builder.push("<option value='" + value + "' ");
+
+            if (cValue == value) {
+                builder.push(" selected ");
+            }
+
+            builder.push(">",
+                obj[value],
+                "</option>");
+        }
+        builder.push("</select>");
+    }
+
+    for (var option in exports.defaultOptions) {
+        table.push("<tr><td>", desc[option], "</td>");
+        table.push("<td>");
+        renderOption(table, option, optionValues[option], editor.getOption(option));
+        table.push("</td></tr>");
+    }
+    table.push("</table>");
+    settingDiv.innerHTML = table.join("");
+
+    var onChange = function(e) {
+        var select = e.currentTarget;
+        editor.setOption(select.title, select.value);
+    };
+    var onClick = function(e) {
+        var cb = e.currentTarget;
+        editor.setOption(cb.title, cb.checked);
+    };
+    var selects = settingDiv.getElementsByTagName("select");
+    for (var i = 0; i < selects.length; i++)
+        selects[i].onchange = onChange;
+    var cbs = settingDiv.getElementsByTagName("input");
+    for (var i = 0; i < cbs.length; i++)
+        cbs[i].onclick = onClick;
+
+
+    var button = document.createElement("input");
+    button.type = "button";
+    button.value = "Hide";
+    event.addListener(button, "click", function() {
+        editor.setDisplaySettings(false);
+    });
+    settingDiv.appendChild(button);
+    settingDiv.hideButton = button;
+}
+exports.defaultOptions = {
+    mode:               "javascript",
+    theme:              "textmate",
+    wrap:               "off",
+    fontSize:           "12px",
+    showGutter:         "false",
+    keybindings:        "ace",
+    showPrintMargin:    "false",
+    useSoftTabs:        "true",
+    showInvisibles:     "false"
+};
+
+});
+                (function() {
+                    ace.require(["ace/ext/textarea"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 66 - 0
services/web/public/js/ace-1.4.3/ext-themelist.js

@@ -0,0 +1,66 @@
+ace.define("ace/ext/themelist",[], function(require, exports, module) {
+"use strict";
+
+var themeData = [
+    ["Chrome"         ],
+    ["Clouds"         ],
+    ["Crimson Editor" ],
+    ["Dawn"           ],
+    ["Dreamweaver"    ],
+    ["Eclipse"        ],
+    ["GitHub"         ],
+    ["IPlastic"       ],
+    ["Solarized Light"],
+    ["TextMate"       ],
+    ["Tomorrow"       ],
+    ["XCode"          ],
+    ["Kuroir"],
+    ["KatzenMilch"],
+    ["SQL Server"           ,"sqlserver"               , "light"],
+    ["Ambiance"             ,"ambiance"                ,  "dark"],
+    ["Chaos"                ,"chaos"                   ,  "dark"],
+    ["Clouds Midnight"      ,"clouds_midnight"         ,  "dark"],
+    ["Dracula"              ,""                        ,  "dark"],
+    ["Cobalt"               ,"cobalt"                  ,  "dark"],
+    ["Gruvbox"              ,"gruvbox"                 ,  "dark"],
+    ["Green on Black"       ,"gob"                     ,  "dark"],
+    ["idle Fingers"         ,"idle_fingers"            ,  "dark"],
+    ["krTheme"              ,"kr_theme"                ,  "dark"],
+    ["Merbivore"            ,"merbivore"               ,  "dark"],
+    ["Merbivore Soft"       ,"merbivore_soft"          ,  "dark"],
+    ["Mono Industrial"      ,"mono_industrial"         ,  "dark"],
+    ["Monokai"              ,"monokai"                 ,  "dark"],
+    ["Pastel on dark"       ,"pastel_on_dark"          ,  "dark"],
+    ["Solarized Dark"       ,"solarized_dark"          ,  "dark"],
+    ["Terminal"             ,"terminal"                ,  "dark"],
+    ["Tomorrow Night"       ,"tomorrow_night"          ,  "dark"],
+    ["Tomorrow Night Blue"  ,"tomorrow_night_blue"     ,  "dark"],
+    ["Tomorrow Night Bright","tomorrow_night_bright"   ,  "dark"],
+    ["Tomorrow Night 80s"   ,"tomorrow_night_eighties" ,  "dark"],
+    ["Twilight"             ,"twilight"                ,  "dark"],
+    ["Vibrant Ink"          ,"vibrant_ink"             ,  "dark"]
+];
+
+
+exports.themesByName = {};
+exports.themes = themeData.map(function(data) {
+    var name = data[1] || data[0].replace(/ /g, "_").toLowerCase();
+    var theme = {
+        caption: data[0],
+        theme: "ace/theme/" + name,
+        isDark: data[2] == "dark",
+        name: name
+    };
+    exports.themesByName[name] = theme;
+    return theme;
+});
+
+});
+                (function() {
+                    ace.require(["ace/ext/themelist"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 210 - 0
services/web/public/js/ace-1.4.3/ext-whitespace.js

@@ -0,0 +1,210 @@
+ace.define("ace/ext/whitespace",[], function(require, exports, module) {
+"use strict";
+
+var lang = require("../lib/lang");
+exports.$detectIndentation = function(lines, fallback) {
+    var stats = [];
+    var changes = [];
+    var tabIndents = 0;
+    var prevSpaces = 0;
+    var max = Math.min(lines.length, 1000);
+    for (var i = 0; i < max; i++) {
+        var line = lines[i];
+        if (!/^\s*[^*+\-\s]/.test(line))
+            continue;
+
+        if (line[0] == "\t") {
+            tabIndents++;
+            prevSpaces = -Number.MAX_VALUE;
+        } else {
+            var spaces = line.match(/^ */)[0].length;
+            if (spaces && line[spaces] != "\t") {
+                var diff = spaces - prevSpaces;
+                if (diff > 0 && !(prevSpaces%diff) && !(spaces%diff))
+                    changes[diff] = (changes[diff] || 0) + 1;
+    
+                stats[spaces] = (stats[spaces] || 0) + 1;
+            }
+            prevSpaces = spaces;
+        }
+        while (i < max && line[line.length - 1] == "\\")
+            line = lines[i++];
+    }
+    
+    function getScore(indent) {
+        var score = 0;
+        for (var i = indent; i < stats.length; i += indent)
+            score += stats[i] || 0;
+        return score;
+    }
+
+    var changesTotal = changes.reduce(function(a,b){return a+b;}, 0);
+
+    var first = {score: 0, length: 0};
+    var spaceIndents = 0;
+    for (var i = 1; i < 12; i++) {
+        var score = getScore(i);
+        if (i == 1) {
+            spaceIndents = score;
+            score = stats[1] ? 0.9 : 0.8;
+            if (!stats.length)
+                score = 0;
+        } else
+            score /= spaceIndents;
+
+        if (changes[i])
+            score += changes[i] / changesTotal;
+
+        if (score > first.score)
+            first = {score: score, length: i};
+    }
+
+    if (first.score && first.score > 1.4)
+        var tabLength = first.length;
+
+    if (tabIndents > spaceIndents + 1) {
+        if (tabLength == 1 || spaceIndents < tabIndents / 4 || first.score < 1.8)
+            tabLength = undefined;
+        return {ch: "\t", length: tabLength};
+    }
+    if (spaceIndents > tabIndents + 1)
+        return {ch: " ", length: tabLength};
+};
+
+exports.detectIndentation = function(session) {
+    var lines = session.getLines(0, 1000);
+    var indent = exports.$detectIndentation(lines) || {};
+
+    if (indent.ch)
+        session.setUseSoftTabs(indent.ch == " ");
+
+    if (indent.length)
+        session.setTabSize(indent.length);
+    return indent;
+};
+exports.trimTrailingSpace = function(session, options) {
+    var doc = session.getDocument();
+    var lines = doc.getAllLines();
+    
+    var min = options && options.trimEmpty ? -1 : 0;
+    var cursors = [], ci = -1;
+    if (options && options.keepCursorPosition) {
+        if (session.selection.rangeCount) {
+            session.selection.rangeList.ranges.forEach(function(x, i, ranges) {
+               var next = ranges[i + 1];
+               if (next && next.cursor.row == x.cursor.row)
+                  return;
+              cursors.push(x.cursor);
+            });
+        } else {
+            cursors.push(session.selection.getCursor());
+        }
+        ci = 0;
+    }
+    var cursorRow = cursors[ci] && cursors[ci].row;
+
+    for (var i = 0, l=lines.length; i < l; i++) {
+        var line = lines[i];
+        var index = line.search(/\s+$/);
+
+        if (i == cursorRow) {
+            if (index < cursors[ci].column && index > min)
+               index = cursors[ci].column;
+            ci++;
+            cursorRow = cursors[ci] ? cursors[ci].row : -1;
+        }
+
+        if (index > min)
+            doc.removeInLine(i, index, line.length);
+    }
+};
+
+exports.convertIndentation = function(session, ch, len) {
+    var oldCh = session.getTabString()[0];
+    var oldLen = session.getTabSize();
+    if (!len) len = oldLen;
+    if (!ch) ch = oldCh;
+
+    var tab = ch == "\t" ? ch: lang.stringRepeat(ch, len);
+
+    var doc = session.doc;
+    var lines = doc.getAllLines();
+
+    var cache = {};
+    var spaceCache = {};
+    for (var i = 0, l=lines.length; i < l; i++) {
+        var line = lines[i];
+        var match = line.match(/^\s*/)[0];
+        if (match) {
+            var w = session.$getStringScreenWidth(match)[0];
+            var tabCount = Math.floor(w/oldLen);
+            var reminder = w%oldLen;
+            var toInsert = cache[tabCount] || (cache[tabCount] = lang.stringRepeat(tab, tabCount));
+            toInsert += spaceCache[reminder] || (spaceCache[reminder] = lang.stringRepeat(" ", reminder));
+
+            if (toInsert != match) {
+                doc.removeInLine(i, 0, match.length);
+                doc.insertInLine({row: i, column: 0}, toInsert);
+            }
+        }
+    }
+    session.setTabSize(len);
+    session.setUseSoftTabs(ch == " ");
+};
+
+exports.$parseStringArg = function(text) {
+    var indent = {};
+    if (/t/.test(text))
+        indent.ch = "\t";
+    else if (/s/.test(text))
+        indent.ch = " ";
+    var m = text.match(/\d+/);
+    if (m)
+        indent.length = parseInt(m[0], 10);
+    return indent;
+};
+
+exports.$parseArg = function(arg) {
+    if (!arg)
+        return {};
+    if (typeof arg == "string")
+        return exports.$parseStringArg(arg);
+    if (typeof arg.text == "string")
+        return exports.$parseStringArg(arg.text);
+    return arg;
+};
+
+exports.commands = [{
+    name: "detectIndentation",
+    exec: function(editor) {
+        exports.detectIndentation(editor.session);
+    }
+}, {
+    name: "trimTrailingSpace",
+    exec: function(editor, args) {
+        exports.trimTrailingSpace(editor.session, args);
+    }
+}, {
+    name: "convertIndentation",
+    exec: function(editor, arg) {
+        var indent = exports.$parseArg(arg);
+        exports.convertIndentation(editor.session, indent.ch, indent.length);
+    }
+}, {
+    name: "setIndentation",
+    exec: function(editor, arg) {
+        var indent = exports.$parseArg(arg);
+        indent.length && editor.session.setTabSize(indent.length);
+        indent.ch && editor.session.setUseSoftTabs(indent.ch == " ");
+    }
+}];
+
+});
+                (function() {
+                    ace.require(["ace/ext/whitespace"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 1170 - 0
services/web/public/js/ace-1.4.3/keybinding-emacs.js

@@ -0,0 +1,1170 @@
+ace.define("ace/occur",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("./lib/oop");
+var Range = require("./range").Range;
+var Search = require("./search").Search;
+var EditSession = require("./edit_session").EditSession;
+var SearchHighlight = require("./search_highlight").SearchHighlight;
+function Occur() {}
+
+oop.inherits(Occur, Search);
+
+(function() {
+    this.enter = function(editor, options) {
+        if (!options.needle) return false;
+        var pos = editor.getCursorPosition();
+        this.displayOccurContent(editor, options);
+        var translatedPos = this.originalToOccurPosition(editor.session, pos);
+        editor.moveCursorToPosition(translatedPos);
+        return true;
+    };
+    this.exit = function(editor, options) {
+        var pos = options.translatePosition && editor.getCursorPosition();
+        var translatedPos = pos && this.occurToOriginalPosition(editor.session, pos);
+        this.displayOriginalContent(editor);
+        if (translatedPos)
+            editor.moveCursorToPosition(translatedPos);
+        return true;
+    };
+
+    this.highlight = function(sess, regexp) {
+        var hl = sess.$occurHighlight = sess.$occurHighlight || sess.addDynamicMarker(
+                new SearchHighlight(null, "ace_occur-highlight", "text"));
+        hl.setRegexp(regexp);
+        sess._emit("changeBackMarker"); // force highlight layer redraw
+    };
+
+    this.displayOccurContent = function(editor, options) {
+        this.$originalSession = editor.session;
+        var found = this.matchingLines(editor.session, options);
+        var lines = found.map(function(foundLine) { return foundLine.content; });
+        var occurSession = new EditSession(lines.join('\n'));
+        occurSession.$occur = this;
+        occurSession.$occurMatchingLines = found;
+        editor.setSession(occurSession);
+        this.$useEmacsStyleLineStart = this.$originalSession.$useEmacsStyleLineStart;
+        occurSession.$useEmacsStyleLineStart = this.$useEmacsStyleLineStart;
+        this.highlight(occurSession, options.re);
+        occurSession._emit('changeBackMarker');
+    };
+
+    this.displayOriginalContent = function(editor) {
+        editor.setSession(this.$originalSession);
+        this.$originalSession.$useEmacsStyleLineStart = this.$useEmacsStyleLineStart;
+    };
+    this.originalToOccurPosition = function(session, pos) {
+        var lines = session.$occurMatchingLines;
+        var nullPos = {row: 0, column: 0};
+        if (!lines) return nullPos;
+        for (var i = 0; i < lines.length; i++) {
+            if (lines[i].row === pos.row)
+                return {row: i, column: pos.column};
+        }
+        return nullPos;
+    };
+    this.occurToOriginalPosition = function(session, pos) {
+        var lines = session.$occurMatchingLines;
+        if (!lines || !lines[pos.row])
+            return pos;
+        return {row: lines[pos.row].row, column: pos.column};
+    };
+
+    this.matchingLines = function(session, options) {
+        options = oop.mixin({}, options);
+        if (!session || !options.needle) return [];
+        var search = new Search();
+        search.set(options);
+        return search.findAll(session).reduce(function(lines, range) {
+            var row = range.start.row;
+            var last = lines[lines.length-1];
+            return last && last.row === row ?
+                lines :
+                lines.concat({row: row, content: session.getLine(row)});
+        }, []);
+    };
+
+}).call(Occur.prototype);
+
+var dom = require('./lib/dom');
+dom.importCssString(".ace_occur-highlight {\n\
+    border-radius: 4px;\n\
+    background-color: rgba(87, 255, 8, 0.25);\n\
+    position: absolute;\n\
+    z-index: 4;\n\
+    box-sizing: border-box;\n\
+    box-shadow: 0 0 4px rgb(91, 255, 50);\n\
+}\n\
+.ace_dark .ace_occur-highlight {\n\
+    background-color: rgb(80, 140, 85);\n\
+    box-shadow: 0 0 4px rgb(60, 120, 70);\n\
+}\n", "incremental-occur-highlighting");
+
+exports.Occur = Occur;
+
+});
+
+ace.define("ace/commands/occur_commands",[], function(require, exports, module) {
+
+var config = require("../config"),
+    Occur = require("../occur").Occur;
+var occurStartCommand = {
+    name: "occur",
+    exec: function(editor, options) {
+        var alreadyInOccur = !!editor.session.$occur;
+        var occurSessionActive = new Occur().enter(editor, options);
+        if (occurSessionActive && !alreadyInOccur)
+            OccurKeyboardHandler.installIn(editor);
+    },
+    readOnly: true
+};
+
+var occurCommands = [{
+    name: "occurexit",
+    bindKey: 'esc|Ctrl-G',
+    exec: function(editor) {
+        var occur = editor.session.$occur;
+        if (!occur) return;
+        occur.exit(editor, {});
+        if (!editor.session.$occur) OccurKeyboardHandler.uninstallFrom(editor);
+    },
+    readOnly: true
+}, {
+    name: "occuraccept",
+    bindKey: 'enter',
+    exec: function(editor) {
+        var occur = editor.session.$occur;
+        if (!occur) return;
+        occur.exit(editor, {translatePosition: true});
+        if (!editor.session.$occur) OccurKeyboardHandler.uninstallFrom(editor);
+    },
+    readOnly: true
+}];
+
+var HashHandler = require("../keyboard/hash_handler").HashHandler;
+var oop = require("../lib/oop");
+
+
+function OccurKeyboardHandler() {}
+
+oop.inherits(OccurKeyboardHandler, HashHandler);
+
+(function() {
+
+    this.isOccurHandler = true;
+
+    this.attach = function(editor) {
+        HashHandler.call(this, occurCommands, editor.commands.platform);
+        this.$editor = editor;
+    };
+
+    var handleKeyboard$super = this.handleKeyboard;
+    this.handleKeyboard = function(data, hashId, key, keyCode) {
+        var cmd = handleKeyboard$super.call(this, data, hashId, key, keyCode);
+        return (cmd && cmd.command) ? cmd : undefined;
+    };
+
+}).call(OccurKeyboardHandler.prototype);
+
+OccurKeyboardHandler.installIn = function(editor) {
+    var handler = new this();
+    editor.keyBinding.addKeyboardHandler(handler);
+    editor.commands.addCommands(occurCommands);
+};
+
+OccurKeyboardHandler.uninstallFrom = function(editor) {
+    editor.commands.removeCommands(occurCommands);
+    var handler = editor.getKeyboardHandler();
+    if (handler.isOccurHandler)
+        editor.keyBinding.removeKeyboardHandler(handler);
+};
+
+exports.occurStartCommand = occurStartCommand;
+
+});
+
+ace.define("ace/commands/incremental_search_commands",[], function(require, exports, module) {
+
+var config = require("../config");
+var oop = require("../lib/oop");
+var HashHandler = require("../keyboard/hash_handler").HashHandler;
+var occurStartCommand = require("./occur_commands").occurStartCommand;
+exports.iSearchStartCommands = [{
+    name: "iSearch",
+    bindKey: {win: "Ctrl-F", mac: "Command-F"},
+    exec: function(editor, options) {
+        config.loadModule(["core", "ace/incremental_search"], function(e) {
+            var iSearch = e.iSearch = e.iSearch || new e.IncrementalSearch();
+            iSearch.activate(editor, options.backwards);
+            if (options.jumpToFirstMatch) iSearch.next(options);
+        });
+    },
+    readOnly: true
+}, {
+    name: "iSearchBackwards",
+    exec: function(editor, jumpToNext) { editor.execCommand('iSearch', {backwards: true}); },
+    readOnly: true
+}, {
+    name: "iSearchAndGo",
+    bindKey: {win: "Ctrl-K", mac: "Command-G"},
+    exec: function(editor, jumpToNext) { editor.execCommand('iSearch', {jumpToFirstMatch: true, useCurrentOrPrevSearch: true}); },
+    readOnly: true
+}, {
+    name: "iSearchBackwardsAndGo",
+    bindKey: {win: "Ctrl-Shift-K", mac: "Command-Shift-G"},
+    exec: function(editor) { editor.execCommand('iSearch', {jumpToFirstMatch: true, backwards: true, useCurrentOrPrevSearch: true}); },
+    readOnly: true
+}];
+exports.iSearchCommands = [{
+    name: "restartSearch",
+    bindKey: {win: "Ctrl-F", mac: "Command-F"},
+    exec: function(iSearch) {
+        iSearch.cancelSearch(true);
+    }
+}, {
+    name: "searchForward",
+    bindKey: {win: "Ctrl-S|Ctrl-K", mac: "Ctrl-S|Command-G"},
+    exec: function(iSearch, options) {
+        options.useCurrentOrPrevSearch = true;
+        iSearch.next(options);
+    }
+}, {
+    name: "searchBackward",
+    bindKey: {win: "Ctrl-R|Ctrl-Shift-K", mac: "Ctrl-R|Command-Shift-G"},
+    exec: function(iSearch, options) {
+        options.useCurrentOrPrevSearch = true;
+        options.backwards = true;
+        iSearch.next(options);
+    }
+}, {
+    name: "extendSearchTerm",
+    exec: function(iSearch, string) {
+        iSearch.addString(string);
+    }
+}, {
+    name: "extendSearchTermSpace",
+    bindKey: "space",
+    exec: function(iSearch) { iSearch.addString(' '); }
+}, {
+    name: "shrinkSearchTerm",
+    bindKey: "backspace",
+    exec: function(iSearch) {
+        iSearch.removeChar();
+    }
+}, {
+    name: 'confirmSearch',
+    bindKey: 'return',
+    exec: function(iSearch) { iSearch.deactivate(); }
+}, {
+    name: 'cancelSearch',
+    bindKey: 'esc|Ctrl-G',
+    exec: function(iSearch) { iSearch.deactivate(true); }
+}, {
+    name: 'occurisearch',
+    bindKey: 'Ctrl-O',
+    exec: function(iSearch) {
+        var options = oop.mixin({}, iSearch.$options);
+        iSearch.deactivate();
+        occurStartCommand.exec(iSearch.$editor, options);
+    }
+}, {
+    name: "yankNextWord",
+    bindKey: "Ctrl-w",
+    exec: function(iSearch) {
+        var ed = iSearch.$editor,
+            range = ed.selection.getRangeOfMovements(function(sel) { sel.moveCursorWordRight(); }),
+            string = ed.session.getTextRange(range);
+        iSearch.addString(string);
+    }
+}, {
+    name: "yankNextChar",
+    bindKey: "Ctrl-Alt-y",
+    exec: function(iSearch) {
+        var ed = iSearch.$editor,
+            range = ed.selection.getRangeOfMovements(function(sel) { sel.moveCursorRight(); }),
+            string = ed.session.getTextRange(range);
+        iSearch.addString(string);
+    }
+}, {
+    name: 'recenterTopBottom',
+    bindKey: 'Ctrl-l',
+    exec: function(iSearch) { iSearch.$editor.execCommand('recenterTopBottom'); }
+}, {
+    name: 'selectAllMatches',
+    bindKey: 'Ctrl-space',
+    exec: function(iSearch) {
+        var ed = iSearch.$editor,
+            hl = ed.session.$isearchHighlight,
+            ranges = hl && hl.cache ? hl.cache
+                .reduce(function(ranges, ea) {
+                    return ranges.concat(ea ? ea : []); }, []) : [];
+        iSearch.deactivate(false);
+        ranges.forEach(ed.selection.addRange.bind(ed.selection));
+    }
+}, {
+    name: 'searchAsRegExp',
+    bindKey: 'Alt-r',
+    exec: function(iSearch) {
+        iSearch.convertNeedleToRegExp();
+    }
+}].map(function(cmd) {
+    cmd.readOnly = true;
+    cmd.isIncrementalSearchCommand = true;
+    cmd.scrollIntoView = "animate-cursor";
+    return cmd;
+});
+
+function IncrementalSearchKeyboardHandler(iSearch) {
+    this.$iSearch = iSearch;
+}
+
+oop.inherits(IncrementalSearchKeyboardHandler, HashHandler);
+
+(function() {
+
+    this.attach = function(editor) {
+        var iSearch = this.$iSearch;
+        HashHandler.call(this, exports.iSearchCommands, editor.commands.platform);
+        this.$commandExecHandler = editor.commands.addEventListener('exec', function(e) {
+            if (!e.command.isIncrementalSearchCommand)
+                return iSearch.deactivate();
+            e.stopPropagation();
+            e.preventDefault();
+            var scrollTop = editor.session.getScrollTop();
+            var result = e.command.exec(iSearch, e.args || {});
+            editor.renderer.scrollCursorIntoView(null, 0.5);
+            editor.renderer.animateScrolling(scrollTop);
+            return result;
+        });
+    };
+
+    this.detach = function(editor) {
+        if (!this.$commandExecHandler) return;
+        editor.commands.removeEventListener('exec', this.$commandExecHandler);
+        delete this.$commandExecHandler;
+    };
+
+    var handleKeyboard$super = this.handleKeyboard;
+    this.handleKeyboard = function(data, hashId, key, keyCode) {
+        if (((hashId === 1/*ctrl*/ || hashId === 8/*command*/) && key === 'v')
+         || (hashId === 1/*ctrl*/ && key === 'y')) return null;
+        var cmd = handleKeyboard$super.call(this, data, hashId, key, keyCode);
+        if (cmd.command) { return cmd; }
+        if (hashId == -1) {
+            var extendCmd = this.commands.extendSearchTerm;
+            if (extendCmd) { return {command: extendCmd, args: key}; }
+        }
+        return false;
+    };
+
+}).call(IncrementalSearchKeyboardHandler.prototype);
+
+
+exports.IncrementalSearchKeyboardHandler = IncrementalSearchKeyboardHandler;
+
+});
+
+ace.define("ace/incremental_search",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("./lib/oop");
+var Range = require("./range").Range;
+var Search = require("./search").Search;
+var SearchHighlight = require("./search_highlight").SearchHighlight;
+var iSearchCommandModule = require("./commands/incremental_search_commands");
+var ISearchKbd = iSearchCommandModule.IncrementalSearchKeyboardHandler;
+function IncrementalSearch() {
+    this.$options = {wrap: false, skipCurrent: false};
+    this.$keyboardHandler = new ISearchKbd(this);
+}
+
+oop.inherits(IncrementalSearch, Search);
+
+function isRegExp(obj) {
+    return obj instanceof RegExp;
+}
+
+function regExpToObject(re) {
+    var string = String(re),
+        start = string.indexOf('/'),
+        flagStart = string.lastIndexOf('/');
+    return {
+        expression: string.slice(start+1, flagStart),
+        flags: string.slice(flagStart+1)
+    };
+}
+
+function stringToRegExp(string, flags) {
+    try {
+        return new RegExp(string, flags);
+    } catch (e) { return string; }
+}
+
+function objectToRegExp(obj) {
+    return stringToRegExp(obj.expression, obj.flags);
+}
+
+(function() {
+
+    this.activate = function(ed, backwards) {
+        this.$editor = ed;
+        this.$startPos = this.$currentPos = ed.getCursorPosition();
+        this.$options.needle = '';
+        this.$options.backwards = backwards;
+        ed.keyBinding.addKeyboardHandler(this.$keyboardHandler);
+        this.$originalEditorOnPaste = ed.onPaste; ed.onPaste = this.onPaste.bind(this);
+        this.$mousedownHandler = ed.addEventListener('mousedown', this.onMouseDown.bind(this));
+        this.selectionFix(ed);
+        this.statusMessage(true);
+    };
+
+    this.deactivate = function(reset) {
+        this.cancelSearch(reset);
+        var ed = this.$editor;
+        ed.keyBinding.removeKeyboardHandler(this.$keyboardHandler);
+        if (this.$mousedownHandler) {
+            ed.removeEventListener('mousedown', this.$mousedownHandler);
+            delete this.$mousedownHandler;
+        }
+        ed.onPaste = this.$originalEditorOnPaste;
+        this.message('');
+    };
+
+    this.selectionFix = function(editor) {
+        if (editor.selection.isEmpty() && !editor.session.$emacsMark) {
+            editor.clearSelection();
+        }
+    };
+
+    this.highlight = function(regexp) {
+        var sess = this.$editor.session,
+            hl = sess.$isearchHighlight = sess.$isearchHighlight || sess.addDynamicMarker(
+                new SearchHighlight(null, "ace_isearch-result", "text"));
+        hl.setRegexp(regexp);
+        sess._emit("changeBackMarker"); // force highlight layer redraw
+    };
+
+    this.cancelSearch = function(reset) {
+        var e = this.$editor;
+        this.$prevNeedle = this.$options.needle;
+        this.$options.needle = '';
+        if (reset) {
+            e.moveCursorToPosition(this.$startPos);
+            this.$currentPos = this.$startPos;
+        } else {
+            e.pushEmacsMark && e.pushEmacsMark(this.$startPos, false);
+        }
+        this.highlight(null);
+        return Range.fromPoints(this.$currentPos, this.$currentPos);
+    };
+
+    this.highlightAndFindWithNeedle = function(moveToNext, needleUpdateFunc) {
+        if (!this.$editor) return null;
+        var options = this.$options;
+        if (needleUpdateFunc) {
+            options.needle = needleUpdateFunc.call(this, options.needle || '') || '';
+        }
+        if (options.needle.length === 0) {
+            this.statusMessage(true);
+            return this.cancelSearch(true);
+        }
+        options.start = this.$currentPos;
+        var session = this.$editor.session,
+            found = this.find(session),
+            shouldSelect = this.$editor.emacsMark ?
+                !!this.$editor.emacsMark() : !this.$editor.selection.isEmpty();
+        if (found) {
+            if (options.backwards) found = Range.fromPoints(found.end, found.start);
+            this.$editor.selection.setRange(Range.fromPoints(shouldSelect ? this.$startPos : found.end, found.end));
+            if (moveToNext) this.$currentPos = found.end;
+            this.highlight(options.re);
+        }
+
+        this.statusMessage(found);
+
+        return found;
+    };
+
+    this.addString = function(s) {
+        return this.highlightAndFindWithNeedle(false, function(needle) {
+            if (!isRegExp(needle))
+              return needle + s;
+            var reObj = regExpToObject(needle);
+            reObj.expression += s;
+            return objectToRegExp(reObj);
+        });
+    };
+
+    this.removeChar = function(c) {
+        return this.highlightAndFindWithNeedle(false, function(needle) {
+            if (!isRegExp(needle))
+              return needle.substring(0, needle.length-1);
+            var reObj = regExpToObject(needle);
+            reObj.expression = reObj.expression.substring(0, reObj.expression.length-1);
+            return objectToRegExp(reObj);
+        });
+    };
+
+    this.next = function(options) {
+        options = options || {};
+        this.$options.backwards = !!options.backwards;
+        this.$currentPos = this.$editor.getCursorPosition();
+        return this.highlightAndFindWithNeedle(true, function(needle) {
+            return options.useCurrentOrPrevSearch && needle.length === 0 ?
+                this.$prevNeedle || '' : needle;
+        });
+    };
+
+    this.onMouseDown = function(evt) {
+        this.deactivate();
+        return true;
+    };
+
+    this.onPaste = function(text) {
+        this.addString(text);
+    };
+
+    this.convertNeedleToRegExp = function() {
+        return this.highlightAndFindWithNeedle(false, function(needle) {
+            return isRegExp(needle) ? needle : stringToRegExp(needle, 'ig');
+        });
+    };
+
+    this.convertNeedleToString = function() {
+        return this.highlightAndFindWithNeedle(false, function(needle) {
+            return isRegExp(needle) ? regExpToObject(needle).expression : needle;
+        });
+    };
+
+    this.statusMessage = function(found) {
+        var options = this.$options, msg = '';
+        msg += options.backwards ? 'reverse-' : '';
+        msg += 'isearch: ' + options.needle;
+        msg += found ? '' : ' (not found)';
+        this.message(msg);
+    };
+
+    this.message = function(msg) {
+        if (this.$editor.showCommandLine) {
+            this.$editor.showCommandLine(msg);
+            this.$editor.focus();
+        } else {
+            console.log(msg);
+        }
+    };
+
+}).call(IncrementalSearch.prototype);
+
+
+exports.IncrementalSearch = IncrementalSearch;
+
+var dom = require('./lib/dom');
+dom.importCssString && dom.importCssString("\
+.ace_marker-layer .ace_isearch-result {\
+  position: absolute;\
+  z-index: 6;\
+  box-sizing: border-box;\
+}\
+div.ace_isearch-result {\
+  border-radius: 4px;\
+  background-color: rgba(255, 200, 0, 0.5);\
+  box-shadow: 0 0 4px rgb(255, 200, 0);\
+}\
+.ace_dark div.ace_isearch-result {\
+  background-color: rgb(100, 110, 160);\
+  box-shadow: 0 0 4px rgb(80, 90, 140);\
+}", "incremental-search-highlighting");
+var commands = require("./commands/command_manager");
+(function() {
+    this.setupIncrementalSearch = function(editor, val) {
+        if (this.usesIncrementalSearch == val) return;
+        this.usesIncrementalSearch = val;
+        var iSearchCommands = iSearchCommandModule.iSearchStartCommands;
+        var method = val ? 'addCommands' : 'removeCommands';
+        this[method](iSearchCommands);
+    };
+}).call(commands.CommandManager.prototype);
+var Editor = require("./editor").Editor;
+require("./config").defineOptions(Editor.prototype, "editor", {
+    useIncrementalSearch: {
+        set: function(val) {
+            this.keyBinding.$handlers.forEach(function(handler) {
+                if (handler.setupIncrementalSearch) {
+                    handler.setupIncrementalSearch(this, val);
+                }
+            });
+            this._emit('incrementalSearchSettingChanged', {isEnabled: val});
+        }
+    }
+});
+
+});
+
+ace.define("ace/keyboard/emacs",[], function(require, exports, module) {
+"use strict";
+
+var dom = require("../lib/dom");
+require("../incremental_search");
+var iSearchCommandModule = require("../commands/incremental_search_commands");
+
+
+var HashHandler = require("./hash_handler").HashHandler;
+exports.handler = new HashHandler();
+
+exports.handler.isEmacs = true;
+exports.handler.$id = "ace/keyboard/emacs";
+
+var initialized = false;
+var $formerLongWords;
+var $formerLineStart;
+
+exports.handler.attach = function(editor) {
+    if (!initialized) {
+        initialized = true;
+        dom.importCssString('\
+            .emacs-mode .ace_cursor{\
+                border: 1px rgba(50,250,50,0.8) solid!important;\
+                box-sizing: border-box!important;\
+                background-color: rgba(0,250,0,0.9);\
+                opacity: 0.5;\
+            }\
+            .emacs-mode .ace_hidden-cursors .ace_cursor{\
+                opacity: 1;\
+                background-color: transparent;\
+            }\
+            .emacs-mode .ace_overwrite-cursors .ace_cursor {\
+                opacity: 1;\
+                background-color: transparent;\
+                border-width: 0 0 2px 2px !important;\
+            }\
+            .emacs-mode .ace_text-layer {\
+                z-index: 4\
+            }\
+            .emacs-mode .ace_cursor-layer {\
+                z-index: 2\
+            }', 'emacsMode'
+        );
+    }
+    $formerLongWords = editor.session.$selectLongWords;
+    editor.session.$selectLongWords = true;
+    $formerLineStart = editor.session.$useEmacsStyleLineStart;
+    editor.session.$useEmacsStyleLineStart = true;
+
+    editor.session.$emacsMark = null; // the active mark
+    editor.session.$emacsMarkRing = editor.session.$emacsMarkRing || [];
+
+    editor.emacsMark = function() {
+        return this.session.$emacsMark;
+    };
+
+    editor.setEmacsMark = function(p) {
+        this.session.$emacsMark = p;
+    };
+
+    editor.pushEmacsMark = function(p, activate) {
+        var prevMark = this.session.$emacsMark;
+        if (prevMark)
+            this.session.$emacsMarkRing.push(prevMark);
+        if (!p || activate) this.setEmacsMark(p);
+        else this.session.$emacsMarkRing.push(p);
+    };
+
+    editor.popEmacsMark = function() {
+        var mark = this.emacsMark();
+        if (mark) { this.setEmacsMark(null); return mark; }
+        return this.session.$emacsMarkRing.pop();
+    };
+
+    editor.getLastEmacsMark = function(p) {
+        return this.session.$emacsMark || this.session.$emacsMarkRing.slice(-1)[0];
+    };
+
+    editor.emacsMarkForSelection = function(replacement) {
+        var sel = this.selection,
+            multiRangeLength = this.multiSelect ?
+                this.multiSelect.getAllRanges().length : 1,
+            selIndex = sel.index || 0,
+            markRing = this.session.$emacsMarkRing,
+            markIndex = markRing.length - (multiRangeLength - selIndex),
+            lastMark = markRing[markIndex] || sel.anchor;
+        if (replacement) {
+            markRing.splice(markIndex, 1,
+                "row" in replacement && "column" in replacement ?
+                    replacement : undefined);
+        }
+        return lastMark;
+    };
+
+    editor.on("click", $resetMarkMode);
+    editor.on("changeSession", $kbSessionChange);
+    editor.renderer.$blockCursor = true;
+    editor.setStyle("emacs-mode");
+    editor.commands.addCommands(commands);
+    exports.handler.platform = editor.commands.platform;
+    editor.$emacsModeHandler = this;
+    editor.addEventListener('copy', this.onCopy);
+    editor.addEventListener('paste', this.onPaste);
+};
+
+exports.handler.detach = function(editor) {
+    editor.renderer.$blockCursor = false;
+    editor.session.$selectLongWords = $formerLongWords;
+    editor.session.$useEmacsStyleLineStart = $formerLineStart;
+    editor.removeEventListener("click", $resetMarkMode);
+    editor.removeEventListener("changeSession", $kbSessionChange);
+    editor.unsetStyle("emacs-mode");
+    editor.commands.removeCommands(commands);
+    editor.removeEventListener('copy', this.onCopy);
+    editor.removeEventListener('paste', this.onPaste);
+    editor.$emacsModeHandler = null;
+};
+
+var $kbSessionChange = function(e) {
+    if (e.oldSession) {
+        e.oldSession.$selectLongWords = $formerLongWords;
+        e.oldSession.$useEmacsStyleLineStart = $formerLineStart;
+    }
+
+    $formerLongWords = e.session.$selectLongWords;
+    e.session.$selectLongWords = true;
+    $formerLineStart = e.session.$useEmacsStyleLineStart;
+    e.session.$useEmacsStyleLineStart = true;
+
+    if (!e.session.hasOwnProperty('$emacsMark'))
+        e.session.$emacsMark = null;
+    if (!e.session.hasOwnProperty('$emacsMarkRing'))
+        e.session.$emacsMarkRing = [];
+};
+
+var $resetMarkMode = function(e) {
+    e.editor.session.$emacsMark = null;
+};
+
+var keys = require("../lib/keys").KEY_MODS;
+var eMods = {C: "ctrl", S: "shift", M: "alt", CMD: "command"};
+var combinations = ["C-S-M-CMD",
+                    "S-M-CMD", "C-M-CMD", "C-S-CMD", "C-S-M",
+                    "M-CMD", "S-CMD", "S-M", "C-CMD", "C-M", "C-S",
+                    "CMD", "M", "S", "C"];
+combinations.forEach(function(c) {
+    var hashId = 0;
+    c.split("-").forEach(function(c) {
+        hashId = hashId | keys[eMods[c]];
+    });
+    eMods[hashId] = c.toLowerCase() + "-";
+});
+
+exports.handler.onCopy = function(e, editor) {
+    if (editor.$handlesEmacsOnCopy) return;
+    editor.$handlesEmacsOnCopy = true;
+    exports.handler.commands.killRingSave.exec(editor);
+    editor.$handlesEmacsOnCopy = false;
+};
+
+exports.handler.onPaste = function(e, editor) {
+    editor.pushEmacsMark(editor.getCursorPosition());
+};
+
+exports.handler.bindKey = function(key, command) {
+    if (typeof key == "object")
+        key = key[this.platform];
+    if (!key)
+        return;
+
+    var ckb = this.commandKeyBinding;
+    key.split("|").forEach(function(keyPart) {
+        keyPart = keyPart.toLowerCase();
+        ckb[keyPart] = command;
+        var keyParts = keyPart.split(" ").slice(0,-1);
+        keyParts.reduce(function(keyMapKeys, keyPart, i) {
+            var prefix = keyMapKeys[i-1] ? keyMapKeys[i-1] + ' ' : '';
+            return keyMapKeys.concat([prefix + keyPart]);
+        }, []).forEach(function(keyPart) {
+            if (!ckb[keyPart]) ckb[keyPart] = "null";
+        });
+    }, this);
+};
+
+exports.handler.getStatusText = function(editor, data) {
+  var str = "";
+  if (data.count)
+    str += data.count;
+  if (data.keyChain)
+    str += " " + data.keyChain;
+  return str;
+};
+
+exports.handler.handleKeyboard = function(data, hashId, key, keyCode) {
+    if (keyCode === -1) return undefined;
+
+    var editor = data.editor;
+    editor._signal("changeStatus");
+    if (hashId == -1) {
+        editor.pushEmacsMark();
+        if (data.count) {
+            var str = new Array(data.count + 1).join(key);
+            data.count = null;
+            return {command: "insertstring", args: str};
+        }
+    }
+
+    var modifier = eMods[hashId];
+    if (modifier == "c-" || data.count) {
+        var count = parseInt(key[key.length - 1]);
+        if (typeof count === 'number' && !isNaN(count)) {
+            data.count = Math.max(data.count, 0) || 0;
+            data.count = 10 * data.count + count;
+            return {command: "null"};
+        }
+    }
+    if (modifier) key = modifier + key;
+    if (data.keyChain) key = data.keyChain += " " + key;
+    var command = this.commandKeyBinding[key];
+    data.keyChain = command == "null" ? key : "";
+    if (!command) return undefined;
+    if (command === "null") return {command: "null"};
+
+    if (command === "universalArgument") {
+        data.count = -4;
+        return {command: "null"};
+    }
+    var args;
+    if (typeof command !== "string") {
+        args = command.args;
+        if (command.command) command = command.command;
+        if (command === "goorselect") {
+            command = editor.emacsMark() ? args[1] : args[0];
+            args = null;
+        }
+    }
+
+    if (typeof command === "string") {
+        if (command === "insertstring" ||
+            command === "splitline" ||
+            command === "togglecomment") {
+            editor.pushEmacsMark();
+        }
+        command = this.commands[command] || editor.commands.commands[command];
+        if (!command) return undefined;
+    }
+
+    if (!command.readOnly && !command.isYank)
+        data.lastCommand = null;
+
+    if (!command.readOnly && editor.emacsMark())
+        editor.setEmacsMark(null);
+        
+    if (data.count) {
+        var count = data.count;
+        data.count = 0;
+        if (!command || !command.handlesCount) {
+            return {
+                args: args,
+                command: {
+                    exec: function(editor, args) {
+                        for (var i = 0; i < count; i++)
+                            command.exec(editor, args);
+                    },
+                    multiSelectAction: command.multiSelectAction
+                }
+            };
+        } else {
+            if (!args) args = {};
+            if (typeof args === 'object') args.count = count;
+        }
+    }
+
+    return {command: command, args: args};
+};
+
+exports.emacsKeys = {
+    "Up|C-p"      : {command: "goorselect", args: ["golineup","selectup"]},
+    "Down|C-n"    : {command: "goorselect", args: ["golinedown","selectdown"]},
+    "Left|C-b"    : {command: "goorselect", args: ["gotoleft","selectleft"]},
+    "Right|C-f"   : {command: "goorselect", args: ["gotoright","selectright"]},
+    "C-Left|M-b"  : {command: "goorselect", args: ["gotowordleft","selectwordleft"]},
+    "C-Right|M-f" : {command: "goorselect", args: ["gotowordright","selectwordright"]},
+    "Home|C-a"    : {command: "goorselect", args: ["gotolinestart","selecttolinestart"]},
+    "End|C-e"     : {command: "goorselect", args: ["gotolineend","selecttolineend"]},
+    "C-Home|S-M-,": {command: "goorselect", args: ["gotostart","selecttostart"]},
+    "C-End|S-M-." : {command: "goorselect", args: ["gotoend","selecttoend"]},
+    "S-Up|S-C-p"      : "selectup",
+    "S-Down|S-C-n"    : "selectdown",
+    "S-Left|S-C-b"    : "selectleft",
+    "S-Right|S-C-f"   : "selectright",
+    "S-C-Left|S-M-b"  : "selectwordleft",
+    "S-C-Right|S-M-f" : "selectwordright",
+    "S-Home|S-C-a"    : "selecttolinestart",
+    "S-End|S-C-e"     : "selecttolineend",
+    "S-C-Home"        : "selecttostart",
+    "S-C-End"         : "selecttoend",
+
+    "C-l" : "recenterTopBottom",
+    "M-s" : "centerselection",
+    "M-g": "gotoline",
+    "C-x C-p": "selectall",
+    "C-Down": {command: "goorselect", args: ["gotopagedown","selectpagedown"]},
+    "C-Up": {command: "goorselect", args: ["gotopageup","selectpageup"]},
+    "PageDown|C-v": {command: "goorselect", args: ["gotopagedown","selectpagedown"]},
+    "PageUp|M-v": {command: "goorselect", args: ["gotopageup","selectpageup"]},
+    "S-C-Down": "selectpagedown",
+    "S-C-Up": "selectpageup",
+
+    "C-s": "iSearch",
+    "C-r": "iSearchBackwards",
+
+    "M-C-s": "findnext",
+    "M-C-r": "findprevious",
+    "S-M-5": "replace",
+    "Backspace": "backspace",
+    "Delete|C-d": "del",
+    "Return|C-m": {command: "insertstring", args: "\n"}, // "newline"
+    "C-o": "splitline",
+
+    "M-d|C-Delete": {command: "killWord", args: "right"},
+    "C-Backspace|M-Backspace|M-Delete": {command: "killWord", args: "left"},
+    "C-k": "killLine",
+
+    "C-y|S-Delete": "yank",
+    "M-y": "yankRotate",
+    "C-g": "keyboardQuit",
+
+    "C-w|C-S-W": "killRegion",
+    "M-w": "killRingSave",
+    "C-Space": "setMark",
+    "C-x C-x": "exchangePointAndMark",
+
+    "C-t": "transposeletters",
+    "M-u": "touppercase",    // Doesn't work
+    "M-l": "tolowercase",
+    "M-/": "autocomplete",   // Doesn't work
+    "C-u": "universalArgument",
+
+    "M-;": "togglecomment",
+
+    "C-/|C-x u|S-C--|C-z": "undo",
+    "S-C-/|S-C-x u|C--|S-C-z": "redo", // infinite undo?
+    "C-x r":  "selectRectangularRegion",
+    "M-x": {command: "focusCommandLine", args: "M-x "}
+};
+
+
+exports.handler.bindKeys(exports.emacsKeys);
+
+exports.handler.addCommands({
+    recenterTopBottom: function(editor) {
+        var renderer = editor.renderer;
+        var pos = renderer.$cursorLayer.getPixelPosition();
+        var h = renderer.$size.scrollerHeight - renderer.lineHeight;
+        var scrollTop = renderer.scrollTop;
+        if (Math.abs(pos.top - scrollTop) < 2) {
+            scrollTop = pos.top - h;
+        } else if (Math.abs(pos.top - scrollTop - h * 0.5) < 2) {
+            scrollTop = pos.top;
+        } else {
+            scrollTop = pos.top - h * 0.5;
+        }
+        editor.session.setScrollTop(scrollTop);
+    },
+    selectRectangularRegion:  function(editor) {
+        editor.multiSelect.toggleBlockSelection();
+    },
+    setMark:  {
+        exec: function(editor, args) {
+
+            if (args && args.count) {
+                if (editor.inMultiSelectMode) editor.forEachSelection(moveToMark);
+                else moveToMark();
+                moveToMark();
+                return;
+            }
+
+            var mark = editor.emacsMark(),
+                ranges = editor.selection.getAllRanges(),
+                rangePositions = ranges.map(function(r) { return {row: r.start.row, column: r.start.column}; }),
+                transientMarkModeActive = true,
+                hasNoSelection = ranges.every(function(range) { return range.isEmpty(); });
+            if (transientMarkModeActive && (mark || !hasNoSelection)) {
+                if (editor.inMultiSelectMode) editor.forEachSelection({exec: editor.clearSelection.bind(editor)});
+                else editor.clearSelection();
+                if (mark) editor.pushEmacsMark(null);
+                return;
+            }
+
+            if (!mark) {
+                rangePositions.forEach(function(pos) { editor.pushEmacsMark(pos); });
+                editor.setEmacsMark(rangePositions[rangePositions.length-1]);
+                return;
+            }
+
+            function moveToMark() {
+                var mark = editor.popEmacsMark();
+                mark && editor.moveCursorToPosition(mark);
+            }
+
+        },
+        readOnly: true,
+        handlesCount: true
+    },
+    exchangePointAndMark: {
+        exec: function exchangePointAndMark$exec(editor, args) {
+            var sel = editor.selection;
+            if (!args.count && !sel.isEmpty()) { // just invert selection
+                sel.setSelectionRange(sel.getRange(), !sel.isBackwards());
+                return;
+            }
+
+            if (args.count) { // replace mark and point
+                var pos = {row: sel.lead.row, column: sel.lead.column};
+                sel.clearSelection();
+                sel.moveCursorToPosition(editor.emacsMarkForSelection(pos));
+            } else { // create selection to last mark
+                sel.selectToPosition(editor.emacsMarkForSelection());
+            }
+        },
+        readOnly: true,
+        handlesCount: true,
+        multiSelectAction: "forEach"
+    },
+    killWord: {
+        exec: function(editor, dir) {
+            editor.clearSelection();
+            if (dir == "left")
+                editor.selection.selectWordLeft();
+            else
+                editor.selection.selectWordRight();
+
+            var range = editor.getSelectionRange();
+            var text = editor.session.getTextRange(range);
+            exports.killRing.add(text);
+
+            editor.session.remove(range);
+            editor.clearSelection();
+        },
+        multiSelectAction: "forEach"
+    },
+    killLine: function(editor) {
+        editor.pushEmacsMark(null);
+        editor.clearSelection();
+        var range = editor.getSelectionRange();
+        var line = editor.session.getLine(range.start.row);
+        range.end.column = line.length;
+        line = line.substr(range.start.column);
+        
+        var foldLine = editor.session.getFoldLine(range.start.row);
+        if (foldLine && range.end.row != foldLine.end.row) {
+            range.end.row = foldLine.end.row;
+            line = "x";
+        }
+        if (/^\s*$/.test(line)) {
+            range.end.row++;
+            line = editor.session.getLine(range.end.row);
+            range.end.column = /^\s*$/.test(line) ? line.length : 0;
+        }
+        var text = editor.session.getTextRange(range);
+        if (editor.prevOp.command == this)
+            exports.killRing.append(text);
+        else
+            exports.killRing.add(text);
+
+        editor.session.remove(range);
+        editor.clearSelection();
+    },
+    yank: function(editor) {
+        editor.onPaste(exports.killRing.get() || '');
+        editor.keyBinding.$data.lastCommand = "yank";
+    },
+    yankRotate: function(editor) {
+        if (editor.keyBinding.$data.lastCommand != "yank")
+            return;
+        editor.undo();
+        editor.session.$emacsMarkRing.pop(); // also undo recording mark
+        editor.onPaste(exports.killRing.rotate());
+        editor.keyBinding.$data.lastCommand = "yank";
+    },
+    killRegion: {
+        exec: function(editor) {
+            exports.killRing.add(editor.getCopyText());
+            editor.commands.byName.cut.exec(editor);
+            editor.setEmacsMark(null);
+        },
+        readOnly: true,
+        multiSelectAction: "forEach"
+    },
+    killRingSave: {
+        exec: function(editor) {
+
+            editor.$handlesEmacsOnCopy = true;
+            var marks = editor.session.$emacsMarkRing.slice(),
+                deselectedMarks = [];
+            exports.killRing.add(editor.getCopyText());
+
+            setTimeout(function() {
+                function deselect() {
+                    var sel = editor.selection, range = sel.getRange(),
+                        pos = sel.isBackwards() ? range.end : range.start;
+                    deselectedMarks.push({row: pos.row, column: pos.column});
+                    sel.clearSelection();
+                }
+                editor.$handlesEmacsOnCopy = false;
+                if (editor.inMultiSelectMode) editor.forEachSelection({exec: deselect});
+                else deselect();
+                editor.session.$emacsMarkRing = marks.concat(deselectedMarks.reverse());
+            }, 0);
+        },
+        readOnly: true
+    },
+    keyboardQuit: function(editor) {
+        editor.selection.clearSelection();
+        editor.setEmacsMark(null);
+        editor.keyBinding.$data.count = null;
+    },
+    focusCommandLine: function(editor, arg) {
+        if (editor.showCommandLine)
+            editor.showCommandLine(arg);
+    }
+});
+
+exports.handler.addCommands(iSearchCommandModule.iSearchStartCommands);
+
+var commands = exports.handler.commands;
+commands.yank.isYank = true;
+commands.yankRotate.isYank = true;
+
+exports.killRing = {
+    $data: [],
+    add: function(str) {
+        str && this.$data.push(str);
+        if (this.$data.length > 30)
+            this.$data.shift();
+    },
+    append: function(str) {
+        var idx = this.$data.length - 1;
+        var text = this.$data[idx] || "";
+        if (str) text += str;
+        if (text) this.$data[idx] = text;
+    },
+    get: function(n) {
+        n = n || 1;
+        return this.$data.slice(this.$data.length-n, this.$data.length).reverse().join('\n');
+    },
+    pop: function() {
+        if (this.$data.length > 1)
+            this.$data.pop();
+        return this.get();
+    },
+    rotate: function() {
+        this.$data.unshift(this.$data.pop());
+        return this.get();
+    }
+};
+
+});
+                (function() {
+                    ace.require(["ace/keyboard/emacs"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 426 - 0
services/web/public/js/ace-1.4.3/keybinding-sublime.js

@@ -0,0 +1,426 @@
+ace.define("ace/keyboard/sublime",[], function(require, exports, module) {
+"use strict";
+
+var keyUtil = require("../lib/keys");
+var oop = require("../lib/oop");
+var useragent = require("../lib/useragent");
+var HashHandler = require("../keyboard/hash_handler").HashHandler;
+
+function moveBySubWords(editor, direction, extend) {
+    var selection = editor.selection;
+    var row = selection.lead.row;
+    var column = selection.lead.column;
+
+    var line = editor.session.getLine(row);
+    if (!line[column + direction]) {
+        var method = (extend ? "selectWord" : "moveCursorShortWord")
+            + (direction == 1 ? "Right" : "Left");
+        return editor.selection[method]();
+    }
+    if (direction == -1) column--;
+    while (line[column]) {
+        var type = getType(line[column]) + getType(line[column + direction]);
+        column += direction;
+        if (direction == 1) {
+            if (type == "WW" && getType(line[column + 1]) == "w")
+                break;
+        }
+        else {
+            if (type == "wW") {
+                if (getType(line[column - 1]) == "W") {
+                    column -= 1;
+                    break;
+                } else {
+                    continue;
+                }
+            }
+            if (type == "Ww")
+                break;
+        }
+        if (/w[s_oW]|_[sWo]|o[s_wW]|s[W]|W[so]/.test(type))
+            break;
+    }
+    if (direction == -1) column++;
+    if (extend)
+        editor.selection.moveCursorTo(row, column);
+    else
+        editor.selection.moveTo(row, column);
+    
+    function getType(x) {
+        if (!x) return "-";
+        if (/\s/.test(x)) return "s";
+        if (x == "_") return "_";
+        if (x.toUpperCase() == x && x.toLowerCase() != x) return "W";
+        if (x.toUpperCase() != x && x.toLowerCase() == x) return "w";
+        return "o";
+    }
+}
+
+exports.handler = new HashHandler();
+ 
+exports.handler.addCommands([{
+    name: "find_all_under",
+    exec: function(editor) {
+        if (editor.selection.isEmpty())
+            editor.selection.selectWord();
+        editor.findAll();
+    },
+    readOnly: true
+}, {
+    name: "find_under",
+    exec: function(editor) {
+        if (editor.selection.isEmpty())
+            editor.selection.selectWord();
+        editor.findNext();
+    },
+    readOnly: true
+}, {
+    name: "find_under_prev",
+    exec: function(editor) {
+        if (editor.selection.isEmpty())
+            editor.selection.selectWord();
+        editor.findPrevious();
+    },
+    readOnly: true
+}, {
+    name: "find_under_expand",
+    exec: function(editor) {
+        editor.selectMore(1, false, true);
+    },
+    scrollIntoView: "animate",
+    readOnly: true
+}, {
+    name: "find_under_expand_skip",
+    exec: function(editor) {
+        editor.selectMore(1, true, true);
+    },
+    scrollIntoView: "animate",
+    readOnly: true
+}, {
+    name: "delete_to_hard_bol",
+    exec: function(editor) {
+        var pos = editor.selection.getCursor();
+        editor.session.remove({
+            start: { row: pos.row, column: 0 },
+            end: pos
+        });
+    },
+    multiSelectAction: "forEach",
+    scrollIntoView: "cursor"
+}, {
+    name: "delete_to_hard_eol",
+    exec: function(editor) {
+        var pos = editor.selection.getCursor();
+        editor.session.remove({
+            start: pos,
+            end: { row: pos.row, column: Infinity }
+        });
+    },
+    multiSelectAction: "forEach",
+    scrollIntoView: "cursor"
+}, {
+    name: "moveToWordStartLeft",
+    exec: function(editor) {
+        editor.selection.moveCursorLongWordLeft();
+        editor.clearSelection();
+    },
+    multiSelectAction: "forEach",
+    scrollIntoView: "cursor"
+}, {
+    name: "moveToWordEndRight",
+    exec: function(editor) {
+        editor.selection.moveCursorLongWordRight();
+        editor.clearSelection();
+    },
+    multiSelectAction: "forEach",
+    scrollIntoView: "cursor"
+}, {
+    name: "selectToWordStartLeft",
+    exec: function(editor) {
+        var sel = editor.selection;
+        sel.$moveSelection(sel.moveCursorLongWordLeft);
+    },
+    multiSelectAction: "forEach",
+    scrollIntoView: "cursor"
+}, {
+    name: "selectToWordEndRight",
+    exec: function(editor) {
+        var sel = editor.selection;
+        sel.$moveSelection(sel.moveCursorLongWordRight);
+    },
+    multiSelectAction: "forEach",
+    scrollIntoView: "cursor"
+}, {
+    name: "selectSubWordRight",
+    exec: function(editor) {
+        moveBySubWords(editor, 1, true);
+    },
+    multiSelectAction: "forEach",
+    scrollIntoView: "cursor",
+    readOnly: true
+}, {
+    name: "selectSubWordLeft",
+    exec: function(editor) {
+        moveBySubWords(editor, -1, true);
+    },
+    multiSelectAction: "forEach",
+    scrollIntoView: "cursor",
+    readOnly: true
+}, {
+    name: "moveSubWordRight",
+    exec: function(editor) {
+        moveBySubWords(editor, 1);
+    },
+    multiSelectAction: "forEach",
+    scrollIntoView: "cursor",
+    readOnly: true
+}, {
+    name: "moveSubWordLeft",
+    exec: function(editor) {
+        moveBySubWords(editor, -1);
+    },
+    multiSelectAction: "forEach",
+    scrollIntoView: "cursor",
+    readOnly: true
+}]);
+
+
+[{
+    bindKey: { mac: "cmd-k cmd-backspace|cmd-backspace", win: "ctrl-shift-backspace|ctrl-k ctrl-backspace" },
+    name: "removetolinestarthard"
+}, {
+    bindKey: { mac: "cmd-k cmd-k|cmd-delete|ctrl-k", win: "ctrl-shift-delete|ctrl-k ctrl-k" },
+    name: "removetolineendhard"
+}, {
+    bindKey: { mac: "cmd-shift-d", win: "ctrl-shift-d" },
+    name: "duplicateSelection"
+}, {
+    bindKey: { mac: "cmd-l", win: "ctrl-l" },
+    name: "expandtoline"
+}, 
+{
+    bindKey: {mac: "cmd-shift-a", win: "ctrl-shift-a"},
+    name: "expandSelection",
+    args: {to: "tag"}
+}, {
+    bindKey: {mac: "cmd-shift-j", win: "ctrl-shift-j"},
+    name: "expandSelection",
+    args: {to: "indentation"}
+}, {
+    bindKey: {mac: "ctrl-shift-m", win: "ctrl-shift-m"},
+    name: "expandSelection",
+    args: {to: "brackets"}
+}, {
+    bindKey: {mac: "cmd-shift-space", win: "ctrl-shift-space"},
+    name: "expandSelection",
+    args: {to: "scope"}
+},
+{
+    bindKey: { mac: "ctrl-cmd-g", win: "alt-f3" },
+    name: "find_all_under"
+}, {
+    bindKey: { mac: "alt-cmd-g", win: "ctrl-f3" },
+    name: "find_under"
+}, {
+    bindKey: { mac: "shift-alt-cmd-g", win: "ctrl-shift-f3" },
+    name: "find_under_prev"
+}, {
+    bindKey: { mac: "cmd-g", win: "f3" },
+    name: "findnext"
+}, {
+    bindKey: { mac: "shift-cmd-g", win: "shift-f3" },
+    name: "findprevious"
+}, {
+    bindKey: { mac: "cmd-d", win: "ctrl-d" },
+    name: "find_under_expand"
+}, {
+    bindKey: { mac: "cmd-k cmd-d", win: "ctrl-k ctrl-d" },
+    name: "find_under_expand_skip"
+}, 
+{
+    bindKey: { mac: "cmd-alt-[", win: "ctrl-shift-[" },
+    name: "toggleFoldWidget"
+}, {
+    bindKey: { mac: "cmd-alt-]", win: "ctrl-shift-]" },
+    name: "unfold"
+}, {
+    bindKey: { mac: "cmd-k cmd-0|cmd-k cmd-j", win: "ctrl-k ctrl-0|ctrl-k ctrl-j" },
+    name: "unfoldall"
+}, {
+    bindKey: { mac: "cmd-k cmd-1", win: "ctrl-k ctrl-1" },
+    name: "foldOther",
+    args: { level: 1 }
+},
+{
+    bindKey: { win: "ctrl-left", mac: "alt-left" },
+    name: "moveToWordStartLeft"
+}, {
+    bindKey: { win: "ctrl-right", mac: "alt-right" },
+    name: "moveToWordEndRight"
+}, {
+    bindKey: { win: "ctrl-shift-left", mac: "alt-shift-left" },
+    name: "selectToWordStartLeft"
+}, {
+    bindKey: { win: "ctrl-shift-right", mac: "alt-shift-right" },
+    name: "selectToWordEndRight"
+}, 
+{
+    bindKey: {mac: "ctrl-alt-shift-right|ctrl-shift-right", win: "alt-shift-right"},
+    name: "selectSubWordRight"
+}, {
+    bindKey: {mac: "ctrl-alt-shift-left|ctrl-shift-left", win: "alt-shift-left"},
+    name: "selectSubWordLeft"
+}, {
+    bindKey: {mac: "ctrl-alt-right|ctrl-right", win: "alt-right"},
+    name: "moveSubWordRight"
+}, {
+    bindKey: {mac: "ctrl-alt-left|ctrl-left", win: "alt-left"},
+    name: "moveSubWordLeft"
+}, 
+{
+    bindKey: { mac: "ctrl-m", win: "ctrl-m" },
+    name: "jumptomatching",
+    args: { to: "brackets" }
+}, 
+{
+    bindKey: { mac: "ctrl-f6", win: "ctrl-f6" },
+    name: "goToNextError"
+}, {
+    bindKey: { mac: "ctrl-shift-f6", win: "ctrl-shift-f6" },
+    name: "goToPreviousError"
+},
+
+{
+    bindKey: { mac: "ctrl-o" },
+    name: "splitline"
+}, 
+{
+    bindKey: {mac: "ctrl-shift-w", win: "alt-shift-w"},
+    name: "surrowndWithTag"
+},{
+    bindKey: {mac: "cmd-alt-.", win: "alt-."},
+    name: "close_tag"
+}, 
+{
+    bindKey: { mac: "cmd-j", win: "ctrl-j" },
+    name: "joinlines"
+}, 
+
+{
+    bindKey: {mac: "ctrl--", win: "alt--"},
+    name: "jumpBack"
+}, {
+    bindKey: {mac: "ctrl-shift--", win: "alt-shift--"},
+    name: "jumpForward"
+}, 
+
+{
+    bindKey: { mac: "cmd-k cmd-l", win: "ctrl-k ctrl-l" },
+    name: "tolowercase"
+}, {
+    bindKey: { mac: "cmd-k cmd-u", win: "ctrl-k ctrl-u" },
+    name: "touppercase"
+}, 
+
+{
+    bindKey: {mac: "cmd-shift-v", win: "ctrl-shift-v"},
+    name: "paste_and_indent"
+}, {
+    bindKey: {mac: "cmd-k cmd-v|cmd-alt-v", win: "ctrl-k ctrl-v"},
+    name: "paste_from_history"
+}, 
+
+{
+    bindKey: { mac: "cmd-shift-enter", win: "ctrl-shift-enter" },
+    name: "addLineBefore"
+}, {
+    bindKey: { mac: "cmd-enter", win: "ctrl-enter" },
+    name: "addLineAfter"
+}, {
+    bindKey: { mac: "ctrl-shift-k", win: "ctrl-shift-k" },
+    name: "removeline"
+}, {
+    bindKey: { mac: "ctrl-alt-up", win: "ctrl-up" },
+    name: "scrollup"
+}, {
+    bindKey: { mac: "ctrl-alt-down", win: "ctrl-down" },
+    name: "scrolldown"
+}, {
+    bindKey: { mac: "cmd-a", win: "ctrl-a" },
+    name: "selectall"
+}, {
+    bindKey: { linux: "alt-shift-down", mac: "ctrl-shift-down", win: "ctrl-alt-down" },
+    name: "addCursorBelow"
+}, {
+    bindKey: { linux: "alt-shift-up", mac: "ctrl-shift-up", win: "ctrl-alt-up" },
+    name: "addCursorAbove"
+},
+
+
+{
+    bindKey: { mac: "cmd-k cmd-c|ctrl-l", win: "ctrl-k ctrl-c" },
+    name: "centerselection"
+}, 
+
+{
+    bindKey: { mac: "f5", win: "f9" },
+    name: "sortlines"
+}, 
+{
+    bindKey: {mac: "ctrl-f5", win: "ctrl-f9"},
+    name: "sortlines",
+    args: {caseSensitive: true}
+},
+{
+    bindKey: { mac: "cmd-shift-l", win: "ctrl-shift-l" },
+    name: "splitIntoLines"
+}, {
+    bindKey: { mac: "ctrl-cmd-down", win: "ctrl-shift-down" },
+    name: "movelinesdown"
+}, {
+    bindKey: { mac: "ctrl-cmd-up", win: "ctrl-shift-up" },
+    name: "movelinesup"
+}, {
+    bindKey: { mac: "alt-down", win: "alt-down" },
+    name: "modifyNumberDown"
+}, {
+    bindKey: { mac: "alt-up", win: "alt-up" },
+    name: "modifyNumberUp"
+}, {
+    bindKey: { mac: "cmd-/", win: "ctrl-/" },
+    name: "togglecomment"
+}, {
+    bindKey: { mac: "cmd-alt-/", win: "ctrl-shift-/" },
+    name: "toggleBlockComment"
+},
+
+
+{
+    bindKey: { linux: "ctrl-alt-q", mac: "ctrl-q", win: "ctrl-q" },
+    name: "togglerecording"
+}, {
+    bindKey: { linux: "ctrl-alt-shift-q", mac: "ctrl-shift-q", win: "ctrl-shift-q" },
+    name: "replaymacro"
+}, 
+
+{
+    bindKey: { mac: "ctrl-t", win: "ctrl-t" },
+    name: "transpose"
+}
+
+].forEach(function(binding) {
+    var command = exports.handler.commands[binding.name];
+    if (command)
+        command.bindKey = binding.bindKey;
+    exports.handler.bindKey(binding.bindKey, command || binding.name);
+});
+
+});
+                (function() {
+                    ace.require(["ace/keyboard/sublime"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 5666 - 0
services/web/public/js/ace-1.4.3/keybinding-vim.js

@@ -0,0 +1,5666 @@
+ace.define("ace/keyboard/vim",[], function(require, exports, module) {
+  'use strict';
+
+  function log() {
+    var d = "";
+    function format(p) {
+      if (typeof p != "object")
+        return p + "";
+      if ("line" in p) {
+        return p.line + ":" + p.ch;
+      }
+      if ("anchor" in p) {
+        return format(p.anchor) + "->" + format(p.head);
+      }
+      if (Array.isArray(p))
+        return "[" + p.map(function(x) {
+          return format(x);
+        }) + "]";
+      return JSON.stringify(p);
+    }
+    for (var i = 0; i < arguments.length; i++) {
+      var p = arguments[i];
+      var f = format(p);
+      d += f + "  ";
+    }
+    console.log(d);
+  }
+  var Range = require("../range").Range;
+  var EventEmitter = require("../lib/event_emitter").EventEmitter;
+  var dom = require("../lib/dom");
+  var oop = require("../lib/oop");
+  var KEYS = require("../lib/keys");
+  var event = require("../lib/event");
+  var Search = require("../search").Search;
+  var useragent = require("../lib/useragent");
+  var SearchHighlight = require("../search_highlight").SearchHighlight;
+  var multiSelectCommands = require("../commands/multi_select_commands");
+  var TextModeTokenRe = require("../mode/text").Mode.prototype.tokenRe;
+  require("../multi_select");
+
+  var CodeMirror = function(ace) {
+    this.ace = ace;
+    this.state = {};
+    this.marks = {};
+    this.$uid = 0;
+    this.onChange = this.onChange.bind(this);
+    this.onSelectionChange = this.onSelectionChange.bind(this);
+    this.onBeforeEndOperation = this.onBeforeEndOperation.bind(this);
+    this.ace.on('change', this.onChange);
+    this.ace.on('changeSelection', this.onSelectionChange);
+    this.ace.on('beforeEndOperation', this.onBeforeEndOperation);
+  };
+  CodeMirror.Pos = function(line, ch) {
+    if (!(this instanceof Pos)) return new Pos(line, ch);
+    this.line = line; this.ch = ch;
+  };
+  CodeMirror.defineOption = function(name, val, setter) {};
+  CodeMirror.commands = {
+    redo: function(cm) { cm.ace.redo(); },
+    undo: function(cm) { cm.ace.undo(); },
+    newlineAndIndent: function(cm) { cm.ace.insert("\n"); }
+  };
+  CodeMirror.keyMap = {};
+  CodeMirror.addClass = CodeMirror.rmClass = function() {};
+  CodeMirror.e_stop = CodeMirror.e_preventDefault = event.stopEvent;
+  CodeMirror.keyName = function(e) {
+    var key = (KEYS[e.keyCode] || e.key || "");
+    if (key.length == 1) key = key.toUpperCase();
+    key = event.getModifierString(e).replace(/(^|-)\w/g, function(m) {
+      return m.toUpperCase();
+    }) + key;
+    return key;
+  };
+  CodeMirror.keyMap['default'] = function(key) {
+    return function(cm) {
+      var cmd = cm.ace.commands.commandKeyBinding[key.toLowerCase()];
+      return cmd && cm.ace.execCommand(cmd) !== false;
+    };
+  };
+  CodeMirror.lookupKey = function lookupKey(key, map, handle) {
+    if (typeof map == "string")
+      map = CodeMirror.keyMap[map];
+    var found = typeof map == "function" ? map(key) : map[key];
+    if (found === false) return "nothing";
+    if (found === "...") return "multi";
+    if (found != null && handle(found)) return "handled";
+
+    if (map.fallthrough) {
+      if (!Array.isArray(map.fallthrough))
+        return lookupKey(key, map.fallthrough, handle);
+      for (var i = 0; i < map.fallthrough.length; i++) {
+        var result = lookupKey(key, map.fallthrough[i], handle);
+        if (result) return result;
+      }
+    }
+  };
+
+  CodeMirror.signal = function(o, name, e) { return o._signal(name, e) };
+  CodeMirror.on = event.addListener;
+  CodeMirror.off = event.removeListener;
+  CodeMirror.isWordChar = function(ch) {
+    if (ch < "\x7f") return /^\w$/.test(ch);
+    TextModeTokenRe.lastIndex = 0;
+    return TextModeTokenRe.test(ch);
+  };
+  
+(function() {
+  oop.implement(CodeMirror.prototype, EventEmitter);
+  
+  this.destroy = function() {
+    this.ace.off('change', this.onChange);
+    this.ace.off('changeSelection', this.onSelectionChange);
+    this.ace.off('beforeEndOperation', this.onBeforeEndOperation);
+    this.removeOverlay();
+  };
+  this.virtualSelectionMode = function() {
+    return this.ace.inVirtualSelectionMode && this.ace.selection.index;
+  };
+  this.onChange = function(delta) {
+    var change = { text: delta.action[0] == 'i' ? delta.lines : [] };
+    var curOp = this.curOp = this.curOp || {};
+    if (!curOp.changeHandlers)
+      curOp.changeHandlers = this._eventRegistry["change"] && this._eventRegistry["change"].slice();
+    if (!curOp.lastChange) {
+      curOp.lastChange = curOp.change = change;
+    } else {
+      curOp.lastChange.next = curOp.lastChange = change;
+    }
+    this.$updateMarkers(delta);
+  };
+  this.onSelectionChange = function() {
+    var curOp = this.curOp = this.curOp || {};
+    if (!curOp.cursorActivityHandlers)
+      curOp.cursorActivityHandlers = this._eventRegistry["cursorActivity"] && this._eventRegistry["cursorActivity"].slice();
+    this.curOp.cursorActivity = true;
+    if (this.ace.inMultiSelectMode) {
+      this.ace.keyBinding.removeKeyboardHandler(multiSelectCommands.keyboardHandler);
+    }
+  };
+  this.operation = function(fn, force) {
+    if (!force && this.curOp || force && this.curOp && this.curOp.force) {
+      return fn();
+    }
+    if (force || !this.ace.curOp) {
+      if (this.curOp)
+        this.onBeforeEndOperation();
+    }
+    if (!this.ace.curOp) {
+      var prevOp = this.ace.prevOp;
+      this.ace.startOperation({
+        command: { name: "vim",  scrollIntoView: "cursor" }
+      });
+    }
+    var curOp = this.curOp = this.curOp || {};
+    this.curOp.force = force;
+    var result = fn();
+    if (this.ace.curOp && this.ace.curOp.command.name == "vim") {
+      if (this.state.dialog)
+        this.ace.curOp.command.scrollIntoView = false;
+      this.ace.endOperation();
+      if (!curOp.cursorActivity && !curOp.lastChange && prevOp)
+        this.ace.prevOp = prevOp;
+    }
+    if (force || !this.ace.curOp) {
+      if (this.curOp)
+        this.onBeforeEndOperation();
+    }
+    return result;
+  };
+  this.onBeforeEndOperation = function() {
+    var op = this.curOp;
+    if (op) {
+      if (op.change) { this.signal("change", op.change, op); }
+      if (op && op.cursorActivity) { this.signal("cursorActivity", null, op); }
+      this.curOp = null;
+    }
+  };
+
+  this.signal = function(eventName, e, handlers) {
+    var listeners = handlers ? handlers[eventName + "Handlers"]
+        : (this._eventRegistry || {})[eventName];
+    if (!listeners)
+        return;
+    listeners = listeners.slice();
+    for (var i=0; i<listeners.length; i++)
+        listeners[i](this, e);
+  };
+  this.firstLine = function() { return 0; };
+  this.lastLine = function() { return this.ace.session.getLength() - 1; };
+  this.lineCount = function() { return this.ace.session.getLength(); };
+  this.setCursor = function(line, ch) {
+    if (typeof line === 'object') {
+      ch = line.ch;
+      line = line.line;
+    }
+    if (!this.ace.inVirtualSelectionMode)
+      this.ace.exitMultiSelectMode();
+    this.ace.session.unfold({row: line, column: ch});
+    this.ace.selection.moveTo(line, ch);
+  };
+  this.getCursor = function(p) {
+    var sel = this.ace.selection;
+    var pos = p == 'anchor' ? (sel.isEmpty() ? sel.lead : sel.anchor) :
+        p == 'head' || !p ? sel.lead : sel.getRange()[p];
+    return toCmPos(pos);
+  };
+  this.listSelections = function(p) {
+    var ranges = this.ace.multiSelect.rangeList.ranges;
+    if (!ranges.length || this.ace.inVirtualSelectionMode)
+      return [{anchor: this.getCursor('anchor'), head: this.getCursor('head')}];
+    return ranges.map(function(r) {
+      return {
+        anchor: this.clipPos(toCmPos(r.cursor == r.end ? r.start : r.end)),
+        head: this.clipPos(toCmPos(r.cursor))
+      };
+    }, this);
+  };
+  this.setSelections = function(p, primIndex) {
+    var sel = this.ace.multiSelect;
+    var ranges = p.map(function(x) {
+      var anchor = toAcePos(x.anchor);
+      var head = toAcePos(x.head);
+      var r = Range.comparePoints(anchor, head) < 0
+        ? new Range.fromPoints(anchor, head)
+        : new Range.fromPoints(head, anchor);
+      r.cursor = Range.comparePoints(r.start, head) ? r.end : r.start;
+      return r;
+    });
+    
+    if (this.ace.inVirtualSelectionMode) {
+      this.ace.selection.fromOrientedRange(ranges[0]);
+      return;
+    }
+    if (!primIndex) {
+        ranges = ranges.reverse();
+    } else if (ranges[primIndex]) {
+       ranges.push(ranges.splice(primIndex, 1)[0]);
+    }
+    sel.toSingleRange(ranges[0].clone());
+    var session = this.ace.session;
+    for (var i = 0; i < ranges.length; i++) {
+      var range = session.$clipRangeToDocument(ranges[i]); // todo why ace doesn't do this?
+      sel.addRange(range);
+    }
+  };
+  this.setSelection = function(a, h, options) {
+    var sel = this.ace.selection;
+    sel.moveTo(a.line, a.ch);
+    sel.selectTo(h.line, h.ch);
+    if (options && options.origin == '*mouse') {
+      this.onBeforeEndOperation();
+    }
+  };
+  this.somethingSelected = function(p) {
+    return !this.ace.selection.isEmpty();
+  };
+  this.clipPos = function(p) {
+    var pos = this.ace.session.$clipPositionToDocument(p.line, p.ch);
+    return toCmPos(pos);
+  };
+  this.markText = function(cursor) {
+    return {clear: function() {}, find: function() {}};
+  };
+  this.$updateMarkers = function(delta) {
+    var isInsert = delta.action == "insert";
+    var start = delta.start;
+    var end = delta.end;
+    var rowShift = (end.row - start.row) * (isInsert ? 1 : -1);
+    var colShift = (end.column - start.column) * (isInsert ? 1 : -1);
+    if (isInsert) end = start;
+    
+    for (var i in this.marks) {
+      var point = this.marks[i];
+      var cmp = Range.comparePoints(point, start);
+      if (cmp < 0) {
+        continue; // delta starts after the range
+      }
+      if (cmp === 0) {
+        if (isInsert) {
+          if (point.bias == 1) {
+            cmp = 1;
+          } else {
+            point.bias = -1;
+            continue;
+          }
+        }
+      }
+      var cmp2 = isInsert ? cmp : Range.comparePoints(point, end);
+      if (cmp2 > 0) {
+        point.row += rowShift;
+        point.column += point.row == end.row ? colShift : 0;
+        continue;
+      }
+      if (!isInsert && cmp2 <= 0) {
+        point.row = start.row;
+        point.column = start.column;
+        if (cmp2 === 0)
+          point.bias = 1;
+      }
+    }
+  };
+  var Marker = function(cm, id, row, column) {
+    this.cm = cm;
+    this.id = id;
+    this.row = row;
+    this.column = column;
+    cm.marks[this.id] = this;
+  };
+  Marker.prototype.clear = function() { delete this.cm.marks[this.id] };
+  Marker.prototype.find = function() { return toCmPos(this) };
+  this.setBookmark = function(cursor, options) {
+    var bm = new Marker(this, this.$uid++, cursor.line, cursor.ch);
+    if (!options || !options.insertLeft)
+      bm.$insertRight = true;
+    this.marks[bm.id] = bm;
+    return bm;
+  };
+  this.moveH = function(increment, unit) {
+    if (unit == 'char') {
+      var sel = this.ace.selection;
+      sel.clearSelection();
+      sel.moveCursorBy(0, increment);
+    }
+  };
+  this.findPosV = function(start, amount, unit, goalColumn) {
+    if (unit == 'page') {
+      var renderer = this.ace.renderer;
+      var config = renderer.layerConfig;
+      amount = amount * Math.floor(config.height / config.lineHeight);
+      unit = 'line';
+    }
+    if (unit == 'line') {
+      var screenPos = this.ace.session.documentToScreenPosition(start.line, start.ch);
+      if (goalColumn != null)
+        screenPos.column = goalColumn;
+      screenPos.row += amount;
+      screenPos.row = Math.min(Math.max(0, screenPos.row), this.ace.session.getScreenLength() - 1);
+      var pos = this.ace.session.screenToDocumentPosition(screenPos.row, screenPos.column);
+      return toCmPos(pos);
+    } else {
+      debugger;
+    }
+  };
+  this.charCoords = function(pos, mode) {
+    if (mode == 'div' || !mode) {
+      var sc = this.ace.session.documentToScreenPosition(pos.line, pos.ch);
+      return {left: sc.column, top: sc.row};
+    }if (mode == 'local') {
+      var renderer = this.ace.renderer;
+      var sc = this.ace.session.documentToScreenPosition(pos.line, pos.ch);
+      var lh = renderer.layerConfig.lineHeight;
+      var cw = renderer.layerConfig.characterWidth;
+      var top = lh * sc.row;
+      return {left: sc.column * cw, top: top, bottom: top + lh};
+    }
+  };
+  this.coordsChar = function(pos, mode) {
+    var renderer = this.ace.renderer;
+    if (mode == 'local') {
+      var row = Math.max(0, Math.floor(pos.top / renderer.lineHeight));
+      var col = Math.max(0, Math.floor(pos.left / renderer.characterWidth));
+      var ch = renderer.session.screenToDocumentPosition(row, col);
+      return toCmPos(ch);
+    } else if (mode == 'div') {
+      throw "not implemented";
+    }
+  };
+  this.getSearchCursor = function(query, pos, caseFold) {
+    var caseSensitive = false;
+    var isRegexp = false;
+    if (query instanceof RegExp && !query.global) {
+      caseSensitive = !query.ignoreCase;
+      query = query.source;
+      isRegexp = true;
+    }
+    var search = new Search();
+    if (pos.ch == undefined) pos.ch = Number.MAX_VALUE;
+    var acePos = {row: pos.line, column: pos.ch};
+    var cm = this;
+    var last = null;
+    return {
+      findNext: function() { return this.find(false) },
+      findPrevious: function() {return this.find(true) },
+      find: function(back) {
+        search.setOptions({
+          needle: query,
+          caseSensitive: caseSensitive,
+          wrap: false,
+          backwards: back,
+          regExp: isRegexp,
+          start: last || acePos
+        });
+        var range = search.find(cm.ace.session);
+        if (range && range.isEmpty()) {
+          if (cm.getLine(range.start.row).length == range.start.column) {
+            search.$options.start = range;
+            range = search.find(cm.ace.session);
+          }
+        }
+        last = range;
+        return last;
+      },
+      from: function() { return last && toCmPos(last.start) },
+      to: function() { return last && toCmPos(last.end) },
+      replace: function(text) {
+        if (last) {
+          last.end = cm.ace.session.doc.replace(last, text);
+        }
+      }
+    };
+  };
+  this.scrollTo = function(x, y) {
+    var renderer = this.ace.renderer;
+    var config = renderer.layerConfig;
+    var maxHeight = config.maxHeight;
+    maxHeight -= (renderer.$size.scrollerHeight - renderer.lineHeight) * renderer.$scrollPastEnd;
+    if (y != null) this.ace.session.setScrollTop(Math.max(0, Math.min(y, maxHeight)));
+    if (x != null) this.ace.session.setScrollLeft(Math.max(0, Math.min(x, config.width)));
+  };
+  this.scrollInfo = function() { return 0; };
+  this.scrollIntoView = function(pos, margin) {
+    if (pos) {
+      var renderer = this.ace.renderer;
+      var viewMargin = { "top": 0, "bottom": margin };
+      renderer.scrollCursorIntoView(toAcePos(pos),
+        (renderer.lineHeight * 2) / renderer.$size.scrollerHeight, viewMargin);
+    }
+  };
+  this.getLine = function(row) { return this.ace.session.getLine(row) };
+  this.getRange = function(s, e) {
+    return this.ace.session.getTextRange(new Range(s.line, s.ch, e.line, e.ch));
+  };
+  this.replaceRange = function(text, s, e) {
+    if (!e) e = s;
+    return this.ace.session.replace(new Range(s.line, s.ch, e.line, e.ch), text);
+  };
+  this.replaceSelections = function(p) {
+    var sel = this.ace.selection;
+    if (this.ace.inVirtualSelectionMode) {
+      this.ace.session.replace(sel.getRange(), p[0] || "");
+      return;
+    }
+    sel.inVirtualSelectionMode = true;
+    var ranges = sel.rangeList.ranges;
+    if (!ranges.length) ranges = [this.ace.multiSelect.getRange()];
+    for (var i = ranges.length; i--;)
+       this.ace.session.replace(ranges[i], p[i] || "");
+    sel.inVirtualSelectionMode = false;
+  };
+  this.getSelection = function() {
+    return this.ace.getSelectedText();
+  };
+  this.getSelections = function() {
+    return this.listSelections().map(function(x) {
+      return this.getRange(x.anchor, x.head);
+    }, this);
+  };
+  this.getInputField = function() {
+    return this.ace.textInput.getElement();
+  };
+  this.getWrapperElement = function() {
+    return this.ace.container;
+  };
+  var optMap = {
+    indentWithTabs: "useSoftTabs",
+    indentUnit: "tabSize",
+    tabSize: "tabSize",
+    firstLineNumber: "firstLineNumber",
+    readOnly: "readOnly"
+  };
+  this.setOption = function(name, val) {
+    this.state[name] = val;
+    switch (name) {
+      case 'indentWithTabs':
+        name = optMap[name];
+        val = !val;
+      break;
+      default:
+        name = optMap[name];
+    }
+    if (name)
+      this.ace.setOption(name, val);
+  };
+  this.getOption = function(name, val) {
+    var aceOpt = optMap[name];
+    if (aceOpt)
+      val = this.ace.getOption(aceOpt);
+    switch (name) {
+      case 'indentWithTabs':
+        name = optMap[name];
+        return !val;
+    }
+    return aceOpt ? val : this.state[name];
+  };
+  this.toggleOverwrite = function(on) {
+    this.state.overwrite = on;
+    return this.ace.setOverwrite(on);
+  };
+  this.addOverlay = function(o) {
+    if (!this.$searchHighlight || !this.$searchHighlight.session) {
+      var highlight = new SearchHighlight(null, "ace_highlight-marker", "text");
+      var marker = this.ace.session.addDynamicMarker(highlight);
+      highlight.id = marker.id;
+      highlight.session = this.ace.session;
+      highlight.destroy = function(o) {
+        highlight.session.off("change", highlight.updateOnChange);
+        highlight.session.off("changeEditor", highlight.destroy);
+        highlight.session.removeMarker(highlight.id);
+        highlight.session = null;
+      };
+      highlight.updateOnChange = function(delta) {
+        var row = delta.start.row;
+        if (row == delta.end.row) highlight.cache[row] = undefined;
+        else highlight.cache.splice(row, highlight.cache.length);
+      };
+      highlight.session.on("changeEditor", highlight.destroy);
+      highlight.session.on("change", highlight.updateOnChange);
+    }
+    var re = new RegExp(o.query.source, "gmi");
+    this.$searchHighlight = o.highlight = highlight;
+    this.$searchHighlight.setRegexp(re);
+    this.ace.renderer.updateBackMarkers();
+  };
+  this.removeOverlay = function(o) {
+    if (this.$searchHighlight && this.$searchHighlight.session) {
+      this.$searchHighlight.destroy();
+    }
+  };
+  this.getScrollInfo = function() {
+    var renderer = this.ace.renderer;
+    var config = renderer.layerConfig;
+    return {
+      left: renderer.scrollLeft,
+      top: renderer.scrollTop,
+      height: config.maxHeight,
+      width: config.width,
+      clientHeight: config.height,
+      clientWidth: config.width
+    };
+  };
+  this.getValue = function() {
+    return this.ace.getValue();
+  };
+  this.setValue = function(v) {
+    return this.ace.setValue(v);
+  };
+  this.getTokenTypeAt = function(pos) {
+    var token = this.ace.session.getTokenAt(pos.line, pos.ch);
+    return token && /comment|string/.test(token.type) ? "string" : "";
+  };
+  this.findMatchingBracket = function(pos) {
+    var m = this.ace.session.findMatchingBracket(toAcePos(pos));
+    return {to: m && toCmPos(m)};
+  };
+  this.indentLine = function(line, method) {
+    if (method === true)
+        this.ace.session.indentRows(line, line, "\t");
+    else if (method === false)
+        this.ace.session.outdentRows(new Range(line, 0, line, 0));
+  };
+  this.indexFromPos = function(pos) {
+    return this.ace.session.doc.positionToIndex(toAcePos(pos));
+  };
+  this.posFromIndex = function(index) {
+    return toCmPos(this.ace.session.doc.indexToPosition(index));
+  };
+  this.focus = function(index) {
+    return this.ace.textInput.focus();
+  };
+  this.blur = function(index) {
+    return this.ace.blur();
+  };
+  this.defaultTextHeight = function(index) {
+    return this.ace.renderer.layerConfig.lineHeight;
+  };
+  this.scanForBracket = function(pos, dir, _, options) {
+    var re = options.bracketRegex.source;
+    var tokenRe = /paren|text|operator|tag/;
+    if (dir == 1) {
+      var m = this.ace.session.$findClosingBracket(re.slice(1, 2), toAcePos(pos), tokenRe);
+    } else {
+      var m = this.ace.session.$findOpeningBracket(re.slice(-2, -1), {row: pos.line, column: pos.ch + 1}, tokenRe);
+    }
+    return m && {pos: toCmPos(m)};
+  };
+  this.refresh = function() {
+    return this.ace.resize(true);
+  };
+  this.getMode = function() {
+    return { name : this.getOption("mode") };
+  }
+}).call(CodeMirror.prototype);
+  function toAcePos(cmPos) {
+    return {row: cmPos.line, column: cmPos.ch};
+  }
+  function toCmPos(acePos) {
+    return new Pos(acePos.row, acePos.column);
+  }
+
+  var StringStream = CodeMirror.StringStream = function(string, tabSize) {
+    this.pos = this.start = 0;
+    this.string = string;
+    this.tabSize = tabSize || 8;
+    this.lastColumnPos = this.lastColumnValue = 0;
+    this.lineStart = 0;
+  };
+
+  StringStream.prototype = {
+    eol: function() {return this.pos >= this.string.length;},
+    sol: function() {return this.pos == this.lineStart;},
+    peek: function() {return this.string.charAt(this.pos) || undefined;},
+    next: function() {
+      if (this.pos < this.string.length)
+        return this.string.charAt(this.pos++);
+    },
+    eat: function(match) {
+      var ch = this.string.charAt(this.pos);
+      if (typeof match == "string") var ok = ch == match;
+      else var ok = ch && (match.test ? match.test(ch) : match(ch));
+      if (ok) {++this.pos; return ch;}
+    },
+    eatWhile: function(match) {
+      var start = this.pos;
+      while (this.eat(match)){}
+      return this.pos > start;
+    },
+    eatSpace: function() {
+      var start = this.pos;
+      while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;
+      return this.pos > start;
+    },
+    skipToEnd: function() {this.pos = this.string.length;},
+    skipTo: function(ch) {
+      var found = this.string.indexOf(ch, this.pos);
+      if (found > -1) {this.pos = found; return true;}
+    },
+    backUp: function(n) {this.pos -= n;},
+    column: function() {
+      throw "not implemented";
+    },
+    indentation: function() {
+      throw "not implemented";
+    },
+    match: function(pattern, consume, caseInsensitive) {
+      if (typeof pattern == "string") {
+        var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
+        var substr = this.string.substr(this.pos, pattern.length);
+        if (cased(substr) == cased(pattern)) {
+          if (consume !== false) this.pos += pattern.length;
+          return true;
+        }
+      } else {
+        var match = this.string.slice(this.pos).match(pattern);
+        if (match && match.index > 0) return null;
+        if (match && consume !== false) this.pos += match[0].length;
+        return match;
+      }
+    },
+    current: function(){return this.string.slice(this.start, this.pos);},
+    hideFirstChars: function(n, inner) {
+      this.lineStart += n;
+      try { return inner(); }
+      finally { this.lineStart -= n; }
+    }
+  };
+CodeMirror.defineExtension = function(name, fn) {
+  CodeMirror.prototype[name] = fn;
+};
+dom.importCssString(".normal-mode .ace_cursor{\
+    border: none;\
+    background-color: rgba(255,0,0,0.5);\
+}\
+.normal-mode .ace_hidden-cursors .ace_cursor{\
+  background-color: transparent;\
+  border: 1px solid red;\
+  opacity: 0.7\
+}\
+.ace_dialog {\
+  position: absolute;\
+  left: 0; right: 0;\
+  background: inherit;\
+  z-index: 15;\
+  padding: .1em .8em;\
+  overflow: hidden;\
+  color: inherit;\
+}\
+.ace_dialog-top {\
+  border-bottom: 1px solid #444;\
+  top: 0;\
+}\
+.ace_dialog-bottom {\
+  border-top: 1px solid #444;\
+  bottom: 0;\
+}\
+.ace_dialog input {\
+  border: none;\
+  outline: none;\
+  background: transparent;\
+  width: 20em;\
+  color: inherit;\
+  font-family: monospace;\
+}", "vimMode");
+(function() {
+  function dialogDiv(cm, template, bottom) {
+    var wrap = cm.ace.container;
+    var dialog;
+    dialog = wrap.appendChild(document.createElement("div"));
+    if (bottom)
+      dialog.className = "ace_dialog ace_dialog-bottom";
+    else
+      dialog.className = "ace_dialog ace_dialog-top";
+
+    if (typeof template == "string") {
+      dialog.innerHTML = template;
+    } else { // Assuming it's a detached DOM element.
+      dialog.appendChild(template);
+    }
+    return dialog;
+  }
+
+  function closeNotification(cm, newVal) {
+    if (cm.state.currentNotificationClose)
+      cm.state.currentNotificationClose();
+    cm.state.currentNotificationClose = newVal;
+  }
+
+  CodeMirror.defineExtension("openDialog", function(template, callback, options) {
+    if (this.virtualSelectionMode()) return;
+    if (!options) options = {};
+
+    closeNotification(this, null);
+
+    var dialog = dialogDiv(this, template, options.bottom);
+    var closed = false, me = this;
+    this.state.dialog = dialog;
+    function close(newVal) {
+      if (typeof newVal == 'string') {
+        inp.value = newVal;
+      } else {
+        if (closed) return;
+        
+        if (newVal && newVal.type == "blur") {
+          if (document.activeElement === inp)
+            return;
+        }
+        
+        me.state.dialog = null;
+        closed = true;
+        dialog.parentNode.removeChild(dialog);
+        me.focus();
+
+        if (options.onClose) options.onClose(dialog);
+      }
+    }
+
+    var inp = dialog.getElementsByTagName("input")[0], button;
+    if (inp) {
+      if (options.value) {
+        inp.value = options.value;
+        if (options.selectValueOnOpen !== false) inp.select();
+      }
+
+      if (options.onInput)
+        CodeMirror.on(inp, "input", function(e) { options.onInput(e, inp.value, close);});
+      if (options.onKeyUp)
+        CodeMirror.on(inp, "keyup", function(e) {options.onKeyUp(e, inp.value, close);});
+
+      CodeMirror.on(inp, "keydown", function(e) {
+        if (options && options.onKeyDown && options.onKeyDown(e, inp.value, close)) { return; }
+        if (e.keyCode == 13) callback(inp.value);
+        if (e.keyCode == 27 || (options.closeOnEnter !== false && e.keyCode == 13)) {
+          inp.blur();
+          CodeMirror.e_stop(e);
+          close();
+        }
+      });
+
+      if (options.closeOnBlur !== false) CodeMirror.on(inp, "blur", close);
+
+      inp.focus();
+    } else if (button = dialog.getElementsByTagName("button")[0]) {
+      CodeMirror.on(button, "click", function() {
+        close();
+        me.focus();
+      });
+
+      if (options.closeOnBlur !== false) CodeMirror.on(button, "blur", close);
+
+      button.focus();
+    }
+    return close;
+  });
+
+  CodeMirror.defineExtension("openNotification", function(template, options) {
+    if (this.virtualSelectionMode()) return;
+    closeNotification(this, close);
+    var dialog = dialogDiv(this, template, options && options.bottom);
+    var closed = false, doneTimer;
+    var duration = options && typeof options.duration !== "undefined" ? options.duration : 5000;
+
+    function close() {
+      if (closed) return;
+      closed = true;
+      clearTimeout(doneTimer);
+      dialog.parentNode.removeChild(dialog);
+    }
+
+    CodeMirror.on(dialog, 'click', function(e) {
+      CodeMirror.e_preventDefault(e);
+      close();
+    });
+
+    if (duration)
+      doneTimer = setTimeout(close, duration);
+
+    return close;
+  });
+})();
+
+  
+  var defaultKeymap = [
+    { keys: '<Left>', type: 'keyToKey', toKeys: 'h' },
+    { keys: '<Right>', type: 'keyToKey', toKeys: 'l' },
+    { keys: '<Up>', type: 'keyToKey', toKeys: 'k' },
+    { keys: '<Down>', type: 'keyToKey', toKeys: 'j' },
+    { keys: '<Space>', type: 'keyToKey', toKeys: 'l' },
+    { keys: '<BS>', type: 'keyToKey', toKeys: 'h', context: 'normal'},
+    { keys: '<C-Space>', type: 'keyToKey', toKeys: 'W' },
+    { keys: '<C-BS>', type: 'keyToKey', toKeys: 'B', context: 'normal' },
+    { keys: '<S-Space>', type: 'keyToKey', toKeys: 'w' },
+    { keys: '<S-BS>', type: 'keyToKey', toKeys: 'b', context: 'normal' },
+    { keys: '<C-n>', type: 'keyToKey', toKeys: 'j' },
+    { keys: '<C-p>', type: 'keyToKey', toKeys: 'k' },
+    { keys: '<C-[>', type: 'keyToKey', toKeys: '<Esc>' },
+    { keys: '<C-c>', type: 'keyToKey', toKeys: '<Esc>' },
+    { keys: '<C-[>', type: 'keyToKey', toKeys: '<Esc>', context: 'insert' },
+    { keys: '<C-c>', type: 'keyToKey', toKeys: '<Esc>', context: 'insert' },
+    { keys: 's', type: 'keyToKey', toKeys: 'cl', context: 'normal' },
+    { keys: 's', type: 'keyToKey', toKeys: 'c', context: 'visual'},
+    { keys: 'S', type: 'keyToKey', toKeys: 'cc', context: 'normal' },
+    { keys: 'S', type: 'keyToKey', toKeys: 'VdO', context: 'visual' },
+    { keys: '<Home>', type: 'keyToKey', toKeys: '0' },
+    { keys: '<End>', type: 'keyToKey', toKeys: '$' },
+    { keys: '<PageUp>', type: 'keyToKey', toKeys: '<C-b>' },
+    { keys: '<PageDown>', type: 'keyToKey', toKeys: '<C-f>' },
+    { keys: '<CR>', type: 'keyToKey', toKeys: 'j^', context: 'normal' },
+    { keys: '<Ins>', type: 'action', action: 'toggleOverwrite', context: 'insert' },
+    { keys: 'H', type: 'motion', motion: 'moveToTopLine', motionArgs: { linewise: true, toJumplist: true }},
+    { keys: 'M', type: 'motion', motion: 'moveToMiddleLine', motionArgs: { linewise: true, toJumplist: true }},
+    { keys: 'L', type: 'motion', motion: 'moveToBottomLine', motionArgs: { linewise: true, toJumplist: true }},
+    { keys: 'h', type: 'motion', motion: 'moveByCharacters', motionArgs: { forward: false }},
+    { keys: 'l', type: 'motion', motion: 'moveByCharacters', motionArgs: { forward: true }},
+    { keys: 'j', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, linewise: true }},
+    { keys: 'k', type: 'motion', motion: 'moveByLines', motionArgs: { forward: false, linewise: true }},
+    { keys: 'gj', type: 'motion', motion: 'moveByDisplayLines', motionArgs: { forward: true }},
+    { keys: 'gk', type: 'motion', motion: 'moveByDisplayLines', motionArgs: { forward: false }},
+    { keys: 'w', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: false }},
+    { keys: 'W', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: false, bigWord: true }},
+    { keys: 'e', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: true, inclusive: true }},
+    { keys: 'E', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: true, bigWord: true, inclusive: true }},
+    { keys: 'b', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false }},
+    { keys: 'B', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false, bigWord: true }},
+    { keys: 'ge', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: true, inclusive: true }},
+    { keys: 'gE', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: true, bigWord: true, inclusive: true }},
+    { keys: '{', type: 'motion', motion: 'moveByParagraph', motionArgs: { forward: false, toJumplist: true }},
+    { keys: '}', type: 'motion', motion: 'moveByParagraph', motionArgs: { forward: true, toJumplist: true }},
+    { keys: '<C-f>', type: 'motion', motion: 'moveByPage', motionArgs: { forward: true }},
+    { keys: '<C-b>', type: 'motion', motion: 'moveByPage', motionArgs: { forward: false }},
+    { keys: '<C-d>', type: 'motion', motion: 'moveByScroll', motionArgs: { forward: true, explicitRepeat: true }},
+    { keys: '<C-u>', type: 'motion', motion: 'moveByScroll', motionArgs: { forward: false, explicitRepeat: true }},
+    { keys: 'gg', type: 'motion', motion: 'moveToLineOrEdgeOfDocument', motionArgs: { forward: false, explicitRepeat: true, linewise: true, toJumplist: true }},
+    { keys: 'G', type: 'motion', motion: 'moveToLineOrEdgeOfDocument', motionArgs: { forward: true, explicitRepeat: true, linewise: true, toJumplist: true }},
+    { keys: '0', type: 'motion', motion: 'moveToStartOfLine' },
+    { keys: '^', type: 'motion', motion: 'moveToFirstNonWhiteSpaceCharacter' },
+    { keys: '+', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, toFirstChar:true }},
+    { keys: '-', type: 'motion', motion: 'moveByLines', motionArgs: { forward: false, toFirstChar:true }},
+    { keys: '_', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, toFirstChar:true, repeatOffset:-1 }},
+    { keys: '$', type: 'motion', motion: 'moveToEol', motionArgs: { inclusive: true }},
+    { keys: '%', type: 'motion', motion: 'moveToMatchedSymbol', motionArgs: { inclusive: true, toJumplist: true }},
+    { keys: 'f<character>', type: 'motion', motion: 'moveToCharacter', motionArgs: { forward: true , inclusive: true }},
+    { keys: 'F<character>', type: 'motion', motion: 'moveToCharacter', motionArgs: { forward: false }},
+    { keys: 't<character>', type: 'motion', motion: 'moveTillCharacter', motionArgs: { forward: true, inclusive: true }},
+    { keys: 'T<character>', type: 'motion', motion: 'moveTillCharacter', motionArgs: { forward: false }},
+    { keys: ';', type: 'motion', motion: 'repeatLastCharacterSearch', motionArgs: { forward: true }},
+    { keys: ',', type: 'motion', motion: 'repeatLastCharacterSearch', motionArgs: { forward: false }},
+    { keys: '\'<character>', type: 'motion', motion: 'goToMark', motionArgs: {toJumplist: true, linewise: true}},
+    { keys: '`<character>', type: 'motion', motion: 'goToMark', motionArgs: {toJumplist: true}},
+    { keys: ']`', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: true } },
+    { keys: '[`', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: false } },
+    { keys: ']\'', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: true, linewise: true } },
+    { keys: '[\'', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: false, linewise: true } },
+    { keys: ']p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: true, isEdit: true, matchIndent: true}},
+    { keys: '[p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: false, isEdit: true, matchIndent: true}},
+    { keys: ']<character>', type: 'motion', motion: 'moveToSymbol', motionArgs: { forward: true, toJumplist: true}},
+    { keys: '[<character>', type: 'motion', motion: 'moveToSymbol', motionArgs: { forward: false, toJumplist: true}},
+    { keys: '|', type: 'motion', motion: 'moveToColumn'},
+    { keys: 'o', type: 'motion', motion: 'moveToOtherHighlightedEnd', context:'visual'},
+    { keys: 'O', type: 'motion', motion: 'moveToOtherHighlightedEnd', motionArgs: {sameLine: true}, context:'visual'},
+    { keys: 'd', type: 'operator', operator: 'delete' },
+    { keys: 'y', type: 'operator', operator: 'yank' },
+    { keys: 'c', type: 'operator', operator: 'change' },
+    { keys: '>', type: 'operator', operator: 'indent', operatorArgs: { indentRight: true }},
+    { keys: '<', type: 'operator', operator: 'indent', operatorArgs: { indentRight: false }},
+    { keys: 'g~', type: 'operator', operator: 'changeCase' },
+    { keys: 'gu', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: true}, isEdit: true },
+    { keys: 'gU', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: false}, isEdit: true },
+    { keys: 'n', type: 'motion', motion: 'findNext', motionArgs: { forward: true, toJumplist: true }},
+    { keys: 'N', type: 'motion', motion: 'findNext', motionArgs: { forward: false, toJumplist: true }},
+    { keys: 'x', type: 'operatorMotion', operator: 'delete', motion: 'moveByCharacters', motionArgs: { forward: true }, operatorMotionArgs: { visualLine: false }},
+    { keys: 'X', type: 'operatorMotion', operator: 'delete', motion: 'moveByCharacters', motionArgs: { forward: false }, operatorMotionArgs: { visualLine: true }},
+    { keys: 'D', type: 'operatorMotion', operator: 'delete', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'},
+    { keys: 'D', type: 'operator', operator: 'delete', operatorArgs: { linewise: true }, context: 'visual'},
+    { keys: 'Y', type: 'operatorMotion', operator: 'yank', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'},
+    { keys: 'Y', type: 'operator', operator: 'yank', operatorArgs: { linewise: true }, context: 'visual'},
+    { keys: 'C', type: 'operatorMotion', operator: 'change', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'},
+    { keys: 'C', type: 'operator', operator: 'change', operatorArgs: { linewise: true }, context: 'visual'},
+    { keys: '~', type: 'operatorMotion', operator: 'changeCase', motion: 'moveByCharacters', motionArgs: { forward: true }, operatorArgs: { shouldMoveCursor: true }, context: 'normal'},
+    { keys: '~', type: 'operator', operator: 'changeCase', context: 'visual'},
+    { keys: '<C-w>', type: 'operatorMotion', operator: 'delete', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false }, context: 'insert' },
+    { keys: '<C-i>', type: 'action', action: 'jumpListWalk', actionArgs: { forward: true }},
+    { keys: '<C-o>', type: 'action', action: 'jumpListWalk', actionArgs: { forward: false }},
+    { keys: '<C-e>', type: 'action', action: 'scroll', actionArgs: { forward: true, linewise: true }},
+    { keys: '<C-y>', type: 'action', action: 'scroll', actionArgs: { forward: false, linewise: true }},
+    { keys: 'a', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'charAfter' }, context: 'normal' },
+    { keys: 'A', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'eol' }, context: 'normal' },
+    { keys: 'A', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'endOfSelectedArea' }, context: 'visual' },
+    { keys: 'i', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'inplace' }, context: 'normal' },
+    { keys: 'I', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'firstNonBlank'}, context: 'normal' },
+    { keys: 'I', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'startOfSelectedArea' }, context: 'visual' },
+    { keys: 'o', type: 'action', action: 'newLineAndEnterInsertMode', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: true }, context: 'normal' },
+    { keys: 'O', type: 'action', action: 'newLineAndEnterInsertMode', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: false }, context: 'normal' },
+    { keys: 'v', type: 'action', action: 'toggleVisualMode' },
+    { keys: 'V', type: 'action', action: 'toggleVisualMode', actionArgs: { linewise: true }},
+    { keys: '<C-v>', type: 'action', action: 'toggleVisualMode', actionArgs: { blockwise: true }},
+    { keys: '<C-q>', type: 'action', action: 'toggleVisualMode', actionArgs: { blockwise: true }},
+    { keys: 'gv', type: 'action', action: 'reselectLastSelection' },
+    { keys: 'J', type: 'action', action: 'joinLines', isEdit: true },
+    { keys: 'p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: true, isEdit: true }},
+    { keys: 'P', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: false, isEdit: true }},
+    { keys: 'r<character>', type: 'action', action: 'replace', isEdit: true },
+    { keys: '@<character>', type: 'action', action: 'replayMacro' },
+    { keys: 'q<character>', type: 'action', action: 'enterMacroRecordMode' },
+    { keys: 'R', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { replace: true }},
+    { keys: 'u', type: 'action', action: 'undo', context: 'normal' },
+    { keys: 'u', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: true}, context: 'visual', isEdit: true },
+    { keys: 'U', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: false}, context: 'visual', isEdit: true },
+    { keys: '<C-r>', type: 'action', action: 'redo' },
+    { keys: 'm<character>', type: 'action', action: 'setMark' },
+    { keys: '"<character>', type: 'action', action: 'setRegister' },
+    { keys: 'zz', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'center' }},
+    { keys: 'z.', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'center' }, motion: 'moveToFirstNonWhiteSpaceCharacter' },
+    { keys: 'zt', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'top' }},
+    { keys: 'z<CR>', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'top' }, motion: 'moveToFirstNonWhiteSpaceCharacter' },
+    { keys: 'z-', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'bottom' }},
+    { keys: 'zb', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'bottom' }, motion: 'moveToFirstNonWhiteSpaceCharacter' },
+    { keys: '.', type: 'action', action: 'repeatLastEdit' },
+    { keys: '<C-a>', type: 'action', action: 'incrementNumberToken', isEdit: true, actionArgs: {increase: true, backtrack: false}},
+    { keys: '<C-x>', type: 'action', action: 'incrementNumberToken', isEdit: true, actionArgs: {increase: false, backtrack: false}},
+    { keys: '<C-t>', type: 'action', action: 'indent', actionArgs: { indentRight: true }, context: 'insert' },
+    { keys: '<C-d>', type: 'action', action: 'indent', actionArgs: { indentRight: false }, context: 'insert' },
+    { keys: 'a<character>', type: 'motion', motion: 'textObjectManipulation' },
+    { keys: 'i<character>', type: 'motion', motion: 'textObjectManipulation', motionArgs: { textObjectInner: true }},
+    { keys: '/', type: 'search', searchArgs: { forward: true, querySrc: 'prompt', toJumplist: true }},
+    { keys: '?', type: 'search', searchArgs: { forward: false, querySrc: 'prompt', toJumplist: true }},
+    { keys: '*', type: 'search', searchArgs: { forward: true, querySrc: 'wordUnderCursor', wholeWordOnly: true, toJumplist: true }},
+    { keys: '#', type: 'search', searchArgs: { forward: false, querySrc: 'wordUnderCursor', wholeWordOnly: true, toJumplist: true }},
+    { keys: 'g*', type: 'search', searchArgs: { forward: true, querySrc: 'wordUnderCursor', toJumplist: true }},
+    { keys: 'g#', type: 'search', searchArgs: { forward: false, querySrc: 'wordUnderCursor', toJumplist: true }},
+    { keys: ':', type: 'ex' }
+  ];
+  var defaultExCommandMap = [
+    { name: 'colorscheme', shortName: 'colo' },
+    { name: 'map' },
+    { name: 'imap', shortName: 'im' },
+    { name: 'nmap', shortName: 'nm' },
+    { name: 'vmap', shortName: 'vm' },
+    { name: 'unmap' },
+    { name: 'write', shortName: 'w' },
+    { name: 'undo', shortName: 'u' },
+    { name: 'redo', shortName: 'red' },
+    { name: 'set', shortName: 'se' },
+    { name: 'set', shortName: 'se' },
+    { name: 'setlocal', shortName: 'setl' },
+    { name: 'setglobal', shortName: 'setg' },
+    { name: 'sort', shortName: 'sor' },
+    { name: 'substitute', shortName: 's', possiblyAsync: true },
+    { name: 'nohlsearch', shortName: 'noh' },
+    { name: 'yank', shortName: 'y' },
+    { name: 'delmarks', shortName: 'delm' },
+    { name: 'registers', shortName: 'reg', excludeFromCommandHistory: true },
+    { name: 'global', shortName: 'g' }
+  ];
+
+  var Pos = CodeMirror.Pos;
+
+  var Vim = function() { return vimApi; } //{
+    function enterVimMode(cm) {
+      cm.setOption('disableInput', true);
+      cm.setOption('showCursorWhenSelecting', false);
+      CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"});
+      cm.on('cursorActivity', onCursorActivity);
+      maybeInitVimState(cm);
+      CodeMirror.on(cm.getInputField(), 'paste', getOnPasteFn(cm));
+    }
+
+    function leaveVimMode(cm) {
+      cm.setOption('disableInput', false);
+      cm.off('cursorActivity', onCursorActivity);
+      CodeMirror.off(cm.getInputField(), 'paste', getOnPasteFn(cm));
+      cm.state.vim = null;
+    }
+
+    function detachVimMap(cm, next) {
+      if (this == CodeMirror.keyMap.vim)
+        CodeMirror.rmClass(cm.getWrapperElement(), "cm-fat-cursor");
+
+      if (!next || next.attach != attachVimMap)
+        leaveVimMode(cm);
+    }
+    function attachVimMap(cm, prev) {
+      if (this == CodeMirror.keyMap.vim)
+        CodeMirror.addClass(cm.getWrapperElement(), "cm-fat-cursor");
+
+      if (!prev || prev.attach != attachVimMap)
+        enterVimMode(cm);
+    }
+    CodeMirror.defineOption('vimMode', false, function(cm, val, prev) {
+      if (val && cm.getOption("keyMap") != "vim")
+        cm.setOption("keyMap", "vim");
+      else if (!val && prev != CodeMirror.Init && /^vim/.test(cm.getOption("keyMap")))
+        cm.setOption("keyMap", "default");
+    });
+
+    function cmKey(key, cm) {
+      if (!cm) { return undefined; }
+      if (this[key]) { return this[key]; }
+      var vimKey = cmKeyToVimKey(key);
+      if (!vimKey) {
+        return false;
+      }
+      var cmd = CodeMirror.Vim.findKey(cm, vimKey);
+      if (typeof cmd == 'function') {
+        CodeMirror.signal(cm, 'vim-keypress', vimKey);
+      }
+      return cmd;
+    }
+
+    var modifiers = {'Shift': 'S', 'Ctrl': 'C', 'Alt': 'A', 'Cmd': 'D', 'Mod': 'A'};
+    var specialKeys = {Enter:'CR',Backspace:'BS',Delete:'Del',Insert:'Ins'};
+    function cmKeyToVimKey(key) {
+      if (key.charAt(0) == '\'') {
+        return key.charAt(1);
+      }
+      var pieces = key.split(/-(?!$)/);
+      var lastPiece = pieces[pieces.length - 1];
+      if (pieces.length == 1 && pieces[0].length == 1) {
+        return false;
+      } else if (pieces.length == 2 && pieces[0] == 'Shift' && lastPiece.length == 1) {
+        return false;
+      }
+      var hasCharacter = false;
+      for (var i = 0; i < pieces.length; i++) {
+        var piece = pieces[i];
+        if (piece in modifiers) { pieces[i] = modifiers[piece]; }
+        else { hasCharacter = true; }
+        if (piece in specialKeys) { pieces[i] = specialKeys[piece]; }
+      }
+      if (!hasCharacter) {
+        return false;
+      }
+      if (isUpperCase(lastPiece)) {
+        pieces[pieces.length - 1] = lastPiece.toLowerCase();
+      }
+      return '<' + pieces.join('-') + '>';
+    }
+
+    function getOnPasteFn(cm) {
+      var vim = cm.state.vim;
+      if (!vim.onPasteFn) {
+        vim.onPasteFn = function() {
+          if (!vim.insertMode) {
+            cm.setCursor(offsetCursor(cm.getCursor(), 0, 1));
+            actions.enterInsertMode(cm, {}, vim);
+          }
+        };
+      }
+      return vim.onPasteFn;
+    }
+
+    var numberRegex = /[\d]/;
+    var wordCharTest = [CodeMirror.isWordChar, function(ch) {
+      return ch && !CodeMirror.isWordChar(ch) && !/\s/.test(ch);
+    }], bigWordCharTest = [function(ch) {
+      return /\S/.test(ch);
+    }];
+    function makeKeyRange(start, size) {
+      var keys = [];
+      for (var i = start; i < start + size; i++) {
+        keys.push(String.fromCharCode(i));
+      }
+      return keys;
+    }
+    var upperCaseAlphabet = makeKeyRange(65, 26);
+    var lowerCaseAlphabet = makeKeyRange(97, 26);
+    var numbers = makeKeyRange(48, 10);
+    var validMarks = [].concat(upperCaseAlphabet, lowerCaseAlphabet, numbers, ['<', '>']);
+    var validRegisters = [].concat(upperCaseAlphabet, lowerCaseAlphabet, numbers, ['-', '"', '.', ':', '/']);
+
+    function isLine(cm, line) {
+      return line >= cm.firstLine() && line <= cm.lastLine();
+    }
+    function isLowerCase(k) {
+      return (/^[a-z]$/).test(k);
+    }
+    function isMatchableSymbol(k) {
+      return '()[]{}'.indexOf(k) != -1;
+    }
+    function isNumber(k) {
+      return numberRegex.test(k);
+    }
+    function isUpperCase(k) {
+      return (/^[A-Z]$/).test(k);
+    }
+    function isWhiteSpaceString(k) {
+      return (/^\s*$/).test(k);
+    }
+    function inArray(val, arr) {
+      for (var i = 0; i < arr.length; i++) {
+        if (arr[i] == val) {
+          return true;
+        }
+      }
+      return false;
+    }
+
+    var options = {};
+    function defineOption(name, defaultValue, type, aliases, callback) {
+      if (defaultValue === undefined && !callback) {
+        throw Error('defaultValue is required unless callback is provided');
+      }
+      if (!type) { type = 'string'; }
+      options[name] = {
+        type: type,
+        defaultValue: defaultValue,
+        callback: callback
+      };
+      if (aliases) {
+        for (var i = 0; i < aliases.length; i++) {
+          options[aliases[i]] = options[name];
+        }
+      }
+      if (defaultValue) {
+        setOption(name, defaultValue);
+      }
+    }
+
+    function setOption(name, value, cm, cfg) {
+      var option = options[name];
+      cfg = cfg || {};
+      var scope = cfg.scope;
+      if (!option) {
+        return new Error('Unknown option: ' + name);
+      }
+      if (option.type == 'boolean') {
+        if (value && value !== true) {
+          return new Error('Invalid argument: ' + name + '=' + value);
+        } else if (value !== false) {
+          value = true;
+        }
+      }
+      if (option.callback) {
+        if (scope !== 'local') {
+          option.callback(value, undefined);
+        }
+        if (scope !== 'global' && cm) {
+          option.callback(value, cm);
+        }
+      } else {
+        if (scope !== 'local') {
+          option.value = option.type == 'boolean' ? !!value : value;
+        }
+        if (scope !== 'global' && cm) {
+          cm.state.vim.options[name] = {value: value};
+        }
+      }
+    }
+
+    function getOption(name, cm, cfg) {
+      var option = options[name];
+      cfg = cfg || {};
+      var scope = cfg.scope;
+      if (!option) {
+        return new Error('Unknown option: ' + name);
+      }
+      if (option.callback) {
+        var local = cm && option.callback(undefined, cm);
+        if (scope !== 'global' && local !== undefined) {
+          return local;
+        }
+        if (scope !== 'local') {
+          return option.callback();
+        }
+        return;
+      } else {
+        var local = (scope !== 'global') && (cm && cm.state.vim.options[name]);
+        return (local || (scope !== 'local') && option || {}).value;
+      }
+    }
+
+    defineOption('filetype', undefined, 'string', ['ft'], function(name, cm) {
+      if (cm === undefined) {
+        return;
+      }
+      if (name === undefined) {
+        var mode = cm.getOption('mode');
+        return mode == 'null' ? '' : mode;
+      } else {
+        var mode = name == '' ? 'null' : name;
+        cm.setOption('mode', mode);
+      }
+    });
+
+    var createCircularJumpList = function() {
+      var size = 100;
+      var pointer = -1;
+      var head = 0;
+      var tail = 0;
+      var buffer = new Array(size);
+      function add(cm, oldCur, newCur) {
+        var current = pointer % size;
+        var curMark = buffer[current];
+        function useNextSlot(cursor) {
+          var next = ++pointer % size;
+          var trashMark = buffer[next];
+          if (trashMark) {
+            trashMark.clear();
+          }
+          buffer[next] = cm.setBookmark(cursor);
+        }
+        if (curMark) {
+          var markPos = curMark.find();
+          if (markPos && !cursorEqual(markPos, oldCur)) {
+            useNextSlot(oldCur);
+          }
+        } else {
+          useNextSlot(oldCur);
+        }
+        useNextSlot(newCur);
+        head = pointer;
+        tail = pointer - size + 1;
+        if (tail < 0) {
+          tail = 0;
+        }
+      }
+      function move(cm, offset) {
+        pointer += offset;
+        if (pointer > head) {
+          pointer = head;
+        } else if (pointer < tail) {
+          pointer = tail;
+        }
+        var mark = buffer[(size + pointer) % size];
+        if (mark && !mark.find()) {
+          var inc = offset > 0 ? 1 : -1;
+          var newCur;
+          var oldCur = cm.getCursor();
+          do {
+            pointer += inc;
+            mark = buffer[(size + pointer) % size];
+            if (mark &&
+                (newCur = mark.find()) &&
+                !cursorEqual(oldCur, newCur)) {
+              break;
+            }
+          } while (pointer < head && pointer > tail);
+        }
+        return mark;
+      }
+      return {
+        cachedCursor: undefined, //used for # and * jumps
+        add: add,
+        move: move
+      };
+    };
+    var createInsertModeChanges = function(c) {
+      if (c) {
+        return {
+          changes: c.changes,
+          expectCursorActivityForChange: c.expectCursorActivityForChange
+        };
+      }
+      return {
+        changes: [],
+        expectCursorActivityForChange: false
+      };
+    };
+
+    function MacroModeState() {
+      this.latestRegister = undefined;
+      this.isPlaying = false;
+      this.isRecording = false;
+      this.replaySearchQueries = [];
+      this.onRecordingDone = undefined;
+      this.lastInsertModeChanges = createInsertModeChanges();
+    }
+    MacroModeState.prototype = {
+      exitMacroRecordMode: function() {
+        var macroModeState = vimGlobalState.macroModeState;
+        if (macroModeState.onRecordingDone) {
+          macroModeState.onRecordingDone(); // close dialog
+        }
+        macroModeState.onRecordingDone = undefined;
+        macroModeState.isRecording = false;
+      },
+      enterMacroRecordMode: function(cm, registerName) {
+        var register =
+            vimGlobalState.registerController.getRegister(registerName);
+        if (register) {
+          register.clear();
+          this.latestRegister = registerName;
+          if (cm.openDialog) {
+            this.onRecordingDone = cm.openDialog(
+                '(recording)['+registerName+']', null, {bottom:true});
+          }
+          this.isRecording = true;
+        }
+      }
+    };
+
+    function maybeInitVimState(cm) {
+      if (!cm.state.vim) {
+        cm.state.vim = {
+          inputState: new InputState(),
+          lastEditInputState: undefined,
+          lastEditActionCommand: undefined,
+          lastHPos: -1,
+          lastHSPos: -1,
+          lastMotion: null,
+          marks: {},
+          fakeCursor: null,
+          insertMode: false,
+          insertModeRepeat: undefined,
+          visualMode: false,
+          visualLine: false,
+          visualBlock: false,
+          lastSelection: null,
+          lastPastedText: null,
+          sel: {},
+          options: {}
+        };
+      }
+      return cm.state.vim;
+    }
+    var vimGlobalState;
+    function resetVimGlobalState() {
+      vimGlobalState = {
+        searchQuery: null,
+        searchIsReversed: false,
+        lastSubstituteReplacePart: undefined,
+        jumpList: createCircularJumpList(),
+        macroModeState: new MacroModeState,
+        lastCharacterSearch: {increment:0, forward:true, selectedCharacter:''},
+        registerController: new RegisterController({}),
+        searchHistoryController: new HistoryController(),
+        exCommandHistoryController : new HistoryController()
+      };
+      for (var optionName in options) {
+        var option = options[optionName];
+        option.value = option.defaultValue;
+      }
+    }
+
+    var lastInsertModeKeyTimer;
+    var vimApi= {
+      buildKeyMap: function() {
+      },
+      getRegisterController: function() {
+        return vimGlobalState.registerController;
+      },
+      resetVimGlobalState_: resetVimGlobalState,
+      getVimGlobalState_: function() {
+        return vimGlobalState;
+      },
+      maybeInitVimState_: maybeInitVimState,
+
+      suppressErrorLogging: false,
+
+      InsertModeKey: InsertModeKey,
+      map: function(lhs, rhs, ctx) {
+        exCommandDispatcher.map(lhs, rhs, ctx);
+      },
+      unmap: function(lhs, ctx) {
+        exCommandDispatcher.unmap(lhs, ctx);
+      },
+      setOption: setOption,
+      getOption: getOption,
+      defineOption: defineOption,
+      defineEx: function(name, prefix, func){
+        if (!prefix) {
+          prefix = name;
+        } else if (name.indexOf(prefix) !== 0) {
+          throw new Error('(Vim.defineEx) "'+prefix+'" is not a prefix of "'+name+'", command not registered');
+        }
+        exCommands[name]=func;
+        exCommandDispatcher.commandMap_[prefix]={name:name, shortName:prefix, type:'api'};
+      },
+      handleKey: function (cm, key, origin) {
+        var command = this.findKey(cm, key, origin);
+        if (typeof command === 'function') {
+          return command();
+        }
+      },
+      findKey: function(cm, key, origin) {
+        var vim = maybeInitVimState(cm);
+        function handleMacroRecording() {
+          var macroModeState = vimGlobalState.macroModeState;
+          if (macroModeState.isRecording) {
+            if (key == 'q') {
+              macroModeState.exitMacroRecordMode();
+              clearInputState(cm);
+              return true;
+            }
+            if (origin != 'mapping') {
+              logKey(macroModeState, key);
+            }
+          }
+        }
+        function handleEsc() {
+          if (key == '<Esc>') {
+            clearInputState(cm);
+            if (vim.visualMode) {
+              exitVisualMode(cm);
+            } else if (vim.insertMode) {
+              exitInsertMode(cm);
+            }
+            return true;
+          }
+        }
+        function doKeyToKey(keys) {
+          var match;
+          while (keys) {
+            match = (/<\w+-.+?>|<\w+>|./).exec(keys);
+            key = match[0];
+            keys = keys.substring(match.index + key.length);
+            CodeMirror.Vim.handleKey(cm, key, 'mapping');
+          }
+        }
+
+        function handleKeyInsertMode() {
+          if (handleEsc()) { return true; }
+          var keys = vim.inputState.keyBuffer = vim.inputState.keyBuffer + key;
+          var keysAreChars = key.length == 1;
+          var match = commandDispatcher.matchCommand(keys, defaultKeymap, vim.inputState, 'insert');
+          while (keys.length > 1 && match.type != 'full') {
+            var keys = vim.inputState.keyBuffer = keys.slice(1);
+            var thisMatch = commandDispatcher.matchCommand(keys, defaultKeymap, vim.inputState, 'insert');
+            if (thisMatch.type != 'none') { match = thisMatch; }
+          }
+          if (match.type == 'none') { clearInputState(cm); return false; }
+          else if (match.type == 'partial') {
+            if (lastInsertModeKeyTimer) { window.clearTimeout(lastInsertModeKeyTimer); }
+            lastInsertModeKeyTimer = window.setTimeout(
+              function() { if (vim.insertMode && vim.inputState.keyBuffer) { clearInputState(cm); } },
+              getOption('insertModeEscKeysTimeout'));
+            return !keysAreChars;
+          }
+
+          if (lastInsertModeKeyTimer) { window.clearTimeout(lastInsertModeKeyTimer); }
+          if (keysAreChars) {
+            var selections = cm.listSelections();
+            for (var i = 0; i < selections.length; i++) {
+              var here = selections[i].head;
+              cm.replaceRange('', offsetCursor(here, 0, -(keys.length - 1)), here, '+input');
+            }
+            vimGlobalState.macroModeState.lastInsertModeChanges.changes.pop();
+          }
+          clearInputState(cm);
+          return match.command;
+        }
+
+        function handleKeyNonInsertMode() {
+          if (handleMacroRecording() || handleEsc()) { return true; }
+
+          var keys = vim.inputState.keyBuffer = vim.inputState.keyBuffer + key;
+          if (/^[1-9]\d*$/.test(keys)) { return true; }
+
+          var keysMatcher = /^(\d*)(.*)$/.exec(keys);
+          if (!keysMatcher) { clearInputState(cm); return false; }
+          var context = vim.visualMode ? 'visual' :
+                                         'normal';
+          var match = commandDispatcher.matchCommand(keysMatcher[2] || keysMatcher[1], defaultKeymap, vim.inputState, context);
+          if (match.type == 'none') { clearInputState(cm); return false; }
+          else if (match.type == 'partial') { return true; }
+
+          vim.inputState.keyBuffer = '';
+          var keysMatcher = /^(\d*)(.*)$/.exec(keys);
+          if (keysMatcher[1] && keysMatcher[1] != '0') {
+            vim.inputState.pushRepeatDigit(keysMatcher[1]);
+          }
+          return match.command;
+        }
+
+        var command;
+        if (vim.insertMode) { command = handleKeyInsertMode(); }
+        else { command = handleKeyNonInsertMode(); }
+        if (command === false) {
+          return undefined;
+        } else if (command === true) {
+          return function() { return true; };
+        } else {
+          return function() {
+            if ((command.operator || command.isEdit) && cm.getOption('readOnly'))
+              return; // ace_patch
+            return cm.operation(function() {
+              cm.curOp.isVimOp = true;
+              try {
+                if (command.type == 'keyToKey') {
+                  doKeyToKey(command.toKeys);
+                } else {
+                  commandDispatcher.processCommand(cm, vim, command);
+                }
+              } catch (e) {
+                cm.state.vim = undefined;
+                maybeInitVimState(cm);
+                if (!CodeMirror.Vim.suppressErrorLogging) {
+                  console['log'](e);
+                }
+                throw e;
+              }
+              return true;
+            });
+          };
+        }
+      },
+      handleEx: function(cm, input) {
+        exCommandDispatcher.processCommand(cm, input);
+      },
+
+      defineMotion: defineMotion,
+      defineAction: defineAction,
+      defineOperator: defineOperator,
+      mapCommand: mapCommand,
+      _mapCommand: _mapCommand,
+
+      defineRegister: defineRegister,
+
+      exitVisualMode: exitVisualMode,
+      exitInsertMode: exitInsertMode
+    };
+    function InputState() {
+      this.prefixRepeat = [];
+      this.motionRepeat = [];
+
+      this.operator = null;
+      this.operatorArgs = null;
+      this.motion = null;
+      this.motionArgs = null;
+      this.keyBuffer = []; // For matching multi-key commands.
+      this.registerName = null; // Defaults to the unnamed register.
+    }
+    InputState.prototype.pushRepeatDigit = function(n) {
+      if (!this.operator) {
+        this.prefixRepeat = this.prefixRepeat.concat(n);
+      } else {
+        this.motionRepeat = this.motionRepeat.concat(n);
+      }
+    };
+    InputState.prototype.getRepeat = function() {
+      var repeat = 0;
+      if (this.prefixRepeat.length > 0 || this.motionRepeat.length > 0) {
+        repeat = 1;
+        if (this.prefixRepeat.length > 0) {
+          repeat *= parseInt(this.prefixRepeat.join(''), 10);
+        }
+        if (this.motionRepeat.length > 0) {
+          repeat *= parseInt(this.motionRepeat.join(''), 10);
+        }
+      }
+      return repeat;
+    };
+
+    function clearInputState(cm, reason) {
+      cm.state.vim.inputState = new InputState();
+      CodeMirror.signal(cm, 'vim-command-done', reason);
+    }
+    function Register(text, linewise, blockwise) {
+      this.clear();
+      this.keyBuffer = [text || ''];
+      this.insertModeChanges = [];
+      this.searchQueries = [];
+      this.linewise = !!linewise;
+      this.blockwise = !!blockwise;
+    }
+    Register.prototype = {
+      setText: function(text, linewise, blockwise) {
+        this.keyBuffer = [text || ''];
+        this.linewise = !!linewise;
+        this.blockwise = !!blockwise;
+      },
+      pushText: function(text, linewise) {
+        if (linewise) {
+          if (!this.linewise) {
+            this.keyBuffer.push('\n');
+          }
+          this.linewise = true;
+        }
+        this.keyBuffer.push(text);
+      },
+      pushInsertModeChanges: function(changes) {
+        this.insertModeChanges.push(createInsertModeChanges(changes));
+      },
+      pushSearchQuery: function(query) {
+        this.searchQueries.push(query);
+      },
+      clear: function() {
+        this.keyBuffer = [];
+        this.insertModeChanges = [];
+        this.searchQueries = [];
+        this.linewise = false;
+      },
+      toString: function() {
+        return this.keyBuffer.join('');
+      }
+    };
+    function defineRegister(name, register) {
+      var registers = vimGlobalState.registerController.registers;
+      if (!name || name.length != 1) {
+        throw Error('Register name must be 1 character');
+      }
+      registers[name] = register;
+      validRegisters.push(name);
+    }
+    function RegisterController(registers) {
+      this.registers = registers;
+      this.unnamedRegister = registers['"'] = new Register();
+      registers['.'] = new Register();
+      registers[':'] = new Register();
+      registers['/'] = new Register();
+    }
+    RegisterController.prototype = {
+      pushText: function(registerName, operator, text, linewise, blockwise) {
+        if (linewise && text.charAt(text.length - 1) !== '\n'){
+          text += '\n';
+        }
+        var register = this.isValidRegister(registerName) ?
+            this.getRegister(registerName) : null;
+        if (!register) {
+          switch (operator) {
+            case 'yank':
+              this.registers['0'] = new Register(text, linewise, blockwise);
+              break;
+            case 'delete':
+            case 'change':
+              if (text.indexOf('\n') == -1) {
+                this.registers['-'] = new Register(text, linewise);
+              } else {
+                this.shiftNumericRegisters_();
+                this.registers['1'] = new Register(text, linewise);
+              }
+              break;
+          }
+          this.unnamedRegister.setText(text, linewise, blockwise);
+          return;
+        }
+        var append = isUpperCase(registerName);
+        if (append) {
+          register.pushText(text, linewise);
+        } else {
+          register.setText(text, linewise, blockwise);
+        }
+        this.unnamedRegister.setText(register.toString(), linewise);
+      },
+      getRegister: function(name) {
+        if (!this.isValidRegister(name)) {
+          return this.unnamedRegister;
+        }
+        name = name.toLowerCase();
+        if (!this.registers[name]) {
+          this.registers[name] = new Register();
+        }
+        return this.registers[name];
+      },
+      isValidRegister: function(name) {
+        return name && inArray(name, validRegisters);
+      },
+      shiftNumericRegisters_: function() {
+        for (var i = 9; i >= 2; i--) {
+          this.registers[i] = this.getRegister('' + (i - 1));
+        }
+      }
+    };
+    function HistoryController() {
+        this.historyBuffer = [];
+        this.iterator = 0;
+        this.initialPrefix = null;
+    }
+    HistoryController.prototype = {
+      nextMatch: function (input, up) {
+        var historyBuffer = this.historyBuffer;
+        var dir = up ? -1 : 1;
+        if (this.initialPrefix === null) this.initialPrefix = input;
+        for (var i = this.iterator + dir; up ? i >= 0 : i < historyBuffer.length; i+= dir) {
+          var element = historyBuffer[i];
+          for (var j = 0; j <= element.length; j++) {
+            if (this.initialPrefix == element.substring(0, j)) {
+              this.iterator = i;
+              return element;
+            }
+          }
+        }
+        if (i >= historyBuffer.length) {
+          this.iterator = historyBuffer.length;
+          return this.initialPrefix;
+        }
+        if (i < 0 ) return input;
+      },
+      pushInput: function(input) {
+        var index = this.historyBuffer.indexOf(input);
+        if (index > -1) this.historyBuffer.splice(index, 1);
+        if (input.length) this.historyBuffer.push(input);
+      },
+      reset: function() {
+        this.initialPrefix = null;
+        this.iterator = this.historyBuffer.length;
+      }
+    };
+    var commandDispatcher = {
+      matchCommand: function(keys, keyMap, inputState, context) {
+        var matches = commandMatches(keys, keyMap, context, inputState);
+        if (!matches.full && !matches.partial) {
+          return {type: 'none'};
+        } else if (!matches.full && matches.partial) {
+          return {type: 'partial'};
+        }
+
+        var bestMatch;
+        for (var i = 0; i < matches.full.length; i++) {
+          var match = matches.full[i];
+          if (!bestMatch) {
+            bestMatch = match;
+          }
+        }
+        if (bestMatch.keys.slice(-11) == '<character>') {
+          var character = lastChar(keys);
+          if (/<C-.>/.test(character)) return {type: 'none'};
+          inputState.selectedCharacter = character;
+        }
+        return {type: 'full', command: bestMatch};
+      },
+      processCommand: function(cm, vim, command) {
+        vim.inputState.repeatOverride = command.repeatOverride;
+        switch (command.type) {
+          case 'motion':
+            this.processMotion(cm, vim, command);
+            break;
+          case 'operator':
+            this.processOperator(cm, vim, command);
+            break;
+          case 'operatorMotion':
+            this.processOperatorMotion(cm, vim, command);
+            break;
+          case 'action':
+            this.processAction(cm, vim, command);
+            break;
+          case 'search':
+            this.processSearch(cm, vim, command);
+            break;
+          case 'ex':
+          case 'keyToEx':
+            this.processEx(cm, vim, command);
+            break;
+          default:
+            break;
+        }
+      },
+      processMotion: function(cm, vim, command) {
+        vim.inputState.motion = command.motion;
+        vim.inputState.motionArgs = copyArgs(command.motionArgs);
+        this.evalInput(cm, vim);
+      },
+      processOperator: function(cm, vim, command) {
+        var inputState = vim.inputState;
+        if (inputState.operator) {
+          if (inputState.operator == command.operator) {
+            inputState.motion = 'expandToLine';
+            inputState.motionArgs = { linewise: true };
+            this.evalInput(cm, vim);
+            return;
+          } else {
+            clearInputState(cm);
+          }
+        }
+        inputState.operator = command.operator;
+        inputState.operatorArgs = copyArgs(command.operatorArgs);
+        if (vim.visualMode) {
+          this.evalInput(cm, vim);
+        }
+      },
+      processOperatorMotion: function(cm, vim, command) {
+        var visualMode = vim.visualMode;
+        var operatorMotionArgs = copyArgs(command.operatorMotionArgs);
+        if (operatorMotionArgs) {
+          if (visualMode && operatorMotionArgs.visualLine) {
+            vim.visualLine = true;
+          }
+        }
+        this.processOperator(cm, vim, command);
+        if (!visualMode) {
+          this.processMotion(cm, vim, command);
+        }
+      },
+      processAction: function(cm, vim, command) {
+        var inputState = vim.inputState;
+        var repeat = inputState.getRepeat();
+        var repeatIsExplicit = !!repeat;
+        var actionArgs = copyArgs(command.actionArgs) || {};
+        if (inputState.selectedCharacter) {
+          actionArgs.selectedCharacter = inputState.selectedCharacter;
+        }
+        if (command.operator) {
+          this.processOperator(cm, vim, command);
+        }
+        if (command.motion) {
+          this.processMotion(cm, vim, command);
+        }
+        if (command.motion || command.operator) {
+          this.evalInput(cm, vim);
+        }
+        actionArgs.repeat = repeat || 1;
+        actionArgs.repeatIsExplicit = repeatIsExplicit;
+        actionArgs.registerName = inputState.registerName;
+        clearInputState(cm);
+        vim.lastMotion = null;
+        if (command.isEdit) {
+          this.recordLastEdit(vim, inputState, command);
+        }
+        actions[command.action](cm, actionArgs, vim);
+      },
+      processSearch: function(cm, vim, command) {
+        if (!cm.getSearchCursor) {
+          return;
+        }
+        var forward = command.searchArgs.forward;
+        var wholeWordOnly = command.searchArgs.wholeWordOnly;
+        getSearchState(cm).setReversed(!forward);
+        var promptPrefix = (forward) ? '/' : '?';
+        var originalQuery = getSearchState(cm).getQuery();
+        var originalScrollPos = cm.getScrollInfo();
+        function handleQuery(query, ignoreCase, smartCase) {
+          vimGlobalState.searchHistoryController.pushInput(query);
+          vimGlobalState.searchHistoryController.reset();
+          try {
+            updateSearchQuery(cm, query, ignoreCase, smartCase);
+          } catch (e) {
+            showConfirm(cm, 'Invalid regex: ' + query);
+            clearInputState(cm);
+            return;
+          }
+          commandDispatcher.processMotion(cm, vim, {
+            type: 'motion',
+            motion: 'findNext',
+            motionArgs: { forward: true, toJumplist: command.searchArgs.toJumplist }
+          });
+        }
+        function onPromptClose(query) {
+          handleQuery(query, true /** ignoreCase */, true /** smartCase */);
+          var macroModeState = vimGlobalState.macroModeState;
+          if (macroModeState.isRecording) {
+            logSearchQuery(macroModeState, query);
+          }
+        }
+        function onPromptKeyUp(e, query, close) {
+          var keyName = CodeMirror.keyName(e), up, offset;
+          if (keyName == 'Up' || keyName == 'Down') {
+            up = keyName == 'Up' ? true : false;
+            offset = e.target ? e.target.selectionEnd : 0;
+            query = vimGlobalState.searchHistoryController.nextMatch(query, up) || '';
+            close(query);
+            if (offset && e.target) e.target.selectionEnd = e.target.selectionStart = Math.min(offset, e.target.value.length);
+          } else {
+            if ( keyName != 'Left' && keyName != 'Right' && keyName != 'Ctrl' && keyName != 'Alt' && keyName != 'Shift')
+              vimGlobalState.searchHistoryController.reset();
+          }
+          var parsedQuery;
+          try {
+            parsedQuery = updateSearchQuery(cm, query,
+                true /** ignoreCase */, true /** smartCase */);
+          } catch (e) {
+          }
+          if (parsedQuery) {
+            cm.scrollIntoView(findNext(cm, !forward, parsedQuery), 30);
+          } else {
+            clearSearchHighlight(cm);
+            cm.scrollTo(originalScrollPos.left, originalScrollPos.top);
+          }
+        }
+        function onPromptKeyDown(e, query, close) {
+          var keyName = CodeMirror.keyName(e);
+          if (keyName == 'Esc' || keyName == 'Ctrl-C' || keyName == 'Ctrl-[' ||
+              (keyName == 'Backspace' && query == '')) {
+            vimGlobalState.searchHistoryController.pushInput(query);
+            vimGlobalState.searchHistoryController.reset();
+            updateSearchQuery(cm, originalQuery);
+            clearSearchHighlight(cm);
+            cm.scrollTo(originalScrollPos.left, originalScrollPos.top);
+            CodeMirror.e_stop(e);
+            clearInputState(cm);
+            close();
+            cm.focus();
+          } else if (keyName == 'Up' || keyName == 'Down') {
+            CodeMirror.e_stop(e);
+          } else if (keyName == 'Ctrl-U') {
+            CodeMirror.e_stop(e);
+            close('');
+          }
+        }
+        switch (command.searchArgs.querySrc) {
+          case 'prompt':
+            var macroModeState = vimGlobalState.macroModeState;
+            if (macroModeState.isPlaying) {
+              var query = macroModeState.replaySearchQueries.shift();
+              handleQuery(query, true /** ignoreCase */, false /** smartCase */);
+            } else {
+              showPrompt(cm, {
+                  onClose: onPromptClose,
+                  prefix: promptPrefix,
+                  desc: searchPromptDesc,
+                  onKeyUp: onPromptKeyUp,
+                  onKeyDown: onPromptKeyDown
+              });
+            }
+            break;
+          case 'wordUnderCursor':
+            var word = expandWordUnderCursor(cm, false /** inclusive */,
+                true /** forward */, false /** bigWord */,
+                true /** noSymbol */);
+            var isKeyword = true;
+            if (!word) {
+              word = expandWordUnderCursor(cm, false /** inclusive */,
+                  true /** forward */, false /** bigWord */,
+                  false /** noSymbol */);
+              isKeyword = false;
+            }
+            if (!word) {
+              return;
+            }
+            var query = cm.getLine(word.start.line).substring(word.start.ch,
+                word.end.ch);
+            if (isKeyword && wholeWordOnly) {
+                query = '\\b' + query + '\\b';
+            } else {
+              query = escapeRegex(query);
+            }
+            vimGlobalState.jumpList.cachedCursor = cm.getCursor();
+            cm.setCursor(word.start);
+
+            handleQuery(query, true /** ignoreCase */, false /** smartCase */);
+            break;
+        }
+      },
+      processEx: function(cm, vim, command) {
+        function onPromptClose(input) {
+          vimGlobalState.exCommandHistoryController.pushInput(input);
+          vimGlobalState.exCommandHistoryController.reset();
+          exCommandDispatcher.processCommand(cm, input);
+        }
+        function onPromptKeyDown(e, input, close) {
+          var keyName = CodeMirror.keyName(e), up, offset;
+          if (keyName == 'Esc' || keyName == 'Ctrl-C' || keyName == 'Ctrl-[' ||
+              (keyName == 'Backspace' && input == '')) {
+            vimGlobalState.exCommandHistoryController.pushInput(input);
+            vimGlobalState.exCommandHistoryController.reset();
+            CodeMirror.e_stop(e);
+            clearInputState(cm);
+            close();
+            cm.focus();
+          }
+          if (keyName == 'Up' || keyName == 'Down') {
+            CodeMirror.e_stop(e);
+            up = keyName == 'Up' ? true : false;
+            offset = e.target ? e.target.selectionEnd : 0;
+            input = vimGlobalState.exCommandHistoryController.nextMatch(input, up) || '';
+            close(input);
+            if (offset && e.target) e.target.selectionEnd = e.target.selectionStart = Math.min(offset, e.target.value.length);
+          } else if (keyName == 'Ctrl-U') {
+            CodeMirror.e_stop(e);
+            close('');
+          } else {
+            if ( keyName != 'Left' && keyName != 'Right' && keyName != 'Ctrl' && keyName != 'Alt' && keyName != 'Shift')
+              vimGlobalState.exCommandHistoryController.reset();
+          }
+        }
+        if (command.type == 'keyToEx') {
+          exCommandDispatcher.processCommand(cm, command.exArgs.input);
+        } else {
+          if (vim.visualMode) {
+            showPrompt(cm, { onClose: onPromptClose, prefix: ':', value: '\'<,\'>',
+                onKeyDown: onPromptKeyDown, selectValueOnOpen: false});
+          } else {
+            showPrompt(cm, { onClose: onPromptClose, prefix: ':',
+                onKeyDown: onPromptKeyDown});
+          }
+        }
+      },
+      evalInput: function(cm, vim) {
+        var inputState = vim.inputState;
+        var motion = inputState.motion;
+        var motionArgs = inputState.motionArgs || {};
+        var operator = inputState.operator;
+        var operatorArgs = inputState.operatorArgs || {};
+        var registerName = inputState.registerName;
+        var sel = vim.sel;
+        var origHead = copyCursor(vim.visualMode ? clipCursorToContent(cm, sel.head): cm.getCursor('head'));
+        var origAnchor = copyCursor(vim.visualMode ? clipCursorToContent(cm, sel.anchor) : cm.getCursor('anchor'));
+        var oldHead = copyCursor(origHead);
+        var oldAnchor = copyCursor(origAnchor);
+        var newHead, newAnchor;
+        var repeat;
+        if (operator) {
+          this.recordLastEdit(vim, inputState);
+        }
+        if (inputState.repeatOverride !== undefined) {
+          repeat = inputState.repeatOverride;
+        } else {
+          repeat = inputState.getRepeat();
+        }
+        if (repeat > 0 && motionArgs.explicitRepeat) {
+          motionArgs.repeatIsExplicit = true;
+        } else if (motionArgs.noRepeat ||
+            (!motionArgs.explicitRepeat && repeat === 0)) {
+          repeat = 1;
+          motionArgs.repeatIsExplicit = false;
+        }
+        if (inputState.selectedCharacter) {
+          motionArgs.selectedCharacter = operatorArgs.selectedCharacter =
+              inputState.selectedCharacter;
+        }
+        motionArgs.repeat = repeat;
+        clearInputState(cm);
+        if (motion) {
+          var motionResult = motions[motion](cm, origHead, motionArgs, vim);
+          vim.lastMotion = motions[motion];
+          if (!motionResult) {
+            return;
+          }
+          if (motionArgs.toJumplist) {
+            if (!operator && cm.ace.curOp != null)
+              cm.ace.curOp.command.scrollIntoView = "center-animate"; // ace_patch
+            var jumpList = vimGlobalState.jumpList;
+            var cachedCursor = jumpList.cachedCursor;
+            if (cachedCursor) {
+              recordJumpPosition(cm, cachedCursor, motionResult);
+              delete jumpList.cachedCursor;
+            } else {
+              recordJumpPosition(cm, origHead, motionResult);
+            }
+          }
+          if (motionResult instanceof Array) {
+            newAnchor = motionResult[0];
+            newHead = motionResult[1];
+          } else {
+            newHead = motionResult;
+          }
+          if (!newHead) {
+            newHead = copyCursor(origHead);
+          }
+          if (vim.visualMode) {
+            if (!(vim.visualBlock && newHead.ch === Infinity)) {
+              newHead = clipCursorToContent(cm, newHead, vim.visualBlock);
+            }
+            if (newAnchor) {
+              newAnchor = clipCursorToContent(cm, newAnchor, true);
+            }
+            newAnchor = newAnchor || oldAnchor;
+            sel.anchor = newAnchor;
+            sel.head = newHead;
+            updateCmSelection(cm);
+            updateMark(cm, vim, '<',
+                cursorIsBefore(newAnchor, newHead) ? newAnchor
+                    : newHead);
+            updateMark(cm, vim, '>',
+                cursorIsBefore(newAnchor, newHead) ? newHead
+                    : newAnchor);
+          } else if (!operator) {
+            newHead = clipCursorToContent(cm, newHead);
+            cm.setCursor(newHead.line, newHead.ch);
+          }
+        }
+        if (operator) {
+          if (operatorArgs.lastSel) {
+            newAnchor = oldAnchor;
+            var lastSel = operatorArgs.lastSel;
+            var lineOffset = Math.abs(lastSel.head.line - lastSel.anchor.line);
+            var chOffset = Math.abs(lastSel.head.ch - lastSel.anchor.ch);
+            if (lastSel.visualLine) {
+              newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch);
+            } else if (lastSel.visualBlock) {
+              newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch + chOffset);
+            } else if (lastSel.head.line == lastSel.anchor.line) {
+              newHead = Pos(oldAnchor.line, oldAnchor.ch + chOffset);
+            } else {
+              newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch);
+            }
+            vim.visualMode = true;
+            vim.visualLine = lastSel.visualLine;
+            vim.visualBlock = lastSel.visualBlock;
+            sel = vim.sel = {
+              anchor: newAnchor,
+              head: newHead
+            };
+            updateCmSelection(cm);
+          } else if (vim.visualMode) {
+            operatorArgs.lastSel = {
+              anchor: copyCursor(sel.anchor),
+              head: copyCursor(sel.head),
+              visualBlock: vim.visualBlock,
+              visualLine: vim.visualLine
+            };
+          }
+          var curStart, curEnd, linewise, mode;
+          var cmSel;
+          if (vim.visualMode) {
+            curStart = cursorMin(sel.head, sel.anchor);
+            curEnd = cursorMax(sel.head, sel.anchor);
+            linewise = vim.visualLine || operatorArgs.linewise;
+            mode = vim.visualBlock ? 'block' :
+                   linewise ? 'line' :
+                   'char';
+            cmSel = makeCmSelection(cm, {
+              anchor: curStart,
+              head: curEnd
+            }, mode);
+            if (linewise) {
+              var ranges = cmSel.ranges;
+              if (mode == 'block') {
+                for (var i = 0; i < ranges.length; i++) {
+                  ranges[i].head.ch = lineLength(cm, ranges[i].head.line);
+                }
+              } else if (mode == 'line') {
+                ranges[0].head = Pos(ranges[0].head.line + 1, 0);
+              }
+            }
+          } else {
+            curStart = copyCursor(newAnchor || oldAnchor);
+            curEnd = copyCursor(newHead || oldHead);
+            if (cursorIsBefore(curEnd, curStart)) {
+              var tmp = curStart;
+              curStart = curEnd;
+              curEnd = tmp;
+            }
+            linewise = motionArgs.linewise || operatorArgs.linewise;
+            if (linewise) {
+              expandSelectionToLine(cm, curStart, curEnd);
+            } else if (motionArgs.forward) {
+              clipToLine(cm, curStart, curEnd);
+            }
+            mode = 'char';
+            var exclusive = !motionArgs.inclusive || linewise;
+            cmSel = makeCmSelection(cm, {
+              anchor: curStart,
+              head: curEnd
+            }, mode, exclusive);
+          }
+          cm.setSelections(cmSel.ranges, cmSel.primary);
+          vim.lastMotion = null;
+          operatorArgs.repeat = repeat; // For indent in visual mode.
+          operatorArgs.registerName = registerName;
+          operatorArgs.linewise = linewise;
+          var operatorMoveTo = operators[operator](
+            cm, operatorArgs, cmSel.ranges, oldAnchor, newHead);
+          if (vim.visualMode) {
+            exitVisualMode(cm, operatorMoveTo != null);
+          }
+          if (operatorMoveTo) {
+            cm.setCursor(operatorMoveTo);
+          }
+        }
+      },
+      recordLastEdit: function(vim, inputState, actionCommand) {
+        var macroModeState = vimGlobalState.macroModeState;
+        if (macroModeState.isPlaying) { return; }
+        vim.lastEditInputState = inputState;
+        vim.lastEditActionCommand = actionCommand;
+        macroModeState.lastInsertModeChanges.changes = [];
+        macroModeState.lastInsertModeChanges.expectCursorActivityForChange = false;
+      }
+    };
+    var motions = {
+      moveToTopLine: function(cm, _head, motionArgs) {
+        var line = getUserVisibleLines(cm).top + motionArgs.repeat -1;
+        return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line)));
+      },
+      moveToMiddleLine: function(cm) {
+        var range = getUserVisibleLines(cm);
+        var line = Math.floor((range.top + range.bottom) * 0.5);
+        return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line)));
+      },
+      moveToBottomLine: function(cm, _head, motionArgs) {
+        var line = getUserVisibleLines(cm).bottom - motionArgs.repeat +1;
+        return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line)));
+      },
+      expandToLine: function(_cm, head, motionArgs) {
+        var cur = head;
+        return Pos(cur.line + motionArgs.repeat - 1, Infinity);
+      },
+      findNext: function(cm, _head, motionArgs) {
+        var state = getSearchState(cm);
+        var query = state.getQuery();
+        if (!query) {
+          return;
+        }
+        var prev = !motionArgs.forward;
+        prev = (state.isReversed()) ? !prev : prev;
+        highlightSearchMatches(cm, query);
+        return findNext(cm, prev/** prev */, query, motionArgs.repeat);
+      },
+      goToMark: function(cm, _head, motionArgs, vim) {
+        var pos = getMarkPos(cm, vim, motionArgs.selectedCharacter);
+        if (pos) {
+          return motionArgs.linewise ? { line: pos.line, ch: findFirstNonWhiteSpaceCharacter(cm.getLine(pos.line)) } : pos;
+        }
+        return null;
+      },
+      moveToOtherHighlightedEnd: function(cm, _head, motionArgs, vim) {
+        if (vim.visualBlock && motionArgs.sameLine) {
+          var sel = vim.sel;
+          return [
+            clipCursorToContent(cm, Pos(sel.anchor.line, sel.head.ch)),
+            clipCursorToContent(cm, Pos(sel.head.line, sel.anchor.ch))
+          ];
+        } else {
+          return ([vim.sel.head, vim.sel.anchor]);
+        }
+      },
+      jumpToMark: function(cm, head, motionArgs, vim) {
+        var best = head;
+        for (var i = 0; i < motionArgs.repeat; i++) {
+          var cursor = best;
+          for (var key in vim.marks) {
+            if (!isLowerCase(key)) {
+              continue;
+            }
+            var mark = vim.marks[key].find();
+            var isWrongDirection = (motionArgs.forward) ?
+              cursorIsBefore(mark, cursor) : cursorIsBefore(cursor, mark);
+
+            if (isWrongDirection) {
+              continue;
+            }
+            if (motionArgs.linewise && (mark.line == cursor.line)) {
+              continue;
+            }
+
+            var equal = cursorEqual(cursor, best);
+            var between = (motionArgs.forward) ?
+              cursorIsBetween(cursor, mark, best) :
+              cursorIsBetween(best, mark, cursor);
+
+            if (equal || between) {
+              best = mark;
+            }
+          }
+        }
+
+        if (motionArgs.linewise) {
+          best = Pos(best.line, findFirstNonWhiteSpaceCharacter(cm.getLine(best.line)));
+        }
+        return best;
+      },
+      moveByCharacters: function(_cm, head, motionArgs) {
+        var cur = head;
+        var repeat = motionArgs.repeat;
+        var ch = motionArgs.forward ? cur.ch + repeat : cur.ch - repeat;
+        return Pos(cur.line, ch);
+      },
+      moveByLines: function(cm, head, motionArgs, vim) {
+        var cur = head;
+        var endCh = cur.ch;
+        switch (vim.lastMotion) {
+          case this.moveByLines:
+          case this.moveByDisplayLines:
+          case this.moveByScroll:
+          case this.moveToColumn:
+          case this.moveToEol:
+            endCh = vim.lastHPos;
+            break;
+          default:
+            vim.lastHPos = endCh;
+        }
+        var repeat = motionArgs.repeat+(motionArgs.repeatOffset||0);
+        var line = motionArgs.forward ? cur.line + repeat : cur.line - repeat;
+        var first = cm.firstLine();
+        var last = cm.lastLine();
+        if (line < first && cur.line == first){
+          return this.moveToStartOfLine(cm, head, motionArgs, vim);
+        }else if (line > last && cur.line == last){
+            return this.moveToEol(cm, head, motionArgs, vim);
+        }
+        var fold = cm.ace.session.getFoldLine(line);
+        if (fold) {
+          if (motionArgs.forward) {
+            if (line > fold.start.row)
+              line = fold.end.row + 1;
+          } else {
+            line = fold.start.row;
+          }
+        }
+        if (motionArgs.toFirstChar){
+          endCh=findFirstNonWhiteSpaceCharacter(cm.getLine(line));
+          vim.lastHPos = endCh;
+        }
+        vim.lastHSPos = cm.charCoords(Pos(line, endCh),'div').left;
+        return Pos(line, endCh);
+      },
+      moveByDisplayLines: function(cm, head, motionArgs, vim) {
+        var cur = head;
+        switch (vim.lastMotion) {
+          case this.moveByDisplayLines:
+          case this.moveByScroll:
+          case this.moveByLines:
+          case this.moveToColumn:
+          case this.moveToEol:
+            break;
+          default:
+            vim.lastHSPos = cm.charCoords(cur,'div').left;
+        }
+        var repeat = motionArgs.repeat;
+        var res=cm.findPosV(cur,(motionArgs.forward ? repeat : -repeat),'line',vim.lastHSPos);
+        if (res.hitSide) {
+          if (motionArgs.forward) {
+            var lastCharCoords = cm.charCoords(res, 'div');
+            var goalCoords = { top: lastCharCoords.top + 8, left: vim.lastHSPos };
+            var res = cm.coordsChar(goalCoords, 'div');
+          } else {
+            var resCoords = cm.charCoords(Pos(cm.firstLine(), 0), 'div');
+            resCoords.left = vim.lastHSPos;
+            res = cm.coordsChar(resCoords, 'div');
+          }
+        }
+        vim.lastHPos = res.ch;
+        return res;
+      },
+      moveByPage: function(cm, head, motionArgs) {
+        var curStart = head;
+        var repeat = motionArgs.repeat;
+        return cm.findPosV(curStart, (motionArgs.forward ? repeat : -repeat), 'page');
+      },
+      moveByParagraph: function(cm, head, motionArgs) {
+        var dir = motionArgs.forward ? 1 : -1;
+        return findParagraph(cm, head, motionArgs.repeat, dir);
+      },
+      moveByScroll: function(cm, head, motionArgs, vim) {
+        var scrollbox = cm.getScrollInfo();
+        var curEnd = null;
+        var repeat = motionArgs.repeat;
+        if (!repeat) {
+          repeat = scrollbox.clientHeight / (2 * cm.defaultTextHeight());
+        }
+        var orig = cm.charCoords(head, 'local');
+        motionArgs.repeat = repeat;
+        var curEnd = motions.moveByDisplayLines(cm, head, motionArgs, vim);
+        if (!curEnd) {
+          return null;
+        }
+        var dest = cm.charCoords(curEnd, 'local');
+        cm.scrollTo(null, scrollbox.top + dest.top - orig.top);
+        return curEnd;
+      },
+      moveByWords: function(cm, head, motionArgs) {
+        return moveToWord(cm, head, motionArgs.repeat, !!motionArgs.forward,
+            !!motionArgs.wordEnd, !!motionArgs.bigWord);
+      },
+      moveTillCharacter: function(cm, _head, motionArgs) {
+        var repeat = motionArgs.repeat;
+        var curEnd = moveToCharacter(cm, repeat, motionArgs.forward,
+            motionArgs.selectedCharacter);
+        var increment = motionArgs.forward ? -1 : 1;
+        recordLastCharacterSearch(increment, motionArgs);
+        if (!curEnd) return null;
+        curEnd.ch += increment;
+        return curEnd;
+      },
+      moveToCharacter: function(cm, head, motionArgs) {
+        var repeat = motionArgs.repeat;
+        recordLastCharacterSearch(0, motionArgs);
+        return moveToCharacter(cm, repeat, motionArgs.forward,
+            motionArgs.selectedCharacter) || head;
+      },
+      moveToSymbol: function(cm, head, motionArgs) {
+        var repeat = motionArgs.repeat;
+        return findSymbol(cm, repeat, motionArgs.forward,
+            motionArgs.selectedCharacter) || head;
+      },
+      moveToColumn: function(cm, head, motionArgs, vim) {
+        var repeat = motionArgs.repeat;
+        vim.lastHPos = repeat - 1;
+        vim.lastHSPos = cm.charCoords(head,'div').left;
+        return moveToColumn(cm, repeat);
+      },
+      moveToEol: function(cm, head, motionArgs, vim) {
+        var cur = head;
+        vim.lastHPos = Infinity;
+        var retval= Pos(cur.line + motionArgs.repeat - 1, Infinity);
+        var end=cm.clipPos(retval);
+        end.ch--;
+        vim.lastHSPos = cm.charCoords(end,'div').left;
+        return retval;
+      },
+      moveToFirstNonWhiteSpaceCharacter: function(cm, head) {
+        var cursor = head;
+        return Pos(cursor.line,
+                   findFirstNonWhiteSpaceCharacter(cm.getLine(cursor.line)));
+      },
+      moveToMatchedSymbol: function(cm, head) {
+        var cursor = head;
+        var line = cursor.line;
+        var ch = cursor.ch;
+        var lineText = cm.getLine(line);
+        var symbol;
+        do {
+          symbol = lineText.charAt(ch++);
+          if (symbol && isMatchableSymbol(symbol)) {
+            var style = cm.getTokenTypeAt(Pos(line, ch));
+            if (style !== "string" && style !== "comment") {
+              break;
+            }
+          }
+        } while (symbol);
+        if (symbol) {
+          var matched = cm.findMatchingBracket(Pos(line, ch));
+          return matched.to;
+        } else {
+          return cursor;
+        }
+      },
+      moveToStartOfLine: function(_cm, head) {
+        return Pos(head.line, 0);
+      },
+      moveToLineOrEdgeOfDocument: function(cm, _head, motionArgs) {
+        var lineNum = motionArgs.forward ? cm.lastLine() : cm.firstLine();
+        if (motionArgs.repeatIsExplicit) {
+          lineNum = motionArgs.repeat - cm.getOption('firstLineNumber');
+        }
+        return Pos(lineNum,
+                   findFirstNonWhiteSpaceCharacter(cm.getLine(lineNum)));
+      },
+      textObjectManipulation: function(cm, head, motionArgs, vim) {
+        var mirroredPairs = {'(': ')', ')': '(',
+                             '{': '}', '}': '{',
+                             '[': ']', ']': '[',
+                             '<': '>', '>': '<'};
+        var selfPaired = {'\'': true, '"': true, '`': true};
+
+        var character = motionArgs.selectedCharacter;
+        if (character == 'b') {
+          character = '(';
+        } else if (character == 'B') {
+          character = '{';
+        }
+        var inclusive = !motionArgs.textObjectInner;
+
+        var tmp;
+        if (mirroredPairs[character]) {
+          tmp = selectCompanionObject(cm, head, character, inclusive);
+        } else if (selfPaired[character]) {
+          tmp = findBeginningAndEnd(cm, head, character, inclusive);
+        } else if (character === 'W') {
+          tmp = expandWordUnderCursor(cm, inclusive, true /** forward */,
+                                                     true /** bigWord */);
+        } else if (character === 'w') {
+          tmp = expandWordUnderCursor(cm, inclusive, true /** forward */,
+                                                     false /** bigWord */);
+        } else if (character === 'p') {
+          tmp = findParagraph(cm, head, motionArgs.repeat, 0, inclusive);
+          motionArgs.linewise = true;
+          if (vim.visualMode) {
+            if (!vim.visualLine) { vim.visualLine = true; }
+          } else {
+            var operatorArgs = vim.inputState.operatorArgs;
+            if (operatorArgs) { operatorArgs.linewise = true; }
+            tmp.end.line--;
+          }
+        } else {
+          return null;
+        }
+
+        if (!cm.state.vim.visualMode) {
+          return [tmp.start, tmp.end];
+        } else {
+          return expandSelection(cm, tmp.start, tmp.end);
+        }
+      },
+
+      repeatLastCharacterSearch: function(cm, head, motionArgs) {
+        var lastSearch = vimGlobalState.lastCharacterSearch;
+        var repeat = motionArgs.repeat;
+        var forward = motionArgs.forward === lastSearch.forward;
+        var increment = (lastSearch.increment ? 1 : 0) * (forward ? -1 : 1);
+        cm.moveH(-increment, 'char');
+        motionArgs.inclusive = forward ? true : false;
+        var curEnd = moveToCharacter(cm, repeat, forward, lastSearch.selectedCharacter);
+        if (!curEnd) {
+          cm.moveH(increment, 'char');
+          return head;
+        }
+        curEnd.ch += increment;
+        return curEnd;
+      }
+    };
+
+    function defineMotion(name, fn) {
+      motions[name] = fn;
+    }
+
+    function fillArray(val, times) {
+      var arr = [];
+      for (var i = 0; i < times; i++) {
+        arr.push(val);
+      }
+      return arr;
+    }
+    var operators = {
+      change: function(cm, args, ranges) {
+        var finalHead, text;
+        var vim = cm.state.vim;
+        vimGlobalState.macroModeState.lastInsertModeChanges.inVisualBlock = vim.visualBlock;
+        if (!vim.visualMode) {
+          var anchor = ranges[0].anchor,
+              head = ranges[0].head;
+          text = cm.getRange(anchor, head);
+          var lastState = vim.lastEditInputState || {};
+          if (lastState.motion == "moveByWords" && !isWhiteSpaceString(text)) {
+            var match = (/\s+$/).exec(text);
+            if (match && lastState.motionArgs && lastState.motionArgs.forward) {
+              head = offsetCursor(head, 0, - match[0].length);
+              text = text.slice(0, - match[0].length);
+            }
+          }
+          var prevLineEnd = new Pos(anchor.line - 1, Number.MAX_VALUE);
+          var wasLastLine = cm.firstLine() == cm.lastLine();
+          if (head.line > cm.lastLine() && args.linewise && !wasLastLine) {
+            cm.replaceRange('', prevLineEnd, head);
+          } else {
+            cm.replaceRange('', anchor, head);
+          }
+          if (args.linewise) {
+            if (!wasLastLine) {
+              cm.setCursor(prevLineEnd);
+              CodeMirror.commands.newlineAndIndent(cm);
+            }
+            anchor.ch = Number.MAX_VALUE;
+          }
+          finalHead = anchor;
+        } else {
+          text = cm.getSelection();
+          var replacement = fillArray('', ranges.length);
+          cm.replaceSelections(replacement);
+          finalHead = cursorMin(ranges[0].head, ranges[0].anchor);
+        }
+        vimGlobalState.registerController.pushText(
+            args.registerName, 'change', text,
+            args.linewise, ranges.length > 1);
+        actions.enterInsertMode(cm, {head: finalHead}, cm.state.vim);
+      },
+      'delete': function(cm, args, ranges) {
+        var finalHead, text;
+        var vim = cm.state.vim;
+        if (!vim.visualBlock) {
+          var anchor = ranges[0].anchor,
+              head = ranges[0].head;
+          if (args.linewise &&
+              head.line != cm.firstLine() &&
+              anchor.line == cm.lastLine() &&
+              anchor.line == head.line - 1) {
+            if (anchor.line == cm.firstLine()) {
+              anchor.ch = 0;
+            } else {
+              anchor = Pos(anchor.line - 1, lineLength(cm, anchor.line - 1));
+            }
+          }
+          text = cm.getRange(anchor, head);
+          cm.replaceRange('', anchor, head);
+          finalHead = anchor;
+          if (args.linewise) {
+            finalHead = motions.moveToFirstNonWhiteSpaceCharacter(cm, anchor);
+          }
+        } else {
+          text = cm.getSelection();
+          var replacement = fillArray('', ranges.length);
+          cm.replaceSelections(replacement);
+          finalHead = ranges[0].anchor;
+        }
+        vimGlobalState.registerController.pushText(
+            args.registerName, 'delete', text,
+            args.linewise, vim.visualBlock);
+        var includeLineBreak = vim.insertMode
+        return clipCursorToContent(cm, finalHead, includeLineBreak);
+      },
+      indent: function(cm, args, ranges) {
+        var vim = cm.state.vim;
+        var startLine = ranges[0].anchor.line;
+        var endLine = vim.visualBlock ?
+          ranges[ranges.length - 1].anchor.line :
+          ranges[0].head.line;
+        var repeat = (vim.visualMode) ? args.repeat : 1;
+        if (args.linewise) {
+          endLine--;
+        }
+        for (var i = startLine; i <= endLine; i++) {
+          for (var j = 0; j < repeat; j++) {
+            cm.indentLine(i, args.indentRight);
+          }
+        }
+        return motions.moveToFirstNonWhiteSpaceCharacter(cm, ranges[0].anchor);
+      },
+      changeCase: function(cm, args, ranges, oldAnchor, newHead) {
+        var selections = cm.getSelections();
+        var swapped = [];
+        var toLower = args.toLower;
+        for (var j = 0; j < selections.length; j++) {
+          var toSwap = selections[j];
+          var text = '';
+          if (toLower === true) {
+            text = toSwap.toLowerCase();
+          } else if (toLower === false) {
+            text = toSwap.toUpperCase();
+          } else {
+            for (var i = 0; i < toSwap.length; i++) {
+              var character = toSwap.charAt(i);
+              text += isUpperCase(character) ? character.toLowerCase() :
+                  character.toUpperCase();
+            }
+          }
+          swapped.push(text);
+        }
+        cm.replaceSelections(swapped);
+        if (args.shouldMoveCursor){
+          return newHead;
+        } else if (!cm.state.vim.visualMode && args.linewise && ranges[0].anchor.line + 1 == ranges[0].head.line) {
+          return motions.moveToFirstNonWhiteSpaceCharacter(cm, oldAnchor);
+        } else if (args.linewise){
+          return oldAnchor;
+        } else {
+          return cursorMin(ranges[0].anchor, ranges[0].head);
+        }
+      },
+      yank: function(cm, args, ranges, oldAnchor) {
+        var vim = cm.state.vim;
+        var text = cm.getSelection();
+        var endPos = vim.visualMode
+          ? cursorMin(vim.sel.anchor, vim.sel.head, ranges[0].head, ranges[0].anchor)
+          : oldAnchor;
+        vimGlobalState.registerController.pushText(
+            args.registerName, 'yank',
+            text, args.linewise, vim.visualBlock);
+        return endPos;
+      }
+    };
+
+    function defineOperator(name, fn) {
+      operators[name] = fn;
+    }
+
+    var actions = {
+      jumpListWalk: function(cm, actionArgs, vim) {
+        if (vim.visualMode) {
+          return;
+        }
+        var repeat = actionArgs.repeat;
+        var forward = actionArgs.forward;
+        var jumpList = vimGlobalState.jumpList;
+
+        var mark = jumpList.move(cm, forward ? repeat : -repeat);
+        var markPos = mark ? mark.find() : undefined;
+        markPos = markPos ? markPos : cm.getCursor();
+        cm.setCursor(markPos);
+        cm.ace.curOp.command.scrollIntoView = "center-animate"; // ace_patch
+      },
+      scroll: function(cm, actionArgs, vim) {
+        if (vim.visualMode) {
+          return;
+        }
+        var repeat = actionArgs.repeat || 1;
+        var lineHeight = cm.defaultTextHeight();
+        var top = cm.getScrollInfo().top;
+        var delta = lineHeight * repeat;
+        var newPos = actionArgs.forward ? top + delta : top - delta;
+        var cursor = copyCursor(cm.getCursor());
+        var cursorCoords = cm.charCoords(cursor, 'local');
+        if (actionArgs.forward) {
+          if (newPos > cursorCoords.top) {
+             cursor.line += (newPos - cursorCoords.top) / lineHeight;
+             cursor.line = Math.ceil(cursor.line);
+             cm.setCursor(cursor);
+             cursorCoords = cm.charCoords(cursor, 'local');
+             cm.scrollTo(null, cursorCoords.top);
+          } else {
+             cm.scrollTo(null, newPos);
+          }
+        } else {
+          var newBottom = newPos + cm.getScrollInfo().clientHeight;
+          if (newBottom < cursorCoords.bottom) {
+             cursor.line -= (cursorCoords.bottom - newBottom) / lineHeight;
+             cursor.line = Math.floor(cursor.line);
+             cm.setCursor(cursor);
+             cursorCoords = cm.charCoords(cursor, 'local');
+             cm.scrollTo(
+                 null, cursorCoords.bottom - cm.getScrollInfo().clientHeight);
+          } else {
+             cm.scrollTo(null, newPos);
+          }
+        }
+      },
+      scrollToCursor: function(cm, actionArgs) {
+        var lineNum = cm.getCursor().line;
+        var charCoords = cm.charCoords(Pos(lineNum, 0), 'local');
+        var height = cm.getScrollInfo().clientHeight;
+        var y = charCoords.top;
+        var lineHeight = charCoords.bottom - y;
+        switch (actionArgs.position) {
+          case 'center': y = y - (height / 2) + lineHeight;
+            break;
+          case 'bottom': y = y - height + lineHeight*1.4;
+            break;
+          case 'top': y = y + lineHeight*0.4;
+            break;
+        }
+        cm.scrollTo(null, y);
+      },
+      replayMacro: function(cm, actionArgs, vim) {
+        var registerName = actionArgs.selectedCharacter;
+        var repeat = actionArgs.repeat;
+        var macroModeState = vimGlobalState.macroModeState;
+        if (registerName == '@') {
+          registerName = macroModeState.latestRegister;
+        }
+        while(repeat--){
+          executeMacroRegister(cm, vim, macroModeState, registerName);
+        }
+      },
+      enterMacroRecordMode: function(cm, actionArgs) {
+        var macroModeState = vimGlobalState.macroModeState;
+        var registerName = actionArgs.selectedCharacter;
+        if (vimGlobalState.registerController.isValidRegister(registerName)) {
+          macroModeState.enterMacroRecordMode(cm, registerName);
+        }
+      },
+      toggleOverwrite: function(cm) {
+        if (!cm.state.overwrite) {
+          cm.toggleOverwrite(true);
+          cm.setOption('keyMap', 'vim-replace');
+          CodeMirror.signal(cm, "vim-mode-change", {mode: "replace"});
+        } else {
+          cm.toggleOverwrite(false);
+          cm.setOption('keyMap', 'vim-insert');
+          CodeMirror.signal(cm, "vim-mode-change", {mode: "insert"});
+        }
+      },
+      enterInsertMode: function(cm, actionArgs, vim) {
+        if (cm.getOption('readOnly')) { return; }
+        vim.insertMode = true;
+        vim.insertModeRepeat = actionArgs && actionArgs.repeat || 1;
+        var insertAt = (actionArgs) ? actionArgs.insertAt : null;
+        var sel = vim.sel;
+        var head = actionArgs.head || cm.getCursor('head');
+        var height = cm.listSelections().length;
+        if (insertAt == 'eol') {
+          head = Pos(head.line, lineLength(cm, head.line));
+        } else if (insertAt == 'charAfter') {
+          head = offsetCursor(head, 0, 1);
+        } else if (insertAt == 'firstNonBlank') {
+          head = motions.moveToFirstNonWhiteSpaceCharacter(cm, head);
+        } else if (insertAt == 'startOfSelectedArea') {
+          if (!vim.visualBlock) {
+            if (sel.head.line < sel.anchor.line) {
+              head = sel.head;
+            } else {
+              head = Pos(sel.anchor.line, 0);
+            }
+          } else {
+            head = Pos(
+                Math.min(sel.head.line, sel.anchor.line),
+                Math.min(sel.head.ch, sel.anchor.ch));
+            height = Math.abs(sel.head.line - sel.anchor.line) + 1;
+          }
+        } else if (insertAt == 'endOfSelectedArea') {
+          if (!vim.visualBlock) {
+            if (sel.head.line >= sel.anchor.line) {
+              head = offsetCursor(sel.head, 0, 1);
+            } else {
+              head = Pos(sel.anchor.line, 0);
+            }
+          } else {
+            head = Pos(
+                Math.min(sel.head.line, sel.anchor.line),
+                Math.max(sel.head.ch + 1, sel.anchor.ch));
+            height = Math.abs(sel.head.line - sel.anchor.line) + 1;
+          }
+        } else if (insertAt == 'inplace') {
+          if (vim.visualMode){
+            return;
+          }
+        }
+        cm.setOption('disableInput', false);
+        if (actionArgs && actionArgs.replace) {
+          cm.toggleOverwrite(true);
+          cm.setOption('keyMap', 'vim-replace');
+          CodeMirror.signal(cm, "vim-mode-change", {mode: "replace"});
+        } else {
+          cm.toggleOverwrite(false);
+          cm.setOption('keyMap', 'vim-insert');
+          CodeMirror.signal(cm, "vim-mode-change", {mode: "insert"});
+        }
+        if (!vimGlobalState.macroModeState.isPlaying) {
+          cm.on('change', onChange);
+          CodeMirror.on(cm.getInputField(), 'keydown', onKeyEventTargetKeyDown);
+        }
+        if (vim.visualMode) {
+          exitVisualMode(cm);
+        }
+        selectForInsert(cm, head, height);
+      },
+      toggleVisualMode: function(cm, actionArgs, vim) {
+        var repeat = actionArgs.repeat;
+        var anchor = cm.getCursor();
+        var head;
+        if (!vim.visualMode) {
+          vim.visualMode = true;
+          vim.visualLine = !!actionArgs.linewise;
+          vim.visualBlock = !!actionArgs.blockwise;
+          head = clipCursorToContent(
+              cm, Pos(anchor.line, anchor.ch + repeat - 1),
+              true /** includeLineBreak */);
+          vim.sel = {
+            anchor: anchor,
+            head: head
+          };
+          CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : vim.visualBlock ? "blockwise" : ""});
+          updateCmSelection(cm);
+          updateMark(cm, vim, '<', cursorMin(anchor, head));
+          updateMark(cm, vim, '>', cursorMax(anchor, head));
+        } else if (vim.visualLine ^ actionArgs.linewise ||
+            vim.visualBlock ^ actionArgs.blockwise) {
+          vim.visualLine = !!actionArgs.linewise;
+          vim.visualBlock = !!actionArgs.blockwise;
+          CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : vim.visualBlock ? "blockwise" : ""});
+          updateCmSelection(cm);
+        } else {
+          exitVisualMode(cm);
+        }
+      },
+      reselectLastSelection: function(cm, _actionArgs, vim) {
+        var lastSelection = vim.lastSelection;
+        if (vim.visualMode) {
+          updateLastSelection(cm, vim);
+        }
+        if (lastSelection) {
+          var anchor = lastSelection.anchorMark.find();
+          var head = lastSelection.headMark.find();
+          if (!anchor || !head) {
+            return;
+          }
+          vim.sel = {
+            anchor: anchor,
+            head: head
+          };
+          vim.visualMode = true;
+          vim.visualLine = lastSelection.visualLine;
+          vim.visualBlock = lastSelection.visualBlock;
+          updateCmSelection(cm);
+          updateMark(cm, vim, '<', cursorMin(anchor, head));
+          updateMark(cm, vim, '>', cursorMax(anchor, head));
+          CodeMirror.signal(cm, 'vim-mode-change', {
+            mode: 'visual',
+            subMode: vim.visualLine ? 'linewise' :
+                     vim.visualBlock ? 'blockwise' : ''});
+        }
+      },
+      joinLines: function(cm, actionArgs, vim) {
+        var curStart, curEnd;
+        if (vim.visualMode) {
+          curStart = cm.getCursor('anchor');
+          curEnd = cm.getCursor('head');
+          if (cursorIsBefore(curEnd, curStart)) {
+            var tmp = curEnd;
+            curEnd = curStart;
+            curStart = tmp;
+          }
+          curEnd.ch = lineLength(cm, curEnd.line) - 1;
+        } else {
+          var repeat = Math.max(actionArgs.repeat, 2);
+          curStart = cm.getCursor();
+          curEnd = clipCursorToContent(cm, Pos(curStart.line + repeat - 1,
+                                               Infinity));
+        }
+        var finalCh = 0;
+        for (var i = curStart.line; i < curEnd.line; i++) {
+          finalCh = lineLength(cm, curStart.line);
+          var tmp = Pos(curStart.line + 1,
+                        lineLength(cm, curStart.line + 1));
+          var text = cm.getRange(curStart, tmp);
+          text = text.replace(/\n\s*/g, ' ');
+          cm.replaceRange(text, curStart, tmp);
+        }
+        var curFinalPos = Pos(curStart.line, finalCh);
+        if (vim.visualMode) {
+          exitVisualMode(cm, false);
+        }
+        cm.setCursor(curFinalPos);
+      },
+      newLineAndEnterInsertMode: function(cm, actionArgs, vim) {
+        vim.insertMode = true;
+        var insertAt = copyCursor(cm.getCursor());
+        if (insertAt.line === cm.firstLine() && !actionArgs.after) {
+          cm.replaceRange('\n', Pos(cm.firstLine(), 0));
+          cm.setCursor(cm.firstLine(), 0);
+        } else {
+          insertAt.line = (actionArgs.after) ? insertAt.line :
+              insertAt.line - 1;
+          insertAt.ch = lineLength(cm, insertAt.line);
+          cm.setCursor(insertAt);
+          var newlineFn = CodeMirror.commands.newlineAndIndentContinueComment ||
+              CodeMirror.commands.newlineAndIndent;
+          newlineFn(cm);
+        }
+        this.enterInsertMode(cm, { repeat: actionArgs.repeat }, vim);
+      },
+      paste: function(cm, actionArgs, vim) {
+        var cur = copyCursor(cm.getCursor());
+        var register = vimGlobalState.registerController.getRegister(
+            actionArgs.registerName);
+        var text = register.toString();
+        if (!text) {
+          return;
+        }
+        if (actionArgs.matchIndent) {
+          var tabSize = cm.getOption("tabSize");
+          var whitespaceLength = function(str) {
+            var tabs = (str.split("\t").length - 1);
+            var spaces = (str.split(" ").length - 1);
+            return tabs * tabSize + spaces * 1;
+          };
+          var currentLine = cm.getLine(cm.getCursor().line);
+          var indent = whitespaceLength(currentLine.match(/^\s*/)[0]);
+          var chompedText = text.replace(/\n$/, '');
+          var wasChomped = text !== chompedText;
+          var firstIndent = whitespaceLength(text.match(/^\s*/)[0]);
+          var text = chompedText.replace(/^\s*/gm, function(wspace) {
+            var newIndent = indent + (whitespaceLength(wspace) - firstIndent);
+            if (newIndent < 0) {
+              return "";
+            }
+            else if (cm.getOption("indentWithTabs")) {
+              var quotient = Math.floor(newIndent / tabSize);
+              return Array(quotient + 1).join('\t');
+            }
+            else {
+              return Array(newIndent + 1).join(' ');
+            }
+          });
+          text += wasChomped ? "\n" : "";
+        }
+        if (actionArgs.repeat > 1) {
+          var text = Array(actionArgs.repeat + 1).join(text);
+        }
+        var linewise = register.linewise;
+        var blockwise = register.blockwise;
+        if (linewise && !blockwise) {
+          if(vim.visualMode) {
+            text = vim.visualLine ? text.slice(0, -1) : '\n' + text.slice(0, text.length - 1) + '\n';
+          } else if (actionArgs.after) {
+            text = '\n' + text.slice(0, text.length - 1);
+            cur.ch = lineLength(cm, cur.line);
+          } else {
+            cur.ch = 0;
+          }
+        } else {
+          if (blockwise) {
+            text = text.split('\n');
+            for (var i = 0; i < text.length; i++) {
+              text[i] = (text[i] == '') ? ' ' : text[i];
+            }
+          }
+          cur.ch += actionArgs.after ? 1 : 0;
+        }
+        var curPosFinal;
+        var idx;
+        if (vim.visualMode) {
+          vim.lastPastedText = text;
+          var lastSelectionCurEnd;
+          var selectedArea = getSelectedAreaRange(cm, vim);
+          var selectionStart = selectedArea[0];
+          var selectionEnd = selectedArea[1];
+          var selectedText = cm.getSelection();
+          var selections = cm.listSelections();
+          var emptyStrings = new Array(selections.length).join('1').split('1');
+          if (vim.lastSelection) {
+            lastSelectionCurEnd = vim.lastSelection.headMark.find();
+          }
+          vimGlobalState.registerController.unnamedRegister.setText(selectedText);
+          if (blockwise) {
+            cm.replaceSelections(emptyStrings);
+            selectionEnd = Pos(selectionStart.line + text.length-1, selectionStart.ch);
+            cm.setCursor(selectionStart);
+            selectBlock(cm, selectionEnd);
+            cm.replaceSelections(text);
+            curPosFinal = selectionStart;
+          } else if (vim.visualBlock) {
+            cm.replaceSelections(emptyStrings);
+            cm.setCursor(selectionStart);
+            cm.replaceRange(text, selectionStart, selectionStart);
+            curPosFinal = selectionStart;
+          } else {
+            cm.replaceRange(text, selectionStart, selectionEnd);
+            curPosFinal = cm.posFromIndex(cm.indexFromPos(selectionStart) + text.length - 1);
+          }
+          if(lastSelectionCurEnd) {
+            vim.lastSelection.headMark = cm.setBookmark(lastSelectionCurEnd);
+          }
+          if (linewise) {
+            curPosFinal.ch=0;
+          }
+        } else {
+          if (blockwise) {
+            cm.setCursor(cur);
+            for (var i = 0; i < text.length; i++) {
+              var line = cur.line+i;
+              if (line > cm.lastLine()) {
+                cm.replaceRange('\n',  Pos(line, 0));
+              }
+              var lastCh = lineLength(cm, line);
+              if (lastCh < cur.ch) {
+                extendLineToColumn(cm, line, cur.ch);
+              }
+            }
+            cm.setCursor(cur);
+            selectBlock(cm, Pos(cur.line + text.length-1, cur.ch));
+            cm.replaceSelections(text);
+            curPosFinal = cur;
+          } else {
+            cm.replaceRange(text, cur);
+            if (linewise && actionArgs.after) {
+              curPosFinal = Pos(
+              cur.line + 1,
+              findFirstNonWhiteSpaceCharacter(cm.getLine(cur.line + 1)));
+            } else if (linewise && !actionArgs.after) {
+              curPosFinal = Pos(
+                cur.line,
+                findFirstNonWhiteSpaceCharacter(cm.getLine(cur.line)));
+            } else if (!linewise && actionArgs.after) {
+              idx = cm.indexFromPos(cur);
+              curPosFinal = cm.posFromIndex(idx + text.length - 1);
+            } else {
+              idx = cm.indexFromPos(cur);
+              curPosFinal = cm.posFromIndex(idx + text.length);
+            }
+          }
+        }
+        if (vim.visualMode) {
+          exitVisualMode(cm, false);
+        }
+        cm.setCursor(curPosFinal);
+      },
+      undo: function(cm, actionArgs) {
+        cm.operation(function() {
+          repeatFn(cm, CodeMirror.commands.undo, actionArgs.repeat)();
+          cm.setCursor(cm.getCursor('anchor'));
+        });
+      },
+      redo: function(cm, actionArgs) {
+        repeatFn(cm, CodeMirror.commands.redo, actionArgs.repeat)();
+      },
+      setRegister: function(_cm, actionArgs, vim) {
+        vim.inputState.registerName = actionArgs.selectedCharacter;
+      },
+      setMark: function(cm, actionArgs, vim) {
+        var markName = actionArgs.selectedCharacter;
+        updateMark(cm, vim, markName, cm.getCursor());
+      },
+      replace: function(cm, actionArgs, vim) {
+        var replaceWith = actionArgs.selectedCharacter;
+        var curStart = cm.getCursor();
+        var replaceTo;
+        var curEnd;
+        var selections = cm.listSelections();
+        if (vim.visualMode) {
+          curStart = cm.getCursor('start');
+          curEnd = cm.getCursor('end');
+        } else {
+          var line = cm.getLine(curStart.line);
+          replaceTo = curStart.ch + actionArgs.repeat;
+          if (replaceTo > line.length) {
+            replaceTo=line.length;
+          }
+          curEnd = Pos(curStart.line, replaceTo);
+        }
+        if (replaceWith=='\n') {
+          if (!vim.visualMode) cm.replaceRange('', curStart, curEnd);
+          (CodeMirror.commands.newlineAndIndentContinueComment || CodeMirror.commands.newlineAndIndent)(cm);
+        } else {
+          var replaceWithStr = cm.getRange(curStart, curEnd);
+          replaceWithStr = replaceWithStr.replace(/[^\n]/g, replaceWith);
+          if (vim.visualBlock) {
+            var spaces = new Array(cm.getOption("tabSize")+1).join(' ');
+            replaceWithStr = cm.getSelection();
+            replaceWithStr = replaceWithStr.replace(/\t/g, spaces).replace(/[^\n]/g, replaceWith).split('\n');
+            cm.replaceSelections(replaceWithStr);
+          } else {
+            cm.replaceRange(replaceWithStr, curStart, curEnd);
+          }
+          if (vim.visualMode) {
+            curStart = cursorIsBefore(selections[0].anchor, selections[0].head) ?
+                         selections[0].anchor : selections[0].head;
+            cm.setCursor(curStart);
+            exitVisualMode(cm, false);
+          } else {
+            cm.setCursor(offsetCursor(curEnd, 0, -1));
+          }
+        }
+      },
+      incrementNumberToken: function(cm, actionArgs) {
+        var cur = cm.getCursor();
+        var lineStr = cm.getLine(cur.line);
+        var re = /(-?)(?:(0x)([\da-f]+)|(0b|0|)(\d+))/gi;
+        var match;
+        var start;
+        var end;
+        var numberStr;
+        while ((match = re.exec(lineStr)) !== null) {
+          start = match.index;
+          end = start + match[0].length;
+          if (cur.ch < end)break;
+        }
+        if (!actionArgs.backtrack && (end <= cur.ch))return;
+        if (match) {
+          var baseStr = match[2] || match[4]
+          var digits = match[3] || match[5]
+          var increment = actionArgs.increase ? 1 : -1;
+          var base = {'0b': 2, '0': 8, '': 10, '0x': 16}[baseStr.toLowerCase()];
+          var number = parseInt(match[1] + digits, base) + (increment * actionArgs.repeat);
+          numberStr = number.toString(base);
+          var zeroPadding = baseStr ? new Array(digits.length - numberStr.length + 1 + match[1].length).join('0') : ''
+          if (numberStr.charAt(0) === '-') {
+            numberStr = '-' + baseStr + zeroPadding + numberStr.substr(1);
+          } else {
+            numberStr = baseStr + zeroPadding + numberStr;
+          }
+          var from = Pos(cur.line, start);
+          var to = Pos(cur.line, end);
+          cm.replaceRange(numberStr, from, to);
+        } else {
+          return;
+        }
+        cm.setCursor(Pos(cur.line, start + numberStr.length - 1));
+      },
+      repeatLastEdit: function(cm, actionArgs, vim) {
+        var lastEditInputState = vim.lastEditInputState;
+        if (!lastEditInputState) { return; }
+        var repeat = actionArgs.repeat;
+        if (repeat && actionArgs.repeatIsExplicit) {
+          vim.lastEditInputState.repeatOverride = repeat;
+        } else {
+          repeat = vim.lastEditInputState.repeatOverride || repeat;
+        }
+        repeatLastEdit(cm, vim, repeat, false /** repeatForInsert */);
+      },
+      indent: function(cm, actionArgs) {
+        cm.indentLine(cm.getCursor().line, actionArgs.indentRight);
+      },
+      exitInsertMode: exitInsertMode
+    };
+
+    function defineAction(name, fn) {
+      actions[name] = fn;
+    }
+    function clipCursorToContent(cm, cur, includeLineBreak) {
+      var line = Math.min(Math.max(cm.firstLine(), cur.line), cm.lastLine() );
+      var maxCh = lineLength(cm, line) - 1;
+      maxCh = (includeLineBreak) ? maxCh + 1 : maxCh;
+      var ch = Math.min(Math.max(0, cur.ch), maxCh);
+      return Pos(line, ch);
+    }
+    function copyArgs(args) {
+      var ret = {};
+      for (var prop in args) {
+        if (args.hasOwnProperty(prop)) {
+          ret[prop] = args[prop];
+        }
+      }
+      return ret;
+    }
+    function offsetCursor(cur, offsetLine, offsetCh) {
+      if (typeof offsetLine === 'object') {
+        offsetCh = offsetLine.ch;
+        offsetLine = offsetLine.line;
+      }
+      return Pos(cur.line + offsetLine, cur.ch + offsetCh);
+    }
+    function getOffset(anchor, head) {
+      return {
+        line: head.line - anchor.line,
+        ch: head.line - anchor.line
+      };
+    }
+    function commandMatches(keys, keyMap, context, inputState) {
+      var match, partial = [], full = [];
+      for (var i = 0; i < keyMap.length; i++) {
+        var command = keyMap[i];
+        if (context == 'insert' && command.context != 'insert' ||
+            command.context && command.context != context ||
+            inputState.operator && command.type == 'action' ||
+            !(match = commandMatch(keys, command.keys))) { continue; }
+        if (match == 'partial') { partial.push(command); }
+        if (match == 'full') { full.push(command); }
+      }
+      return {
+        partial: partial.length && partial,
+        full: full.length && full
+      };
+    }
+    function commandMatch(pressed, mapped) {
+      if (mapped.slice(-11) == '<character>') {
+        var prefixLen = mapped.length - 11;
+        var pressedPrefix = pressed.slice(0, prefixLen);
+        var mappedPrefix = mapped.slice(0, prefixLen);
+        return pressedPrefix == mappedPrefix && pressed.length > prefixLen ? 'full' :
+               mappedPrefix.indexOf(pressedPrefix) == 0 ? 'partial' : false;
+      } else {
+        return pressed == mapped ? 'full' :
+               mapped.indexOf(pressed) == 0 ? 'partial' : false;
+      }
+    }
+    function lastChar(keys) {
+      var match = /^.*(<[^>]+>)$/.exec(keys);
+      var selectedCharacter = match ? match[1] : keys.slice(-1);
+      if (selectedCharacter.length > 1){
+        switch(selectedCharacter){
+          case '<CR>':
+            selectedCharacter='\n';
+            break;
+          case '<Space>':
+            selectedCharacter=' ';
+            break;
+          default:
+            selectedCharacter='';
+            break;
+        }
+      }
+      return selectedCharacter;
+    }
+    function repeatFn(cm, fn, repeat) {
+      return function() {
+        for (var i = 0; i < repeat; i++) {
+          fn(cm);
+        }
+      };
+    }
+    function copyCursor(cur) {
+      return Pos(cur.line, cur.ch);
+    }
+    function cursorEqual(cur1, cur2) {
+      return cur1.ch == cur2.ch && cur1.line == cur2.line;
+    }
+    function cursorIsBefore(cur1, cur2) {
+      if (cur1.line < cur2.line) {
+        return true;
+      }
+      if (cur1.line == cur2.line && cur1.ch < cur2.ch) {
+        return true;
+      }
+      return false;
+    }
+    function cursorMin(cur1, cur2) {
+      if (arguments.length > 2) {
+        cur2 = cursorMin.apply(undefined, Array.prototype.slice.call(arguments, 1));
+      }
+      return cursorIsBefore(cur1, cur2) ? cur1 : cur2;
+    }
+    function cursorMax(cur1, cur2) {
+      if (arguments.length > 2) {
+        cur2 = cursorMax.apply(undefined, Array.prototype.slice.call(arguments, 1));
+      }
+      return cursorIsBefore(cur1, cur2) ? cur2 : cur1;
+    }
+    function cursorIsBetween(cur1, cur2, cur3) {
+      var cur1before2 = cursorIsBefore(cur1, cur2);
+      var cur2before3 = cursorIsBefore(cur2, cur3);
+      return cur1before2 && cur2before3;
+    }
+    function lineLength(cm, lineNum) {
+      return cm.getLine(lineNum).length;
+    }
+    function trim(s) {
+      if (s.trim) {
+        return s.trim();
+      }
+      return s.replace(/^\s+|\s+$/g, '');
+    }
+    function escapeRegex(s) {
+      return s.replace(/([.?*+$\[\]\/\\(){}|\-])/g, '\\$1');
+    }
+    function extendLineToColumn(cm, lineNum, column) {
+      var endCh = lineLength(cm, lineNum);
+      var spaces = new Array(column-endCh+1).join(' ');
+      cm.setCursor(Pos(lineNum, endCh));
+      cm.replaceRange(spaces, cm.getCursor());
+    }
+    function selectBlock(cm, selectionEnd) {
+      var selections = [], ranges = cm.listSelections();
+      var head = copyCursor(cm.clipPos(selectionEnd));
+      var isClipped = !cursorEqual(selectionEnd, head);
+      var curHead = cm.getCursor('head');
+      var primIndex = getIndex(ranges, curHead);
+      var wasClipped = cursorEqual(ranges[primIndex].head, ranges[primIndex].anchor);
+      var max = ranges.length - 1;
+      var index = max - primIndex > primIndex ? max : 0;
+      var base = ranges[index].anchor;
+
+      var firstLine = Math.min(base.line, head.line);
+      var lastLine = Math.max(base.line, head.line);
+      var baseCh = base.ch, headCh = head.ch;
+
+      var dir = ranges[index].head.ch - baseCh;
+      var newDir = headCh - baseCh;
+      if (dir > 0 && newDir <= 0) {
+        baseCh++;
+        if (!isClipped) { headCh--; }
+      } else if (dir < 0 && newDir >= 0) {
+        baseCh--;
+        if (!wasClipped) { headCh++; }
+      } else if (dir < 0 && newDir == -1) {
+        baseCh--;
+        headCh++;
+      }
+      for (var line = firstLine; line <= lastLine; line++) {
+        var range = {anchor: new Pos(line, baseCh), head: new Pos(line, headCh)};
+        selections.push(range);
+      }
+      cm.setSelections(selections);
+      selectionEnd.ch = headCh;
+      base.ch = baseCh;
+      return base;
+    }
+    function selectForInsert(cm, head, height) {
+      var sel = [];
+      for (var i = 0; i < height; i++) {
+        var lineHead = offsetCursor(head, i, 0);
+        sel.push({anchor: lineHead, head: lineHead});
+      }
+      cm.setSelections(sel, 0);
+    }
+    function getIndex(ranges, cursor, end) {
+      for (var i = 0; i < ranges.length; i++) {
+        var atAnchor = end != 'head' && cursorEqual(ranges[i].anchor, cursor);
+        var atHead = end != 'anchor' && cursorEqual(ranges[i].head, cursor);
+        if (atAnchor || atHead) {
+          return i;
+        }
+      }
+      return -1;
+    }
+    function getSelectedAreaRange(cm, vim) {
+      var lastSelection = vim.lastSelection;
+      var getCurrentSelectedAreaRange = function() {
+        var selections = cm.listSelections();
+        var start =  selections[0];
+        var end = selections[selections.length-1];
+        var selectionStart = cursorIsBefore(start.anchor, start.head) ? start.anchor : start.head;
+        var selectionEnd = cursorIsBefore(end.anchor, end.head) ? end.head : end.anchor;
+        return [selectionStart, selectionEnd];
+      };
+      var getLastSelectedAreaRange = function() {
+        var selectionStart = cm.getCursor();
+        var selectionEnd = cm.getCursor();
+        var block = lastSelection.visualBlock;
+        if (block) {
+          var width = block.width;
+          var height = block.height;
+          selectionEnd = Pos(selectionStart.line + height, selectionStart.ch + width);
+          var selections = [];
+          for (var i = selectionStart.line; i < selectionEnd.line; i++) {
+            var anchor = Pos(i, selectionStart.ch);
+            var head = Pos(i, selectionEnd.ch);
+            var range = {anchor: anchor, head: head};
+            selections.push(range);
+          }
+          cm.setSelections(selections);
+        } else {
+          var start = lastSelection.anchorMark.find();
+          var end = lastSelection.headMark.find();
+          var line = end.line - start.line;
+          var ch = end.ch - start.ch;
+          selectionEnd = {line: selectionEnd.line + line, ch: line ? selectionEnd.ch : ch + selectionEnd.ch};
+          if (lastSelection.visualLine) {
+            selectionStart = Pos(selectionStart.line, 0);
+            selectionEnd = Pos(selectionEnd.line, lineLength(cm, selectionEnd.line));
+          }
+          cm.setSelection(selectionStart, selectionEnd);
+        }
+        return [selectionStart, selectionEnd];
+      };
+      if (!vim.visualMode) {
+        return getLastSelectedAreaRange();
+      } else {
+        return getCurrentSelectedAreaRange();
+      }
+    }
+    function updateLastSelection(cm, vim) {
+      var anchor = vim.sel.anchor;
+      var head = vim.sel.head;
+      if (vim.lastPastedText) {
+        head = cm.posFromIndex(cm.indexFromPos(anchor) + vim.lastPastedText.length);
+        vim.lastPastedText = null;
+      }
+      vim.lastSelection = {'anchorMark': cm.setBookmark(anchor),
+                           'headMark': cm.setBookmark(head),
+                           'anchor': copyCursor(anchor),
+                           'head': copyCursor(head),
+                           'visualMode': vim.visualMode,
+                           'visualLine': vim.visualLine,
+                           'visualBlock': vim.visualBlock};
+    }
+    function expandSelection(cm, start, end) {
+      var sel = cm.state.vim.sel;
+      var head = sel.head;
+      var anchor = sel.anchor;
+      var tmp;
+      if (cursorIsBefore(end, start)) {
+        tmp = end;
+        end = start;
+        start = tmp;
+      }
+      if (cursorIsBefore(head, anchor)) {
+        head = cursorMin(start, head);
+        anchor = cursorMax(anchor, end);
+      } else {
+        anchor = cursorMin(start, anchor);
+        head = cursorMax(head, end);
+        head = offsetCursor(head, 0, -1);
+        if (head.ch == -1 && head.line != cm.firstLine()) {
+          head = Pos(head.line - 1, lineLength(cm, head.line - 1));
+        }
+      }
+      return [anchor, head];
+    }
+    function updateCmSelection(cm, sel, mode) {
+      var vim = cm.state.vim;
+      sel = sel || vim.sel;
+      var mode = mode ||
+        vim.visualLine ? 'line' : vim.visualBlock ? 'block' : 'char';
+      var cmSel = makeCmSelection(cm, sel, mode);
+      cm.setSelections(cmSel.ranges, cmSel.primary);
+      updateFakeCursor(cm);
+    }
+    function makeCmSelection(cm, sel, mode, exclusive) {
+      var head = copyCursor(sel.head);
+      var anchor = copyCursor(sel.anchor);
+      if (mode == 'char') {
+        var headOffset = !exclusive && !cursorIsBefore(sel.head, sel.anchor) ? 1 : 0;
+        var anchorOffset = cursorIsBefore(sel.head, sel.anchor) ? 1 : 0;
+        head = offsetCursor(sel.head, 0, headOffset);
+        anchor = offsetCursor(sel.anchor, 0, anchorOffset);
+        return {
+          ranges: [{anchor: anchor, head: head}],
+          primary: 0
+        };
+      } else if (mode == 'line') {
+        if (!cursorIsBefore(sel.head, sel.anchor)) {
+          anchor.ch = 0;
+
+          var lastLine = cm.lastLine();
+          if (head.line > lastLine) {
+            head.line = lastLine;
+          }
+          head.ch = lineLength(cm, head.line);
+        } else {
+          head.ch = 0;
+          anchor.ch = lineLength(cm, anchor.line);
+        }
+        return {
+          ranges: [{anchor: anchor, head: head}],
+          primary: 0
+        };
+      } else if (mode == 'block') {
+        var top = Math.min(anchor.line, head.line),
+            left = Math.min(anchor.ch, head.ch),
+            bottom = Math.max(anchor.line, head.line),
+            right = Math.max(anchor.ch, head.ch) + 1;
+        var height = bottom - top + 1;
+        var primary = head.line == top ? 0 : height - 1;
+        var ranges = [];
+        for (var i = 0; i < height; i++) {
+          ranges.push({
+            anchor: Pos(top + i, left),
+            head: Pos(top + i, right)
+          });
+        }
+        return {
+          ranges: ranges,
+          primary: primary
+        };
+      }
+    }
+    function getHead(cm) {
+      var cur = cm.getCursor('head');
+      if (cm.getSelection().length == 1) {
+        cur = cursorMin(cur, cm.getCursor('anchor'));
+      }
+      return cur;
+    }
+    function exitVisualMode(cm, moveHead) {
+      var vim = cm.state.vim;
+      if (moveHead !== false) {
+        cm.setCursor(clipCursorToContent(cm, vim.sel.head));
+      }
+      updateLastSelection(cm, vim);
+      vim.visualMode = false;
+      vim.visualLine = false;
+      vim.visualBlock = false;
+      CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"});
+      if (vim.fakeCursor) {
+        vim.fakeCursor.clear();
+      }
+    }
+    function clipToLine(cm, curStart, curEnd) {
+      var selection = cm.getRange(curStart, curEnd);
+      if (/\n\s*$/.test(selection)) {
+        var lines = selection.split('\n');
+        lines.pop();
+        var line;
+        for (var line = lines.pop(); lines.length > 0 && line && isWhiteSpaceString(line); line = lines.pop()) {
+          curEnd.line--;
+          curEnd.ch = 0;
+        }
+        if (line) {
+          curEnd.line--;
+          curEnd.ch = lineLength(cm, curEnd.line);
+        } else {
+          curEnd.ch = 0;
+        }
+      }
+    }
+    function expandSelectionToLine(_cm, curStart, curEnd) {
+      curStart.ch = 0;
+      curEnd.ch = 0;
+      curEnd.line++;
+    }
+
+    function findFirstNonWhiteSpaceCharacter(text) {
+      if (!text) {
+        return 0;
+      }
+      var firstNonWS = text.search(/\S/);
+      return firstNonWS == -1 ? text.length : firstNonWS;
+    }
+
+    function expandWordUnderCursor(cm, inclusive, _forward, bigWord, noSymbol) {
+      var cur = getHead(cm);
+      var line = cm.getLine(cur.line);
+      var idx = cur.ch;
+      var test = noSymbol ? wordCharTest[0] : bigWordCharTest [0];
+      while (!test(line.charAt(idx))) {
+        idx++;
+        if (idx >= line.length) { return null; }
+      }
+
+      if (bigWord) {
+        test = bigWordCharTest[0];
+      } else {
+        test = wordCharTest[0];
+        if (!test(line.charAt(idx))) {
+          test = wordCharTest[1];
+        }
+      }
+
+      var end = idx, start = idx;
+      while (test(line.charAt(end)) && end < line.length) { end++; }
+      while (test(line.charAt(start)) && start >= 0) { start--; }
+      start++;
+
+      if (inclusive) {
+        var wordEnd = end;
+        while (/\s/.test(line.charAt(end)) && end < line.length) { end++; }
+        if (wordEnd == end) {
+          var wordStart = start;
+          while (/\s/.test(line.charAt(start - 1)) && start > 0) { start--; }
+          if (!start) { start = wordStart; }
+        }
+      }
+      return { start: Pos(cur.line, start), end: Pos(cur.line, end) };
+    }
+
+    function recordJumpPosition(cm, oldCur, newCur) {
+      if (!cursorEqual(oldCur, newCur)) {
+        vimGlobalState.jumpList.add(cm, oldCur, newCur);
+      }
+    }
+
+    function recordLastCharacterSearch(increment, args) {
+        vimGlobalState.lastCharacterSearch.increment = increment;
+        vimGlobalState.lastCharacterSearch.forward = args.forward;
+        vimGlobalState.lastCharacterSearch.selectedCharacter = args.selectedCharacter;
+    }
+
+    var symbolToMode = {
+        '(': 'bracket', ')': 'bracket', '{': 'bracket', '}': 'bracket',
+        '[': 'section', ']': 'section',
+        '*': 'comment', '/': 'comment',
+        'm': 'method', 'M': 'method',
+        '#': 'preprocess'
+    };
+    var findSymbolModes = {
+      bracket: {
+        isComplete: function(state) {
+          if (state.nextCh === state.symb) {
+            state.depth++;
+            if (state.depth >= 1)return true;
+          } else if (state.nextCh === state.reverseSymb) {
+            state.depth--;
+          }
+          return false;
+        }
+      },
+      section: {
+        init: function(state) {
+          state.curMoveThrough = true;
+          state.symb = (state.forward ? ']' : '[') === state.symb ? '{' : '}';
+        },
+        isComplete: function(state) {
+          return state.index === 0 && state.nextCh === state.symb;
+        }
+      },
+      comment: {
+        isComplete: function(state) {
+          var found = state.lastCh === '*' && state.nextCh === '/';
+          state.lastCh = state.nextCh;
+          return found;
+        }
+      },
+      method: {
+        init: function(state) {
+          state.symb = (state.symb === 'm' ? '{' : '}');
+          state.reverseSymb = state.symb === '{' ? '}' : '{';
+        },
+        isComplete: function(state) {
+          if (state.nextCh === state.symb)return true;
+          return false;
+        }
+      },
+      preprocess: {
+        init: function(state) {
+          state.index = 0;
+        },
+        isComplete: function(state) {
+          if (state.nextCh === '#') {
+            var token = state.lineText.match(/#(\w+)/)[1];
+            if (token === 'endif') {
+              if (state.forward && state.depth === 0) {
+                return true;
+              }
+              state.depth++;
+            } else if (token === 'if') {
+              if (!state.forward && state.depth === 0) {
+                return true;
+              }
+              state.depth--;
+            }
+            if (token === 'else' && state.depth === 0)return true;
+          }
+          return false;
+        }
+      }
+    };
+    function findSymbol(cm, repeat, forward, symb) {
+      var cur = copyCursor(cm.getCursor());
+      var increment = forward ? 1 : -1;
+      var endLine = forward ? cm.lineCount() : -1;
+      var curCh = cur.ch;
+      var line = cur.line;
+      var lineText = cm.getLine(line);
+      var state = {
+        lineText: lineText,
+        nextCh: lineText.charAt(curCh),
+        lastCh: null,
+        index: curCh,
+        symb: symb,
+        reverseSymb: (forward ?  { ')': '(', '}': '{' } : { '(': ')', '{': '}' })[symb],
+        forward: forward,
+        depth: 0,
+        curMoveThrough: false
+      };
+      var mode = symbolToMode[symb];
+      if (!mode)return cur;
+      var init = findSymbolModes[mode].init;
+      var isComplete = findSymbolModes[mode].isComplete;
+      if (init) { init(state); }
+      while (line !== endLine && repeat) {
+        state.index += increment;
+        state.nextCh = state.lineText.charAt(state.index);
+        if (!state.nextCh) {
+          line += increment;
+          state.lineText = cm.getLine(line) || '';
+          if (increment > 0) {
+            state.index = 0;
+          } else {
+            var lineLen = state.lineText.length;
+            state.index = (lineLen > 0) ? (lineLen-1) : 0;
+          }
+          state.nextCh = state.lineText.charAt(state.index);
+        }
+        if (isComplete(state)) {
+          cur.line = line;
+          cur.ch = state.index;
+          repeat--;
+        }
+      }
+      if (state.nextCh || state.curMoveThrough) {
+        return Pos(line, state.index);
+      }
+      return cur;
+    }
+    function findWord(cm, cur, forward, bigWord, emptyLineIsWord) {
+      var lineNum = cur.line;
+      var pos = cur.ch;
+      var line = cm.getLine(lineNum);
+      var dir = forward ? 1 : -1;
+      var charTests = bigWord ? bigWordCharTest: wordCharTest;
+
+      if (emptyLineIsWord && line == '') {
+        lineNum += dir;
+        line = cm.getLine(lineNum);
+        if (!isLine(cm, lineNum)) {
+          return null;
+        }
+        pos = (forward) ? 0 : line.length;
+      }
+
+      while (true) {
+        if (emptyLineIsWord && line == '') {
+          return { from: 0, to: 0, line: lineNum };
+        }
+        var stop = (dir > 0) ? line.length : -1;
+        var wordStart = stop, wordEnd = stop;
+        while (pos != stop) {
+          var foundWord = false;
+          for (var i = 0; i < charTests.length && !foundWord; ++i) {
+            if (charTests[i](line.charAt(pos))) {
+              wordStart = pos;
+              while (pos != stop && charTests[i](line.charAt(pos))) {
+                pos += dir;
+              }
+              wordEnd = pos;
+              foundWord = wordStart != wordEnd;
+              if (wordStart == cur.ch && lineNum == cur.line &&
+                  wordEnd == wordStart + dir) {
+                continue;
+              } else {
+                return {
+                  from: Math.min(wordStart, wordEnd + 1),
+                  to: Math.max(wordStart, wordEnd),
+                  line: lineNum };
+              }
+            }
+          }
+          if (!foundWord) {
+            pos += dir;
+          }
+        }
+        lineNum += dir;
+        if (!isLine(cm, lineNum)) {
+          return null;
+        }
+        line = cm.getLine(lineNum);
+        pos = (dir > 0) ? 0 : line.length;
+      }
+    }
+    function moveToWord(cm, cur, repeat, forward, wordEnd, bigWord) {
+      var curStart = copyCursor(cur);
+      var words = [];
+      if (forward && !wordEnd || !forward && wordEnd) {
+        repeat++;
+      }
+      var emptyLineIsWord = !(forward && wordEnd);
+      for (var i = 0; i < repeat; i++) {
+        var word = findWord(cm, cur, forward, bigWord, emptyLineIsWord);
+        if (!word) {
+          var eodCh = lineLength(cm, cm.lastLine());
+          words.push(forward
+              ? {line: cm.lastLine(), from: eodCh, to: eodCh}
+              : {line: 0, from: 0, to: 0});
+          break;
+        }
+        words.push(word);
+        cur = Pos(word.line, forward ? (word.to - 1) : word.from);
+      }
+      var shortCircuit = words.length != repeat;
+      var firstWord = words[0];
+      var lastWord = words.pop();
+      if (forward && !wordEnd) {
+        if (!shortCircuit && (firstWord.from != curStart.ch || firstWord.line != curStart.line)) {
+          lastWord = words.pop();
+        }
+        return Pos(lastWord.line, lastWord.from);
+      } else if (forward && wordEnd) {
+        return Pos(lastWord.line, lastWord.to - 1);
+      } else if (!forward && wordEnd) {
+        if (!shortCircuit && (firstWord.to != curStart.ch || firstWord.line != curStart.line)) {
+          lastWord = words.pop();
+        }
+        return Pos(lastWord.line, lastWord.to);
+      } else {
+        return Pos(lastWord.line, lastWord.from);
+      }
+    }
+
+    function moveToCharacter(cm, repeat, forward, character) {
+      var cur = cm.getCursor();
+      var start = cur.ch;
+      var idx;
+      for (var i = 0; i < repeat; i ++) {
+        var line = cm.getLine(cur.line);
+        idx = charIdxInLine(start, line, character, forward, true);
+        if (idx == -1) {
+          return null;
+        }
+        start = idx;
+      }
+      return Pos(cm.getCursor().line, idx);
+    }
+
+    function moveToColumn(cm, repeat) {
+      var line = cm.getCursor().line;
+      return clipCursorToContent(cm, Pos(line, repeat - 1));
+    }
+
+    function updateMark(cm, vim, markName, pos) {
+      if (!inArray(markName, validMarks)) {
+        return;
+      }
+      if (vim.marks[markName]) {
+        vim.marks[markName].clear();
+      }
+      vim.marks[markName] = cm.setBookmark(pos);
+    }
+
+    function charIdxInLine(start, line, character, forward, includeChar) {
+      var idx;
+      if (forward) {
+        idx = line.indexOf(character, start + 1);
+        if (idx != -1 && !includeChar) {
+          idx -= 1;
+        }
+      } else {
+        idx = line.lastIndexOf(character, start - 1);
+        if (idx != -1 && !includeChar) {
+          idx += 1;
+        }
+      }
+      return idx;
+    }
+
+    function findParagraph(cm, head, repeat, dir, inclusive) {
+      var line = head.line;
+      var min = cm.firstLine();
+      var max = cm.lastLine();
+      var start, end, i = line;
+      function isEmpty(i) { return !/\S/.test(cm.getLine(i)); } // ace_patch
+      function isBoundary(i, dir, any) {
+        if (any) { return isEmpty(i) != isEmpty(i + dir); }
+        return !isEmpty(i) && isEmpty(i + dir);
+      }
+      function skipFold(i) {
+          dir = dir > 0 ? 1 : -1;
+          var foldLine = cm.ace.session.getFoldLine(i);
+          if (foldLine) {
+              if (i + dir > foldLine.start.row && i + dir < foldLine.end.row)
+                  dir = (dir > 0 ? foldLine.end.row : foldLine.start.row) - i;
+          }
+      }
+      if (dir) {
+        while (min <= i && i <= max && repeat > 0) {
+          skipFold(i);
+          if (isBoundary(i, dir)) { repeat--; }
+          i += dir;
+        }
+        return new Pos(i, 0);
+      }
+
+      var vim = cm.state.vim;
+      if (vim.visualLine && isBoundary(line, 1, true)) {
+        var anchor = vim.sel.anchor;
+        if (isBoundary(anchor.line, -1, true)) {
+          if (!inclusive || anchor.line != line) {
+            line += 1;
+          }
+        }
+      }
+      var startState = isEmpty(line);
+      for (i = line; i <= max && repeat; i++) {
+        if (isBoundary(i, 1, true)) {
+          if (!inclusive || isEmpty(i) != startState) {
+            repeat--;
+          }
+        }
+      }
+      end = new Pos(i, 0);
+      if (i > max && !startState) { startState = true; }
+      else { inclusive = false; }
+      for (i = line; i > min; i--) {
+        if (!inclusive || isEmpty(i) == startState || i == line) {
+          if (isBoundary(i, -1, true)) { break; }
+        }
+      }
+      start = new Pos(i, 0);
+      return { start: start, end: end };
+    }
+    function selectCompanionObject(cm, head, symb, inclusive) {
+      var cur = head, start, end;
+
+      var bracketRegexp = ({
+        '(': /[()]/, ')': /[()]/,
+        '[': /[[\]]/, ']': /[[\]]/,
+        '{': /[{}]/, '}': /[{}]/,
+        '<': /[<>]/, '>': /[<>]/})[symb];
+      var openSym = ({
+        '(': '(', ')': '(',
+        '[': '[', ']': '[',
+        '{': '{', '}': '{',
+        '<': '<', '>': '<'})[symb];
+      var curChar = cm.getLine(cur.line).charAt(cur.ch);
+      var offset = curChar === openSym ? 1 : 0;
+
+      start = cm.scanForBracket(Pos(cur.line, cur.ch + offset), -1, null, {'bracketRegex': bracketRegexp});
+      end = cm.scanForBracket(Pos(cur.line, cur.ch + offset), 1, null, {'bracketRegex': bracketRegexp});
+
+      if (!start || !end) {
+        return { start: cur, end: cur };
+      }
+
+      start = start.pos;
+      end = end.pos;
+
+      if ((start.line == end.line && start.ch > end.ch)
+          || (start.line > end.line)) {
+        var tmp = start;
+        start = end;
+        end = tmp;
+      }
+
+      if (inclusive) {
+        end.ch += 1;
+      } else {
+        start.ch += 1;
+      }
+
+      return { start: start, end: end };
+    }
+    function findBeginningAndEnd(cm, head, symb, inclusive) {
+      var cur = copyCursor(head);
+      var line = cm.getLine(cur.line);
+      var chars = line.split('');
+      var start, end, i, len;
+      var firstIndex = chars.indexOf(symb);
+      if (cur.ch < firstIndex) {
+        cur.ch = firstIndex;
+      }
+      else if (firstIndex < cur.ch && chars[cur.ch] == symb) {
+        end = cur.ch; // assign end to the current cursor
+        --cur.ch; // make sure to look backwards
+      }
+      if (chars[cur.ch] == symb && !end) {
+        start = cur.ch + 1; // assign start to ahead of the cursor
+      } else {
+        for (i = cur.ch; i > -1 && !start; i--) {
+          if (chars[i] == symb) {
+            start = i + 1;
+          }
+        }
+      }
+      if (start && !end) {
+        for (i = start, len = chars.length; i < len && !end; i++) {
+          if (chars[i] == symb) {
+            end = i;
+          }
+        }
+      }
+      if (!start || !end) {
+        return { start: cur, end: cur };
+      }
+      if (inclusive) {
+        --start; ++end;
+      }
+
+      return {
+        start: Pos(cur.line, start),
+        end: Pos(cur.line, end)
+      };
+    }
+    defineOption('pcre', true, 'boolean');
+    function SearchState() {}
+    SearchState.prototype = {
+      getQuery: function() {
+        return vimGlobalState.query;
+      },
+      setQuery: function(query) {
+        vimGlobalState.query = query;
+      },
+      getOverlay: function() {
+        return this.searchOverlay;
+      },
+      setOverlay: function(overlay) {
+        this.searchOverlay = overlay;
+      },
+      isReversed: function() {
+        return vimGlobalState.isReversed;
+      },
+      setReversed: function(reversed) {
+        vimGlobalState.isReversed = reversed;
+      },
+      getScrollbarAnnotate: function() {
+        return this.annotate;
+      },
+      setScrollbarAnnotate: function(annotate) {
+        this.annotate = annotate;
+      }
+    };
+    function getSearchState(cm) {
+      var vim = cm.state.vim;
+      return vim.searchState_ || (vim.searchState_ = new SearchState());
+    }
+    function dialog(cm, template, shortText, onClose, options) {
+      if (cm.openDialog) {
+        cm.openDialog(template, onClose, { bottom: true, value: options.value,
+            onKeyDown: options.onKeyDown, onKeyUp: options.onKeyUp,
+            selectValueOnOpen: false, onClose: function() {
+              if (cm.state.vim) {
+                cm.state.vim.status = "";
+                cm.ace.renderer.$loop.schedule(cm.ace.renderer.CHANGE_CURSOR);
+              }
+            }});
+      }
+      else {
+        onClose(prompt(shortText, ''));
+      }
+    }
+    
+    function splitBySlash(argString) {
+      return splitBySeparator(argString, '/');
+    }
+  
+    function findUnescapedSlashes(argString) {
+      return findUnescapedSeparators(argString, '/');
+    }
+
+    function splitBySeparator(argString, separator) {
+      var slashes = findUnescapedSeparators(argString, separator) || [];
+      if (!slashes.length) return [];
+      var tokens = [];
+      if (slashes[0] !== 0) return;
+      for (var i = 0; i < slashes.length; i++) {
+        if (typeof slashes[i] == 'number')
+          tokens.push(argString.substring(slashes[i] + 1, slashes[i+1]));
+      }
+      return tokens;
+    }
+
+    function findUnescapedSeparators(str, separator) {
+      if (!separator)
+        separator = '/';
+
+      var escapeNextChar = false;
+      var slashes = [];
+      for (var i = 0; i < str.length; i++) {
+        var c = str.charAt(i);
+        if (!escapeNextChar && c == separator) {
+          slashes.push(i);
+        }
+        escapeNextChar = !escapeNextChar && (c == '\\');
+      }
+      return slashes;
+    }
+    function translateRegex(str) {
+      var specials = '|(){';
+      var unescape = '}';
+      var escapeNextChar = false;
+      var out = [];
+      for (var i = -1; i < str.length; i++) {
+        var c = str.charAt(i) || '';
+        var n = str.charAt(i+1) || '';
+        var specialComesNext = (n && specials.indexOf(n) != -1);
+        if (escapeNextChar) {
+          if (c !== '\\' || !specialComesNext) {
+            out.push(c);
+          }
+          escapeNextChar = false;
+        } else {
+          if (c === '\\') {
+            escapeNextChar = true;
+            if (n && unescape.indexOf(n) != -1) {
+              specialComesNext = true;
+            }
+            if (!specialComesNext || n === '\\') {
+              out.push(c);
+            }
+          } else {
+            out.push(c);
+            if (specialComesNext && n !== '\\') {
+              out.push('\\');
+            }
+          }
+        }
+      }
+      return out.join('');
+    }
+    var charUnescapes = {'\\n': '\n', '\\r': '\r', '\\t': '\t'};
+    function translateRegexReplace(str) {
+      var escapeNextChar = false;
+      var out = [];
+      for (var i = -1; i < str.length; i++) {
+        var c = str.charAt(i) || '';
+        var n = str.charAt(i+1) || '';
+        if (charUnescapes[c + n]) {
+          out.push(charUnescapes[c+n]);
+          i++;
+        } else if (escapeNextChar) {
+          out.push(c);
+          escapeNextChar = false;
+        } else {
+          if (c === '\\') {
+            escapeNextChar = true;
+            if ((isNumber(n) || n === '$')) {
+              out.push('$');
+            } else if (n !== '/' && n !== '\\') {
+              out.push('\\');
+            }
+          } else {
+            if (c === '$') {
+              out.push('$');
+            }
+            out.push(c);
+            if (n === '/') {
+              out.push('\\');
+            }
+          }
+        }
+      }
+      return out.join('');
+    }
+    var unescapes = {'\\/': '/', '\\\\': '\\', '\\n': '\n', '\\r': '\r', '\\t': '\t'};
+    function unescapeRegexReplace(str) {
+      var stream = new CodeMirror.StringStream(str);
+      var output = [];
+      while (!stream.eol()) {
+        while (stream.peek() && stream.peek() != '\\') {
+          output.push(stream.next());
+        }
+        var matched = false;
+        for (var matcher in unescapes) {
+          if (stream.match(matcher, true)) {
+            matched = true;
+            output.push(unescapes[matcher]);
+            break;
+          }
+        }
+        if (!matched) {
+          output.push(stream.next());
+        }
+      }
+      return output.join('');
+    }
+    function parseQuery(query, ignoreCase, smartCase) {
+      var lastSearchRegister = vimGlobalState.registerController.getRegister('/');
+      lastSearchRegister.setText(query);
+      if (query instanceof RegExp) { return query; }
+      var slashes = findUnescapedSlashes(query);
+      var regexPart;
+      var forceIgnoreCase;
+      if (!slashes.length) {
+        regexPart = query;
+      } else {
+        regexPart = query.substring(0, slashes[0]);
+        var flagsPart = query.substring(slashes[0]);
+        forceIgnoreCase = (flagsPart.indexOf('i') != -1);
+      }
+      if (!regexPart) {
+        return null;
+      }
+      if (!getOption('pcre')) {
+        regexPart = translateRegex(regexPart);
+      }
+      if (smartCase) {
+        ignoreCase = (/^[^A-Z]*$/).test(regexPart);
+      }
+      var regexp = new RegExp(regexPart,
+          (ignoreCase || forceIgnoreCase) ? 'i' : undefined);
+      return regexp;
+    }
+    function showConfirm(cm, text) {
+      if (cm.openNotification) {
+        cm.openNotification('<span style="color: red">' + text + '</span>',
+                            {bottom: true, duration: 5000});
+      } else {
+        alert(text);
+      }
+    }
+    function makePrompt(prefix, desc) {
+      var raw = '<span style="font-family: monospace; white-space: pre">' +
+          (prefix || "") + '<input type="text" autocorrect="off" autocapitalize="none" autocomplete="off"></span>';
+      if (desc)
+        raw += ' <span style="color: #888">' + desc + '</span>';
+      return raw;
+    }
+    var searchPromptDesc = '(Javascript regexp)';
+    function showPrompt(cm, options) {
+      var shortText = (options.prefix || '') + ' ' + (options.desc || '');
+      var prompt = makePrompt(options.prefix, options.desc);
+      dialog(cm, prompt, shortText, options.onClose, options);
+    }
+    function regexEqual(r1, r2) {
+      if (r1 instanceof RegExp && r2 instanceof RegExp) {
+          var props = ['global', 'multiline', 'ignoreCase', 'source'];
+          for (var i = 0; i < props.length; i++) {
+              var prop = props[i];
+              if (r1[prop] !== r2[prop]) {
+                  return false;
+              }
+          }
+          return true;
+      }
+      return false;
+    }
+    function updateSearchQuery(cm, rawQuery, ignoreCase, smartCase) {
+      if (!rawQuery) {
+        return;
+      }
+      var state = getSearchState(cm);
+      var query = parseQuery(rawQuery, !!ignoreCase, !!smartCase);
+      if (!query) {
+        return;
+      }
+      highlightSearchMatches(cm, query);
+      if (regexEqual(query, state.getQuery())) {
+        return query;
+      }
+      state.setQuery(query);
+      return query;
+    }
+    function searchOverlay(query) {
+      if (query.source.charAt(0) == '^') {
+        var matchSol = true;
+      }
+      return {
+        token: function(stream) {
+          if (matchSol && !stream.sol()) {
+            stream.skipToEnd();
+            return;
+          }
+          var match = stream.match(query, false);
+          if (match) {
+            if (match[0].length == 0) {
+              stream.next();
+              return 'searching';
+            }
+            if (!stream.sol()) {
+              stream.backUp(1);
+              if (!query.exec(stream.next() + match[0])) {
+                stream.next();
+                return null;
+              }
+            }
+            stream.match(query);
+            return 'searching';
+          }
+          while (!stream.eol()) {
+            stream.next();
+            if (stream.match(query, false)) break;
+          }
+        },
+        query: query
+      };
+    }
+    function highlightSearchMatches(cm, query) {
+      var searchState = getSearchState(cm);
+      var overlay = searchState.getOverlay();
+      if (!overlay || query != overlay.query) {
+        if (overlay) {
+          cm.removeOverlay(overlay);
+        }
+        overlay = searchOverlay(query);
+        cm.addOverlay(overlay);
+        if (cm.showMatchesOnScrollbar) {
+          if (searchState.getScrollbarAnnotate()) {
+            searchState.getScrollbarAnnotate().clear();
+          }
+          searchState.setScrollbarAnnotate(cm.showMatchesOnScrollbar(query));
+        }
+        searchState.setOverlay(overlay);
+      }
+    }
+    function findNext(cm, prev, query, repeat) {
+      if (repeat === undefined) { repeat = 1; }
+      return cm.operation(function() {
+        var pos = cm.getCursor();
+        var cursor = cm.getSearchCursor(query, pos);
+        for (var i = 0; i < repeat; i++) {
+          var found = cursor.find(prev);
+          if (i == 0 && found && cursorEqual(cursor.from(), pos)) { found = cursor.find(prev); }
+          if (!found) {
+            cursor = cm.getSearchCursor(query,
+                (prev) ? Pos(cm.lastLine()) : Pos(cm.firstLine(), 0) );
+            if (!cursor.find(prev)) {
+              return;
+            }
+          }
+        }
+        return cursor.from();
+      });
+    }
+    function clearSearchHighlight(cm) {
+      var state = getSearchState(cm);
+      cm.removeOverlay(getSearchState(cm).getOverlay());
+      state.setOverlay(null);
+      if (state.getScrollbarAnnotate()) {
+        state.getScrollbarAnnotate().clear();
+        state.setScrollbarAnnotate(null);
+      }
+    }
+    function isInRange(pos, start, end) {
+      if (typeof pos != 'number') {
+        pos = pos.line;
+      }
+      if (start instanceof Array) {
+        return inArray(pos, start);
+      } else {
+        if (end) {
+          return (pos >= start && pos <= end);
+        } else {
+          return pos == start;
+        }
+      }
+    }
+    function getUserVisibleLines(cm) {
+      var renderer = cm.ace.renderer;
+      return {
+        top: renderer.getFirstFullyVisibleRow(),
+        bottom: renderer.getLastFullyVisibleRow()
+      }
+    }
+
+    function getMarkPos(cm, vim, markName) {
+
+      var mark = vim.marks[markName];
+      return mark && mark.find();
+    }
+
+    var ExCommandDispatcher = function() {
+      this.buildCommandMap_();
+    };
+    ExCommandDispatcher.prototype = {
+      processCommand: function(cm, input, opt_params) {
+        var that = this;
+        cm.operation(function () {
+          cm.curOp.isVimOp = true;
+          that._processCommand(cm, input, opt_params);
+        });
+      },
+      _processCommand: function(cm, input, opt_params) {
+        var vim = cm.state.vim;
+        var commandHistoryRegister = vimGlobalState.registerController.getRegister(':');
+        var previousCommand = commandHistoryRegister.toString();
+        if (vim.visualMode) {
+          exitVisualMode(cm);
+        }
+        var inputStream = new CodeMirror.StringStream(input);
+        commandHistoryRegister.setText(input);
+        var params = opt_params || {};
+        params.input = input;
+        try {
+          this.parseInput_(cm, inputStream, params);
+        } catch(e) {
+          showConfirm(cm, e);
+          throw e;
+        }
+        var command;
+        var commandName;
+        if (!params.commandName) {
+          if (params.line !== undefined) {
+            commandName = 'move';
+          }
+        } else {
+          command = this.matchCommand_(params.commandName);
+          if (command) {
+            commandName = command.name;
+            if (command.excludeFromCommandHistory) {
+              commandHistoryRegister.setText(previousCommand);
+            }
+            this.parseCommandArgs_(inputStream, params, command);
+            if (command.type == 'exToKey') {
+              for (var i = 0; i < command.toKeys.length; i++) {
+                CodeMirror.Vim.handleKey(cm, command.toKeys[i], 'mapping');
+              }
+              return;
+            } else if (command.type == 'exToEx') {
+              this.processCommand(cm, command.toInput);
+              return;
+            }
+          }
+        }
+        if (!commandName) {
+          showConfirm(cm, 'Not an editor command ":' + input + '"');
+          return;
+        }
+        try {
+          exCommands[commandName](cm, params);
+          if ((!command || !command.possiblyAsync) && params.callback) {
+            params.callback();
+          }
+        } catch(e) {
+          showConfirm(cm, e);
+          throw e;
+        }
+      },
+      parseInput_: function(cm, inputStream, result) {
+        inputStream.eatWhile(':');
+        if (inputStream.eat('%')) {
+          result.line = cm.firstLine();
+          result.lineEnd = cm.lastLine();
+        } else {
+          result.line = this.parseLineSpec_(cm, inputStream);
+          if (result.line !== undefined && inputStream.eat(',')) {
+            result.lineEnd = this.parseLineSpec_(cm, inputStream);
+          }
+        }
+        var commandMatch = inputStream.match(/^(\w+)/);
+        if (commandMatch) {
+          result.commandName = commandMatch[1];
+        } else {
+          result.commandName = inputStream.match(/.*/)[0];
+        }
+
+        return result;
+      },
+      parseLineSpec_: function(cm, inputStream) {
+        var numberMatch = inputStream.match(/^(\d+)/);
+        if (numberMatch) {
+          return parseInt(numberMatch[1], 10) - 1;
+        }
+        switch (inputStream.next()) {
+          case '.':
+            return this.parseLineSpecOffset_(inputStream, cm.getCursor().line);
+          case '$':
+            return this.parseLineSpecOffset_(inputStream, cm.lastLine());
+          case '\'':
+            var markName = inputStream.next();
+            var markPos = getMarkPos(cm, cm.state.vim, markName);
+            if (!markPos) throw new Error('Mark not set');
+            return this.parseLineSpecOffset_(inputStream, markPos.line);
+          case '-':
+          case '+':
+            inputStream.backUp(1);
+            return this.parseLineSpecOffset_(inputStream, cm.getCursor().line);
+          default:
+            inputStream.backUp(1);
+            return undefined;
+        }
+      },
+      parseLineSpecOffset_: function(inputStream, line) {
+        var offsetMatch = inputStream.match(/^([+-])?(\d+)/);
+        if (offsetMatch) {
+          var offset = parseInt(offsetMatch[2], 10);
+          if (offsetMatch[1] == "-") {
+            line -= offset;
+          } else {
+            line += offset;
+          }
+        }
+        return line;
+      },
+      parseCommandArgs_: function(inputStream, params, command) {
+        if (inputStream.eol()) {
+          return;
+        }
+        params.argString = inputStream.match(/.*/)[0];
+        var delim = command.argDelimiter || /\s+/;
+        var args = trim(params.argString).split(delim);
+        if (args.length && args[0]) {
+          params.args = args;
+        }
+      },
+      matchCommand_: function(commandName) {
+        for (var i = commandName.length; i > 0; i--) {
+          var prefix = commandName.substring(0, i);
+          if (this.commandMap_[prefix]) {
+            var command = this.commandMap_[prefix];
+            if (command.name.indexOf(commandName) === 0) {
+              return command;
+            }
+          }
+        }
+        return null;
+      },
+      buildCommandMap_: function() {
+        this.commandMap_ = {};
+        for (var i = 0; i < defaultExCommandMap.length; i++) {
+          var command = defaultExCommandMap[i];
+          var key = command.shortName || command.name;
+          this.commandMap_[key] = command;
+        }
+      },
+      map: function(lhs, rhs, ctx) {
+        if (lhs != ':' && lhs.charAt(0) == ':') {
+          if (ctx) { throw Error('Mode not supported for ex mappings'); }
+          var commandName = lhs.substring(1);
+          if (rhs != ':' && rhs.charAt(0) == ':') {
+            this.commandMap_[commandName] = {
+              name: commandName,
+              type: 'exToEx',
+              toInput: rhs.substring(1),
+              user: true
+            };
+          } else {
+            this.commandMap_[commandName] = {
+              name: commandName,
+              type: 'exToKey',
+              toKeys: rhs,
+              user: true
+            };
+          }
+        } else {
+          if (rhs != ':' && rhs.charAt(0) == ':') {
+            var mapping = {
+              keys: lhs,
+              type: 'keyToEx',
+              exArgs: { input: rhs.substring(1) }
+            };
+            if (ctx) { mapping.context = ctx; }
+            defaultKeymap.unshift(mapping);
+          } else {
+            var mapping = {
+              keys: lhs,
+              type: 'keyToKey',
+              toKeys: rhs
+            };
+            if (ctx) { mapping.context = ctx; }
+            defaultKeymap.unshift(mapping);
+          }
+        }
+      },
+      unmap: function(lhs, ctx) {
+        if (lhs != ':' && lhs.charAt(0) == ':') {
+          if (ctx) { throw Error('Mode not supported for ex mappings'); }
+          var commandName = lhs.substring(1);
+          if (this.commandMap_[commandName] && this.commandMap_[commandName].user) {
+            delete this.commandMap_[commandName];
+            return;
+          }
+        } else {
+          var keys = lhs;
+          for (var i = 0; i < defaultKeymap.length; i++) {
+            if (keys == defaultKeymap[i].keys
+                && defaultKeymap[i].context === ctx) {
+              defaultKeymap.splice(i, 1);
+              return;
+            }
+          }
+        }
+      }
+    };
+
+    var exCommands = {
+      colorscheme: function(cm, params) {
+        if (!params.args || params.args.length < 1) {
+          showConfirm(cm, cm.getOption('theme'));
+          return;
+        }
+        cm.setOption('theme', params.args[0]);
+      },
+      map: function(cm, params, ctx) {
+        var mapArgs = params.args;
+        if (!mapArgs || mapArgs.length < 2) {
+          if (cm) {
+            showConfirm(cm, 'Invalid mapping: ' + params.input);
+          }
+          return;
+        }
+        exCommandDispatcher.map(mapArgs[0], mapArgs[1], ctx);
+      },
+      imap: function(cm, params) { this.map(cm, params, 'insert'); },
+      nmap: function(cm, params) { this.map(cm, params, 'normal'); },
+      vmap: function(cm, params) { this.map(cm, params, 'visual'); },
+      unmap: function(cm, params, ctx) {
+        var mapArgs = params.args;
+        if (!mapArgs || mapArgs.length < 1) {
+          if (cm) {
+            showConfirm(cm, 'No such mapping: ' + params.input);
+          }
+          return;
+        }
+        exCommandDispatcher.unmap(mapArgs[0], ctx);
+      },
+      move: function(cm, params) {
+        commandDispatcher.processCommand(cm, cm.state.vim, {
+            type: 'motion',
+            motion: 'moveToLineOrEdgeOfDocument',
+            motionArgs: { forward: false, explicitRepeat: true,
+              linewise: true },
+            repeatOverride: params.line+1});
+      },
+      set: function(cm, params) {
+        var setArgs = params.args;
+        var setCfg = params.setCfg || {};
+        if (!setArgs || setArgs.length < 1) {
+          if (cm) {
+            showConfirm(cm, 'Invalid mapping: ' + params.input);
+          }
+          return;
+        }
+        var expr = setArgs[0].split('=');
+        var optionName = expr[0];
+        var value = expr[1];
+        var forceGet = false;
+
+        if (optionName.charAt(optionName.length - 1) == '?') {
+          if (value) { throw Error('Trailing characters: ' + params.argString); }
+          optionName = optionName.substring(0, optionName.length - 1);
+          forceGet = true;
+        }
+        if (value === undefined && optionName.substring(0, 2) == 'no') {
+          optionName = optionName.substring(2);
+          value = false;
+        }
+
+        var optionIsBoolean = options[optionName] && options[optionName].type == 'boolean';
+        if (optionIsBoolean && value == undefined) {
+          value = true;
+        }
+        if (!optionIsBoolean && value === undefined || forceGet) {
+          var oldValue = getOption(optionName, cm, setCfg);
+          if (oldValue instanceof Error) {
+            showConfirm(cm, oldValue.message);
+          } else if (oldValue === true || oldValue === false) {
+            showConfirm(cm, ' ' + (oldValue ? '' : 'no') + optionName);
+          } else {
+            showConfirm(cm, '  ' + optionName + '=' + oldValue);
+          }
+        } else {
+          var setOptionReturn = setOption(optionName, value, cm, setCfg);
+          if (setOptionReturn instanceof Error) {
+            showConfirm(cm, setOptionReturn.message);
+          }
+        }
+      },
+      setlocal: function (cm, params) {
+        params.setCfg = {scope: 'local'};
+        this.set(cm, params);
+      },
+      setglobal: function (cm, params) {
+        params.setCfg = {scope: 'global'};
+        this.set(cm, params);
+      },
+      registers: function(cm, params) {
+        var regArgs = params.args;
+        var registers = vimGlobalState.registerController.registers;
+        var regInfo = '----------Registers----------<br><br>';
+        if (!regArgs) {
+          for (var registerName in registers) {
+            var text = registers[registerName].toString();
+            if (text.length) {
+              regInfo += '"' + registerName + '    ' + text + '<br>';
+            }
+          }
+        } else {
+          var registerName;
+          regArgs = regArgs.join('');
+          for (var i = 0; i < regArgs.length; i++) {
+            registerName = regArgs.charAt(i);
+            if (!vimGlobalState.registerController.isValidRegister(registerName)) {
+              continue;
+            }
+            var register = registers[registerName] || new Register();
+            regInfo += '"' + registerName + '    ' + register.toString() + '<br>';
+          }
+        }
+        showConfirm(cm, regInfo);
+      },
+      sort: function(cm, params) {
+        var reverse, ignoreCase, unique, number, pattern;
+        function parseArgs() {
+          if (params.argString) {
+            var args = new CodeMirror.StringStream(params.argString);
+            if (args.eat('!')) { reverse = true; }
+            if (args.eol()) { return; }
+            if (!args.eatSpace()) { return 'Invalid arguments'; }
+            var opts = args.match(/([dinuox]+)?\s*(\/.+\/)?\s*/);
+            if (!opts && !args.eol()) { return 'Invalid arguments'; }
+            if (opts[1]) {
+              ignoreCase = opts[1].indexOf('i') != -1;
+              unique = opts[1].indexOf('u') != -1;
+              var decimal = opts[1].indexOf('d') != -1 || opts[1].indexOf('n') != -1 && 1;
+              var hex = opts[1].indexOf('x') != -1 && 1;
+              var octal = opts[1].indexOf('o') != -1 && 1;
+              if (decimal + hex + octal > 1) { return 'Invalid arguments'; }
+              number = decimal && 'decimal' || hex && 'hex' || octal && 'octal';
+            }
+            if (opts[2]) {
+              pattern = new RegExp(opts[2].substr(1, opts[2].length - 2), ignoreCase ? 'i' : '');
+            }
+          }
+        }
+        var err = parseArgs();
+        if (err) {
+          showConfirm(cm, err + ': ' + params.argString);
+          return;
+        }
+        var lineStart = params.line || cm.firstLine();
+        var lineEnd = params.lineEnd || params.line || cm.lastLine();
+        if (lineStart == lineEnd) { return; }
+        var curStart = Pos(lineStart, 0);
+        var curEnd = Pos(lineEnd, lineLength(cm, lineEnd));
+        var text = cm.getRange(curStart, curEnd).split('\n');
+        var numberRegex = pattern ? pattern :
+           (number == 'decimal') ? /(-?)([\d]+)/ :
+           (number == 'hex') ? /(-?)(?:0x)?([0-9a-f]+)/i :
+           (number == 'octal') ? /([0-7]+)/ : null;
+        var radix = (number == 'decimal') ? 10 : (number == 'hex') ? 16 : (number == 'octal') ? 8 : null;
+        var numPart = [], textPart = [];
+        if (number || pattern) {
+          for (var i = 0; i < text.length; i++) {
+            var matchPart = pattern ? text[i].match(pattern) : null;
+            if (matchPart && matchPart[0] != '') {
+              numPart.push(matchPart);
+            } else if (!pattern && numberRegex.exec(text[i])) {
+              numPart.push(text[i]);
+            } else {
+              textPart.push(text[i]);
+            }
+          }
+        } else {
+          textPart = text;
+        }
+        function compareFn(a, b) {
+          if (reverse) { var tmp; tmp = a; a = b; b = tmp; }
+          if (ignoreCase) { a = a.toLowerCase(); b = b.toLowerCase(); }
+          var anum = number && numberRegex.exec(a);
+          var bnum = number && numberRegex.exec(b);
+          if (!anum) { return a < b ? -1 : 1; }
+          anum = parseInt((anum[1] + anum[2]).toLowerCase(), radix);
+          bnum = parseInt((bnum[1] + bnum[2]).toLowerCase(), radix);
+          return anum - bnum;
+        }
+        function comparePatternFn(a, b) {
+          if (reverse) { var tmp; tmp = a; a = b; b = tmp; }
+          if (ignoreCase) { a[0] = a[0].toLowerCase(); b[0] = b[0].toLowerCase(); }
+          return (a[0] < b[0]) ? -1 : 1;
+        }
+        numPart.sort(pattern ? comparePatternFn : compareFn);
+        if (pattern) {
+          for (var i = 0; i < numPart.length; i++) {
+            numPart[i] = numPart[i].input;
+          }
+        } else if (!number) { textPart.sort(compareFn); }
+        text = (!reverse) ? textPart.concat(numPart) : numPart.concat(textPart);
+        if (unique) { // Remove duplicate lines
+          var textOld = text;
+          var lastLine;
+          text = [];
+          for (var i = 0; i < textOld.length; i++) {
+            if (textOld[i] != lastLine) {
+              text.push(textOld[i]);
+            }
+            lastLine = textOld[i];
+          }
+        }
+        cm.replaceRange(text.join('\n'), curStart, curEnd);
+      },
+      global: function(cm, params) {
+        var argString = params.argString;
+        if (!argString) {
+          showConfirm(cm, 'Regular Expression missing from global');
+          return;
+        }
+        var lineStart = (params.line !== undefined) ? params.line : cm.firstLine();
+        var lineEnd = params.lineEnd || params.line || cm.lastLine();
+        var tokens = splitBySlash(argString);
+        var regexPart = argString, cmd;
+        if (tokens.length) {
+          regexPart = tokens[0];
+          cmd = tokens.slice(1, tokens.length).join('/');
+        }
+        if (regexPart) {
+          try {
+           updateSearchQuery(cm, regexPart, true /** ignoreCase */,
+             true /** smartCase */);
+          } catch (e) {
+           showConfirm(cm, 'Invalid regex: ' + regexPart);
+           return;
+          }
+        }
+        var query = getSearchState(cm).getQuery();
+        var matchedLines = [], content = '';
+        for (var i = lineStart; i <= lineEnd; i++) {
+          var matched = query.test(cm.getLine(i));
+          if (matched) {
+            matchedLines.push(i+1);
+            content+= cm.getLine(i) + '<br>';
+          }
+        }
+        if (!cmd) {
+          showConfirm(cm, content);
+          return;
+        }
+        var index = 0;
+        var nextCommand = function() {
+          if (index < matchedLines.length) {
+            var command = matchedLines[index] + cmd;
+            exCommandDispatcher.processCommand(cm, command, {
+              callback: nextCommand
+            });
+          }
+          index++;
+        };
+        nextCommand();
+      },
+      substitute: function(cm, params) {
+        if (!cm.getSearchCursor) {
+          throw new Error('Search feature not available. Requires searchcursor.js or ' +
+              'any other getSearchCursor implementation.');
+        }
+        var argString = params.argString;
+        var tokens = argString ? splitBySeparator(argString, argString[0]) : [];
+        var regexPart, replacePart = '', trailing, flagsPart, count;
+        var confirm = false; // Whether to confirm each replace.
+        var global = false; // True to replace all instances on a line, false to replace only 1.
+        if (tokens.length) {
+          regexPart = tokens[0];
+          replacePart = tokens[1];
+          if (regexPart && regexPart[regexPart.length - 1] === '$') {
+            regexPart = regexPart.slice(0, regexPart.length - 1) + '\\n';
+            replacePart = replacePart ? replacePart + '\n' : '\n';
+          }
+          if (replacePart !== undefined) {
+            if (getOption('pcre')) {
+              replacePart = unescapeRegexReplace(replacePart);
+            } else {
+              replacePart = translateRegexReplace(replacePart);
+            }
+            vimGlobalState.lastSubstituteReplacePart = replacePart;
+          }
+          trailing = tokens[2] ? tokens[2].split(' ') : [];
+        } else {
+          if (argString && argString.length) {
+            showConfirm(cm, 'Substitutions should be of the form ' +
+                ':s/pattern/replace/');
+            return;
+          }
+        }
+        if (trailing) {
+          flagsPart = trailing[0];
+          count = parseInt(trailing[1]);
+          if (flagsPart) {
+            if (flagsPart.indexOf('c') != -1) {
+              confirm = true;
+              flagsPart.replace('c', '');
+            }
+            if (flagsPart.indexOf('g') != -1) {
+              global = true;
+              flagsPart.replace('g', '');
+            }
+            regexPart = regexPart.replace(/\//g, "\\/") + '/' + flagsPart;
+          }
+        }
+        if (regexPart) {
+          try {
+            updateSearchQuery(cm, regexPart, true /** ignoreCase */,
+              true /** smartCase */);
+          } catch (e) {
+            showConfirm(cm, 'Invalid regex: ' + regexPart);
+            return;
+          }
+        }
+        replacePart = replacePart || vimGlobalState.lastSubstituteReplacePart;
+        if (replacePart === undefined) {
+          showConfirm(cm, 'No previous substitute regular expression');
+          return;
+        }
+        var state = getSearchState(cm);
+        var query = state.getQuery();
+        var lineStart = (params.line !== undefined) ? params.line : cm.getCursor().line;
+        var lineEnd = params.lineEnd || lineStart;
+        if (lineStart == cm.firstLine() && lineEnd == cm.lastLine()) {
+          lineEnd = Infinity;
+        }
+        if (count) {
+          lineStart = lineEnd;
+          lineEnd = lineStart + count - 1;
+        }
+        var startPos = clipCursorToContent(cm, Pos(lineStart, 0));
+        var cursor = cm.getSearchCursor(query, startPos);
+        doReplace(cm, confirm, global, lineStart, lineEnd, cursor, query, replacePart, params.callback);
+      },
+      redo: CodeMirror.commands.redo,
+      undo: CodeMirror.commands.undo,
+      write: function(cm) {
+        if (CodeMirror.commands.save) {
+          CodeMirror.commands.save(cm);
+        } else if (cm.save) {
+          cm.save();
+        }
+      },
+      nohlsearch: function(cm) {
+        clearSearchHighlight(cm);
+      },
+      yank: function (cm) {
+        var cur = copyCursor(cm.getCursor());
+        var line = cur.line;
+        var lineText = cm.getLine(line);
+        vimGlobalState.registerController.pushText(
+          '0', 'yank', lineText, true, true);
+      },
+      delmarks: function(cm, params) {
+        if (!params.argString || !trim(params.argString)) {
+          showConfirm(cm, 'Argument required');
+          return;
+        }
+
+        var state = cm.state.vim;
+        var stream = new CodeMirror.StringStream(trim(params.argString));
+        while (!stream.eol()) {
+          stream.eatSpace();
+          var count = stream.pos;
+
+          if (!stream.match(/[a-zA-Z]/, false)) {
+            showConfirm(cm, 'Invalid argument: ' + params.argString.substring(count));
+            return;
+          }
+
+          var sym = stream.next();
+          if (stream.match('-', true)) {
+            if (!stream.match(/[a-zA-Z]/, false)) {
+              showConfirm(cm, 'Invalid argument: ' + params.argString.substring(count));
+              return;
+            }
+
+            var startMark = sym;
+            var finishMark = stream.next();
+            if (isLowerCase(startMark) && isLowerCase(finishMark) ||
+                isUpperCase(startMark) && isUpperCase(finishMark)) {
+              var start = startMark.charCodeAt(0);
+              var finish = finishMark.charCodeAt(0);
+              if (start >= finish) {
+                showConfirm(cm, 'Invalid argument: ' + params.argString.substring(count));
+                return;
+              }
+              for (var j = 0; j <= finish - start; j++) {
+                var mark = String.fromCharCode(start + j);
+                delete state.marks[mark];
+              }
+            } else {
+              showConfirm(cm, 'Invalid argument: ' + startMark + '-');
+              return;
+            }
+          } else {
+            delete state.marks[sym];
+          }
+        }
+      }
+    };
+
+    var exCommandDispatcher = new ExCommandDispatcher();
+    function doReplace(cm, confirm, global, lineStart, lineEnd, searchCursor, query,
+        replaceWith, callback) {
+      cm.state.vim.exMode = true;
+      var done = false;
+      var lastPos = searchCursor.from();
+      function replaceAll() {
+        cm.operation(function() {
+          while (!done) {
+            replace();
+            next();
+          }
+          stop();
+        });
+      }
+      function replace() {
+        var text = cm.getRange(searchCursor.from(), searchCursor.to());
+        var newText = text.replace(query, replaceWith);
+        searchCursor.replace(newText);
+      }
+      function next() {
+        while(searchCursor.findNext() &&
+              isInRange(searchCursor.from(), lineStart, lineEnd)) {
+          if (!global && lastPos && searchCursor.from().line == lastPos.line) {
+            continue;
+          }
+          cm.scrollIntoView(searchCursor.from(), 30);
+          cm.setSelection(searchCursor.from(), searchCursor.to());
+          lastPos = searchCursor.from();
+          done = false;
+          return;
+        }
+        done = true;
+      }
+      function stop(close) {
+        if (close) { close(); }
+        cm.focus();
+        if (lastPos) {
+          cm.setCursor(lastPos);
+          var vim = cm.state.vim;
+          vim.exMode = false;
+          vim.lastHPos = vim.lastHSPos = lastPos.ch;
+        }
+        if (callback) { callback(); }
+      }
+      function onPromptKeyDown(e, _value, close) {
+        CodeMirror.e_stop(e);
+        var keyName = CodeMirror.keyName(e);
+        switch (keyName) {
+          case 'Y':
+            replace(); next(); break;
+          case 'N':
+            next(); break;
+          case 'A':
+            var savedCallback = callback;
+            callback = undefined;
+            cm.operation(replaceAll);
+            callback = savedCallback;
+            break;
+          case 'L':
+            replace();
+          case 'Q':
+          case 'Esc':
+          case 'Ctrl-C':
+          case 'Ctrl-[':
+            stop(close);
+            break;
+        }
+        if (done) { stop(close); }
+        return true;
+      }
+      next();
+      if (done) {
+        showConfirm(cm, 'No matches for ' + query.source);
+        return;
+      }
+      if (!confirm) {
+        replaceAll();
+        if (callback) { callback(); }
+        return;
+      }
+      showPrompt(cm, {
+        prefix: 'replace with <strong>' + replaceWith + '</strong> (y/n/a/q/l)',
+        onKeyDown: onPromptKeyDown
+      });
+    }
+
+    CodeMirror.keyMap.vim = {
+      attach: attachVimMap,
+      detach: detachVimMap,
+      call: cmKey
+    };
+
+    function exitInsertMode(cm) {
+      var vim = cm.state.vim;
+      var macroModeState = vimGlobalState.macroModeState;
+      var insertModeChangeRegister = vimGlobalState.registerController.getRegister('.');
+      var isPlaying = macroModeState.isPlaying;
+      var lastChange = macroModeState.lastInsertModeChanges;
+      if (!isPlaying) {
+        cm.off('change', onChange);
+        CodeMirror.off(cm.getInputField(), 'keydown', onKeyEventTargetKeyDown);
+      }
+      if (!isPlaying && vim.insertModeRepeat > 1) {
+        repeatLastEdit(cm, vim, vim.insertModeRepeat - 1,
+            true /** repeatForInsert */);
+        vim.lastEditInputState.repeatOverride = vim.insertModeRepeat;
+      }
+      delete vim.insertModeRepeat;
+      vim.insertMode = false;
+      cm.setCursor(cm.getCursor().line, cm.getCursor().ch-1);
+      cm.setOption('keyMap', 'vim');
+      cm.setOption('disableInput', true);
+      cm.toggleOverwrite(false); // exit replace mode if we were in it.
+      insertModeChangeRegister.setText(lastChange.changes.join(''));
+      CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"});
+      if (macroModeState.isRecording) {
+        logInsertModeChange(macroModeState);
+      }
+    }
+
+    function _mapCommand(command) {
+      defaultKeymap.unshift(command);
+    }
+
+    function mapCommand(keys, type, name, args, extra) {
+      var command = {keys: keys, type: type};
+      command[type] = name;
+      command[type + "Args"] = args;
+      for (var key in extra)
+        command[key] = extra[key];
+      _mapCommand(command);
+    }
+    defineOption('insertModeEscKeysTimeout', 200, 'number');
+
+    CodeMirror.keyMap['vim-insert'] = {
+      'Ctrl-N': 'autocomplete',
+      'Ctrl-P': 'autocomplete',
+      'Enter': function(cm) {
+        var fn = CodeMirror.commands.newlineAndIndentContinueComment ||
+            CodeMirror.commands.newlineAndIndent;
+        fn(cm);
+      },
+      fallthrough: ['default'],
+      attach: attachVimMap,
+      detach: detachVimMap,
+      call: cmKey
+    };
+
+    CodeMirror.keyMap['vim-replace'] = {
+      'Backspace': 'goCharLeft',
+      fallthrough: ['vim-insert'],
+      attach: attachVimMap,
+      detach: detachVimMap,
+      call: cmKey
+    };
+
+    function executeMacroRegister(cm, vim, macroModeState, registerName) {
+      var register = vimGlobalState.registerController.getRegister(registerName);
+      if (registerName == ':') {
+        if (register.keyBuffer[0]) {
+          exCommandDispatcher.processCommand(cm, register.keyBuffer[0]);
+        }
+        macroModeState.isPlaying = false;
+        return;
+      }
+      var keyBuffer = register.keyBuffer;
+      var imc = 0;
+      macroModeState.isPlaying = true;
+      macroModeState.replaySearchQueries = register.searchQueries.slice(0);
+      for (var i = 0; i < keyBuffer.length; i++) {
+        var text = keyBuffer[i];
+        var match, key;
+        while (text) {
+          match = (/<\w+-.+?>|<\w+>|./).exec(text);
+          key = match[0];
+          text = text.substring(match.index + key.length);
+          CodeMirror.Vim.handleKey(cm, key, 'macro');
+          if (vim.insertMode) {
+            var changes = register.insertModeChanges[imc++].changes;
+            vimGlobalState.macroModeState.lastInsertModeChanges.changes =
+                changes;
+            repeatInsertModeChanges(cm, changes, 1);
+            exitInsertMode(cm);
+          }
+        }
+      }
+      macroModeState.isPlaying = false;
+    }
+
+    function logKey(macroModeState, key) {
+      if (macroModeState.isPlaying) { return; }
+      var registerName = macroModeState.latestRegister;
+      var register = vimGlobalState.registerController.getRegister(registerName);
+      if (register) {
+        register.pushText(key);
+      }
+    }
+
+    function logInsertModeChange(macroModeState) {
+      if (macroModeState.isPlaying) { return; }
+      var registerName = macroModeState.latestRegister;
+      var register = vimGlobalState.registerController.getRegister(registerName);
+      if (register && register.pushInsertModeChanges) {
+        register.pushInsertModeChanges(macroModeState.lastInsertModeChanges);
+      }
+    }
+
+    function logSearchQuery(macroModeState, query) {
+      if (macroModeState.isPlaying) { return; }
+      var registerName = macroModeState.latestRegister;
+      var register = vimGlobalState.registerController.getRegister(registerName);
+      if (register && register.pushSearchQuery) {
+        register.pushSearchQuery(query);
+      }
+    }
+    function onChange(cm, changeObj) {
+      var macroModeState = vimGlobalState.macroModeState;
+      var lastChange = macroModeState.lastInsertModeChanges;
+      if (!macroModeState.isPlaying) {
+        while(changeObj) {
+          lastChange.expectCursorActivityForChange = true;
+          if (lastChange.ignoreCount > 1) {
+            lastChange.ignoreCount--;
+          } else if (changeObj.origin == '+input' || changeObj.origin == 'paste'
+              || changeObj.origin === undefined /* only in testing */) {
+            var selectionCount = cm.listSelections().length;
+            if (selectionCount > 1)
+              lastChange.ignoreCount = selectionCount;
+            var text = changeObj.text.join('\n');
+            if (lastChange.maybeReset) {
+              lastChange.changes = [];
+              lastChange.maybeReset = false;
+            }
+            if (cm.state.overwrite && !/\n/.test(text)) {
+                lastChange.changes.push([text]);
+            } else {
+                lastChange.changes.push(text);
+            }
+          }
+          changeObj = changeObj.next;
+        }
+      }
+    }
+    function onCursorActivity(cm) {
+      var vim = cm.state.vim;
+      if (vim.insertMode) {
+        var macroModeState = vimGlobalState.macroModeState;
+        if (macroModeState.isPlaying) { return; }
+        var lastChange = macroModeState.lastInsertModeChanges;
+        if (lastChange.expectCursorActivityForChange) {
+          lastChange.expectCursorActivityForChange = false;
+        } else {
+          lastChange.maybeReset = true;
+        }
+      } else if (!cm.curOp.isVimOp) {
+        handleExternalSelection(cm, vim);
+      }
+      if (vim.visualMode) {
+        updateFakeCursor(cm);
+      }
+    }
+    function updateFakeCursor(cm) {
+      var vim = cm.state.vim;
+      var from = clipCursorToContent(cm, copyCursor(vim.sel.head));
+      var to = offsetCursor(from, 0, 1);
+      if (vim.fakeCursor) {
+        vim.fakeCursor.clear();
+      }
+      vim.fakeCursor = cm.markText(from, to, {className: 'cm-animate-fat-cursor'});
+    }
+    function handleExternalSelection(cm, vim) {
+      var anchor = cm.getCursor('anchor');
+      var head = cm.getCursor('head');
+      if (vim.visualMode && !cm.somethingSelected()) {
+        exitVisualMode(cm, false);
+      } else if (!vim.visualMode && !vim.insertMode && cm.somethingSelected()) {
+        vim.visualMode = true;
+        vim.visualLine = false;
+        CodeMirror.signal(cm, "vim-mode-change", {mode: "visual"});
+      }
+      if (vim.visualMode) {
+        var headOffset = !cursorIsBefore(head, anchor) ? -1 : 0;
+        var anchorOffset = cursorIsBefore(head, anchor) ? -1 : 0;
+        head = offsetCursor(head, 0, headOffset);
+        anchor = offsetCursor(anchor, 0, anchorOffset);
+        vim.sel = {
+          anchor: anchor,
+          head: head
+        };
+        updateMark(cm, vim, '<', cursorMin(head, anchor));
+        updateMark(cm, vim, '>', cursorMax(head, anchor));
+      } else if (!vim.insertMode) {
+        vim.lastHPos = cm.getCursor().ch;
+      }
+    }
+    function InsertModeKey(keyName) {
+      this.keyName = keyName;
+    }
+    function onKeyEventTargetKeyDown(e) {
+      var macroModeState = vimGlobalState.macroModeState;
+      var lastChange = macroModeState.lastInsertModeChanges;
+      var keyName = CodeMirror.keyName(e);
+      if (!keyName) { return; }
+      function onKeyFound() {
+        if (lastChange.maybeReset) {
+          lastChange.changes = [];
+          lastChange.maybeReset = false;
+        }
+        lastChange.changes.push(new InsertModeKey(keyName));
+        return true;
+      }
+      if (keyName.indexOf('Delete') != -1 || keyName.indexOf('Backspace') != -1) {
+        CodeMirror.lookupKey(keyName, 'vim-insert', onKeyFound);
+      }
+    }
+    function repeatLastEdit(cm, vim, repeat, repeatForInsert) {
+      var macroModeState = vimGlobalState.macroModeState;
+      macroModeState.isPlaying = true;
+      var isAction = !!vim.lastEditActionCommand;
+      var cachedInputState = vim.inputState;
+      function repeatCommand() {
+        if (isAction) {
+          commandDispatcher.processAction(cm, vim, vim.lastEditActionCommand);
+        } else {
+          commandDispatcher.evalInput(cm, vim);
+        }
+      }
+      function repeatInsert(repeat) {
+        if (macroModeState.lastInsertModeChanges.changes.length > 0) {
+          repeat = !vim.lastEditActionCommand ? 1 : repeat;
+          var changeObject = macroModeState.lastInsertModeChanges;
+          repeatInsertModeChanges(cm, changeObject.changes, repeat);
+        }
+      }
+      vim.inputState = vim.lastEditInputState;
+      if (isAction && vim.lastEditActionCommand.interlaceInsertRepeat) {
+        for (var i = 0; i < repeat; i++) {
+          repeatCommand();
+          repeatInsert(1);
+        }
+      } else {
+        if (!repeatForInsert) {
+          repeatCommand();
+        }
+        repeatInsert(repeat);
+      }
+      vim.inputState = cachedInputState;
+      if (vim.insertMode && !repeatForInsert) {
+        exitInsertMode(cm);
+      }
+      macroModeState.isPlaying = false;
+    }
+
+    function repeatInsertModeChanges(cm, changes, repeat) {
+      function keyHandler(binding) {
+        if (typeof binding == 'string') {
+          CodeMirror.commands[binding](cm);
+        } else {
+          binding(cm);
+        }
+        return true;
+      }
+      var head = cm.getCursor('head');
+      var inVisualBlock = vimGlobalState.macroModeState.lastInsertModeChanges.inVisualBlock;
+      if (inVisualBlock) {
+        var vim = cm.state.vim;
+        var lastSel = vim.lastSelection;
+        var offset = getOffset(lastSel.anchor, lastSel.head);
+        selectForInsert(cm, head, offset.line + 1);
+        repeat = cm.listSelections().length;
+        cm.setCursor(head);
+      }
+      for (var i = 0; i < repeat; i++) {
+        if (inVisualBlock) {
+          cm.setCursor(offsetCursor(head, i, 0));
+        }
+        for (var j = 0; j < changes.length; j++) {
+          var change = changes[j];
+          if (change instanceof InsertModeKey) {
+            CodeMirror.lookupKey(change.keyName, 'vim-insert', keyHandler);
+          } else if (typeof change == "string") {
+            var cur = cm.getCursor();
+            cm.replaceRange(change, cur, cur);
+          } else {
+            var start = cm.getCursor();
+            var end = offsetCursor(start, 0, change[0].length);
+            cm.replaceRange(change[0], start, end);
+          }
+        }
+      }
+      if (inVisualBlock) {
+        cm.setCursor(offsetCursor(head, 0, 1));
+      }
+    }
+
+    resetVimGlobalState();
+  CodeMirror.Vim = Vim();
+
+  Vim = CodeMirror.Vim;
+
+  var specialKey = {'return':'CR',backspace:'BS','delete':'Del',esc:'Esc',
+    left:'Left',right:'Right',up:'Up',down:'Down',space: 'Space',
+    home:'Home',end:'End',pageup:'PageUp',pagedown:'PageDown', enter: 'CR'
+  };
+  function lookupKey(hashId, key, e) {
+    if (key.length > 1 && key[0] == "n") {
+      key = key.replace("numpad", "");
+    }
+    key = specialKey[key] || key;
+    var name = '';
+    if (e.ctrlKey) { name += 'C-'; }
+    if (e.altKey) { name += 'A-'; }
+    if ((name || key.length > 1) && e.shiftKey) { name += 'S-'; }
+
+    name += key;
+    if (name.length > 1) { name = '<' + name + '>'; }
+    return name;
+  }
+  var handleKey = Vim.handleKey.bind(Vim);
+  Vim.handleKey = function(cm, key, origin) {
+    return cm.operation(function() {
+      return handleKey(cm, key, origin);
+    }, true);
+  }
+  function cloneVimState(state) {
+    var n = new state.constructor();
+    Object.keys(state).forEach(function(key) {
+      var o = state[key];
+      if (Array.isArray(o))
+        o = o.slice();
+      else if (o && typeof o == "object" && o.constructor != Object)
+        o = cloneVimState(o);
+      n[key] = o;
+    });
+    if (state.sel) {
+      n.sel = {
+        head: state.sel.head && copyCursor(state.sel.head),
+        anchor: state.sel.anchor && copyCursor(state.sel.anchor)
+      };
+    }
+    return n;
+  }
+  function multiSelectHandleKey(cm, key, origin) {
+    var isHandled = false;
+    var vim = Vim.maybeInitVimState_(cm);
+    var visualBlock = vim.visualBlock || vim.wasInVisualBlock;
+    if (vim.wasInVisualBlock && !cm.ace.inMultiSelectMode) {
+      vim.wasInVisualBlock = false;
+    } else if (cm.ace.inMultiSelectMode && vim.visualBlock) {
+       vim.wasInVisualBlock = true;
+    }
+    
+    if (key == '<Esc>' && !vim.insertMode && !vim.visualMode && cm.ace.inMultiSelectMode) {
+      cm.ace.exitMultiSelectMode();
+    } else if (visualBlock || !cm.ace.inMultiSelectMode || cm.ace.inVirtualSelectionMode) {
+      isHandled = Vim.handleKey(cm, key, origin);
+    } else {
+      var old = cloneVimState(vim);
+      cm.operation(function() {
+        cm.ace.forEachSelection(function() {
+          var sel = cm.ace.selection;
+          cm.state.vim.lastHPos = sel.$desiredColumn == null ? sel.lead.column : sel.$desiredColumn;
+          var head = cm.getCursor("head");
+          var anchor = cm.getCursor("anchor");
+          var headOffset = !cursorIsBefore(head, anchor) ? -1 : 0;
+          var anchorOffset = cursorIsBefore(head, anchor) ? -1 : 0;
+          head = offsetCursor(head, 0, headOffset);
+          anchor = offsetCursor(anchor, 0, anchorOffset);
+          cm.state.vim.sel.head = head;
+          cm.state.vim.sel.anchor = anchor;
+          
+          isHandled = handleKey(cm, key, origin);
+          sel.$desiredColumn = cm.state.vim.lastHPos == -1 ? null : cm.state.vim.lastHPos;
+          if (cm.virtualSelectionMode()) {
+            cm.state.vim = cloneVimState(old);
+          }
+        });
+        if (cm.curOp.cursorActivity && !isHandled)
+          cm.curOp.cursorActivity = false;
+      }, true);
+    }
+    if (isHandled && !vim.visualMode && !vim.insert)
+      handleExternalSelection(cm, vim);
+    return isHandled;
+  }
+  exports.CodeMirror = CodeMirror;
+  var getVim = Vim.maybeInitVimState_;
+  exports.handler = {
+    $id: "ace/keyboard/vim",
+    drawCursor: function(element, pixelPos, config, sel, session) {
+      var vim = this.state.vim || {};
+      var w = config.characterWidth;
+      var h = config.lineHeight;
+      var top = pixelPos.top;
+      var left = pixelPos.left;
+      if (!vim.insertMode) {
+        var isbackwards = !sel.cursor 
+            ? session.selection.isBackwards() || session.selection.isEmpty()
+            : Range.comparePoints(sel.cursor, sel.start) <= 0;
+        if (!isbackwards && left > w)
+          left -= w;
+      }     
+      if (!vim.insertMode && vim.status) {
+        h = h / 2;
+        top += h;
+      }
+      dom.translate(element, left, top);
+      dom.setStyle(element.style, "width", w + "px");
+      dom.setStyle(element.style, "height", h + "px");
+    },
+    handleKeyboard: function(data, hashId, key, keyCode, e) {
+      var editor = data.editor;
+      var cm = editor.state.cm;
+      var vim = getVim(cm);
+      if (keyCode == -1) return;
+      if (!vim.insertMode) {
+        if (hashId == -1) {
+          if (key.charCodeAt(0) > 0xFF) {
+            if (data.inputKey) {
+              key = data.inputKey;
+              if (key && data.inputHash == 4)
+                key = key.toUpperCase();
+            }
+          }
+          data.inputChar = key;
+        }
+        else if (hashId == 4 || hashId == 0) {
+          if (data.inputKey == key && data.inputHash == hashId && data.inputChar) {
+            key = data.inputChar;
+            hashId = -1
+          }
+          else {
+            data.inputChar = null;
+            data.inputKey = key;
+            data.inputHash = hashId;
+          }
+        }
+        else {
+          data.inputChar = data.inputKey = null;
+        }
+      }
+      if (key == "c" && hashId == 1) { // key == "ctrl-c"
+        if (!useragent.isMac && editor.getCopyText()) {
+          editor.once("copy", function() {
+            editor.selection.clearSelection();
+          });
+          return {command: "null", passEvent: true};
+        }
+      }
+      
+      if (key == "esc" && !vim.insertMode && !vim.visualMode && !cm.ace.inMultiSelectMode) {
+        var searchState = getSearchState(cm);
+        var overlay = searchState.getOverlay();
+        if (overlay) cm.removeOverlay(overlay);
+      }
+      
+      if (hashId == -1 || hashId & 1 || hashId === 0 && key.length > 1) {
+        var insertMode = vim.insertMode;
+        var name = lookupKey(hashId, key, e || {});
+        if (vim.status == null)
+          vim.status = "";
+        var isHandled = multiSelectHandleKey(cm, name, 'user');
+        vim = getVim(cm); // may be changed by multiSelectHandleKey
+        if (isHandled && vim.status != null)
+          vim.status += name;
+        else if (vim.status == null)
+          vim.status = "";
+        cm._signal("changeStatus");
+        if (!isHandled && (hashId != -1 || insertMode))
+          return;
+        return {command: "null", passEvent: !isHandled};
+      }
+    },
+    attach: function(editor) {
+      if (!editor.state) editor.state = {};
+      var cm = new CodeMirror(editor);
+      editor.state.cm = cm;
+      editor.$vimModeHandler = this;
+      CodeMirror.keyMap.vim.attach(cm);
+      getVim(cm).status = null;
+      cm.on('vim-command-done', function() {
+        if (cm.virtualSelectionMode()) return;
+        getVim(cm).status = null;
+        cm.ace._signal("changeStatus");
+        cm.ace.session.markUndoGroup();
+      });
+      cm.on("changeStatus", function() {
+        cm.ace.renderer.updateCursor();
+        cm.ace._signal("changeStatus");
+      });
+      cm.on("vim-mode-change", function() {
+        if (cm.virtualSelectionMode()) return;
+        updateInputMode();
+        cm._signal("changeStatus");
+      });
+      function updateInputMode() {
+        var isIntsert = getVim(cm).insertMode;
+        cm.ace.renderer.setStyle("normal-mode", !isIntsert);
+        editor.textInput.setCommandMode(!isIntsert);
+        editor.renderer.$keepTextAreaAtCursor = isIntsert;
+        editor.renderer.$blockCursor = !isIntsert;
+      }
+      updateInputMode();
+      editor.renderer.$cursorLayer.drawCursor = this.drawCursor.bind(cm);
+    },
+    detach: function(editor) {
+      var cm = editor.state.cm;
+      CodeMirror.keyMap.vim.detach(cm);
+      cm.destroy();
+      editor.state.cm = null;
+      editor.$vimModeHandler = null;
+      editor.renderer.$cursorLayer.drawCursor = null;
+      editor.renderer.setStyle("normal-mode", false);
+      editor.textInput.setCommandMode(false);
+      editor.renderer.$keepTextAreaAtCursor = true;
+    },
+    getStatusText: function(editor) {
+      var cm = editor.state.cm;
+      var vim = getVim(cm);
+      if (vim.insertMode)
+        return "INSERT";
+      var status = "";
+      if (vim.visualMode) {
+        status += "VISUAL";
+        if (vim.visualLine)
+          status += " LINE";
+        if (vim.visualBlock)
+          status += " BLOCK";
+      }
+      if (vim.status)
+        status += (status ? " " : "") + vim.status;
+      return status;
+    }
+  };
+  Vim.defineOption({
+    name: "wrap",
+    set: function(value, cm) {
+      if (cm) {cm.ace.setOption("wrap", value)}
+    },
+    type: "boolean"
+  }, false);
+  Vim.defineEx('write', 'w', function() {
+    console.log(':write is not implemented')
+  });
+  defaultKeymap.push(
+    { keys: 'zc', type: 'action', action: 'fold', actionArgs: { open: false } },
+    { keys: 'zC', type: 'action', action: 'fold', actionArgs: { open: false, all: true } },
+    { keys: 'zo', type: 'action', action: 'fold', actionArgs: { open: true } },
+    { keys: 'zO', type: 'action', action: 'fold', actionArgs: { open: true, all: true } },
+    { keys: 'za', type: 'action', action: 'fold', actionArgs: { toggle: true } },
+    { keys: 'zA', type: 'action', action: 'fold', actionArgs: { toggle: true, all: true } },
+    { keys: 'zf', type: 'action', action: 'fold', actionArgs: { open: true, all: true } },
+    { keys: 'zd', type: 'action', action: 'fold', actionArgs: { open: true, all: true } },
+    
+    { keys: '<C-A-k>', type: 'action', action: 'aceCommand', actionArgs: { name: "addCursorAbove" } },
+    { keys: '<C-A-j>', type: 'action', action: 'aceCommand', actionArgs: { name: "addCursorBelow" } },
+    { keys: '<C-A-S-k>', type: 'action', action: 'aceCommand', actionArgs: { name: "addCursorAboveSkipCurrent" } },
+    { keys: '<C-A-S-j>', type: 'action', action: 'aceCommand', actionArgs: { name: "addCursorBelowSkipCurrent" } },
+    { keys: '<C-A-h>', type: 'action', action: 'aceCommand', actionArgs: { name: "selectMoreBefore" } },
+    { keys: '<C-A-l>', type: 'action', action: 'aceCommand', actionArgs: { name: "selectMoreAfter" } },
+    { keys: '<C-A-S-h>', type: 'action', action: 'aceCommand', actionArgs: { name: "selectNextBefore" } },
+    { keys: '<C-A-S-l>', type: 'action', action: 'aceCommand', actionArgs: { name: "selectNextAfter" } }
+  );
+  actions.aceCommand = function(cm, actionArgs, vim) {
+    cm.vimCmd = actionArgs;
+    if (cm.ace.inVirtualSelectionMode)
+      cm.ace.on("beforeEndOperation", delayedExecAceCommand);
+    else
+      delayedExecAceCommand(null, cm.ace);
+  };
+  function delayedExecAceCommand(op, ace) {
+    ace.off("beforeEndOperation", delayedExecAceCommand);
+    var cmd = ace.state.cm.vimCmd;
+    if (cmd) {
+      ace.execCommand(cmd.exec ? cmd : cmd.name, cmd.args);
+    }
+    ace.curOp = ace.prevOp;
+  }
+  actions.fold = function(cm, actionArgs, vim) {
+    cm.ace.execCommand(['toggleFoldWidget', 'toggleFoldWidget', 'foldOther', 'unfoldall'
+      ][(actionArgs.all ? 2 : 0) + (actionArgs.open ? 1 : 0)]);
+  };
+
+  exports.handler.defaultKeymap = defaultKeymap;
+  exports.handler.actions = actions;
+  exports.Vim = Vim;
+  
+  Vim.map("Y", "yy", "normal");
+});
+                (function() {
+                    ace.require(["ace/keyboard/vim"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 222 - 0
services/web/public/js/ace-1.4.3/mode-abap.js

@@ -0,0 +1,222 @@
+ace.define("ace/mode/abap_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var AbapHighlightRules = function() {
+
+    var keywordMapper = this.createKeywordMapper({
+        "variable.language": "this",
+        "keyword": 
+            "ADD ALIAS ALIASES ASCENDING ASSERT ASSIGN ASSIGNING AT BACK" +
+            " CALL CASE CATCH CHECK CLASS CLEAR CLOSE CNT COLLECT COMMIT COMMUNICATION COMPUTE CONCATENATE CONDENSE CONSTANTS CONTINUE CONTROLS CONVERT CREATE CURRENCY" +
+            " DATA DEFINE DEFINITION DEFERRED DELETE DESCENDING DESCRIBE DETAIL DIVIDE DO" +
+            " ELSE ELSEIF ENDAT ENDCASE ENDCLASS ENDDO ENDEXEC ENDFORM ENDFUNCTION ENDIF ENDIFEND ENDINTERFACE ENDLOOP ENDMETHOD ENDMODULE ENDON ENDPROVIDE ENDSELECT ENDTRY ENDWHILE EVENT EVENTS EXEC EXIT EXPORT EXPORTING EXTRACT" +
+            " FETCH FIELDS FORM FORMAT FREE FROM FUNCTION" +
+            " GENERATE GET" +
+            " HIDE" +
+            " IF IMPORT IMPORTING INDEX INFOTYPES INITIALIZATION INTERFACE INTERFACES INPUT INSERT IMPLEMENTATION" +
+            " LEAVE LIKE LINE LOAD LOCAL LOOP" +
+            " MESSAGE METHOD METHODS MODIFY MODULE MOVE MULTIPLY" +
+            " ON OVERLAY OPTIONAL OTHERS" +
+            " PACK PARAMETERS PERFORM POSITION PROGRAM PROVIDE PUT" +
+            " RAISE RANGES READ RECEIVE RECEIVING REDEFINITION REFERENCE REFRESH REJECT REPLACE REPORT RESERVE RESTORE RETURN RETURNING ROLLBACK" +
+            " SCAN SCROLL SEARCH SELECT SET SHIFT SKIP SORT SORTED SPLIT STANDARD STATICS STEP STOP SUBMIT SUBTRACT SUM SUMMARY SUPPRESS" +
+            " TABLES TIMES TRANSFER TRANSLATE TRY TYPE TYPES" +
+            " UNASSIGN ULINE UNPACK UPDATE" +
+            " WHEN WHILE WINDOW WRITE" +
+            " OCCURS STRUCTURE OBJECT PROPERTY" +
+            " CASTING APPEND RAISING VALUE COLOR" +
+            " CHANGING EXCEPTION EXCEPTIONS DEFAULT CHECKBOX COMMENT" +
+            " ID NUMBER FOR TITLE OUTPUT" +
+            " WITH EXIT USING" +
+            " INTO WHERE GROUP BY HAVING ORDER BY SINGLE" +
+            " APPENDING CORRESPONDING FIELDS OF TABLE" +
+            " LEFT RIGHT OUTER INNER JOIN AS CLIENT SPECIFIED BYPASSING BUFFER UP TO ROWS CONNECTING" +
+            " EQ NE LT LE GT GE NOT AND OR XOR IN LIKE BETWEEN",
+        "constant.language": 
+            "TRUE FALSE NULL SPACE",
+        "support.type": 
+            "c n i p f d t x string xstring decfloat16 decfloat34",
+        "keyword.operator":
+            "abs sign ceil floor trunc frac acos asin atan cos sin tan" +
+            " abapOperator cosh sinh tanh exp log log10 sqrt" +
+            " strlen xstrlen charlen numofchar dbmaxlen lines" 
+    }, "text", true, " ");
+
+    var compoundKeywords = "WITH\\W+(?:HEADER\\W+LINE|FRAME|KEY)|NO\\W+STANDARD\\W+PAGE\\W+HEADING|"+
+        "EXIT\\W+FROM\\W+STEP\\W+LOOP|BEGIN\\W+OF\\W+(?:BLOCK|LINE)|BEGIN\\W+OF|"+
+        "END\\W+OF\\W+(?:BLOCK|LINE)|END\\W+OF|NO\\W+INTERVALS|"+
+        "RESPECTING\\W+BLANKS|SEPARATED\\W+BY|USING\\W+(?:EDIT\\W+MASK)|"+
+        "WHERE\\W+(?:LINE)|RADIOBUTTON\\W+GROUP|REF\\W+TO|"+
+        "(?:PUBLIC|PRIVATE|PROTECTED)(?:\\W+SECTION)?|DELETING\\W+(?:TRAILING|LEADING)"+
+        "(?:ALL\\W+OCCURRENCES)|(?:FIRST|LAST)\\W+OCCURRENCE|INHERITING\\W+FROM|"+
+        "LINE-COUNT|ADD-CORRESPONDING|AUTHORITY-CHECK|BREAK-POINT|CLASS-DATA|CLASS-METHODS|"+
+        "CLASS-METHOD|DIVIDE-CORRESPONDING|EDITOR-CALL|END-OF-DEFINITION|END-OF-PAGE|END-OF-SELECTION|"+
+        "FIELD-GROUPS|FIELD-SYMBOLS|FUNCTION-POOL|MOVE-CORRESPONDING|MULTIPLY-CORRESPONDING|NEW-LINE|"+
+        "NEW-PAGE|NEW-SECTION|PRINT-CONTROL|RP-PROVIDE-FROM-LAST|SELECT-OPTIONS|SELECTION-SCREEN|"+
+        "START-OF-SELECTION|SUBTRACT-CORRESPONDING|SYNTAX-CHECK|SYNTAX-TRACE|TOP-OF-PAGE|TYPE-POOL|"+
+        "TYPE-POOLS|LINE-SIZE|LINE-COUNT|MESSAGE-ID|DISPLAY-MODE|READ(?:-ONLY)?|"+
+        "IS\\W+(?:NOT\\W+)?(?:ASSIGNED|BOUND|INITIAL|SUPPLIED)";
+     
+    this.$rules = {
+        "start" : [
+            {token : "string", regex : "`", next  : "string"},
+            {token : "string", regex : "'", next  : "qstring"},
+            {token : "doc.comment", regex : /^\*.+/},
+            {token : "comment",  regex : /".+$/},
+            {token : "invalid", regex: "\\.{2,}"},
+            {token : "keyword.operator", regex: /\W[\-+%=<>*]\W|\*\*|[~:,\.&$]|->*?|=>/},
+            {token : "paren.lparen", regex : "[\\[({]"},
+            {token : "paren.rparen", regex : "[\\])}]"},
+            {token : "constant.numeric", regex: "[+-]?\\d+\\b"},
+            {token : "variable.parameter", regex : /sy|pa?\d\d\d\d\|t\d\d\d\.|innnn/}, 
+            {token : "keyword", regex : compoundKeywords}, 
+            {token : "variable.parameter", regex : /\w+-\w[\-\w]*/},
+            {token : keywordMapper, regex : "\\b\\w+\\b"},
+            {caseInsensitive: true}
+        ],
+        "qstring" : [
+            {token : "constant.language.escape",   regex : "''"},
+            {token : "string", regex : "'",     next  : "start"},
+            {defaultToken : "string"}
+        ],
+        "string" : [
+            {token : "constant.language.escape",   regex : "``"},
+            {token : "string", regex : "`",     next  : "start"},
+            {defaultToken : "string"}
+        ]
+    };
+};
+oop.inherits(AbapHighlightRules, TextHighlightRules);
+
+exports.AbapHighlightRules = AbapHighlightRules;
+});
+
+ace.define("ace/mode/folding/coffee",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var BaseFoldMode = require("./fold_mode").FoldMode;
+var Range = require("../../range").Range;
+
+var FoldMode = exports.FoldMode = function() {};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+
+    this.getFoldWidgetRange = function(session, foldStyle, row) {
+        var range = this.indentationBlock(session, row);
+        if (range)
+            return range;
+
+        var re = /\S/;
+        var line = session.getLine(row);
+        var startLevel = line.search(re);
+        if (startLevel == -1 || line[startLevel] != "#")
+            return;
+
+        var startColumn = line.length;
+        var maxRow = session.getLength();
+        var startRow = row;
+        var endRow = row;
+
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var level = line.search(re);
+
+            if (level == -1)
+                continue;
+
+            if (line[level] != "#")
+                break;
+
+            endRow = row;
+        }
+
+        if (endRow > startRow) {
+            var endColumn = session.getLine(endRow).length;
+            return new Range(startRow, startColumn, endRow, endColumn);
+        }
+    };
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+        var indent = line.search(/\S/);
+        var next = session.getLine(row + 1);
+        var prev = session.getLine(row - 1);
+        var prevIndent = prev.search(/\S/);
+        var nextIndent = next.search(/\S/);
+
+        if (indent == -1) {
+            session.foldWidgets[row - 1] = prevIndent!= -1 && prevIndent < nextIndent ? "start" : "";
+            return "";
+        }
+        if (prevIndent == -1) {
+            if (indent == nextIndent && line[indent] == "#" && next[indent] == "#") {
+                session.foldWidgets[row - 1] = "";
+                session.foldWidgets[row + 1] = "";
+                return "start";
+            }
+        } else if (prevIndent == indent && line[indent] == "#" && prev[indent] == "#") {
+            if (session.getLine(row - 2).search(/\S/) == -1) {
+                session.foldWidgets[row - 1] = "start";
+                session.foldWidgets[row + 1] = "";
+                return "";
+            }
+        }
+
+        if (prevIndent!= -1 && prevIndent < indent)
+            session.foldWidgets[row - 1] = "start";
+        else
+            session.foldWidgets[row - 1] = "";
+
+        if (indent < nextIndent)
+            return "start";
+        else
+            return "";
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/abap",[], function(require, exports, module) {
+"use strict";
+
+var Rules = require("./abap_highlight_rules").AbapHighlightRules;
+var FoldMode = require("./folding/coffee").FoldMode;
+var Range = require("../range").Range;
+var TextMode = require("./text").Mode;
+var oop = require("../lib/oop");
+
+function Mode() {
+    this.HighlightRules = Rules;
+    this.foldingRules = new FoldMode();
+}
+
+oop.inherits(Mode, TextMode);
+
+(function() {
+    
+    this.lineCommentStart = '"';
+    
+    this.getNextLineIndent = function(state, line, tab) {
+        var indent = this.$getIndent(line);
+        return indent;
+    };    
+    
+    this.$id = "ace/mode/abap";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+
+});
+                (function() {
+                    ace.require(["ace/mode/abap"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 269 - 0
services/web/public/js/ace-1.4.3/mode-abc.js

@@ -0,0 +1,269 @@
+ace.define("ace/mode/abc_highlight_rules",[], function (require, exports, module) {
+    "use strict";
+
+    var oop = require("../lib/oop");
+    var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+    var ABCHighlightRules = function () {
+
+        this.$rules = {
+            start: [
+                {
+                    token: ['zupfnoter.information.comment.line.percentage', 'information.keyword', 'in formation.keyword.embedded'],
+                    regex: '(%%%%)(hn\\.[a-z]*)(.*)',
+                    comment: 'Instruction Comment'
+                },
+                {
+                    token: ['information.comment.line.percentage', 'information.keyword.embedded'],
+                    regex: '(%%)(.*)',
+                    comment: 'Instruction Comment'
+                },
+
+                {
+                    token: 'comment.line.percentage',
+                    regex: '%.*',
+                    comment: 'Comments'
+                },
+
+                {
+                    token: 'barline.keyword.operator',
+                    regex: '[\\[:]*[|:][|\\]:]*(?:\\[?[0-9]+)?|\\[[0-9]+',
+                    comment: 'Bar lines'
+                },
+                {
+                    token: ['information.keyword.embedded', 'information.argument.string.unquoted'],
+                    regex: '(\\[[A-Za-z]:)([^\\]]*\\])',
+                    comment: 'embedded Header lines'
+                },
+                {
+                    token: ['information.keyword', 'information.argument.string.unquoted'],
+                    regex: '^([A-Za-z]:)([^%\\\\]*)',
+                    comment: 'Header lines'
+                },
+                {
+                    token: ['text', 'entity.name.function', 'string.unquoted', 'text'],
+                    regex: '(\\[)([A-Z]:)(.*?)(\\])',
+                    comment: 'Inline fields'
+                },
+                {
+                    token: ['accent.constant.language', 'pitch.constant.numeric', 'duration.constant.numeric'],
+                    regex: '([\\^=_]*)([A-Ga-gz][,\']*)([0-9]*/*[><0-9]*)',
+                    comment: 'Notes'
+                },
+                {
+                    token: 'zupfnoter.jumptarget.string.quoted',
+                    regex: '[\\"!]\\^\\:.*?[\\"!]',
+                    comment: 'Zupfnoter jumptarget'
+                }, {
+                    token: 'zupfnoter.goto.string.quoted',
+                    regex: '[\\"!]\\^\\@.*?[\\"!]',
+                    comment: 'Zupfnoter goto'
+                },
+                {
+                    token: 'zupfnoter.annotation.string.quoted',
+                    regex: '[\\"!]\\^\\!.*?[\\"!]',
+                    comment: 'Zupfnoter annoation'
+                },
+                {
+                    token: 'zupfnoter.annotationref.string.quoted',
+                    regex: '[\\"!]\\^\\#.*?[\\"!]',
+                    comment: 'Zupfnoter annotation reference'
+                },
+                {
+                    token: 'chordname.string.quoted',
+                    regex: '[\\"!]\\^.*?[\\"!]',
+                    comment: 'abc chord'
+                },
+                {
+                    token: 'string.quoted',
+                    regex: '[\\"!].*?[\\"!]',
+                    comment: 'abc annotation'
+                }
+
+            ]
+        };
+
+        this.normalizeRules();
+    };
+
+    ABCHighlightRules.metaData = {
+        fileTypes: ['abc'],
+        name: 'ABC',
+        scopeName: 'text.abcnotation'
+    };
+
+
+    oop.inherits(ABCHighlightRules, TextHighlightRules);
+
+    exports.ABCHighlightRules = ABCHighlightRules;
+});
+
+ace.define("ace/mode/folding/cstyle",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Range = require("../../range").Range;
+var BaseFoldMode = require("./fold_mode").FoldMode;
+
+var FoldMode = exports.FoldMode = function(commentRegex) {
+    if (commentRegex) {
+        this.foldingStartMarker = new RegExp(
+            this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start)
+        );
+        this.foldingStopMarker = new RegExp(
+            this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end)
+        );
+    }
+};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+    
+    this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/;
+    this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/;
+    this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/;
+    this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/;
+    this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/;
+    this._getFoldWidgetBase = this.getFoldWidget;
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+    
+        if (this.singleLineBlockCommentRe.test(line)) {
+            if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line))
+                return "";
+        }
+    
+        var fw = this._getFoldWidgetBase(session, foldStyle, row);
+    
+        if (!fw && this.startRegionRe.test(line))
+            return "start"; // lineCommentRegionStart
+    
+        return fw;
+    };
+
+    this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) {
+        var line = session.getLine(row);
+        
+        if (this.startRegionRe.test(line))
+            return this.getCommentRegionBlock(session, line, row);
+        
+        var match = line.match(this.foldingStartMarker);
+        if (match) {
+            var i = match.index;
+
+            if (match[1])
+                return this.openingBracketBlock(session, match[1], row, i);
+                
+            var range = session.getCommentFoldRange(row, i + match[0].length, 1);
+            
+            if (range && !range.isMultiLine()) {
+                if (forceMultiline) {
+                    range = this.getSectionRange(session, row);
+                } else if (foldStyle != "all")
+                    range = null;
+            }
+            
+            return range;
+        }
+
+        if (foldStyle === "markbegin")
+            return;
+
+        var match = line.match(this.foldingStopMarker);
+        if (match) {
+            var i = match.index + match[0].length;
+
+            if (match[1])
+                return this.closingBracketBlock(session, match[1], row, i);
+
+            return session.getCommentFoldRange(row, i, -1);
+        }
+    };
+    
+    this.getSectionRange = function(session, row) {
+        var line = session.getLine(row);
+        var startIndent = line.search(/\S/);
+        var startRow = row;
+        var startColumn = line.length;
+        row = row + 1;
+        var endRow = row;
+        var maxRow = session.getLength();
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var indent = line.search(/\S/);
+            if (indent === -1)
+                continue;
+            if  (startIndent > indent)
+                break;
+            var subRange = this.getFoldWidgetRange(session, "all", row);
+            
+            if (subRange) {
+                if (subRange.start.row <= startRow) {
+                    break;
+                } else if (subRange.isMultiLine()) {
+                    row = subRange.end.row;
+                } else if (startIndent == indent) {
+                    break;
+                }
+            }
+            endRow = row;
+        }
+        
+        return new Range(startRow, startColumn, endRow, session.getLine(endRow).length);
+    };
+    this.getCommentRegionBlock = function(session, line, row) {
+        var startColumn = line.search(/\s*$/);
+        var maxRow = session.getLength();
+        var startRow = row;
+        
+        var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/;
+        var depth = 1;
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var m = re.exec(line);
+            if (!m) continue;
+            if (m[1]) depth--;
+            else depth++;
+
+            if (!depth) break;
+        }
+
+        var endRow = row;
+        if (endRow > startRow) {
+            return new Range(startRow, startColumn, endRow, line.length);
+        }
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/abc",[], function (require, exports, module) {
+    "use strict";
+
+    var oop = require("../lib/oop");
+    var TextMode = require("./text").Mode;
+    var ABCHighlightRules = require("./abc_highlight_rules").ABCHighlightRules;
+    var FoldMode = require("./folding/cstyle").FoldMode;
+
+    var Mode = function () {
+        this.HighlightRules = ABCHighlightRules;
+        this.foldingRules = new FoldMode();
+        this.$behaviour = this.$defaultBehaviour;
+    };
+    oop.inherits(Mode, TextMode);
+
+    (function () {
+        this.$id = "ace/mode/abc";
+    }).call(Mode.prototype);
+
+    exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/abc"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

Fișier diff suprimat deoarece este prea mare
+ 12 - 0
services/web/public/js/ace-1.4.3/mode-actionscript.js


+ 138 - 0
services/web/public/js/ace-1.4.3/mode-ada.js

@@ -0,0 +1,138 @@
+ace.define("ace/mode/ada_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var AdaHighlightRules = function() {
+var keywords = "abort|else|new|return|abs|elsif|not|reverse|abstract|end|null|accept|entry|select|" +
+"access|exception|of|separate|aliased|exit|or|some|all|others|subtype|and|for|out|synchronized|" +
+"array|function|overriding|at|tagged|generic|package|task|begin|goto|pragma|terminate|" +
+"body|private|then|if|procedure|type|case|in|protected|constant|interface|until|" +
+"|is|raise|use|declare|range|delay|limited|record|when|delta|loop|rem|while|digits|renames|with|do|mod|requeue|xor";
+
+    var builtinConstants = (
+        "true|false|null"
+    );
+
+    var builtinFunctions = (
+        "count|min|max|avg|sum|rank|now|coalesce|main"
+    );
+
+    var keywordMapper = this.createKeywordMapper({
+        "support.function": builtinFunctions,
+        "keyword": keywords,
+        "constant.language": builtinConstants
+    }, "identifier", true);
+
+    this.$rules = {
+        "start" : [ {
+            token : "comment",
+            regex : "--.*$"
+        }, {
+            token : "string",           // " string
+            regex : '".*?"'
+        }, {
+            token : "string",           // character
+            regex : "'.'"
+        }, {
+            token : "constant.numeric", // float
+            regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
+        }, {
+            token : keywordMapper,
+            regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
+        }, {
+            token : "keyword.operator",
+            regex : "\\+|\\-|\\/|\\/\\/|%|<@>|@>|<@|&|\\^|~|<|>|<=|=>|==|!=|<>|="
+        }, {
+            token : "paren.lparen",
+            regex : "[\\(]"
+        }, {
+            token : "paren.rparen",
+            regex : "[\\)]"
+        }, {
+            token : "text",
+            regex : "\\s+"
+        } ]
+    };
+};
+
+oop.inherits(AdaHighlightRules, TextHighlightRules);
+
+exports.AdaHighlightRules = AdaHighlightRules;
+});
+
+ace.define("ace/mode/ada",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var AdaHighlightRules = require("./ada_highlight_rules").AdaHighlightRules;
+var Range = require("../range").Range;
+
+var Mode = function() {
+    this.HighlightRules = AdaHighlightRules;
+    this.$behaviour = this.$defaultBehaviour;
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+
+    this.lineCommentStart = "--";
+
+    this.getNextLineIndent = function(state, line, tab) {
+        var indent = this.$getIndent(line);
+
+        var tokenizedLine = this.getTokenizer().getLineTokens(line, state);
+        var tokens = tokenizedLine.tokens;
+
+        if (tokens.length && tokens[tokens.length-1].type == "comment") {
+            return indent;
+        }
+        if (state == "start") {
+            var match = line.match(/^.*(begin|loop|then|is|do)\s*$/);
+            if (match) {
+                indent += tab;
+            }
+        }
+
+        return indent;
+    };
+
+    this.checkOutdent = function(state, line, input) {
+        var complete_line = line + input;
+        if (complete_line.match(/^\s*(begin|end)$/)) {
+            return true;
+        }
+
+        return false;
+    };
+
+    this.autoOutdent = function(state, session, row) {
+
+        var line = session.getLine(row);
+        var prevLine = session.getLine(row - 1);
+        var prevIndent = this.$getIndent(prevLine).length;
+        var indent = this.$getIndent(line).length;
+        if (indent <= prevIndent) {
+            return;
+        }
+
+        session.outdentRows(new Range(row, 0, row + 2, 0));
+    };
+
+
+    this.$id = "ace/mode/ada";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+
+});
+                (function() {
+                    ace.require(["ace/mode/ada"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 364 - 0
services/web/public/js/ace-1.4.3/mode-apache_conf.js

@@ -0,0 +1,364 @@
+ace.define("ace/mode/apache_conf_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var ApacheConfHighlightRules = function() {
+
+    this.$rules = { start: 
+       [ { token: 
+            [ 'punctuation.definition.comment.apacheconf',
+              'comment.line.hash.ini',
+              'comment.line.hash.ini' ],
+           regex: '^((?:\\s)*)(#)(.*$)' },
+         { token: 
+            [ 'punctuation.definition.tag.apacheconf',
+              'entity.tag.apacheconf',
+              'text',
+              'string.value.apacheconf',
+              'punctuation.definition.tag.apacheconf' ],
+           regex: '(<)(Proxy|ProxyMatch|IfVersion|Directory|DirectoryMatch|Files|FilesMatch|IfDefine|IfModule|Limit|LimitExcept|Location|LocationMatch|VirtualHost)(?:(\\s)(.+?))?(>)' },
+         { token: 
+            [ 'punctuation.definition.tag.apacheconf',
+              'entity.tag.apacheconf',
+              'punctuation.definition.tag.apacheconf' ],
+           regex: '(</)(Proxy|ProxyMatch|IfVersion|Directory|DirectoryMatch|Files|FilesMatch|IfDefine|IfModule|Limit|LimitExcept|Location|LocationMatch|VirtualHost)(>)' },
+         { token: 
+            [ 'keyword.alias.apacheconf', 'text',
+              'string.regexp.apacheconf', 'text',
+              'string.replacement.apacheconf', 'text' ],
+           regex: '(Rewrite(?:Rule|Cond))(\\s+)(.+?)(\\s+)(.+?)($|\\s)' },
+         { token: 
+            [ 'keyword.alias.apacheconf', 'text',
+              'entity.status.apacheconf', 'text',
+              'string.regexp.apacheconf', 'text',
+              'string.path.apacheconf', 'text' ],
+           regex: '(RedirectMatch)(?:(\\s+)(\\d\\d\\d|permanent|temp|seeother|gone))?(\\s+)(.+?)(\\s+)(?:(.+?)($|\\s))?' },
+         { token: 
+            [ 'keyword.alias.apacheconf', 'text', 
+              'entity.status.apacheconf', 'text',
+              'string.path.apacheconf', 'text',
+              'string.path.apacheconf', 'text' ],
+           regex: '(Redirect)(?:(\\s+)(\\d\\d\\d|permanent|temp|seeother|gone))?(\\s+)(.+?)(\\s+)(?:(.+?)($|\\s))?' },
+         { token: 
+            [ 'keyword.alias.apacheconf', 'text',
+              'string.regexp.apacheconf', 'text',
+              'string.path.apacheconf', 'text' ],
+           regex: '(ScriptAliasMatch|AliasMatch)(\\s+)(.+?)(\\s+)(?:(.+?)(\\s))?' },
+         { token: 
+            [ 'keyword.alias.apacheconf', 'text',
+              'string.path.apacheconf', 'text',
+              'string.path.apacheconf', 'text' ],
+           regex: '(RedirectPermanent|RedirectTemp|ScriptAlias|Alias)(\\s+)(.+?)(\\s+)(?:(.+?)($|\\s))?' },
+         { token: 'keyword.core.apacheconf',
+           regex: '\\b(?:AcceptPathInfo|AccessFileName|AddDefaultCharset|AddOutputFilterByType|AllowEncodedSlashes|AllowOverride|AuthName|AuthType|CGIMapExtension|ContentDigest|DefaultType|DocumentRoot|EnableMMAP|EnableSendfile|ErrorDocument|ErrorLog|FileETag|ForceType|HostnameLookups|IdentityCheck|Include|KeepAlive|KeepAliveTimeout|LimitInternalRecursion|LimitRequestBody|LimitRequestFields|LimitRequestFieldSize|LimitRequestLine|LimitXMLRequestBody|LogLevel|MaxKeepAliveRequests|NameVirtualHost|Options|Require|RLimitCPU|RLimitMEM|RLimitNPROC|Satisfy|ScriptInterpreterSource|ServerAdmin|ServerAlias|ServerName|ServerPath|ServerRoot|ServerSignature|ServerTokens|SetHandler|SetInputFilter|SetOutputFilter|TimeOut|TraceEnable|UseCanonicalName)\\b' },
+         { token: 'keyword.mpm.apacheconf',
+           regex: '\\b(?:AcceptMutex|AssignUserID|BS2000Account|ChildPerUserID|CoreDumpDirectory|EnableExceptionHook|Group|Listen|ListenBacklog|LockFile|MaxClients|MaxMemFree|MaxRequestsPerChild|MaxRequestsPerThread|MaxSpareServers|MaxSpareThreads|MaxThreads|MaxThreadsPerChild|MinSpareServers|MinSpareThreads|NumServers|PidFile|ReceiveBufferSize|ScoreBoardFile|SendBufferSize|ServerLimit|StartServers|StartThreads|ThreadLimit|ThreadsPerChild|ThreadStackSize|User|Win32DisableAcceptEx)\\b' },
+         { token: 'keyword.access.apacheconf',
+           regex: '\\b(?:Allow|Deny|Order)\\b' },
+         { token: 'keyword.actions.apacheconf',
+           regex: '\\b(?:Action|Script)\\b' },
+         { token: 'keyword.alias.apacheconf',
+           regex: '\\b(?:Alias|AliasMatch|Redirect|RedirectMatch|RedirectPermanent|RedirectTemp|ScriptAlias|ScriptAliasMatch)\\b' },
+         { token: 'keyword.auth.apacheconf',
+           regex: '\\b(?:AuthAuthoritative|AuthGroupFile|AuthUserFile)\\b' },
+         { token: 'keyword.auth_anon.apacheconf',
+           regex: '\\b(?:Anonymous|Anonymous_Authoritative|Anonymous_LogEmail|Anonymous_MustGiveEmail|Anonymous_NoUserID|Anonymous_VerifyEmail)\\b' },
+         { token: 'keyword.auth_dbm.apacheconf',
+           regex: '\\b(?:AuthDBMAuthoritative|AuthDBMGroupFile|AuthDBMType|AuthDBMUserFile)\\b' },
+         { token: 'keyword.auth_digest.apacheconf',
+           regex: '\\b(?:AuthDigestAlgorithm|AuthDigestDomain|AuthDigestFile|AuthDigestGroupFile|AuthDigestNcCheck|AuthDigestNonceFormat|AuthDigestNonceLifetime|AuthDigestQop|AuthDigestShmemSize)\\b' },
+         { token: 'keyword.auth_ldap.apacheconf',
+           regex: '\\b(?:AuthLDAPAuthoritative|AuthLDAPBindDN|AuthLDAPBindPassword|AuthLDAPCharsetConfig|AuthLDAPCompareDNOnServer|AuthLDAPDereferenceAliases|AuthLDAPEnabled|AuthLDAPFrontPageHack|AuthLDAPGroupAttribute|AuthLDAPGroupAttributeIsDN|AuthLDAPRemoteUserIsDN|AuthLDAPUrl)\\b' },
+         { token: 'keyword.autoindex.apacheconf',
+           regex: '\\b(?:AddAlt|AddAltByEncoding|AddAltByType|AddDescription|AddIcon|AddIconByEncoding|AddIconByType|DefaultIcon|HeaderName|IndexIgnore|IndexOptions|IndexOrderDefault|ReadmeName)\\b' },
+         { token: 'keyword.cache.apacheconf',
+           regex: '\\b(?:CacheDefaultExpire|CacheDisable|CacheEnable|CacheForceCompletion|CacheIgnoreCacheControl|CacheIgnoreHeaders|CacheIgnoreNoLastMod|CacheLastModifiedFactor|CacheMaxExpire)\\b' },
+         { token: 'keyword.cern_meta.apacheconf',
+           regex: '\\b(?:MetaDir|MetaFiles|MetaSuffix)\\b' },
+         { token: 'keyword.cgi.apacheconf',
+           regex: '\\b(?:ScriptLog|ScriptLogBuffer|ScriptLogLength)\\b' },
+         { token: 'keyword.cgid.apacheconf',
+           regex: '\\b(?:ScriptLog|ScriptLogBuffer|ScriptLogLength|ScriptSock)\\b' },
+         { token: 'keyword.charset_lite.apacheconf',
+           regex: '\\b(?:CharsetDefault|CharsetOptions|CharsetSourceEnc)\\b' },
+         { token: 'keyword.dav.apacheconf',
+           regex: '\\b(?:Dav|DavDepthInfinity|DavMinTimeout|DavLockDB)\\b' },
+         { token: 'keyword.deflate.apacheconf',
+           regex: '\\b(?:DeflateBufferSize|DeflateCompressionLevel|DeflateFilterNote|DeflateMemLevel|DeflateWindowSize)\\b' },
+         { token: 'keyword.dir.apacheconf',
+           regex: '\\b(?:DirectoryIndex|DirectorySlash)\\b' },
+         { token: 'keyword.disk_cache.apacheconf',
+           regex: '\\b(?:CacheDirLength|CacheDirLevels|CacheExpiryCheck|CacheGcClean|CacheGcDaily|CacheGcInterval|CacheGcMemUsage|CacheGcUnused|CacheMaxFileSize|CacheMinFileSize|CacheRoot|CacheSize|CacheTimeMargin)\\b' },
+         { token: 'keyword.dumpio.apacheconf',
+           regex: '\\b(?:DumpIOInput|DumpIOOutput)\\b' },
+         { token: 'keyword.env.apacheconf',
+           regex: '\\b(?:PassEnv|SetEnv|UnsetEnv)\\b' },
+         { token: 'keyword.expires.apacheconf',
+           regex: '\\b(?:ExpiresActive|ExpiresByType|ExpiresDefault)\\b' },
+         { token: 'keyword.ext_filter.apacheconf',
+           regex: '\\b(?:ExtFilterDefine|ExtFilterOptions)\\b' },
+         { token: 'keyword.file_cache.apacheconf',
+           regex: '\\b(?:CacheFile|MMapFile)\\b' },
+         { token: 'keyword.headers.apacheconf',
+           regex: '\\b(?:Header|RequestHeader)\\b' },
+         { token: 'keyword.imap.apacheconf',
+           regex: '\\b(?:ImapBase|ImapDefault|ImapMenu)\\b' },
+         { token: 'keyword.include.apacheconf',
+           regex: '\\b(?:SSIEndTag|SSIErrorMsg|SSIStartTag|SSITimeFormat|SSIUndefinedEcho|XBitHack)\\b' },
+         { token: 'keyword.isapi.apacheconf',
+           regex: '\\b(?:ISAPIAppendLogToErrors|ISAPIAppendLogToQuery|ISAPICacheFile|ISAPIFakeAsync|ISAPILogNotSupported|ISAPIReadAheadBuffer)\\b' },
+         { token: 'keyword.ldap.apacheconf',
+           regex: '\\b(?:LDAPCacheEntries|LDAPCacheTTL|LDAPConnectionTimeout|LDAPOpCacheEntries|LDAPOpCacheTTL|LDAPSharedCacheFile|LDAPSharedCacheSize|LDAPTrustedCA|LDAPTrustedCAType)\\b' },
+         { token: 'keyword.log.apacheconf',
+           regex: '\\b(?:BufferedLogs|CookieLog|CustomLog|LogFormat|TransferLog|ForensicLog)\\b' },
+         { token: 'keyword.mem_cache.apacheconf',
+           regex: '\\b(?:MCacheMaxObjectCount|MCacheMaxObjectSize|MCacheMaxStreamingBuffer|MCacheMinObjectSize|MCacheRemovalAlgorithm|MCacheSize)\\b' },
+         { token: 'keyword.mime.apacheconf',
+           regex: '\\b(?:AddCharset|AddEncoding|AddHandler|AddInputFilter|AddLanguage|AddOutputFilter|AddType|DefaultLanguage|ModMimeUsePathInfo|MultiviewsMatch|RemoveCharset|RemoveEncoding|RemoveHandler|RemoveInputFilter|RemoveLanguage|RemoveOutputFilter|RemoveType|TypesConfig)\\b' },
+         { token: 'keyword.misc.apacheconf',
+           regex: '\\b(?:ProtocolEcho|Example|AddModuleInfo|MimeMagicFile|CheckSpelling|ExtendedStatus|SuexecUserGroup|UserDir)\\b' },
+         { token: 'keyword.negotiation.apacheconf',
+           regex: '\\b(?:CacheNegotiatedDocs|ForceLanguagePriority|LanguagePriority)\\b' },
+         { token: 'keyword.nw_ssl.apacheconf',
+           regex: '\\b(?:NWSSLTrustedCerts|NWSSLUpgradeable|SecureListen)\\b' },
+         { token: 'keyword.proxy.apacheconf',
+           regex: '\\b(?:AllowCONNECT|NoProxy|ProxyBadHeader|ProxyBlock|ProxyDomain|ProxyErrorOverride|ProxyFtpDirCharset|ProxyIOBufferSize|ProxyMaxForwards|ProxyPass|ProxyPassReverse|ProxyPreserveHost|ProxyReceiveBufferSize|ProxyRemote|ProxyRemoteMatch|ProxyRequests|ProxyTimeout|ProxyVia)\\b' },
+         { token: 'keyword.rewrite.apacheconf',
+           regex: '\\b(?:RewriteBase|RewriteCond|RewriteEngine|RewriteLock|RewriteLog|RewriteLogLevel|RewriteMap|RewriteOptions|RewriteRule)\\b' },
+         { token: 'keyword.setenvif.apacheconf',
+           regex: '\\b(?:BrowserMatch|BrowserMatchNoCase|SetEnvIf|SetEnvIfNoCase)\\b' },
+         { token: 'keyword.so.apacheconf',
+           regex: '\\b(?:LoadFile|LoadModule)\\b' },
+         { token: 'keyword.ssl.apacheconf',
+           regex: '\\b(?:SSLCACertificateFile|SSLCACertificatePath|SSLCARevocationFile|SSLCARevocationPath|SSLCertificateChainFile|SSLCertificateFile|SSLCertificateKeyFile|SSLCipherSuite|SSLEngine|SSLMutex|SSLOptions|SSLPassPhraseDialog|SSLProtocol|SSLProxyCACertificateFile|SSLProxyCACertificatePath|SSLProxyCARevocationFile|SSLProxyCARevocationPath|SSLProxyCipherSuite|SSLProxyEngine|SSLProxyMachineCertificateFile|SSLProxyMachineCertificatePath|SSLProxyProtocol|SSLProxyVerify|SSLProxyVerifyDepth|SSLRandomSeed|SSLRequire|SSLRequireSSL|SSLSessionCache|SSLSessionCacheTimeout|SSLUserName|SSLVerifyClient|SSLVerifyDepth)\\b' },
+         { token: 'keyword.usertrack.apacheconf',
+           regex: '\\b(?:CookieDomain|CookieExpires|CookieName|CookieStyle|CookieTracking)\\b' },
+         { token: 'keyword.vhost_alias.apacheconf',
+           regex: '\\b(?:VirtualDocumentRoot|VirtualDocumentRootIP|VirtualScriptAlias|VirtualScriptAliasIP)\\b' },
+         { token: 
+            [ 'keyword.php.apacheconf',
+              'text',
+              'entity.property.apacheconf',
+              'text',
+              'string.value.apacheconf',
+              'text' ],
+           regex: '\\b(php_value|php_flag)\\b(?:(\\s+)(.+?)(?:(\\s+)(.+?))?)?(\\s)' },
+         { token: 
+            [ 'punctuation.variable.apacheconf',
+              'variable.env.apacheconf',
+              'variable.misc.apacheconf',
+              'punctuation.variable.apacheconf' ],
+           regex: '(%\\{)(?:(HTTP_USER_AGENT|HTTP_REFERER|HTTP_COOKIE|HTTP_FORWARDED|HTTP_HOST|HTTP_PROXY_CONNECTION|HTTP_ACCEPT|REMOTE_ADDR|REMOTE_HOST|REMOTE_PORT|REMOTE_USER|REMOTE_IDENT|REQUEST_METHOD|SCRIPT_FILENAME|PATH_INFO|QUERY_STRING|AUTH_TYPE|DOCUMENT_ROOT|SERVER_ADMIN|SERVER_NAME|SERVER_ADDR|SERVER_PORT|SERVER_PROTOCOL|SERVER_SOFTWARE|TIME_YEAR|TIME_MON|TIME_DAY|TIME_HOUR|TIME_MIN|TIME_SEC|TIME_WDAY|TIME|API_VERSION|THE_REQUEST|REQUEST_URI|REQUEST_FILENAME|IS_SUBREQ|HTTPS)|(.*?))(\\})' },
+         { token: [ 'entity.mime-type.apacheconf', 'text' ],
+           regex: '\\b((?:text|image|application|video|audio)/.+?)(\\s)' },
+         { token: 'entity.helper.apacheconf',
+           regex: '\\b(?:from|unset|set|on|off)\\b',
+           caseInsensitive: true },
+         { token: 'constant.integer.apacheconf', regex: '\\b\\d+\\b' },
+         { token: 
+            [ 'text',
+              'punctuation.definition.flag.apacheconf',
+              'string.flag.apacheconf',
+              'punctuation.definition.flag.apacheconf',
+              'text' ],
+           regex: '(\\s)(\\[)(.*?)(\\])(\\s)' } ] };
+    
+    this.normalizeRules();
+};
+
+ApacheConfHighlightRules.metaData = { fileTypes: 
+       [ 'conf',
+         'CONF',
+         'htaccess',
+         'HTACCESS',
+         'htgroups',
+         'HTGROUPS',
+         'htpasswd',
+         'HTPASSWD',
+         '.htaccess',
+         '.HTACCESS',
+         '.htgroups',
+         '.HTGROUPS',
+         '.htpasswd',
+         '.HTPASSWD' ],
+      name: 'Apache Conf',
+      scopeName: 'source.apacheconf' };
+
+
+oop.inherits(ApacheConfHighlightRules, TextHighlightRules);
+
+exports.ApacheConfHighlightRules = ApacheConfHighlightRules;
+});
+
+ace.define("ace/mode/folding/cstyle",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Range = require("../../range").Range;
+var BaseFoldMode = require("./fold_mode").FoldMode;
+
+var FoldMode = exports.FoldMode = function(commentRegex) {
+    if (commentRegex) {
+        this.foldingStartMarker = new RegExp(
+            this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start)
+        );
+        this.foldingStopMarker = new RegExp(
+            this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end)
+        );
+    }
+};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+    
+    this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/;
+    this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/;
+    this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/;
+    this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/;
+    this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/;
+    this._getFoldWidgetBase = this.getFoldWidget;
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+    
+        if (this.singleLineBlockCommentRe.test(line)) {
+            if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line))
+                return "";
+        }
+    
+        var fw = this._getFoldWidgetBase(session, foldStyle, row);
+    
+        if (!fw && this.startRegionRe.test(line))
+            return "start"; // lineCommentRegionStart
+    
+        return fw;
+    };
+
+    this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) {
+        var line = session.getLine(row);
+        
+        if (this.startRegionRe.test(line))
+            return this.getCommentRegionBlock(session, line, row);
+        
+        var match = line.match(this.foldingStartMarker);
+        if (match) {
+            var i = match.index;
+
+            if (match[1])
+                return this.openingBracketBlock(session, match[1], row, i);
+                
+            var range = session.getCommentFoldRange(row, i + match[0].length, 1);
+            
+            if (range && !range.isMultiLine()) {
+                if (forceMultiline) {
+                    range = this.getSectionRange(session, row);
+                } else if (foldStyle != "all")
+                    range = null;
+            }
+            
+            return range;
+        }
+
+        if (foldStyle === "markbegin")
+            return;
+
+        var match = line.match(this.foldingStopMarker);
+        if (match) {
+            var i = match.index + match[0].length;
+
+            if (match[1])
+                return this.closingBracketBlock(session, match[1], row, i);
+
+            return session.getCommentFoldRange(row, i, -1);
+        }
+    };
+    
+    this.getSectionRange = function(session, row) {
+        var line = session.getLine(row);
+        var startIndent = line.search(/\S/);
+        var startRow = row;
+        var startColumn = line.length;
+        row = row + 1;
+        var endRow = row;
+        var maxRow = session.getLength();
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var indent = line.search(/\S/);
+            if (indent === -1)
+                continue;
+            if  (startIndent > indent)
+                break;
+            var subRange = this.getFoldWidgetRange(session, "all", row);
+            
+            if (subRange) {
+                if (subRange.start.row <= startRow) {
+                    break;
+                } else if (subRange.isMultiLine()) {
+                    row = subRange.end.row;
+                } else if (startIndent == indent) {
+                    break;
+                }
+            }
+            endRow = row;
+        }
+        
+        return new Range(startRow, startColumn, endRow, session.getLine(endRow).length);
+    };
+    this.getCommentRegionBlock = function(session, line, row) {
+        var startColumn = line.search(/\s*$/);
+        var maxRow = session.getLength();
+        var startRow = row;
+        
+        var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/;
+        var depth = 1;
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var m = re.exec(line);
+            if (!m) continue;
+            if (m[1]) depth--;
+            else depth++;
+
+            if (!depth) break;
+        }
+
+        var endRow = row;
+        if (endRow > startRow) {
+            return new Range(startRow, startColumn, endRow, line.length);
+        }
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/apache_conf",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var ApacheConfHighlightRules = require("./apache_conf_highlight_rules").ApacheConfHighlightRules;
+var FoldMode = require("./folding/cstyle").FoldMode;
+
+var Mode = function() {
+    this.HighlightRules = ApacheConfHighlightRules;
+    this.foldingRules = new FoldMode();
+    this.$behaviour = this.$defaultBehaviour;
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+    this.lineCommentStart = "#";
+    this.$id = "ace/mode/apache_conf";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/apache_conf"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 458 - 0
services/web/public/js/ace-1.4.3/mode-apex.js

@@ -0,0 +1,458 @@
+ace.define("ace/mode/doc_comment_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var DocCommentHighlightRules = function() {
+    this.$rules = {
+        "start" : [ {
+            token : "comment.doc.tag",
+            regex : "@[\\w\\d_]+" // TODO: fix email addresses
+        }, 
+        DocCommentHighlightRules.getTagRule(),
+        {
+            defaultToken : "comment.doc",
+            caseInsensitive: true
+        }]
+    };
+};
+
+oop.inherits(DocCommentHighlightRules, TextHighlightRules);
+
+DocCommentHighlightRules.getTagRule = function(start) {
+    return {
+        token : "comment.doc.tag.storage.type",
+        regex : "\\b(?:TODO|FIXME|XXX|HACK)\\b"
+    };
+};
+
+DocCommentHighlightRules.getStartRule = function(start) {
+    return {
+        token : "comment.doc", // doc comment
+        regex : "\\/\\*(?=\\*)",
+        next  : start
+    };
+};
+
+DocCommentHighlightRules.getEndRule = function (start) {
+    return {
+        token : "comment.doc", // closing comment
+        regex : "\\*\\/",
+        next  : start
+    };
+};
+
+
+exports.DocCommentHighlightRules = DocCommentHighlightRules;
+
+});
+
+ace.define("ace/mode/apex_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("../mode/text_highlight_rules").TextHighlightRules;
+var DocCommentHighlightRules = require("../mode/doc_comment_highlight_rules").DocCommentHighlightRules;
+
+var ApexHighlightRules = function() {
+    var mainKeywordMapper = this.createKeywordMapper({
+        "variable.language": "activate|any|autonomous|begin|bigdecimal|byte|cast|char|collect|const"
+             + "|end|exit|export|float|goto|group|having|hint|import|inner|into|join|loop|number|object|of|outer"
+             + "|parallel|pragma|retrieve|returning|search|short|stat|synchronized|then|this_month"
+             + "|transaction|type|when",
+        "keyword": "private|protected|public|native|synchronized|abstract|threadsafe|transient|static|final"
+             + "|and|array|as|asc|break|bulk|by|catch|class|commit|continue|convertcurrency"
+             + "|delete|desc|do|else|enum|extends|false|final|finally|for|from|future|global"
+             + "|if|implements|in|insert|instanceof|interface|last_90_days|last_month"
+             + "|last_n_days|last_week|like|limit|list|map|merge|new|next_90_days|next_month|next_n_days"
+             + "|next_week|not|null|nulls|on|or|override|package|return"
+             + "|rollback|savepoint|select|set|sort|super|testmethod|this|this_week|throw|today"
+             + "|tolabel|tomorrow|trigger|true|try|undelete|update|upsert|using|virtual|webservice"
+             + "|where|while|yesterday|switch|case|default",
+        "storage.type":
+            "def|boolean|byte|char|short|int|float|pblob|date|datetime|decimal|double|id|integer|long|string|time|void|blob|Object",
+        "constant.language":
+            "true|false|null|after|before|count|excludes|first|includes|last|order|sharing|with",
+        "support.function":
+            "system|apex|label|apexpages|userinfo|schema"
+    }, "identifier", true);
+    function keywordMapper(value) {
+        if (value.slice(-3) == "__c") return "support.function";
+        return mainKeywordMapper(value);
+    }
+    
+    function string(start, options) {
+        return {
+            regex: start + (options.multiline ? "" : "(?=.)"),
+            token: "string.start",
+            next: [{
+                regex: options.escape,
+                token: "character.escape"
+            }, {
+                regex: options.error,
+                token: "error.invalid"
+            }, {
+                regex: start + (options.multiline ? "" : "|$"),
+                token: "string.end",
+                next: options.next || "start"
+            }, {
+                defaultToken: "string"
+            }]
+        };
+    }
+    
+    function comments() {
+        return [{
+                token : "comment",
+                regex : "\\/\\/(?=.)",
+                next : [
+                    DocCommentHighlightRules.getTagRule(),
+                    {token : "comment", regex : "$|^", next : "start"},
+                    {defaultToken : "comment", caseInsensitive: true}
+                ]
+            },
+            DocCommentHighlightRules.getStartRule("doc-start"),
+            {
+                token : "comment", // multi line comment
+                regex : /\/\*/,
+                next : [
+                    DocCommentHighlightRules.getTagRule(),
+                    {token : "comment", regex : "\\*\\/", next : "start"},
+                    {defaultToken : "comment", caseInsensitive: true}
+                ]
+            }
+        ];
+    }
+    
+    this.$rules = {
+        start: [
+            string("'", {
+                escape: /\\[nb'"\\]/,
+                error: /\\./,
+                multiline: false
+            }),
+            comments("c"),
+            {
+                type: "decoration",
+                token: [
+                    "meta.package.apex",
+                    "keyword.other.package.apex",
+                    "meta.package.apex",
+                    "storage.modifier.package.apex",
+                    "meta.package.apex",
+                    "punctuation.terminator.apex"
+                ],
+                regex: /^(\s*)(package)\b(?:(\s*)([^ ;$]+)(\s*)((?:;)?))?/
+            }, {
+                 regex: /@[a-zA-Z_$][a-zA-Z_$\d\u0080-\ufffe]*/,
+                 token: "constant.language"
+            },
+            {
+                regex: /[a-zA-Z_$][a-zA-Z_$\d\u0080-\ufffe]*/,
+                token: keywordMapper
+            },  
+            {
+                regex: "`#%",
+                token: "error.invalid"
+            }, {
+                token : "constant.numeric", // float
+                regex : /[+-]?\d+(?:(?:\.\d*)?(?:[LlDdEe][+-]?\d+)?)\b|\.\d+[LlDdEe]/
+            }, {
+                token : "keyword.operator",
+                regex : /--|\+\+|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|[!$%&*+\-~\/^]=?/,
+                next  : "start"
+            }, {
+                token : "punctuation.operator",
+                regex : /[?:,;.]/,
+                next  : "start"
+            }, {
+                token : "paren.lparen",
+                regex : /[\[]/,
+                next  : "maybe_soql",
+                merge : false
+            }, {
+                token : "paren.lparen",
+                regex : /[\[({]/,
+                next  : "start",
+                merge : false
+            }, {
+                token : "paren.rparen",
+                regex : /[\])}]/,
+                merge : false
+            } 
+        ], 
+        maybe_soql: [{
+            regex: /\s+/,
+            token: "text"
+        }, {
+            regex: /(SELECT|FIND)\b/,
+            token: "keyword",
+            caseInsensitive: true,
+            next: "soql"
+        }, {
+            regex: "",
+            token: "none",
+            next: "start"
+        }],
+        soql: [{
+            regex: "(:?ASC|BY|CATEGORY|CUBE|DATA|DESC|END|FIND|FIRST|FOR|FROM|GROUP|HAVING|IN|LAST"
+                + "|LIMIT|NETWORK|NULLS|OFFSET|ORDER|REFERENCE|RETURNING|ROLLUP|SCOPE|SELECT"
+                + "|SNIPPET|TRACKING|TYPEOF|UPDATE|USING|VIEW|VIEWSTAT|WHERE|WITH|AND|OR)\\b",
+            token: "keyword",
+            caseInsensitive: true
+        }, {
+            regex: "(:?target_length|toLabel|convertCurrency|count|Contact|Account|User|FIELDS)\\b",
+            token: "support.function",
+            caseInsensitive: true
+        }, {
+            token : "paren.rparen",
+            regex : /[\]]/,
+            next  : "start",
+            merge : false
+        }, 
+        string("'", {
+            escape: /\\[nb'"\\]/,
+            error: /\\./,
+            multiline: false,
+            next: "soql"
+        }),
+        string('"', {
+            escape: /\\[nb'"\\]/,
+            error: /\\./,
+            multiline: false,
+            next: "soql"
+        }),
+        {
+            regex: /\\./,
+            token: "character.escape"
+        },
+        {
+            regex : /[\?\&\|\!\{\}\[\]\(\)\^\~\*\:\"\'\+\-\,\.=\\\/]/,
+            token : "keyword.operator"
+        }],
+        
+        "log-start" : [ {
+            token : "timestamp.invisible",
+            regex : /^[\d:.() ]+\|/, 
+            next: "log-header"
+        },  {
+            token : "timestamp.invisible",
+            regex : /^  (Number of|Maximum)[^:]*:/,
+            next: "log-comment"
+        }, {
+            token : "invisible",
+            regex : /^Execute Anonymous:/,
+            next: "log-comment"
+        },  {
+            defaultToken: "text"
+        }],
+        "log-comment": [{
+            token : "log-comment",
+            regex : /.*$/,
+            next: "log-start"
+        }],
+        "log-header": [{
+            token : "timestamp.invisible",
+            regex : /((USER_DEBUG|\[\d+\]|DEBUG)\|)+/
+        },
+        {
+            token : "keyword",
+            regex: "(?:EXECUTION_FINISHED|EXECUTION_STARTED|CODE_UNIT_STARTED"
+                + "|CUMULATIVE_LIMIT_USAGE|LIMIT_USAGE_FOR_NS"
+                + "|CUMULATIVE_LIMIT_USAGE_END|CODE_UNIT_FINISHED)"
+        }, {
+            regex: "",
+            next: "log-start"
+        }]
+    };
+    this.embedRules(DocCommentHighlightRules, "doc-",
+        [ DocCommentHighlightRules.getEndRule("start") ]);
+        
+
+    this.normalizeRules();
+};
+
+
+oop.inherits(ApexHighlightRules, TextHighlightRules);
+
+exports.ApexHighlightRules = ApexHighlightRules;
+});
+
+ace.define("ace/mode/folding/cstyle",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Range = require("../../range").Range;
+var BaseFoldMode = require("./fold_mode").FoldMode;
+
+var FoldMode = exports.FoldMode = function(commentRegex) {
+    if (commentRegex) {
+        this.foldingStartMarker = new RegExp(
+            this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start)
+        );
+        this.foldingStopMarker = new RegExp(
+            this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end)
+        );
+    }
+};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+    
+    this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/;
+    this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/;
+    this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/;
+    this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/;
+    this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/;
+    this._getFoldWidgetBase = this.getFoldWidget;
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+    
+        if (this.singleLineBlockCommentRe.test(line)) {
+            if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line))
+                return "";
+        }
+    
+        var fw = this._getFoldWidgetBase(session, foldStyle, row);
+    
+        if (!fw && this.startRegionRe.test(line))
+            return "start"; // lineCommentRegionStart
+    
+        return fw;
+    };
+
+    this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) {
+        var line = session.getLine(row);
+        
+        if (this.startRegionRe.test(line))
+            return this.getCommentRegionBlock(session, line, row);
+        
+        var match = line.match(this.foldingStartMarker);
+        if (match) {
+            var i = match.index;
+
+            if (match[1])
+                return this.openingBracketBlock(session, match[1], row, i);
+                
+            var range = session.getCommentFoldRange(row, i + match[0].length, 1);
+            
+            if (range && !range.isMultiLine()) {
+                if (forceMultiline) {
+                    range = this.getSectionRange(session, row);
+                } else if (foldStyle != "all")
+                    range = null;
+            }
+            
+            return range;
+        }
+
+        if (foldStyle === "markbegin")
+            return;
+
+        var match = line.match(this.foldingStopMarker);
+        if (match) {
+            var i = match.index + match[0].length;
+
+            if (match[1])
+                return this.closingBracketBlock(session, match[1], row, i);
+
+            return session.getCommentFoldRange(row, i, -1);
+        }
+    };
+    
+    this.getSectionRange = function(session, row) {
+        var line = session.getLine(row);
+        var startIndent = line.search(/\S/);
+        var startRow = row;
+        var startColumn = line.length;
+        row = row + 1;
+        var endRow = row;
+        var maxRow = session.getLength();
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var indent = line.search(/\S/);
+            if (indent === -1)
+                continue;
+            if  (startIndent > indent)
+                break;
+            var subRange = this.getFoldWidgetRange(session, "all", row);
+            
+            if (subRange) {
+                if (subRange.start.row <= startRow) {
+                    break;
+                } else if (subRange.isMultiLine()) {
+                    row = subRange.end.row;
+                } else if (startIndent == indent) {
+                    break;
+                }
+            }
+            endRow = row;
+        }
+        
+        return new Range(startRow, startColumn, endRow, session.getLine(endRow).length);
+    };
+    this.getCommentRegionBlock = function(session, line, row) {
+        var startColumn = line.search(/\s*$/);
+        var maxRow = session.getLength();
+        var startRow = row;
+        
+        var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/;
+        var depth = 1;
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var m = re.exec(line);
+            if (!m) continue;
+            if (m[1]) depth--;
+            else depth++;
+
+            if (!depth) break;
+        }
+
+        var endRow = row;
+        if (endRow > startRow) {
+            return new Range(startRow, startColumn, endRow, line.length);
+        }
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/apex",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("../mode/text").Mode;
+var ApexHighlightRules = require("./apex_highlight_rules").ApexHighlightRules;
+var FoldMode = require("../mode/folding/cstyle").FoldMode;
+var CstyleBehaviour = require("../mode/behaviour/cstyle").CstyleBehaviour;
+
+function ApexMode() {
+    TextMode.call(this);
+
+    this.HighlightRules = ApexHighlightRules;
+    this.foldingRules = new FoldMode();
+    this.$behaviour = new CstyleBehaviour();
+}
+
+oop.inherits(ApexMode, TextMode);
+
+ApexMode.prototype.lineCommentStart = "//";
+
+ApexMode.prototype.blockComment = {
+    start: "/*",
+    end: "*/"
+};
+
+exports.Mode = ApexMode;
+
+});
+                (function() {
+                    ace.require(["ace/mode/apex"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 279 - 0
services/web/public/js/ace-1.4.3/mode-applescript.js

@@ -0,0 +1,279 @@
+ace.define("ace/mode/applescript_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var AppleScriptHighlightRules = function() {
+    var keywords = (
+        "about|above|after|against|and|around|as|at|back|before|beginning|" +
+        "behind|below|beneath|beside|between|but|by|considering|" +
+        "contain|contains|continue|copy|div|does|eighth|else|end|equal|" +
+        "equals|error|every|exit|fifth|first|for|fourth|from|front|" +
+        "get|given|global|if|ignoring|in|into|is|it|its|last|local|me|" +
+        "middle|mod|my|ninth|not|of|on|onto|or|over|prop|property|put|ref|" +
+        "reference|repeat|returning|script|second|set|seventh|since|" +
+        "sixth|some|tell|tenth|that|the|then|third|through|thru|" +
+        "timeout|times|to|transaction|try|until|where|while|whose|with|without"
+    );
+
+    var builtinConstants = (
+        "AppleScript|false|linefeed|return|pi|quote|result|space|tab|true"
+    );
+
+    var builtinFunctions = (
+        "activate|beep|count|delay|launch|log|offset|read|round|run|say|" +
+        "summarize|write"
+    );
+
+    var builtinTypes = (
+        "alias|application|boolean|class|constant|date|file|integer|list|" +
+        "number|real|record|string|text|character|characters|contents|day|" +
+        "frontmost|id|item|length|month|name|paragraph|paragraphs|rest|" +
+        "reverse|running|time|version|weekday|word|words|year"
+    );
+
+    var keywordMapper = this.createKeywordMapper({
+        "support.function": builtinFunctions,
+        "constant.language": builtinConstants,
+        "support.type": builtinTypes,
+        "keyword": keywords
+    }, "identifier");
+
+    this.$rules = {
+        "start": [
+            {
+                token: "comment",
+                regex: "--.*$"
+            },
+            {
+                token : "comment", // multi line comment
+                regex : "\\(\\*",
+                next : "comment"
+            },
+            {
+                token: "string",           // " string
+                regex: '".*?"'
+            },
+            {
+                token: "support.type",
+                regex: '\\b(POSIX file|POSIX path|(date|time) string|quoted form)\\b'
+            },
+            {
+                token: "support.function",
+                regex: '\\b(clipboard info|the clipboard|info for|list (disks|folder)|' +
+          'mount volume|path to|(close|open for) access|(get|set) eof|' +
+          'current date|do shell script|get volume settings|random number|' +
+          'set volume|system attribute|system info|time to GMT|' +
+          '(load|run|store) script|scripting components|' +
+          'ASCII (character|number)|localized string|' +
+          'choose (application|color|file|file name|' +
+          'folder|from list|remote application|URL)|' +
+          'display (alert|dialog))\\b|^\\s*return\\b'
+            },
+            {
+                token: "constant.language",
+                regex: '\\b(text item delimiters|current application|missing value)\\b'
+            },
+            {
+                token: "keyword",
+                regex: '\\b(apart from|aside from|instead of|out of|greater than|' +
+          "isn't|(doesn't|does not) (equal|come before|come after|contain)|" +
+          '(greater|less) than( or equal)?|(starts?|ends|begins?) with|' +
+          'contained by|comes (before|after)|a (ref|reference))\\b'
+            },
+            {
+                token: keywordMapper,
+                regex: "[a-zA-Z][a-zA-Z0-9_]*\\b"
+            }
+        ],
+        "comment": [
+            {
+                token: "comment", // closing comment
+                regex: "\\*\\)",
+                next: "start"
+            }, {
+                defaultToken: "comment"
+            }
+        ]
+    };
+
+    this.normalizeRules();
+};
+
+oop.inherits(AppleScriptHighlightRules, TextHighlightRules);
+
+exports.AppleScriptHighlightRules = AppleScriptHighlightRules;
+});
+
+ace.define("ace/mode/folding/cstyle",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Range = require("../../range").Range;
+var BaseFoldMode = require("./fold_mode").FoldMode;
+
+var FoldMode = exports.FoldMode = function(commentRegex) {
+    if (commentRegex) {
+        this.foldingStartMarker = new RegExp(
+            this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start)
+        );
+        this.foldingStopMarker = new RegExp(
+            this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end)
+        );
+    }
+};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+    
+    this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/;
+    this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/;
+    this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/;
+    this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/;
+    this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/;
+    this._getFoldWidgetBase = this.getFoldWidget;
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+    
+        if (this.singleLineBlockCommentRe.test(line)) {
+            if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line))
+                return "";
+        }
+    
+        var fw = this._getFoldWidgetBase(session, foldStyle, row);
+    
+        if (!fw && this.startRegionRe.test(line))
+            return "start"; // lineCommentRegionStart
+    
+        return fw;
+    };
+
+    this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) {
+        var line = session.getLine(row);
+        
+        if (this.startRegionRe.test(line))
+            return this.getCommentRegionBlock(session, line, row);
+        
+        var match = line.match(this.foldingStartMarker);
+        if (match) {
+            var i = match.index;
+
+            if (match[1])
+                return this.openingBracketBlock(session, match[1], row, i);
+                
+            var range = session.getCommentFoldRange(row, i + match[0].length, 1);
+            
+            if (range && !range.isMultiLine()) {
+                if (forceMultiline) {
+                    range = this.getSectionRange(session, row);
+                } else if (foldStyle != "all")
+                    range = null;
+            }
+            
+            return range;
+        }
+
+        if (foldStyle === "markbegin")
+            return;
+
+        var match = line.match(this.foldingStopMarker);
+        if (match) {
+            var i = match.index + match[0].length;
+
+            if (match[1])
+                return this.closingBracketBlock(session, match[1], row, i);
+
+            return session.getCommentFoldRange(row, i, -1);
+        }
+    };
+    
+    this.getSectionRange = function(session, row) {
+        var line = session.getLine(row);
+        var startIndent = line.search(/\S/);
+        var startRow = row;
+        var startColumn = line.length;
+        row = row + 1;
+        var endRow = row;
+        var maxRow = session.getLength();
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var indent = line.search(/\S/);
+            if (indent === -1)
+                continue;
+            if  (startIndent > indent)
+                break;
+            var subRange = this.getFoldWidgetRange(session, "all", row);
+            
+            if (subRange) {
+                if (subRange.start.row <= startRow) {
+                    break;
+                } else if (subRange.isMultiLine()) {
+                    row = subRange.end.row;
+                } else if (startIndent == indent) {
+                    break;
+                }
+            }
+            endRow = row;
+        }
+        
+        return new Range(startRow, startColumn, endRow, session.getLine(endRow).length);
+    };
+    this.getCommentRegionBlock = function(session, line, row) {
+        var startColumn = line.search(/\s*$/);
+        var maxRow = session.getLength();
+        var startRow = row;
+        
+        var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/;
+        var depth = 1;
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var m = re.exec(line);
+            if (!m) continue;
+            if (m[1]) depth--;
+            else depth++;
+
+            if (!depth) break;
+        }
+
+        var endRow = row;
+        if (endRow > startRow) {
+            return new Range(startRow, startColumn, endRow, line.length);
+        }
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/applescript",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var AppleScriptHighlightRules = require("./applescript_highlight_rules").AppleScriptHighlightRules;
+var FoldMode = require("./folding/cstyle").FoldMode;
+
+var Mode = function() {
+    this.HighlightRules = AppleScriptHighlightRules;
+    this.foldingRules = new FoldMode();
+    this.$behaviour = this.$defaultBehaviour;
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+    this.lineCommentStart = "--";
+    this.blockComment = {start: "(*", end: "*)"};
+    this.$id = "ace/mode/applescript";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/applescript"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 350 - 0
services/web/public/js/ace-1.4.3/mode-asciidoc.js

@@ -0,0 +1,350 @@
+ace.define("ace/mode/asciidoc_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var AsciidocHighlightRules = function() {
+    var identifierRe = "[a-zA-Z\u00a1-\uffff]+\\b";
+
+    this.$rules = {
+        "start": [
+            {token: "empty",   regex: /$/},
+            {token: "literal", regex: /^\.{4,}\s*$/,  next: "listingBlock"},
+            {token: "literal", regex: /^-{4,}\s*$/,   next: "literalBlock"},
+            {token: "string",  regex: /^\+{4,}\s*$/,  next: "passthroughBlock"},
+            {token: "keyword", regex: /^={4,}\s*$/},
+            {token: "text",    regex: /^\s*$/},
+            {token: "empty", regex: "", next: "dissallowDelimitedBlock"}
+        ],
+
+        "dissallowDelimitedBlock": [
+            {include: "paragraphEnd"},
+            {token: "comment", regex: '^//.+$'},
+            {token: "keyword", regex: "^(?:NOTE|TIP|IMPORTANT|WARNING|CAUTION):"},
+
+            {include: "listStart"},
+            {token: "literal", regex: /^\s+.+$/, next: "indentedBlock"},
+            {token: "empty",   regex: "", next: "text"}
+        ],
+
+        "paragraphEnd": [
+            {token: "doc.comment", regex: /^\/{4,}\s*$/,    next: "commentBlock"},
+            {token: "tableBlock",  regex: /^\s*[|!]=+\s*$/, next: "tableBlock"},
+            {token: "keyword",     regex: /^(?:--|''')\s*$/, next: "start"},
+            {token: "option",      regex: /^\[.*\]\s*$/,     next: "start"},
+            {token: "pageBreak",   regex: /^>{3,}$/,         next: "start"},
+            {token: "literal",     regex: /^\.{4,}\s*$/,     next: "listingBlock"},
+            {token: "titleUnderline",    regex: /^(?:={2,}|-{2,}|~{2,}|\^{2,}|\+{2,})\s*$/, next: "start"},
+            {token: "singleLineTitle",   regex: /^={1,5}\s+\S.*$/, next: "start"},
+
+            {token: "otherBlock",    regex: /^(?:\*{2,}|_{2,})\s*$/, next: "start"},
+            {token: "optionalTitle", regex: /^\.[^.\s].+$/,  next: "start"}
+        ],
+
+        "listStart": [
+            {token: "keyword",  regex: /^\s*(?:\d+\.|[a-zA-Z]\.|[ixvmIXVM]+\)|\*{1,5}|-|\.{1,5})\s/, next: "listText"},
+            {token: "meta.tag", regex: /^.+(?::{2,4}|;;)(?: |$)/, next: "listText"},
+            {token: "support.function.list.callout", regex: /^(?:<\d+>|\d+>|>) /, next: "text"},
+            {token: "keyword",  regex: /^\+\s*$/, next: "start"}
+        ],
+
+        "text": [
+            {token: ["link", "variable.language"], regex: /((?:https?:\/\/|ftp:\/\/|file:\/\/|mailto:|callto:)[^\s\[]+)(\[.*?\])/},
+            {token: "link", regex: /(?:https?:\/\/|ftp:\/\/|file:\/\/|mailto:|callto:)[^\s\[]+/},
+            {token: "link", regex: /\b[\w\.\/\-]+@[\w\.\/\-]+\b/},
+            {include: "macros"},
+            {include: "paragraphEnd"},
+            {token: "literal", regex:/\+{3,}/, next:"smallPassthrough"},
+            {token: "escape", regex: /\((?:C|TM|R)\)|\.{3}|->|<-|=>|<=|&#(?:\d+|x[a-fA-F\d]+);|(?: |^)--(?=\s+\S)/},
+            {token: "escape", regex: /\\[_*'`+#]|\\{2}[_*'`+#]{2}/},
+            {token: "keyword", regex: /\s\+$/},
+            {token: "text", regex: identifierRe},
+            {token: ["keyword", "string", "keyword"],
+                regex: /(<<[\w\d\-$]+,)(.*?)(>>|$)/},
+            {token: "keyword", regex: /<<[\w\d\-$]+,?|>>/},
+            {token: "constant.character", regex: /\({2,3}.*?\){2,3}/},
+            {token: "keyword", regex: /\[\[.+?\]\]/},
+            {token: "support", regex: /^\[{3}[\w\d =\-]+\]{3}/},
+
+            {include: "quotes"},
+            {token: "empty", regex: /^\s*$/, next: "start"}
+        ],
+
+        "listText": [
+            {include: "listStart"},
+            {include: "text"}
+        ],
+
+        "indentedBlock": [
+            {token: "literal", regex: /^[\s\w].+$/, next: "indentedBlock"},
+            {token: "literal", regex: "", next: "start"}
+        ],
+
+        "listingBlock": [
+            {token: "literal", regex: /^\.{4,}\s*$/, next: "dissallowDelimitedBlock"},
+            {token: "constant.numeric", regex: '<\\d+>'},
+            {token: "literal", regex: '[^<]+'},
+            {token: "literal", regex: '<'}
+        ],
+        "literalBlock": [
+            {token: "literal", regex: /^-{4,}\s*$/, next: "dissallowDelimitedBlock"},
+            {token: "constant.numeric", regex: '<\\d+>'},
+            {token: "literal", regex: '[^<]+'},
+            {token: "literal", regex: '<'}
+        ],
+        "passthroughBlock": [
+            {token: "literal", regex: /^\+{4,}\s*$/, next: "dissallowDelimitedBlock"},
+            {token: "literal", regex: identifierRe + "|\\d+"},
+            {include: "macros"},
+            {token: "literal", regex: "."}
+        ],
+
+        "smallPassthrough": [
+            {token: "literal", regex: /[+]{3,}/, next: "dissallowDelimitedBlock"},
+            {token: "literal", regex: /^\s*$/, next: "dissallowDelimitedBlock"},
+            {token: "literal", regex: identifierRe + "|\\d+"},
+            {include: "macros"}
+        ],
+
+        "commentBlock": [
+            {token: "doc.comment", regex: /^\/{4,}\s*$/, next: "dissallowDelimitedBlock"},
+            {token: "doc.comment", regex: '^.*$'}
+        ],
+        "tableBlock": [
+            {token: "tableBlock", regex: /^\s*\|={3,}\s*$/, next: "dissallowDelimitedBlock"},
+            {token: "tableBlock", regex: /^\s*!={3,}\s*$/, next: "innerTableBlock"},
+            {token: "tableBlock", regex: /\|/},
+            {include: "text", noEscape: true}
+        ],
+        "innerTableBlock": [
+            {token: "tableBlock", regex: /^\s*!={3,}\s*$/, next: "tableBlock"},
+            {token: "tableBlock", regex: /^\s*|={3,}\s*$/, next: "dissallowDelimitedBlock"},
+            {token: "tableBlock", regex: /!/}
+        ],
+        "macros": [
+            {token: "macro", regex: /{[\w\-$]+}/},
+            {token: ["text", "string", "text", "constant.character", "text"], regex: /({)([\w\-$]+)(:)?(.+)?(})/},
+            {token: ["text", "markup.list.macro", "keyword", "string"], regex: /(\w+)(footnote(?:ref)?::?)([^\s\[]+)?(\[.*?\])?/},
+            {token: ["markup.list.macro", "keyword", "string"], regex: /([a-zA-Z\-][\w\.\/\-]*::?)([^\s\[]+)(\[.*?\])?/},
+            {token: ["markup.list.macro", "keyword"], regex: /([a-zA-Z\-][\w\.\/\-]+::?)(\[.*?\])/},
+            {token: "keyword",     regex: /^:.+?:(?= |$)/}
+        ],
+
+        "quotes": [
+            {token: "string.italic", regex: /__[^_\s].*?__/},
+            {token: "string.italic", regex: quoteRule("_")},
+            
+            {token: "keyword.bold", regex: /\*\*[^*\s].*?\*\*/},
+            {token: "keyword.bold", regex: quoteRule("\\*")},
+            
+            {token: "literal", regex: quoteRule("\\+")},
+            {token: "literal", regex: /\+\+[^+\s].*?\+\+/},
+            {token: "literal", regex: /\$\$.+?\$\$/},
+            {token: "literal", regex: quoteRule("`")},
+
+            {token: "keyword", regex: quoteRule("^")},
+            {token: "keyword", regex: quoteRule("~")},
+            {token: "keyword", regex: /##?/},
+            {token: "keyword", regex: /(?:\B|^)``|\b''/}
+        ]
+
+    };
+
+    function quoteRule(ch) {
+        var prefix = /\w/.test(ch) ? "\\b" : "(?:\\B|^)";
+        return prefix + ch + "[^" + ch + "].*?" + ch + "(?![\\w*])";
+    }
+
+    var tokenMap = {
+        macro: "constant.character",
+        tableBlock: "doc.comment",
+        titleUnderline: "markup.heading",
+        singleLineTitle: "markup.heading",
+        pageBreak: "string",
+        option: "string.regexp",
+        otherBlock: "markup.list",
+        literal: "support.function",
+        optionalTitle: "constant.numeric",
+        escape: "constant.language.escape",
+        link: "markup.underline.list"
+    };
+
+    for (var state in this.$rules) {
+        var stateRules = this.$rules[state];
+        for (var i = stateRules.length; i--; ) {
+            var rule = stateRules[i];
+            if (rule.include || typeof rule == "string") {
+                var args = [i, 1].concat(this.$rules[rule.include || rule]);
+                if (rule.noEscape) {
+                    args = args.filter(function(x) {
+                        return !x.next;
+                    });
+                }
+                stateRules.splice.apply(stateRules, args);
+            } else if (rule.token in tokenMap) {
+                rule.token = tokenMap[rule.token];
+            }
+        }
+    }
+};
+oop.inherits(AsciidocHighlightRules, TextHighlightRules);
+
+exports.AsciidocHighlightRules = AsciidocHighlightRules;
+});
+
+ace.define("ace/mode/folding/asciidoc",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var BaseFoldMode = require("./fold_mode").FoldMode;
+var Range = require("../../range").Range;
+
+var FoldMode = exports.FoldMode = function() {};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+    this.foldingStartMarker = /^(?:\|={10,}|[\.\/=\-~^+]{4,}\s*$|={1,5} )/;
+    this.singleLineHeadingRe = /^={1,5}(?=\s+\S)/;
+
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+        if (!this.foldingStartMarker.test(line))
+            return "";
+
+        if (line[0] == "=") {
+            if (this.singleLineHeadingRe.test(line))
+                return "start";
+            if (session.getLine(row - 1).length != session.getLine(row).length)
+                return "";
+            return "start";
+        }
+        if (session.bgTokenizer.getState(row) == "dissallowDelimitedBlock")
+            return "end";
+        return "start";
+    };
+
+    this.getFoldWidgetRange = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+        var startColumn = line.length;
+        var maxRow = session.getLength();
+        var startRow = row;
+        var endRow = row;
+        if (!line.match(this.foldingStartMarker))
+            return;
+
+        var token;
+        function getTokenType(row) {
+            token = session.getTokens(row)[0];
+            return token && token.type;
+        }
+
+        var levels = ["=","-","~","^","+"];
+        var heading = "markup.heading";
+        var singleLineHeadingRe = this.singleLineHeadingRe;
+        function getLevel() {
+            var match = token.value.match(singleLineHeadingRe);
+            if (match)
+                return match[0].length;
+            var level = levels.indexOf(token.value[0]) + 1;
+            if (level == 1) {
+                if (session.getLine(row - 1).length != session.getLine(row).length)
+                    return Infinity;
+            }
+            return level;
+        }
+
+        if (getTokenType(row) == heading) {
+            var startHeadingLevel = getLevel();
+            while (++row < maxRow) {
+                if (getTokenType(row) != heading)
+                    continue;
+                var level = getLevel();
+                if (level <= startHeadingLevel)
+                    break;
+            }
+
+            var isSingleLineHeading = token && token.value.match(this.singleLineHeadingRe);
+            endRow = isSingleLineHeading ? row - 1 : row - 2;
+
+            if (endRow > startRow) {
+                while (endRow > startRow && (!getTokenType(endRow) || token.value[0] == "["))
+                    endRow--;
+            }
+
+            if (endRow > startRow) {
+                var endColumn = session.getLine(endRow).length;
+                return new Range(startRow, startColumn, endRow, endColumn);
+            }
+        } else {
+            var state = session.bgTokenizer.getState(row);
+            if (state == "dissallowDelimitedBlock") {
+                while (row -- > 0) {
+                    if (session.bgTokenizer.getState(row).lastIndexOf("Block") == -1)
+                        break;
+                }
+                endRow = row + 1;
+                if (endRow < startRow) {
+                    var endColumn = session.getLine(row).length;
+                    return new Range(endRow, 5, startRow, startColumn - 5);
+                }
+            } else {
+                while (++row < maxRow) {
+                    if (session.bgTokenizer.getState(row) == "dissallowDelimitedBlock")
+                        break;
+                }
+                endRow = row;
+                if (endRow > startRow) {
+                    var endColumn = session.getLine(row).length;
+                    return new Range(startRow, 5, endRow, endColumn - 5);
+                }
+            }
+        }
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/asciidoc",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var AsciidocHighlightRules = require("./asciidoc_highlight_rules").AsciidocHighlightRules;
+var AsciidocFoldMode = require("./folding/asciidoc").FoldMode;
+
+var Mode = function() {
+    this.HighlightRules = AsciidocHighlightRules;
+    
+    this.foldingRules = new AsciidocFoldMode();    
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+    this.type = "text";
+    this.getNextLineIndent = function(state, line, tab) {
+        if (state == "listblock") {
+            var match = /^((?:.+)?)([-+*][ ]+)/.exec(line);
+            if (match) {
+                return new Array(match[1].length + 1).join(" ") + match[2];
+            } else {
+                return "";
+            }
+        } else {
+            return this.$getIndent(line);
+        }
+    };
+    this.$id = "ace/mode/asciidoc";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/asciidoc"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 422 - 0
services/web/public/js/ace-1.4.3/mode-asl.js

@@ -0,0 +1,422 @@
+ace.define("ace/mode/doc_comment_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var DocCommentHighlightRules = function() {
+    this.$rules = {
+        "start" : [ {
+            token : "comment.doc.tag",
+            regex : "@[\\w\\d_]+" // TODO: fix email addresses
+        }, 
+        DocCommentHighlightRules.getTagRule(),
+        {
+            defaultToken : "comment.doc",
+            caseInsensitive: true
+        }]
+    };
+};
+
+oop.inherits(DocCommentHighlightRules, TextHighlightRules);
+
+DocCommentHighlightRules.getTagRule = function(start) {
+    return {
+        token : "comment.doc.tag.storage.type",
+        regex : "\\b(?:TODO|FIXME|XXX|HACK)\\b"
+    };
+};
+
+DocCommentHighlightRules.getStartRule = function(start) {
+    return {
+        token : "comment.doc", // doc comment
+        regex : "\\/\\*(?=\\*)",
+        next  : start
+    };
+};
+
+DocCommentHighlightRules.getEndRule = function (start) {
+    return {
+        token : "comment.doc", // closing comment
+        regex : "\\*\\/",
+        next  : start
+    };
+};
+
+
+exports.DocCommentHighlightRules = DocCommentHighlightRules;
+
+});
+
+ace.define("ace/mode/asl_highlight_rules",[], function(require, exports, module) {
+    "use strict";
+
+    var oop = require("../lib/oop");
+    var DocCommentHighlightRules = require("./doc_comment_highlight_rules").DocCommentHighlightRules;
+    var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+    var ASLHighlightRules = function() {
+        var keywords = (
+            "Default|DefinitionBlock|Device|Method|Else|ElseIf|For|Function|If|Include|Method|Return|" +
+            "Scope|Switch|Case|While|Break|BreakPoint|Continue|NoOp|Wait"
+        );
+
+        var keywordOperators = (
+            "Add|And|Decrement|Divide|Increment|Index|LAnd|LEqual|LGreater|LGreaterEqual|" +
+            "LLess|LLessEqual|LNot|LNotEqual|LOr|Mod|Multiply|NAnd|NOr|Not|Or|RefOf|Revision|" +
+            "ShiftLeft|ShiftRight|Subtract|XOr|DerefOf"
+        );
+
+        var buildinFunctions = (
+            "AccessAs|Acquire|Alias|BankField|Buffer|Concatenate|ConcatenateResTemplate|" +
+            "CondRefOf|Connection|CopyObject|CreateBitField|CreateByteField|CreateDWordField|" +
+            "CreateField|CreateQWordField|CreateWordField|DataTableRegion|Debug|" +
+            "DMA|DWordIO|DWordMemory|DWordSpace|EisaId|EISAID|EndDependentFn|Event|ExtendedIO|" +
+            "ExtendedMemory|ExtendedSpace|External|Fatal|Field|FindSetLeftBit|FindSetRightBit|" +
+            "FixedDMA|FixedIO|Fprintf|FromBCD|GpioInt|GpioIo|I2CSerialBusV2|IndexField|" +
+            "Interrupt|IO|IRQ|IRQNoFlags|Load|LoadTable|Match|Memory32|Memory32Fixed|" +
+            "Mid|Mutex|Name|Notify|Offset|ObjectType|OperationRegion|Package|PowerResource|Printf|" +
+            "QWordIO|QWordMemory|QWordSpace|RawDataBuffer|Register|Release|Reset|ResourceTemplate|" +
+            "Signal|SizeOf|Sleep|SPISerialBusV2|Stall|StartDependentFn|StartDependentFnNoPri|" +
+            "Store|ThermalZone|Timer|ToBCD|ToBuffer|ToDecimalString|ToInteger|ToPLD|ToString|" +
+            "ToUUID|UARTSerialBusV2|Unicode|Unload|VendorLong|VendorShort|WordBusNumber|WordIO|" +
+            "WordSpace"
+        );
+
+        var flags = (
+            "AttribQuick|AttribSendReceive|AttribByte|AttribBytes|AttribRawBytes|" +
+            "AttribRawProcessBytes|AttribWord|AttribBlock|AttribProcessCall|AttribBlockProcessCall|" +
+            "AnyAcc|ByteAcc|WordAcc|DWordAcc|QWordAcc|BufferAcc|" +
+            "AddressRangeMemory|AddressRangeReserved|AddressRangeNVS|AddressRangeACPI|" +
+            "RegionSpaceKeyword|FFixedHW|PCC|" +
+            "AddressingMode7Bit|AddressingMode10Bit|" +
+            "DataBitsFive|DataBitsSix|DataBitsSeven|DataBitsEight|DataBitsNine|" +
+            "BusMaster|NotBusMaster|" +
+            "ClockPhaseFirst|ClockPhaseSecond|ClockPolarityLow|ClockPolarityHigh|" +
+            "SubDecode|PosDecode|" +
+            "BigEndianing|LittleEndian|" +
+            "FlowControlNone|FlowControlXon|FlowControlHardware|" +
+            "Edge|Level|ActiveHigh|ActiveLow|ActiveBoth|Decode16|Decode10|" +
+            "IoRestrictionNone|IoRestrictionInputOnly|IoRestrictionOutputOnly|" +
+            "IoRestrictionNoneAndPreserve|Lock|NoLock|MTR|MEQ|MLE|MLT|MGE|MGT|" +
+            "MaxFixed|MaxNotFixed|Cacheable|WriteCombining|Prefetchable|NonCacheable|" +
+            "MinFixed|MinNotFixed|" +
+            "ParityTypeNone|ParityTypeSpace|ParityTypeMark|ParityTypeOdd|ParityTypeEven|" +
+            "PullDefault|PullUp|PullDown|PullNone|PolarityHigh|PolarityLow|" +
+            "ISAOnlyRanges|NonISAOnlyRanges|EntireRange|ReadWrite|ReadOnly|" +
+            "UserDefRegionSpace|SystemIO|SystemMemory|PCI_Config|EmbeddedControl|" +
+            "SMBus|SystemCMOS|PciBarTarget|IPMI|GeneralPurposeIO|GenericSerialBus|" +
+            "ResourceConsumer|ResourceProducer|Serialized|NotSerialized|" +
+            "Shared|Exclusive|SharedAndWake|ExclusiveAndWake|ControllerInitiated|DeviceInitiated|" +
+            "StopBitsZero|StopBitsOne|StopBitsOnePlusHalf|StopBitsTwo|" +
+            "Width8Bit|Width16Bit|Width32Bit|Width64Bit|Width128Bit|Width256Bit|" +
+            "SparseTranslation|DenseTranslation|TypeTranslation|TypeStatic|" +
+            "Preserve|WriteAsOnes|WriteAsZeros|Transfer8|Transfer16|Transfer8_16|" +
+            "ThreeWireMode|FourWireMode"
+        );
+
+        var storageTypes = (
+            "UnknownObj|IntObj|StrObj|BuffObj|PkgObj|FieldUnitObj|DeviceObj|" +
+            "EventObj|MethodObj|MutexObj|OpRegionObj|PowerResObj|ProcessorObj|" +
+            "ThermalZoneObj|BuffFieldObj|DDBHandleObj"
+        );
+
+        var buildinConstants = (
+            "__FILE__|__PATH__|__LINE__|__DATE__|__IASL__"
+        );
+
+        var deprecated = (
+            "Memory24|Processor"
+        );
+
+        var keywordMapper = this.createKeywordMapper({
+            "keyword": keywords,
+            "keyword.operator": keywordOperators,
+            "function.buildin": buildinFunctions,
+            "constant.language": buildinConstants,
+            "storage.type": storageTypes,
+            "constant.character": flags,
+            "invalid.deprecated": deprecated
+        }, "identifier");
+
+        this.$rules = {
+            "start" : [
+                {
+                    token : "comment",
+                    regex : "\\/\\/.*$"
+                },
+                DocCommentHighlightRules.getStartRule("doc-start"),
+                {
+                    token : "comment", // multi line comment
+                    regex : "\\/\\*",
+                    next : "comment"
+                },
+                DocCommentHighlightRules.getStartRule("doc-start"),
+                {
+                    token : "comment", // ignored fields / comments
+                    regex : "\\\[",
+                    next : "ignoredfield"
+                }, {
+                    token : "variable",
+                    regex : "\\Local[0-7]|\\Arg[0-6]"
+                }, {
+                    token : "keyword", // pre-compiler directives
+                    regex : "#\\s*(?:define|elif|else|endif|error|if|ifdef|ifndef|include|includebuffer|line|pragma|undef|warning)\\b",
+                    next  : "directive"
+                }, {
+                    token : "string", // single line
+                    regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
+                }, {
+                    token : "constant.character", // single line
+                    regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
+                }, {
+                    token : "constant.numeric", // hex
+                    regex : /0[xX][0-9a-fA-F]+\b/
+                }, {
+                    token : "constant.numeric",
+                    regex : /(One(s)?|Zero|True|False|[0-9]+)\b/
+                }, {
+                    token : keywordMapper,
+                    regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
+                }, {
+                    token : "keyword.operator",
+                    regex : "/|!|\\$|%|&|\\||\\*|\\-\\-|\\-|\\+\\+|\\+|~|==|=|!=|\\^|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\|="
+                }, {
+                    token : "lparen",
+                    regex : "[[({]"
+                }, {
+                    token : "rparen",
+                    regex : "[\\])}]"
+                }, {
+                    token : "text",
+                    regex : "\\s+"
+                }
+            ],
+            "comment" : [
+                {
+                    token : "comment", // closing comment
+                    regex : "\\*\\/",
+                    next : "start"
+                }, {
+                    defaultToken : "comment"
+                }
+            ],
+            "ignoredfield" : [
+                {
+                    token : "comment", // closing ignored fields / comments
+                    regex : "\\\]",
+                    next : "start"
+                }, {
+                    defaultToken : "comment"
+                }
+            ],
+            "directive" : [
+                {
+                    token : "constant.other.multiline",
+                    regex : /\\/
+                },
+                {
+                    token : "constant.other.multiline",
+                    regex : /.*\\/
+                },
+                {
+                    token : "constant.other",
+                    regex : "\\s*<.+?>*s",
+                    next : "start"
+                },
+                {
+                    token : "constant.other", // single line
+                    regex : '\\s*["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]*s',
+                    next : "start"
+                },
+                {
+                    token : "constant.other", // single line
+                    regex : "\\s*['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']",
+                    next : "start"
+                },
+                {
+                    token : "constant.other",
+                    regex : /[^\\\/]+/,
+                    next : "start"
+                }
+            ]
+        };
+
+        this.embedRules(DocCommentHighlightRules, "doc-",
+            [ DocCommentHighlightRules.getEndRule("start") ]);
+    };
+
+    oop.inherits(ASLHighlightRules, TextHighlightRules);
+
+    exports.ASLHighlightRules = ASLHighlightRules;
+});
+
+ace.define("ace/mode/folding/cstyle",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Range = require("../../range").Range;
+var BaseFoldMode = require("./fold_mode").FoldMode;
+
+var FoldMode = exports.FoldMode = function(commentRegex) {
+    if (commentRegex) {
+        this.foldingStartMarker = new RegExp(
+            this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start)
+        );
+        this.foldingStopMarker = new RegExp(
+            this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end)
+        );
+    }
+};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+    
+    this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/;
+    this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/;
+    this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/;
+    this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/;
+    this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/;
+    this._getFoldWidgetBase = this.getFoldWidget;
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+    
+        if (this.singleLineBlockCommentRe.test(line)) {
+            if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line))
+                return "";
+        }
+    
+        var fw = this._getFoldWidgetBase(session, foldStyle, row);
+    
+        if (!fw && this.startRegionRe.test(line))
+            return "start"; // lineCommentRegionStart
+    
+        return fw;
+    };
+
+    this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) {
+        var line = session.getLine(row);
+        
+        if (this.startRegionRe.test(line))
+            return this.getCommentRegionBlock(session, line, row);
+        
+        var match = line.match(this.foldingStartMarker);
+        if (match) {
+            var i = match.index;
+
+            if (match[1])
+                return this.openingBracketBlock(session, match[1], row, i);
+                
+            var range = session.getCommentFoldRange(row, i + match[0].length, 1);
+            
+            if (range && !range.isMultiLine()) {
+                if (forceMultiline) {
+                    range = this.getSectionRange(session, row);
+                } else if (foldStyle != "all")
+                    range = null;
+            }
+            
+            return range;
+        }
+
+        if (foldStyle === "markbegin")
+            return;
+
+        var match = line.match(this.foldingStopMarker);
+        if (match) {
+            var i = match.index + match[0].length;
+
+            if (match[1])
+                return this.closingBracketBlock(session, match[1], row, i);
+
+            return session.getCommentFoldRange(row, i, -1);
+        }
+    };
+    
+    this.getSectionRange = function(session, row) {
+        var line = session.getLine(row);
+        var startIndent = line.search(/\S/);
+        var startRow = row;
+        var startColumn = line.length;
+        row = row + 1;
+        var endRow = row;
+        var maxRow = session.getLength();
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var indent = line.search(/\S/);
+            if (indent === -1)
+                continue;
+            if  (startIndent > indent)
+                break;
+            var subRange = this.getFoldWidgetRange(session, "all", row);
+            
+            if (subRange) {
+                if (subRange.start.row <= startRow) {
+                    break;
+                } else if (subRange.isMultiLine()) {
+                    row = subRange.end.row;
+                } else if (startIndent == indent) {
+                    break;
+                }
+            }
+            endRow = row;
+        }
+        
+        return new Range(startRow, startColumn, endRow, session.getLine(endRow).length);
+    };
+    this.getCommentRegionBlock = function(session, line, row) {
+        var startColumn = line.search(/\s*$/);
+        var maxRow = session.getLength();
+        var startRow = row;
+        
+        var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/;
+        var depth = 1;
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var m = re.exec(line);
+            if (!m) continue;
+            if (m[1]) depth--;
+            else depth++;
+
+            if (!depth) break;
+        }
+
+        var endRow = row;
+        if (endRow > startRow) {
+            return new Range(startRow, startColumn, endRow, line.length);
+        }
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/asl",[], function (require, exports, module) {
+    "use strict";
+
+    var oop = require("../lib/oop");
+    var TextMode = require("./text").Mode;
+    var ASLHighlightRules = require("./asl_highlight_rules").ASLHighlightRules;
+    var FoldMode = require("./folding/cstyle").FoldMode;
+
+    var Mode = function () {
+        this.HighlightRules = ASLHighlightRules;
+        this.foldingRules = new FoldMode();
+        this.$behaviour = this.$defaultBehaviour;
+    };
+    oop.inherits(Mode, TextMode);
+
+    (function () {
+        this.$id = "ace/mode/asl";
+    }).call(Mode.prototype);
+
+    exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/asl"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

Fișier diff suprimat deoarece este prea mare
+ 10 - 0
services/web/public/js/ace-1.4.3/mode-assembly_x86.js


Fișier diff suprimat deoarece este prea mare
+ 8 - 0
services/web/public/js/ace-1.4.3/mode-autohotkey.js


+ 231 - 0
services/web/public/js/ace-1.4.3/mode-batchfile.js

@@ -0,0 +1,231 @@
+ace.define("ace/mode/batchfile_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var BatchFileHighlightRules = function() {
+
+    this.$rules = { start: 
+       [ { token: 'keyword.command.dosbatch',
+           regex: '\\b(?:append|assoc|at|attrib|break|cacls|cd|chcp|chdir|chkdsk|chkntfs|cls|cmd|color|comp|compact|convert|copy|date|del|dir|diskcomp|diskcopy|doskey|echo|endlocal|erase|fc|find|findstr|format|ftype|graftabl|help|keyb|label|md|mkdir|mode|more|move|path|pause|popd|print|prompt|pushd|rd|recover|ren|rename|replace|restore|rmdir|set|setlocal|shift|sort|start|subst|time|title|tree|type|ver|verify|vol|xcopy)\\b',
+           caseInsensitive: true },
+         { token: 'keyword.control.statement.dosbatch',
+           regex: '\\b(?:goto|call|exit)\\b',
+           caseInsensitive: true },
+         { token: 'keyword.control.conditional.if.dosbatch',
+           regex: '\\bif\\s+not\\s+(?:exist|defined|errorlevel|cmdextversion)\\b',
+           caseInsensitive: true },
+         { token: 'keyword.control.conditional.dosbatch',
+           regex: '\\b(?:if|else)\\b',
+           caseInsensitive: true },
+         { token: 'keyword.control.repeat.dosbatch',
+           regex: '\\bfor\\b',
+           caseInsensitive: true },
+         { token: 'keyword.operator.dosbatch',
+           regex: '\\b(?:EQU|NEQ|LSS|LEQ|GTR|GEQ)\\b' },
+         { token: ['doc.comment', 'comment'],
+           regex: '(?:^|\\b)(rem)($|\\s.*$)',
+           caseInsensitive: true },
+         { token: 'comment.line.colons.dosbatch',
+           regex: '::.*$' },
+         { include: 'variable' },
+         { token: 'punctuation.definition.string.begin.shell',
+           regex: '"',
+           push: [ 
+              { token: 'punctuation.definition.string.end.shell', regex: '"', next: 'pop' },
+              { include: 'variable' },
+              { defaultToken: 'string.quoted.double.dosbatch' } ] },
+         { token: 'keyword.operator.pipe.dosbatch', regex: '[|]' },
+         { token: 'keyword.operator.redirect.shell',
+           regex: '&>|\\d*>&\\d*|\\d*(?:>>|>|<)|\\d*<&|\\d*<>' } ],
+        variable: [
+         { token: 'constant.numeric', regex: '%%\\w+|%[*\\d]|%\\w+%'},
+         { token: 'constant.numeric', regex: '%~\\d+'},
+         { token: ['markup.list', 'constant.other', 'markup.list'],
+            regex: '(%)(\\w+)(%?)' }]};
+    
+    this.normalizeRules();
+};
+
+BatchFileHighlightRules.metaData = { name: 'Batch File',
+      scopeName: 'source.dosbatch',
+      fileTypes: [ 'bat' ] };
+
+
+oop.inherits(BatchFileHighlightRules, TextHighlightRules);
+
+exports.BatchFileHighlightRules = BatchFileHighlightRules;
+});
+
+ace.define("ace/mode/folding/cstyle",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Range = require("../../range").Range;
+var BaseFoldMode = require("./fold_mode").FoldMode;
+
+var FoldMode = exports.FoldMode = function(commentRegex) {
+    if (commentRegex) {
+        this.foldingStartMarker = new RegExp(
+            this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start)
+        );
+        this.foldingStopMarker = new RegExp(
+            this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end)
+        );
+    }
+};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+    
+    this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/;
+    this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/;
+    this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/;
+    this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/;
+    this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/;
+    this._getFoldWidgetBase = this.getFoldWidget;
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+    
+        if (this.singleLineBlockCommentRe.test(line)) {
+            if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line))
+                return "";
+        }
+    
+        var fw = this._getFoldWidgetBase(session, foldStyle, row);
+    
+        if (!fw && this.startRegionRe.test(line))
+            return "start"; // lineCommentRegionStart
+    
+        return fw;
+    };
+
+    this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) {
+        var line = session.getLine(row);
+        
+        if (this.startRegionRe.test(line))
+            return this.getCommentRegionBlock(session, line, row);
+        
+        var match = line.match(this.foldingStartMarker);
+        if (match) {
+            var i = match.index;
+
+            if (match[1])
+                return this.openingBracketBlock(session, match[1], row, i);
+                
+            var range = session.getCommentFoldRange(row, i + match[0].length, 1);
+            
+            if (range && !range.isMultiLine()) {
+                if (forceMultiline) {
+                    range = this.getSectionRange(session, row);
+                } else if (foldStyle != "all")
+                    range = null;
+            }
+            
+            return range;
+        }
+
+        if (foldStyle === "markbegin")
+            return;
+
+        var match = line.match(this.foldingStopMarker);
+        if (match) {
+            var i = match.index + match[0].length;
+
+            if (match[1])
+                return this.closingBracketBlock(session, match[1], row, i);
+
+            return session.getCommentFoldRange(row, i, -1);
+        }
+    };
+    
+    this.getSectionRange = function(session, row) {
+        var line = session.getLine(row);
+        var startIndent = line.search(/\S/);
+        var startRow = row;
+        var startColumn = line.length;
+        row = row + 1;
+        var endRow = row;
+        var maxRow = session.getLength();
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var indent = line.search(/\S/);
+            if (indent === -1)
+                continue;
+            if  (startIndent > indent)
+                break;
+            var subRange = this.getFoldWidgetRange(session, "all", row);
+            
+            if (subRange) {
+                if (subRange.start.row <= startRow) {
+                    break;
+                } else if (subRange.isMultiLine()) {
+                    row = subRange.end.row;
+                } else if (startIndent == indent) {
+                    break;
+                }
+            }
+            endRow = row;
+        }
+        
+        return new Range(startRow, startColumn, endRow, session.getLine(endRow).length);
+    };
+    this.getCommentRegionBlock = function(session, line, row) {
+        var startColumn = line.search(/\s*$/);
+        var maxRow = session.getLength();
+        var startRow = row;
+        
+        var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/;
+        var depth = 1;
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var m = re.exec(line);
+            if (!m) continue;
+            if (m[1]) depth--;
+            else depth++;
+
+            if (!depth) break;
+        }
+
+        var endRow = row;
+        if (endRow > startRow) {
+            return new Range(startRow, startColumn, endRow, line.length);
+        }
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/batchfile",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var BatchFileHighlightRules = require("./batchfile_highlight_rules").BatchFileHighlightRules;
+var FoldMode = require("./folding/cstyle").FoldMode;
+
+var Mode = function() {
+    this.HighlightRules = BatchFileHighlightRules;
+    this.foldingRules = new FoldMode();
+    this.$behaviour = this.$defaultBehaviour;
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+    this.lineCommentStart = "::";
+    this.blockComment = "";
+    this.$id = "ace/mode/batchfile";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/batchfile"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 335 - 0
services/web/public/js/ace-1.4.3/mode-bro.js

@@ -0,0 +1,335 @@
+ace.define("ace/mode/bro_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var BroHighlightRules = function() {
+
+    this.$rules = {
+        start: [{
+            token: "punctuation.definition.comment.bro",
+            regex: /#/,
+            push: [{
+                token: "comment.line.number-sign.bro",
+                regex: /$/,
+                next: "pop"
+            }, {
+                defaultToken: "comment.line.number-sign.bro"
+            }]
+        }, {
+            token: "keyword.control.bro",
+            regex: /\b(?:break|case|continue|else|for|if|return|switch|next|when|timeout|schedule)\b/
+        }, {
+            token: [
+                "meta.function.bro",
+                "meta.function.bro",
+                "storage.type.bro",
+                "meta.function.bro",
+                "entity.name.function.bro",
+                "meta.function.bro"
+            ],
+            regex: /^(\s*)(?:function|hook|event)(\s*)(.*)(\s*\()(.*)(\).*$)/
+        }, {
+            token: "storage.type.bro",
+            regex: /\b(?:bool|enum|double|int|count|port|addr|subnet|any|file|interval|time|string|table|vector|set|record|pattern|hook)\b/
+        }, {
+            token: "storage.modifier.bro",
+            regex: /\b(?:global|const|redef|local|&(?:optional|rotate_interval|rotate_size|add_func|del_func|expire_func|expire_create|expire_read|expire_write|persistent|synchronized|encrypt|mergeable|priority|group|type_column|log|error_handler))\b/
+        }, {
+            token: "keyword.operator.bro",
+            regex: /\s*(?:\||&&|(?:>|<|!)=?|==)\s*|\b!?in\b/
+        }, {
+            token: "constant.language.bro",
+            regex: /\b(?:T|F)\b/
+        }, {
+            token: "constant.numeric.bro",
+            regex: /\b(?:0(?:x|X)[0-9a-fA-F]*|(?:[0-9]+\.?[0-9]*|\.[0-9]+)(?:(?:e|E)(?:\+|-)?[0-9]+)?)(?:\/(?:tcp|udp|icmp)|\s*(?:u?sec|min|hr|day)s?)?\b/
+        }, {
+            token: "punctuation.definition.string.begin.bro",
+            regex: /"/,
+            push: [{
+                token: "punctuation.definition.string.end.bro",
+                regex: /"/,
+                next: "pop"
+            }, {
+                include: "#string_escaped_char"
+            }, {
+                include: "#string_placeholder"
+            }, {
+                defaultToken: "string.quoted.double.bro"
+            }]
+        }, {
+            token: "punctuation.definition.string.begin.bro",
+            regex: /\//,
+            push: [{
+                token: "punctuation.definition.string.end.bro",
+                regex: /\//,
+                next: "pop"
+            }, {
+                include: "#string_escaped_char"
+            }, {
+                include: "#string_placeholder"
+            }, {
+                defaultToken: "string.quoted.regex.bro"
+            }]
+        }, {
+            token: [
+                "meta.preprocessor.bro.load",
+                "keyword.other.special-method.bro"
+            ],
+            regex: /^(\s*)(\@load(?:-sigs)?)\b/,
+            push: [{
+                token: [],
+                regex: /(?=\#)|$/,
+                next: "pop"
+            }, {
+                defaultToken: "meta.preprocessor.bro.load"
+            }]
+        }, {
+            token: [
+                "meta.preprocessor.bro.if",
+                "keyword.other.special-method.bro",
+                "meta.preprocessor.bro.if"
+            ],
+            regex: /^(\s*)(\@endif|\@if(?:n?def)?)(.*$)/,
+            push: [{
+                token: [],
+                regex: /$/,
+                next: "pop"
+            }, {
+                defaultToken: "meta.preprocessor.bro.if"
+            }]
+        }],
+        "#disabled": [{
+            token: "text",
+            regex: /^\s*\@if(?:n?def)?\b.*$/,
+            push: [{
+                token: "text",
+                regex: /^\s*\@endif\b.*$/,
+                next: "pop"
+            }, {
+                include: "#disabled"
+            }, {
+                include: "#pragma-mark"
+            }],
+            comment: "eat nested preprocessor ifdefs"
+        }],
+        "#preprocessor-rule-other": [{
+            token: [
+                "text",
+                "meta.preprocessor.bro",
+                "meta.preprocessor.bro",
+                "text"
+            ],
+            regex: /^(\s*)(@if)((?:n?def)?)\b(.*?)(?:(?=)|$)/,
+            push: [{
+                token: ["text", "meta.preprocessor.bro", "text"],
+                regex: /^(\s*)(@endif)\b(.*$)/,
+                next: "pop"
+            }, {
+                include: "$base"
+            }]
+        }],
+        "#string_escaped_char": [{
+            token: "constant.character.escape.bro",
+            regex: /\\(?:\\|[abefnprtv'"?]|[0-3]\d{,2}|[4-7]\d?|x[a-fA-F0-9]{,2})/
+        }, {
+            token: "invalid.illegal.unknown-escape.bro",
+            regex: /\\./
+        }],
+        "#string_placeholder": [{
+            token: "constant.other.placeholder.bro",
+            regex: /%(?:\d+\$)?[#0\- +']*[,;:_]?(?:-?\d+|\*(?:-?\d+\$)?)?(?:\.(?:-?\d+|\*(?:-?\d+\$)?)?)?(?:hh|h|ll|l|j|t|z|q|L|vh|vl|v|hv|hl)?[diouxXDOUeEfFgGaACcSspn%]/
+        }, {
+            token: "invalid.illegal.placeholder.bro",
+            regex: /%/
+        }]
+    };
+    
+    this.normalizeRules();
+};
+
+BroHighlightRules.metaData = {
+    fileTypes: ["bro"],
+    foldingStartMarker: "^(\\@if(n?def)?)",
+    foldingStopMarker: "^\\@endif",
+    keyEquivalent: "@B",
+    name: "Bro",
+    scopeName: "source.bro"
+};
+
+
+oop.inherits(BroHighlightRules, TextHighlightRules);
+
+exports.BroHighlightRules = BroHighlightRules;
+});
+
+ace.define("ace/mode/folding/cstyle",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Range = require("../../range").Range;
+var BaseFoldMode = require("./fold_mode").FoldMode;
+
+var FoldMode = exports.FoldMode = function(commentRegex) {
+    if (commentRegex) {
+        this.foldingStartMarker = new RegExp(
+            this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start)
+        );
+        this.foldingStopMarker = new RegExp(
+            this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end)
+        );
+    }
+};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+    
+    this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/;
+    this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/;
+    this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/;
+    this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/;
+    this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/;
+    this._getFoldWidgetBase = this.getFoldWidget;
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+    
+        if (this.singleLineBlockCommentRe.test(line)) {
+            if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line))
+                return "";
+        }
+    
+        var fw = this._getFoldWidgetBase(session, foldStyle, row);
+    
+        if (!fw && this.startRegionRe.test(line))
+            return "start"; // lineCommentRegionStart
+    
+        return fw;
+    };
+
+    this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) {
+        var line = session.getLine(row);
+        
+        if (this.startRegionRe.test(line))
+            return this.getCommentRegionBlock(session, line, row);
+        
+        var match = line.match(this.foldingStartMarker);
+        if (match) {
+            var i = match.index;
+
+            if (match[1])
+                return this.openingBracketBlock(session, match[1], row, i);
+                
+            var range = session.getCommentFoldRange(row, i + match[0].length, 1);
+            
+            if (range && !range.isMultiLine()) {
+                if (forceMultiline) {
+                    range = this.getSectionRange(session, row);
+                } else if (foldStyle != "all")
+                    range = null;
+            }
+            
+            return range;
+        }
+
+        if (foldStyle === "markbegin")
+            return;
+
+        var match = line.match(this.foldingStopMarker);
+        if (match) {
+            var i = match.index + match[0].length;
+
+            if (match[1])
+                return this.closingBracketBlock(session, match[1], row, i);
+
+            return session.getCommentFoldRange(row, i, -1);
+        }
+    };
+    
+    this.getSectionRange = function(session, row) {
+        var line = session.getLine(row);
+        var startIndent = line.search(/\S/);
+        var startRow = row;
+        var startColumn = line.length;
+        row = row + 1;
+        var endRow = row;
+        var maxRow = session.getLength();
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var indent = line.search(/\S/);
+            if (indent === -1)
+                continue;
+            if  (startIndent > indent)
+                break;
+            var subRange = this.getFoldWidgetRange(session, "all", row);
+            
+            if (subRange) {
+                if (subRange.start.row <= startRow) {
+                    break;
+                } else if (subRange.isMultiLine()) {
+                    row = subRange.end.row;
+                } else if (startIndent == indent) {
+                    break;
+                }
+            }
+            endRow = row;
+        }
+        
+        return new Range(startRow, startColumn, endRow, session.getLine(endRow).length);
+    };
+    this.getCommentRegionBlock = function(session, line, row) {
+        var startColumn = line.search(/\s*$/);
+        var maxRow = session.getLength();
+        var startRow = row;
+        
+        var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/;
+        var depth = 1;
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var m = re.exec(line);
+            if (!m) continue;
+            if (m[1]) depth--;
+            else depth++;
+
+            if (!depth) break;
+        }
+
+        var endRow = row;
+        if (endRow > startRow) {
+            return new Range(startRow, startColumn, endRow, line.length);
+        }
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/bro",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var BroHighlightRules = require("./bro_highlight_rules").BroHighlightRules;
+var FoldMode = require("./folding/cstyle").FoldMode;
+
+var Mode = function() {
+    this.HighlightRules = BroHighlightRules;
+    this.foldingRules = new FoldMode();
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+    this.$id = "ace/mode/bro";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/bro"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 294 - 0
services/web/public/js/ace-1.4.3/mode-c9search.js

@@ -0,0 +1,294 @@
+ace.define("ace/mode/c9search_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var lang = require("../lib/lang");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+function safeCreateRegexp(source, flag) {
+    try {
+        return new RegExp(source, flag);
+    } catch(e) {}
+}
+
+var C9SearchHighlightRules = function() {
+    this.$rules = {
+        "start" : [
+            {
+                tokenNames : ["c9searchresults.constant.numeric", "c9searchresults.text", "c9searchresults.text", "c9searchresults.keyword"],
+                regex : /(^\s+[0-9]+)(:)(\d*\s?)([^\r\n]+)/,
+                onMatch : function(val, state, stack) {
+                    var values = this.splitRegex.exec(val);
+                    var types = this.tokenNames;
+                    var tokens = [{
+                        type: types[0],
+                        value: values[1]
+                    }, {
+                        type: types[1],
+                        value: values[2]
+                    }];
+                    
+                    if (values[3]) {
+                        if (values[3] == " ")
+                            tokens[1] = { type: types[1], value: values[2] + " " };
+                        else
+                            tokens.push({ type: types[1], value: values[3] });
+                    }
+                    var regex = stack[1];
+                    var str = values[4];
+                    
+                    var m;
+                    var last = 0;
+                    if (regex && regex.exec) {
+                        regex.lastIndex = 0;
+                        while (m = regex.exec(str)) {
+                            var skipped = str.substring(last, m.index);
+                            last = regex.lastIndex;
+                            if (skipped)
+                                tokens.push({type: types[2], value: skipped});
+                            if (m[0])
+                                tokens.push({type: types[3], value: m[0]});
+                            else if (!skipped)
+                                break;
+                        }
+                    }
+                    if (last < str.length)
+                        tokens.push({type: types[2], value: str.substr(last)});
+                    return tokens;
+                }
+            },
+            {
+                regex : "^Searching for [^\\r\\n]*$",
+                onMatch: function(val, state, stack) {
+                    var parts = val.split("\x01");
+                    if (parts.length < 3)
+                        return "text";
+
+                    var options, search;
+                    
+                    var i = 0;
+                    var tokens = [{
+                        value: parts[i++] + "'",
+                        type: "text"
+                    }, {
+                        value: search = parts[i++],
+                        type: "text" // "c9searchresults.keyword"
+                    }, {
+                        value: "'" + parts[i++],
+                        type: "text"
+                    }];
+                    if (parts[2] !== " in") {
+                        tokens.push({
+                            value: "'" + parts[i++] + "'",
+                            type: "text"
+                        }, {
+                            value: parts[i++],
+                            type: "text"
+                        });
+                    }
+                    tokens.push({
+                        value: " " + parts[i++] + " ",
+                        type: "text"
+                    });
+                    if (parts[i+1]) {
+                        options = parts[i+1];
+                        tokens.push({
+                            value: "(" + parts[i+1] + ")",
+                            type: "text"
+                        });
+                        i += 1;
+                    } else {
+                        i -= 1;
+                    }
+                    while (i++ < parts.length) {
+                        parts[i] && tokens.push({
+                            value: parts[i],
+                            type: "text"
+                        });
+                    }
+                    
+                    if (search) {
+                        if (!/regex/.test(options))
+                            search = lang.escapeRegExp(search);
+                        if (/whole/.test(options))
+                            search = "\\b" + search + "\\b";
+                    }
+                    
+                    var regex = search && safeCreateRegexp(
+                        "(" + search + ")",
+                        / sensitive/.test(options) ? "g" : "ig"
+                    );
+                    if (regex) {
+                        stack[0] = state;
+                        stack[1] = regex;
+                    }
+                    
+                    return tokens;
+                }
+            },
+            {
+                regex : "^(?=Found \\d+ matches)",
+                token : "text",
+                next : "numbers"
+            },
+            {
+                token : "string", // single line
+                regex : "^\\S:?[^:]+",
+                next : "numbers"
+            }
+        ],
+        numbers:[{
+            regex : "\\d+",
+            token : "constant.numeric"
+        }, {
+            regex : "$",
+            token : "text",
+            next : "start"
+        }]
+    };
+    this.normalizeRules();
+};
+
+oop.inherits(C9SearchHighlightRules, TextHighlightRules);
+
+exports.C9SearchHighlightRules = C9SearchHighlightRules;
+
+});
+
+ace.define("ace/mode/matching_brace_outdent",[], function(require, exports, module) {
+"use strict";
+
+var Range = require("../range").Range;
+
+var MatchingBraceOutdent = function() {};
+
+(function() {
+
+    this.checkOutdent = function(line, input) {
+        if (! /^\s+$/.test(line))
+            return false;
+
+        return /^\s*\}/.test(input);
+    };
+
+    this.autoOutdent = function(doc, row) {
+        var line = doc.getLine(row);
+        var match = line.match(/^(\s*\})/);
+
+        if (!match) return 0;
+
+        var column = match[1].length;
+        var openBracePos = doc.findMatchingBracket({row: row, column: column});
+
+        if (!openBracePos || openBracePos.row == row) return 0;
+
+        var indent = this.$getIndent(doc.getLine(openBracePos.row));
+        doc.replace(new Range(row, 0, row, column-1), indent);
+    };
+
+    this.$getIndent = function(line) {
+        return line.match(/^\s*/)[0];
+    };
+
+}).call(MatchingBraceOutdent.prototype);
+
+exports.MatchingBraceOutdent = MatchingBraceOutdent;
+});
+
+ace.define("ace/mode/folding/c9search",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Range = require("../../range").Range;
+var BaseFoldMode = require("./fold_mode").FoldMode;
+
+var FoldMode = exports.FoldMode = function() {};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+
+    this.foldingStartMarker = /^(\S.*:|Searching for.*)$/;
+    this.foldingStopMarker = /^(\s+|Found.*)$/;
+    
+    this.getFoldWidgetRange = function(session, foldStyle, row) {
+        var lines = session.doc.getAllLines(row);
+        var line = lines[row];
+        var level1 = /^(Found.*|Searching for.*)$/;
+        var level2 = /^(\S.*:|\s*)$/;
+        var re = level1.test(line) ? level1 : level2;
+        
+        var startRow = row;
+        var endRow = row;
+
+        if (this.foldingStartMarker.test(line)) {
+            for (var i = row + 1, l = session.getLength(); i < l; i++) {
+                if (re.test(lines[i]))
+                    break;
+            }
+            endRow = i;
+        }
+        else if (this.foldingStopMarker.test(line)) {
+            for (var i = row - 1; i >= 0; i--) {
+                line = lines[i];
+                if (re.test(line))
+                    break;
+            }
+            startRow = i;
+        }
+        if (startRow != endRow) {
+            var col = line.length;
+            if (re === level1)
+                col = line.search(/\(Found[^)]+\)$|$/);
+            return new Range(startRow, col, endRow, 0);
+        }
+    };
+    
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/c9search",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var C9SearchHighlightRules = require("./c9search_highlight_rules").C9SearchHighlightRules;
+var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent;
+var C9StyleFoldMode = require("./folding/c9search").FoldMode;
+
+var Mode = function() {
+    this.HighlightRules = C9SearchHighlightRules;
+    this.$outdent = new MatchingBraceOutdent();
+    this.foldingRules = new C9StyleFoldMode();
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+    
+    this.getNextLineIndent = function(state, line, tab) {
+        var indent = this.$getIndent(line);
+        return indent;
+    };
+
+    this.checkOutdent = function(state, line, input) {
+        return this.$outdent.checkOutdent(line, input);
+    };
+
+    this.autoOutdent = function(state, doc, row) {
+        this.$outdent.autoOutdent(doc, row);
+    };
+
+    this.$id = "ace/mode/c9search";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+
+});
+                (function() {
+                    ace.require(["ace/mode/c9search"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

Fișier diff suprimat deoarece este prea mare
+ 56 - 0
services/web/public/js/ace-1.4.3/mode-c_cpp.js


+ 211 - 0
services/web/public/js/ace-1.4.3/mode-cirru.js

@@ -0,0 +1,211 @@
+ace.define("ace/mode/cirru_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+var CirruHighlightRules = function() {
+    this.$rules = {
+        start: [{
+            token: 'constant.numeric',
+            regex: /[\d\.]+/
+        }, {
+            token: 'comment.line.double-dash',
+            regex: /--/,
+            next: 'comment'
+        }, {
+            token: 'storage.modifier',
+            regex: /\(/
+        }, {
+            token: 'storage.modifier',
+            regex: /,/,
+            next: 'line'
+        }, {
+            token: 'support.function',
+            regex: /[^\(\)"\s]+/,
+            next: 'line'
+        }, {
+            token: 'string.quoted.double',
+            regex: /"/,
+            next: 'string'
+        }, {
+            token: 'storage.modifier',
+            regex: /\)/
+        }],
+        comment: [{
+            token: 'comment.line.double-dash',
+            regex: / +[^\n]+/,
+            next: 'start'
+        }],
+        string: [{
+            token: 'string.quoted.double',
+            regex: /"/,
+            next: 'line'
+        }, {
+            token: 'constant.character.escape',
+            regex: /\\/,
+            next: 'escape'
+        }, {
+            token: 'string.quoted.double',
+            regex: /[^\\"]+/
+        }],
+        escape: [{
+            token: 'constant.character.escape',
+            regex: /./,
+            next: 'string'
+        }],
+        line: [{
+            token: 'constant.numeric',
+            regex: /[\d\.]+/
+        }, {
+            token: 'markup.raw',
+            regex: /^\s*/,
+            next: 'start'
+        }, {
+            token: 'storage.modifier',
+            regex: /\$/,
+            next: 'start'
+        }, {
+            token: 'variable.parameter',
+            regex: /[^\(\)"\s]+/
+        }, {
+            token: 'storage.modifier',
+            regex: /\(/,
+            next: 'start'
+        }, {
+            token: 'storage.modifier',
+            regex: /\)/
+        }, {
+            token: 'markup.raw',
+            regex: /^ */,
+            next: 'start'
+        }, {
+            token: 'string.quoted.double',
+            regex: /"/,
+            next: 'string'
+        }]
+    };
+
+};
+
+oop.inherits(CirruHighlightRules, TextHighlightRules);
+
+exports.CirruHighlightRules = CirruHighlightRules;
+});
+
+ace.define("ace/mode/folding/coffee",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var BaseFoldMode = require("./fold_mode").FoldMode;
+var Range = require("../../range").Range;
+
+var FoldMode = exports.FoldMode = function() {};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+
+    this.getFoldWidgetRange = function(session, foldStyle, row) {
+        var range = this.indentationBlock(session, row);
+        if (range)
+            return range;
+
+        var re = /\S/;
+        var line = session.getLine(row);
+        var startLevel = line.search(re);
+        if (startLevel == -1 || line[startLevel] != "#")
+            return;
+
+        var startColumn = line.length;
+        var maxRow = session.getLength();
+        var startRow = row;
+        var endRow = row;
+
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var level = line.search(re);
+
+            if (level == -1)
+                continue;
+
+            if (line[level] != "#")
+                break;
+
+            endRow = row;
+        }
+
+        if (endRow > startRow) {
+            var endColumn = session.getLine(endRow).length;
+            return new Range(startRow, startColumn, endRow, endColumn);
+        }
+    };
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+        var indent = line.search(/\S/);
+        var next = session.getLine(row + 1);
+        var prev = session.getLine(row - 1);
+        var prevIndent = prev.search(/\S/);
+        var nextIndent = next.search(/\S/);
+
+        if (indent == -1) {
+            session.foldWidgets[row - 1] = prevIndent!= -1 && prevIndent < nextIndent ? "start" : "";
+            return "";
+        }
+        if (prevIndent == -1) {
+            if (indent == nextIndent && line[indent] == "#" && next[indent] == "#") {
+                session.foldWidgets[row - 1] = "";
+                session.foldWidgets[row + 1] = "";
+                return "start";
+            }
+        } else if (prevIndent == indent && line[indent] == "#" && prev[indent] == "#") {
+            if (session.getLine(row - 2).search(/\S/) == -1) {
+                session.foldWidgets[row - 1] = "start";
+                session.foldWidgets[row + 1] = "";
+                return "";
+            }
+        }
+
+        if (prevIndent!= -1 && prevIndent < indent)
+            session.foldWidgets[row - 1] = "start";
+        else
+            session.foldWidgets[row - 1] = "";
+
+        if (indent < nextIndent)
+            return "start";
+        else
+            return "";
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/cirru",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var CirruHighlightRules = require("./cirru_highlight_rules").CirruHighlightRules;
+var CoffeeFoldMode = require("./folding/coffee").FoldMode;
+
+var Mode = function() {
+    this.HighlightRules = CirruHighlightRules;
+    this.foldingRules = new CoffeeFoldMode();
+    this.$behaviour = this.$defaultBehaviour;
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+    this.lineCommentStart = "--";
+    this.$id = "ace/mode/cirru";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/cirru"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 315 - 0
services/web/public/js/ace-1.4.3/mode-clojure.js

@@ -0,0 +1,315 @@
+ace.define("ace/mode/clojure_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+
+
+var ClojureHighlightRules = function() {
+
+    var builtinFunctions = (
+        '* *1 *2 *3 *agent* *allow-unresolved-vars* *assert* *clojure-version* ' +
+        '*command-line-args* *compile-files* *compile-path* *e *err* *file* ' +
+        '*flush-on-newline* *in* *macro-meta* *math-context* *ns* *out* ' +
+        '*print-dup* *print-length* *print-level* *print-meta* *print-readably* ' +
+        '*read-eval* *source-path* *use-context-classloader* ' +
+        '*warn-on-reflection* + - -> ->> .. / < <= = ' +
+        '== > &gt; >= &gt;= accessor aclone ' +
+        'add-classpath add-watch agent agent-errors aget alength alias all-ns ' +
+        'alter alter-meta! alter-var-root amap ancestors and apply areduce ' +
+        'array-map aset aset-boolean aset-byte aset-char aset-double aset-float ' +
+        'aset-int aset-long aset-short assert assoc assoc! assoc-in associative? ' +
+        'atom await await-for await1 bases bean bigdec bigint binding bit-and ' +
+        'bit-and-not bit-clear bit-flip bit-not bit-or bit-set bit-shift-left ' +
+        'bit-shift-right bit-test bit-xor boolean boolean-array booleans ' +
+        'bound-fn bound-fn* butlast byte byte-array bytes cast char char-array ' +
+        'char-escape-string char-name-string char? chars chunk chunk-append ' +
+        'chunk-buffer chunk-cons chunk-first chunk-next chunk-rest chunked-seq? ' +
+        'class class? clear-agent-errors clojure-version coll? comment commute ' +
+        'comp comparator compare compare-and-set! compile complement concat cond ' +
+        'condp conj conj! cons constantly construct-proxy contains? count ' +
+        'counted? create-ns create-struct cycle dec decimal? declare definline ' +
+        'defmacro defmethod defmulti defn defn- defonce defstruct delay delay? ' +
+        'deliver deref derive descendants destructure disj disj! dissoc dissoc! ' +
+        'distinct distinct? doall doc dorun doseq dosync dotimes doto double ' +
+        'double-array doubles drop drop-last drop-while empty empty? ensure ' +
+        'enumeration-seq eval even? every? false? ffirst file-seq filter find ' +
+        'find-doc find-ns find-var first float float-array float? floats flush ' +
+        'fn fn? fnext for force format future future-call future-cancel ' +
+        'future-cancelled? future-done? future? gen-class gen-interface gensym ' +
+        'get get-in get-method get-proxy-class get-thread-bindings get-validator ' +
+        'hash hash-map hash-set identical? identity if-let if-not ifn? import ' +
+        'in-ns inc init-proxy instance? int int-array integer? interleave intern ' +
+        'interpose into into-array ints io! isa? iterate iterator-seq juxt key ' +
+        'keys keyword keyword? last lazy-cat lazy-seq let letfn line-seq list ' +
+        'list* list? load load-file load-reader load-string loaded-libs locking ' +
+        'long long-array longs loop macroexpand macroexpand-1 make-array ' +
+        'make-hierarchy map map? mapcat max max-key memfn memoize merge ' +
+        'merge-with meta method-sig methods min min-key mod name namespace neg? ' +
+        'newline next nfirst nil? nnext not not-any? not-empty not-every? not= ' +
+        'ns ns-aliases ns-imports ns-interns ns-map ns-name ns-publics ' +
+        'ns-refers ns-resolve ns-unalias ns-unmap nth nthnext num number? odd? ' +
+        'or parents partial partition pcalls peek persistent! pmap pop pop! ' +
+        'pop-thread-bindings pos? pr pr-str prefer-method prefers ' +
+        'primitives-classnames print print-ctor print-doc print-dup print-method ' +
+        'print-namespace-doc print-simple print-special-doc print-str printf ' +
+        'println println-str prn prn-str promise proxy proxy-call-with-super ' +
+        'proxy-mappings proxy-name proxy-super push-thread-bindings pvalues quot ' +
+        'rand rand-int range ratio? rational? rationalize re-find re-groups ' +
+        're-matcher re-matches re-pattern re-seq read read-line read-string ' +
+        'reduce ref ref-history-count ref-max-history ref-min-history ref-set ' +
+        'refer refer-clojure release-pending-sends rem remove remove-method ' +
+        'remove-ns remove-watch repeat repeatedly replace replicate require ' +
+        'reset! reset-meta! resolve rest resultset-seq reverse reversible? rseq ' +
+        'rsubseq second select-keys send send-off seq seq? seque sequence ' +
+        'sequential? set set-validator! set? short short-array shorts ' +
+        'shutdown-agents slurp some sort sort-by sorted-map sorted-map-by ' +
+        'sorted-set sorted-set-by sorted? special-form-anchor special-symbol? ' +
+        'split-at split-with str stream? string? struct struct-map subs subseq ' +
+        'subvec supers swap! symbol symbol? sync syntax-symbol-anchor take ' +
+        'take-last take-nth take-while test the-ns time to-array to-array-2d ' +
+        'trampoline transient tree-seq true? type unchecked-add unchecked-dec ' +
+        'unchecked-divide unchecked-inc unchecked-multiply unchecked-negate ' +
+        'unchecked-remainder unchecked-subtract underive unquote ' +
+        'unquote-splicing update-in update-proxy use val vals var-get var-set ' +
+        'var? vary-meta vec vector vector? when when-first when-let when-not ' +
+        'while with-bindings with-bindings* with-in-str with-loading-context ' +
+        'with-local-vars with-meta with-open with-out-str with-precision xml-seq ' +
+        'zero? zipmap'
+    );
+
+    var keywords = ('throw try var ' +
+        'def do fn if let loop monitor-enter monitor-exit new quote recur set!'
+    );
+
+    var buildinConstants = ("true false nil");
+
+    var keywordMapper = this.createKeywordMapper({
+        "keyword": keywords,
+        "constant.language": buildinConstants,
+        "support.function": builtinFunctions
+    }, "identifier", false, " ");
+
+    this.$rules = {
+        "start" : [
+            {
+                token : "comment",
+                regex : ";.*$"
+            }, {
+                token : "keyword", //parens
+                regex : "[\\(|\\)]"
+            }, {
+                token : "keyword", //lists
+                regex : "[\\'\\(]"
+            }, {
+                token : "keyword", //vectors
+                regex : "[\\[|\\]]"
+            }, {
+                token : "keyword", //sets and maps
+                regex : "[\\{|\\}|\\#\\{|\\#\\}]"
+            }, {
+                    token : "keyword", // ampersands
+                    regex : '[\\&]'
+            }, {
+                    token : "keyword", // metadata
+                    regex : '[\\#\\^\\{]'
+            }, {
+                    token : "keyword", // anonymous fn syntactic sugar
+                    regex : '[\\%]'
+            }, {
+                    token : "keyword", // deref reader macro
+                    regex : '[@]'
+            }, {
+                token : "constant.numeric", // hex
+                regex : "0[xX][0-9a-fA-F]+\\b"
+            }, {
+                token : "constant.numeric", // float
+                regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
+            }, {
+                token : "constant.language",
+                regex : '[!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+||=|!=|<=|>=|<>|<|>|!|&&]'
+            }, {
+                token : keywordMapper,
+                regex : "[a-zA-Z_$][a-zA-Z0-9_$\\-]*\\b"
+            }, {
+                token : "string", // single line
+                regex : '"',
+                next: "string"
+            }, {
+                token : "constant", // symbol
+                regex : /:[^()\[\]{}'"\^%`,;\s]+/
+            }, {
+                token : "string.regexp", //Regular Expressions
+                regex : '/#"(?:\\.|(?:\\")|[^""\n])*"/g'
+            }
+
+        ],
+        "string" : [
+            {
+                token : "constant.language.escape",
+                regex : "\\\\.|\\\\$"
+            }, {
+                token : "string",
+                regex : '[^"\\\\]+'
+            }, {
+                token : "string",
+                regex : '"',
+                next : "start"
+            }
+        ]
+    };
+};
+
+oop.inherits(ClojureHighlightRules, TextHighlightRules);
+
+exports.ClojureHighlightRules = ClojureHighlightRules;
+});
+
+ace.define("ace/mode/matching_parens_outdent",[], function(require, exports, module) {
+"use strict";
+
+var Range = require("../range").Range;
+
+var MatchingParensOutdent = function() {};
+
+(function() {
+
+    this.checkOutdent = function(line, input) {
+        if (! /^\s+$/.test(line))
+            return false;
+
+        return /^\s*\)/.test(input);
+    };
+
+    this.autoOutdent = function(doc, row) {
+        var line = doc.getLine(row);
+        var match = line.match(/^(\s*\))/);
+
+        if (!match) return 0;
+
+        var column = match[1].length;
+        var openBracePos = doc.findMatchingBracket({row: row, column: column});
+
+        if (!openBracePos || openBracePos.row == row) return 0;
+
+        var indent = this.$getIndent(doc.getLine(openBracePos.row));
+        doc.replace(new Range(row, 0, row, column-1), indent);
+    };
+
+    this.$getIndent = function(line) {
+        var match = line.match(/^(\s+)/);
+        if (match) {
+            return match[1];
+        }
+
+        return "";
+    };
+
+}).call(MatchingParensOutdent.prototype);
+
+exports.MatchingParensOutdent = MatchingParensOutdent;
+});
+
+ace.define("ace/mode/clojure",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var ClojureHighlightRules = require("./clojure_highlight_rules").ClojureHighlightRules;
+var MatchingParensOutdent = require("./matching_parens_outdent").MatchingParensOutdent;
+
+var Mode = function() {
+    this.HighlightRules = ClojureHighlightRules;
+    this.$outdent = new MatchingParensOutdent();
+    this.$behaviour = this.$defaultBehaviour;
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+
+    this.lineCommentStart = ";";
+    this.minorIndentFunctions = ["defn", "defn-", "defmacro", "def", "deftest", "testing"];
+
+    this.$toIndent = function(str) {
+        return str.split('').map(function(ch) {
+            if (/\s/.exec(ch)) {
+                return ch;
+            } else {
+                return ' ';
+            }
+        }).join('');
+    };
+
+    this.$calculateIndent = function(line, tab) {
+        var baseIndent = this.$getIndent(line);
+        var delta = 0;
+        var isParen, ch;
+        for (var i = line.length - 1; i >= 0; i--) {
+            ch = line[i];
+            if (ch === '(') {
+                delta--;
+                isParen = true;
+            } else if (ch === '(' || ch === '[' || ch === '{') {
+                delta--;
+                isParen = false;
+            } else if (ch === ')' || ch === ']' || ch === '}') {
+                delta++;
+            }
+            if (delta < 0) {
+                break;
+            }
+        }
+        if (delta < 0 && isParen) {
+            i += 1;
+            var iBefore = i;
+            var fn = '';
+            while (true) {
+                ch = line[i];
+                if (ch === ' ' || ch === '\t') {
+                    if(this.minorIndentFunctions.indexOf(fn) !== -1) {
+                        return this.$toIndent(line.substring(0, iBefore - 1) + tab);
+                    } else {
+                        return this.$toIndent(line.substring(0, i + 1));
+                    }
+                } else if (ch === undefined) {
+                    return this.$toIndent(line.substring(0, iBefore - 1) + tab);
+                }
+                fn += line[i];
+                i++;
+            }
+        } else if(delta < 0 && !isParen) {
+            return this.$toIndent(line.substring(0, i+1));
+        } else if(delta > 0) {
+            baseIndent = baseIndent.substring(0, baseIndent.length - tab.length);
+            return baseIndent;
+        } else {
+            return baseIndent;
+        }
+    };
+
+    this.getNextLineIndent = function(state, line, tab) {
+        return this.$calculateIndent(line, tab);
+    };
+
+    this.checkOutdent = function(state, line, input) {
+        return this.$outdent.checkOutdent(line, input);
+    };
+
+    this.autoOutdent = function(state, doc, row) {
+        this.$outdent.autoOutdent(doc, row);
+    };
+
+    this.$id = "ace/mode/clojure";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/clojure"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 102 - 0
services/web/public/js/ace-1.4.3/mode-cobol.js

@@ -0,0 +1,102 @@
+ace.define("ace/mode/cobol_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var CobolHighlightRules = function() {
+var keywords = "ACCEPT|MERGE|SUM|ADD||MESSAGE|TABLE|ADVANCING|MODE|TAPE|" +
+"AFTER|MULTIPLY|TEST|ALL|NEGATIVE|TEXT|ALPHABET|NEXT|THAN|" +
+"ALSO|NO|THEN|ALTERNATE|NOT|THROUGH|AND|NUMBER|THRU|ANY|OCCURS|" +
+"TIME|ARE|OF|TO|AREA|OFF|TOP||ASCENDING|OMITTED|TRUE|ASSIGN|ON|TYPE|AT|OPEN|" +
+"UNIT|AUTHOR|OR|UNTIL|BEFORE|OTHER|UP|BLANK|OUTPUT|USE|BLOCK|PAGE|USING|BOTTOM|" +
+"PERFORM|VALUE|BY|PIC|VALUES|CALL|PICTURE|WHEN|CANCEL|PLUS|WITH|CD|POINTER|WRITE|" +
+"CHARACTER|POSITION||ZERO|CLOSE|POSITIVE|ZEROS|COLUMN|PROCEDURE|ZEROES|COMMA|PROGRAM|" +
+"COMMON|PROGRAM-ID|COMMUNICATION|QUOTE|COMP|RANDOM|COMPUTE|READ|CONTAINS|RECEIVE|CONFIGURATION|" +
+"RECORD|CONTINUE|REDEFINES|CONTROL|REFERENCE|COPY|REMAINDER|COUNT|REPLACE|DATA|REPORT|DATE|RESERVE|" +
+"DAY|RESET|DELETE|RETURN|DESTINATION|REWIND|DISABLE|REWRITE|DISPLAY|RIGHT|DIVIDE|RUN|DOWN|SAME|" +
+"ELSE|SEARCH|ENABLE|SECTION|END|SELECT|ENVIRONMENT|SENTENCE|EQUAL|SET|ERROR|SIGN|EXIT|SEQUENTIAL|" +
+"EXTERNAL|SIZE|FLASE|SORT|FILE|SOURCE|LENGTH|SPACE|LESS|STANDARD|LIMIT|START|LINE|STOP|LOCK|STRING|LOW-VALUE|SUBTRACT";
+
+    var builtinConstants = (
+        "true|false|null"
+    );
+
+    var builtinFunctions = (
+        "count|min|max|avg|sum|rank|now|coalesce|main"
+    );
+
+    var keywordMapper = this.createKeywordMapper({
+        "support.function": builtinFunctions,
+        "keyword": keywords,
+        "constant.language": builtinConstants
+    }, "identifier", true);
+
+    this.$rules = {
+        "start" : [ {
+            token : "comment",
+            regex : "\\*.*$"
+        }, {
+            token : "string",           // " string
+            regex : '".*?"'
+        }, {
+            token : "string",           // ' string
+            regex : "'.*?'"
+        }, {
+            token : "constant.numeric", // float
+            regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
+        }, {
+            token : keywordMapper,
+            regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
+        }, {
+            token : "keyword.operator",
+            regex : "\\+|\\-|\\/|\\/\\/|%|<@>|@>|<@|&|\\^|~|<|>|<=|=>|==|!=|<>|="
+        }, {
+            token : "paren.lparen",
+            regex : "[\\(]"
+        }, {
+            token : "paren.rparen",
+            regex : "[\\)]"
+        }, {
+            token : "text",
+            regex : "\\s+"
+        } ]
+    };
+};
+
+oop.inherits(CobolHighlightRules, TextHighlightRules);
+
+exports.CobolHighlightRules = CobolHighlightRules;
+});
+
+ace.define("ace/mode/cobol",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var CobolHighlightRules = require("./cobol_highlight_rules").CobolHighlightRules;
+
+var Mode = function() {
+    this.HighlightRules = CobolHighlightRules;
+    this.$behaviour = this.$defaultBehaviour;
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+
+    this.lineCommentStart = "*";
+
+    this.$id = "ace/mode/cobol";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+
+});
+                (function() {
+                    ace.require(["ace/mode/cobol"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 400 - 0
services/web/public/js/ace-1.4.3/mode-coffee.js

@@ -0,0 +1,400 @@
+ace.define("ace/mode/coffee_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+    var oop = require("../lib/oop");
+    var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+    oop.inherits(CoffeeHighlightRules, TextHighlightRules);
+
+    function CoffeeHighlightRules() {
+        var identifier = "[$A-Za-z_\\x7f-\\uffff][$\\w\\x7f-\\uffff]*";
+
+        var keywords = (
+            "this|throw|then|try|typeof|super|switch|return|break|by|continue|" +
+            "catch|class|in|instanceof|is|isnt|if|else|extends|for|own|" +
+            "finally|function|while|when|new|no|not|delete|debugger|do|loop|of|off|" +
+            "or|on|unless|until|and|yes|yield|export|import|default"
+        );
+
+        var langConstant = (
+            "true|false|null|undefined|NaN|Infinity"
+        );
+
+        var illegal = (
+            "case|const|function|var|void|with|enum|implements|" +
+            "interface|let|package|private|protected|public|static"
+        );
+
+        var supportClass = (
+            "Array|Boolean|Date|Function|Number|Object|RegExp|ReferenceError|String|" +
+            "Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|" +
+            "SyntaxError|TypeError|URIError|"  +
+            "ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|" +
+            "Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray"
+        );
+
+        var supportFunction = (
+            "Math|JSON|isNaN|isFinite|parseInt|parseFloat|encodeURI|" +
+            "encodeURIComponent|decodeURI|decodeURIComponent|String|"
+        );
+
+        var variableLanguage = (
+            "window|arguments|prototype|document"
+        );
+
+        var keywordMapper = this.createKeywordMapper({
+            "keyword": keywords,
+            "constant.language": langConstant,
+            "invalid.illegal": illegal,
+            "language.support.class": supportClass,
+            "language.support.function": supportFunction,
+            "variable.language": variableLanguage
+        }, "identifier");
+
+        var functionRule = {
+            token: ["paren.lparen", "variable.parameter", "paren.rparen", "text", "storage.type"],
+            regex: /(?:(\()((?:"[^")]*?"|'[^')]*?'|\/[^\/)]*?\/|[^()"'\/])*?)(\))(\s*))?([\-=]>)/.source
+        };
+
+        var stringEscape = /\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)/;
+
+        this.$rules = {
+            start : [
+                {
+                    token : "constant.numeric",
+                    regex : "(?:0x[\\da-fA-F]+|(?:\\d+(?:\\.\\d+)?|\\.\\d+)(?:[eE][+-]?\\d+)?)"
+                }, {
+                    stateName: "qdoc",
+                    token : "string", regex : "'''", next : [
+                        {token : "string", regex : "'''", next : "start"},
+                        {token : "constant.language.escape", regex : stringEscape},
+                        {defaultToken: "string"}
+                    ]
+                }, {
+                    stateName: "qqdoc",
+                    token : "string",
+                    regex : '"""',
+                    next : [
+                        {token : "string", regex : '"""', next : "start"},
+                        {token : "paren.string", regex : '#{', push : "start"},
+                        {token : "constant.language.escape", regex : stringEscape},
+                        {defaultToken: "string"}
+                    ]
+                }, {
+                    stateName: "qstring",
+                    token : "string", regex : "'", next : [
+                        {token : "string", regex : "'", next : "start"},
+                        {token : "constant.language.escape", regex : stringEscape},
+                        {defaultToken: "string"}
+                    ]
+                }, {
+                    stateName: "qqstring",
+                    token : "string.start", regex : '"', next : [
+                        {token : "string.end", regex : '"', next : "start"},
+                        {token : "paren.string", regex : '#{', push : "start"},
+                        {token : "constant.language.escape", regex : stringEscape},
+                        {defaultToken: "string"}
+                    ]
+                }, {
+                    stateName: "js",
+                    token : "string", regex : "`", next : [
+                        {token : "string", regex : "`", next : "start"},
+                        {token : "constant.language.escape", regex : stringEscape},
+                        {defaultToken: "string"}
+                    ]
+                }, {
+                    regex: "[{}]", onMatch: function(val, state, stack) {
+                        this.next = "";
+                        if (val == "{" && stack.length) {
+                            stack.unshift("start", state);
+                            return "paren";
+                        }
+                        if (val == "}" && stack.length) {
+                            stack.shift();
+                            this.next = stack.shift() || "";
+                            if (this.next.indexOf("string") != -1)
+                                return "paren.string";
+                        }
+                        return "paren";
+                    }
+                }, {
+                    token : "string.regex",
+                    regex : "///",
+                    next : "heregex"
+                }, {
+                    token : "string.regex",
+                    regex : /(?:\/(?![\s=])[^[\/\n\\]*(?:(?:\\[\s\S]|\[[^\]\n\\]*(?:\\[\s\S][^\]\n\\]*)*])[^[\/\n\\]*)*\/)(?:[imgy]{0,4})(?!\w)/
+                }, {
+                    token : "comment",
+                    regex : "###(?!#)",
+                    next : "comment"
+                }, {
+                    token : "comment",
+                    regex : "#.*"
+                }, {
+                    token : ["punctuation.operator", "text", "identifier"],
+                    regex : "(\\.)(\\s*)(" + illegal + ")"
+                }, {
+                    token : "punctuation.operator",
+                    regex : "\\.{1,3}"
+                }, {
+                    token : ["keyword", "text", "language.support.class",
+                     "text", "keyword", "text", "language.support.class"],
+                    regex : "(class)(\\s+)(" + identifier + ")(?:(\\s+)(extends)(\\s+)(" + identifier + "))?"
+                }, {
+                    token : ["entity.name.function", "text", "keyword.operator", "text"].concat(functionRule.token),
+                    regex : "(" + identifier + ")(\\s*)([=:])(\\s*)" + functionRule.regex
+                }, 
+                functionRule, 
+                {
+                    token : "variable",
+                    regex : "@(?:" + identifier + ")?"
+                }, {
+                    token: keywordMapper,
+                    regex : identifier
+                }, {
+                    token : "punctuation.operator",
+                    regex : "\\,|\\."
+                }, {
+                    token : "storage.type",
+                    regex : "[\\-=]>"
+                }, {
+                    token : "keyword.operator",
+                    regex : "(?:[-+*/%<>&|^!?=]=|>>>=?|\\-\\-|\\+\\+|::|&&=|\\|\\|=|<<=|>>=|\\?\\.|\\.{2,3}|[!*+-=><])"
+                }, {
+                    token : "paren.lparen",
+                    regex : "[({[]"
+                }, {
+                    token : "paren.rparen",
+                    regex : "[\\]})]"
+                }, {
+                    token : "text",
+                    regex : "\\s+"
+                }],
+
+
+            heregex : [{
+                token : "string.regex",
+                regex : '.*?///[imgy]{0,4}',
+                next : "start"
+            }, {
+                token : "comment.regex",
+                regex : "\\s+(?:#.*)?"
+            }, {
+                token : "string.regex",
+                regex : "\\S+"
+            }],
+
+            comment : [{
+                token : "comment",
+                regex : '###',
+                next : "start"
+            }, {
+                defaultToken : "comment"
+            }]
+        };
+        this.normalizeRules();
+    }
+
+    exports.CoffeeHighlightRules = CoffeeHighlightRules;
+});
+
+ace.define("ace/mode/matching_brace_outdent",[], function(require, exports, module) {
+"use strict";
+
+var Range = require("../range").Range;
+
+var MatchingBraceOutdent = function() {};
+
+(function() {
+
+    this.checkOutdent = function(line, input) {
+        if (! /^\s+$/.test(line))
+            return false;
+
+        return /^\s*\}/.test(input);
+    };
+
+    this.autoOutdent = function(doc, row) {
+        var line = doc.getLine(row);
+        var match = line.match(/^(\s*\})/);
+
+        if (!match) return 0;
+
+        var column = match[1].length;
+        var openBracePos = doc.findMatchingBracket({row: row, column: column});
+
+        if (!openBracePos || openBracePos.row == row) return 0;
+
+        var indent = this.$getIndent(doc.getLine(openBracePos.row));
+        doc.replace(new Range(row, 0, row, column-1), indent);
+    };
+
+    this.$getIndent = function(line) {
+        return line.match(/^\s*/)[0];
+    };
+
+}).call(MatchingBraceOutdent.prototype);
+
+exports.MatchingBraceOutdent = MatchingBraceOutdent;
+});
+
+ace.define("ace/mode/folding/coffee",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var BaseFoldMode = require("./fold_mode").FoldMode;
+var Range = require("../../range").Range;
+
+var FoldMode = exports.FoldMode = function() {};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+
+    this.getFoldWidgetRange = function(session, foldStyle, row) {
+        var range = this.indentationBlock(session, row);
+        if (range)
+            return range;
+
+        var re = /\S/;
+        var line = session.getLine(row);
+        var startLevel = line.search(re);
+        if (startLevel == -1 || line[startLevel] != "#")
+            return;
+
+        var startColumn = line.length;
+        var maxRow = session.getLength();
+        var startRow = row;
+        var endRow = row;
+
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var level = line.search(re);
+
+            if (level == -1)
+                continue;
+
+            if (line[level] != "#")
+                break;
+
+            endRow = row;
+        }
+
+        if (endRow > startRow) {
+            var endColumn = session.getLine(endRow).length;
+            return new Range(startRow, startColumn, endRow, endColumn);
+        }
+    };
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+        var indent = line.search(/\S/);
+        var next = session.getLine(row + 1);
+        var prev = session.getLine(row - 1);
+        var prevIndent = prev.search(/\S/);
+        var nextIndent = next.search(/\S/);
+
+        if (indent == -1) {
+            session.foldWidgets[row - 1] = prevIndent!= -1 && prevIndent < nextIndent ? "start" : "";
+            return "";
+        }
+        if (prevIndent == -1) {
+            if (indent == nextIndent && line[indent] == "#" && next[indent] == "#") {
+                session.foldWidgets[row - 1] = "";
+                session.foldWidgets[row + 1] = "";
+                return "start";
+            }
+        } else if (prevIndent == indent && line[indent] == "#" && prev[indent] == "#") {
+            if (session.getLine(row - 2).search(/\S/) == -1) {
+                session.foldWidgets[row - 1] = "start";
+                session.foldWidgets[row + 1] = "";
+                return "";
+            }
+        }
+
+        if (prevIndent!= -1 && prevIndent < indent)
+            session.foldWidgets[row - 1] = "start";
+        else
+            session.foldWidgets[row - 1] = "";
+
+        if (indent < nextIndent)
+            return "start";
+        else
+            return "";
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/coffee",[], function(require, exports, module) {
+"use strict";
+
+var Rules = require("./coffee_highlight_rules").CoffeeHighlightRules;
+var Outdent = require("./matching_brace_outdent").MatchingBraceOutdent;
+var FoldMode = require("./folding/coffee").FoldMode;
+var Range = require("../range").Range;
+var TextMode = require("./text").Mode;
+var WorkerClient = require("../worker/worker_client").WorkerClient;
+var oop = require("../lib/oop");
+
+function Mode() {
+    this.HighlightRules = Rules;
+    this.$outdent = new Outdent();
+    this.foldingRules = new FoldMode();
+}
+
+oop.inherits(Mode, TextMode);
+
+(function() {
+    var indenter = /(?:[({[=:]|[-=]>|\b(?:else|try|(?:swi|ca)tch(?:\s+[$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*)?|finally))\s*$|^\s*(else\b\s*)?(?:if|for|while|loop)\b(?!.*\bthen\b)/;
+    
+    this.lineCommentStart = "#";
+    this.blockComment = {start: "###", end: "###"};
+    
+    this.getNextLineIndent = function(state, line, tab) {
+        var indent = this.$getIndent(line);
+        var tokens = this.getTokenizer().getLineTokens(line, state).tokens;
+    
+        if (!(tokens.length && tokens[tokens.length - 1].type === 'comment') &&
+            state === 'start' && indenter.test(line))
+            indent += tab;
+        return indent;
+    };
+    
+    this.checkOutdent = function(state, line, input) {
+        return this.$outdent.checkOutdent(line, input);
+    };
+    
+    this.autoOutdent = function(state, doc, row) {
+        this.$outdent.autoOutdent(doc, row);
+    };
+    
+    this.createWorker = function(session) {
+        var worker = new WorkerClient(["ace"], "ace/mode/coffee_worker", "Worker");
+        worker.attachToDocument(session.getDocument());
+        
+        worker.on("annotate", function(e) {
+            session.setAnnotations(e.data);
+        });
+        
+        worker.on("terminate", function() {
+            session.clearAnnotations();
+        });
+        
+        return worker;
+    };
+
+    this.$id = "ace/mode/coffee";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+
+});
+                (function() {
+                    ace.require(["ace/mode/coffee"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

Fișier diff suprimat deoarece este prea mare
+ 797 - 0
services/web/public/js/ace-1.4.3/mode-coldfusion.js


+ 503 - 0
services/web/public/js/ace-1.4.3/mode-csharp.js

@@ -0,0 +1,503 @@
+ace.define("ace/mode/doc_comment_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var DocCommentHighlightRules = function() {
+    this.$rules = {
+        "start" : [ {
+            token : "comment.doc.tag",
+            regex : "@[\\w\\d_]+" // TODO: fix email addresses
+        }, 
+        DocCommentHighlightRules.getTagRule(),
+        {
+            defaultToken : "comment.doc",
+            caseInsensitive: true
+        }]
+    };
+};
+
+oop.inherits(DocCommentHighlightRules, TextHighlightRules);
+
+DocCommentHighlightRules.getTagRule = function(start) {
+    return {
+        token : "comment.doc.tag.storage.type",
+        regex : "\\b(?:TODO|FIXME|XXX|HACK)\\b"
+    };
+};
+
+DocCommentHighlightRules.getStartRule = function(start) {
+    return {
+        token : "comment.doc", // doc comment
+        regex : "\\/\\*(?=\\*)",
+        next  : start
+    };
+};
+
+DocCommentHighlightRules.getEndRule = function (start) {
+    return {
+        token : "comment.doc", // closing comment
+        regex : "\\*\\/",
+        next  : start
+    };
+};
+
+
+exports.DocCommentHighlightRules = DocCommentHighlightRules;
+
+});
+
+ace.define("ace/mode/csharp_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var DocCommentHighlightRules = require("./doc_comment_highlight_rules").DocCommentHighlightRules;
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var CSharpHighlightRules = function() {
+    var keywordMapper = this.createKeywordMapper({
+        "variable.language": "this",
+        "keyword": "abstract|async|await|event|new|struct|as|explicit|null|switch|base|extern|object|this|bool|false|operator|throw|break|finally|out|true|byte|fixed|override|try|case|float|params|typeof|catch|for|private|uint|char|foreach|protected|ulong|checked|goto|public|unchecked|class|if|readonly|unsafe|const|implicit|ref|ushort|continue|in|return|using|decimal|int|sbyte|virtual|default|interface|sealed|volatile|delegate|internal|partial|short|void|do|is|sizeof|while|double|lock|stackalloc|else|long|static|enum|namespace|string|var|dynamic",
+        "constant.language": "null|true|false"
+    }, "identifier");
+
+    this.$rules = {
+        "start" : [
+            {
+                token : "comment",
+                regex : "\\/\\/.*$"
+            },
+            DocCommentHighlightRules.getStartRule("doc-start"),
+            {
+                token : "comment", // multi line comment
+                regex : "\\/\\*",
+                next : "comment"
+            }, {
+                token : "string", // character
+                regex : /'(?:.|\\(:?u[\da-fA-F]+|x[\da-fA-F]+|[tbrf'"n]))?'/
+            }, {
+                token : "string", start : '"', end : '"|$', next: [
+                    {token: "constant.language.escape", regex: /\\(:?u[\da-fA-F]+|x[\da-fA-F]+|[tbrf'"n])/},
+                    {token: "invalid", regex: /\\./}
+                ]
+            }, {
+                token : "string", start : '@"', end : '"', next:[
+                    {token: "constant.language.escape", regex: '""'}
+                ]
+            }, {
+                token : "string", start : /\$"/, end : '"|$', next: [
+                    {token: "constant.language.escape", regex: /\\(:?$)|{{/},
+                    {token: "constant.language.escape", regex: /\\(:?u[\da-fA-F]+|x[\da-fA-F]+|[tbrf'"n])/},
+                    {token: "invalid", regex: /\\./}
+                ]
+            }, {
+                token : "constant.numeric", // hex
+                regex : "0[xX][0-9a-fA-F]+\\b"
+            }, {
+                token : "constant.numeric", // float
+                regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
+            }, {
+                token : "constant.language.boolean",
+                regex : "(?:true|false)\\b"
+            }, {
+                token : keywordMapper,
+                regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
+            }, {
+                token : "keyword.operator",
+                regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"
+            }, {
+                token : "keyword",
+                regex : "^\\s*#(if|else|elif|endif|define|undef|warning|error|line|region|endregion|pragma)"
+            }, {
+                token : "punctuation.operator",
+                regex : "\\?|\\:|\\,|\\;|\\."
+            }, {
+                token : "paren.lparen",
+                regex : "[[({]"
+            }, {
+                token : "paren.rparen",
+                regex : "[\\])}]"
+            }, {
+                token : "text",
+                regex : "\\s+"
+            }
+        ],
+        "comment" : [
+            {
+                token : "comment", // closing comment
+                regex : "\\*\\/",
+                next : "start"
+            }, {
+                defaultToken : "comment"
+            }
+        ]
+    };
+
+    this.embedRules(DocCommentHighlightRules, "doc-",
+        [ DocCommentHighlightRules.getEndRule("start") ]);
+    this.normalizeRules();
+};
+
+oop.inherits(CSharpHighlightRules, TextHighlightRules);
+
+exports.CSharpHighlightRules = CSharpHighlightRules;
+});
+
+ace.define("ace/mode/matching_brace_outdent",[], function(require, exports, module) {
+"use strict";
+
+var Range = require("../range").Range;
+
+var MatchingBraceOutdent = function() {};
+
+(function() {
+
+    this.checkOutdent = function(line, input) {
+        if (! /^\s+$/.test(line))
+            return false;
+
+        return /^\s*\}/.test(input);
+    };
+
+    this.autoOutdent = function(doc, row) {
+        var line = doc.getLine(row);
+        var match = line.match(/^(\s*\})/);
+
+        if (!match) return 0;
+
+        var column = match[1].length;
+        var openBracePos = doc.findMatchingBracket({row: row, column: column});
+
+        if (!openBracePos || openBracePos.row == row) return 0;
+
+        var indent = this.$getIndent(doc.getLine(openBracePos.row));
+        doc.replace(new Range(row, 0, row, column-1), indent);
+    };
+
+    this.$getIndent = function(line) {
+        return line.match(/^\s*/)[0];
+    };
+
+}).call(MatchingBraceOutdent.prototype);
+
+exports.MatchingBraceOutdent = MatchingBraceOutdent;
+});
+
+ace.define("ace/mode/folding/cstyle",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Range = require("../../range").Range;
+var BaseFoldMode = require("./fold_mode").FoldMode;
+
+var FoldMode = exports.FoldMode = function(commentRegex) {
+    if (commentRegex) {
+        this.foldingStartMarker = new RegExp(
+            this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start)
+        );
+        this.foldingStopMarker = new RegExp(
+            this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end)
+        );
+    }
+};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+    
+    this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/;
+    this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/;
+    this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/;
+    this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/;
+    this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/;
+    this._getFoldWidgetBase = this.getFoldWidget;
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+    
+        if (this.singleLineBlockCommentRe.test(line)) {
+            if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line))
+                return "";
+        }
+    
+        var fw = this._getFoldWidgetBase(session, foldStyle, row);
+    
+        if (!fw && this.startRegionRe.test(line))
+            return "start"; // lineCommentRegionStart
+    
+        return fw;
+    };
+
+    this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) {
+        var line = session.getLine(row);
+        
+        if (this.startRegionRe.test(line))
+            return this.getCommentRegionBlock(session, line, row);
+        
+        var match = line.match(this.foldingStartMarker);
+        if (match) {
+            var i = match.index;
+
+            if (match[1])
+                return this.openingBracketBlock(session, match[1], row, i);
+                
+            var range = session.getCommentFoldRange(row, i + match[0].length, 1);
+            
+            if (range && !range.isMultiLine()) {
+                if (forceMultiline) {
+                    range = this.getSectionRange(session, row);
+                } else if (foldStyle != "all")
+                    range = null;
+            }
+            
+            return range;
+        }
+
+        if (foldStyle === "markbegin")
+            return;
+
+        var match = line.match(this.foldingStopMarker);
+        if (match) {
+            var i = match.index + match[0].length;
+
+            if (match[1])
+                return this.closingBracketBlock(session, match[1], row, i);
+
+            return session.getCommentFoldRange(row, i, -1);
+        }
+    };
+    
+    this.getSectionRange = function(session, row) {
+        var line = session.getLine(row);
+        var startIndent = line.search(/\S/);
+        var startRow = row;
+        var startColumn = line.length;
+        row = row + 1;
+        var endRow = row;
+        var maxRow = session.getLength();
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var indent = line.search(/\S/);
+            if (indent === -1)
+                continue;
+            if  (startIndent > indent)
+                break;
+            var subRange = this.getFoldWidgetRange(session, "all", row);
+            
+            if (subRange) {
+                if (subRange.start.row <= startRow) {
+                    break;
+                } else if (subRange.isMultiLine()) {
+                    row = subRange.end.row;
+                } else if (startIndent == indent) {
+                    break;
+                }
+            }
+            endRow = row;
+        }
+        
+        return new Range(startRow, startColumn, endRow, session.getLine(endRow).length);
+    };
+    this.getCommentRegionBlock = function(session, line, row) {
+        var startColumn = line.search(/\s*$/);
+        var maxRow = session.getLength();
+        var startRow = row;
+        
+        var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/;
+        var depth = 1;
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var m = re.exec(line);
+            if (!m) continue;
+            if (m[1]) depth--;
+            else depth++;
+
+            if (!depth) break;
+        }
+
+        var endRow = row;
+        if (endRow > startRow) {
+            return new Range(startRow, startColumn, endRow, line.length);
+        }
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/folding/csharp",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Range = require("../../range").Range;
+var CFoldMode = require("./cstyle").FoldMode;
+
+var FoldMode = exports.FoldMode = function(commentRegex) {
+    if (commentRegex) {
+        this.foldingStartMarker = new RegExp(
+            this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start)
+        );
+        this.foldingStopMarker = new RegExp(
+            this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end)
+        );
+    }
+};
+oop.inherits(FoldMode, CFoldMode);
+
+(function() {
+    this.usingRe = /^\s*using \S/;
+
+    this.getFoldWidgetRangeBase = this.getFoldWidgetRange;
+    this.getFoldWidgetBase = this.getFoldWidget;
+    
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var fw = this.getFoldWidgetBase(session, foldStyle, row);
+        if (!fw) {
+            var line = session.getLine(row);
+            if (/^\s*#region\b/.test(line)) 
+                return "start";
+            var usingRe = this.usingRe;
+            if (usingRe.test(line)) {
+                var prev = session.getLine(row - 1);
+                var next = session.getLine(row + 1);
+                if (!usingRe.test(prev) && usingRe.test(next))
+                    return "start";
+            }
+        }
+        return fw;
+    };
+    
+    this.getFoldWidgetRange = function(session, foldStyle, row) {
+        var range = this.getFoldWidgetRangeBase(session, foldStyle, row);
+        if (range)
+            return range;
+
+        var line = session.getLine(row);
+        if (this.usingRe.test(line))
+            return this.getUsingStatementBlock(session, line, row);
+            
+        if (/^\s*#region\b/.test(line))
+            return this.getRegionBlock(session, line, row);
+    };
+    
+    this.getUsingStatementBlock = function(session, line, row) {
+        var startColumn = line.match(this.usingRe)[0].length - 1;
+        var maxRow = session.getLength();
+        var startRow = row;
+        var endRow = row;
+
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            if (/^\s*$/.test(line))
+                continue;
+            if (!this.usingRe.test(line))
+                break;
+
+            endRow = row;
+        }
+
+        if (endRow > startRow) {
+            var endColumn = session.getLine(endRow).length;
+            return new Range(startRow, startColumn, endRow, endColumn);
+        }
+    };
+    
+    this.getRegionBlock = function(session, line, row) {
+        var startColumn = line.search(/\s*$/);
+        var maxRow = session.getLength();
+        var startRow = row;
+        
+        var re = /^\s*#(end)?region\b/;
+        var depth = 1;
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var m = re.exec(line);
+            if (!m)
+                continue;
+            if (m[1])
+                depth--;
+            else
+                depth++;
+
+            if (!depth)
+                break;
+        }
+
+        var endRow = row;
+        if (endRow > startRow) {
+            return new Range(startRow, startColumn, endRow, line.length);
+        }
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/csharp",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var CSharpHighlightRules = require("./csharp_highlight_rules").CSharpHighlightRules;
+var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent;
+var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour;
+var CStyleFoldMode = require("./folding/csharp").FoldMode;
+
+var Mode = function() {
+    this.HighlightRules = CSharpHighlightRules;
+    this.$outdent = new MatchingBraceOutdent();
+    this.$behaviour = new CstyleBehaviour();
+    this.foldingRules = new CStyleFoldMode();
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+    
+    this.lineCommentStart = "//";
+    this.blockComment = {start: "/*", end: "*/"};
+    
+    this.getNextLineIndent = function(state, line, tab) {
+        var indent = this.$getIndent(line);
+  
+        var tokenizedLine = this.getTokenizer().getLineTokens(line, state);
+        var tokens = tokenizedLine.tokens;
+  
+        if (tokens.length && tokens[tokens.length-1].type == "comment") {
+            return indent;
+        }
+    
+        if (state == "start") {
+            var match = line.match(/^.*[\{\(\[]\s*$/);
+            if (match) {
+                indent += tab;
+            }
+        }
+  
+        return indent;
+    };
+
+    this.checkOutdent = function(state, line, input) {
+        return this.$outdent.checkOutdent(line, input);
+    };
+  
+    this.autoOutdent = function(state, doc, row) {
+        this.$outdent.autoOutdent(doc, row);
+    };
+
+
+    this.createWorker = function(session) {
+        return null;
+    };
+
+    this.$id = "ace/mode/csharp";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/csharp"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

Fișier diff suprimat deoarece este prea mare
+ 2902 - 0
services/web/public/js/ace-1.4.3/mode-csound_document.js


+ 2925 - 0
services/web/public/js/ace-1.4.3/mode-csound_orchestra.js

@@ -0,0 +1,2925 @@
+ace.define("ace/mode/csound_preprocessor_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var CsoundPreprocessorHighlightRules = function() {
+
+    this.semicolonComments = {
+        token : "comment.line.semicolon.csound",
+        regex : ";.*$"
+    };
+
+    this.comments = [
+        {
+            token : "punctuation.definition.comment.begin.csound",
+            regex : "/\\*",
+            push  : [
+                {
+                    token : "punctuation.definition.comment.end.csound",
+                    regex : "\\*/",
+                    next  : "pop"
+                }, {
+                    defaultToken: "comment.block.csound"
+                }
+            ]
+        }, {
+            token : "comment.line.double-slash.csound",
+            regex : "//.*$"
+        },
+        this.semicolonComments
+    ];
+
+    this.macroUses = [
+        {
+            token : ["entity.name.function.preprocessor.csound", "punctuation.definition.macro-parameter-value-list.begin.csound"],
+            regex : /(\$[A-Z_a-z]\w*\.?)(\()/,
+            next  : "macro parameter value list"
+        }, {
+            token : "entity.name.function.preprocessor.csound",
+            regex : /\$[A-Z_a-z]\w*(?:\.|\b)/
+        }
+    ];
+
+    this.numbers = [
+        {
+            token : "constant.numeric.float.csound",
+            regex : /(?:\d+[Ee][+-]?\d+)|(?:\d+\.\d*|\d*\.\d+)(?:[Ee][+-]?\d+)?/
+        }, {
+            token : ["storage.type.number.csound", "constant.numeric.integer.hexadecimal.csound"],
+            regex : /(0[Xx])([0-9A-Fa-f]+)/
+        }, {
+            token : "constant.numeric.integer.decimal.csound",
+            regex : /\d+/
+        }
+    ];
+
+    this.bracedStringContents = [
+        {
+            token : "constant.character.escape.csound",
+            regex : /\\(?:[\\abnrt"]|[0-7]{1,3})/
+        },
+        {
+            token : "constant.character.placeholder.csound",
+            regex : /%[#0\- +]*\d*(?:\.\d+)?[diuoxXfFeEgGaAcs]/
+        }, {
+            token : "constant.character.escape.csound",
+            regex : /%%/
+        }
+    ];
+
+    this.quotedStringContents = [
+        this.macroUses,
+        this.bracedStringContents
+    ];
+
+    var start = [
+        this.comments,
+
+        {
+            token : "keyword.preprocessor.csound",
+            regex : /#(?:e(?:nd(?:if)?|lse)\b|##)|@@?[ \t]*\d+/
+        }, {
+            token : "keyword.preprocessor.csound",
+            regex : /#include/,
+            push  : [
+                this.comments,
+                {
+                    token : "string.csound",
+                    regex : /([^ \t])(?:.*?\1)/,
+                    next  : "pop"
+                }
+            ]
+        }, {
+            token : "keyword.preprocessor.csound",
+            regex : /#[ \t]*define/,
+            next  : "define directive"
+        }, {
+            token : "keyword.preprocessor.csound",
+            regex : /#(?:ifn?def|undef)\b/,
+            next  : "macro directive"
+        },
+
+        this.macroUses
+    ];
+
+    this.$rules = {
+        "start": start,
+
+        "define directive": [
+            this.comments,
+            {
+                token : "entity.name.function.preprocessor.csound",
+                regex : /[A-Z_a-z]\w*/
+            }, {
+                token : "punctuation.definition.macro-parameter-name-list.begin.csound",
+                regex : /\(/,
+                next  : "macro parameter name list"
+            }, {
+                token : "punctuation.definition.macro.begin.csound",
+                regex : /#/,
+                next  : "macro body"
+            }
+        ],
+        "macro parameter name list": [
+            {
+                token : "variable.parameter.preprocessor.csound",
+                regex : /[A-Z_a-z]\w*/
+            }, {
+                token : "punctuation.definition.macro-parameter-name-list.end.csound",
+                regex : /\)/,
+                next  : "define directive"
+            }
+        ],
+        "macro body": [
+            {
+                token : "constant.character.escape.csound",
+                regex : /\\#/
+            }, {
+                token : "punctuation.definition.macro.end.csound",
+                regex : /#/,
+                next  : "start"
+            },
+            start
+        ],
+
+        "macro directive": [
+            this.comments,
+            {
+                token : "entity.name.function.preprocessor.csound",
+                regex : /[A-Z_a-z]\w*/,
+                next  : "start"
+            }
+        ],
+
+        "macro parameter value list": [
+            {
+                token : "punctuation.definition.macro-parameter-value-list.end.csound",
+                regex : /\)/,
+                next  : "start"
+            }, {
+                token : "punctuation.definition.string.begin.csound",
+                regex : /"/,
+                next  : "macro parameter value quoted string"
+            }, this.pushRule({
+                token : "punctuation.macro-parameter-value-parenthetical.begin.csound",
+                regex : /\(/,
+                next  : "macro parameter value parenthetical"
+            }), {
+                token : "punctuation.macro-parameter-value-separator.csound",
+                regex : "[#']"
+            }
+        ],
+        "macro parameter value quoted string": [
+            {
+                token : "constant.character.escape.csound",
+                regex : /\\[#'()]/
+            }, {
+                token : "invalid.illegal.csound",
+                regex : /[#'()]/
+            }, {
+                token : "punctuation.definition.string.end.csound",
+                regex : /"/,
+                next  : "macro parameter value list"
+            },
+            this.quotedStringContents,
+            {
+                defaultToken: "string.quoted.csound"
+            }
+        ],
+        "macro parameter value parenthetical": [
+            {
+                token : "constant.character.escape.csound",
+                regex : /\\\)/
+            }, this.popRule({
+                token : "punctuation.macro-parameter-value-parenthetical.end.csound",
+                regex : /\)/
+            }), this.pushRule({
+                token : "punctuation.macro-parameter-value-parenthetical.begin.csound",
+                regex : /\(/,
+                next  : "macro parameter value parenthetical"
+            }),
+            start
+        ]
+    };
+};
+
+oop.inherits(CsoundPreprocessorHighlightRules, TextHighlightRules);
+
+(function() {
+
+    this.pushRule = function(params) {
+        return {
+            regex : params.regex, onMatch: function(value, currentState, stack, line) {
+                if (stack.length === 0)
+                    stack.push(currentState);
+                if (Array.isArray(params.next)) {
+                    for (var i = 0; i < params.next.length; i++) {
+                        stack.push(params.next[i]);
+                    }
+                } else {
+                    stack.push(params.next);
+                }
+                this.next = stack[stack.length - 1];
+                return params.token;
+            },
+            get next() { return Array.isArray(params.next) ? params.next[params.next.length - 1] : params.next; },
+            set next(next) {
+                if (Array.isArray(params.next)) {
+                    var oldNext = params.next[params.next.length - 1];
+                    var oldNextIndex = oldNext.length - 1;
+                    var newNextIndex = next.length - 1;
+                    if (newNextIndex > oldNextIndex) {
+                        while (oldNextIndex >= 0 && newNextIndex >= 0) {
+                            if (oldNext.charAt(oldNextIndex) !== next.charAt(newNextIndex)) {
+                                var prefix = next.substr(0, newNextIndex);
+                                for (var i = 0; i < params.next.length; i++) {
+                                    params.next[i] = prefix + params.next[i];
+                                }
+                                break;
+                            }
+                            oldNextIndex--;
+                            newNextIndex--;
+                        }
+                    }
+                } else {
+                    params.next = next;
+                }
+            },
+            get token() { return params.token; }
+        };
+    };
+
+    this.popRule = function(params) {
+        return {
+            regex : params.regex, onMatch: function(value, currentState, stack, line) {
+                stack.pop();
+                if (params.next) {
+                    stack.push(params.next);
+                    this.next = stack[stack.length - 1];
+                } else {
+                    this.next = stack.length > 1 ? stack[stack.length - 1] : stack.pop();
+                }
+                return params.token;
+            }
+        };
+    };
+
+}).call(CsoundPreprocessorHighlightRules.prototype);
+
+exports.CsoundPreprocessorHighlightRules = CsoundPreprocessorHighlightRules;
+});
+
+ace.define("ace/mode/csound_score_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+
+var CsoundPreprocessorHighlightRules = require("./csound_preprocessor_highlight_rules").CsoundPreprocessorHighlightRules;
+
+var CsoundScoreHighlightRules = function() {
+
+    CsoundPreprocessorHighlightRules.call(this);
+
+    this.quotedStringContents.push({
+        token : "invalid.illegal.csound-score",
+        regex : /[^"]*$/
+    });
+
+    var start = this.$rules.start;
+    start.push(
+        {
+            token : "keyword.control.csound-score",
+            regex : /[abCdefiqstvxy]/
+        }, {
+            token : "invalid.illegal.csound-score",
+            regex : /w/
+        }, {
+            token : "constant.numeric.language.csound-score",
+            regex : /z/
+        }, {
+            token : ["keyword.control.csound-score", "constant.numeric.integer.decimal.csound-score"],
+            regex : /([nNpP][pP])(\d+)/
+        }, {
+            token : "keyword.other.csound-score",
+            regex : /[mn]/,
+            push  : [
+                {
+                    token : "empty",
+                    regex : /$/,
+                    next  : "pop"
+                },
+                this.comments,
+                {
+                    token : "entity.name.label.csound-score",
+                    regex : /[A-Z_a-z]\w*/
+                }
+            ]
+        }, {
+            token : "keyword.preprocessor.csound-score",
+            regex : /r\b/,
+            next  : "repeat section"
+        },
+
+        this.numbers,
+
+        {
+            token : "keyword.operator.csound-score",
+            regex : "[!+\\-*/^%&|<>#~.]"
+        },
+
+        this.pushRule({
+            token : "punctuation.definition.string.begin.csound-score",
+            regex : /"/,
+            next  : "quoted string"
+        }),
+
+        this.pushRule({
+            token : "punctuation.braced-loop.begin.csound-score",
+            regex : /{/,
+            next  : "loop after left brace"
+        })
+    );
+
+    this.addRules({
+        "repeat section": [
+            {
+                token : "empty",
+                regex : /$/,
+                next  : "start"
+            },
+            this.comments,
+            {
+                token : "constant.numeric.integer.decimal.csound-score",
+                regex : /\d+/,
+                next  : "repeat section before label"
+            }
+        ],
+        "repeat section before label": [
+            {
+                token : "empty",
+                regex : /$/,
+                next  : "start"
+            },
+            this.comments,
+            {
+                token : "entity.name.label.csound-score",
+                regex : /[A-Z_a-z]\w*/,
+                next  : "start"
+            }
+        ],
+
+        "quoted string": [
+            this.popRule({
+                token : "punctuation.definition.string.end.csound-score",
+                regex : /"/
+            }),
+            this.quotedStringContents,
+            {
+                defaultToken: "string.quoted.csound-score"
+            }
+        ],
+
+        "loop after left brace": [
+            this.popRule({
+                token : "constant.numeric.integer.decimal.csound-score",
+                regex : /\d+/,
+                next  : "loop after repeat count"
+            }),
+            this.comments,
+            {
+                token : "invalid.illegal.csound",
+                regex : /\S.*/
+            }
+        ],
+        "loop after repeat count": [
+            this.popRule({
+                token : "entity.name.function.preprocessor.csound-score",
+                regex : /[A-Z_a-z]\w*\b/,
+                next  : "loop after macro name"
+            }),
+            this.comments,
+            {
+                token : "invalid.illegal.csound",
+                regex : /\S.*/
+            }
+        ],
+        "loop after macro name": [
+            start,
+            this.popRule({
+                token : "punctuation.braced-loop.end.csound-score",
+                regex : /}/
+            })
+        ]
+    });
+
+    this.normalizeRules();
+};
+
+oop.inherits(CsoundScoreHighlightRules, CsoundPreprocessorHighlightRules);
+
+exports.CsoundScoreHighlightRules = CsoundScoreHighlightRules;
+});
+
+ace.define("ace/mode/lua_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var LuaHighlightRules = function() {
+
+    var keywords = (
+        "break|do|else|elseif|end|for|function|if|in|local|repeat|"+
+         "return|then|until|while|or|and|not"
+    );
+
+    var builtinConstants = ("true|false|nil|_G|_VERSION");
+
+    var functions = (
+        "string|xpcall|package|tostring|print|os|unpack|require|"+
+        "getfenv|setmetatable|next|assert|tonumber|io|rawequal|"+
+        "collectgarbage|getmetatable|module|rawset|math|debug|"+
+        "pcall|table|newproxy|type|coroutine|_G|select|gcinfo|"+
+        "pairs|rawget|loadstring|ipairs|_VERSION|dofile|setfenv|"+
+        "load|error|loadfile|"+
+
+        "sub|upper|len|gfind|rep|find|match|char|dump|gmatch|"+
+        "reverse|byte|format|gsub|lower|preload|loadlib|loaded|"+
+        "loaders|cpath|config|path|seeall|exit|setlocale|date|"+
+        "getenv|difftime|remove|time|clock|tmpname|rename|execute|"+
+        "lines|write|close|flush|open|output|type|read|stderr|"+
+        "stdin|input|stdout|popen|tmpfile|log|max|acos|huge|"+
+        "ldexp|pi|cos|tanh|pow|deg|tan|cosh|sinh|random|randomseed|"+
+        "frexp|ceil|floor|rad|abs|sqrt|modf|asin|min|mod|fmod|log10|"+
+        "atan2|exp|sin|atan|getupvalue|debug|sethook|getmetatable|"+
+        "gethook|setmetatable|setlocal|traceback|setfenv|getinfo|"+
+        "setupvalue|getlocal|getregistry|getfenv|setn|insert|getn|"+
+        "foreachi|maxn|foreach|concat|sort|remove|resume|yield|"+
+        "status|wrap|create|running|"+
+        "__add|__sub|__mod|__unm|__concat|__lt|__index|__call|__gc|__metatable|"+
+         "__mul|__div|__pow|__len|__eq|__le|__newindex|__tostring|__mode|__tonumber"
+    );
+
+    var stdLibaries = ("string|package|os|io|math|debug|table|coroutine");
+
+    var deprecatedIn5152 = ("setn|foreach|foreachi|gcinfo|log10|maxn");
+
+    var keywordMapper = this.createKeywordMapper({
+        "keyword": keywords,
+        "support.function": functions,
+        "keyword.deprecated": deprecatedIn5152,
+        "constant.library": stdLibaries,
+        "constant.language": builtinConstants,
+        "variable.language": "self"
+    }, "identifier");
+
+    var decimalInteger = "(?:(?:[1-9]\\d*)|(?:0))";
+    var hexInteger = "(?:0[xX][\\dA-Fa-f]+)";
+    var integer = "(?:" + decimalInteger + "|" + hexInteger + ")";
+
+    var fraction = "(?:\\.\\d+)";
+    var intPart = "(?:\\d+)";
+    var pointFloat = "(?:(?:" + intPart + "?" + fraction + ")|(?:" + intPart + "\\.))";
+    var floatNumber = "(?:" + pointFloat + ")";
+
+    this.$rules = {
+        "start" : [{
+            stateName: "bracketedComment",
+            onMatch : function(value, currentState, stack){
+                stack.unshift(this.next, value.length - 2, currentState);
+                return "comment";
+            },
+            regex : /\-\-\[=*\[/,
+            next  : [
+                {
+                    onMatch : function(value, currentState, stack) {
+                        if (value.length == stack[1]) {
+                            stack.shift();
+                            stack.shift();
+                            this.next = stack.shift();
+                        } else {
+                            this.next = "";
+                        }
+                        return "comment";
+                    },
+                    regex : /\]=*\]/,
+                    next  : "start"
+                }, {
+                    defaultToken : "comment"
+                }
+            ]
+        },
+
+        {
+            token : "comment",
+            regex : "\\-\\-.*$"
+        },
+        {
+            stateName: "bracketedString",
+            onMatch : function(value, currentState, stack){
+                stack.unshift(this.next, value.length, currentState);
+                return "string.start";
+            },
+            regex : /\[=*\[/,
+            next  : [
+                {
+                    onMatch : function(value, currentState, stack) {
+                        if (value.length == stack[1]) {
+                            stack.shift();
+                            stack.shift();
+                            this.next = stack.shift();
+                        } else {
+                            this.next = "";
+                        }
+                        return "string.end";
+                    },
+                    
+                    regex : /\]=*\]/,
+                    next  : "start"
+                }, {
+                    defaultToken : "string"
+                }
+            ]
+        },
+        {
+            token : "string",           // " string
+            regex : '"(?:[^\\\\]|\\\\.)*?"'
+        }, {
+            token : "string",           // ' string
+            regex : "'(?:[^\\\\]|\\\\.)*?'"
+        }, {
+            token : "constant.numeric", // float
+            regex : floatNumber
+        }, {
+            token : "constant.numeric", // integer
+            regex : integer + "\\b"
+        }, {
+            token : keywordMapper,
+            regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
+        }, {
+            token : "keyword.operator",
+            regex : "\\+|\\-|\\*|\\/|%|\\#|\\^|~|<|>|<=|=>|==|~=|=|\\:|\\.\\.\\.|\\.\\."
+        }, {
+            token : "paren.lparen",
+            regex : "[\\[\\(\\{]"
+        }, {
+            token : "paren.rparen",
+            regex : "[\\]\\)\\}]"
+        }, {
+            token : "text",
+            regex : "\\s+|\\w+"
+        } ]
+    };
+    
+    this.normalizeRules();
+};
+
+oop.inherits(LuaHighlightRules, TextHighlightRules);
+
+exports.LuaHighlightRules = LuaHighlightRules;
+});
+
+ace.define("ace/mode/python_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var PythonHighlightRules = function() {
+
+    var keywords = (
+        "and|as|assert|break|class|continue|def|del|elif|else|except|exec|" +
+        "finally|for|from|global|if|import|in|is|lambda|not|or|pass|print|" +
+        "raise|return|try|while|with|yield|async|await|nonlocal"
+    );
+
+    var builtinConstants = (
+        "True|False|None|NotImplemented|Ellipsis|__debug__"
+    );
+
+    var builtinFunctions = (
+        "abs|divmod|input|open|staticmethod|all|enumerate|int|ord|str|any|" +
+        "eval|isinstance|pow|sum|basestring|execfile|issubclass|print|super|" +
+        "binfile|bin|iter|property|tuple|bool|filter|len|range|type|bytearray|" +
+        "float|list|raw_input|unichr|callable|format|locals|reduce|unicode|" +
+        "chr|frozenset|long|reload|vars|classmethod|getattr|map|repr|xrange|" +
+        "cmp|globals|max|reversed|zip|compile|hasattr|memoryview|round|" +
+        "__import__|complex|hash|min|apply|delattr|help|next|setattr|set|" +
+        "buffer|dict|hex|object|slice|coerce|dir|id|oct|sorted|intern|" +
+        "ascii|breakpoint|bytes"
+    );
+    var keywordMapper = this.createKeywordMapper({
+        "invalid.deprecated": "debugger",
+        "support.function": builtinFunctions,
+        "variable.language": "self|cls",
+        "constant.language": builtinConstants,
+        "keyword": keywords
+    }, "identifier");
+
+    var strPre = "[uU]?";
+    var strRawPre = "[rR]";
+    var strFormatPre = "[fF]";
+    var strRawFormatPre = "(?:[rR][fF]|[fF][rR])";
+    var decimalInteger = "(?:(?:[1-9]\\d*)|(?:0))";
+    var octInteger = "(?:0[oO]?[0-7]+)";
+    var hexInteger = "(?:0[xX][\\dA-Fa-f]+)";
+    var binInteger = "(?:0[bB][01]+)";
+    var integer = "(?:" + decimalInteger + "|" + octInteger + "|" + hexInteger + "|" + binInteger + ")";
+
+    var exponent = "(?:[eE][+-]?\\d+)";
+    var fraction = "(?:\\.\\d+)";
+    var intPart = "(?:\\d+)";
+    var pointFloat = "(?:(?:" + intPart + "?" + fraction + ")|(?:" + intPart + "\\.))";
+    var exponentFloat = "(?:(?:" + pointFloat + "|" + intPart + ")" + exponent + ")";
+    var floatNumber = "(?:" + exponentFloat + "|" + pointFloat + ")";
+
+    var stringEscape = "\\\\(x[0-9A-Fa-f]{2}|[0-7]{3}|[\\\\abfnrtv'\"]|U[0-9A-Fa-f]{8}|u[0-9A-Fa-f]{4})";
+
+    this.$rules = {
+        "start" : [ {
+            token : "comment",
+            regex : "#.*$"
+        }, {
+            token : "string",           // multi line """ string start
+            regex : strPre + '"{3}',
+            next : "qqstring3"
+        }, {
+            token : "string",           // " string
+            regex : strPre + '"(?=.)',
+            next : "qqstring"
+        }, {
+            token : "string",           // multi line ''' string start
+            regex : strPre + "'{3}",
+            next : "qstring3"
+        }, {
+            token : "string",           // ' string
+            regex : strPre + "'(?=.)",
+            next : "qstring"
+        }, {
+            token: "string",
+            regex: strRawPre + '"{3}',
+            next: "rawqqstring3"
+        }, {
+            token: "string", 
+            regex: strRawPre + '"(?=.)',
+            next: "rawqqstring"
+        }, {
+            token: "string",
+            regex: strRawPre + "'{3}",
+            next: "rawqstring3"
+        }, {
+            token: "string",
+            regex: strRawPre + "'(?=.)",
+            next: "rawqstring"
+        }, {
+            token: "string",
+            regex: strFormatPre + '"{3}',
+            next: "fqqstring3"
+        }, {
+            token: "string",
+            regex: strFormatPre + '"(?=.)',
+            next: "fqqstring"
+        }, {
+            token: "string",
+            regex: strFormatPre + "'{3}",
+            next: "fqstring3"
+        }, {
+            token: "string",
+            regex: strFormatPre + "'(?=.)",
+            next: "fqstring"
+        },{
+            token: "string",
+            regex: strRawFormatPre + '"{3}',
+            next: "rfqqstring3"
+        }, {
+            token: "string",
+            regex: strRawFormatPre + '"(?=.)',
+            next: "rfqqstring"
+        }, {
+            token: "string",
+            regex: strRawFormatPre + "'{3}",
+            next: "rfqstring3"
+        }, {
+            token: "string",
+            regex: strRawFormatPre + "'(?=.)",
+            next: "rfqstring"
+        }, {
+            token: "keyword.operator",
+            regex: "\\+|\\-|\\*|\\*\\*|\\/|\\/\\/|%|@|<<|>>|&|\\||\\^|~|<|>|<=|=>|==|!=|<>|="
+        }, {
+            token: "punctuation",
+            regex: ",|:|;|\\->|\\+=|\\-=|\\*=|\\/=|\\/\\/=|%=|@=|&=|\\|=|^=|>>=|<<=|\\*\\*="
+        }, {
+            token: "paren.lparen",
+            regex: "[\\[\\(\\{]"
+        }, {
+            token: "paren.rparen",
+            regex: "[\\]\\)\\}]"
+        }, {
+            token: "text",
+            regex: "\\s+"
+        }, {
+            include: "constants"
+        }],
+        "qqstring3": [{
+            token: "constant.language.escape",
+            regex: stringEscape
+        }, {
+            token: "string", // multi line """ string end
+            regex: '"{3}',
+            next: "start"
+        }, {
+            defaultToken: "string"
+        }],
+        "qstring3": [{
+            token: "constant.language.escape",
+            regex: stringEscape
+        }, {
+            token: "string",  // multi line ''' string end
+            regex: "'{3}",
+            next: "start"
+        }, {
+            defaultToken: "string"
+        }],
+        "qqstring": [{
+            token: "constant.language.escape",
+            regex: stringEscape
+        }, {
+            token: "string",
+            regex: "\\\\$",
+            next: "qqstring"
+        }, {
+            token: "string",
+            regex: '"|$',
+            next: "start"
+        }, {
+            defaultToken: "string"
+        }],
+        "qstring": [{
+            token: "constant.language.escape",
+            regex: stringEscape
+        }, {
+            token: "string",
+            regex: "\\\\$",
+            next: "qstring"
+        }, {
+            token: "string",
+            regex: "'|$",
+            next: "start"
+        }, {
+            defaultToken: "string"
+        }],
+        "rawqqstring3": [{
+            token: "string", // multi line """ string end
+            regex: '"{3}',
+            next: "start"
+        }, {
+            defaultToken: "string"
+        }],
+        "rawqstring3": [{
+            token: "string",  // multi line ''' string end
+            regex: "'{3}",
+            next: "start"
+        }, {
+            defaultToken: "string"
+        }],
+        "rawqqstring": [{
+            token: "string",
+            regex: "\\\\$",
+            next: "rawqqstring"
+        }, {
+            token: "string",
+            regex: '"|$',
+            next: "start"
+        }, {
+            defaultToken: "string"
+        }],
+        "rawqstring": [{
+            token: "string",
+            regex: "\\\\$",
+            next: "rawqstring"
+        }, {
+            token: "string",
+            regex: "'|$",
+            next: "start"
+        }, {
+            defaultToken: "string"
+        }],
+        "fqqstring3": [{
+            token: "constant.language.escape",
+            regex: stringEscape
+        }, {
+            token: "string", // multi line """ string end
+            regex: '"{3}',
+            next: "start"
+        }, {
+            token: "paren.lparen",
+            regex: "{",
+            push: "fqstringParRules"
+        }, {
+            defaultToken: "string"
+        }],
+        "fqstring3": [{
+            token: "constant.language.escape",
+            regex: stringEscape
+        }, {
+            token: "string",  // multi line ''' string end
+            regex: "'{3}",
+            next: "start"
+        }, {
+            token: "paren.lparen",
+            regex: "{",
+            push: "fqstringParRules"
+        }, {
+            defaultToken: "string"
+        }],
+        "fqqstring": [{
+            token: "constant.language.escape",
+            regex: stringEscape
+        }, {
+            token: "string",
+            regex: "\\\\$",
+            next: "fqqstring"
+        }, {
+            token: "string",
+            regex: '"|$',
+            next: "start"
+        }, {
+            token: "paren.lparen",
+            regex: "{",
+            push: "fqstringParRules"
+        }, {
+            defaultToken: "string"
+        }],
+        "fqstring": [{
+            token: "constant.language.escape",
+            regex: stringEscape
+        }, {
+            token: "string",
+            regex: "'|$",
+            next: "start"
+        }, {
+            token: "paren.lparen",
+            regex: "{",
+            push: "fqstringParRules"
+        }, {
+            defaultToken: "string"
+        }],
+        "rfqqstring3": [{
+            token: "string", // multi line """ string end
+            regex: '"{3}',
+            next: "start"
+        }, {
+            token: "paren.lparen",
+            regex: "{",
+            push: "fqstringParRules"
+        }, {
+            defaultToken: "string"
+        }],
+        "rfqstring3": [{
+            token: "string",  // multi line ''' string end
+            regex: "'{3}",
+            next: "start"
+        }, {
+            token: "paren.lparen",
+            regex: "{",
+            push: "fqstringParRules"
+        }, {
+            defaultToken: "string"
+        }],
+        "rfqqstring": [{
+            token: "string",
+            regex: "\\\\$",
+            next: "rfqqstring"
+        }, {
+            token: "string",
+            regex: '"|$',
+            next: "start"
+        }, {
+            token: "paren.lparen",
+            regex: "{",
+            push: "fqstringParRules"
+        }, {
+            defaultToken: "string"
+        }],
+        "rfqstring": [{
+            token: "string",
+            regex: "'|$",
+            next: "start"
+        }, {
+            token: "paren.lparen",
+            regex: "{",
+            push: "fqstringParRules"
+        }, {
+            defaultToken: "string"
+        }],
+        "fqstringParRules": [{//TODO: nested {}
+            token: "paren.lparen",
+            regex: "[\\[\\(]"
+        }, {
+            token: "paren.rparen",
+            regex: "[\\]\\)]"
+        }, {
+            token: "string",
+            regex: "\\s+"
+        }, {
+            token: "string",
+            regex: "'(.)*'"
+        }, {
+            token: "string",
+            regex: '"(.)*"'
+        }, {
+            token: "function.support",
+            regex: "(!s|!r|!a)"
+        }, {
+            include: "constants"
+        },{
+            token: 'paren.rparen',
+            regex: "}",
+            next: 'pop'
+        },{
+            token: 'paren.lparen',
+            regex: "{",
+            push: "fqstringParRules"
+        }],
+        "constants": [{
+            token: "constant.numeric", // imaginary
+            regex: "(?:" + floatNumber + "|\\d+)[jJ]\\b"
+        }, {
+            token: "constant.numeric", // float
+            regex: floatNumber
+        }, {
+            token: "constant.numeric", // long integer
+            regex: integer + "[lL]\\b"
+        }, {
+            token: "constant.numeric", // integer
+            regex: integer + "\\b"
+        }, {
+            token: ["punctuation", "function.support"],// method
+            regex: "(\\.)([a-zA-Z_]+)\\b"
+        }, {
+            token: keywordMapper,
+            regex: "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
+        }]
+    };
+    this.normalizeRules();
+};
+
+oop.inherits(PythonHighlightRules, TextHighlightRules);
+
+exports.PythonHighlightRules = PythonHighlightRules;
+});
+
+ace.define("ace/mode/csound_orchestra_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var lang = require("../lib/lang");
+var oop = require("../lib/oop");
+
+var CsoundPreprocessorHighlightRules = require("./csound_preprocessor_highlight_rules").CsoundPreprocessorHighlightRules;
+var CsoundScoreHighlightRules = require("./csound_score_highlight_rules").CsoundScoreHighlightRules;
+var LuaHighlightRules = require("./lua_highlight_rules").LuaHighlightRules;
+var PythonHighlightRules = require("./python_highlight_rules").PythonHighlightRules;
+
+var CsoundOrchestraHighlightRules = function() {
+
+    CsoundPreprocessorHighlightRules.call(this);
+    var opcodes = [
+        "ATSadd",
+        "ATSaddnz",
+        "ATSbufread",
+        "ATScross",
+        "ATSinfo",
+        "ATSinterpread",
+        "ATSpartialtap",
+        "ATSread",
+        "ATSreadnz",
+        "ATSsinnoi",
+        "FLbox",
+        "FLbutBank",
+        "FLbutton",
+        "FLcloseButton",
+        "FLcolor",
+        "FLcolor2",
+        "FLcount",
+        "FLexecButton",
+        "FLgetsnap",
+        "FLgroup",
+        "FLgroupEnd",
+        "FLgroup_end",
+        "FLhide",
+        "FLhvsBox",
+        "FLhvsBoxSetValue",
+        "FLjoy",
+        "FLkeyIn",
+        "FLknob",
+        "FLlabel",
+        "FLloadsnap",
+        "FLmouse",
+        "FLpack",
+        "FLpackEnd",
+        "FLpack_end",
+        "FLpanel",
+        "FLpanelEnd",
+        "FLpanel_end",
+        "FLprintk",
+        "FLprintk2",
+        "FLroller",
+        "FLrun",
+        "FLsavesnap",
+        "FLscroll",
+        "FLscrollEnd",
+        "FLscroll_end",
+        "FLsetAlign",
+        "FLsetBox",
+        "FLsetColor",
+        "FLsetColor2",
+        "FLsetFont",
+        "FLsetPosition",
+        "FLsetSize",
+        "FLsetSnapGroup",
+        "FLsetText",
+        "FLsetTextColor",
+        "FLsetTextSize",
+        "FLsetTextType",
+        "FLsetVal",
+        "FLsetVal_i",
+        "FLsetVali",
+        "FLsetsnap",
+        "FLshow",
+        "FLslidBnk",
+        "FLslidBnk2",
+        "FLslidBnk2Set",
+        "FLslidBnk2Setk",
+        "FLslidBnkGetHandle",
+        "FLslidBnkSet",
+        "FLslidBnkSetk",
+        "FLslider",
+        "FLtabs",
+        "FLtabsEnd",
+        "FLtabs_end",
+        "FLtext",
+        "FLupdate",
+        "FLvalue",
+        "FLvkeybd",
+        "FLvslidBnk",
+        "FLvslidBnk2",
+        "FLxyin",
+        "JackoAudioIn",
+        "JackoAudioInConnect",
+        "JackoAudioOut",
+        "JackoAudioOutConnect",
+        "JackoFreewheel",
+        "JackoInfo",
+        "JackoInit",
+        "JackoMidiInConnect",
+        "JackoMidiOut",
+        "JackoMidiOutConnect",
+        "JackoNoteOut",
+        "JackoOn",
+        "JackoTransport",
+        "K35_hpf",
+        "K35_lpf",
+        "MixerClear",
+        "MixerGetLevel",
+        "MixerReceive",
+        "MixerSend",
+        "MixerSetLevel",
+        "MixerSetLevel_i",
+        "OSCbundle",
+        "OSCcount",
+        "OSCinit",
+        "OSCinitM",
+        "OSClisten",
+        "OSCraw",
+        "OSCsend",
+        "OSCsend_lo",
+        "S",
+        "STKBandedWG",
+        "STKBeeThree",
+        "STKBlowBotl",
+        "STKBlowHole",
+        "STKBowed",
+        "STKBrass",
+        "STKClarinet",
+        "STKDrummer",
+        "STKFMVoices",
+        "STKFlute",
+        "STKHevyMetl",
+        "STKMandolin",
+        "STKModalBar",
+        "STKMoog",
+        "STKPercFlut",
+        "STKPlucked",
+        "STKResonate",
+        "STKRhodey",
+        "STKSaxofony",
+        "STKShakers",
+        "STKSimple",
+        "STKSitar",
+        "STKStifKarp",
+        "STKTubeBell",
+        "STKVoicForm",
+        "STKWhistle",
+        "STKWurley",
+        "a",
+        "abs",
+        "active",
+        "adsr",
+        "adsyn",
+        "adsynt",
+        "adsynt2",
+        "aftouch",
+        "alpass",
+        "alwayson",
+        "ampdb",
+        "ampdbfs",
+        "ampmidi",
+        "ampmidid",
+        "areson",
+        "aresonk",
+        "atone",
+        "atonek",
+        "atonex",
+        "babo",
+        "balance",
+        "balance2",
+        "bamboo",
+        "barmodel",
+        "bbcutm",
+        "bbcuts",
+        "beadsynt",
+        "beosc",
+        "betarand",
+        "bexprnd",
+        "bformdec1",
+        "bformenc1",
+        "binit",
+        "biquad",
+        "biquada",
+        "birnd",
+        "bpf",
+        "bpfcos",
+        "bqrez",
+        "butbp",
+        "butbr",
+        "buthp",
+        "butlp",
+        "butterbp",
+        "butterbr",
+        "butterhp",
+        "butterlp",
+        "button",
+        "buzz",
+        "c2r",
+        "cabasa",
+        "cauchy",
+        "cauchyi",
+        "cbrt",
+        "ceil",
+        "cell",
+        "cent",
+        "centroid",
+        "ceps",
+        "cepsinv",
+        "chanctrl",
+        "changed",
+        "changed2",
+        "chani",
+        "chano",
+        "chebyshevpoly",
+        "checkbox",
+        "chn_S",
+        "chn_a",
+        "chn_k",
+        "chnclear",
+        "chnexport",
+        "chnget",
+        "chngetks",
+        "chnmix",
+        "chnparams",
+        "chnset",
+        "chnsetks",
+        "chuap",
+        "clear",
+        "clfilt",
+        "clip",
+        "clockoff",
+        "clockon",
+        "cmp",
+        "cmplxprod",
+        "comb",
+        "combinv",
+        "compilecsd",
+        "compileorc",
+        "compilestr",
+        "compress",
+        "compress2",
+        "connect",
+        "control",
+        "convle",
+        "convolve",
+        "copya2ftab",
+        "copyf2array",
+        "cos",
+        "cosh",
+        "cosinv",
+        "cosseg",
+        "cossegb",
+        "cossegr",
+        "cps2pch",
+        "cpsmidi",
+        "cpsmidib",
+        "cpsmidinn",
+        "cpsoct",
+        "cpspch",
+        "cpstmid",
+        "cpstun",
+        "cpstuni",
+        "cpsxpch",
+        "cpumeter",
+        "cpuprc",
+        "cross2",
+        "crossfm",
+        "crossfmi",
+        "crossfmpm",
+        "crossfmpmi",
+        "crosspm",
+        "crosspmi",
+        "crunch",
+        "ctlchn",
+        "ctrl14",
+        "ctrl21",
+        "ctrl7",
+        "ctrlinit",
+        "cuserrnd",
+        "dam",
+        "date",
+        "dates",
+        "db",
+        "dbamp",
+        "dbfsamp",
+        "dcblock",
+        "dcblock2",
+        "dconv",
+        "dct",
+        "dctinv",
+        "deinterleave",
+        "delay",
+        "delay1",
+        "delayk",
+        "delayr",
+        "delayw",
+        "deltap",
+        "deltap3",
+        "deltapi",
+        "deltapn",
+        "deltapx",
+        "deltapxw",
+        "denorm",
+        "diff",
+        "diode_ladder",
+        "directory",
+        "diskgrain",
+        "diskin",
+        "diskin2",
+        "dispfft",
+        "display",
+        "distort",
+        "distort1",
+        "divz",
+        "doppler",
+        "dot",
+        "downsamp",
+        "dripwater",
+        "dssiactivate",
+        "dssiaudio",
+        "dssictls",
+        "dssiinit",
+        "dssilist",
+        "dumpk",
+        "dumpk2",
+        "dumpk3",
+        "dumpk4",
+        "duserrnd",
+        "dust",
+        "dust2",
+        "envlpx",
+        "envlpxr",
+        "ephasor",
+        "eqfil",
+        "evalstr",
+        "event",
+        "event_i",
+        "exciter",
+        "exitnow",
+        "exp",
+        "expcurve",
+        "expon",
+        "exprand",
+        "exprandi",
+        "expseg",
+        "expsega",
+        "expsegb",
+        "expsegba",
+        "expsegr",
+        "fareylen",
+        "fareyleni",
+        "faustaudio",
+        "faustcompile",
+        "faustctl",
+        "faustdsp",
+        "faustgen",
+        "faustplay",
+        "fft",
+        "fftinv",
+        "ficlose",
+        "filebit",
+        "filelen",
+        "filenchnls",
+        "filepeak",
+        "filescal",
+        "filesr",
+        "filevalid",
+        "fillarray",
+        "filter2",
+        "fin",
+        "fini",
+        "fink",
+        "fiopen",
+        "flanger",
+        "flashtxt",
+        "flooper",
+        "flooper2",
+        "floor",
+        "fmanal",
+        "fmax",
+        "fmb3",
+        "fmbell",
+        "fmin",
+        "fmmetal",
+        "fmod",
+        "fmpercfl",
+        "fmrhode",
+        "fmvoice",
+        "fmwurlie",
+        "fof",
+        "fof2",
+        "fofilter",
+        "fog",
+        "fold",
+        "follow",
+        "follow2",
+        "foscil",
+        "foscili",
+        "fout",
+        "fouti",
+        "foutir",
+        "foutk",
+        "fprintks",
+        "fprints",
+        "frac",
+        "fractalnoise",
+        "framebuffer",
+        "freeverb",
+        "ftaudio",
+        "ftchnls",
+        "ftconv",
+        "ftcps",
+        "ftfree",
+        "ftgen",
+        "ftgenonce",
+        "ftgentmp",
+        "ftlen",
+        "ftload",
+        "ftloadk",
+        "ftlptim",
+        "ftmorf",
+        "ftom",
+        "ftprint",
+        "ftresize",
+        "ftresizei",
+        "ftsamplebank",
+        "ftsave",
+        "ftsavek",
+        "ftslice",
+        "ftsr",
+        "gain",
+        "gainslider",
+        "gauss",
+        "gaussi",
+        "gausstrig",
+        "gbuzz",
+        "genarray",
+        "genarray_i",
+        "gendy",
+        "gendyc",
+        "gendyx",
+        "getcfg",
+        "getcol",
+        "getftargs",
+        "getrow",
+        "getrowlin",
+        "getseed",
+        "gogobel",
+        "grain",
+        "grain2",
+        "grain3",
+        "granule",
+        "guiro",
+        "harmon",
+        "harmon2",
+        "harmon3",
+        "harmon4",
+        "hdf5read",
+        "hdf5write",
+        "hilbert",
+        "hilbert2",
+        "hrtfearly",
+        "hrtfmove",
+        "hrtfmove2",
+        "hrtfreverb",
+        "hrtfstat",
+        "hsboscil",
+        "hvs1",
+        "hvs2",
+        "hvs3",
+        "hypot",
+        "i",
+        "ihold",
+        "imagecreate",
+        "imagefree",
+        "imagegetpixel",
+        "imageload",
+        "imagesave",
+        "imagesetpixel",
+        "imagesize",
+        "in",
+        "in32",
+        "inch",
+        "inh",
+        "init",
+        "initc14",
+        "initc21",
+        "initc7",
+        "inleta",
+        "inletf",
+        "inletk",
+        "inletkid",
+        "inletv",
+        "ino",
+        "inq",
+        "inrg",
+        "ins",
+        "insglobal",
+        "insremot",
+        "int",
+        "integ",
+        "interleave",
+        "interp",
+        "invalue",
+        "inx",
+        "inz",
+        "jacktransport",
+        "jitter",
+        "jitter2",
+        "joystick",
+        "jspline",
+        "k",
+        "la_i_add_mc",
+        "la_i_add_mr",
+        "la_i_add_vc",
+        "la_i_add_vr",
+        "la_i_assign_mc",
+        "la_i_assign_mr",
+        "la_i_assign_t",
+        "la_i_assign_vc",
+        "la_i_assign_vr",
+        "la_i_conjugate_mc",
+        "la_i_conjugate_mr",
+        "la_i_conjugate_vc",
+        "la_i_conjugate_vr",
+        "la_i_distance_vc",
+        "la_i_distance_vr",
+        "la_i_divide_mc",
+        "la_i_divide_mr",
+        "la_i_divide_vc",
+        "la_i_divide_vr",
+        "la_i_dot_mc",
+        "la_i_dot_mc_vc",
+        "la_i_dot_mr",
+        "la_i_dot_mr_vr",
+        "la_i_dot_vc",
+        "la_i_dot_vr",
+        "la_i_get_mc",
+        "la_i_get_mr",
+        "la_i_get_vc",
+        "la_i_get_vr",
+        "la_i_invert_mc",
+        "la_i_invert_mr",
+        "la_i_lower_solve_mc",
+        "la_i_lower_solve_mr",
+        "la_i_lu_det_mc",
+        "la_i_lu_det_mr",
+        "la_i_lu_factor_mc",
+        "la_i_lu_factor_mr",
+        "la_i_lu_solve_mc",
+        "la_i_lu_solve_mr",
+        "la_i_mc_create",
+        "la_i_mc_set",
+        "la_i_mr_create",
+        "la_i_mr_set",
+        "la_i_multiply_mc",
+        "la_i_multiply_mr",
+        "la_i_multiply_vc",
+        "la_i_multiply_vr",
+        "la_i_norm1_mc",
+        "la_i_norm1_mr",
+        "la_i_norm1_vc",
+        "la_i_norm1_vr",
+        "la_i_norm_euclid_mc",
+        "la_i_norm_euclid_mr",
+        "la_i_norm_euclid_vc",
+        "la_i_norm_euclid_vr",
+        "la_i_norm_inf_mc",
+        "la_i_norm_inf_mr",
+        "la_i_norm_inf_vc",
+        "la_i_norm_inf_vr",
+        "la_i_norm_max_mc",
+        "la_i_norm_max_mr",
+        "la_i_print_mc",
+        "la_i_print_mr",
+        "la_i_print_vc",
+        "la_i_print_vr",
+        "la_i_qr_eigen_mc",
+        "la_i_qr_eigen_mr",
+        "la_i_qr_factor_mc",
+        "la_i_qr_factor_mr",
+        "la_i_qr_sym_eigen_mc",
+        "la_i_qr_sym_eigen_mr",
+        "la_i_random_mc",
+        "la_i_random_mr",
+        "la_i_random_vc",
+        "la_i_random_vr",
+        "la_i_size_mc",
+        "la_i_size_mr",
+        "la_i_size_vc",
+        "la_i_size_vr",
+        "la_i_subtract_mc",
+        "la_i_subtract_mr",
+        "la_i_subtract_vc",
+        "la_i_subtract_vr",
+        "la_i_t_assign",
+        "la_i_trace_mc",
+        "la_i_trace_mr",
+        "la_i_transpose_mc",
+        "la_i_transpose_mr",
+        "la_i_upper_solve_mc",
+        "la_i_upper_solve_mr",
+        "la_i_vc_create",
+        "la_i_vc_set",
+        "la_i_vr_create",
+        "la_i_vr_set",
+        "la_k_a_assign",
+        "la_k_add_mc",
+        "la_k_add_mr",
+        "la_k_add_vc",
+        "la_k_add_vr",
+        "la_k_assign_a",
+        "la_k_assign_f",
+        "la_k_assign_mc",
+        "la_k_assign_mr",
+        "la_k_assign_t",
+        "la_k_assign_vc",
+        "la_k_assign_vr",
+        "la_k_conjugate_mc",
+        "la_k_conjugate_mr",
+        "la_k_conjugate_vc",
+        "la_k_conjugate_vr",
+        "la_k_current_f",
+        "la_k_current_vr",
+        "la_k_distance_vc",
+        "la_k_distance_vr",
+        "la_k_divide_mc",
+        "la_k_divide_mr",
+        "la_k_divide_vc",
+        "la_k_divide_vr",
+        "la_k_dot_mc",
+        "la_k_dot_mc_vc",
+        "la_k_dot_mr",
+        "la_k_dot_mr_vr",
+        "la_k_dot_vc",
+        "la_k_dot_vr",
+        "la_k_f_assign",
+        "la_k_get_mc",
+        "la_k_get_mr",
+        "la_k_get_vc",
+        "la_k_get_vr",
+        "la_k_invert_mc",
+        "la_k_invert_mr",
+        "la_k_lower_solve_mc",
+        "la_k_lower_solve_mr",
+        "la_k_lu_det_mc",
+        "la_k_lu_det_mr",
+        "la_k_lu_factor_mc",
+        "la_k_lu_factor_mr",
+        "la_k_lu_solve_mc",
+        "la_k_lu_solve_mr",
+        "la_k_mc_set",
+        "la_k_mr_set",
+        "la_k_multiply_mc",
+        "la_k_multiply_mr",
+        "la_k_multiply_vc",
+        "la_k_multiply_vr",
+        "la_k_norm1_mc",
+        "la_k_norm1_mr",
+        "la_k_norm1_vc",
+        "la_k_norm1_vr",
+        "la_k_norm_euclid_mc",
+        "la_k_norm_euclid_mr",
+        "la_k_norm_euclid_vc",
+        "la_k_norm_euclid_vr",
+        "la_k_norm_inf_mc",
+        "la_k_norm_inf_mr",
+        "la_k_norm_inf_vc",
+        "la_k_norm_inf_vr",
+        "la_k_norm_max_mc",
+        "la_k_norm_max_mr",
+        "la_k_qr_eigen_mc",
+        "la_k_qr_eigen_mr",
+        "la_k_qr_factor_mc",
+        "la_k_qr_factor_mr",
+        "la_k_qr_sym_eigen_mc",
+        "la_k_qr_sym_eigen_mr",
+        "la_k_random_mc",
+        "la_k_random_mr",
+        "la_k_random_vc",
+        "la_k_random_vr",
+        "la_k_subtract_mc",
+        "la_k_subtract_mr",
+        "la_k_subtract_vc",
+        "la_k_subtract_vr",
+        "la_k_t_assign",
+        "la_k_trace_mc",
+        "la_k_trace_mr",
+        "la_k_upper_solve_mc",
+        "la_k_upper_solve_mr",
+        "la_k_vc_set",
+        "la_k_vr_set",
+        "lenarray",
+        "lfo",
+        "limit",
+        "limit1",
+        "lincos",
+        "line",
+        "linen",
+        "linenr",
+        "lineto",
+        "link_beat_force",
+        "link_beat_get",
+        "link_beat_request",
+        "link_create",
+        "link_enable",
+        "link_is_enabled",
+        "link_metro",
+        "link_peers",
+        "link_tempo_get",
+        "link_tempo_set",
+        "linlin",
+        "linrand",
+        "linseg",
+        "linsegb",
+        "linsegr",
+        "liveconv",
+        "locsend",
+        "locsig",
+        "log",
+        "log10",
+        "log2",
+        "logbtwo",
+        "logcurve",
+        "loopseg",
+        "loopsegp",
+        "looptseg",
+        "loopxseg",
+        "lorenz",
+        "loscil",
+        "loscil3",
+        "loscil3phs",
+        "loscilphs",
+        "loscilx",
+        "lowpass2",
+        "lowres",
+        "lowresx",
+        "lpf18",
+        "lpform",
+        "lpfreson",
+        "lphasor",
+        "lpinterp",
+        "lposcil",
+        "lposcil3",
+        "lposcila",
+        "lposcilsa",
+        "lposcilsa2",
+        "lpread",
+        "lpreson",
+        "lpshold",
+        "lpsholdp",
+        "lpslot",
+        "lua_exec",
+        "lua_iaopcall",
+        "lua_iaopcall_off",
+        "lua_ikopcall",
+        "lua_ikopcall_off",
+        "lua_iopcall",
+        "lua_iopcall_off",
+        "lua_opdef",
+        "mac",
+        "maca",
+        "madsr",
+        "mags",
+        "mandel",
+        "mandol",
+        "maparray",
+        "maparray_i",
+        "marimba",
+        "massign",
+        "max",
+        "max_k",
+        "maxabs",
+        "maxabsaccum",
+        "maxaccum",
+        "maxalloc",
+        "maxarray",
+        "mclock",
+        "mdelay",
+        "median",
+        "mediank",
+        "metro",
+        "mfb",
+        "midglobal",
+        "midiarp",
+        "midic14",
+        "midic21",
+        "midic7",
+        "midichannelaftertouch",
+        "midichn",
+        "midicontrolchange",
+        "midictrl",
+        "mididefault",
+        "midifilestatus",
+        "midiin",
+        "midinoteoff",
+        "midinoteoncps",
+        "midinoteonkey",
+        "midinoteonoct",
+        "midinoteonpch",
+        "midion",
+        "midion2",
+        "midiout",
+        "midiout_i",
+        "midipgm",
+        "midipitchbend",
+        "midipolyaftertouch",
+        "midiprogramchange",
+        "miditempo",
+        "midremot",
+        "min",
+        "minabs",
+        "minabsaccum",
+        "minaccum",
+        "minarray",
+        "mincer",
+        "mirror",
+        "mode",
+        "modmatrix",
+        "monitor",
+        "moog",
+        "moogladder",
+        "moogladder2",
+        "moogvcf",
+        "moogvcf2",
+        "moscil",
+        "mp3bitrate",
+        "mp3in",
+        "mp3len",
+        "mp3nchnls",
+        "mp3scal",
+        "mp3sr",
+        "mpulse",
+        "mrtmsg",
+        "mtof",
+        "mton",
+        "multitap",
+        "mute",
+        "mvchpf",
+        "mvclpf1",
+        "mvclpf2",
+        "mvclpf3",
+        "mvclpf4",
+        "mxadsr",
+        "nchnls_hw",
+        "nestedap",
+        "nlalp",
+        "nlfilt",
+        "nlfilt2",
+        "noise",
+        "noteoff",
+        "noteon",
+        "noteondur",
+        "noteondur2",
+        "notnum",
+        "nreverb",
+        "nrpn",
+        "nsamp",
+        "nstance",
+        "nstrnum",
+        "ntom",
+        "ntrpol",
+        "nxtpow2",
+        "octave",
+        "octcps",
+        "octmidi",
+        "octmidib",
+        "octmidinn",
+        "octpch",
+        "olabuffer",
+        "oscbnk",
+        "oscil",
+        "oscil1",
+        "oscil1i",
+        "oscil3",
+        "oscili",
+        "oscilikt",
+        "osciliktp",
+        "oscilikts",
+        "osciln",
+        "oscils",
+        "oscilx",
+        "out",
+        "out32",
+        "outc",
+        "outch",
+        "outh",
+        "outiat",
+        "outic",
+        "outic14",
+        "outipat",
+        "outipb",
+        "outipc",
+        "outkat",
+        "outkc",
+        "outkc14",
+        "outkpat",
+        "outkpb",
+        "outkpc",
+        "outleta",
+        "outletf",
+        "outletk",
+        "outletkid",
+        "outletv",
+        "outo",
+        "outq",
+        "outq1",
+        "outq2",
+        "outq3",
+        "outq4",
+        "outrg",
+        "outs",
+        "outs1",
+        "outs2",
+        "outvalue",
+        "outx",
+        "outz",
+        "p",
+        "p5gconnect",
+        "p5gdata",
+        "pan",
+        "pan2",
+        "pareq",
+        "part2txt",
+        "partials",
+        "partikkel",
+        "partikkelget",
+        "partikkelset",
+        "partikkelsync",
+        "passign",
+        "paulstretch",
+        "pcauchy",
+        "pchbend",
+        "pchmidi",
+        "pchmidib",
+        "pchmidinn",
+        "pchoct",
+        "pchtom",
+        "pconvolve",
+        "pcount",
+        "pdclip",
+        "pdhalf",
+        "pdhalfy",
+        "peak",
+        "pgmassign",
+        "pgmchn",
+        "phaser1",
+        "phaser2",
+        "phasor",
+        "phasorbnk",
+        "phs",
+        "pindex",
+        "pinker",
+        "pinkish",
+        "pitch",
+        "pitchac",
+        "pitchamdf",
+        "planet",
+        "platerev",
+        "plltrack",
+        "pluck",
+        "poisson",
+        "pol2rect",
+        "polyaft",
+        "polynomial",
+        "port",
+        "portk",
+        "poscil",
+        "poscil3",
+        "pow",
+        "powershape",
+        "powoftwo",
+        "pows",
+        "prealloc",
+        "prepiano",
+        "print",
+        "print_type",
+        "printarray",
+        "printf",
+        "printf_i",
+        "printk",
+        "printk2",
+        "printks",
+        "printks2",
+        "prints",
+        "product",
+        "pset",
+        "ptable",
+        "ptable3",
+        "ptablei",
+        "ptableiw",
+        "ptablew",
+        "ptrack",
+        "puts",
+        "pvadd",
+        "pvbufread",
+        "pvcross",
+        "pvinterp",
+        "pvoc",
+        "pvread",
+        "pvs2array",
+        "pvs2tab",
+        "pvsadsyn",
+        "pvsanal",
+        "pvsarp",
+        "pvsbandp",
+        "pvsbandr",
+        "pvsbin",
+        "pvsblur",
+        "pvsbuffer",
+        "pvsbufread",
+        "pvsbufread2",
+        "pvscale",
+        "pvscent",
+        "pvsceps",
+        "pvscross",
+        "pvsdemix",
+        "pvsdiskin",
+        "pvsdisp",
+        "pvsenvftw",
+        "pvsfilter",
+        "pvsfread",
+        "pvsfreeze",
+        "pvsfromarray",
+        "pvsftr",
+        "pvsftw",
+        "pvsfwrite",
+        "pvsgain",
+        "pvshift",
+        "pvsifd",
+        "pvsin",
+        "pvsinfo",
+        "pvsinit",
+        "pvslock",
+        "pvsmaska",
+        "pvsmix",
+        "pvsmooth",
+        "pvsmorph",
+        "pvsosc",
+        "pvsout",
+        "pvspitch",
+        "pvstanal",
+        "pvstencil",
+        "pvstrace",
+        "pvsvoc",
+        "pvswarp",
+        "pvsynth",
+        "pwd",
+        "pyassign",
+        "pyassigni",
+        "pyassignt",
+        "pycall",
+        "pycall1",
+        "pycall1i",
+        "pycall1t",
+        "pycall2",
+        "pycall2i",
+        "pycall2t",
+        "pycall3",
+        "pycall3i",
+        "pycall3t",
+        "pycall4",
+        "pycall4i",
+        "pycall4t",
+        "pycall5",
+        "pycall5i",
+        "pycall5t",
+        "pycall6",
+        "pycall6i",
+        "pycall6t",
+        "pycall7",
+        "pycall7i",
+        "pycall7t",
+        "pycall8",
+        "pycall8i",
+        "pycall8t",
+        "pycalli",
+        "pycalln",
+        "pycallni",
+        "pycallt",
+        "pyeval",
+        "pyevali",
+        "pyevalt",
+        "pyexec",
+        "pyexeci",
+        "pyexect",
+        "pyinit",
+        "pylassign",
+        "pylassigni",
+        "pylassignt",
+        "pylcall",
+        "pylcall1",
+        "pylcall1i",
+        "pylcall1t",
+        "pylcall2",
+        "pylcall2i",
+        "pylcall2t",
+        "pylcall3",
+        "pylcall3i",
+        "pylcall3t",
+        "pylcall4",
+        "pylcall4i",
+        "pylcall4t",
+        "pylcall5",
+        "pylcall5i",
+        "pylcall5t",
+        "pylcall6",
+        "pylcall6i",
+        "pylcall6t",
+        "pylcall7",
+        "pylcall7i",
+        "pylcall7t",
+        "pylcall8",
+        "pylcall8i",
+        "pylcall8t",
+        "pylcalli",
+        "pylcalln",
+        "pylcallni",
+        "pylcallt",
+        "pyleval",
+        "pylevali",
+        "pylevalt",
+        "pylexec",
+        "pylexeci",
+        "pylexect",
+        "pylrun",
+        "pylruni",
+        "pylrunt",
+        "pyrun",
+        "pyruni",
+        "pyrunt",
+        "qinf",
+        "qnan",
+        "r2c",
+        "rand",
+        "randh",
+        "randi",
+        "random",
+        "randomh",
+        "randomi",
+        "rbjeq",
+        "readclock",
+        "readf",
+        "readfi",
+        "readk",
+        "readk2",
+        "readk3",
+        "readk4",
+        "readks",
+        "readscore",
+        "readscratch",
+        "rect2pol",
+        "release",
+        "remoteport",
+        "remove",
+        "repluck",
+        "reshapearray",
+        "reson",
+        "resonk",
+        "resonr",
+        "resonx",
+        "resonxk",
+        "resony",
+        "resonz",
+        "resyn",
+        "reverb",
+        "reverb2",
+        "reverbsc",
+        "rewindscore",
+        "rezzy",
+        "rfft",
+        "rifft",
+        "rms",
+        "rnd",
+        "rnd31",
+        "round",
+        "rspline",
+        "rtclock",
+        "s16b14",
+        "s32b14",
+        "samphold",
+        "sandpaper",
+        "sc_lag",
+        "sc_lagud",
+        "sc_phasor",
+        "sc_trig",
+        "scale",
+        "scalearray",
+        "scanhammer",
+        "scans",
+        "scantable",
+        "scanu",
+        "schedkwhen",
+        "schedkwhennamed",
+        "schedule",
+        "schedwhen",
+        "scoreline",
+        "scoreline_i",
+        "seed",
+        "sekere",
+        "select",
+        "semitone",
+        "sense",
+        "sensekey",
+        "seqtime",
+        "seqtime2",
+        "serialBegin",
+        "serialEnd",
+        "serialFlush",
+        "serialPrint",
+        "serialRead",
+        "serialWrite",
+        "serialWrite_i",
+        "setcol",
+        "setctrl",
+        "setksmps",
+        "setrow",
+        "setscorepos",
+        "sfilist",
+        "sfinstr",
+        "sfinstr3",
+        "sfinstr3m",
+        "sfinstrm",
+        "sfload",
+        "sflooper",
+        "sfpassign",
+        "sfplay",
+        "sfplay3",
+        "sfplay3m",
+        "sfplaym",
+        "sfplist",
+        "sfpreset",
+        "shaker",
+        "shiftin",
+        "shiftout",
+        "signum",
+        "sin",
+        "sinh",
+        "sininv",
+        "sinsyn",
+        "sleighbells",
+        "slicearray",
+        "slicearray_i",
+        "slider16",
+        "slider16f",
+        "slider16table",
+        "slider16tablef",
+        "slider32",
+        "slider32f",
+        "slider32table",
+        "slider32tablef",
+        "slider64",
+        "slider64f",
+        "slider64table",
+        "slider64tablef",
+        "slider8",
+        "slider8f",
+        "slider8table",
+        "slider8tablef",
+        "sliderKawai",
+        "sndloop",
+        "sndwarp",
+        "sndwarpst",
+        "sockrecv",
+        "sockrecvs",
+        "socksend",
+        "socksends",
+        "sorta",
+        "sortd",
+        "soundin",
+        "space",
+        "spat3d",
+        "spat3di",
+        "spat3dt",
+        "spdist",
+        "splitrig",
+        "sprintf",
+        "sprintfk",
+        "spsend",
+        "sqrt",
+        "squinewave",
+        "statevar",
+        "stix",
+        "strcat",
+        "strcatk",
+        "strchar",
+        "strchark",
+        "strcmp",
+        "strcmpk",
+        "strcpy",
+        "strcpyk",
+        "strecv",
+        "streson",
+        "strfromurl",
+        "strget",
+        "strindex",
+        "strindexk",
+        "strlen",
+        "strlenk",
+        "strlower",
+        "strlowerk",
+        "strrindex",
+        "strrindexk",
+        "strset",
+        "strsub",
+        "strsubk",
+        "strtod",
+        "strtodk",
+        "strtol",
+        "strtolk",
+        "strupper",
+        "strupperk",
+        "stsend",
+        "subinstr",
+        "subinstrinit",
+        "sum",
+        "sumarray",
+        "svfilter",
+        "syncgrain",
+        "syncloop",
+        "syncphasor",
+        "system",
+        "system_i",
+        "tab",
+        "tab2array",
+        "tab2pvs",
+        "tab_i",
+        "tabifd",
+        "table",
+        "table3",
+        "table3kt",
+        "tablecopy",
+        "tablefilter",
+        "tablefilteri",
+        "tablegpw",
+        "tablei",
+        "tableicopy",
+        "tableigpw",
+        "tableikt",
+        "tableimix",
+        "tableiw",
+        "tablekt",
+        "tablemix",
+        "tableng",
+        "tablera",
+        "tableseg",
+        "tableshuffle",
+        "tableshufflei",
+        "tablew",
+        "tablewa",
+        "tablewkt",
+        "tablexkt",
+        "tablexseg",
+        "tabmorph",
+        "tabmorpha",
+        "tabmorphak",
+        "tabmorphi",
+        "tabplay",
+        "tabrec",
+        "tabrowlin",
+        "tabsum",
+        "tabw",
+        "tabw_i",
+        "tambourine",
+        "tan",
+        "tanh",
+        "taninv",
+        "taninv2",
+        "tbvcf",
+        "tempest",
+        "tempo",
+        "temposcal",
+        "tempoval",
+        "timedseq",
+        "timeinstk",
+        "timeinsts",
+        "timek",
+        "times",
+        "tival",
+        "tlineto",
+        "tone",
+        "tonek",
+        "tonex",
+        "tradsyn",
+        "trandom",
+        "transeg",
+        "transegb",
+        "transegr",
+        "trcross",
+        "trfilter",
+        "trhighest",
+        "trigger",
+        "trigseq",
+        "trim",
+        "trim_i",
+        "trirand",
+        "trlowest",
+        "trmix",
+        "trscale",
+        "trshift",
+        "trsplit",
+        "turnoff",
+        "turnoff2",
+        "turnon",
+        "tvconv",
+        "unirand",
+        "unwrap",
+        "upsamp",
+        "urandom",
+        "urd",
+        "vactrol",
+        "vadd",
+        "vadd_i",
+        "vaddv",
+        "vaddv_i",
+        "vaget",
+        "valpass",
+        "vaset",
+        "vbap",
+        "vbapg",
+        "vbapgmove",
+        "vbaplsinit",
+        "vbapmove",
+        "vbapz",
+        "vbapzmove",
+        "vcella",
+        "vco",
+        "vco2",
+        "vco2ft",
+        "vco2ift",
+        "vco2init",
+        "vcomb",
+        "vcopy",
+        "vcopy_i",
+        "vdel_k",
+        "vdelay",
+        "vdelay3",
+        "vdelayk",
+        "vdelayx",
+        "vdelayxq",
+        "vdelayxs",
+        "vdelayxw",
+        "vdelayxwq",
+        "vdelayxws",
+        "vdivv",
+        "vdivv_i",
+        "vecdelay",
+        "veloc",
+        "vexp",
+        "vexp_i",
+        "vexpseg",
+        "vexpv",
+        "vexpv_i",
+        "vibes",
+        "vibr",
+        "vibrato",
+        "vincr",
+        "vlimit",
+        "vlinseg",
+        "vlowres",
+        "vmap",
+        "vmirror",
+        "vmult",
+        "vmult_i",
+        "vmultv",
+        "vmultv_i",
+        "voice",
+        "vosim",
+        "vphaseseg",
+        "vport",
+        "vpow",
+        "vpow_i",
+        "vpowv",
+        "vpowv_i",
+        "vpvoc",
+        "vrandh",
+        "vrandi",
+        "vsubv",
+        "vsubv_i",
+        "vtaba",
+        "vtabi",
+        "vtabk",
+        "vtable1k",
+        "vtablea",
+        "vtablei",
+        "vtablek",
+        "vtablewa",
+        "vtablewi",
+        "vtablewk",
+        "vtabwa",
+        "vtabwi",
+        "vtabwk",
+        "vwrap",
+        "waveset",
+        "websocket",
+        "weibull",
+        "wgbow",
+        "wgbowedbar",
+        "wgbrass",
+        "wgclar",
+        "wgflute",
+        "wgpluck",
+        "wgpluck2",
+        "wguide1",
+        "wguide2",
+        "wiiconnect",
+        "wiidata",
+        "wiirange",
+        "wiisend",
+        "window",
+        "wrap",
+        "writescratch",
+        "wterrain",
+        "xadsr",
+        "xin",
+        "xout",
+        "xscanmap",
+        "xscans",
+        "xscansmap",
+        "xscanu",
+        "xtratim",
+        "xyscale",
+        "zacl",
+        "zakinit",
+        "zamod",
+        "zar",
+        "zarg",
+        "zaw",
+        "zawm",
+        "zdf_1pole",
+        "zdf_1pole_mode",
+        "zdf_2pole",
+        "zdf_2pole_mode",
+        "zdf_ladder",
+        "zfilter2",
+        "zir",
+        "ziw",
+        "ziwm",
+        "zkcl",
+        "zkmod",
+        "zkr",
+        "zkw",
+        "zkwm"
+    ];
+    var deprecatedOpcodes = [
+        "array",
+        "bformdec",
+        "bformenc",
+        "copy2ftab",
+        "copy2ttab",
+        "hrtfer",
+        "ktableseg",
+        "lentab",
+        "maxtab",
+        "mintab",
+        "pop",
+        "pop_f",
+        "push",
+        "push_f",
+        "scalet",
+        "sndload",
+        "soundout",
+        "soundouts",
+        "specaddm",
+        "specdiff",
+        "specdisp",
+        "specfilt",
+        "spechist",
+        "specptrk",
+        "specscal",
+        "specsum",
+        "spectrum",
+        "stack",
+        "sumtab",
+        "tabgen",
+        "tabmap",
+        "tabmap_i",
+        "tabslice",
+        "tb0",
+        "tb0_init",
+        "tb1",
+        "tb10",
+        "tb10_init",
+        "tb11",
+        "tb11_init",
+        "tb12",
+        "tb12_init",
+        "tb13",
+        "tb13_init",
+        "tb14",
+        "tb14_init",
+        "tb15",
+        "tb15_init",
+        "tb1_init",
+        "tb2",
+        "tb2_init",
+        "tb3",
+        "tb3_init",
+        "tb4",
+        "tb4_init",
+        "tb5",
+        "tb5_init",
+        "tb6",
+        "tb6_init",
+        "tb7",
+        "tb7_init",
+        "tb8",
+        "tb8_init",
+        "tb9",
+        "tb9_init",
+        "vbap16",
+        "vbap4",
+        "vbap4move",
+        "vbap8",
+        "vbap8move",
+        "xyin"
+    ];
+
+    opcodes = lang.arrayToMap(opcodes);
+    deprecatedOpcodes = lang.arrayToMap(deprecatedOpcodes);
+
+    this.lineContinuations = [
+        {
+            token : "constant.character.escape.line-continuation.csound",
+            regex : /\\$/
+        }, this.pushRule({
+            token : "constant.character.escape.line-continuation.csound",
+            regex : /\\/,
+            next  : "line continuation"
+        })
+    ];
+
+    this.comments.push(this.lineContinuations);
+
+    this.quotedStringContents.push(
+        this.lineContinuations,
+        {
+            token : "invalid.illegal",
+            regex : /[^"\\]*$/
+        }
+    );
+
+    var start = this.$rules.start;
+    start.splice(1, 0, {
+        token : ["text.csound", "entity.name.label.csound", "entity.punctuation.label.csound", "text.csound"],
+        regex : /^([ \t]*)(\w+)(:)([ \t]+|$)/
+    });
+    start.push(
+        this.pushRule({
+            token : "keyword.function.csound",
+            regex : /\binstr\b/,
+            next  : "instrument numbers and identifiers"
+        }), this.pushRule({
+            token : "keyword.function.csound",
+            regex : /\bopcode\b/,
+            next  : "after opcode keyword"
+        }), {
+            token : "keyword.other.csound",
+            regex : /\bend(?:in|op)\b/
+        },
+
+        {
+            token : "variable.language.csound",
+            regex : /\b(?:0dbfs|A4|k(?:r|smps)|nchnls(?:_i)?|sr)\b/
+        },
+
+        this.numbers,
+
+        {
+            token : "keyword.operator.csound",
+            regex : "\\+=|-=|\\*=|/=|<<|>>|<=|>=|==|!=|&&|\\|\\||[~¬]|[=!+\\-*/^%&|<>#?:]"
+        },
+
+        this.pushRule({
+            token : "punctuation.definition.string.begin.csound",
+            regex : /"/,
+            next  : "quoted string"
+        }), this.pushRule({
+            token : "punctuation.definition.string.begin.csound",
+            regex : /{{/,
+            next  : "braced string"
+        }),
+
+        {
+            token : "keyword.control.csound",
+            regex : /\b(?:do|else(?:if)?|end(?:if|until)|fi|i(?:f|then)|kthen|od|r(?:ir)?eturn|then|until|while)\b/
+        },
+
+        this.pushRule({
+            token : "keyword.control.csound",
+            regex : /\b[ik]?goto\b/,
+            next  : "goto before label"
+        }), this.pushRule({
+            token : "keyword.control.csound",
+            regex : /\b(?:r(?:einit|igoto)|tigoto)\b/,
+            next  : "goto before label"
+        }), this.pushRule({
+            token : "keyword.control.csound",
+            regex : /\bc(?:g|in?|k|nk?)goto\b/,
+            next  : ["goto before label", "goto before argument"]
+        }), this.pushRule({
+            token : "keyword.control.csound",
+            regex : /\btimout\b/,
+            next  : ["goto before label", "goto before argument", "goto before argument"]
+        }), this.pushRule({
+            token : "keyword.control.csound",
+            regex : /\bloop_[gl][et]\b/,
+            next  : ["goto before label", "goto before argument", "goto before argument", "goto before argument"]
+        }),
+
+        this.pushRule({
+            token : "support.function.csound",
+            regex : /\b(?:readscore|scoreline(?:_i)?)\b/,
+            next  : "Csound score opcode"
+        }), this.pushRule({
+            token : "support.function.csound",
+            regex : /\bpyl?run[it]?\b(?!$)/,
+            next  : "Python opcode"
+        }), this.pushRule({
+            token : "support.function.csound",
+            regex : /\blua_(?:exec|opdef)\b(?!$)/,
+            next  : "Lua opcode"
+        }),
+
+        {
+            token : "support.variable.csound",
+            regex : /\bp\d+\b/
+        }, {
+            regex : /\b([A-Z_a-z]\w*)(?:(:)([A-Za-z]))?\b/, onMatch: function(value, currentState, stack, line) {
+                var tokens = value.split(this.splitRegex);
+                var name = tokens[1];
+                var type;
+                if (opcodes.hasOwnProperty(name))
+                    type = "support.function.csound";
+                else if (deprecatedOpcodes.hasOwnProperty(name))
+                    type = "invalid.deprecated.csound";
+                if (type) {
+                    if (tokens[2]) {
+                        return [
+                            {type: type, value: name},
+                            {type: "punctuation.type-annotation.csound", value: tokens[2]},
+                            {type: "type-annotation.storage.type.csound", value: tokens[3]}
+                        ];
+                    }
+                    return type;
+                }
+                return "text.csound";
+            }
+        }
+    );
+
+    this.$rules["macro parameter value list"].splice(2, 0, {
+        token : "punctuation.definition.string.begin.csound",
+        regex : /{{/,
+        next  : "macro parameter value braced string"
+    });
+
+    this.addRules({
+        "macro parameter value braced string": [
+            {
+                token : "constant.character.escape.csound",
+                regex : /\\[#'()]/
+            }, {
+                token : "invalid.illegal.csound.csound",
+                regex : /[#'()]/
+            }, {
+                token : "punctuation.definition.string.end.csound",
+                regex : /}}/,
+                next  : "macro parameter value list"
+            }, {
+                defaultToken: "string.braced.csound"
+            }
+        ],
+
+        "instrument numbers and identifiers": [
+            this.comments,
+            {
+                token : "entity.name.function.csound",
+                regex : /\d+|[A-Z_a-z]\w*/
+            }, this.popRule({
+                token : "empty",
+                regex : /$/
+            })
+        ],
+
+        "after opcode keyword": [
+            this.comments,
+            this.popRule({
+                token : "empty",
+                regex : /$/
+            }), this.popRule({
+                token : "entity.name.function.opcode.csound",
+                regex : /[A-Z_a-z]\w*/,
+                next  : "opcode type signatures"
+            })
+        ],
+        "opcode type signatures": [
+            this.comments,
+            this.popRule({
+                token : "empty",
+                regex : /$/
+            }), {
+                token : "storage.type.csound",
+                regex : /\b(?:0|[afijkKoOpPStV\[\]]+)/
+            }
+        ],
+
+        "quoted string": [
+            this.popRule({
+                token : "punctuation.definition.string.end.csound",
+                regex : /"/
+            }),
+            this.quotedStringContents,
+            {
+                defaultToken: "string.quoted.csound"
+            }
+        ],
+        "braced string": [
+            this.popRule({
+                token : "punctuation.definition.string.end.csound",
+                regex : /}}/
+            }),
+            this.bracedStringContents,
+            {
+                defaultToken: "string.braced.csound"
+            }
+        ],
+
+        "goto before argument": [
+            this.popRule({
+                token : "text.csound",
+                regex : /,/
+            }),
+            start
+        ],
+        "goto before label": [
+            {
+                token : "text.csound",
+                regex : /\s+/
+            },
+            this.comments,
+            this.popRule({
+                token : "entity.name.label.csound",
+                regex : /\w+/
+            }), this.popRule({
+                token : "empty",
+                regex : /(?!\w)/
+            })
+        ],
+
+        "Csound score opcode": [
+            this.comments,
+            {
+                token : "punctuation.definition.string.begin.csound",
+                regex : /{{/,
+                next  : "csound-score-start"
+            }, this.popRule({
+                token : "empty",
+                regex : /$/
+            })
+        ],
+
+        "Python opcode": [
+            this.comments,
+            {
+                token : "punctuation.definition.string.begin.csound",
+                regex : /{{/,
+                next  : "python-start"
+            }, this.popRule({
+                token : "empty",
+                regex : /$/
+            })
+        ],
+
+        "Lua opcode": [
+            this.comments,
+            {
+                token : "punctuation.definition.string.begin.csound",
+                regex : /{{/,
+                next  : "lua-start"
+            }, this.popRule({
+                token : "empty",
+                regex : /$/
+            })
+        ],
+
+        "line continuation": [
+            this.popRule({
+                token : "empty",
+                regex : /$/
+            }),
+            this.semicolonComments,
+            {
+                token : "invalid.illegal.csound",
+                regex : /\S.*/
+            }
+        ]
+    });
+
+    var rules = [
+        this.popRule({
+            token : "punctuation.definition.string.end.csound",
+            regex : /}}/
+        })
+    ];
+    this.embedRules(CsoundScoreHighlightRules, "csound-score-", rules);
+    this.embedRules(PythonHighlightRules, "python-", rules);
+    this.embedRules(LuaHighlightRules, "lua-", rules);
+
+    this.normalizeRules();
+};
+
+oop.inherits(CsoundOrchestraHighlightRules, CsoundPreprocessorHighlightRules);
+
+exports.CsoundOrchestraHighlightRules = CsoundOrchestraHighlightRules;
+});
+
+ace.define("ace/mode/csound_orchestra",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var CsoundOrchestraHighlightRules = require("./csound_orchestra_highlight_rules").CsoundOrchestraHighlightRules;
+
+var Mode = function() {
+    this.HighlightRules = CsoundOrchestraHighlightRules;
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+
+    this.lineCommentStart = ";";
+    this.blockComment = {start: "/*", end: "*/"};
+
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/csound_orchestra"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 454 - 0
services/web/public/js/ace-1.4.3/mode-csound_score.js

@@ -0,0 +1,454 @@
+ace.define("ace/mode/csound_preprocessor_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var CsoundPreprocessorHighlightRules = function() {
+
+    this.semicolonComments = {
+        token : "comment.line.semicolon.csound",
+        regex : ";.*$"
+    };
+
+    this.comments = [
+        {
+            token : "punctuation.definition.comment.begin.csound",
+            regex : "/\\*",
+            push  : [
+                {
+                    token : "punctuation.definition.comment.end.csound",
+                    regex : "\\*/",
+                    next  : "pop"
+                }, {
+                    defaultToken: "comment.block.csound"
+                }
+            ]
+        }, {
+            token : "comment.line.double-slash.csound",
+            regex : "//.*$"
+        },
+        this.semicolonComments
+    ];
+
+    this.macroUses = [
+        {
+            token : ["entity.name.function.preprocessor.csound", "punctuation.definition.macro-parameter-value-list.begin.csound"],
+            regex : /(\$[A-Z_a-z]\w*\.?)(\()/,
+            next  : "macro parameter value list"
+        }, {
+            token : "entity.name.function.preprocessor.csound",
+            regex : /\$[A-Z_a-z]\w*(?:\.|\b)/
+        }
+    ];
+
+    this.numbers = [
+        {
+            token : "constant.numeric.float.csound",
+            regex : /(?:\d+[Ee][+-]?\d+)|(?:\d+\.\d*|\d*\.\d+)(?:[Ee][+-]?\d+)?/
+        }, {
+            token : ["storage.type.number.csound", "constant.numeric.integer.hexadecimal.csound"],
+            regex : /(0[Xx])([0-9A-Fa-f]+)/
+        }, {
+            token : "constant.numeric.integer.decimal.csound",
+            regex : /\d+/
+        }
+    ];
+
+    this.bracedStringContents = [
+        {
+            token : "constant.character.escape.csound",
+            regex : /\\(?:[\\abnrt"]|[0-7]{1,3})/
+        },
+        {
+            token : "constant.character.placeholder.csound",
+            regex : /%[#0\- +]*\d*(?:\.\d+)?[diuoxXfFeEgGaAcs]/
+        }, {
+            token : "constant.character.escape.csound",
+            regex : /%%/
+        }
+    ];
+
+    this.quotedStringContents = [
+        this.macroUses,
+        this.bracedStringContents
+    ];
+
+    var start = [
+        this.comments,
+
+        {
+            token : "keyword.preprocessor.csound",
+            regex : /#(?:e(?:nd(?:if)?|lse)\b|##)|@@?[ \t]*\d+/
+        }, {
+            token : "keyword.preprocessor.csound",
+            regex : /#include/,
+            push  : [
+                this.comments,
+                {
+                    token : "string.csound",
+                    regex : /([^ \t])(?:.*?\1)/,
+                    next  : "pop"
+                }
+            ]
+        }, {
+            token : "keyword.preprocessor.csound",
+            regex : /#[ \t]*define/,
+            next  : "define directive"
+        }, {
+            token : "keyword.preprocessor.csound",
+            regex : /#(?:ifn?def|undef)\b/,
+            next  : "macro directive"
+        },
+
+        this.macroUses
+    ];
+
+    this.$rules = {
+        "start": start,
+
+        "define directive": [
+            this.comments,
+            {
+                token : "entity.name.function.preprocessor.csound",
+                regex : /[A-Z_a-z]\w*/
+            }, {
+                token : "punctuation.definition.macro-parameter-name-list.begin.csound",
+                regex : /\(/,
+                next  : "macro parameter name list"
+            }, {
+                token : "punctuation.definition.macro.begin.csound",
+                regex : /#/,
+                next  : "macro body"
+            }
+        ],
+        "macro parameter name list": [
+            {
+                token : "variable.parameter.preprocessor.csound",
+                regex : /[A-Z_a-z]\w*/
+            }, {
+                token : "punctuation.definition.macro-parameter-name-list.end.csound",
+                regex : /\)/,
+                next  : "define directive"
+            }
+        ],
+        "macro body": [
+            {
+                token : "constant.character.escape.csound",
+                regex : /\\#/
+            }, {
+                token : "punctuation.definition.macro.end.csound",
+                regex : /#/,
+                next  : "start"
+            },
+            start
+        ],
+
+        "macro directive": [
+            this.comments,
+            {
+                token : "entity.name.function.preprocessor.csound",
+                regex : /[A-Z_a-z]\w*/,
+                next  : "start"
+            }
+        ],
+
+        "macro parameter value list": [
+            {
+                token : "punctuation.definition.macro-parameter-value-list.end.csound",
+                regex : /\)/,
+                next  : "start"
+            }, {
+                token : "punctuation.definition.string.begin.csound",
+                regex : /"/,
+                next  : "macro parameter value quoted string"
+            }, this.pushRule({
+                token : "punctuation.macro-parameter-value-parenthetical.begin.csound",
+                regex : /\(/,
+                next  : "macro parameter value parenthetical"
+            }), {
+                token : "punctuation.macro-parameter-value-separator.csound",
+                regex : "[#']"
+            }
+        ],
+        "macro parameter value quoted string": [
+            {
+                token : "constant.character.escape.csound",
+                regex : /\\[#'()]/
+            }, {
+                token : "invalid.illegal.csound",
+                regex : /[#'()]/
+            }, {
+                token : "punctuation.definition.string.end.csound",
+                regex : /"/,
+                next  : "macro parameter value list"
+            },
+            this.quotedStringContents,
+            {
+                defaultToken: "string.quoted.csound"
+            }
+        ],
+        "macro parameter value parenthetical": [
+            {
+                token : "constant.character.escape.csound",
+                regex : /\\\)/
+            }, this.popRule({
+                token : "punctuation.macro-parameter-value-parenthetical.end.csound",
+                regex : /\)/
+            }), this.pushRule({
+                token : "punctuation.macro-parameter-value-parenthetical.begin.csound",
+                regex : /\(/,
+                next  : "macro parameter value parenthetical"
+            }),
+            start
+        ]
+    };
+};
+
+oop.inherits(CsoundPreprocessorHighlightRules, TextHighlightRules);
+
+(function() {
+
+    this.pushRule = function(params) {
+        return {
+            regex : params.regex, onMatch: function(value, currentState, stack, line) {
+                if (stack.length === 0)
+                    stack.push(currentState);
+                if (Array.isArray(params.next)) {
+                    for (var i = 0; i < params.next.length; i++) {
+                        stack.push(params.next[i]);
+                    }
+                } else {
+                    stack.push(params.next);
+                }
+                this.next = stack[stack.length - 1];
+                return params.token;
+            },
+            get next() { return Array.isArray(params.next) ? params.next[params.next.length - 1] : params.next; },
+            set next(next) {
+                if (Array.isArray(params.next)) {
+                    var oldNext = params.next[params.next.length - 1];
+                    var oldNextIndex = oldNext.length - 1;
+                    var newNextIndex = next.length - 1;
+                    if (newNextIndex > oldNextIndex) {
+                        while (oldNextIndex >= 0 && newNextIndex >= 0) {
+                            if (oldNext.charAt(oldNextIndex) !== next.charAt(newNextIndex)) {
+                                var prefix = next.substr(0, newNextIndex);
+                                for (var i = 0; i < params.next.length; i++) {
+                                    params.next[i] = prefix + params.next[i];
+                                }
+                                break;
+                            }
+                            oldNextIndex--;
+                            newNextIndex--;
+                        }
+                    }
+                } else {
+                    params.next = next;
+                }
+            },
+            get token() { return params.token; }
+        };
+    };
+
+    this.popRule = function(params) {
+        return {
+            regex : params.regex, onMatch: function(value, currentState, stack, line) {
+                stack.pop();
+                if (params.next) {
+                    stack.push(params.next);
+                    this.next = stack[stack.length - 1];
+                } else {
+                    this.next = stack.length > 1 ? stack[stack.length - 1] : stack.pop();
+                }
+                return params.token;
+            }
+        };
+    };
+
+}).call(CsoundPreprocessorHighlightRules.prototype);
+
+exports.CsoundPreprocessorHighlightRules = CsoundPreprocessorHighlightRules;
+});
+
+ace.define("ace/mode/csound_score_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+
+var CsoundPreprocessorHighlightRules = require("./csound_preprocessor_highlight_rules").CsoundPreprocessorHighlightRules;
+
+var CsoundScoreHighlightRules = function() {
+
+    CsoundPreprocessorHighlightRules.call(this);
+
+    this.quotedStringContents.push({
+        token : "invalid.illegal.csound-score",
+        regex : /[^"]*$/
+    });
+
+    var start = this.$rules.start;
+    start.push(
+        {
+            token : "keyword.control.csound-score",
+            regex : /[abCdefiqstvxy]/
+        }, {
+            token : "invalid.illegal.csound-score",
+            regex : /w/
+        }, {
+            token : "constant.numeric.language.csound-score",
+            regex : /z/
+        }, {
+            token : ["keyword.control.csound-score", "constant.numeric.integer.decimal.csound-score"],
+            regex : /([nNpP][pP])(\d+)/
+        }, {
+            token : "keyword.other.csound-score",
+            regex : /[mn]/,
+            push  : [
+                {
+                    token : "empty",
+                    regex : /$/,
+                    next  : "pop"
+                },
+                this.comments,
+                {
+                    token : "entity.name.label.csound-score",
+                    regex : /[A-Z_a-z]\w*/
+                }
+            ]
+        }, {
+            token : "keyword.preprocessor.csound-score",
+            regex : /r\b/,
+            next  : "repeat section"
+        },
+
+        this.numbers,
+
+        {
+            token : "keyword.operator.csound-score",
+            regex : "[!+\\-*/^%&|<>#~.]"
+        },
+
+        this.pushRule({
+            token : "punctuation.definition.string.begin.csound-score",
+            regex : /"/,
+            next  : "quoted string"
+        }),
+
+        this.pushRule({
+            token : "punctuation.braced-loop.begin.csound-score",
+            regex : /{/,
+            next  : "loop after left brace"
+        })
+    );
+
+    this.addRules({
+        "repeat section": [
+            {
+                token : "empty",
+                regex : /$/,
+                next  : "start"
+            },
+            this.comments,
+            {
+                token : "constant.numeric.integer.decimal.csound-score",
+                regex : /\d+/,
+                next  : "repeat section before label"
+            }
+        ],
+        "repeat section before label": [
+            {
+                token : "empty",
+                regex : /$/,
+                next  : "start"
+            },
+            this.comments,
+            {
+                token : "entity.name.label.csound-score",
+                regex : /[A-Z_a-z]\w*/,
+                next  : "start"
+            }
+        ],
+
+        "quoted string": [
+            this.popRule({
+                token : "punctuation.definition.string.end.csound-score",
+                regex : /"/
+            }),
+            this.quotedStringContents,
+            {
+                defaultToken: "string.quoted.csound-score"
+            }
+        ],
+
+        "loop after left brace": [
+            this.popRule({
+                token : "constant.numeric.integer.decimal.csound-score",
+                regex : /\d+/,
+                next  : "loop after repeat count"
+            }),
+            this.comments,
+            {
+                token : "invalid.illegal.csound",
+                regex : /\S.*/
+            }
+        ],
+        "loop after repeat count": [
+            this.popRule({
+                token : "entity.name.function.preprocessor.csound-score",
+                regex : /[A-Z_a-z]\w*\b/,
+                next  : "loop after macro name"
+            }),
+            this.comments,
+            {
+                token : "invalid.illegal.csound",
+                regex : /\S.*/
+            }
+        ],
+        "loop after macro name": [
+            start,
+            this.popRule({
+                token : "punctuation.braced-loop.end.csound-score",
+                regex : /}/
+            })
+        ]
+    });
+
+    this.normalizeRules();
+};
+
+oop.inherits(CsoundScoreHighlightRules, CsoundPreprocessorHighlightRules);
+
+exports.CsoundScoreHighlightRules = CsoundScoreHighlightRules;
+});
+
+ace.define("ace/mode/csound_score",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var CsoundScoreHighlightRules = require("./csound_score_highlight_rules").CsoundScoreHighlightRules;
+
+var Mode = function() {
+    this.HighlightRules = CsoundScoreHighlightRules;
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+
+    this.lineCommentStart = ";";
+    this.blockComment = {start: "/*", end: "*/"};
+
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/csound_score"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 60 - 0
services/web/public/js/ace-1.4.3/mode-csp.js

@@ -0,0 +1,60 @@
+ace.define("ace/mode/csp_highlight_rules",[], function(require, exports, module) {
+    "use strict";
+
+    var oop = require("../lib/oop");
+    var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+    var CspHighlightRules = function() {
+        var keywordMapper = this.createKeywordMapper({
+            "constant.language": "child-src|connect-src|default-src|font-src|frame-src|img-src|manifest-src|media-src|object-src"
+                  + "|script-src|style-src|worker-src|base-uri|plugin-types|sandbox|disown-opener|form-action|frame-ancestors|report-uri"
+                  + "|report-to|upgrade-insecure-requests|block-all-mixed-content|require-sri-for|reflected-xss|referrer|policy-uri",
+            "variable": "'none'|'self'|'unsafe-inline'|'unsafe-eval'|'strict-dynamic'|'unsafe-hashed-attributes'"
+        }, "identifier", true);
+
+        this.$rules = {
+            start: [{
+                token: "string.link",
+                regex: /https?:[^;\s]*/
+            }, {
+                token: "operator.punctuation",
+                regex: /;/
+            }, {
+                token: keywordMapper,
+                regex: /[^\s;]+/
+            }]
+        };
+    };
+
+    oop.inherits(CspHighlightRules, TextHighlightRules);
+
+    exports.CspHighlightRules = CspHighlightRules;
+});
+
+ace.define("ace/mode/csp",[], function(require, exports, module) {
+    "use strict";
+
+    var TextMode = require("./text").Mode;
+    var CspHighlightRules = require("./csp_highlight_rules").CspHighlightRules;
+    var oop = require("../lib/oop");
+
+    var Mode = function() {
+        this.HighlightRules = CspHighlightRules;
+    };
+
+    oop.inherits(Mode, TextMode);
+
+    (function() {
+        this.$id = "ace/mode/csp";
+    }).call(Mode.prototype);
+
+    exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/csp"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

Fișier diff suprimat deoarece este prea mare
+ 6 - 0
services/web/public/js/ace-1.4.3/mode-css.js


Fișier diff suprimat deoarece este prea mare
+ 797 - 0
services/web/public/js/ace-1.4.3/mode-curly.js


+ 521 - 0
services/web/public/js/ace-1.4.3/mode-d.js

@@ -0,0 +1,521 @@
+ace.define("ace/mode/doc_comment_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var DocCommentHighlightRules = function() {
+    this.$rules = {
+        "start" : [ {
+            token : "comment.doc.tag",
+            regex : "@[\\w\\d_]+" // TODO: fix email addresses
+        }, 
+        DocCommentHighlightRules.getTagRule(),
+        {
+            defaultToken : "comment.doc",
+            caseInsensitive: true
+        }]
+    };
+};
+
+oop.inherits(DocCommentHighlightRules, TextHighlightRules);
+
+DocCommentHighlightRules.getTagRule = function(start) {
+    return {
+        token : "comment.doc.tag.storage.type",
+        regex : "\\b(?:TODO|FIXME|XXX|HACK)\\b"
+    };
+};
+
+DocCommentHighlightRules.getStartRule = function(start) {
+    return {
+        token : "comment.doc", // doc comment
+        regex : "\\/\\*(?=\\*)",
+        next  : start
+    };
+};
+
+DocCommentHighlightRules.getEndRule = function (start) {
+    return {
+        token : "comment.doc", // closing comment
+        regex : "\\*\\/",
+        next  : start
+    };
+};
+
+
+exports.DocCommentHighlightRules = DocCommentHighlightRules;
+
+});
+
+ace.define("ace/mode/d_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var DocCommentHighlightRules = require("./doc_comment_highlight_rules").DocCommentHighlightRules;
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var DHighlightRules = function() {
+
+    var keywords = (
+        "this|super|import|module|body|mixin|__traits|invariant|alias|asm|delete|"+
+        "typeof|typeid|sizeof|cast|new|in|is|typedef|__vector|__parameters"
+    );
+
+    var keywordControls = (
+        "break|case|continue|default|do|else|for|foreach|foreach_reverse|goto|if|" +
+        "return|switch|while|catch|try|throw|finally|version|assert|unittest|with"
+    );
+    
+    var types = (
+        "auto|bool|char|dchar|wchar|byte|ubyte|float|double|real|" +
+        "cfloat|creal|cdouble|cent|ifloat|ireal|idouble|" +
+        "int|long|short|void|uint|ulong|ushort|ucent|" +
+        "function|delegate|string|wstring|dstring|size_t|ptrdiff_t|hash_t|Object"
+    );
+
+    var modifiers = (
+        "abstract|align|debug|deprecated|export|extern|const|final|in|inout|out|" +
+        "ref|immutable|lazy|nothrow|override|package|pragma|private|protected|" +
+        "public|pure|scope|shared|__gshared|synchronized|static|volatile"
+    );
+    
+    var storages = (
+        "class|struct|union|template|interface|enum|macro"
+    );
+    
+    var stringEscapesSeq =  {
+        token: "constant.language.escape",
+        regex: "\\\\(?:(?:x[0-9A-F]{2})|(?:[0-7]{1,3})|(?:['\"\\?0abfnrtv\\\\])|" +
+            "(?:u[0-9a-fA-F]{4})|(?:U[0-9a-fA-F]{8}))"
+    };
+
+    var builtinConstants = (
+        "null|true|false|"+
+        "__DATE__|__EOF__|__TIME__|__TIMESTAMP__|__VENDOR__|__VERSION__|"+
+        "__FILE__|__MODULE__|__LINE__|__FUNCTION__|__PRETTY_FUNCTION__"
+    );
+    
+    var operators = (
+        "/|/\\=|&|&\\=|&&|\\|\\|\\=|\\|\\||\\-|\\-\\=|\\-\\-|\\+|" +
+        "\\+\\=|\\+\\+|\\<|\\<\\=|\\<\\<|\\<\\<\\=|\\<\\>|\\<\\>\\=|\\>|\\>\\=|\\>\\>\\=|" +
+        "\\>\\>\\>\\=|\\>\\>|\\>\\>\\>|\\!|\\!\\=|\\!\\<\\>|\\!\\<\\>\\=|\\!\\<|\\!\\<\\=|" +
+        "\\!\\>|\\!\\>\\=|\\?|\\$|\\=|\\=\\=|\\*|\\*\\=|%|%\\=|" +
+        "\\^|\\^\\=|\\^\\^|\\^\\^\\=|~|~\\=|\\=\\>|#"
+    );
+
+    var keywordMapper = this.$keywords = this.createKeywordMapper({
+        "keyword.modifier" : modifiers,
+        "keyword.control" :  keywordControls,
+        "keyword.type" :     types,
+        "keyword":           keywords,
+        "keyword.storage":   storages,
+        "punctation": "\\.|\\,|;|\\.\\.|\\.\\.\\.",
+        "keyword.operator" : operators,
+        "constant.language": builtinConstants
+    }, "identifier");
+    
+    var identifierRe = "[a-zA-Z_\u00a1-\uffff][a-zA-Z\\d_\u00a1-\uffff]*\\b";
+
+    this.$rules = {
+        "start" : [
+            {     //-------------------------------------------------------- COMMENTS
+                token : "comment",
+                regex : "\\/\\/.*$"
+            },
+            DocCommentHighlightRules.getStartRule("doc-start"),
+            {
+                token : "comment", // multi line comment
+                regex : "\\/\\*",
+                next : "star-comment"
+            }, {
+                token: "comment.shebang",
+                regex: "^\\s*#!.*"
+            }, {
+                token : "comment",
+                regex : "\\/\\+",
+                next: "plus-comment"
+            }, {  //-------------------------------------------------------- STRINGS
+                onMatch: function(value, currentState, state) {
+                    state.unshift(this.next, value.substr(2));
+                    return "string";
+                },
+                regex: 'q"(?:[\\[\\(\\{\\<]+)',
+                next: 'operator-heredoc-string'
+            }, {
+                onMatch: function(value, currentState, state) {
+                    state.unshift(this.next, value.substr(2));
+                    return "string";
+                },
+                regex: 'q"(?:[a-zA-Z_]+)$',
+                next: 'identifier-heredoc-string'
+            }, {
+                token : "string", // multi line string start
+                regex : '[xr]?"',
+                next : "quote-string"
+            }, {
+                token : "string", // multi line string start
+                regex : '[xr]?`',
+                next : "backtick-string"
+            }, {
+                token : "string", // single line
+                regex : "[xr]?['](?:(?:\\\\.)|(?:[^'\\\\]))*?['][cdw]?"
+            }, {  //-------------------------------------------------------- RULES
+                token: ["keyword", "text", "paren.lparen"],
+                regex: /(asm)(\s*)({)/,
+                next: "d-asm"
+            }, {
+                token: ["keyword", "text", "paren.lparen", "constant.language"],
+                regex: "(__traits)(\\s*)(\\()("+identifierRe+")"
+            }, { // import|module abc
+                token: ["keyword", "text", "variable.module"],
+                regex: "(import|module)(\\s+)((?:"+identifierRe+"\\.?)*)"
+            }, { // storage Name
+                token: ["keyword.storage", "text", "entity.name.type"],
+                regex: "("+storages+")(\\s*)("+identifierRe+")"
+            }, { // alias|typedef foo bar;
+                token: ["keyword", "text", "variable.storage", "text"],
+                regex: "(alias|typedef)(\\s*)("+identifierRe+")(\\s*)"
+            }, {  //-------------------------------------------------------- OTHERS
+                token : "constant.numeric", // hex
+                regex : "0[xX][0-9a-fA-F_]+(l|ul|u|f|F|L|U|UL)?\\b"
+            }, {
+                token : "constant.numeric", // float
+                regex : "[+-]?\\d[\\d_]*(?:(?:\\.[\\d_]*)?(?:[eE][+-]?[\\d_]+)?)?(l|ul|u|f|F|L|U|UL)?\\b"
+            }, {
+                token: "entity.other.attribute-name",
+                regex: "@"+identifierRe
+            }, {
+                token : keywordMapper,
+                regex : "[a-zA-Z_][a-zA-Z0-9_]*\\b"
+            }, {
+                token : "keyword.operator",
+                regex : operators
+            }, {
+                token : "punctuation.operator",
+                regex : "\\?|\\:|\\,|\\;|\\.|\\:"
+            }, {
+                token : "paren.lparen",
+                regex : "[[({]"
+            }, {
+                token : "paren.rparen",
+                regex : "[\\])}]"
+            }, {
+                token : "text",
+                regex : "\\s+"
+            }
+        ],
+        "star-comment" : [
+            {
+                token : "comment", // closing comment
+                regex : "\\*\\/",
+                next : "start"
+            }, {
+                defaultToken: 'comment'
+            }
+        ],
+        "plus-comment" : [
+            {
+                token : "comment", // closing comment
+                regex : "\\+\\/",
+                next : "start"
+            }, {
+                defaultToken: 'comment'
+            }
+        ],
+        
+        "quote-string" : [
+           stringEscapesSeq,
+           {
+                token : "string",
+                regex : '"[cdw]?',
+                next : "start"
+            }, {
+                defaultToken: 'string'
+            }
+        ],
+        
+        "backtick-string" : [
+           stringEscapesSeq,
+           {
+                token : "string",
+                regex : '`[cdw]?',
+                next : "start"
+            }, {
+                defaultToken: 'string'
+            }
+        ],
+        
+        "operator-heredoc-string": [
+            {
+                onMatch: function(value, currentState, state) {
+                    value = value.substring(value.length-2, value.length-1);
+                    var map = {'>':'<',']':'[',')':'(','}':'{'};
+                    if(Object.keys(map).indexOf(value) != -1)
+                        value = map[value];
+                    if(value != state[1]) return "string";
+                    state.shift();
+                    state.shift();
+                    
+                    return "string";
+                },
+                regex: '(?:[\\]\\)}>]+)"',
+                next: 'start'
+            }, {
+                token: 'string',
+                regex: '[^\\]\\)}>]+'
+            }
+        ],
+        
+        "identifier-heredoc-string": [
+            {
+                onMatch: function(value, currentState, state) {
+                    value = value.substring(0, value.length-1);
+                    if(value != state[1]) return "string";
+                    state.shift();
+                    state.shift();
+                    
+                    return "string";
+                },
+                regex: '^(?:[A-Za-z_][a-zA-Z0-9]+)"',
+                next: 'start'
+            }, {
+                token: 'string',
+                regex: '[^\\]\\)}>]+'
+            }
+        ],
+        
+        "d-asm": [
+            {
+                token: "paren.rparen",
+                regex: "\\}",
+                next: "start"
+            }, {
+                token: 'keyword.instruction',
+                regex: '[a-zA-Z]+',
+                next: 'd-asm-instruction' 
+            }, {
+                token: "text",
+                regex: "\\s+"
+            }
+        ],
+        'd-asm-instruction': [
+            {
+                token: 'constant.language',
+                regex: /AL|AH|AX|EAX|BL|BH|BX|EBX|CL|CH|CX|ECX|DL|DH|DX|EDX|BP|EBP|SP|ESP|DI|EDI|SI|ESI/i
+            }, {
+                token: 'identifier',
+                regex: '[a-zA-Z]+'
+            }, {
+                token: 'string',
+                regex: '".*"'
+            }, {
+                token: 'comment',
+                regex: '//.*$'
+            }, {
+                token: 'constant.numeric',
+                regex: '[0-9.xA-F]+'
+            }, {
+                token: 'punctuation.operator',
+                regex: '\\,'
+            }, {
+                token: 'punctuation.operator',
+                regex: ';',
+                next: 'd-asm'
+            }, {
+                token: 'text',
+                regex: '\\s+'
+            }
+        ]
+    };
+
+    this.embedRules(DocCommentHighlightRules, "doc-",
+        [ DocCommentHighlightRules.getEndRule("start") ]);
+};
+
+DHighlightRules.metaData = {
+      comment: 'D language',
+      fileTypes: [ 'd', 'di' ],
+      firstLineMatch: '^#!.*\\b[glr]?dmd\\b.',
+      foldingStartMarker: '(?x)/\\*\\*(?!\\*)|^(?![^{]*?//|[^{]*?/\\*(?!.*?\\*/.*?\\{)).*?\\{\\s*($|//|/\\*(?!.*?\\*/.*\\S))',
+      foldingStopMarker: '(?<!\\*)\\*\\*/|^\\s*\\}',
+      keyEquivalent: '^~D',
+      name: 'D',
+      scopeName: 'source.d'
+};
+oop.inherits(DHighlightRules, TextHighlightRules);
+
+exports.DHighlightRules = DHighlightRules;
+});
+
+ace.define("ace/mode/folding/cstyle",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Range = require("../../range").Range;
+var BaseFoldMode = require("./fold_mode").FoldMode;
+
+var FoldMode = exports.FoldMode = function(commentRegex) {
+    if (commentRegex) {
+        this.foldingStartMarker = new RegExp(
+            this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start)
+        );
+        this.foldingStopMarker = new RegExp(
+            this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end)
+        );
+    }
+};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+    
+    this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/;
+    this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/;
+    this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/;
+    this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/;
+    this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/;
+    this._getFoldWidgetBase = this.getFoldWidget;
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+    
+        if (this.singleLineBlockCommentRe.test(line)) {
+            if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line))
+                return "";
+        }
+    
+        var fw = this._getFoldWidgetBase(session, foldStyle, row);
+    
+        if (!fw && this.startRegionRe.test(line))
+            return "start"; // lineCommentRegionStart
+    
+        return fw;
+    };
+
+    this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) {
+        var line = session.getLine(row);
+        
+        if (this.startRegionRe.test(line))
+            return this.getCommentRegionBlock(session, line, row);
+        
+        var match = line.match(this.foldingStartMarker);
+        if (match) {
+            var i = match.index;
+
+            if (match[1])
+                return this.openingBracketBlock(session, match[1], row, i);
+                
+            var range = session.getCommentFoldRange(row, i + match[0].length, 1);
+            
+            if (range && !range.isMultiLine()) {
+                if (forceMultiline) {
+                    range = this.getSectionRange(session, row);
+                } else if (foldStyle != "all")
+                    range = null;
+            }
+            
+            return range;
+        }
+
+        if (foldStyle === "markbegin")
+            return;
+
+        var match = line.match(this.foldingStopMarker);
+        if (match) {
+            var i = match.index + match[0].length;
+
+            if (match[1])
+                return this.closingBracketBlock(session, match[1], row, i);
+
+            return session.getCommentFoldRange(row, i, -1);
+        }
+    };
+    
+    this.getSectionRange = function(session, row) {
+        var line = session.getLine(row);
+        var startIndent = line.search(/\S/);
+        var startRow = row;
+        var startColumn = line.length;
+        row = row + 1;
+        var endRow = row;
+        var maxRow = session.getLength();
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var indent = line.search(/\S/);
+            if (indent === -1)
+                continue;
+            if  (startIndent > indent)
+                break;
+            var subRange = this.getFoldWidgetRange(session, "all", row);
+            
+            if (subRange) {
+                if (subRange.start.row <= startRow) {
+                    break;
+                } else if (subRange.isMultiLine()) {
+                    row = subRange.end.row;
+                } else if (startIndent == indent) {
+                    break;
+                }
+            }
+            endRow = row;
+        }
+        
+        return new Range(startRow, startColumn, endRow, session.getLine(endRow).length);
+    };
+    this.getCommentRegionBlock = function(session, line, row) {
+        var startColumn = line.search(/\s*$/);
+        var maxRow = session.getLength();
+        var startRow = row;
+        
+        var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/;
+        var depth = 1;
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var m = re.exec(line);
+            if (!m) continue;
+            if (m[1]) depth--;
+            else depth++;
+
+            if (!depth) break;
+        }
+
+        var endRow = row;
+        if (endRow > startRow) {
+            return new Range(startRow, startColumn, endRow, line.length);
+        }
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/d",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var DHighlightRules = require("./d_highlight_rules").DHighlightRules;
+var FoldMode = require("./folding/cstyle").FoldMode;
+
+var Mode = function() {
+    this.HighlightRules = DHighlightRules;
+    this.foldingRules = new FoldMode();
+    this.$behaviour = this.$defaultBehaviour;
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+    this.lineCommentStart = "//";
+    this.blockComment = {start: "/*", end: "*/"};
+    this.$id = "ace/mode/d";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/d"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

Fișier diff suprimat deoarece este prea mare
+ 56 - 0
services/web/public/js/ace-1.4.3/mode-dart.js


+ 147 - 0
services/web/public/js/ace-1.4.3/mode-diff.js

@@ -0,0 +1,147 @@
+ace.define("ace/mode/diff_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var DiffHighlightRules = function() {
+
+    this.$rules = {
+        "start" : [{
+                regex: "^(?:\\*{15}|={67}|-{3}|\\+{3})$",
+                token: "punctuation.definition.separator.diff",
+                "name": "keyword"
+            }, { //diff.range.unified
+                regex: "^(@@)(\\s*.+?\\s*)(@@)(.*)$",
+                token: [
+                    "constant",
+                    "constant.numeric",
+                    "constant",
+                    "comment.doc.tag"
+                ]
+            }, { //diff.range.normal
+                regex: "^(\\d+)([,\\d]+)(a|d|c)(\\d+)([,\\d]+)(.*)$",
+                token: [
+                    "constant.numeric",
+                    "punctuation.definition.range.diff",
+                    "constant.function",
+                    "constant.numeric",
+                    "punctuation.definition.range.diff",
+                    "invalid"
+                ],
+                "name": "meta."
+            }, {
+                regex: "^(\\-{3}|\\+{3}|\\*{3})( .+)$",
+                token: [
+                    "constant.numeric",
+                    "meta.tag"
+                ]
+            }, { // added
+                regex: "^([!+>])(.*?)(\\s*)$",
+                token: [
+                    "support.constant",
+                    "text",
+                    "invalid"
+                ]
+            }, { // removed
+                regex: "^([<\\-])(.*?)(\\s*)$",
+                token: [
+                    "support.function",
+                    "string",
+                    "invalid"
+                ]
+            }, {
+                regex: "^(diff)(\\s+--\\w+)?(.+?)( .+)?$",
+                token: ["variable", "variable", "keyword", "variable"]
+            }, {
+                regex: "^Index.+$",
+                token: "variable"
+            }, {
+                regex: "^\\s+$",
+                token: "text"
+            }, {
+                regex: "\\s*$",
+                token: "invalid"
+            }, {
+                defaultToken: "invisible",
+                caseInsensitive: true
+            }
+        ]
+    };
+};
+
+oop.inherits(DiffHighlightRules, TextHighlightRules);
+
+exports.DiffHighlightRules = DiffHighlightRules;
+});
+
+ace.define("ace/mode/folding/diff",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var BaseFoldMode = require("./fold_mode").FoldMode;
+var Range = require("../../range").Range;
+
+var FoldMode = exports.FoldMode = function(levels, flag) {
+	this.regExpList = levels;
+	this.flag = flag;
+	this.foldingStartMarker = RegExp("^(" + levels.join("|") + ")", this.flag);
+};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+    this.getFoldWidgetRange = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+        var start = {row: row, column: line.length};
+
+        var regList = this.regExpList;
+        for (var i = 1; i <= regList.length; i++) {
+            var re = RegExp("^(" + regList.slice(0, i).join("|") + ")", this.flag);
+            if (re.test(line))
+                break;
+        }
+
+        for (var l = session.getLength(); ++row < l; ) {
+            line = session.getLine(row);
+            if (re.test(line))
+                break;
+        }
+        if (row == start.row + 1)
+            return;
+        return new Range(start.row, start.column, row - 1, line.length);
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/diff",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var HighlightRules = require("./diff_highlight_rules").DiffHighlightRules;
+var FoldMode = require("./folding/diff").FoldMode;
+
+var Mode = function() {
+    this.HighlightRules = HighlightRules;
+    this.foldingRules = new FoldMode(["diff", "@@|\\*{5}"], "i");
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+
+    this.$id = "ace/mode/diff";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+
+});
+                (function() {
+                    ace.require(["ace/mode/diff"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

Fișier diff suprimat deoarece este prea mare
+ 797 - 0
services/web/public/js/ace-1.4.3/mode-django.js


+ 500 - 0
services/web/public/js/ace-1.4.3/mode-dockerfile.js

@@ -0,0 +1,500 @@
+ace.define("ace/mode/sh_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var reservedKeywords = exports.reservedKeywords = (
+        '!|{|}|case|do|done|elif|else|'+
+        'esac|fi|for|if|in|then|until|while|'+
+        '&|;|export|local|read|typeset|unset|'+
+        'elif|select|set|function|declare|readonly'
+    );
+
+var languageConstructs = exports.languageConstructs = (
+    '[|]|alias|bg|bind|break|builtin|'+
+     'cd|command|compgen|complete|continue|'+
+     'dirs|disown|echo|enable|eval|exec|'+
+     'exit|fc|fg|getopts|hash|help|history|'+
+     'jobs|kill|let|logout|popd|printf|pushd|'+
+     'pwd|return|set|shift|shopt|source|'+
+     'suspend|test|times|trap|type|ulimit|'+
+     'umask|unalias|wait'
+);
+
+var ShHighlightRules = function() {
+    var keywordMapper = this.createKeywordMapper({
+        "keyword": reservedKeywords,
+        "support.function.builtin": languageConstructs,
+        "invalid.deprecated": "debugger"
+    }, "identifier");
+
+    var integer = "(?:(?:[1-9]\\d*)|(?:0))";
+
+    var fraction = "(?:\\.\\d+)";
+    var intPart = "(?:\\d+)";
+    var pointFloat = "(?:(?:" + intPart + "?" + fraction + ")|(?:" + intPart + "\\.))";
+    var exponentFloat = "(?:(?:" + pointFloat + "|" +  intPart + ")" + ")";
+    var floatNumber = "(?:" + exponentFloat + "|" + pointFloat + ")";
+    var fileDescriptor = "(?:&" + intPart + ")";
+
+    var variableName = "[a-zA-Z_][a-zA-Z0-9_]*";
+    var variable = "(?:" + variableName + "(?==))";
+
+    var builtinVariable = "(?:\\$(?:SHLVL|\\$|\\!|\\?))";
+
+    var func = "(?:" + variableName + "\\s*\\(\\))";
+
+    this.$rules = {
+        "start" : [{
+            token : "constant",
+            regex : /\\./
+        }, {
+            token : ["text", "comment"],
+            regex : /(^|\s)(#.*)$/
+        }, {
+            token : "string.start",
+            regex : '"',
+            push : [{
+                token : "constant.language.escape",
+                regex : /\\(?:[$`"\\]|$)/
+            }, {
+                include : "variables"
+            }, {
+                token : "keyword.operator",
+                regex : /`/ // TODO highlight `
+            }, {
+                token : "string.end",
+                regex : '"',
+                next: "pop"
+            }, {
+                defaultToken: "string"
+            }]
+        }, {
+            token : "string",
+            regex : "\\$'",
+            push : [{
+                token : "constant.language.escape",
+                regex : /\\(?:[abeEfnrtv\\'"]|x[a-fA-F\d]{1,2}|u[a-fA-F\d]{4}([a-fA-F\d]{4})?|c.|\d{1,3})/
+            }, {
+                token : "string",
+                regex : "'",
+                next: "pop"
+            }, {
+                defaultToken: "string"
+            }]
+        }, {
+            regex : "<<<",
+            token : "keyword.operator"
+        }, {
+            stateName: "heredoc",
+            regex : "(<<-?)(\\s*)(['\"`]?)([\\w\\-]+)(['\"`]?)",
+            onMatch : function(value, currentState, stack) {
+                var next = value[2] == '-' ? "indentedHeredoc" : "heredoc";
+                var tokens = value.split(this.splitRegex);
+                stack.push(next, tokens[4]);
+                return [
+                    {type:"constant", value: tokens[1]},
+                    {type:"text", value: tokens[2]},
+                    {type:"string", value: tokens[3]},
+                    {type:"support.class", value: tokens[4]},
+                    {type:"string", value: tokens[5]}
+                ];
+            },
+            rules: {
+                heredoc: [{
+                    onMatch:  function(value, currentState, stack) {
+                        if (value === stack[1]) {
+                            stack.shift();
+                            stack.shift();
+                            this.next = stack[0] || "start";
+                            return "support.class";
+                        }
+                        this.next = "";
+                        return "string";
+                    },
+                    regex: ".*$",
+                    next: "start"
+                }],
+                indentedHeredoc: [{
+                    token: "string",
+                    regex: "^\t+"
+                }, {
+                    onMatch:  function(value, currentState, stack) {
+                        if (value === stack[1]) {
+                            stack.shift();
+                            stack.shift();
+                            this.next = stack[0] || "start";
+                            return "support.class";
+                        }
+                        this.next = "";
+                        return "string";
+                    },
+                    regex: ".*$",
+                    next: "start"
+                }]
+            }
+        }, {
+            regex : "$",
+            token : "empty",
+            next : function(currentState, stack) {
+                if (stack[0] === "heredoc" || stack[0] === "indentedHeredoc")
+                    return stack[0];
+                return currentState;
+            }
+        }, {
+            token : ["keyword", "text", "text", "text", "variable"],
+            regex : /(declare|local|readonly)(\s+)(?:(-[fixar]+)(\s+))?([a-zA-Z_][a-zA-Z0-9_]*\b)/
+        }, {
+            token : "variable.language",
+            regex : builtinVariable
+        }, {
+            token : "variable",
+            regex : variable
+        }, {
+            include : "variables"
+        }, {
+            token : "support.function",
+            regex : func
+        }, {
+            token : "support.function",
+            regex : fileDescriptor
+        }, {
+            token : "string",           // ' string
+            start : "'", end : "'"
+        }, {
+            token : "constant.numeric", // float
+            regex : floatNumber
+        }, {
+            token : "constant.numeric", // integer
+            regex : integer + "\\b"
+        }, {
+            token : keywordMapper,
+            regex : "[a-zA-Z_][a-zA-Z0-9_]*\\b"
+        }, {
+            token : "keyword.operator",
+            regex : "\\+|\\-|\\*|\\*\\*|\\/|\\/\\/|~|<|>|<=|=>|=|!=|[%&|`]"
+        }, {
+            token : "punctuation.operator",
+            regex : ";"
+        }, {
+            token : "paren.lparen",
+            regex : "[\\[\\(\\{]"
+        }, {
+            token : "paren.rparen",
+            regex : "[\\]]"
+        }, {
+            token : "paren.rparen",
+            regex : "[\\)\\}]",
+            next : "pop"
+        }],
+        variables: [{
+            token : "variable",
+            regex : /(\$)(\w+)/
+        }, {
+            token : ["variable", "paren.lparen"],
+            regex : /(\$)(\()/,
+            push : "start"
+        }, {
+            token : ["variable", "paren.lparen", "keyword.operator", "variable", "keyword.operator"],
+            regex : /(\$)(\{)([#!]?)(\w+|[*@#?\-$!0_])(:[?+\-=]?|##?|%%?|,,?\/|\^\^?)?/,
+            push : "start"
+        }, {
+            token : "variable",
+            regex : /\$[*@#?\-$!0_]/
+        }, {
+            token : ["variable", "paren.lparen"],
+            regex : /(\$)(\{)/,
+            push : "start"
+        }]
+    };
+    
+    this.normalizeRules();
+};
+
+oop.inherits(ShHighlightRules, TextHighlightRules);
+
+exports.ShHighlightRules = ShHighlightRules;
+});
+
+ace.define("ace/mode/folding/cstyle",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Range = require("../../range").Range;
+var BaseFoldMode = require("./fold_mode").FoldMode;
+
+var FoldMode = exports.FoldMode = function(commentRegex) {
+    if (commentRegex) {
+        this.foldingStartMarker = new RegExp(
+            this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start)
+        );
+        this.foldingStopMarker = new RegExp(
+            this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end)
+        );
+    }
+};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+    
+    this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/;
+    this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/;
+    this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/;
+    this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/;
+    this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/;
+    this._getFoldWidgetBase = this.getFoldWidget;
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+    
+        if (this.singleLineBlockCommentRe.test(line)) {
+            if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line))
+                return "";
+        }
+    
+        var fw = this._getFoldWidgetBase(session, foldStyle, row);
+    
+        if (!fw && this.startRegionRe.test(line))
+            return "start"; // lineCommentRegionStart
+    
+        return fw;
+    };
+
+    this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) {
+        var line = session.getLine(row);
+        
+        if (this.startRegionRe.test(line))
+            return this.getCommentRegionBlock(session, line, row);
+        
+        var match = line.match(this.foldingStartMarker);
+        if (match) {
+            var i = match.index;
+
+            if (match[1])
+                return this.openingBracketBlock(session, match[1], row, i);
+                
+            var range = session.getCommentFoldRange(row, i + match[0].length, 1);
+            
+            if (range && !range.isMultiLine()) {
+                if (forceMultiline) {
+                    range = this.getSectionRange(session, row);
+                } else if (foldStyle != "all")
+                    range = null;
+            }
+            
+            return range;
+        }
+
+        if (foldStyle === "markbegin")
+            return;
+
+        var match = line.match(this.foldingStopMarker);
+        if (match) {
+            var i = match.index + match[0].length;
+
+            if (match[1])
+                return this.closingBracketBlock(session, match[1], row, i);
+
+            return session.getCommentFoldRange(row, i, -1);
+        }
+    };
+    
+    this.getSectionRange = function(session, row) {
+        var line = session.getLine(row);
+        var startIndent = line.search(/\S/);
+        var startRow = row;
+        var startColumn = line.length;
+        row = row + 1;
+        var endRow = row;
+        var maxRow = session.getLength();
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var indent = line.search(/\S/);
+            if (indent === -1)
+                continue;
+            if  (startIndent > indent)
+                break;
+            var subRange = this.getFoldWidgetRange(session, "all", row);
+            
+            if (subRange) {
+                if (subRange.start.row <= startRow) {
+                    break;
+                } else if (subRange.isMultiLine()) {
+                    row = subRange.end.row;
+                } else if (startIndent == indent) {
+                    break;
+                }
+            }
+            endRow = row;
+        }
+        
+        return new Range(startRow, startColumn, endRow, session.getLine(endRow).length);
+    };
+    this.getCommentRegionBlock = function(session, line, row) {
+        var startColumn = line.search(/\s*$/);
+        var maxRow = session.getLength();
+        var startRow = row;
+        
+        var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/;
+        var depth = 1;
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var m = re.exec(line);
+            if (!m) continue;
+            if (m[1]) depth--;
+            else depth++;
+
+            if (!depth) break;
+        }
+
+        var endRow = row;
+        if (endRow > startRow) {
+            return new Range(startRow, startColumn, endRow, line.length);
+        }
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/sh",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var ShHighlightRules = require("./sh_highlight_rules").ShHighlightRules;
+var Range = require("../range").Range;
+var CStyleFoldMode = require("./folding/cstyle").FoldMode;
+var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour;
+
+var Mode = function() {
+    this.HighlightRules = ShHighlightRules;
+    this.foldingRules = new CStyleFoldMode();
+    this.$behaviour = new CstyleBehaviour();
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+
+   
+    this.lineCommentStart = "#";
+
+    this.getNextLineIndent = function(state, line, tab) {
+        var indent = this.$getIndent(line);
+
+        var tokenizedLine = this.getTokenizer().getLineTokens(line, state);
+        var tokens = tokenizedLine.tokens;
+
+        if (tokens.length && tokens[tokens.length-1].type == "comment") {
+            return indent;
+        }
+
+        if (state == "start") {
+            var match = line.match(/^.*[\{\(\[:]\s*$/);
+            if (match) {
+                indent += tab;
+            }
+        }
+
+        return indent;
+    };
+
+    var outdents = {
+        "pass": 1,
+        "return": 1,
+        "raise": 1,
+        "break": 1,
+        "continue": 1
+    };
+
+    this.checkOutdent = function(state, line, input) {
+        if (input !== "\r\n" && input !== "\r" && input !== "\n")
+            return false;
+
+        var tokens = this.getTokenizer().getLineTokens(line.trim(), state).tokens;
+
+        if (!tokens)
+            return false;
+        do {
+            var last = tokens.pop();
+        } while (last && (last.type == "comment" || (last.type == "text" && last.value.match(/^\s+$/))));
+
+        if (!last)
+            return false;
+
+        return (last.type == "keyword" && outdents[last.value]);
+    };
+
+    this.autoOutdent = function(state, doc, row) {
+
+        row += 1;
+        var indent = this.$getIndent(doc.getLine(row));
+        var tab = doc.getTabString();
+        if (indent.slice(-tab.length) == tab)
+            doc.remove(new Range(row, indent.length-tab.length, row, indent.length));
+    };
+
+    this.$id = "ace/mode/sh";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+
+ace.define("ace/mode/dockerfile_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var ShHighlightRules = require("./sh_highlight_rules").ShHighlightRules;
+
+var DockerfileHighlightRules = function() {
+    ShHighlightRules.call(this);
+
+    var startRules = this.$rules.start;
+    for (var i = 0; i < startRules.length; i++) {
+        if (startRules[i].token == "variable.language") {
+            startRules.splice(i, 0, {
+                token: "constant.language",
+                regex: "(?:^(?:FROM|MAINTAINER|RUN|CMD|EXPOSE|ENV|ADD|ENTRYPOINT|VOLUME|USER|WORKDIR|ONBUILD|COPY|LABEL)\\b)",
+                caseInsensitive: true
+            });
+            break;
+        }
+    }
+    
+};
+
+oop.inherits(DockerfileHighlightRules, ShHighlightRules);
+
+exports.DockerfileHighlightRules = DockerfileHighlightRules;
+});
+
+ace.define("ace/mode/dockerfile",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var ShMode = require("./sh").Mode;
+var DockerfileHighlightRules = require("./dockerfile_highlight_rules").DockerfileHighlightRules;
+var CStyleFoldMode = require("./folding/cstyle").FoldMode;
+
+var Mode = function() {
+    ShMode.call(this);
+    
+    this.HighlightRules = DockerfileHighlightRules;
+    this.foldingRules = new CStyleFoldMode();
+};
+oop.inherits(Mode, ShMode);
+
+(function() {
+    this.$id = "ace/mode/dockerfile";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/dockerfile"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 418 - 0
services/web/public/js/ace-1.4.3/mode-dot.js

@@ -0,0 +1,418 @@
+ace.define("ace/mode/matching_brace_outdent",[], function(require, exports, module) {
+"use strict";
+
+var Range = require("../range").Range;
+
+var MatchingBraceOutdent = function() {};
+
+(function() {
+
+    this.checkOutdent = function(line, input) {
+        if (! /^\s+$/.test(line))
+            return false;
+
+        return /^\s*\}/.test(input);
+    };
+
+    this.autoOutdent = function(doc, row) {
+        var line = doc.getLine(row);
+        var match = line.match(/^(\s*\})/);
+
+        if (!match) return 0;
+
+        var column = match[1].length;
+        var openBracePos = doc.findMatchingBracket({row: row, column: column});
+
+        if (!openBracePos || openBracePos.row == row) return 0;
+
+        var indent = this.$getIndent(doc.getLine(openBracePos.row));
+        doc.replace(new Range(row, 0, row, column-1), indent);
+    };
+
+    this.$getIndent = function(line) {
+        return line.match(/^\s*/)[0];
+    };
+
+}).call(MatchingBraceOutdent.prototype);
+
+exports.MatchingBraceOutdent = MatchingBraceOutdent;
+});
+
+ace.define("ace/mode/doc_comment_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var DocCommentHighlightRules = function() {
+    this.$rules = {
+        "start" : [ {
+            token : "comment.doc.tag",
+            regex : "@[\\w\\d_]+" // TODO: fix email addresses
+        }, 
+        DocCommentHighlightRules.getTagRule(),
+        {
+            defaultToken : "comment.doc",
+            caseInsensitive: true
+        }]
+    };
+};
+
+oop.inherits(DocCommentHighlightRules, TextHighlightRules);
+
+DocCommentHighlightRules.getTagRule = function(start) {
+    return {
+        token : "comment.doc.tag.storage.type",
+        regex : "\\b(?:TODO|FIXME|XXX|HACK)\\b"
+    };
+};
+
+DocCommentHighlightRules.getStartRule = function(start) {
+    return {
+        token : "comment.doc", // doc comment
+        regex : "\\/\\*(?=\\*)",
+        next  : start
+    };
+};
+
+DocCommentHighlightRules.getEndRule = function (start) {
+    return {
+        token : "comment.doc", // closing comment
+        regex : "\\*\\/",
+        next  : start
+    };
+};
+
+
+exports.DocCommentHighlightRules = DocCommentHighlightRules;
+
+});
+
+ace.define("ace/mode/dot_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var lang = require("../lib/lang");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+var DocCommentHighlightRules = require("./doc_comment_highlight_rules").DocCommentHighlightRules;
+
+var DotHighlightRules = function() {
+
+   var keywords = lang.arrayToMap(
+        ("strict|node|edge|graph|digraph|subgraph").split("|")
+   );
+
+   var attributes = lang.arrayToMap(
+        ("damping|k|url|area|arrowhead|arrowsize|arrowtail|aspect|bb|bgcolor|center|charset|clusterrank|color|colorscheme|comment|compound|concentrate|constraint|decorate|defaultdist|dim|dimen|dir|diredgeconstraints|distortion|dpi|edgeurl|edgehref|edgetarget|edgetooltip|epsilon|esep|fillcolor|fixedsize|fontcolor|fontname|fontnames|fontpath|fontsize|forcelabels|gradientangle|group|headurl|head_lp|headclip|headhref|headlabel|headport|headtarget|headtooltip|height|href|id|image|imagepath|imagescale|label|labelurl|label_scheme|labelangle|labeldistance|labelfloat|labelfontcolor|labelfontname|labelfontsize|labelhref|labeljust|labelloc|labeltarget|labeltooltip|landscape|layer|layerlistsep|layers|layerselect|layersep|layout|len|levels|levelsgap|lhead|lheight|lp|ltail|lwidth|margin|maxiter|mclimit|mindist|minlen|mode|model|mosek|nodesep|nojustify|normalize|nslimit|nslimit1|ordering|orientation|outputorder|overlap|overlap_scaling|pack|packmode|pad|page|pagedir|pencolor|penwidth|peripheries|pin|pos|quadtree|quantum|rank|rankdir|ranksep|ratio|rects|regular|remincross|repulsiveforce|resolution|root|rotate|rotation|samehead|sametail|samplepoints|scale|searchsize|sep|shape|shapefile|showboxes|sides|size|skew|smoothing|sortv|splines|start|style|stylesheet|tailurl|tail_lp|tailclip|tailhref|taillabel|tailport|tailtarget|tailtooltip|target|tooltip|truecolor|vertices|viewport|voro_margin|weight|width|xlabel|xlp|z").split("|")
+   );
+
+   this.$rules = {
+        "start" : [
+            {
+                token : "comment",
+                regex : /\/\/.*$/
+            }, {
+                token : "comment",
+                regex : /#.*$/
+            }, {
+                token : "comment", // multi line comment
+                merge : true,
+                regex : /\/\*/,
+                next : "comment"
+            }, {
+                token : "string",
+                regex : "'(?=.)",
+                next  : "qstring"
+            }, {
+                token : "string",
+                regex : '"(?=.)',
+                next  : "qqstring"
+            }, {
+                token : "constant.numeric",
+                regex : /[+\-]?\d+(?:(?:\.\d*)?(?:[eE][+\-]?\d+)?)?\b/
+            }, {
+                token : "keyword.operator",
+                regex : /\+|=|\->/
+            }, {
+                token : "punctuation.operator",
+                regex : /,|;/
+            }, {
+                token : "paren.lparen",
+                regex : /[\[{]/
+            }, {
+                token : "paren.rparen",
+                regex : /[\]}]/
+            }, {
+                token: "comment",
+                regex: /^#!.*$/
+            }, {
+                token: function(value) {
+                    if (keywords.hasOwnProperty(value.toLowerCase())) {
+                        return "keyword";
+                    }
+                    else if (attributes.hasOwnProperty(value.toLowerCase())) {
+                        return "variable";
+                    }
+                    else {
+                        return "text";
+                    }
+                },
+                regex: "\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*"
+           }
+        ],
+        "comment" : [
+            {
+                token : "comment", // closing comment
+                regex : "\\*\\/",
+                next : "start"
+            }, {
+                defaultToken : "comment"
+            }
+        ],
+        "qqstring" : [
+            {
+                token : "string",
+                regex : '[^"\\\\]+',
+                merge : true
+            }, {
+                token : "string",
+                regex : "\\\\$",
+                next  : "qqstring",
+                merge : true
+            }, {
+                token : "string",
+                regex : '"|$',
+                next  : "start",
+                merge : true
+            }
+        ],
+        "qstring" : [
+            {
+                token : "string",
+                regex : "[^'\\\\]+",
+                merge : true
+            }, {
+                token : "string",
+                regex : "\\\\$",
+                next  : "qstring",
+                merge : true
+            }, {
+                token : "string",
+                regex : "'|$",
+                next  : "start",
+                merge : true
+            }
+        ]
+   };
+};
+
+oop.inherits(DotHighlightRules, TextHighlightRules);
+
+exports.DotHighlightRules = DotHighlightRules;
+
+});
+
+ace.define("ace/mode/folding/cstyle",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Range = require("../../range").Range;
+var BaseFoldMode = require("./fold_mode").FoldMode;
+
+var FoldMode = exports.FoldMode = function(commentRegex) {
+    if (commentRegex) {
+        this.foldingStartMarker = new RegExp(
+            this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start)
+        );
+        this.foldingStopMarker = new RegExp(
+            this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end)
+        );
+    }
+};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+    
+    this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/;
+    this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/;
+    this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/;
+    this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/;
+    this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/;
+    this._getFoldWidgetBase = this.getFoldWidget;
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+    
+        if (this.singleLineBlockCommentRe.test(line)) {
+            if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line))
+                return "";
+        }
+    
+        var fw = this._getFoldWidgetBase(session, foldStyle, row);
+    
+        if (!fw && this.startRegionRe.test(line))
+            return "start"; // lineCommentRegionStart
+    
+        return fw;
+    };
+
+    this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) {
+        var line = session.getLine(row);
+        
+        if (this.startRegionRe.test(line))
+            return this.getCommentRegionBlock(session, line, row);
+        
+        var match = line.match(this.foldingStartMarker);
+        if (match) {
+            var i = match.index;
+
+            if (match[1])
+                return this.openingBracketBlock(session, match[1], row, i);
+                
+            var range = session.getCommentFoldRange(row, i + match[0].length, 1);
+            
+            if (range && !range.isMultiLine()) {
+                if (forceMultiline) {
+                    range = this.getSectionRange(session, row);
+                } else if (foldStyle != "all")
+                    range = null;
+            }
+            
+            return range;
+        }
+
+        if (foldStyle === "markbegin")
+            return;
+
+        var match = line.match(this.foldingStopMarker);
+        if (match) {
+            var i = match.index + match[0].length;
+
+            if (match[1])
+                return this.closingBracketBlock(session, match[1], row, i);
+
+            return session.getCommentFoldRange(row, i, -1);
+        }
+    };
+    
+    this.getSectionRange = function(session, row) {
+        var line = session.getLine(row);
+        var startIndent = line.search(/\S/);
+        var startRow = row;
+        var startColumn = line.length;
+        row = row + 1;
+        var endRow = row;
+        var maxRow = session.getLength();
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var indent = line.search(/\S/);
+            if (indent === -1)
+                continue;
+            if  (startIndent > indent)
+                break;
+            var subRange = this.getFoldWidgetRange(session, "all", row);
+            
+            if (subRange) {
+                if (subRange.start.row <= startRow) {
+                    break;
+                } else if (subRange.isMultiLine()) {
+                    row = subRange.end.row;
+                } else if (startIndent == indent) {
+                    break;
+                }
+            }
+            endRow = row;
+        }
+        
+        return new Range(startRow, startColumn, endRow, session.getLine(endRow).length);
+    };
+    this.getCommentRegionBlock = function(session, line, row) {
+        var startColumn = line.search(/\s*$/);
+        var maxRow = session.getLength();
+        var startRow = row;
+        
+        var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/;
+        var depth = 1;
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var m = re.exec(line);
+            if (!m) continue;
+            if (m[1]) depth--;
+            else depth++;
+
+            if (!depth) break;
+        }
+
+        var endRow = row;
+        if (endRow > startRow) {
+            return new Range(startRow, startColumn, endRow, line.length);
+        }
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/dot",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent;
+var DotHighlightRules = require("./dot_highlight_rules").DotHighlightRules;
+var DotFoldMode = require("./folding/cstyle").FoldMode;
+
+var Mode = function() {
+    this.HighlightRules = DotHighlightRules;
+    this.$outdent = new MatchingBraceOutdent();
+    this.foldingRules = new DotFoldMode();
+    this.$behaviour = this.$defaultBehaviour;
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+
+    this.lineCommentStart = ["//", "#"];
+    this.blockComment = {start: "/*", end: "*/"};
+
+    this.getNextLineIndent = function(state, line, tab) {
+        var indent = this.$getIndent(line);
+
+        var tokenizedLine = this.getTokenizer().getLineTokens(line, state);
+        var tokens = tokenizedLine.tokens;
+        var endState = tokenizedLine.state;
+
+        if (tokens.length && tokens[tokens.length-1].type == "comment") {
+            return indent;
+        }
+
+        if (state == "start") {
+            var match = line.match(/^.*(?:\bcase\b.*:|[\{\(\[])\s*$/);
+            if (match) {
+                indent += tab;
+            }
+        }
+
+        return indent;
+    };
+
+    this.checkOutdent = function(state, line, input) {
+        return this.$outdent.checkOutdent(line, input);
+    };
+
+    this.autoOutdent = function(state, doc, row) {
+        this.$outdent.autoOutdent(doc, row);
+    };
+
+    this.$id = "ace/mode/dot";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/dot"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 498 - 0
services/web/public/js/ace-1.4.3/mode-drools.js

@@ -0,0 +1,498 @@
+ace.define("ace/mode/doc_comment_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var DocCommentHighlightRules = function() {
+    this.$rules = {
+        "start" : [ {
+            token : "comment.doc.tag",
+            regex : "@[\\w\\d_]+" // TODO: fix email addresses
+        }, 
+        DocCommentHighlightRules.getTagRule(),
+        {
+            defaultToken : "comment.doc",
+            caseInsensitive: true
+        }]
+    };
+};
+
+oop.inherits(DocCommentHighlightRules, TextHighlightRules);
+
+DocCommentHighlightRules.getTagRule = function(start) {
+    return {
+        token : "comment.doc.tag.storage.type",
+        regex : "\\b(?:TODO|FIXME|XXX|HACK)\\b"
+    };
+};
+
+DocCommentHighlightRules.getStartRule = function(start) {
+    return {
+        token : "comment.doc", // doc comment
+        regex : "\\/\\*(?=\\*)",
+        next  : start
+    };
+};
+
+DocCommentHighlightRules.getEndRule = function (start) {
+    return {
+        token : "comment.doc", // closing comment
+        regex : "\\*\\/",
+        next  : start
+    };
+};
+
+
+exports.DocCommentHighlightRules = DocCommentHighlightRules;
+
+});
+
+ace.define("ace/mode/java_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var DocCommentHighlightRules = require("./doc_comment_highlight_rules").DocCommentHighlightRules;
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var JavaHighlightRules = function() {
+    var keywords = (
+    "abstract|continue|for|new|switch|" +
+    "assert|default|goto|package|synchronized|" +
+    "boolean|do|if|private|this|" +
+    "break|double|implements|protected|throw|" +
+    "byte|else|import|public|throws|" +
+    "case|enum|instanceof|return|transient|" +
+    "catch|extends|int|short|try|" +
+    "char|final|interface|static|void|" +
+    "class|finally|long|strictfp|volatile|" +
+    "const|float|native|super|while|" +
+    "var"
+    );
+
+    var buildinConstants = ("null|Infinity|NaN|undefined");
+
+
+    var langClasses = (
+        "AbstractMethodError|AssertionError|ClassCircularityError|"+
+        "ClassFormatError|Deprecated|EnumConstantNotPresentException|"+
+        "ExceptionInInitializerError|IllegalAccessError|"+
+        "IllegalThreadStateException|InstantiationError|InternalError|"+
+        "NegativeArraySizeException|NoSuchFieldError|Override|Process|"+
+        "ProcessBuilder|SecurityManager|StringIndexOutOfBoundsException|"+
+        "SuppressWarnings|TypeNotPresentException|UnknownError|"+
+        "UnsatisfiedLinkError|UnsupportedClassVersionError|VerifyError|"+
+        "InstantiationException|IndexOutOfBoundsException|"+
+        "ArrayIndexOutOfBoundsException|CloneNotSupportedException|"+
+        "NoSuchFieldException|IllegalArgumentException|NumberFormatException|"+
+        "SecurityException|Void|InheritableThreadLocal|IllegalStateException|"+
+        "InterruptedException|NoSuchMethodException|IllegalAccessException|"+
+        "UnsupportedOperationException|Enum|StrictMath|Package|Compiler|"+
+        "Readable|Runtime|StringBuilder|Math|IncompatibleClassChangeError|"+
+        "NoSuchMethodError|ThreadLocal|RuntimePermission|ArithmeticException|"+
+        "NullPointerException|Long|Integer|Short|Byte|Double|Number|Float|"+
+        "Character|Boolean|StackTraceElement|Appendable|StringBuffer|"+
+        "Iterable|ThreadGroup|Runnable|Thread|IllegalMonitorStateException|"+
+        "StackOverflowError|OutOfMemoryError|VirtualMachineError|"+
+        "ArrayStoreException|ClassCastException|LinkageError|"+
+        "NoClassDefFoundError|ClassNotFoundException|RuntimeException|"+
+        "Exception|ThreadDeath|Error|Throwable|System|ClassLoader|"+
+        "Cloneable|Class|CharSequence|Comparable|String|Object"
+    );
+
+    var keywordMapper = this.createKeywordMapper({
+        "variable.language": "this",
+        "keyword": keywords,
+        "constant.language": buildinConstants,
+        "support.function": langClasses
+    }, "identifier");
+
+    this.$rules = {
+        "start" : [
+            {
+                token : "comment",
+                regex : "\\/\\/.*$"
+            },
+            DocCommentHighlightRules.getStartRule("doc-start"),
+            {
+                token : "comment", // multi line comment
+                regex : "\\/\\*",
+                next : "comment"
+            }, {
+                token : "string", // single line
+                regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
+            }, {
+                token : "string", // single line
+                regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
+            }, {
+                token : "constant.numeric", // hex
+                regex : /0(?:[xX][0-9a-fA-F][0-9a-fA-F_]*|[bB][01][01_]*)[LlSsDdFfYy]?\b/
+            }, {
+                token : "constant.numeric", // float
+                regex : /[+-]?\d[\d_]*(?:(?:\.[\d_]*)?(?:[eE][+-]?[\d_]+)?)?[LlSsDdFfYy]?\b/
+            }, {
+                token : "constant.language.boolean",
+                regex : "(?:true|false)\\b"
+            }, {
+                regex: "(open(?:\\s+))?module(?=\\s*\\w)",
+                token: "keyword",
+                next: [{
+                    regex: "{",
+                    token: "paren.lparen",
+                    next: [{
+                        regex: "}",
+                        token: "paren.rparen",
+                        next: "start"
+                    }, {
+                        regex: "\\b(requires|transitive|exports|opens|to|uses|provides|with)\\b",
+                        token: "keyword" 
+                    }]
+                }, {
+                    token : "text",
+                    regex : "\\s+"
+                }, {
+                    token : "identifier",
+                    regex : "\\w+"
+                }, {
+                    token : "punctuation.operator",
+                    regex : "."
+                }, {
+                    token : "text",
+                    regex : "\\s+"
+                }, {
+                    regex: "", // exit if there is anything else
+                    next: "start"
+                }]
+            }, {
+                token : keywordMapper,
+                regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
+            }, {
+                token : "keyword.operator",
+                regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"
+            }, {
+                token : "lparen",
+                regex : "[[({]"
+            }, {
+                token : "rparen",
+                regex : "[\\])}]"
+            }, {
+                token : "text",
+                regex : "\\s+"
+            }
+        ],
+        "comment" : [
+            {
+                token : "comment", // closing comment
+                regex : "\\*\\/",
+                next : "start"
+            }, {
+                defaultToken : "comment"
+            }
+        ]
+    };
+
+    
+    this.embedRules(DocCommentHighlightRules, "doc-",
+        [ DocCommentHighlightRules.getEndRule("start") ]);
+    this.normalizeRules();
+};
+
+oop.inherits(JavaHighlightRules, TextHighlightRules);
+
+exports.JavaHighlightRules = JavaHighlightRules;
+});
+
+ace.define("ace/mode/drools_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+var JavaHighlightRules = require("./java_highlight_rules").JavaHighlightRules;
+var DocCommentHighlightRules = require("./doc_comment_highlight_rules").DocCommentHighlightRules;
+
+var identifierRe = "[a-zA-Z\\$_\u00a1-\uffff][a-zA-Z\\d\\$_\u00a1-\uffff]*";
+var packageIdentifierRe = "[a-zA-Z\\$_\u00a1-\uffff][\\.a-zA-Z\\d\\$_\u00a1-\uffff]*";
+
+var DroolsHighlightRules = function() {
+
+    var keywords = ("date|effective|expires|lock|on|active|no|loop|auto|focus" +
+        "|activation|group|agenda|ruleflow|duration|timer|calendars|refract|direct" +
+        "|dialect|salience|enabled|attributes|extends|template" +
+        "|function|contains|matches|eval|excludes|soundslike" +
+        "|memberof|not|in|or|and|exists|forall|over|from|entry|point|accumulate|acc|collect" +
+        "|action|reverse|result|end|init|instanceof|extends|super|boolean|char|byte|short" +
+        "|int|long|float|double|this|void|class|new|case|final|if|else|for|while|do" +
+        "|default|try|catch|finally|switch|synchronized|return|throw|break|continue|assert" +
+        "|modify|static|public|protected|private|abstract|native|transient|volatile" +
+        "|strictfp|throws|interface|enum|implements|type|window|trait|no-loop|str"
+      );
+
+      var langClasses = (
+          "AbstractMethodError|AssertionError|ClassCircularityError|"+
+          "ClassFormatError|Deprecated|EnumConstantNotPresentException|"+
+          "ExceptionInInitializerError|IllegalAccessError|"+
+          "IllegalThreadStateException|InstantiationError|InternalError|"+
+          "NegativeArraySizeException|NoSuchFieldError|Override|Process|"+
+          "ProcessBuilder|SecurityManager|StringIndexOutOfBoundsException|"+
+          "SuppressWarnings|TypeNotPresentException|UnknownError|"+
+          "UnsatisfiedLinkError|UnsupportedClassVersionError|VerifyError|"+
+          "InstantiationException|IndexOutOfBoundsException|"+
+          "ArrayIndexOutOfBoundsException|CloneNotSupportedException|"+
+          "NoSuchFieldException|IllegalArgumentException|NumberFormatException|"+
+          "SecurityException|Void|InheritableThreadLocal|IllegalStateException|"+
+          "InterruptedException|NoSuchMethodException|IllegalAccessException|"+
+          "UnsupportedOperationException|Enum|StrictMath|Package|Compiler|"+
+          "Readable|Runtime|StringBuilder|Math|IncompatibleClassChangeError|"+
+          "NoSuchMethodError|ThreadLocal|RuntimePermission|ArithmeticException|"+
+          "NullPointerException|Long|Integer|Short|Byte|Double|Number|Float|"+
+          "Character|Boolean|StackTraceElement|Appendable|StringBuffer|"+
+          "Iterable|ThreadGroup|Runnable|Thread|IllegalMonitorStateException|"+
+          "StackOverflowError|OutOfMemoryError|VirtualMachineError|"+
+          "ArrayStoreException|ClassCastException|LinkageError|"+
+          "NoClassDefFoundError|ClassNotFoundException|RuntimeException|"+
+          "Exception|ThreadDeath|Error|Throwable|System|ClassLoader|"+
+          "Cloneable|Class|CharSequence|Comparable|String|Object"
+      );
+
+    var keywordMapper = this.createKeywordMapper({
+        "variable.language": "this",
+        "keyword": keywords,
+        "constant.language": "null",
+        "support.class" : langClasses,
+        "support.function" : "retract|update|modify|insert"
+    }, "identifier");
+
+    var stringRules = function() {
+      return [{
+        token : "string", // single line
+        regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
+      }, {
+        token : "string", // single line
+        regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
+      }];
+    };
+
+
+      var basicPreRules = function(blockCommentRules) {
+        return [{
+            token : "comment",
+            regex : "\\/\\/.*$"
+        },
+        DocCommentHighlightRules.getStartRule("doc-start"),
+        {
+            token : "comment", // multi line comment
+            regex : "\\/\\*",
+            next : blockCommentRules
+        }, {
+            token : "constant.numeric", // hex
+            regex : "0[xX][0-9a-fA-F]+\\b"
+        }, {
+            token : "constant.numeric", // float
+            regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
+        }, {
+            token : "constant.language.boolean",
+            regex : "(?:true|false)\\b"
+          }];
+      };
+
+      var blockCommentRules = function(returnRule) {
+        return [
+            {
+                token : "comment.block", // closing comment
+                regex : "\\*\\/",
+                next : returnRule
+            }, {
+                defaultToken : "comment.block"
+            }
+        ];
+      };
+
+      var basicPostRules = function() {
+        return [{
+            token : keywordMapper,
+            regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
+        }, {
+            token : "keyword.operator",
+            regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"
+        }, {
+            token : "lparen",
+            regex : "[[({]"
+        }, {
+            token : "rparen",
+            regex : "[\\])}]"
+        }, {
+            token : "text",
+            regex : "\\s+"
+        }];
+      };
+
+
+    this.$rules = {
+        "start" : [].concat(basicPreRules("block.comment"), [
+              {
+                token : "entity.name.type",
+                regex : "@[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
+              }, {
+                token : ["keyword","text","entity.name.type"],
+                regex : "(package)(\\s+)(" + packageIdentifierRe +")"
+              }, {
+                token : ["keyword","text","keyword","text","entity.name.type"],
+                regex : "(import)(\\s+)(function)(\\s+)(" + packageIdentifierRe +")"
+              }, {
+                token : ["keyword","text","entity.name.type"],
+                regex : "(import)(\\s+)(" + packageIdentifierRe +")"
+              }, {
+                token : ["keyword","text","entity.name.type","text","variable"],
+                regex : "(global)(\\s+)(" + packageIdentifierRe +")(\\s+)(" + identifierRe +")"
+              }, {
+                token : ["keyword","text","keyword","text","entity.name.type"],
+                regex : "(declare)(\\s+)(trait)(\\s+)(" + identifierRe +")"
+              }, {
+                token : ["keyword","text","entity.name.type"],
+                regex : "(declare)(\\s+)(" + identifierRe +")"
+              }, {
+                token : ["keyword","text","entity.name.type"],
+                regex : "(extends)(\\s+)(" + packageIdentifierRe +")"
+              }, {
+                token : ["keyword","text"],
+                regex : "(rule)(\\s+)",
+                next :  "asset.name"
+              }],
+              stringRules(),
+              [{
+                token : ["variable.other","text","text"],
+                regex : "(" + identifierRe + ")(\\s*)(:)"
+              }, {
+                token : ["keyword","text"],
+                regex : "(query)(\\s+)",
+                next :  "asset.name"
+              }, {
+                token : ["keyword","text"],
+                regex : "(when)(\\s*)"
+              }, {
+                token : ["keyword","text"],
+                regex : "(then)(\\s*)",
+                next :  "java-start"
+              }, {
+                  token : "paren.lparen",
+                  regex : /[\[({]/
+              }, {
+                  token : "paren.rparen",
+                  regex : /[\])}]/
+              }], basicPostRules()),
+        "block.comment" : blockCommentRules("start"),
+        "asset.name" : [
+            {
+                token : "entity.name",
+                regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
+            }, {
+                token : "entity.name",
+                regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
+            }, {
+                token : "entity.name",
+                regex : identifierRe
+            }, {
+                regex: "",
+                token: "empty",
+                next: "start"
+            }]
+    };
+    this.embedRules(DocCommentHighlightRules, "doc-",
+        [ DocCommentHighlightRules.getEndRule("start") ]);
+
+    this.embedRules(JavaHighlightRules, "java-", [
+      {
+       token : "support.function",
+       regex: "\\b(insert|modify|retract|update)\\b"
+     }, {
+       token : "keyword",
+       regex: "\\bend\\b",
+       next  : "start"
+    }]);
+
+};
+
+oop.inherits(DroolsHighlightRules, TextHighlightRules);
+
+exports.DroolsHighlightRules = DroolsHighlightRules;
+});
+
+ace.define("ace/mode/folding/drools",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Range = require("../../range").Range;
+var BaseFoldMode = require("./fold_mode").FoldMode;
+var TokenIterator = require("../../token_iterator").TokenIterator;
+
+var FoldMode = exports.FoldMode = function() {};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+    this.foldingStartMarker = /\b(rule|declare|query|when|then)\b/; 
+    this.foldingStopMarker = /\bend\b/;
+
+    this.getFoldWidgetRange = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+        var match = line.match(this.foldingStartMarker);
+        if (match) {
+            var i = match.index;
+
+            if (match[1]) {
+                var position = {row: row, column: line.length};
+                var iterator = new TokenIterator(session, position.row, position.column);
+                var seek = "end";
+                var token = iterator.getCurrentToken();
+                if (token.value == "when") {
+                    seek = "then";
+                }
+                while (token) {
+                    if (token.value == seek) { 
+                        return Range.fromPoints(position ,{
+                            row: iterator.getCurrentTokenRow(),
+                            column: iterator.getCurrentTokenColumn()
+                        });
+                    }
+                    token = iterator.stepForward();
+                }
+            }
+
+        }
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/drools",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var DroolsHighlightRules = require("./drools_highlight_rules").DroolsHighlightRules;
+var DroolsFoldMode = require("./folding/drools").FoldMode;
+
+var Mode = function() {
+    this.HighlightRules = DroolsHighlightRules;
+    this.foldingRules = new DroolsFoldMode();
+    this.$behaviour = this.$defaultBehaviour;
+
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+    this.lineCommentStart = "//";
+    this.$id = "ace/mode/drools";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+
+});
+                (function() {
+                    ace.require(["ace/mode/drools"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 166 - 0
services/web/public/js/ace-1.4.3/mode-edifact.js

@@ -0,0 +1,166 @@
+ace.define("ace/mode/doc_comment_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var DocCommentHighlightRules = function() {
+    this.$rules = {
+        "start" : [ {
+            token : "comment.doc.tag",
+            regex : "@[\\w\\d_]+" // TODO: fix email addresses
+        }, 
+        DocCommentHighlightRules.getTagRule(),
+        {
+            defaultToken : "comment.doc",
+            caseInsensitive: true
+        }]
+    };
+};
+
+oop.inherits(DocCommentHighlightRules, TextHighlightRules);
+
+DocCommentHighlightRules.getTagRule = function(start) {
+    return {
+        token : "comment.doc.tag.storage.type",
+        regex : "\\b(?:TODO|FIXME|XXX|HACK)\\b"
+    };
+};
+
+DocCommentHighlightRules.getStartRule = function(start) {
+    return {
+        token : "comment.doc", // doc comment
+        regex : "\\/\\*(?=\\*)",
+        next  : start
+    };
+};
+
+DocCommentHighlightRules.getEndRule = function (start) {
+    return {
+        token : "comment.doc", // closing comment
+        regex : "\\*\\/",
+        next  : start
+    };
+};
+
+
+exports.DocCommentHighlightRules = DocCommentHighlightRules;
+
+});
+
+ace.define("ace/mode/edifact_highlight_rules",[], function(require, exports, module) {
+    "use strict";
+    
+    var oop = require("../lib/oop");
+    var DocCommentHighlightRules = require("./doc_comment_highlight_rules").DocCommentHighlightRules;
+    var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+    
+    var EdifactHighlightRules = function() {
+    
+        var header = (
+            "UNH"
+        );
+        var segment = (
+            "ADR|AGR|AJT|ALC|ALI|APP|APR|ARD|ARR|ASI|ATT|AUT|"+
+            "BAS|BGM|BII|BUS|"+
+            "CAV|CCD|CCI|CDI|CDS|CDV|CED|CIN|CLA|CLI|CMP|CNI|CNT|COD|COM|COT|CPI|CPS|CPT|CST|CTA|CUX|"+
+            "DAM|DFN|DGS|DII|DIM|DLI|DLM|DMS|DOC|DRD|DSG|DSI|DTM|"+
+            "EDT|EFI|ELM|ELU|ELV|EMP|EQA|EQD|EQN|ERC|ERP|EVE|FCA|FII|FNS|FNT|FOR|FSQ|FTX|"+
+            "GDS|GEI|GID|GIN|GIR|GOR|GPO|GRU|HAN|HYN|ICD|IDE|IFD|IHC|IMD|IND|INP|INV|IRQ|"+
+            "LAN|LIN|LOC|MEA|MEM|MKS|MOA|MSG|MTD|NAD|NAT|"+
+            "PAC|PAI|PAS|PCC|PCD|PCI|PDI|PER|PGI|PIA|PNA|POC|PRC|PRI|PRV|PSD|PTY|PYT|"+
+            "QRS|QTY|QUA|QVR|"+
+            "RCS|REL|RFF|RJL|RNG|ROD|RSL|RTE|"+
+            "SAL|SCC|SCD|SEG|SEL|SEQ|SFI|SGP|SGU|SPR|SPS|STA|STC|STG|STS|"+
+            "TAX|TCC|TDT|TEM|TMD|TMP|TOD|TPL|TRU|TSR|"+
+            "UNB|UNZ|UNT|UGH|UGT|UNS|"+
+            "VLI"
+        );
+    
+        var header = (
+            "UNH"
+        );
+    
+        var buildinConstants = ("null|Infinity|NaN|undefined");
+        var langClasses = (
+            ""
+        );
+    
+        var keywords = (
+            "BY|SE|ON|INV|JP|UNOA"
+        );
+    
+        var keywordMapper = this.createKeywordMapper({
+            "variable.language": "this",
+            "keyword": keywords,
+            "entity.name.segment":segment,
+            "entity.name.header":header,
+            "constant.language": buildinConstants,
+            "support.function": langClasses
+        }, "identifier");
+    
+        this.$rules = {
+            "start" : [
+                {
+                    token : "punctuation.operator",
+                    regex : "\\+.\\+"
+                }, {
+                    token : "constant.language.boolean",
+                    regex : "(?:true|false)\\b"
+                }, {
+                    token : keywordMapper,
+                    regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
+                }, {
+                    token : "keyword.operator",
+                    regex : "\\+"
+                }, {
+                    token : "punctuation.operator",
+                    regex : "\\:|'"
+                },{
+                    token : "identifier",
+                    regex : "\\:D\\:"
+                }
+            ]
+        };
+    
+        this.embedRules(DocCommentHighlightRules, "doc-",
+            [ DocCommentHighlightRules.getEndRule("start") ]);
+    };
+    
+    EdifactHighlightRules.metaData = { fileTypes: [ 'edi' ],
+          keyEquivalent: '^~E',
+          name: 'Edifact',
+          scopeName: 'source.edifact' };
+    
+    oop.inherits(EdifactHighlightRules, TextHighlightRules);
+    
+    exports.EdifactHighlightRules = EdifactHighlightRules;
+    });
+
+ace.define("ace/mode/edifact",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var EdifactHighlightRules = require("./edifact_highlight_rules").EdifactHighlightRules;
+
+var Mode = function() {
+   
+    this.HighlightRules = EdifactHighlightRules;
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+    this.$id = "ace/mode/edifact";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/edifact"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 136 - 0
services/web/public/js/ace-1.4.3/mode-eiffel.js

@@ -0,0 +1,136 @@
+ace.define("ace/mode/eiffel_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var EiffelHighlightRules = function() {
+    var keywords = "across|agent|alias|all|attached|as|assign|attribute|check|" +
+        "class|convert|create|debug|deferred|detachable|do|else|elseif|end|" +
+        "ensure|expanded|export|external|feature|from|frozen|if|inherit|" +
+        "inspect|invariant|like|local|loop|not|note|obsolete|old|once|" +
+        "Precursor|redefine|rename|require|rescue|retry|select|separate|" +
+        "some|then|undefine|until|variant|when";
+
+    var operatorKeywords = "and|implies|or|xor";
+
+    var languageConstants = "Void";
+
+    var booleanConstants = "True|False";
+
+    var languageVariables = "Current|Result";
+
+    var keywordMapper = this.createKeywordMapper({
+        "constant.language": languageConstants,
+        "constant.language.boolean": booleanConstants,
+        "variable.language": languageVariables,
+        "keyword.operator": operatorKeywords,
+        "keyword": keywords
+    }, "identifier", true);
+
+    var simpleString = /(?:[^"%\b\f\v]|%[A-DFHLNQR-V%'"()<>]|%\/(?:0[xX][\da-fA-F](?:_*[\da-fA-F])*|0[cC][0-7](?:_*[0-7])*|0[bB][01](?:_*[01])*|\d(?:_*\d)*)\/)+?/;
+
+    this.$rules = {
+        "start": [{
+                token : "string.quoted.other", // Aligned-verbatim-strings (verbatim option not supported)
+                regex : /"\[/,
+                next: "aligned_verbatim_string"
+            }, {
+                token : "string.quoted.other", // Non-aligned-verbatim-strings (verbatim option not supported)
+                regex : /"\{/,
+                next: "non-aligned_verbatim_string"
+            }, {
+                token : "string.quoted.double",
+                regex : /"(?:[^%\b\f\n\r\v]|%[A-DFHLNQR-V%'"()<>]|%\/(?:0[xX][\da-fA-F](?:_*[\da-fA-F])*|0[cC][0-7](?:_*[0-7])*|0[bB][01](?:_*[01])*|\d(?:_*\d)*)\/)*?"/
+            }, {
+                token : "comment.line.double-dash",
+                regex : /--.*/
+            }, {
+                token : "constant.character",
+                regex : /'(?:[^%\b\f\n\r\t\v]|%[A-DFHLNQR-V%'"()<>]|%\/(?:0[xX][\da-fA-F](?:_*[\da-fA-F])*|0[cC][0-7](?:_*[0-7])*|0[bB][01](?:_*[01])*|\d(?:_*\d)*)\/)'/
+            }, {
+                token : "constant.numeric", // hexa | octal | bin
+                regex : /\b0(?:[xX][\da-fA-F](?:_*[\da-fA-F])*|[cC][0-7](?:_*[0-7])*|[bB][01](?:_*[01])*)\b/
+            }, {
+                token : "constant.numeric",
+                regex : /(?:\d(?:_*\d)*)?\.(?:(?:\d(?:_*\d)*)?[eE][+-]?)?\d(?:_*\d)*|\d(?:_*\d)*\.?/
+            }, {
+                token : "paren.lparen",
+                regex : /[\[({]|<<|\|\(/
+            }, {
+                token : "paren.rparen",
+                regex : /[\])}]|>>|\|\)/
+            }, {
+                token : "keyword.operator", // punctuation
+                regex : /:=|->|\.(?=\w)|[;,:?]/
+            }, {
+                token : "keyword.operator",
+                regex : /\\\\|\|\.\.\||\.\.|\/[~\/]?|[><\/]=?|[-+*^=~]/
+            }, {
+                token : function (v) {
+                    var result = keywordMapper(v);
+                    if (result === "identifier" && v === v.toUpperCase()) {
+                        result =  "entity.name.type";
+                    }
+                    return result;
+                },
+                regex : /[a-zA-Z][a-zA-Z\d_]*\b/
+            }, {
+                token : "text",
+                regex : /\s+/
+            }
+        ],
+        "aligned_verbatim_string" : [{
+                token : "string",
+                regex : /]"/,
+                next : "start"
+            }, {
+                token : "string",
+                regex : simpleString
+            }
+        ],
+        "non-aligned_verbatim_string" : [{
+                token : "string.quoted.other",
+                regex : /}"/,
+                next : "start"
+            }, {
+                token : "string.quoted.other",
+                regex : simpleString
+            }
+        ]};
+};
+
+oop.inherits(EiffelHighlightRules, TextHighlightRules);
+
+exports.EiffelHighlightRules = EiffelHighlightRules;
+});
+
+ace.define("ace/mode/eiffel",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var EiffelHighlightRules = require("./eiffel_highlight_rules").EiffelHighlightRules;
+
+var Mode = function() {
+    this.HighlightRules = EiffelHighlightRules;
+    this.$behaviour = this.$defaultBehaviour;
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+    this.lineCommentStart = "--";
+    this.$id = "ace/mode/eiffel";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+
+});
+                (function() {
+                    ace.require(["ace/mode/eiffel"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

Fișier diff suprimat deoarece este prea mare
+ 6 - 0
services/web/public/js/ace-1.4.3/mode-ejs.js


+ 502 - 0
services/web/public/js/ace-1.4.3/mode-elixir.js

@@ -0,0 +1,502 @@
+ace.define("ace/mode/elixir_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var ElixirHighlightRules = function() {
+
+    this.$rules = { start: 
+       [ { token: 
+            [ 'meta.module.elixir',
+              'keyword.control.module.elixir',
+              'meta.module.elixir',
+              'entity.name.type.module.elixir' ],
+           regex: '^(\\s*)(defmodule)(\\s+)((?:[A-Z]\\w*\\s*\\.\\s*)*[A-Z]\\w*)' },
+         { token: 'comment.documentation.heredoc',
+           regex: '@(?:module|type)?doc (?:~[a-z])?"""',
+           push: 
+            [ { token: 'comment.documentation.heredoc',
+                regex: '\\s*"""',
+                next: 'pop' },
+              { include: '#interpolated_elixir' },
+              { include: '#escaped_char' },
+              { defaultToken: 'comment.documentation.heredoc' } ],
+           comment: '@doc with heredocs is treated as documentation' },
+         { token: 'comment.documentation.heredoc',
+           regex: '@(?:module|type)?doc ~[A-Z]"""',
+           push: 
+            [ { token: 'comment.documentation.heredoc',
+                regex: '\\s*"""',
+                next: 'pop' },
+              { defaultToken: 'comment.documentation.heredoc' } ],
+           comment: '@doc with heredocs is treated as documentation' },
+         { token: 'comment.documentation.heredoc',
+           regex: '@(?:module|type)?doc (?:~[a-z])?\'\'\'',
+           push: 
+            [ { token: 'comment.documentation.heredoc',
+                regex: '\\s*\'\'\'',
+                next: 'pop' },
+              { include: '#interpolated_elixir' },
+              { include: '#escaped_char' },
+              { defaultToken: 'comment.documentation.heredoc' } ],
+           comment: '@doc with heredocs is treated as documentation' },
+         { token: 'comment.documentation.heredoc',
+           regex: '@(?:module|type)?doc ~[A-Z]\'\'\'',
+           push: 
+            [ { token: 'comment.documentation.heredoc',
+                regex: '\\s*\'\'\'',
+                next: 'pop' },
+              { defaultToken: 'comment.documentation.heredoc' } ],
+           comment: '@doc with heredocs is treated as documentation' },
+         { token: 'comment.documentation.false',
+           regex: '@(?:module|type)?doc false',
+           comment: '@doc false is treated as documentation' },
+         { token: 'comment.documentation.string',
+           regex: '@(?:module|type)?doc "',
+           push: 
+            [ { token: 'comment.documentation.string',
+                regex: '"',
+                next: 'pop' },
+              { include: '#interpolated_elixir' },
+              { include: '#escaped_char' },
+              { defaultToken: 'comment.documentation.string' } ],
+           comment: '@doc with string is treated as documentation' },
+         { token: 'keyword.control.elixir',
+           regex: '\\b(?:do|end|case|bc|lc|for|if|cond|unless|try|receive|fn|defmodule|defp?|defprotocol|defimpl|defrecord|defstruct|defmacrop?|defdelegate|defcallback|defmacrocallback|defexception|defoverridable|exit|after|rescue|catch|else|raise|throw|import|require|alias|use|quote|unquote|super)\\b(?![?!])',
+           TODO: 'FIXME: regexp doesn\'t have js equivalent',
+           originalRegex: '(?<!\\.)\\b(do|end|case|bc|lc|for|if|cond|unless|try|receive|fn|defmodule|defp?|defprotocol|defimpl|defrecord|defstruct|defmacrop?|defdelegate|defcallback|defmacrocallback|defexception|defoverridable|exit|after|rescue|catch|else|raise|throw|import|require|alias|use|quote|unquote|super)\\b(?![?!])' },
+         { token: 'keyword.operator.elixir',
+           regex: '\\b(?:and|not|or|when|xor|in|inlist|inbits)\\b',
+           TODO: 'FIXME: regexp doesn\'t have js equivalent',
+           originalRegex: '(?<!\\.)\\b(and|not|or|when|xor|in|inlist|inbits)\\b',
+           comment: ' as above, just doesn\'t need a \'end\' and does a logic operation' },
+         { token: 'constant.language.elixir',
+           regex: '\\b(?:nil|true|false)\\b(?![?!])' },
+         { token: 'variable.language.elixir',
+           regex: '\\b__(?:CALLER|ENV|MODULE|DIR)__\\b(?![?!])' },
+         { token: 
+            [ 'punctuation.definition.variable.elixir',
+              'variable.other.readwrite.module.elixir' ],
+           regex: '(@)([a-zA-Z_]\\w*)' },
+         { token: 
+            [ 'punctuation.definition.variable.elixir',
+              'variable.other.anonymous.elixir' ],
+           regex: '(&)(\\d*)' },
+         { token: 'variable.other.constant.elixir',
+           regex: '\\b[A-Z]\\w*\\b' },
+         { token: 'constant.numeric.elixir',
+           regex: '\\b(?:0x[\\da-fA-F](?:_?[\\da-fA-F])*|\\d(?:_?\\d)*(?:\\.(?![^[:space:][:digit:]])(?:_?\\d)*)?(?:[eE][-+]?\\d(?:_?\\d)*)?|0b[01]+|0o[0-7]+)\\b',
+           TODO: 'FIXME: regexp doesn\'t have js equivalent',
+           originalRegex: '\\b(0x\\h(?>_?\\h)*|\\d(?>_?\\d)*(\\.(?![^[:space:][:digit:]])(?>_?\\d)*)?([eE][-+]?\\d(?>_?\\d)*)?|0b[01]+|0o[0-7]+)\\b' },
+         { token: 'punctuation.definition.constant.elixir',
+           regex: ':\'',
+           push: 
+            [ { token: 'punctuation.definition.constant.elixir',
+                regex: '\'',
+                next: 'pop' },
+              { include: '#interpolated_elixir' },
+              { include: '#escaped_char' },
+              { defaultToken: 'constant.other.symbol.single-quoted.elixir' } ] },
+         { token: 'punctuation.definition.constant.elixir',
+           regex: ':"',
+           push: 
+            [ { token: 'punctuation.definition.constant.elixir',
+                regex: '"',
+                next: 'pop' },
+              { include: '#interpolated_elixir' },
+              { include: '#escaped_char' },
+              { defaultToken: 'constant.other.symbol.double-quoted.elixir' } ] },
+         { token: 'punctuation.definition.string.begin.elixir',
+           regex: '(?:\'\'\')',
+           TODO: 'FIXME: regexp doesn\'t have js equivalent',
+           originalRegex: '(?>\'\'\')',
+           push: 
+            [ { token: 'punctuation.definition.string.end.elixir',
+                regex: '^\\s*\'\'\'',
+                next: 'pop' },
+              { include: '#interpolated_elixir' },
+              { include: '#escaped_char' },
+              { defaultToken: 'support.function.variable.quoted.single.heredoc.elixir' } ],
+           comment: 'Single-quoted heredocs' },
+         { token: 'punctuation.definition.string.begin.elixir',
+           regex: '\'',
+           push: 
+            [ { token: 'punctuation.definition.string.end.elixir',
+                regex: '\'',
+                next: 'pop' },
+              { include: '#interpolated_elixir' },
+              { include: '#escaped_char' },
+              { defaultToken: 'support.function.variable.quoted.single.elixir' } ],
+           comment: 'single quoted string (allows for interpolation)' },
+         { token: 'punctuation.definition.string.begin.elixir',
+           regex: '(?:""")',
+           TODO: 'FIXME: regexp doesn\'t have js equivalent',
+           originalRegex: '(?>""")',
+           push: 
+            [ { token: 'punctuation.definition.string.end.elixir',
+                regex: '^\\s*"""',
+                next: 'pop' },
+              { include: '#interpolated_elixir' },
+              { include: '#escaped_char' },
+              { defaultToken: 'string.quoted.double.heredoc.elixir' } ],
+           comment: 'Double-quoted heredocs' },
+         { token: 'punctuation.definition.string.begin.elixir',
+           regex: '"',
+           push: 
+            [ { token: 'punctuation.definition.string.end.elixir',
+                regex: '"',
+                next: 'pop' },
+              { include: '#interpolated_elixir' },
+              { include: '#escaped_char' },
+              { defaultToken: 'string.quoted.double.elixir' } ],
+           comment: 'double quoted string (allows for interpolation)' },
+         { token: 'punctuation.definition.string.begin.elixir',
+           regex: '~[a-z](?:""")',
+           TODO: 'FIXME: regexp doesn\'t have js equivalent',
+           originalRegex: '~[a-z](?>""")',
+           push: 
+            [ { token: 'punctuation.definition.string.end.elixir',
+                regex: '^\\s*"""',
+                next: 'pop' },
+              { include: '#interpolated_elixir' },
+              { include: '#escaped_char' },
+              { defaultToken: 'string.quoted.double.heredoc.elixir' } ],
+           comment: 'Double-quoted heredocs sigils' },
+         { token: 'punctuation.definition.string.begin.elixir',
+           regex: '~[a-z]\\{',
+           push: 
+            [ { token: 'punctuation.definition.string.end.elixir',
+                regex: '\\}[a-z]*',
+                next: 'pop' },
+              { include: '#interpolated_elixir' },
+              { include: '#escaped_char' },
+              { defaultToken: 'string.interpolated.elixir' } ],
+           comment: 'sigil (allow for interpolation)' },
+         { token: 'punctuation.definition.string.begin.elixir',
+           regex: '~[a-z]\\[',
+           push: 
+            [ { token: 'punctuation.definition.string.end.elixir',
+                regex: '\\][a-z]*',
+                next: 'pop' },
+              { include: '#interpolated_elixir' },
+              { include: '#escaped_char' },
+              { defaultToken: 'string.interpolated.elixir' } ],
+           comment: 'sigil (allow for interpolation)' },
+         { token: 'punctuation.definition.string.begin.elixir',
+           regex: '~[a-z]\\<',
+           push: 
+            [ { token: 'punctuation.definition.string.end.elixir',
+                regex: '\\>[a-z]*',
+                next: 'pop' },
+              { include: '#interpolated_elixir' },
+              { include: '#escaped_char' },
+              { defaultToken: 'string.interpolated.elixir' } ],
+           comment: 'sigil (allow for interpolation)' },
+         { token: 'punctuation.definition.string.begin.elixir',
+           regex: '~[a-z]\\(',
+           push: 
+            [ { token: 'punctuation.definition.string.end.elixir',
+                regex: '\\)[a-z]*',
+                next: 'pop' },
+              { include: '#interpolated_elixir' },
+              { include: '#escaped_char' },
+              { defaultToken: 'string.interpolated.elixir' } ],
+           comment: 'sigil (allow for interpolation)' },
+         { token: 'punctuation.definition.string.begin.elixir',
+           regex: '~[a-z][^\\w]',
+           push: 
+            [ { token: 'punctuation.definition.string.end.elixir',
+                regex: '[^\\w][a-z]*',
+                next: 'pop' },
+              { include: '#interpolated_elixir' },
+              { include: '#escaped_char' },
+              { include: '#escaped_char' },
+              { defaultToken: 'string.interpolated.elixir' } ],
+           comment: 'sigil (allow for interpolation)' },
+         { token: 'punctuation.definition.string.begin.elixir',
+           regex: '~[A-Z](?:""")',
+           TODO: 'FIXME: regexp doesn\'t have js equivalent',
+           originalRegex: '~[A-Z](?>""")',
+           push: 
+            [ { token: 'punctuation.definition.string.end.elixir',
+                regex: '^\\s*"""',
+                next: 'pop' },
+              { defaultToken: 'string.quoted.other.literal.upper.elixir' } ],
+           comment: 'Double-quoted heredocs sigils' },
+         { token: 'punctuation.definition.string.begin.elixir',
+           regex: '~[A-Z]\\{',
+           push: 
+            [ { token: 'punctuation.definition.string.end.elixir',
+                regex: '\\}[a-z]*',
+                next: 'pop' },
+              { defaultToken: 'string.quoted.other.literal.upper.elixir' } ],
+           comment: 'sigil (without interpolation)' },
+         { token: 'punctuation.definition.string.begin.elixir',
+           regex: '~[A-Z]\\[',
+           push: 
+            [ { token: 'punctuation.definition.string.end.elixir',
+                regex: '\\][a-z]*',
+                next: 'pop' },
+              { defaultToken: 'string.quoted.other.literal.upper.elixir' } ],
+           comment: 'sigil (without interpolation)' },
+         { token: 'punctuation.definition.string.begin.elixir',
+           regex: '~[A-Z]\\<',
+           push: 
+            [ { token: 'punctuation.definition.string.end.elixir',
+                regex: '\\>[a-z]*',
+                next: 'pop' },
+              { defaultToken: 'string.quoted.other.literal.upper.elixir' } ],
+           comment: 'sigil (without interpolation)' },
+         { token: 'punctuation.definition.string.begin.elixir',
+           regex: '~[A-Z]\\(',
+           push: 
+            [ { token: 'punctuation.definition.string.end.elixir',
+                regex: '\\)[a-z]*',
+                next: 'pop' },
+              { defaultToken: 'string.quoted.other.literal.upper.elixir' } ],
+           comment: 'sigil (without interpolation)' },
+         { token: 'punctuation.definition.string.begin.elixir',
+           regex: '~[A-Z][^\\w]',
+           push: 
+            [ { token: 'punctuation.definition.string.end.elixir',
+                regex: '[^\\w][a-z]*',
+                next: 'pop' },
+              { defaultToken: 'string.quoted.other.literal.upper.elixir' } ],
+           comment: 'sigil (without interpolation)' },
+         { token: ['punctuation.definition.constant.elixir', 'constant.other.symbol.elixir'],
+           regex: '(:)([a-zA-Z_][\\w@]*(?:[?!]|=(?![>=]))?|\\<\\>|===?|!==?|<<>>|<<<|>>>|~~~|::|<\\-|\\|>|=>|~|~=|=|/|\\\\\\\\|\\*\\*?|\\.\\.?\\.?|>=?|<=?|&&?&?|\\+\\+?|\\-\\-?|\\|\\|?\\|?|\\!|@|\\%?\\{\\}|%|\\[\\]|\\^(?:\\^\\^)?)',
+           TODO: 'FIXME: regexp doesn\'t have js equivalent',
+           originalRegex: '(?<!:)(:)(?>[a-zA-Z_][\\w@]*(?>[?!]|=(?![>=]))?|\\<\\>|===?|!==?|<<>>|<<<|>>>|~~~|::|<\\-|\\|>|=>|~|~=|=|/|\\\\\\\\|\\*\\*?|\\.\\.?\\.?|>=?|<=?|&&?&?|\\+\\+?|\\-\\-?|\\|\\|?\\|?|\\!|@|\\%?\\{\\}|%|\\[\\]|\\^(\\^\\^)?)',
+           comment: 'symbols' },
+         { token: 'punctuation.definition.constant.elixir',
+           regex: '(?:[a-zA-Z_][\\w@]*(?:[?!])?):(?!:)',
+           TODO: 'FIXME: regexp doesn\'t have js equivalent',
+           originalRegex: '(?>[a-zA-Z_][\\w@]*(?>[?!])?)(:)(?!:)',
+           comment: 'symbols' },
+         { token: 
+            [ 'punctuation.definition.comment.elixir',
+              'comment.line.number-sign.elixir' ],
+           regex: '(#)(.*)' },
+         { token: 'constant.numeric.elixir',
+           regex: '\\?(?:\\\\(?:x[\\da-fA-F]{1,2}(?![\\da-fA-F])\\b|[^xMC])|[^\\s\\\\])',
+           TODO: 'FIXME: regexp doesn\'t have js equivalent',
+           originalRegex: '(?<!\\w)\\?(\\\\(x\\h{1,2}(?!\\h)\\b|[^xMC])|[^\\s\\\\])',
+           comment: '\n\t\t\tmatches questionmark-letters.\n\n\t\t\texamples (1st alternation = hex):\n\t\t\t?\\x1     ?\\x61\n\n\t\t\texamples (2rd alternation = escaped):\n\t\t\t?\\n      ?\\b\n\n\t\t\texamples (3rd alternation = normal):\n\t\t\t?a       ?A       ?0 \n\t\t\t?*       ?"       ?( \n\t\t\t?.       ?#\n\t\t\t\n\t\t\tthe negative lookbehind prevents against matching\n\t\t\tp(42.tainted?)\n\t\t\t' },
+         { token: 'keyword.operator.assignment.augmented.elixir',
+           regex: '\\+=|\\-=|\\|\\|=|~=|&&=' },
+         { token: 'keyword.operator.comparison.elixir',
+           regex: '===?|!==?|<=?|>=?' },
+         { token: 'keyword.operator.bitwise.elixir',
+           regex: '\\|{3}|&{3}|\\^{3}|<{3}|>{3}|~{3}' },
+         { token: 'keyword.operator.logical.elixir',
+           regex: '!+|\\bnot\\b|&&|\\band\\b|\\|\\||\\bor\\b|\\bxor\\b',
+           originalRegex: '(?<=[ \\t])!+|\\bnot\\b|&&|\\band\\b|\\|\\||\\bor\\b|\\bxor\\b' },
+         { token: 'keyword.operator.arithmetic.elixir',
+           regex: '\\*|\\+|\\-|/' },
+         { token: 'keyword.operator.other.elixir',
+           regex: '\\||\\+\\+|\\-\\-|\\*\\*|\\\\\\\\|\\<\\-|\\<\\>|\\<\\<|\\>\\>|\\:\\:|\\.\\.|\\|>|~|=>' },
+         { token: 'keyword.operator.assignment.elixir', regex: '=' },
+         { token: 'punctuation.separator.other.elixir', regex: ':' },
+         { token: 'punctuation.separator.statement.elixir',
+           regex: '\\;' },
+         { token: 'punctuation.separator.object.elixir', regex: ',' },
+         { token: 'punctuation.separator.method.elixir', regex: '\\.' },
+         { token: 'punctuation.section.scope.elixir', regex: '\\{|\\}' },
+         { token: 'punctuation.section.array.elixir', regex: '\\[|\\]' },
+         { token: 'punctuation.section.function.elixir',
+           regex: '\\(|\\)' } ],
+      '#escaped_char': 
+       [ { token: 'constant.character.escape.elixir',
+           regex: '\\\\(?:x[\\da-fA-F]{1,2}|.)' } ],
+      '#interpolated_elixir': 
+       [ { token: 
+            [ 'source.elixir.embedded.source',
+              'source.elixir.embedded.source.empty' ],
+           regex: '(#\\{)(\\})' },
+         { todo: 
+            { token: 'punctuation.section.embedded.elixir',
+              regex: '#\\{',
+              push: 
+               [ { token: 'punctuation.section.embedded.elixir',
+                   regex: '\\}',
+                   next: 'pop' },
+                 { include: '#nest_curly_and_self' },
+                 { include: '$self' },
+                 { defaultToken: 'source.elixir.embedded.source' } ] } } ],
+      '#nest_curly_and_self': 
+       [ { token: 'punctuation.section.scope.elixir',
+           regex: '\\{',
+           push: 
+            [ { token: 'punctuation.section.scope.elixir',
+                regex: '\\}',
+                next: 'pop' },
+              { include: '#nest_curly_and_self' } ] },
+         { include: '$self' } ],
+      '#regex_sub': 
+       [ { include: '#interpolated_elixir' },
+         { include: '#escaped_char' },
+         { token: 
+            [ 'punctuation.definition.arbitrary-repitition.elixir',
+              'string.regexp.arbitrary-repitition.elixir',
+              'string.regexp.arbitrary-repitition.elixir',
+              'punctuation.definition.arbitrary-repitition.elixir' ],
+           regex: '(\\{)(\\d+)((?:,\\d+)?)(\\})' },
+         { token: 'punctuation.definition.character-class.elixir',
+           regex: '\\[(?:\\^?\\])?',
+           push: 
+            [ { token: 'punctuation.definition.character-class.elixir',
+                regex: '\\]',
+                next: 'pop' },
+              { include: '#escaped_char' },
+              { defaultToken: 'string.regexp.character-class.elixir' } ] },
+         { token: 'punctuation.definition.group.elixir',
+           regex: '\\(',
+           push: 
+            [ { token: 'punctuation.definition.group.elixir',
+                regex: '\\)',
+                next: 'pop' },
+              { include: '#regex_sub' },
+              { defaultToken: 'string.regexp.group.elixir' } ] },
+         { token: 
+            [ 'punctuation.definition.comment.elixir',
+              'comment.line.number-sign.elixir' ],
+           regex: '(?:^|\\s)(#)(\\s[[a-zA-Z0-9,. \\t?!-][^\\x00-\\x7F]]*$)',
+           originalRegex: '(?<=^|\\s)(#)\\s[[a-zA-Z0-9,. \\t?!-][^\\x{00}-\\x{7F}]]*$',
+           comment: 'We are restrictive in what we allow to go after the comment character to avoid false positives, since the availability of comments depend on regexp flags.' } ] };
+    
+    this.normalizeRules();
+};
+
+ElixirHighlightRules.metaData = { comment: 'Textmate bundle for Elixir Programming Language.',
+      fileTypes: [ 'ex', 'exs' ],
+      firstLineMatch: '^#!/.*\\belixir',
+      foldingStartMarker: '(after|else|catch|rescue|\\-\\>|\\{|\\[|do)\\s*$',
+      foldingStopMarker: '^\\s*((\\}|\\]|after|else|catch|rescue)\\s*$|end\\b)',
+      keyEquivalent: '^~E',
+      name: 'Elixir',
+      scopeName: 'source.elixir' };
+
+
+oop.inherits(ElixirHighlightRules, TextHighlightRules);
+
+exports.ElixirHighlightRules = ElixirHighlightRules;
+});
+
+ace.define("ace/mode/folding/coffee",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var BaseFoldMode = require("./fold_mode").FoldMode;
+var Range = require("../../range").Range;
+
+var FoldMode = exports.FoldMode = function() {};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+
+    this.getFoldWidgetRange = function(session, foldStyle, row) {
+        var range = this.indentationBlock(session, row);
+        if (range)
+            return range;
+
+        var re = /\S/;
+        var line = session.getLine(row);
+        var startLevel = line.search(re);
+        if (startLevel == -1 || line[startLevel] != "#")
+            return;
+
+        var startColumn = line.length;
+        var maxRow = session.getLength();
+        var startRow = row;
+        var endRow = row;
+
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var level = line.search(re);
+
+            if (level == -1)
+                continue;
+
+            if (line[level] != "#")
+                break;
+
+            endRow = row;
+        }
+
+        if (endRow > startRow) {
+            var endColumn = session.getLine(endRow).length;
+            return new Range(startRow, startColumn, endRow, endColumn);
+        }
+    };
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+        var indent = line.search(/\S/);
+        var next = session.getLine(row + 1);
+        var prev = session.getLine(row - 1);
+        var prevIndent = prev.search(/\S/);
+        var nextIndent = next.search(/\S/);
+
+        if (indent == -1) {
+            session.foldWidgets[row - 1] = prevIndent!= -1 && prevIndent < nextIndent ? "start" : "";
+            return "";
+        }
+        if (prevIndent == -1) {
+            if (indent == nextIndent && line[indent] == "#" && next[indent] == "#") {
+                session.foldWidgets[row - 1] = "";
+                session.foldWidgets[row + 1] = "";
+                return "start";
+            }
+        } else if (prevIndent == indent && line[indent] == "#" && prev[indent] == "#") {
+            if (session.getLine(row - 2).search(/\S/) == -1) {
+                session.foldWidgets[row - 1] = "start";
+                session.foldWidgets[row + 1] = "";
+                return "";
+            }
+        }
+
+        if (prevIndent!= -1 && prevIndent < indent)
+            session.foldWidgets[row - 1] = "start";
+        else
+            session.foldWidgets[row - 1] = "";
+
+        if (indent < nextIndent)
+            return "start";
+        else
+            return "";
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/elixir",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var ElixirHighlightRules = require("./elixir_highlight_rules").ElixirHighlightRules;
+var FoldMode = require("./folding/coffee").FoldMode;
+
+var Mode = function() {
+    this.HighlightRules = ElixirHighlightRules;
+    this.foldingRules = new FoldMode();
+    this.$behaviour = this.$defaultBehaviour;
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+    this.lineCommentStart = "#";
+    this.$id = "ace/mode/elixir";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/elixir"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 307 - 0
services/web/public/js/ace-1.4.3/mode-elm.js

@@ -0,0 +1,307 @@
+ace.define("ace/mode/elm_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var ElmHighlightRules = function() {
+    var keywordMapper = this.createKeywordMapper({
+       "keyword": "as|case|class|data|default|deriving|do|else|export|foreign|" +
+            "hiding|jsevent|if|import|in|infix|infixl|infixr|instance|let|" +
+            "module|newtype|of|open|then|type|where|_|port|\u03BB"
+    }, "identifier");
+    
+    var escapeRe = /\\(\d+|['"\\&trnbvf])/;
+    
+    var smallRe = /[a-z_]/.source;
+    var largeRe = /[A-Z]/.source;
+    var idRe = /[a-z_A-Z0-9']/.source;
+
+    this.$rules = {
+        start: [{
+            token: "string.start",
+            regex: '"',
+            next: "string"
+        }, {
+            token: "string.character",
+            regex: "'(?:" + escapeRe.source + "|.)'?"
+        }, {
+            regex: /0(?:[xX][0-9A-Fa-f]+|[oO][0-7]+)|\d+(\.\d+)?([eE][-+]?\d*)?/,
+            token: "constant.numeric"
+        }, {
+            token: "comment",
+            regex: "--.*"
+        }, {
+            token : "keyword",
+            regex : /\.\.|\||:|=|\\|"|->|<-|\u2192/
+        }, {
+            token : "keyword.operator",
+            regex : /[-!#$%&*+.\/<=>?@\\^|~:\u03BB\u2192]+/
+        }, {
+            token : "operator.punctuation",
+            regex : /[,;`]/
+        }, {
+            regex : largeRe + idRe + "+\\.?",
+            token : function(value) {
+                if (value[value.length - 1] == ".")
+                    return "entity.name.function"; 
+                return "constant.language"; 
+            }
+        }, {
+            regex : "^" + smallRe  + idRe + "+",
+            token : function(value) {
+                return "constant.language"; 
+            }
+        }, {
+            token : keywordMapper,
+            regex : "[\\w\\xff-\\u218e\\u2455-\\uffff]+\\b"
+        }, {
+            regex: "{-#?",
+            token: "comment.start",
+            onMatch: function(value, currentState, stack) {
+                this.next = value.length == 2 ? "blockComment" : "docComment";
+                return this.token;
+            }
+        }, {
+            token: "variable.language",
+            regex: /\[markdown\|/,
+            next: "markdown"
+        }, {
+            token: "paren.lparen",
+            regex: /[\[({]/ 
+        }, {
+            token: "paren.rparen",
+            regex: /[\])}]/
+        } ],
+        markdown: [{
+            regex: /\|\]/,
+            next: "start"
+        }, {
+            defaultToken : "string"
+        }],
+        blockComment: [{
+            regex: "{-",
+            token: "comment.start",
+            push: "blockComment"
+        }, {
+            regex: "-}",
+            token: "comment.end",
+            next: "pop"
+        }, {
+            defaultToken: "comment"
+        }],
+        docComment: [{
+            regex: "{-",
+            token: "comment.start",
+            push: "docComment"
+        }, {
+            regex: "-}",
+            token: "comment.end",
+            next: "pop" 
+        }, {
+            defaultToken: "doc.comment"
+        }],
+        string: [{
+            token: "constant.language.escape",
+            regex: escapeRe
+        }, {
+            token: "text",
+            regex: /\\(\s|$)/,
+            next: "stringGap"
+        }, {
+            token: "string.end",
+            regex: '"',
+            next: "start"
+        }, {
+            defaultToken: "string"
+        }],
+        stringGap: [{
+            token: "text",
+            regex: /\\/,
+            next: "string"
+        }, {
+            token: "error",
+            regex: "",
+            next: "start"
+        }]
+    };
+    
+    this.normalizeRules();
+};
+
+oop.inherits(ElmHighlightRules, TextHighlightRules);
+
+exports.ElmHighlightRules = ElmHighlightRules;
+});
+
+ace.define("ace/mode/folding/cstyle",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Range = require("../../range").Range;
+var BaseFoldMode = require("./fold_mode").FoldMode;
+
+var FoldMode = exports.FoldMode = function(commentRegex) {
+    if (commentRegex) {
+        this.foldingStartMarker = new RegExp(
+            this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start)
+        );
+        this.foldingStopMarker = new RegExp(
+            this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end)
+        );
+    }
+};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+    
+    this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/;
+    this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/;
+    this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/;
+    this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/;
+    this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/;
+    this._getFoldWidgetBase = this.getFoldWidget;
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+    
+        if (this.singleLineBlockCommentRe.test(line)) {
+            if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line))
+                return "";
+        }
+    
+        var fw = this._getFoldWidgetBase(session, foldStyle, row);
+    
+        if (!fw && this.startRegionRe.test(line))
+            return "start"; // lineCommentRegionStart
+    
+        return fw;
+    };
+
+    this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) {
+        var line = session.getLine(row);
+        
+        if (this.startRegionRe.test(line))
+            return this.getCommentRegionBlock(session, line, row);
+        
+        var match = line.match(this.foldingStartMarker);
+        if (match) {
+            var i = match.index;
+
+            if (match[1])
+                return this.openingBracketBlock(session, match[1], row, i);
+                
+            var range = session.getCommentFoldRange(row, i + match[0].length, 1);
+            
+            if (range && !range.isMultiLine()) {
+                if (forceMultiline) {
+                    range = this.getSectionRange(session, row);
+                } else if (foldStyle != "all")
+                    range = null;
+            }
+            
+            return range;
+        }
+
+        if (foldStyle === "markbegin")
+            return;
+
+        var match = line.match(this.foldingStopMarker);
+        if (match) {
+            var i = match.index + match[0].length;
+
+            if (match[1])
+                return this.closingBracketBlock(session, match[1], row, i);
+
+            return session.getCommentFoldRange(row, i, -1);
+        }
+    };
+    
+    this.getSectionRange = function(session, row) {
+        var line = session.getLine(row);
+        var startIndent = line.search(/\S/);
+        var startRow = row;
+        var startColumn = line.length;
+        row = row + 1;
+        var endRow = row;
+        var maxRow = session.getLength();
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var indent = line.search(/\S/);
+            if (indent === -1)
+                continue;
+            if  (startIndent > indent)
+                break;
+            var subRange = this.getFoldWidgetRange(session, "all", row);
+            
+            if (subRange) {
+                if (subRange.start.row <= startRow) {
+                    break;
+                } else if (subRange.isMultiLine()) {
+                    row = subRange.end.row;
+                } else if (startIndent == indent) {
+                    break;
+                }
+            }
+            endRow = row;
+        }
+        
+        return new Range(startRow, startColumn, endRow, session.getLine(endRow).length);
+    };
+    this.getCommentRegionBlock = function(session, line, row) {
+        var startColumn = line.search(/\s*$/);
+        var maxRow = session.getLength();
+        var startRow = row;
+        
+        var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/;
+        var depth = 1;
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var m = re.exec(line);
+            if (!m) continue;
+            if (m[1]) depth--;
+            else depth++;
+
+            if (!depth) break;
+        }
+
+        var endRow = row;
+        if (endRow > startRow) {
+            return new Range(startRow, startColumn, endRow, line.length);
+        }
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/elm",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var HighlightRules = require("./elm_highlight_rules").ElmHighlightRules;
+var FoldMode = require("./folding/cstyle").FoldMode;
+
+var Mode = function() {
+    this.HighlightRules = HighlightRules;
+    this.foldingRules = new FoldMode();
+    this.$behaviour = this.$defaultBehaviour;
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+    this.lineCommentStart = "--";
+    this.blockComment = {start: "{-", end: "-}", nestable: true};
+    this.$id = "ace/mode/elm";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/elm"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 1010 - 0
services/web/public/js/ace-1.4.3/mode-erlang.js

@@ -0,0 +1,1010 @@
+ace.define("ace/mode/erlang_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var ErlangHighlightRules = function() {
+
+    this.$rules = { start: 
+       [ { include: '#module-directive' },
+         { include: '#import-export-directive' },
+         { include: '#behaviour-directive' },
+         { include: '#record-directive' },
+         { include: '#define-directive' },
+         { include: '#macro-directive' },
+         { include: '#directive' },
+         { include: '#function' },
+         { include: '#everything-else' } ],
+      '#atom': 
+       [ { token: 'punctuation.definition.symbol.begin.erlang',
+           regex: '\'',
+           push: 
+            [ { token: 'punctuation.definition.symbol.end.erlang',
+                regex: '\'',
+                next: 'pop' },
+              { token: 
+                 [ 'punctuation.definition.escape.erlang',
+                   'constant.other.symbol.escape.erlang',
+                   'punctuation.definition.escape.erlang',
+                   'constant.other.symbol.escape.erlang',
+                   'constant.other.symbol.escape.erlang' ],
+                regex: '(\\\\)(?:([bdefnrstv\\\\\'"])|(\\^)([@-_])|([0-7]{1,3}))' },
+              { token: 'invalid.illegal.atom.erlang', regex: '\\\\\\^?.?' },
+              { defaultToken: 'constant.other.symbol.quoted.single.erlang' } ] },
+         { token: 'constant.other.symbol.unquoted.erlang',
+           regex: '[a-z][a-zA-Z\\d@_]*' } ],
+      '#behaviour-directive': 
+       [ { token: 
+            [ 'meta.directive.behaviour.erlang',
+              'punctuation.section.directive.begin.erlang',
+              'meta.directive.behaviour.erlang',
+              'keyword.control.directive.behaviour.erlang',
+              'meta.directive.behaviour.erlang',
+              'punctuation.definition.parameters.begin.erlang',
+              'meta.directive.behaviour.erlang',
+              'entity.name.type.class.behaviour.definition.erlang',
+              'meta.directive.behaviour.erlang',
+              'punctuation.definition.parameters.end.erlang',
+              'meta.directive.behaviour.erlang',
+              'punctuation.section.directive.end.erlang' ],
+           regex: '^(\\s*)(-)(\\s*)(behaviour)(\\s*)(\\()(\\s*)([a-z][a-zA-Z\\d@_]*)(\\s*)(\\))(\\s*)(\\.)' } ],
+      '#binary': 
+       [ { token: 'punctuation.definition.binary.begin.erlang',
+           regex: '<<',
+           push: 
+            [ { token: 'punctuation.definition.binary.end.erlang',
+                regex: '>>',
+                next: 'pop' },
+              { token: 
+                 [ 'punctuation.separator.binary.erlang',
+                   'punctuation.separator.value-size.erlang' ],
+                regex: '(,)|(:)' },
+              { include: '#internal-type-specifiers' },
+              { include: '#everything-else' },
+              { defaultToken: 'meta.structure.binary.erlang' } ] } ],
+      '#character': 
+       [ { token: 
+            [ 'punctuation.definition.character.erlang',
+              'punctuation.definition.escape.erlang',
+              'constant.character.escape.erlang',
+              'punctuation.definition.escape.erlang',
+              'constant.character.escape.erlang',
+              'constant.character.escape.erlang' ],
+           regex: '(\\$)(\\\\)(?:([bdefnrstv\\\\\'"])|(\\^)([@-_])|([0-7]{1,3}))' },
+         { token: 'invalid.illegal.character.erlang',
+           regex: '\\$\\\\\\^?.?' },
+         { token: 
+            [ 'punctuation.definition.character.erlang',
+              'constant.character.erlang' ],
+           regex: '(\\$)(\\S)' },
+         { token: 'invalid.illegal.character.erlang', regex: '\\$.?' } ],
+      '#comment': 
+       [ { token: 'punctuation.definition.comment.erlang',
+           regex: '%.*$',
+           push_: 
+            [ { token: 'comment.line.percentage.erlang',
+                regex: '$',
+                next: 'pop' },
+              { defaultToken: 'comment.line.percentage.erlang' } ] } ],
+      '#define-directive': 
+       [ { token: 
+            [ 'meta.directive.define.erlang',
+              'punctuation.section.directive.begin.erlang',
+              'meta.directive.define.erlang',
+              'keyword.control.directive.define.erlang',
+              'meta.directive.define.erlang',
+              'punctuation.definition.parameters.begin.erlang',
+              'meta.directive.define.erlang',
+              'entity.name.function.macro.definition.erlang',
+              'meta.directive.define.erlang',
+              'punctuation.separator.parameters.erlang' ],
+           regex: '^(\\s*)(-)(\\s*)(define)(\\s*)(\\()(\\s*)([a-zA-Z\\d@_]+)(\\s*)(,)',
+           push: 
+            [ { token: 
+                 [ 'punctuation.definition.parameters.end.erlang',
+                   'meta.directive.define.erlang',
+                   'punctuation.section.directive.end.erlang' ],
+                regex: '(\\))(\\s*)(\\.)',
+                next: 'pop' },
+              { include: '#everything-else' },
+              { defaultToken: 'meta.directive.define.erlang' } ] },
+         { token: 'meta.directive.define.erlang',
+           regex: '(?=^\\s*-\\s*define\\s*\\(\\s*[a-zA-Z\\d@_]+\\s*\\()',
+           push: 
+            [ { token: 
+                 [ 'punctuation.definition.parameters.end.erlang',
+                   'meta.directive.define.erlang',
+                   'punctuation.section.directive.end.erlang' ],
+                regex: '(\\))(\\s*)(\\.)',
+                next: 'pop' },
+              { token: 
+                 [ 'text',
+                   'punctuation.section.directive.begin.erlang',
+                   'text',
+                   'keyword.control.directive.define.erlang',
+                   'text',
+                   'punctuation.definition.parameters.begin.erlang',
+                   'text',
+                   'entity.name.function.macro.definition.erlang',
+                   'text',
+                   'punctuation.definition.parameters.begin.erlang' ],
+                regex: '^(\\s*)(-)(\\s*)(define)(\\s*)(\\()(\\s*)([a-zA-Z\\d@_]+)(\\s*)(\\()',
+                push: 
+                 [ { token: 
+                      [ 'punctuation.definition.parameters.end.erlang',
+                        'text',
+                        'punctuation.separator.parameters.erlang' ],
+                     regex: '(\\))(\\s*)(,)',
+                     next: 'pop' },
+                   { token: 'punctuation.separator.parameters.erlang', regex: ',' },
+                   { include: '#everything-else' } ] },
+              { token: 'punctuation.separator.define.erlang',
+                regex: '\\|\\||\\||:|;|,|\\.|->' },
+              { include: '#everything-else' },
+              { defaultToken: 'meta.directive.define.erlang' } ] } ],
+      '#directive': 
+       [ { token: 
+            [ 'meta.directive.erlang',
+              'punctuation.section.directive.begin.erlang',
+              'meta.directive.erlang',
+              'keyword.control.directive.erlang',
+              'meta.directive.erlang',
+              'punctuation.definition.parameters.begin.erlang' ],
+           regex: '^(\\s*)(-)(\\s*)([a-z][a-zA-Z\\d@_]*)(\\s*)(\\(?)',
+           push: 
+            [ { token: 
+                 [ 'punctuation.definition.parameters.end.erlang',
+                   'meta.directive.erlang',
+                   'punctuation.section.directive.end.erlang' ],
+                regex: '(\\)?)(\\s*)(\\.)',
+                next: 'pop' },
+              { include: '#everything-else' },
+              { defaultToken: 'meta.directive.erlang' } ] },
+         { token: 
+            [ 'meta.directive.erlang',
+              'punctuation.section.directive.begin.erlang',
+              'meta.directive.erlang',
+              'keyword.control.directive.erlang',
+              'meta.directive.erlang',
+              'punctuation.section.directive.end.erlang' ],
+           regex: '^(\\s*)(-)(\\s*)([a-z][a-zA-Z\\d@_]*)(\\s*)(\\.)' } ],
+      '#everything-else': 
+       [ { include: '#comment' },
+         { include: '#record-usage' },
+         { include: '#macro-usage' },
+         { include: '#expression' },
+         { include: '#keyword' },
+         { include: '#textual-operator' },
+         { include: '#function-call' },
+         { include: '#tuple' },
+         { include: '#list' },
+         { include: '#binary' },
+         { include: '#parenthesized-expression' },
+         { include: '#character' },
+         { include: '#number' },
+         { include: '#atom' },
+         { include: '#string' },
+         { include: '#symbolic-operator' },
+         { include: '#variable' } ],
+      '#expression': 
+       [ { token: 'keyword.control.if.erlang',
+           regex: '\\bif\\b',
+           push: 
+            [ { token: 'keyword.control.end.erlang',
+                regex: '\\bend\\b',
+                next: 'pop' },
+              { include: '#internal-expression-punctuation' },
+              { include: '#everything-else' },
+              { defaultToken: 'meta.expression.if.erlang' } ] },
+         { token: 'keyword.control.case.erlang',
+           regex: '\\bcase\\b',
+           push: 
+            [ { token: 'keyword.control.end.erlang',
+                regex: '\\bend\\b',
+                next: 'pop' },
+              { include: '#internal-expression-punctuation' },
+              { include: '#everything-else' },
+              { defaultToken: 'meta.expression.case.erlang' } ] },
+         { token: 'keyword.control.receive.erlang',
+           regex: '\\breceive\\b',
+           push: 
+            [ { token: 'keyword.control.end.erlang',
+                regex: '\\bend\\b',
+                next: 'pop' },
+              { include: '#internal-expression-punctuation' },
+              { include: '#everything-else' },
+              { defaultToken: 'meta.expression.receive.erlang' } ] },
+         { token: 
+            [ 'keyword.control.fun.erlang',
+              'text',
+              'entity.name.type.class.module.erlang',
+              'text',
+              'punctuation.separator.module-function.erlang',
+              'text',
+              'entity.name.function.erlang',
+              'text',
+              'punctuation.separator.function-arity.erlang' ],
+           regex: '\\b(fun)(\\s*)(?:([a-z][a-zA-Z\\d@_]*)(\\s*)(:)(\\s*))?([a-z][a-zA-Z\\d@_]*)(\\s*)(/)' },
+         { token: 'keyword.control.fun.erlang',
+           regex: '\\bfun\\b',
+           push: 
+            [ { token: 'keyword.control.end.erlang',
+                regex: '\\bend\\b',
+                next: 'pop' },
+              { token: 'text',
+                regex: '(?=\\()',
+                push: 
+                 [ { token: 'punctuation.separator.clauses.erlang',
+                     regex: ';|(?=\\bend\\b)',
+                     next: 'pop' },
+                   { include: '#internal-function-parts' } ] },
+              { include: '#everything-else' },
+              { defaultToken: 'meta.expression.fun.erlang' } ] },
+         { token: 'keyword.control.try.erlang',
+           regex: '\\btry\\b',
+           push: 
+            [ { token: 'keyword.control.end.erlang',
+                regex: '\\bend\\b',
+                next: 'pop' },
+              { include: '#internal-expression-punctuation' },
+              { include: '#everything-else' },
+              { defaultToken: 'meta.expression.try.erlang' } ] },
+         { token: 'keyword.control.begin.erlang',
+           regex: '\\bbegin\\b',
+           push: 
+            [ { token: 'keyword.control.end.erlang',
+                regex: '\\bend\\b',
+                next: 'pop' },
+              { include: '#internal-expression-punctuation' },
+              { include: '#everything-else' },
+              { defaultToken: 'meta.expression.begin.erlang' } ] },
+         { token: 'keyword.control.query.erlang',
+           regex: '\\bquery\\b',
+           push: 
+            [ { token: 'keyword.control.end.erlang',
+                regex: '\\bend\\b',
+                next: 'pop' },
+              { include: '#everything-else' },
+              { defaultToken: 'meta.expression.query.erlang' } ] } ],
+      '#function': 
+       [ { token: 
+            [ 'meta.function.erlang',
+              'entity.name.function.definition.erlang',
+              'meta.function.erlang' ],
+           regex: '^(\\s*)([a-z][a-zA-Z\\d@_]*|\'[^\']*\')(\\s*)(?=\\()',
+           push: 
+            [ { token: 'punctuation.terminator.function.erlang',
+                regex: '\\.',
+                next: 'pop' },
+              { token: [ 'text', 'entity.name.function.erlang', 'text' ],
+                regex: '^(\\s*)([a-z][a-zA-Z\\d@_]*|\'[^\']*\')(\\s*)(?=\\()' },
+              { token: 'text',
+                regex: '(?=\\()',
+                push: 
+                 [ { token: 'punctuation.separator.clauses.erlang',
+                     regex: ';|(?=\\.)',
+                     next: 'pop' },
+                   { include: '#parenthesized-expression' },
+                   { include: '#internal-function-parts' } ] },
+              { include: '#everything-else' },
+              { defaultToken: 'meta.function.erlang' } ] } ],
+      '#function-call': 
+       [ { token: 'meta.function-call.erlang',
+           regex: '(?=(?:[a-z][a-zA-Z\\d@_]*|\'[^\']*\')\\s*(?:\\(|:\\s*(?:[a-z][a-zA-Z\\d@_]*|\'[^\']*\')\\s*\\())',
+           push: 
+            [ { token: 'punctuation.definition.parameters.end.erlang',
+                regex: '\\)',
+                next: 'pop' },
+              { token: 
+                 [ 'entity.name.type.class.module.erlang',
+                   'text',
+                   'punctuation.separator.module-function.erlang',
+                   'text',
+                   'entity.name.function.guard.erlang',
+                   'text',
+                   'punctuation.definition.parameters.begin.erlang' ],
+                regex: '(?:(erlang)(\\s*)(:)(\\s*))?(is_atom|is_binary|is_constant|is_float|is_function|is_integer|is_list|is_number|is_pid|is_port|is_reference|is_tuple|is_record|abs|element|hd|length|node|round|self|size|tl|trunc)(\\s*)(\\()',
+                push: 
+                 [ { token: 'text', regex: '(?=\\))', next: 'pop' },
+                   { token: 'punctuation.separator.parameters.erlang', regex: ',' },
+                   { include: '#everything-else' } ] },
+              { token: 
+                 [ 'entity.name.type.class.module.erlang',
+                   'text',
+                   'punctuation.separator.module-function.erlang',
+                   'text',
+                   'entity.name.function.erlang',
+                   'text',
+                   'punctuation.definition.parameters.begin.erlang' ],
+                regex: '(?:([a-z][a-zA-Z\\d@_]*|\'[^\']*\')(\\s*)(:)(\\s*))?([a-z][a-zA-Z\\d@_]*|\'[^\']*\')(\\s*)(\\()',
+                push: 
+                 [ { token: 'text', regex: '(?=\\))', next: 'pop' },
+                   { token: 'punctuation.separator.parameters.erlang', regex: ',' },
+                   { include: '#everything-else' } ] },
+              { defaultToken: 'meta.function-call.erlang' } ] } ],
+      '#import-export-directive': 
+       [ { token: 
+            [ 'meta.directive.import.erlang',
+              'punctuation.section.directive.begin.erlang',
+              'meta.directive.import.erlang',
+              'keyword.control.directive.import.erlang',
+              'meta.directive.import.erlang',
+              'punctuation.definition.parameters.begin.erlang',
+              'meta.directive.import.erlang',
+              'entity.name.type.class.module.erlang',
+              'meta.directive.import.erlang',
+              'punctuation.separator.parameters.erlang' ],
+           regex: '^(\\s*)(-)(\\s*)(import)(\\s*)(\\()(\\s*)([a-z][a-zA-Z\\d@_]*|\'[^\']*\')(\\s*)(,)',
+           push: 
+            [ { token: 
+                 [ 'punctuation.definition.parameters.end.erlang',
+                   'meta.directive.import.erlang',
+                   'punctuation.section.directive.end.erlang' ],
+                regex: '(\\))(\\s*)(\\.)',
+                next: 'pop' },
+              { include: '#internal-function-list' },
+              { defaultToken: 'meta.directive.import.erlang' } ] },
+         { token: 
+            [ 'meta.directive.export.erlang',
+              'punctuation.section.directive.begin.erlang',
+              'meta.directive.export.erlang',
+              'keyword.control.directive.export.erlang',
+              'meta.directive.export.erlang',
+              'punctuation.definition.parameters.begin.erlang' ],
+           regex: '^(\\s*)(-)(\\s*)(export)(\\s*)(\\()',
+           push: 
+            [ { token: 
+                 [ 'punctuation.definition.parameters.end.erlang',
+                   'meta.directive.export.erlang',
+                   'punctuation.section.directive.end.erlang' ],
+                regex: '(\\))(\\s*)(\\.)',
+                next: 'pop' },
+              { include: '#internal-function-list' },
+              { defaultToken: 'meta.directive.export.erlang' } ] } ],
+      '#internal-expression-punctuation': 
+       [ { token: 
+            [ 'punctuation.separator.clause-head-body.erlang',
+              'punctuation.separator.clauses.erlang',
+              'punctuation.separator.expressions.erlang' ],
+           regex: '(->)|(;)|(,)' } ],
+      '#internal-function-list': 
+       [ { token: 'punctuation.definition.list.begin.erlang',
+           regex: '\\[',
+           push: 
+            [ { token: 'punctuation.definition.list.end.erlang',
+                regex: '\\]',
+                next: 'pop' },
+              { token: 
+                 [ 'entity.name.function.erlang',
+                   'text',
+                   'punctuation.separator.function-arity.erlang' ],
+                regex: '([a-z][a-zA-Z\\d@_]*|\'[^\']*\')(\\s*)(/)',
+                push: 
+                 [ { token: 'punctuation.separator.list.erlang',
+                     regex: ',|(?=\\])',
+                     next: 'pop' },
+                   { include: '#everything-else' } ] },
+              { include: '#everything-else' },
+              { defaultToken: 'meta.structure.list.function.erlang' } ] } ],
+      '#internal-function-parts': 
+       [ { token: 'text',
+           regex: '(?=\\()',
+           push: 
+            [ { token: 'punctuation.separator.clause-head-body.erlang',
+                regex: '->',
+                next: 'pop' },
+              { token: 'punctuation.definition.parameters.begin.erlang',
+                regex: '\\(',
+                push: 
+                 [ { token: 'punctuation.definition.parameters.end.erlang',
+                     regex: '\\)',
+                     next: 'pop' },
+                   { token: 'punctuation.separator.parameters.erlang', regex: ',' },
+                   { include: '#everything-else' } ] },
+              { token: 'punctuation.separator.guards.erlang', regex: ',|;' },
+              { include: '#everything-else' } ] },
+         { token: 'punctuation.separator.expressions.erlang',
+           regex: ',' },
+         { include: '#everything-else' } ],
+      '#internal-record-body': 
+       [ { token: 'punctuation.definition.class.record.begin.erlang',
+           regex: '\\{',
+           push: 
+            [ { token: 'meta.structure.record.erlang',
+                regex: '(?=\\})',
+                next: 'pop' },
+              { token: 
+                 [ 'variable.other.field.erlang',
+                   'variable.language.omitted.field.erlang',
+                   'text',
+                   'keyword.operator.assignment.erlang' ],
+                regex: '(?:([a-z][a-zA-Z\\d@_]*|\'[^\']*\')|(_))(\\s*)(=|::)',
+                push: 
+                 [ { token: 'punctuation.separator.class.record.erlang',
+                     regex: ',|(?=\\})',
+                     next: 'pop' },
+                   { include: '#everything-else' } ] },
+              { token: 
+                 [ 'variable.other.field.erlang',
+                   'text',
+                   'punctuation.separator.class.record.erlang' ],
+                regex: '([a-z][a-zA-Z\\d@_]*|\'[^\']*\')(\\s*)((?:,)?)' },
+              { include: '#everything-else' },
+              { defaultToken: 'meta.structure.record.erlang' } ] } ],
+      '#internal-type-specifiers': 
+       [ { token: 'punctuation.separator.value-type.erlang',
+           regex: '/',
+           push: 
+            [ { token: 'text', regex: '(?=,|:|>>)', next: 'pop' },
+              { token: 
+                 [ 'storage.type.erlang',
+                   'storage.modifier.signedness.erlang',
+                   'storage.modifier.endianness.erlang',
+                   'storage.modifier.unit.erlang',
+                   'punctuation.separator.type-specifiers.erlang' ],
+                regex: '(integer|float|binary|bytes|bitstring|bits)|(signed|unsigned)|(big|little|native)|(unit)|(-)' } ] } ],
+      '#keyword': 
+       [ { token: 'keyword.control.erlang',
+           regex: '\\b(?:after|begin|case|catch|cond|end|fun|if|let|of|query|try|receive|when)\\b' } ],
+      '#list': 
+       [ { token: 'punctuation.definition.list.begin.erlang',
+           regex: '\\[',
+           push: 
+            [ { token: 'punctuation.definition.list.end.erlang',
+                regex: '\\]',
+                next: 'pop' },
+              { token: 'punctuation.separator.list.erlang',
+                regex: '\\||\\|\\||,' },
+              { include: '#everything-else' },
+              { defaultToken: 'meta.structure.list.erlang' } ] } ],
+      '#macro-directive': 
+       [ { token: 
+            [ 'meta.directive.ifdef.erlang',
+              'punctuation.section.directive.begin.erlang',
+              'meta.directive.ifdef.erlang',
+              'keyword.control.directive.ifdef.erlang',
+              'meta.directive.ifdef.erlang',
+              'punctuation.definition.parameters.begin.erlang',
+              'meta.directive.ifdef.erlang',
+              'entity.name.function.macro.erlang',
+              'meta.directive.ifdef.erlang',
+              'punctuation.definition.parameters.end.erlang',
+              'meta.directive.ifdef.erlang',
+              'punctuation.section.directive.end.erlang' ],
+           regex: '^(\\s*)(-)(\\s*)(ifdef)(\\s*)(\\()(\\s*)([a-zA-Z\\d@_]+)(\\s*)(\\))(\\s*)(\\.)' },
+         { token: 
+            [ 'meta.directive.ifndef.erlang',
+              'punctuation.section.directive.begin.erlang',
+              'meta.directive.ifndef.erlang',
+              'keyword.control.directive.ifndef.erlang',
+              'meta.directive.ifndef.erlang',
+              'punctuation.definition.parameters.begin.erlang',
+              'meta.directive.ifndef.erlang',
+              'entity.name.function.macro.erlang',
+              'meta.directive.ifndef.erlang',
+              'punctuation.definition.parameters.end.erlang',
+              'meta.directive.ifndef.erlang',
+              'punctuation.section.directive.end.erlang' ],
+           regex: '^(\\s*)(-)(\\s*)(ifndef)(\\s*)(\\()(\\s*)([a-zA-Z\\d@_]+)(\\s*)(\\))(\\s*)(\\.)' },
+         { token: 
+            [ 'meta.directive.undef.erlang',
+              'punctuation.section.directive.begin.erlang',
+              'meta.directive.undef.erlang',
+              'keyword.control.directive.undef.erlang',
+              'meta.directive.undef.erlang',
+              'punctuation.definition.parameters.begin.erlang',
+              'meta.directive.undef.erlang',
+              'entity.name.function.macro.erlang',
+              'meta.directive.undef.erlang',
+              'punctuation.definition.parameters.end.erlang',
+              'meta.directive.undef.erlang',
+              'punctuation.section.directive.end.erlang' ],
+           regex: '^(\\s*)(-)(\\s*)(undef)(\\s*)(\\()(\\s*)([a-zA-Z\\d@_]+)(\\s*)(\\))(\\s*)(\\.)' } ],
+      '#macro-usage': 
+       [ { token: 
+            [ 'keyword.operator.macro.erlang',
+              'meta.macro-usage.erlang',
+              'entity.name.function.macro.erlang' ],
+           regex: '(\\?\\??)(\\s*)([a-zA-Z\\d@_]+)' } ],
+      '#module-directive': 
+       [ { token: 
+            [ 'meta.directive.module.erlang',
+              'punctuation.section.directive.begin.erlang',
+              'meta.directive.module.erlang',
+              'keyword.control.directive.module.erlang',
+              'meta.directive.module.erlang',
+              'punctuation.definition.parameters.begin.erlang',
+              'meta.directive.module.erlang',
+              'entity.name.type.class.module.definition.erlang',
+              'meta.directive.module.erlang',
+              'punctuation.definition.parameters.end.erlang',
+              'meta.directive.module.erlang',
+              'punctuation.section.directive.end.erlang' ],
+           regex: '^(\\s*)(-)(\\s*)(module)(\\s*)(\\()(\\s*)([a-z][a-zA-Z\\d@_]*)(\\s*)(\\))(\\s*)(\\.)' } ],
+      '#number': 
+       [ { token: 'text',
+           regex: '(?=\\d)',
+           push: 
+            [ { token: 'text', regex: '(?!\\d)', next: 'pop' },
+              { token: 
+                 [ 'constant.numeric.float.erlang',
+                   'punctuation.separator.integer-float.erlang',
+                   'constant.numeric.float.erlang',
+                   'punctuation.separator.float-exponent.erlang' ],
+                regex: '(\\d+)(\\.)(\\d+)((?:[eE][\\+\\-]?\\d+)?)' },
+              { token: 
+                 [ 'constant.numeric.integer.binary.erlang',
+                   'punctuation.separator.base-integer.erlang',
+                   'constant.numeric.integer.binary.erlang' ],
+                regex: '(2)(#)([0-1]+)' },
+              { token: 
+                 [ 'constant.numeric.integer.base-3.erlang',
+                   'punctuation.separator.base-integer.erlang',
+                   'constant.numeric.integer.base-3.erlang' ],
+                regex: '(3)(#)([0-2]+)' },
+              { token: 
+                 [ 'constant.numeric.integer.base-4.erlang',
+                   'punctuation.separator.base-integer.erlang',
+                   'constant.numeric.integer.base-4.erlang' ],
+                regex: '(4)(#)([0-3]+)' },
+              { token: 
+                 [ 'constant.numeric.integer.base-5.erlang',
+                   'punctuation.separator.base-integer.erlang',
+                   'constant.numeric.integer.base-5.erlang' ],
+                regex: '(5)(#)([0-4]+)' },
+              { token: 
+                 [ 'constant.numeric.integer.base-6.erlang',
+                   'punctuation.separator.base-integer.erlang',
+                   'constant.numeric.integer.base-6.erlang' ],
+                regex: '(6)(#)([0-5]+)' },
+              { token: 
+                 [ 'constant.numeric.integer.base-7.erlang',
+                   'punctuation.separator.base-integer.erlang',
+                   'constant.numeric.integer.base-7.erlang' ],
+                regex: '(7)(#)([0-6]+)' },
+              { token: 
+                 [ 'constant.numeric.integer.octal.erlang',
+                   'punctuation.separator.base-integer.erlang',
+                   'constant.numeric.integer.octal.erlang' ],
+                regex: '(8)(#)([0-7]+)' },
+              { token: 
+                 [ 'constant.numeric.integer.base-9.erlang',
+                   'punctuation.separator.base-integer.erlang',
+                   'constant.numeric.integer.base-9.erlang' ],
+                regex: '(9)(#)([0-8]+)' },
+              { token: 
+                 [ 'constant.numeric.integer.decimal.erlang',
+                   'punctuation.separator.base-integer.erlang',
+                   'constant.numeric.integer.decimal.erlang' ],
+                regex: '(10)(#)(\\d+)' },
+              { token: 
+                 [ 'constant.numeric.integer.base-11.erlang',
+                   'punctuation.separator.base-integer.erlang',
+                   'constant.numeric.integer.base-11.erlang' ],
+                regex: '(11)(#)([\\daA]+)' },
+              { token: 
+                 [ 'constant.numeric.integer.base-12.erlang',
+                   'punctuation.separator.base-integer.erlang',
+                   'constant.numeric.integer.base-12.erlang' ],
+                regex: '(12)(#)([\\da-bA-B]+)' },
+              { token: 
+                 [ 'constant.numeric.integer.base-13.erlang',
+                   'punctuation.separator.base-integer.erlang',
+                   'constant.numeric.integer.base-13.erlang' ],
+                regex: '(13)(#)([\\da-cA-C]+)' },
+              { token: 
+                 [ 'constant.numeric.integer.base-14.erlang',
+                   'punctuation.separator.base-integer.erlang',
+                   'constant.numeric.integer.base-14.erlang' ],
+                regex: '(14)(#)([\\da-dA-D]+)' },
+              { token: 
+                 [ 'constant.numeric.integer.base-15.erlang',
+                   'punctuation.separator.base-integer.erlang',
+                   'constant.numeric.integer.base-15.erlang' ],
+                regex: '(15)(#)([\\da-eA-E]+)' },
+              { token: 
+                 [ 'constant.numeric.integer.hexadecimal.erlang',
+                   'punctuation.separator.base-integer.erlang',
+                   'constant.numeric.integer.hexadecimal.erlang' ],
+                regex: '(16)(#)([\\da-fA-F]+)' },
+              { token: 
+                 [ 'constant.numeric.integer.base-17.erlang',
+                   'punctuation.separator.base-integer.erlang',
+                   'constant.numeric.integer.base-17.erlang' ],
+                regex: '(17)(#)([\\da-gA-G]+)' },
+              { token: 
+                 [ 'constant.numeric.integer.base-18.erlang',
+                   'punctuation.separator.base-integer.erlang',
+                   'constant.numeric.integer.base-18.erlang' ],
+                regex: '(18)(#)([\\da-hA-H]+)' },
+              { token: 
+                 [ 'constant.numeric.integer.base-19.erlang',
+                   'punctuation.separator.base-integer.erlang',
+                   'constant.numeric.integer.base-19.erlang' ],
+                regex: '(19)(#)([\\da-iA-I]+)' },
+              { token: 
+                 [ 'constant.numeric.integer.base-20.erlang',
+                   'punctuation.separator.base-integer.erlang',
+                   'constant.numeric.integer.base-20.erlang' ],
+                regex: '(20)(#)([\\da-jA-J]+)' },
+              { token: 
+                 [ 'constant.numeric.integer.base-21.erlang',
+                   'punctuation.separator.base-integer.erlang',
+                   'constant.numeric.integer.base-21.erlang' ],
+                regex: '(21)(#)([\\da-kA-K]+)' },
+              { token: 
+                 [ 'constant.numeric.integer.base-22.erlang',
+                   'punctuation.separator.base-integer.erlang',
+                   'constant.numeric.integer.base-22.erlang' ],
+                regex: '(22)(#)([\\da-lA-L]+)' },
+              { token: 
+                 [ 'constant.numeric.integer.base-23.erlang',
+                   'punctuation.separator.base-integer.erlang',
+                   'constant.numeric.integer.base-23.erlang' ],
+                regex: '(23)(#)([\\da-mA-M]+)' },
+              { token: 
+                 [ 'constant.numeric.integer.base-24.erlang',
+                   'punctuation.separator.base-integer.erlang',
+                   'constant.numeric.integer.base-24.erlang' ],
+                regex: '(24)(#)([\\da-nA-N]+)' },
+              { token: 
+                 [ 'constant.numeric.integer.base-25.erlang',
+                   'punctuation.separator.base-integer.erlang',
+                   'constant.numeric.integer.base-25.erlang' ],
+                regex: '(25)(#)([\\da-oA-O]+)' },
+              { token: 
+                 [ 'constant.numeric.integer.base-26.erlang',
+                   'punctuation.separator.base-integer.erlang',
+                   'constant.numeric.integer.base-26.erlang' ],
+                regex: '(26)(#)([\\da-pA-P]+)' },
+              { token: 
+                 [ 'constant.numeric.integer.base-27.erlang',
+                   'punctuation.separator.base-integer.erlang',
+                   'constant.numeric.integer.base-27.erlang' ],
+                regex: '(27)(#)([\\da-qA-Q]+)' },
+              { token: 
+                 [ 'constant.numeric.integer.base-28.erlang',
+                   'punctuation.separator.base-integer.erlang',
+                   'constant.numeric.integer.base-28.erlang' ],
+                regex: '(28)(#)([\\da-rA-R]+)' },
+              { token: 
+                 [ 'constant.numeric.integer.base-29.erlang',
+                   'punctuation.separator.base-integer.erlang',
+                   'constant.numeric.integer.base-29.erlang' ],
+                regex: '(29)(#)([\\da-sA-S]+)' },
+              { token: 
+                 [ 'constant.numeric.integer.base-30.erlang',
+                   'punctuation.separator.base-integer.erlang',
+                   'constant.numeric.integer.base-30.erlang' ],
+                regex: '(30)(#)([\\da-tA-T]+)' },
+              { token: 
+                 [ 'constant.numeric.integer.base-31.erlang',
+                   'punctuation.separator.base-integer.erlang',
+                   'constant.numeric.integer.base-31.erlang' ],
+                regex: '(31)(#)([\\da-uA-U]+)' },
+              { token: 
+                 [ 'constant.numeric.integer.base-32.erlang',
+                   'punctuation.separator.base-integer.erlang',
+                   'constant.numeric.integer.base-32.erlang' ],
+                regex: '(32)(#)([\\da-vA-V]+)' },
+              { token: 
+                 [ 'constant.numeric.integer.base-33.erlang',
+                   'punctuation.separator.base-integer.erlang',
+                   'constant.numeric.integer.base-33.erlang' ],
+                regex: '(33)(#)([\\da-wA-W]+)' },
+              { token: 
+                 [ 'constant.numeric.integer.base-34.erlang',
+                   'punctuation.separator.base-integer.erlang',
+                   'constant.numeric.integer.base-34.erlang' ],
+                regex: '(34)(#)([\\da-xA-X]+)' },
+              { token: 
+                 [ 'constant.numeric.integer.base-35.erlang',
+                   'punctuation.separator.base-integer.erlang',
+                   'constant.numeric.integer.base-35.erlang' ],
+                regex: '(35)(#)([\\da-yA-Y]+)' },
+              { token: 
+                 [ 'constant.numeric.integer.base-36.erlang',
+                   'punctuation.separator.base-integer.erlang',
+                   'constant.numeric.integer.base-36.erlang' ],
+                regex: '(36)(#)([\\da-zA-Z]+)' },
+              { token: 'invalid.illegal.integer.erlang',
+                regex: '\\d+#[\\da-zA-Z]+' },
+              { token: 'constant.numeric.integer.decimal.erlang',
+                regex: '\\d+' } ] } ],
+      '#parenthesized-expression': 
+       [ { token: 'punctuation.section.expression.begin.erlang',
+           regex: '\\(',
+           push: 
+            [ { token: 'punctuation.section.expression.end.erlang',
+                regex: '\\)',
+                next: 'pop' },
+              { include: '#everything-else' },
+              { defaultToken: 'meta.expression.parenthesized' } ] } ],
+      '#record-directive': 
+       [ { token: 
+            [ 'meta.directive.record.erlang',
+              'punctuation.section.directive.begin.erlang',
+              'meta.directive.record.erlang',
+              'keyword.control.directive.import.erlang',
+              'meta.directive.record.erlang',
+              'punctuation.definition.parameters.begin.erlang',
+              'meta.directive.record.erlang',
+              'entity.name.type.class.record.definition.erlang',
+              'meta.directive.record.erlang',
+              'punctuation.separator.parameters.erlang' ],
+           regex: '^(\\s*)(-)(\\s*)(record)(\\s*)(\\()(\\s*)([a-z][a-zA-Z\\d@_]*|\'[^\']*\')(\\s*)(,)',
+           push: 
+            [ { token: 
+                 [ 'punctuation.definition.class.record.end.erlang',
+                   'meta.directive.record.erlang',
+                   'punctuation.definition.parameters.end.erlang',
+                   'meta.directive.record.erlang',
+                   'punctuation.section.directive.end.erlang' ],
+                regex: '(\\})(\\s*)(\\))(\\s*)(\\.)',
+                next: 'pop' },
+              { include: '#internal-record-body' },
+              { defaultToken: 'meta.directive.record.erlang' } ] } ],
+      '#record-usage': 
+       [ { token: 
+            [ 'keyword.operator.record.erlang',
+              'meta.record-usage.erlang',
+              'entity.name.type.class.record.erlang',
+              'meta.record-usage.erlang',
+              'punctuation.separator.record-field.erlang',
+              'meta.record-usage.erlang',
+              'variable.other.field.erlang' ],
+           regex: '(#)(\\s*)([a-z][a-zA-Z\\d@_]*|\'[^\']*\')(\\s*)(\\.)(\\s*)([a-z][a-zA-Z\\d@_]*|\'[^\']*\')' },
+         { token: 
+            [ 'keyword.operator.record.erlang',
+              'meta.record-usage.erlang',
+              'entity.name.type.class.record.erlang' ],
+           regex: '(#)(\\s*)([a-z][a-zA-Z\\d@_]*|\'[^\']*\')',
+           push: 
+            [ { token: 'punctuation.definition.class.record.end.erlang',
+                regex: '\\}',
+                next: 'pop' },
+              { include: '#internal-record-body' },
+              { defaultToken: 'meta.record-usage.erlang' } ] } ],
+      '#string': 
+       [ { token: 'punctuation.definition.string.begin.erlang',
+           regex: '"',
+           push: 
+            [ { token: 'punctuation.definition.string.end.erlang',
+                regex: '"',
+                next: 'pop' },
+              { token: 
+                 [ 'punctuation.definition.escape.erlang',
+                   'constant.character.escape.erlang',
+                   'punctuation.definition.escape.erlang',
+                   'constant.character.escape.erlang',
+                   'constant.character.escape.erlang' ],
+                regex: '(\\\\)(?:([bdefnrstv\\\\\'"])|(\\^)([@-_])|([0-7]{1,3}))' },
+              { token: 'invalid.illegal.string.erlang', regex: '\\\\\\^?.?' },
+              { token: 
+                 [ 'punctuation.definition.placeholder.erlang',
+                   'punctuation.separator.placeholder-parts.erlang',
+                   'constant.other.placeholder.erlang',
+                   'punctuation.separator.placeholder-parts.erlang',
+                   'punctuation.separator.placeholder-parts.erlang',
+                   'constant.other.placeholder.erlang',
+                   'punctuation.separator.placeholder-parts.erlang',
+                   'punctuation.separator.placeholder-parts.erlang',
+                   'punctuation.separator.placeholder-parts.erlang',
+                   'constant.other.placeholder.erlang',
+                   'constant.other.placeholder.erlang' ],
+                regex: '(~)(?:((?:\\-)?)(\\d+)|(\\*))?(?:(\\.)(?:(\\d+)|(\\*)))?(?:(\\.)(?:(\\*)|(.)))?([~cfegswpWPBX#bx\\+ni])' },
+              { token: 
+                 [ 'punctuation.definition.placeholder.erlang',
+                   'punctuation.separator.placeholder-parts.erlang',
+                   'constant.other.placeholder.erlang',
+                   'constant.other.placeholder.erlang' ],
+                regex: '(~)((?:\\*)?)((?:\\d+)?)([~du\\-#fsacl])' },
+              { token: 'invalid.illegal.string.erlang', regex: '~.?' },
+              { defaultToken: 'string.quoted.double.erlang' } ] } ],
+      '#symbolic-operator': 
+       [ { token: 'keyword.operator.symbolic.erlang',
+           regex: '\\+\\+|\\+|--|-|\\*|/=|/|=/=|=:=|==|=<|=|<-|<|>=|>|!|::' } ],
+      '#textual-operator': 
+       [ { token: 'keyword.operator.textual.erlang',
+           regex: '\\b(?:andalso|band|and|bxor|xor|bor|orelse|or|bnot|not|bsl|bsr|div|rem)\\b' } ],
+      '#tuple': 
+       [ { token: 'punctuation.definition.tuple.begin.erlang',
+           regex: '\\{',
+           push: 
+            [ { token: 'punctuation.definition.tuple.end.erlang',
+                regex: '\\}',
+                next: 'pop' },
+              { token: 'punctuation.separator.tuple.erlang', regex: ',' },
+              { include: '#everything-else' },
+              { defaultToken: 'meta.structure.tuple.erlang' } ] } ],
+      '#variable': 
+       [ { token: [ 'variable.other.erlang', 'variable.language.omitted.erlang' ],
+           regex: '(_[a-zA-Z\\d@_]+|[A-Z][a-zA-Z\\d@_]*)|(_)' } ] };
+    
+    this.normalizeRules();
+};
+
+ErlangHighlightRules.metaData = { comment: 'The recognition of function definitions and compiler directives (such as module, record and macro definitions) requires that each of the aforementioned constructs must be the first string inside a line (except for whitespace).  Also, the function/module/record/macro names must be given unquoted.  -- desp',
+      fileTypes: [ 'erl', 'hrl' ],
+      keyEquivalent: '^~E',
+      name: 'Erlang',
+      scopeName: 'source.erlang' };
+
+
+oop.inherits(ErlangHighlightRules, TextHighlightRules);
+
+exports.ErlangHighlightRules = ErlangHighlightRules;
+});
+
+ace.define("ace/mode/folding/cstyle",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Range = require("../../range").Range;
+var BaseFoldMode = require("./fold_mode").FoldMode;
+
+var FoldMode = exports.FoldMode = function(commentRegex) {
+    if (commentRegex) {
+        this.foldingStartMarker = new RegExp(
+            this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start)
+        );
+        this.foldingStopMarker = new RegExp(
+            this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end)
+        );
+    }
+};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+    
+    this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/;
+    this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/;
+    this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/;
+    this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/;
+    this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/;
+    this._getFoldWidgetBase = this.getFoldWidget;
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+    
+        if (this.singleLineBlockCommentRe.test(line)) {
+            if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line))
+                return "";
+        }
+    
+        var fw = this._getFoldWidgetBase(session, foldStyle, row);
+    
+        if (!fw && this.startRegionRe.test(line))
+            return "start"; // lineCommentRegionStart
+    
+        return fw;
+    };
+
+    this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) {
+        var line = session.getLine(row);
+        
+        if (this.startRegionRe.test(line))
+            return this.getCommentRegionBlock(session, line, row);
+        
+        var match = line.match(this.foldingStartMarker);
+        if (match) {
+            var i = match.index;
+
+            if (match[1])
+                return this.openingBracketBlock(session, match[1], row, i);
+                
+            var range = session.getCommentFoldRange(row, i + match[0].length, 1);
+            
+            if (range && !range.isMultiLine()) {
+                if (forceMultiline) {
+                    range = this.getSectionRange(session, row);
+                } else if (foldStyle != "all")
+                    range = null;
+            }
+            
+            return range;
+        }
+
+        if (foldStyle === "markbegin")
+            return;
+
+        var match = line.match(this.foldingStopMarker);
+        if (match) {
+            var i = match.index + match[0].length;
+
+            if (match[1])
+                return this.closingBracketBlock(session, match[1], row, i);
+
+            return session.getCommentFoldRange(row, i, -1);
+        }
+    };
+    
+    this.getSectionRange = function(session, row) {
+        var line = session.getLine(row);
+        var startIndent = line.search(/\S/);
+        var startRow = row;
+        var startColumn = line.length;
+        row = row + 1;
+        var endRow = row;
+        var maxRow = session.getLength();
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var indent = line.search(/\S/);
+            if (indent === -1)
+                continue;
+            if  (startIndent > indent)
+                break;
+            var subRange = this.getFoldWidgetRange(session, "all", row);
+            
+            if (subRange) {
+                if (subRange.start.row <= startRow) {
+                    break;
+                } else if (subRange.isMultiLine()) {
+                    row = subRange.end.row;
+                } else if (startIndent == indent) {
+                    break;
+                }
+            }
+            endRow = row;
+        }
+        
+        return new Range(startRow, startColumn, endRow, session.getLine(endRow).length);
+    };
+    this.getCommentRegionBlock = function(session, line, row) {
+        var startColumn = line.search(/\s*$/);
+        var maxRow = session.getLength();
+        var startRow = row;
+        
+        var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/;
+        var depth = 1;
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var m = re.exec(line);
+            if (!m) continue;
+            if (m[1]) depth--;
+            else depth++;
+
+            if (!depth) break;
+        }
+
+        var endRow = row;
+        if (endRow > startRow) {
+            return new Range(startRow, startColumn, endRow, line.length);
+        }
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/erlang",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var ErlangHighlightRules = require("./erlang_highlight_rules").ErlangHighlightRules;
+var FoldMode = require("./folding/cstyle").FoldMode;
+
+var Mode = function() {
+    this.HighlightRules = ErlangHighlightRules;
+    this.foldingRules = new FoldMode();
+    this.$behaviour = this.$defaultBehaviour;
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+    this.lineCommentStart = "%";
+    this.blockComment = null;
+    this.$id = "ace/mode/erlang";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/erlang"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 298 - 0
services/web/public/js/ace-1.4.3/mode-forth.js

@@ -0,0 +1,298 @@
+ace.define("ace/mode/forth_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var ForthHighlightRules = function() {
+
+    this.$rules = { start: [ { include: '#forth' } ],
+      '#comment':
+       [ { token: 'comment.line.double-dash.forth',
+           regex: '(?:^|\\s)--\\s.*$',
+           comment: 'line comments for iForth' },
+         { token: 'comment.line.backslash.forth',
+           regex: '(?:^|\\s)\\\\[\\s\\S]*$',
+           comment: 'ANSI line comment' },
+         { token: 'comment.line.backslash-g.forth',
+           regex: '(?:^|\\s)\\\\[Gg] .*$',
+           comment: 'gForth line comment' },
+         { token: 'comment.block.forth',
+           regex: '(?:^|\\s)\\(\\*(?=\\s|$)',
+           push:
+            [ { token: 'comment.block.forth',
+                regex: '(?:^|\\s)\\*\\)(?=\\s|$)',
+                next: 'pop' },
+              { defaultToken: 'comment.block.forth' } ],
+           comment: 'multiline comments for iForth' },
+         { token: 'comment.block.documentation.forth',
+           regex: '\\bDOC\\b',
+           caseInsensitive: true,
+           push:
+            [ { token: 'comment.block.documentation.forth',
+                regex: '\\bENDDOC\\b',
+                caseInsensitive: true,
+                next: 'pop' },
+              { defaultToken: 'comment.block.documentation.forth' } ],
+           comment: 'documentation comments for iForth' },
+         { token: 'comment.line.parentheses.forth',
+           regex: '(?:^|\\s)\\.?\\( [^)]*\\)',
+           comment: 'ANSI line comment' } ],
+      '#constant':
+       [ { token: 'constant.language.forth',
+           regex: '(?:^|\\s)(?:TRUE|FALSE|BL|PI|CELL|C/L|R/O|W/O|R/W)(?=\\s|$)',
+           caseInsensitive: true},
+         { token: 'constant.numeric.forth',
+           regex: '(?:^|\\s)[$#%]?[-+]?[0-9]+(?:\\.[0-9]*e-?[0-9]+|\\.?[0-9a-fA-F]*)(?=\\s|$)'},
+         { token: 'constant.character.forth',
+           regex: '(?:^|\\s)(?:[&^]\\S|(?:"|\')\\S(?:"|\'))(?=\\s|$)'}],
+      '#forth':
+       [ { include: '#constant' },
+         { include: '#comment' },
+         { include: '#string' },
+         { include: '#word' },
+         { include: '#variable' },
+         { include: '#storage' },
+         { include: '#word-def' } ],
+      '#storage':
+       [ { token: 'storage.type.forth',
+           regex: '(?:^|\\s)(?:2CONSTANT|2VARIABLE|ALIAS|CONSTANT|CREATE-INTERPRET/COMPILE[:]?|CREATE|DEFER|FCONSTANT|FIELD|FVARIABLE|USER|VALUE|VARIABLE|VOCABULARY)(?=\\s|$)',
+           caseInsensitive: true}],
+      '#string':
+       [ { token: 'string.quoted.double.forth',
+           regex: '(ABORT" |BREAK" |\\." |C" |0"|S\\\\?" )([^"]+")',
+           caseInsensitive: true},
+         { token: 'string.unquoted.forth',
+           regex: '(?:INCLUDE|NEEDS|REQUIRE|USE)[ ]\\S+(?=\\s|$)',
+           caseInsensitive: true}],
+      '#variable':
+       [ { token: 'variable.language.forth',
+           regex: '\\b(?:I|J)\\b',
+           caseInsensitive: true } ],
+      '#word':
+       [ { token: 'keyword.control.immediate.forth',
+           regex: '(?:^|\\s)\\[(?:\\?DO|\\+LOOP|AGAIN|BEGIN|DEFINED|DO|ELSE|ENDIF|FOR|IF|IFDEF|IFUNDEF|LOOP|NEXT|REPEAT|THEN|UNTIL|WHILE)\\](?=\\s|$)',
+           caseInsensitive: true},
+         { token: 'keyword.other.immediate.forth',
+           regex: '(?:^|\\s)(?:COMPILE-ONLY|IMMEDIATE|IS|RESTRICT|TO|WHAT\'S|])(?=\\s|$)',
+           caseInsensitive: true},
+         { token: 'keyword.control.compile-only.forth',
+           regex: '(?:^|\\s)(?:-DO|\\-LOOP|\\?DO|\\?LEAVE|\\+DO|\\+LOOP|ABORT\\"|AGAIN|AHEAD|BEGIN|CASE|DO|ELSE|ENDCASE|ENDIF|ENDOF|ENDTRY\\-IFERROR|ENDTRY|FOR|IF|IFERROR|LEAVE|LOOP|NEXT|RECOVER|REPEAT|RESTORE|THEN|TRY|U\\-DO|U\\+DO|UNTIL|WHILE)(?=\\s|$)',
+           caseInsensitive: true},
+         { token: 'keyword.other.compile-only.forth',
+           regex: '(?:^|\\s)(?:\\?DUP-0=-IF|\\?DUP-IF|\\)|\\[|\\[\'\\]|\\[CHAR\\]|\\[COMPILE\\]|\\[IS\\]|\\[TO\\]|<COMPILATION|<INTERPRETATION|ASSERT\\(|ASSERT0\\(|ASSERT1\\(|ASSERT2\\(|ASSERT3\\(|COMPILATION>|DEFERS|DOES>|INTERPRETATION>|OF|POSTPONE)(?=\\s|$)',
+           caseInsensitive: true},
+         { token: 'keyword.other.non-immediate.forth',
+           regex: '(?:^|\\s)(?:\'|<IS>|<TO>|CHAR|END-STRUCT|INCLUDE[D]?|LOAD|NEEDS|REQUIRE[D]?|REVISION|SEE|STRUCT|THRU|USE)(?=\\s|$)',
+           caseInsensitive: true},
+         { token: 'keyword.other.warning.forth',
+           regex: '(?:^|\\s)(?:~~|BREAK:|BREAK"|DBG)(?=\\s|$)',
+           caseInsensitive: true}],
+      '#word-def':
+       [ { token:
+            [ 'keyword.other.compile-only.forth',
+              'keyword.other.compile-only.forth',
+              'meta.block.forth',
+              'entity.name.function.forth' ],
+           regex: '(:NONAME)|(^:|\\s:)(\\s)(\\S+)(?=\\s|$)',
+           caseInsensitive: true,
+           push:
+            [ { token: 'keyword.other.compile-only.forth',
+                regex: ';(?:CODE)?',
+                caseInsensitive: true,
+                next: 'pop' },
+              { include: '#constant' },
+              { include: '#comment' },
+              { include: '#string' },
+              { include: '#word' },
+              { include: '#variable' },
+              { include: '#storage' },
+              { defaultToken: 'meta.block.forth' } ] } ] };
+    
+    this.normalizeRules();
+};
+
+ForthHighlightRules.metaData = { fileTypes: [ 'frt', 'fs', 'ldr', 'fth', '4th' ],
+      foldingStartMarker: '/\\*\\*|\\{\\s*$',
+      foldingStopMarker: '\\*\\*/|^\\s*\\}',
+      keyEquivalent: '^~F',
+      name: 'Forth',
+      scopeName: 'source.forth' };
+
+
+oop.inherits(ForthHighlightRules, TextHighlightRules);
+
+exports.ForthHighlightRules = ForthHighlightRules;
+});
+
+ace.define("ace/mode/folding/cstyle",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Range = require("../../range").Range;
+var BaseFoldMode = require("./fold_mode").FoldMode;
+
+var FoldMode = exports.FoldMode = function(commentRegex) {
+    if (commentRegex) {
+        this.foldingStartMarker = new RegExp(
+            this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start)
+        );
+        this.foldingStopMarker = new RegExp(
+            this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end)
+        );
+    }
+};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+    
+    this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/;
+    this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/;
+    this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/;
+    this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/;
+    this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/;
+    this._getFoldWidgetBase = this.getFoldWidget;
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+    
+        if (this.singleLineBlockCommentRe.test(line)) {
+            if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line))
+                return "";
+        }
+    
+        var fw = this._getFoldWidgetBase(session, foldStyle, row);
+    
+        if (!fw && this.startRegionRe.test(line))
+            return "start"; // lineCommentRegionStart
+    
+        return fw;
+    };
+
+    this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) {
+        var line = session.getLine(row);
+        
+        if (this.startRegionRe.test(line))
+            return this.getCommentRegionBlock(session, line, row);
+        
+        var match = line.match(this.foldingStartMarker);
+        if (match) {
+            var i = match.index;
+
+            if (match[1])
+                return this.openingBracketBlock(session, match[1], row, i);
+                
+            var range = session.getCommentFoldRange(row, i + match[0].length, 1);
+            
+            if (range && !range.isMultiLine()) {
+                if (forceMultiline) {
+                    range = this.getSectionRange(session, row);
+                } else if (foldStyle != "all")
+                    range = null;
+            }
+            
+            return range;
+        }
+
+        if (foldStyle === "markbegin")
+            return;
+
+        var match = line.match(this.foldingStopMarker);
+        if (match) {
+            var i = match.index + match[0].length;
+
+            if (match[1])
+                return this.closingBracketBlock(session, match[1], row, i);
+
+            return session.getCommentFoldRange(row, i, -1);
+        }
+    };
+    
+    this.getSectionRange = function(session, row) {
+        var line = session.getLine(row);
+        var startIndent = line.search(/\S/);
+        var startRow = row;
+        var startColumn = line.length;
+        row = row + 1;
+        var endRow = row;
+        var maxRow = session.getLength();
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var indent = line.search(/\S/);
+            if (indent === -1)
+                continue;
+            if  (startIndent > indent)
+                break;
+            var subRange = this.getFoldWidgetRange(session, "all", row);
+            
+            if (subRange) {
+                if (subRange.start.row <= startRow) {
+                    break;
+                } else if (subRange.isMultiLine()) {
+                    row = subRange.end.row;
+                } else if (startIndent == indent) {
+                    break;
+                }
+            }
+            endRow = row;
+        }
+        
+        return new Range(startRow, startColumn, endRow, session.getLine(endRow).length);
+    };
+    this.getCommentRegionBlock = function(session, line, row) {
+        var startColumn = line.search(/\s*$/);
+        var maxRow = session.getLength();
+        var startRow = row;
+        
+        var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/;
+        var depth = 1;
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var m = re.exec(line);
+            if (!m) continue;
+            if (m[1]) depth--;
+            else depth++;
+
+            if (!depth) break;
+        }
+
+        var endRow = row;
+        if (endRow > startRow) {
+            return new Range(startRow, startColumn, endRow, line.length);
+        }
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/forth",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var ForthHighlightRules = require("./forth_highlight_rules").ForthHighlightRules;
+var FoldMode = require("./folding/cstyle").FoldMode;
+
+var Mode = function() {
+    this.HighlightRules = ForthHighlightRules;
+    this.foldingRules = new FoldMode();
+    this.$behaviour = this.$defaultBehaviour;
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+    this.lineCommentStart = "--";
+    this.blockComment = null;
+    this.$id = "ace/mode/forth";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/forth"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 431 - 0
services/web/public/js/ace-1.4.3/mode-fortran.js

@@ -0,0 +1,431 @@
+ace.define("ace/mode/fortran_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var FortranHighlightRules = function() {
+
+    var keywords = (
+        "call|case|contains|continue|cycle|do|else|elseif|end|enddo|endif|function|"+ 
+        "if|implicit|in|include|inout|intent|module|none|only|out|print|program|return|"+ 
+        "select|status|stop|subroutine|" +
+        "return|then|use|while|write|"+
+        "CALL|CASE|CONTAINS|CONTINUE|CYCLE|DO|ELSE|ELSEIF|END|ENDDO|ENDIF|FUNCTION|"+
+        "IF|IMPLICIT|IN|INCLUDE|INOUT|INTENT|MODULE|NONE|ONLY|OUT|PRINT|PROGRAM|RETURN|"+
+        "SELECT|STATUS|STOP|SUBROUTINE|" +
+        "RETURN|THEN|USE|WHILE|WRITE"
+    );
+
+    var keywordOperators = (
+        "and|or|not|eq|ne|gt|ge|lt|le|" +
+        "AND|OR|NOT|EQ|NE|GT|GE|LT|LE" 
+    );
+
+    var builtinConstants = (
+        "true|false|TRUE|FALSE"
+    );
+
+    var builtinFunctions = (
+        "abs|achar|acos|acosh|adjustl|adjustr|aimag|aint|all|allocate|"+
+        "anint|any|asin|asinh|associated|atan|atan2|atanh|"+
+        "bessel_j0|bessel_j1|bessel_jn|bessel_y0|bessel_y1|bessel_yn|"+
+        "bge|bgt|bit_size|ble|blt|btest|ceiling|char|cmplx|conjg|cos|cosh|"+
+        "count|cpu_time|cshift|date_and_time|dble|deallocate|digits|dim|dot_product|dprod|"+
+        "dshiftl|dshiftr|dsqrt|eoshift|epsilon|erf|erfc|erfc_scaled|exp|float|floor|"+
+        "format|fraction|gamma|input|len|lge|lgt|lle|llt|log|log10|maskl|maskr|matmul|max|maxloc|maxval|"+
+        "merge|min|minloc|minval|mod|modulo|nint|not|norm2|null|nullify|pack|parity|popcnt|poppar|"+
+        "precision|present|product|radix|random_number|random_seed|range|repeat|reshape|round|"+
+        "rrspacing|same_type_as|scale|scan|selected_char_kind|selected_int_kind|selected_real_kind|"+
+        "set_exponent|shape|shifta|shiftl|shiftr|sign|sin|sinh|size|sngl|spacing|spread|"+
+        "sqrt|sum|system_clock|tan|tanh|tiny|trailz|transfer|transpose|trim|ubound|unpack|verify|" +
+        "ABS|ACHAR|ACOS|ACOSH|ADJUSTL|ADJUSTR|AIMAG|AINT|ALL|ALLOCATE|"+
+        "ANINT|ANY|ASIN|ASINH|ASSOCIATED|ATAN|ATAN2|ATANH|"+
+        "BESSEL_J0|BESSEL_J1|BESSEL_JN|BESSEL_Y0|BESSEL_Y1|BESSEL_YN|"+
+        "BGE|BGT|BIT_SIZE|BLE|BLT|BTEST|CEILING|CHAR|CMPLX|CONJG|COS|COSH|"+
+        "COUNT|CPU_TIME|CSHIFT|DATE_AND_TIME|DBLE|DEALLOCATE|DIGITS|DIM|DOT_PRODUCT|DPROD|"+
+        "DSHIFTL|DSHIFTR|DSQRT|EOSHIFT|EPSILON|ERF|ERFC|ERFC_SCALED|EXP|FLOAT|FLOOR|"+
+        "FORMAT|FRACTION|GAMMA|INPUT|LEN|LGE|LGT|LLE|LLT|LOG|LOG10|MASKL|MASKR|MATMUL|MAX|MAXLOC|MAXVAL|"+
+        "MERGE|MIN|MINLOC|MINVAL|MOD|MODULO|NINT|NOT|NORM2|NULL|NULLIFY|PACK|PARITY|POPCNT|POPPAR|"+
+        "PRECISION|PRESENT|PRODUCT|RADIX|RANDOM_NUMBER|RANDOM_SEED|RANGE|REPEAT|RESHAPE|ROUND|"+
+        "RRSPACING|SAME_TYPE_AS|SCALE|SCAN|SELECTED_CHAR_KIND|SELECTED_INT_KIND|SELECTED_REAL_KIND|"+
+        "SET_EXPONENT|SHAPE|SHIFTA|SHIFTL|SHIFTR|SIGN|SIN|SINH|SIZE|SNGL|SPACING|SPREAD|"+
+        "SQRT|SUM|SYSTEM_CLOCK|TAN|TANH|TINY|TRAILZ|TRANSFER|TRANSPOSE|TRIM|UBOUND|UNPACK|VERIFY"
+    );
+
+    var storageType = (
+        "logical|character|integer|real|type|" +
+        "LOGICAL|CHARACTER|INTEGER|REAL|TYPE"    
+    );
+
+    var storageModifiers = ( 
+        "allocatable|dimension|intent|parameter|pointer|target|private|public|" +
+        "ALLOCATABLE|DIMENSION|INTENT|PARAMETER|POINTER|TARGET|PRIVATE|PUBLIC"
+    );
+
+    var keywordMapper = this.createKeywordMapper({
+        "invalid.deprecated": "debugger",
+        "support.function": builtinFunctions,
+        "constant.language": builtinConstants,
+        "keyword": keywords,
+        "keyword.operator": keywordOperators,
+        "storage.type": storageType,
+        "storage.modifier" : storageModifiers
+    }, "identifier");
+
+    var strPre = "(?:r|u|ur|R|U|UR|Ur|uR)?";
+
+    var decimalInteger = "(?:(?:[1-9]\\d*)|(?:0))";
+    var octInteger = "(?:0[oO]?[0-7]+)";
+    var hexInteger = "(?:0[xX][\\dA-Fa-f]+)";
+    var binInteger = "(?:0[bB][01]+)";
+    var integer = "(?:" + decimalInteger + "|" + octInteger + "|" + hexInteger + "|" + binInteger + ")";
+
+    var exponent = "(?:[eE][+-]?\\d+)";
+    var fraction = "(?:\\.\\d+)";
+    var intPart = "(?:\\d+)";
+    var pointFloat = "(?:(?:" + intPart + "?" + fraction + ")|(?:" + intPart + "\\.))";
+    var exponentFloat = "(?:(?:" + pointFloat + "|" +  intPart + ")" + exponent + ")";
+    var floatNumber = "(?:" + exponentFloat + "|" + pointFloat + ")";
+
+    var stringEscape =  "\\\\(x[0-9A-Fa-f]{2}|[0-7]{3}|[\\\\abfnrtv'\"]|U[0-9A-Fa-f]{8}|u[0-9A-Fa-f]{4})";
+
+    this.$rules = {
+        "start" : [ {
+            token : "comment",
+            regex : "!.*$"
+        }, {
+            token : "string",           // multi line """ string start
+            regex : strPre + '"{3}',
+            next : "qqstring3"
+        }, {
+            token : "string",           // " string
+            regex : strPre + '"(?=.)',
+            next : "qqstring"
+        }, {
+            token : "string",           // multi line ''' string start
+            regex : strPre + "'{3}",
+            next : "qstring3"
+        }, {
+            token : "string",           // ' string
+            regex : strPre + "'(?=.)",
+            next : "qstring"
+        }, {
+            token : "constant.numeric", // imaginary
+            regex : "(?:" + floatNumber + "|\\d+)[jJ]\\b"
+        }, {
+            token : "constant.numeric", // float
+            regex : floatNumber
+        }, {
+            token : "constant.numeric", // long integer
+            regex : integer + "[lL]\\b"
+        }, {
+            token : "constant.numeric", // integer
+            regex : integer + "\\b"
+        }, {
+            token : "keyword", // pre-compiler directives
+            regex : "#\\s*(?:include|import|define|undef|INCLUDE|IMPORT|DEFINE|UNDEF)\\b"
+        }, {
+            token : "keyword", // special case pre-compiler directive
+            regex : "#\\s*(?:endif|ifdef|else|elseif|ifndef|ENDIF|IFDEF|ELSE|ELSEIF|IFNDEF)\\b"
+        }, {
+            token : keywordMapper,
+            regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
+        }, {
+            token : "keyword.operator",
+            regex : "\\+|\\-|\\*|\\*\\*|\\/|\\/\\/|%|<<|>>|&|\\||\\^|~|<|>|<=|=>|==|!=|<>|="
+        }, {
+            token : "paren.lparen",
+            regex : "[\\[\\(\\{]"
+        }, {
+            token : "paren.rparen",
+            regex : "[\\]\\)\\}]"
+        }, {
+            token : "text",
+            regex : "\\s+"
+        } ],
+        "qqstring3" : [ {
+            token : "constant.language.escape",
+            regex : stringEscape
+        }, {
+            token : "string", // multi line """ string end
+            regex : '"{3}',
+            next : "start"
+        }, {
+            defaultToken : "string"
+        } ],
+        "qstring3" : [ {
+            token : "constant.language.escape",
+            regex : stringEscape
+        }, {
+            token : "string", // multi line """ string end
+            regex : '"{3}',
+            next : "start"
+        }, {
+            defaultToken : "string"
+        } ],
+        "qqstring" : [{
+            token : "constant.language.escape",
+            regex : stringEscape
+        }, {
+            token : "string",
+            regex : "\\\\$",
+            next  : "qqstring"
+        }, {
+            token : "string",
+            regex : '"|$',
+            next  : "start"
+        }, {
+            defaultToken: "string"
+        }],
+        "qstring" : [{
+            token : "constant.language.escape",
+            regex : stringEscape
+        }, {
+            token : "string",
+            regex : "\\\\$",
+            next  : "qstring"
+        }, {
+            token : "string",
+            regex : "'|$",
+            next  : "start"
+        }, {
+            defaultToken: "string"
+        }]
+    };
+};
+
+oop.inherits(FortranHighlightRules, TextHighlightRules);
+
+exports.FortranHighlightRules = FortranHighlightRules;
+});
+
+ace.define("ace/mode/folding/cstyle",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Range = require("../../range").Range;
+var BaseFoldMode = require("./fold_mode").FoldMode;
+
+var FoldMode = exports.FoldMode = function(commentRegex) {
+    if (commentRegex) {
+        this.foldingStartMarker = new RegExp(
+            this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start)
+        );
+        this.foldingStopMarker = new RegExp(
+            this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end)
+        );
+    }
+};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+    
+    this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/;
+    this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/;
+    this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/;
+    this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/;
+    this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/;
+    this._getFoldWidgetBase = this.getFoldWidget;
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+    
+        if (this.singleLineBlockCommentRe.test(line)) {
+            if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line))
+                return "";
+        }
+    
+        var fw = this._getFoldWidgetBase(session, foldStyle, row);
+    
+        if (!fw && this.startRegionRe.test(line))
+            return "start"; // lineCommentRegionStart
+    
+        return fw;
+    };
+
+    this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) {
+        var line = session.getLine(row);
+        
+        if (this.startRegionRe.test(line))
+            return this.getCommentRegionBlock(session, line, row);
+        
+        var match = line.match(this.foldingStartMarker);
+        if (match) {
+            var i = match.index;
+
+            if (match[1])
+                return this.openingBracketBlock(session, match[1], row, i);
+                
+            var range = session.getCommentFoldRange(row, i + match[0].length, 1);
+            
+            if (range && !range.isMultiLine()) {
+                if (forceMultiline) {
+                    range = this.getSectionRange(session, row);
+                } else if (foldStyle != "all")
+                    range = null;
+            }
+            
+            return range;
+        }
+
+        if (foldStyle === "markbegin")
+            return;
+
+        var match = line.match(this.foldingStopMarker);
+        if (match) {
+            var i = match.index + match[0].length;
+
+            if (match[1])
+                return this.closingBracketBlock(session, match[1], row, i);
+
+            return session.getCommentFoldRange(row, i, -1);
+        }
+    };
+    
+    this.getSectionRange = function(session, row) {
+        var line = session.getLine(row);
+        var startIndent = line.search(/\S/);
+        var startRow = row;
+        var startColumn = line.length;
+        row = row + 1;
+        var endRow = row;
+        var maxRow = session.getLength();
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var indent = line.search(/\S/);
+            if (indent === -1)
+                continue;
+            if  (startIndent > indent)
+                break;
+            var subRange = this.getFoldWidgetRange(session, "all", row);
+            
+            if (subRange) {
+                if (subRange.start.row <= startRow) {
+                    break;
+                } else if (subRange.isMultiLine()) {
+                    row = subRange.end.row;
+                } else if (startIndent == indent) {
+                    break;
+                }
+            }
+            endRow = row;
+        }
+        
+        return new Range(startRow, startColumn, endRow, session.getLine(endRow).length);
+    };
+    this.getCommentRegionBlock = function(session, line, row) {
+        var startColumn = line.search(/\s*$/);
+        var maxRow = session.getLength();
+        var startRow = row;
+        
+        var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/;
+        var depth = 1;
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var m = re.exec(line);
+            if (!m) continue;
+            if (m[1]) depth--;
+            else depth++;
+
+            if (!depth) break;
+        }
+
+        var endRow = row;
+        if (endRow > startRow) {
+            return new Range(startRow, startColumn, endRow, line.length);
+        }
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/fortran",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var FortranHighlightRules = require("./fortran_highlight_rules").FortranHighlightRules;
+var CStyleFoldMode = require("./folding/cstyle").FoldMode;
+var Range = require("../range").Range;
+
+var Mode = function() {
+    this.HighlightRules = FortranHighlightRules;
+    this.foldingRules = new CStyleFoldMode();
+    this.$behaviour = this.$defaultBehaviour;
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+
+    this.lineCommentStart = "!";
+
+    this.getNextLineIndent = function(state, line, tab) {
+        var indent = this.$getIndent(line);
+
+        var tokenizedLine = this.getTokenizer().getLineTokens(line, state);
+        var tokens = tokenizedLine.tokens;
+
+        if (tokens.length && tokens[tokens.length-1].type == "comment") {
+            return indent;
+        }
+
+        if (state == "start") {
+            var match = line.match(/^.*[\{\(\[:]\s*$/);
+            if (match) {
+                indent += tab;
+            }
+        }
+
+        return indent;
+    };
+
+    var outdents = {
+        "return": 1,
+        "break": 1,
+        "continue": 1,
+        "RETURN": 1,
+        "BREAK": 1,
+        "CONTINUE": 1
+    };
+
+    this.checkOutdent = function(state, line, input) {
+        if (input !== "\r\n" && input !== "\r" && input !== "\n")
+            return false;
+
+        var tokens = this.getTokenizer().getLineTokens(line.trim(), state).tokens;
+
+        if (!tokens)
+            return false;
+        do {
+            var last = tokens.pop();
+        } while (last && (last.type == "comment" || (last.type == "text" && last.value.match(/^\s+$/))));
+
+        if (!last)
+            return false;
+
+        return (last.type == "keyword" && outdents[last.value]);
+    };
+
+    this.autoOutdent = function(state, doc, row) {
+
+        row += 1;
+        var indent = this.$getIndent(doc.getLine(row));
+        var tab = doc.getTabString();
+        if (indent.slice(-tab.length) == tab)
+            doc.remove(new Range(row, indent.length-tab.length, row, indent.length));
+    };
+
+    this.$id = "ace/mode/fortran";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/fortran"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 317 - 0
services/web/public/js/ace-1.4.3/mode-fsharp.js

@@ -0,0 +1,317 @@
+ace.define("ace/mode/fsharp_highlight_rules",[], function (require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+var FSharpHighlightRules = function () {
+
+    var keywordMapper = this.createKeywordMapper({
+        "variable": "this",
+        "keyword": 'abstract|assert|base|begin|class|default|delegate|done|downcast|downto|elif\
+|else|exception|extern|false|finally|function|global|inherit|inline|interface|internal|lazy|match\
+|member|module|mutable|namespace|open|or|override|private|public|rec|return|return!|select|static\
+|struct|then|to|true|try|typeof|upcast|use|use!|val|void|when|while|with|yield|yield!|__SOURCE_DIRECTORY__\
+|as|asr|land|lor|lsl|lsr|lxor|mod|sig|atomic|break|checked|component|const|constraint|constructor|continue\
+|eager|event|external|fixed|functor|include|method|mixin|object|parallel|process|protected|pure|sealed|tailcall\
+|trait|virtual|volatile|and|do|end|for|fun|if|in|let|let!|new|not|null|of|endif',
+        "constant": "true|false"
+    }, "identifier");
+
+    var floatNumber = "(?:(?:(?:(?:(?:(?:\\d+)?(?:\\.\\d+))|(?:(?:\\d+)\\.))|(?:\\d+))(?:[eE][+-]?\\d+))|(?:(?:(?:\\d+)?(?:\\.\\d+))|(?:(?:\\d+)\\.)))";
+
+    this.$rules = {
+        "start": [
+            {
+              token: "variable.classes",
+              regex: '\\[\\<[.]*\\>\\]'
+            },
+            {
+                token: "comment",
+                regex: '//.*$'
+            },
+            {
+                token: "comment.start",
+                regex: /\(\*(?!\))/,
+                push: "blockComment"
+            },
+            {
+                token: "string",
+                regex: "'.'"
+            },
+            {
+                token: "string",
+                regex: '"""',
+                next  : [{
+                    token : "constant.language.escape",
+                    regex : /\\./,
+                    next  : "qqstring"
+                }, {
+                    token : "string",
+                    regex : '"""',
+                    next  : "start"
+                }, {
+                    defaultToken: "string"
+                }]
+            },
+            {
+                token: "string",
+                regex: '"',
+                next  : [{
+                    token : "constant.language.escape",
+                    regex : /\\./,
+                    next  : "qqstring"
+                }, {
+                    token : "string",
+                    regex : '"',
+                    next  : "start"
+                }, {
+                    defaultToken: "string"
+                }]
+            },
+            {
+                token: ["verbatim.string", "string"],
+                regex: '(@?)(")',
+                stateName : "qqstring",
+                next  : [{
+                    token : "constant.language.escape",
+                    regex : '""'
+                }, {
+                    token : "string",
+                    regex : '"',
+                    next  : "start"
+                }, {
+                    defaultToken: "string"
+                }]
+            },
+            {
+                token: "constant.float",
+                regex: "(?:" + floatNumber + "|\\d+)[jJ]\\b"
+            },
+            {
+                token: "constant.float",
+                regex: floatNumber
+            },
+            {
+                token: "constant.integer",
+                regex: "(?:(?:(?:[1-9]\\d*)|(?:0))|(?:0[oO]?[0-7]+)|(?:0[xX][\\dA-Fa-f]+)|(?:0[bB][01]+))\\b"
+            },
+            {
+                token: ["keyword.type", "variable"],
+                regex: "(type\\s)([a-zA-Z0-9_$\-]*\\b)"
+            },
+            {
+                token: keywordMapper,
+                regex: "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
+            },
+            {
+                token: "keyword.operator",
+                regex: "\\+\\.|\\-\\.|\\*\\.|\\/\\.|#|;;|\\+|\\-|\\*|\\*\\*\\/|\\/\\/|%|<<|>>|&|\\||\\^|~|<|>|<=|=>|==|!=|<>|<-|=|\\(\\*\\)"
+            },
+            {
+                token: "paren.lpar",
+                regex: "[[({]"
+            },
+            {
+                token: "paren.rpar",
+                regex: "[\\])}]"
+            }
+        ],
+        blockComment: [{
+            regex: /\(\*\)/,
+            token: "comment"
+        }, {
+            regex: /\(\*(?!\))/,
+            token: "comment.start",
+            push: "blockComment"
+        }, {
+            regex: /\*\)/,
+            token: "comment.end",
+            next: "pop"
+        }, {
+            defaultToken: "comment"
+        }]
+    };
+    this.normalizeRules();
+};
+
+
+oop.inherits(FSharpHighlightRules, TextHighlightRules);
+
+exports.FSharpHighlightRules = FSharpHighlightRules;
+});
+
+ace.define("ace/mode/folding/cstyle",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Range = require("../../range").Range;
+var BaseFoldMode = require("./fold_mode").FoldMode;
+
+var FoldMode = exports.FoldMode = function(commentRegex) {
+    if (commentRegex) {
+        this.foldingStartMarker = new RegExp(
+            this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start)
+        );
+        this.foldingStopMarker = new RegExp(
+            this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end)
+        );
+    }
+};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+    
+    this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/;
+    this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/;
+    this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/;
+    this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/;
+    this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/;
+    this._getFoldWidgetBase = this.getFoldWidget;
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+    
+        if (this.singleLineBlockCommentRe.test(line)) {
+            if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line))
+                return "";
+        }
+    
+        var fw = this._getFoldWidgetBase(session, foldStyle, row);
+    
+        if (!fw && this.startRegionRe.test(line))
+            return "start"; // lineCommentRegionStart
+    
+        return fw;
+    };
+
+    this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) {
+        var line = session.getLine(row);
+        
+        if (this.startRegionRe.test(line))
+            return this.getCommentRegionBlock(session, line, row);
+        
+        var match = line.match(this.foldingStartMarker);
+        if (match) {
+            var i = match.index;
+
+            if (match[1])
+                return this.openingBracketBlock(session, match[1], row, i);
+                
+            var range = session.getCommentFoldRange(row, i + match[0].length, 1);
+            
+            if (range && !range.isMultiLine()) {
+                if (forceMultiline) {
+                    range = this.getSectionRange(session, row);
+                } else if (foldStyle != "all")
+                    range = null;
+            }
+            
+            return range;
+        }
+
+        if (foldStyle === "markbegin")
+            return;
+
+        var match = line.match(this.foldingStopMarker);
+        if (match) {
+            var i = match.index + match[0].length;
+
+            if (match[1])
+                return this.closingBracketBlock(session, match[1], row, i);
+
+            return session.getCommentFoldRange(row, i, -1);
+        }
+    };
+    
+    this.getSectionRange = function(session, row) {
+        var line = session.getLine(row);
+        var startIndent = line.search(/\S/);
+        var startRow = row;
+        var startColumn = line.length;
+        row = row + 1;
+        var endRow = row;
+        var maxRow = session.getLength();
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var indent = line.search(/\S/);
+            if (indent === -1)
+                continue;
+            if  (startIndent > indent)
+                break;
+            var subRange = this.getFoldWidgetRange(session, "all", row);
+            
+            if (subRange) {
+                if (subRange.start.row <= startRow) {
+                    break;
+                } else if (subRange.isMultiLine()) {
+                    row = subRange.end.row;
+                } else if (startIndent == indent) {
+                    break;
+                }
+            }
+            endRow = row;
+        }
+        
+        return new Range(startRow, startColumn, endRow, session.getLine(endRow).length);
+    };
+    this.getCommentRegionBlock = function(session, line, row) {
+        var startColumn = line.search(/\s*$/);
+        var maxRow = session.getLength();
+        var startRow = row;
+        
+        var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/;
+        var depth = 1;
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var m = re.exec(line);
+            if (!m) continue;
+            if (m[1]) depth--;
+            else depth++;
+
+            if (!depth) break;
+        }
+
+        var endRow = row;
+        if (endRow > startRow) {
+            return new Range(startRow, startColumn, endRow, line.length);
+        }
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/fsharp",[], function (require, exports, module) {
+    "use strict";
+
+    var oop = require("../lib/oop");
+    var TextMode = require("./text").Mode;
+    var FSharpHighlightRules = require("./fsharp_highlight_rules").FSharpHighlightRules;
+    var CStyleFoldMode = require("./folding/cstyle").FoldMode;
+
+    var Mode = function () {
+        TextMode.call(this);
+        this.HighlightRules = FSharpHighlightRules;
+        this.foldingRules = new CStyleFoldMode();
+    };
+
+    oop.inherits(Mode, TextMode);
+
+
+    (function () {
+        this.lineCommentStart = "//";
+        this.blockComment = {start: "(*", end: "*)", nestable: true};
+
+
+        this.$id = "ace/mode/fsharp";
+    }).call(Mode.prototype);
+
+    exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/fsharp"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 259 - 0
services/web/public/js/ace-1.4.3/mode-fsl.js

@@ -0,0 +1,259 @@
+ace.define("ace/mode/fsl_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var FSLHighlightRules = function() {
+
+    this.$rules = {
+        start: [{
+            token: "punctuation.definition.comment.mn",
+            regex: /\/\*/,
+            push: [{
+                token: "punctuation.definition.comment.mn",
+                regex: /\*\//,
+                next: "pop"
+            }, {
+                defaultToken: "comment.block.fsl"
+            }]
+        }, {
+            token: "comment.line.fsl",
+            regex: /\/\//,
+            push: [{
+                token: "comment.line.fsl",
+                regex: /$/,
+                next: "pop"
+            }, {
+                defaultToken: "comment.line.fsl"
+            }]
+        }, {
+            token: "entity.name.function",
+            regex: /\${/,
+            push: [{
+                token: "entity.name.function",
+                regex: /}/,
+                next: "pop"
+            }, {
+                defaultToken: "keyword.other"
+            }],
+            comment: "js outcalls"
+        }, {
+            token: "constant.numeric",
+            regex: /[0-9]*\.[0-9]*\.[0-9]*/,
+            comment: "semver"
+        }, {
+            token: "constant.language.fslLanguage",
+            regex: "(?:"
+                + "graph_layout|machine_name|machine_author|machine_license|machine_comment|machine_language"
+                + "|machine_version|machine_reference|npm_name|graph_layout|on_init|on_halt|on_end|on_terminate|on_finalize|on_transition"
+                + "|on_action|on_stochastic_action|on_legal|on_main|on_forced|on_validation|on_validation_failure|on_transition_refused|on_forced_transition_refused"
+                + "|on_action_refused|on_enter|on_exit|start_states|end_states|terminal_states|final_states|fsl_version"
+                + ")\\s*:"
+        }, {
+            token: "keyword.control.transition.fslArrow",
+            regex: /<->|<-|->|<=>|=>|<=|<~>|~>|<~|<-=>|<=->|<-~>|<~->|<=~>|<~=>/
+        }, {
+            token: "constant.numeric.fslProbability",
+            regex: /[0-9]+%/,
+            comment: "edge probability annotation"
+        }, {
+            token: "constant.character.fslAction",
+            regex: /\'[^']*\'/,
+            comment: "action annotation"
+        }, {
+            token: "string.quoted.double.fslLabel.doublequoted",
+            regex: /\"[^"]*\"/,
+            comment: "fsl label annotation"
+        }, {
+            token: "entity.name.tag.fslLabel.atom",
+            regex: /[a-zA-Z0-9_.+&()#@!?,]/,
+            comment: "fsl label annotation"
+        }]
+    };
+
+    this.normalizeRules();
+};
+
+FSLHighlightRules.metaData = {
+    fileTypes: ["fsl", "fsl_state"],
+    name: "FSL",
+    scopeName: "source.fsl"
+};
+
+
+oop.inherits(FSLHighlightRules, TextHighlightRules);
+
+exports.FSLHighlightRules = FSLHighlightRules;
+});
+
+ace.define("ace/mode/folding/cstyle",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Range = require("../../range").Range;
+var BaseFoldMode = require("./fold_mode").FoldMode;
+
+var FoldMode = exports.FoldMode = function(commentRegex) {
+    if (commentRegex) {
+        this.foldingStartMarker = new RegExp(
+            this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start)
+        );
+        this.foldingStopMarker = new RegExp(
+            this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end)
+        );
+    }
+};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+    
+    this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/;
+    this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/;
+    this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/;
+    this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/;
+    this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/;
+    this._getFoldWidgetBase = this.getFoldWidget;
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+    
+        if (this.singleLineBlockCommentRe.test(line)) {
+            if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line))
+                return "";
+        }
+    
+        var fw = this._getFoldWidgetBase(session, foldStyle, row);
+    
+        if (!fw && this.startRegionRe.test(line))
+            return "start"; // lineCommentRegionStart
+    
+        return fw;
+    };
+
+    this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) {
+        var line = session.getLine(row);
+        
+        if (this.startRegionRe.test(line))
+            return this.getCommentRegionBlock(session, line, row);
+        
+        var match = line.match(this.foldingStartMarker);
+        if (match) {
+            var i = match.index;
+
+            if (match[1])
+                return this.openingBracketBlock(session, match[1], row, i);
+                
+            var range = session.getCommentFoldRange(row, i + match[0].length, 1);
+            
+            if (range && !range.isMultiLine()) {
+                if (forceMultiline) {
+                    range = this.getSectionRange(session, row);
+                } else if (foldStyle != "all")
+                    range = null;
+            }
+            
+            return range;
+        }
+
+        if (foldStyle === "markbegin")
+            return;
+
+        var match = line.match(this.foldingStopMarker);
+        if (match) {
+            var i = match.index + match[0].length;
+
+            if (match[1])
+                return this.closingBracketBlock(session, match[1], row, i);
+
+            return session.getCommentFoldRange(row, i, -1);
+        }
+    };
+    
+    this.getSectionRange = function(session, row) {
+        var line = session.getLine(row);
+        var startIndent = line.search(/\S/);
+        var startRow = row;
+        var startColumn = line.length;
+        row = row + 1;
+        var endRow = row;
+        var maxRow = session.getLength();
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var indent = line.search(/\S/);
+            if (indent === -1)
+                continue;
+            if  (startIndent > indent)
+                break;
+            var subRange = this.getFoldWidgetRange(session, "all", row);
+            
+            if (subRange) {
+                if (subRange.start.row <= startRow) {
+                    break;
+                } else if (subRange.isMultiLine()) {
+                    row = subRange.end.row;
+                } else if (startIndent == indent) {
+                    break;
+                }
+            }
+            endRow = row;
+        }
+        
+        return new Range(startRow, startColumn, endRow, session.getLine(endRow).length);
+    };
+    this.getCommentRegionBlock = function(session, line, row) {
+        var startColumn = line.search(/\s*$/);
+        var maxRow = session.getLength();
+        var startRow = row;
+        
+        var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/;
+        var depth = 1;
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var m = re.exec(line);
+            if (!m) continue;
+            if (m[1]) depth--;
+            else depth++;
+
+            if (!depth) break;
+        }
+
+        var endRow = row;
+        if (endRow > startRow) {
+            return new Range(startRow, startColumn, endRow, line.length);
+        }
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/fsl",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var FSLHighlightRules = require("./fsl_highlight_rules").FSLHighlightRules;
+var FoldMode = require("./folding/cstyle").FoldMode;
+
+var Mode = function() {
+    this.HighlightRules = FSLHighlightRules;
+    this.foldingRules = new FoldMode();
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+    this.lineCommentStart = "//";
+    this.blockComment = {start: "/*", end: "*/"};
+    this.$id = "ace/mode/fsl";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/fsl"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

Fișier diff suprimat deoarece este prea mare
+ 6 - 0
services/web/public/js/ace-1.4.3/mode-ftl.js


+ 94 - 0
services/web/public/js/ace-1.4.3/mode-gcode.js

@@ -0,0 +1,94 @@
+ace.define("ace/mode/gcode_highlight_rules",[], function(require, exports, module) {
+    "use strict";
+
+    var oop = require("../lib/oop");
+    var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+    var GcodeHighlightRules = function() {
+
+        var keywords = (
+            "IF|DO|WHILE|ENDWHILE|CALL|ENDIF|SUB|ENDSUB|GOTO|REPEAT|ENDREPEAT|CALL"
+            );
+
+        var builtinConstants = (
+            "PI"
+            );
+
+        var builtinFunctions = (
+            "ATAN|ABS|ACOS|ASIN|SIN|COS|EXP|FIX|FUP|ROUND|LN|TAN"
+            );
+        var keywordMapper = this.createKeywordMapper({
+            "support.function": builtinFunctions,
+            "keyword": keywords,
+            "constant.language": builtinConstants
+        }, "identifier", true);
+
+        this.$rules = {
+            "start" : [ {
+                token : "comment",
+                regex : "\\(.*\\)"
+            }, {
+                token : "comment",           // block number
+                regex : "([N])([0-9]+)"
+            }, {
+                token : "string",           // " string
+                regex : "([G])([0-9]+\\.?[0-9]?)"
+            }, {
+                token : "string",           // ' string
+                regex : "([M])([0-9]+\\.?[0-9]?)"
+            }, {
+                token : "constant.numeric", // float
+                regex : "([-+]?([0-9]*\\.?[0-9]+\\.?))|(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)"
+            }, {
+                token : keywordMapper,
+                regex : "[A-Z]"
+            }, {
+                token : "keyword.operator",
+                regex : "EQ|LT|GT|NE|GE|LE|OR|XOR"
+            }, {
+                token : "paren.lparen",
+                regex : "[\\[]"
+            }, {
+                token : "paren.rparen",
+                regex : "[\\]]"
+            }, {
+                token : "text",
+                regex : "\\s+"
+            } ]
+        };
+    };
+
+    oop.inherits(GcodeHighlightRules, TextHighlightRules);
+
+    exports.GcodeHighlightRules = GcodeHighlightRules;
+});
+
+ace.define("ace/mode/gcode",[], function(require, exports, module) {
+    "use strict";
+
+    var oop = require("../lib/oop");
+    var TextMode = require("./text").Mode;
+    var GcodeHighlightRules = require("./gcode_highlight_rules").GcodeHighlightRules;
+    var Range = require("../range").Range;
+
+    var Mode = function() {
+        this.HighlightRules = GcodeHighlightRules;
+        this.$behaviour = this.$defaultBehaviour;
+    };
+    oop.inherits(Mode, TextMode);
+
+    (function() {
+        this.$id = "ace/mode/gcode";
+    }).call(Mode.prototype);
+
+    exports.Mode = Mode;
+
+});
+                (function() {
+                    ace.require(["ace/mode/gcode"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 171 - 0
services/web/public/js/ace-1.4.3/mode-gherkin.js

@@ -0,0 +1,171 @@
+ace.define("ace/mode/gherkin_highlight_rules",[], function(require, exports, module) {
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+var stringEscape =  "\\\\(x[0-9A-Fa-f]{2}|[0-7]{3}|[\\\\abfnrtv'\"]|U[0-9A-Fa-f]{8}|u[0-9A-Fa-f]{4})";
+
+var GherkinHighlightRules = function() {
+    var languages = [{
+        name: "en",
+        labels: "Feature|Background|Scenario(?: Outline)?|Examples",
+        keywords: "Given|When|Then|And|But"
+    }];
+    
+    var labels = languages.map(function(l) {
+        return l.labels;
+    }).join("|");
+    var keywords = languages.map(function(l) {
+        return l.keywords;
+    }).join("|");
+    this.$rules = {
+        start : [{
+            token: "constant.numeric",
+            regex: "(?:(?:[1-9]\\d*)|(?:0))"
+        }, {
+            token : "comment",
+            regex : "#.*$"
+        }, {
+            token : "keyword",
+            regex : "(?:" + labels + "):|(?:" + keywords + ")\\b"
+        }, {
+            token : "keyword",
+            regex : "\\*"
+        }, {
+            token : "string",           // multi line """ string start
+            regex : '"{3}',
+            next : "qqstring3"
+        }, {
+            token : "string",           // " string
+            regex : '"',
+            next : "qqstring"
+        }, {
+            token : "text",
+            regex : "^\\s*(?=@[\\w])",
+            next : [{
+                token : "text",
+                regex : "\\s+"
+            }, {
+                token : "variable.parameter",
+                regex : "@[\\w]+"
+            }, {
+                token : "empty",
+                regex : "",
+                next : "start"
+            }]
+        }, {
+            token : "comment",
+            regex : "<[^>]+>"
+        }, {
+            token : "comment",
+            regex : "\\|(?=.)",
+            next : "table-item"
+        }, {
+            token : "comment",
+            regex : "\\|$",
+            next : "start"
+        }],
+        "qqstring3" : [ {
+            token : "constant.language.escape",
+            regex : stringEscape
+        }, {
+            token : "string", // multi line """ string end
+            regex : '"{3}',
+            next : "start"
+        }, {
+            defaultToken : "string"
+        }],
+        "qqstring" : [{
+            token : "constant.language.escape",
+            regex : stringEscape
+        }, {
+            token : "string",
+            regex : "\\\\$",
+            next  : "qqstring"
+        }, {
+            token : "string",
+            regex : '"|$',
+            next  : "start"
+        }, {
+            defaultToken: "string"
+        }],
+        "table-item" : [{
+            token : "comment",
+            regex : /$/,
+            next : "start"
+        }, {
+            token : "comment",
+            regex : /\|/
+        }, {
+            token : "string",
+            regex : /\\./
+        }, {
+            defaultToken : "string"
+        }]
+    };
+    this.normalizeRules();
+};
+
+oop.inherits(GherkinHighlightRules, TextHighlightRules);
+
+exports.GherkinHighlightRules = GherkinHighlightRules;
+});
+
+ace.define("ace/mode/gherkin",[], function(require, exports, module) {
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var GherkinHighlightRules = require("./gherkin_highlight_rules").GherkinHighlightRules;
+
+var Mode = function() {
+    this.HighlightRules = GherkinHighlightRules;
+    this.$behaviour = this.$defaultBehaviour;
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+    this.lineCommentStart = "#";
+    this.$id = "ace/mode/gherkin";
+
+    this.getNextLineIndent = function(state, line, tab) {
+        var indent = this.$getIndent(line);
+        var space2 = "  ";
+
+        var tokenizedLine = this.getTokenizer().getLineTokens(line, state);
+        var tokens = tokenizedLine.tokens;
+        
+        console.log(state);
+        
+        if(line.match("[ ]*\\|")) {
+            indent += "| ";
+        }
+
+        if (tokens.length && tokens[tokens.length-1].type == "comment") {
+            return indent;
+        }
+        
+
+        if (state == "start") {
+            if (line.match("Scenario:|Feature:|Scenario Outline:|Background:")) {
+                indent += space2;
+            } else if(line.match("(Given|Then).+(:)$|Examples:")) {
+                indent += space2;
+            } else if(line.match("\\*.+")) {
+                indent += "* ";
+            } 
+        }
+        
+
+        return indent;
+    };
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/gherkin"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 60 - 0
services/web/public/js/ace-1.4.3/mode-gitignore.js

@@ -0,0 +1,60 @@
+ace.define("ace/mode/gitignore_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var GitignoreHighlightRules = function() {
+    this.$rules = {
+        "start" : [
+            {
+                token : "comment",
+                regex : /^\s*#.*$/
+            }, {
+                token : "keyword", // negated patterns
+                regex : /^\s*!.*$/
+            }
+        ]
+    };
+    
+    this.normalizeRules();
+};
+
+GitignoreHighlightRules.metaData = {
+    fileTypes: ['gitignore'],
+    name: 'Gitignore'
+};
+
+oop.inherits(GitignoreHighlightRules, TextHighlightRules);
+
+exports.GitignoreHighlightRules = GitignoreHighlightRules;
+});
+
+ace.define("ace/mode/gitignore",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var GitignoreHighlightRules = require("./gitignore_highlight_rules").GitignoreHighlightRules;
+
+var Mode = function() {
+    this.HighlightRules = GitignoreHighlightRules;
+    this.$behaviour = this.$defaultBehaviour;
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+    this.lineCommentStart = "#";
+    this.$id = "ace/mode/gitignore";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/gitignore"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

Fișier diff suprimat deoarece este prea mare
+ 56 - 0
services/web/public/js/ace-1.4.3/mode-glsl.js


+ 931 - 0
services/web/public/js/ace-1.4.3/mode-gobstones.js

@@ -0,0 +1,931 @@
+ace.define("ace/mode/doc_comment_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var DocCommentHighlightRules = function() {
+    this.$rules = {
+        "start" : [ {
+            token : "comment.doc.tag",
+            regex : "@[\\w\\d_]+" // TODO: fix email addresses
+        }, 
+        DocCommentHighlightRules.getTagRule(),
+        {
+            defaultToken : "comment.doc",
+            caseInsensitive: true
+        }]
+    };
+};
+
+oop.inherits(DocCommentHighlightRules, TextHighlightRules);
+
+DocCommentHighlightRules.getTagRule = function(start) {
+    return {
+        token : "comment.doc.tag.storage.type",
+        regex : "\\b(?:TODO|FIXME|XXX|HACK)\\b"
+    };
+};
+
+DocCommentHighlightRules.getStartRule = function(start) {
+    return {
+        token : "comment.doc", // doc comment
+        regex : "\\/\\*(?=\\*)",
+        next  : start
+    };
+};
+
+DocCommentHighlightRules.getEndRule = function (start) {
+    return {
+        token : "comment.doc", // closing comment
+        regex : "\\*\\/",
+        next  : start
+    };
+};
+
+
+exports.DocCommentHighlightRules = DocCommentHighlightRules;
+
+});
+
+ace.define("ace/mode/javascript_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var DocCommentHighlightRules = require("./doc_comment_highlight_rules").DocCommentHighlightRules;
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+var identifierRe = "[a-zA-Z\\$_\u00a1-\uffff][a-zA-Z\\d\\$_\u00a1-\uffff]*";
+
+var JavaScriptHighlightRules = function(options) {
+    var keywordMapper = this.createKeywordMapper({
+        "variable.language":
+            "Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|"  + // Constructors
+            "Namespace|QName|XML|XMLList|"                                             + // E4X
+            "ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|"   +
+            "Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|"                    +
+            "Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|"   + // Errors
+            "SyntaxError|TypeError|URIError|"                                          +
+            "decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|" + // Non-constructor functions
+            "isNaN|parseFloat|parseInt|"                                               +
+            "JSON|Math|"                                                               + // Other
+            "this|arguments|prototype|window|document"                                 , // Pseudo
+        "keyword":
+            "const|yield|import|get|set|async|await|" +
+            "break|case|catch|continue|default|delete|do|else|finally|for|function|" +
+            "if|in|of|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|debugger|" +
+            "__parent__|__count__|escape|unescape|with|__proto__|" +
+            "class|enum|extends|super|export|implements|private|public|interface|package|protected|static",
+        "storage.type":
+            "const|let|var|function",
+        "constant.language":
+            "null|Infinity|NaN|undefined",
+        "support.function":
+            "alert",
+        "constant.language.boolean": "true|false"
+    }, "identifier");
+    var kwBeforeRe = "case|do|else|finally|in|instanceof|return|throw|try|typeof|yield|void";
+
+    var escapedRe = "\\\\(?:x[0-9a-fA-F]{2}|" + // hex
+        "u[0-9a-fA-F]{4}|" + // unicode
+        "u{[0-9a-fA-F]{1,6}}|" + // es6 unicode
+        "[0-2][0-7]{0,2}|" + // oct
+        "3[0-7][0-7]?|" + // oct
+        "[4-7][0-7]?|" + //oct
+        ".)";
+
+    this.$rules = {
+        "no_regex" : [
+            DocCommentHighlightRules.getStartRule("doc-start"),
+            comments("no_regex"),
+            {
+                token : "string",
+                regex : "'(?=.)",
+                next  : "qstring"
+            }, {
+                token : "string",
+                regex : '"(?=.)',
+                next  : "qqstring"
+            }, {
+                token : "constant.numeric", // hexadecimal, octal and binary
+                regex : /0(?:[xX][0-9a-fA-F]+|[oO][0-7]+|[bB][01]+)\b/
+            }, {
+                token : "constant.numeric", // decimal integers and floats
+                regex : /(?:\d\d*(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+\b)?/
+            }, {
+                token : [
+                    "storage.type", "punctuation.operator", "support.function",
+                    "punctuation.operator", "entity.name.function", "text","keyword.operator"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(prototype)(\\.)(" + identifierRe +")(\\s*)(=)",
+                next: "function_arguments"
+            }, {
+                token : [
+                    "storage.type", "punctuation.operator", "entity.name.function", "text",
+                    "keyword.operator", "text", "storage.type", "text", "paren.lparen"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",
+                next: "function_arguments"
+            }, {
+                token : [
+                    "entity.name.function", "text", "keyword.operator", "text", "storage.type",
+                    "text", "paren.lparen"
+                ],
+                regex : "(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",
+                next: "function_arguments"
+            }, {
+                token : [
+                    "storage.type", "punctuation.operator", "entity.name.function", "text",
+                    "keyword.operator", "text",
+                    "storage.type", "text", "entity.name.function", "text", "paren.lparen"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s+)(\\w+)(\\s*)(\\()",
+                next: "function_arguments"
+            }, {
+                token : [
+                    "storage.type", "text", "entity.name.function", "text", "paren.lparen"
+                ],
+                regex : "(function)(\\s+)(" + identifierRe + ")(\\s*)(\\()",
+                next: "function_arguments"
+            }, {
+                token : [
+                    "entity.name.function", "text", "punctuation.operator",
+                    "text", "storage.type", "text", "paren.lparen"
+                ],
+                regex : "(" + identifierRe + ")(\\s*)(:)(\\s*)(function)(\\s*)(\\()",
+                next: "function_arguments"
+            }, {
+                token : [
+                    "text", "text", "storage.type", "text", "paren.lparen"
+                ],
+                regex : "(:)(\\s*)(function)(\\s*)(\\()",
+                next: "function_arguments"
+            }, {
+                token : "keyword",
+                regex : "from(?=\\s*('|\"))"
+            }, {
+                token : "keyword",
+                regex : "(?:" + kwBeforeRe + ")\\b",
+                next : "start"
+            }, {
+                token : ["support.constant"],
+                regex : /that\b/
+            }, {
+                token : ["storage.type", "punctuation.operator", "support.function.firebug"],
+                regex : /(console)(\.)(warn|info|log|error|time|trace|timeEnd|assert)\b/
+            }, {
+                token : keywordMapper,
+                regex : identifierRe
+            }, {
+                token : "punctuation.operator",
+                regex : /[.](?![.])/,
+                next  : "property"
+            }, {
+                token : "storage.type",
+                regex : /=>/,
+                next  : "start"
+            }, {
+                token : "keyword.operator",
+                regex : /--|\+\+|\.{3}|===|==|=|!=|!==|<+=?|>+=?|!|&&|\|\||\?:|[!$%&*+\-~\/^]=?/,
+                next  : "start"
+            }, {
+                token : "punctuation.operator",
+                regex : /[?:,;.]/,
+                next  : "start"
+            }, {
+                token : "paren.lparen",
+                regex : /[\[({]/,
+                next  : "start"
+            }, {
+                token : "paren.rparen",
+                regex : /[\])}]/
+            }, {
+                token: "comment",
+                regex: /^#!.*$/
+            }
+        ],
+        property: [{
+                token : "text",
+                regex : "\\s+"
+            }, {
+                token : [
+                    "storage.type", "punctuation.operator", "entity.name.function", "text",
+                    "keyword.operator", "text",
+                    "storage.type", "text", "entity.name.function", "text", "paren.lparen"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(?:(\\s+)(\\w+))?(\\s*)(\\()",
+                next: "function_arguments"
+            }, {
+                token : "punctuation.operator",
+                regex : /[.](?![.])/
+            }, {
+                token : "support.function",
+                regex : /(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:op|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/
+            }, {
+                token : "support.function.dom",
+                regex : /(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName|ClassName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/
+            }, {
+                token :  "support.constant",
+                regex : /(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/
+            }, {
+                token : "identifier",
+                regex : identifierRe
+            }, {
+                regex: "",
+                token: "empty",
+                next: "no_regex"
+            }
+        ],
+        "start": [
+            DocCommentHighlightRules.getStartRule("doc-start"),
+            comments("start"),
+            {
+                token: "string.regexp",
+                regex: "\\/",
+                next: "regex"
+            }, {
+                token : "text",
+                regex : "\\s+|^$",
+                next : "start"
+            }, {
+                token: "empty",
+                regex: "",
+                next: "no_regex"
+            }
+        ],
+        "regex": [
+            {
+                token: "regexp.keyword.operator",
+                regex: "\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"
+            }, {
+                token: "string.regexp",
+                regex: "/[sxngimy]*",
+                next: "no_regex"
+            }, {
+                token : "invalid",
+                regex: /\{\d+\b,?\d*\}[+*]|[+*$^?][+*]|[$^][?]|\?{3,}/
+            }, {
+                token : "constant.language.escape",
+                regex: /\(\?[:=!]|\)|\{\d+\b,?\d*\}|[+*]\?|[()$^+*?.]/
+            }, {
+                token : "constant.language.delimiter",
+                regex: /\|/
+            }, {
+                token: "constant.language.escape",
+                regex: /\[\^?/,
+                next: "regex_character_class"
+            }, {
+                token: "empty",
+                regex: "$",
+                next: "no_regex"
+            }, {
+                defaultToken: "string.regexp"
+            }
+        ],
+        "regex_character_class": [
+            {
+                token: "regexp.charclass.keyword.operator",
+                regex: "\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"
+            }, {
+                token: "constant.language.escape",
+                regex: "]",
+                next: "regex"
+            }, {
+                token: "constant.language.escape",
+                regex: "-"
+            }, {
+                token: "empty",
+                regex: "$",
+                next: "no_regex"
+            }, {
+                defaultToken: "string.regexp.charachterclass"
+            }
+        ],
+        "function_arguments": [
+            {
+                token: "variable.parameter",
+                regex: identifierRe
+            }, {
+                token: "punctuation.operator",
+                regex: "[, ]+"
+            }, {
+                token: "punctuation.operator",
+                regex: "$"
+            }, {
+                token: "empty",
+                regex: "",
+                next: "no_regex"
+            }
+        ],
+        "qqstring" : [
+            {
+                token : "constant.language.escape",
+                regex : escapedRe
+            }, {
+                token : "string",
+                regex : "\\\\$",
+                consumeLineEnd  : true
+            }, {
+                token : "string",
+                regex : '"|$',
+                next  : "no_regex"
+            }, {
+                defaultToken: "string"
+            }
+        ],
+        "qstring" : [
+            {
+                token : "constant.language.escape",
+                regex : escapedRe
+            }, {
+                token : "string",
+                regex : "\\\\$",
+                consumeLineEnd  : true
+            }, {
+                token : "string",
+                regex : "'|$",
+                next  : "no_regex"
+            }, {
+                defaultToken: "string"
+            }
+        ]
+    };
+
+
+    if (!options || !options.noES6) {
+        this.$rules.no_regex.unshift({
+            regex: "[{}]", onMatch: function(val, state, stack) {
+                this.next = val == "{" ? this.nextState : "";
+                if (val == "{" && stack.length) {
+                    stack.unshift("start", state);
+                }
+                else if (val == "}" && stack.length) {
+                    stack.shift();
+                    this.next = stack.shift();
+                    if (this.next.indexOf("string") != -1 || this.next.indexOf("jsx") != -1)
+                        return "paren.quasi.end";
+                }
+                return val == "{" ? "paren.lparen" : "paren.rparen";
+            },
+            nextState: "start"
+        }, {
+            token : "string.quasi.start",
+            regex : /`/,
+            push  : [{
+                token : "constant.language.escape",
+                regex : escapedRe
+            }, {
+                token : "paren.quasi.start",
+                regex : /\${/,
+                push  : "start"
+            }, {
+                token : "string.quasi.end",
+                regex : /`/,
+                next  : "pop"
+            }, {
+                defaultToken: "string.quasi"
+            }]
+        });
+
+        if (!options || options.jsx != false)
+            JSX.call(this);
+    }
+
+    this.embedRules(DocCommentHighlightRules, "doc-",
+        [ DocCommentHighlightRules.getEndRule("no_regex") ]);
+
+    this.normalizeRules();
+};
+
+oop.inherits(JavaScriptHighlightRules, TextHighlightRules);
+
+function JSX() {
+    var tagRegex = identifierRe.replace("\\d", "\\d\\-");
+    var jsxTag = {
+        onMatch : function(val, state, stack) {
+            var offset = val.charAt(1) == "/" ? 2 : 1;
+            if (offset == 1) {
+                if (state != this.nextState)
+                    stack.unshift(this.next, this.nextState, 0);
+                else
+                    stack.unshift(this.next);
+                stack[2]++;
+            } else if (offset == 2) {
+                if (state == this.nextState) {
+                    stack[1]--;
+                    if (!stack[1] || stack[1] < 0) {
+                        stack.shift();
+                        stack.shift();
+                    }
+                }
+            }
+            return [{
+                type: "meta.tag.punctuation." + (offset == 1 ? "" : "end-") + "tag-open.xml",
+                value: val.slice(0, offset)
+            }, {
+                type: "meta.tag.tag-name.xml",
+                value: val.substr(offset)
+            }];
+        },
+        regex : "</?" + tagRegex + "",
+        next: "jsxAttributes",
+        nextState: "jsx"
+    };
+    this.$rules.start.unshift(jsxTag);
+    var jsxJsRule = {
+        regex: "{",
+        token: "paren.quasi.start",
+        push: "start"
+    };
+    this.$rules.jsx = [
+        jsxJsRule,
+        jsxTag,
+        {include : "reference"},
+        {defaultToken: "string"}
+    ];
+    this.$rules.jsxAttributes = [{
+        token : "meta.tag.punctuation.tag-close.xml",
+        regex : "/?>",
+        onMatch : function(value, currentState, stack) {
+            if (currentState == stack[0])
+                stack.shift();
+            if (value.length == 2) {
+                if (stack[0] == this.nextState)
+                    stack[1]--;
+                if (!stack[1] || stack[1] < 0) {
+                    stack.splice(0, 2);
+                }
+            }
+            this.next = stack[0] || "start";
+            return [{type: this.token, value: value}];
+        },
+        nextState: "jsx"
+    },
+    jsxJsRule,
+    comments("jsxAttributes"),
+    {
+        token : "entity.other.attribute-name.xml",
+        regex : tagRegex
+    }, {
+        token : "keyword.operator.attribute-equals.xml",
+        regex : "="
+    }, {
+        token : "text.tag-whitespace.xml",
+        regex : "\\s+"
+    }, {
+        token : "string.attribute-value.xml",
+        regex : "'",
+        stateName : "jsx_attr_q",
+        push : [
+            {token : "string.attribute-value.xml", regex: "'", next: "pop"},
+            {include : "reference"},
+            {defaultToken : "string.attribute-value.xml"}
+        ]
+    }, {
+        token : "string.attribute-value.xml",
+        regex : '"',
+        stateName : "jsx_attr_qq",
+        push : [
+            {token : "string.attribute-value.xml", regex: '"', next: "pop"},
+            {include : "reference"},
+            {defaultToken : "string.attribute-value.xml"}
+        ]
+    },
+    jsxTag
+    ];
+    this.$rules.reference = [{
+        token : "constant.language.escape.reference.xml",
+        regex : "(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"
+    }];
+}
+
+function comments(next) {
+    return [
+        {
+            token : "comment", // multi line comment
+            regex : /\/\*/,
+            next: [
+                DocCommentHighlightRules.getTagRule(),
+                {token : "comment", regex : "\\*\\/", next : next || "pop"},
+                {defaultToken : "comment", caseInsensitive: true}
+            ]
+        }, {
+            token : "comment",
+            regex : "\\/\\/",
+            next: [
+                DocCommentHighlightRules.getTagRule(),
+                {token : "comment", regex : "$|^", next : next || "pop"},
+                {defaultToken : "comment", caseInsensitive: true}
+            ]
+        }
+    ];
+}
+exports.JavaScriptHighlightRules = JavaScriptHighlightRules;
+});
+
+ace.define("ace/mode/matching_brace_outdent",[], function(require, exports, module) {
+"use strict";
+
+var Range = require("../range").Range;
+
+var MatchingBraceOutdent = function() {};
+
+(function() {
+
+    this.checkOutdent = function(line, input) {
+        if (! /^\s+$/.test(line))
+            return false;
+
+        return /^\s*\}/.test(input);
+    };
+
+    this.autoOutdent = function(doc, row) {
+        var line = doc.getLine(row);
+        var match = line.match(/^(\s*\})/);
+
+        if (!match) return 0;
+
+        var column = match[1].length;
+        var openBracePos = doc.findMatchingBracket({row: row, column: column});
+
+        if (!openBracePos || openBracePos.row == row) return 0;
+
+        var indent = this.$getIndent(doc.getLine(openBracePos.row));
+        doc.replace(new Range(row, 0, row, column-1), indent);
+    };
+
+    this.$getIndent = function(line) {
+        return line.match(/^\s*/)[0];
+    };
+
+}).call(MatchingBraceOutdent.prototype);
+
+exports.MatchingBraceOutdent = MatchingBraceOutdent;
+});
+
+ace.define("ace/mode/folding/cstyle",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Range = require("../../range").Range;
+var BaseFoldMode = require("./fold_mode").FoldMode;
+
+var FoldMode = exports.FoldMode = function(commentRegex) {
+    if (commentRegex) {
+        this.foldingStartMarker = new RegExp(
+            this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start)
+        );
+        this.foldingStopMarker = new RegExp(
+            this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end)
+        );
+    }
+};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+    
+    this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/;
+    this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/;
+    this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/;
+    this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/;
+    this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/;
+    this._getFoldWidgetBase = this.getFoldWidget;
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+    
+        if (this.singleLineBlockCommentRe.test(line)) {
+            if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line))
+                return "";
+        }
+    
+        var fw = this._getFoldWidgetBase(session, foldStyle, row);
+    
+        if (!fw && this.startRegionRe.test(line))
+            return "start"; // lineCommentRegionStart
+    
+        return fw;
+    };
+
+    this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) {
+        var line = session.getLine(row);
+        
+        if (this.startRegionRe.test(line))
+            return this.getCommentRegionBlock(session, line, row);
+        
+        var match = line.match(this.foldingStartMarker);
+        if (match) {
+            var i = match.index;
+
+            if (match[1])
+                return this.openingBracketBlock(session, match[1], row, i);
+                
+            var range = session.getCommentFoldRange(row, i + match[0].length, 1);
+            
+            if (range && !range.isMultiLine()) {
+                if (forceMultiline) {
+                    range = this.getSectionRange(session, row);
+                } else if (foldStyle != "all")
+                    range = null;
+            }
+            
+            return range;
+        }
+
+        if (foldStyle === "markbegin")
+            return;
+
+        var match = line.match(this.foldingStopMarker);
+        if (match) {
+            var i = match.index + match[0].length;
+
+            if (match[1])
+                return this.closingBracketBlock(session, match[1], row, i);
+
+            return session.getCommentFoldRange(row, i, -1);
+        }
+    };
+    
+    this.getSectionRange = function(session, row) {
+        var line = session.getLine(row);
+        var startIndent = line.search(/\S/);
+        var startRow = row;
+        var startColumn = line.length;
+        row = row + 1;
+        var endRow = row;
+        var maxRow = session.getLength();
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var indent = line.search(/\S/);
+            if (indent === -1)
+                continue;
+            if  (startIndent > indent)
+                break;
+            var subRange = this.getFoldWidgetRange(session, "all", row);
+            
+            if (subRange) {
+                if (subRange.start.row <= startRow) {
+                    break;
+                } else if (subRange.isMultiLine()) {
+                    row = subRange.end.row;
+                } else if (startIndent == indent) {
+                    break;
+                }
+            }
+            endRow = row;
+        }
+        
+        return new Range(startRow, startColumn, endRow, session.getLine(endRow).length);
+    };
+    this.getCommentRegionBlock = function(session, line, row) {
+        var startColumn = line.search(/\s*$/);
+        var maxRow = session.getLength();
+        var startRow = row;
+        
+        var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/;
+        var depth = 1;
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var m = re.exec(line);
+            if (!m) continue;
+            if (m[1]) depth--;
+            else depth++;
+
+            if (!depth) break;
+        }
+
+        var endRow = row;
+        if (endRow > startRow) {
+            return new Range(startRow, startColumn, endRow, line.length);
+        }
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/javascript",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var JavaScriptHighlightRules = require("./javascript_highlight_rules").JavaScriptHighlightRules;
+var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent;
+var WorkerClient = require("../worker/worker_client").WorkerClient;
+var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour;
+var CStyleFoldMode = require("./folding/cstyle").FoldMode;
+
+var Mode = function() {
+    this.HighlightRules = JavaScriptHighlightRules;
+    
+    this.$outdent = new MatchingBraceOutdent();
+    this.$behaviour = new CstyleBehaviour();
+    this.foldingRules = new CStyleFoldMode();
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+
+    this.lineCommentStart = "//";
+    this.blockComment = {start: "/*", end: "*/"};
+    this.$quotes = {'"': '"', "'": "'", "`": "`"};
+
+    this.getNextLineIndent = function(state, line, tab) {
+        var indent = this.$getIndent(line);
+
+        var tokenizedLine = this.getTokenizer().getLineTokens(line, state);
+        var tokens = tokenizedLine.tokens;
+        var endState = tokenizedLine.state;
+
+        if (tokens.length && tokens[tokens.length-1].type == "comment") {
+            return indent;
+        }
+
+        if (state == "start" || state == "no_regex") {
+            var match = line.match(/^.*(?:\bcase\b.*:|[\{\(\[])\s*$/);
+            if (match) {
+                indent += tab;
+            }
+        } else if (state == "doc-start") {
+            if (endState == "start" || endState == "no_regex") {
+                return "";
+            }
+            var match = line.match(/^\s*(\/?)\*/);
+            if (match) {
+                if (match[1]) {
+                    indent += " ";
+                }
+                indent += "* ";
+            }
+        }
+
+        return indent;
+    };
+
+    this.checkOutdent = function(state, line, input) {
+        return this.$outdent.checkOutdent(line, input);
+    };
+
+    this.autoOutdent = function(state, doc, row) {
+        this.$outdent.autoOutdent(doc, row);
+    };
+
+    this.createWorker = function(session) {
+        var worker = new WorkerClient(["ace"], "ace/mode/javascript_worker", "JavaScriptWorker");
+        worker.attachToDocument(session.getDocument());
+
+        worker.on("annotate", function(results) {
+            session.setAnnotations(results.data);
+        });
+
+        worker.on("terminate", function() {
+            session.clearAnnotations();
+        });
+
+        return worker;
+    };
+
+    this.$id = "ace/mode/javascript";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+
+ace.define("ace/mode/gobstones_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var DocCommentHighlightRules = require("./doc_comment_highlight_rules").DocCommentHighlightRules;
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var GobstonesHighlightRules = function() {
+
+    var keywords = (
+    "program|procedure|function|interactive|if|then|else|switch|repeat|while|foreach|in|not|div|mod|Skip|return"
+    );
+
+    var buildinConstants = (
+        "False|True"
+    );
+
+
+    var langClasses = (
+        "Poner|Sacar|Mover|IrAlBorde|VaciarTablero|" +
+        "nroBolitas|hayBolitas|puedeMover|siguiente|previo|opuesto|minBool|maxBool|" +
+        "minDir|maxDir|minColor|maxColor"
+    );
+
+    var supportType = (
+        "Verde|Rojo|Azul|Negro|Norte|Sur|Este|Oeste"
+    );
+
+    var keywordMapper = this.createKeywordMapper({
+        "keyword": keywords,
+        "constant.language": buildinConstants,
+        "support.function": langClasses,
+        "support.type": supportType
+    }, "identifier");
+
+    this.$rules = {
+        "start" : [
+            {
+                token : "comment",
+                regex : "\\/\\/.*$"
+            },
+            {
+                token : "comment",
+                regex : "\\-\\-.*$"
+            },
+            {
+                token : "comment",
+                regex : "#.*$"
+            },
+            DocCommentHighlightRules.getStartRule("doc-start"),
+            {
+                token : "comment", // multi line comment
+                regex : "\\/\\*",
+                next : "comment"
+            }, {
+
+                token : "string", // single line
+                regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
+            }, {
+                token : "string", // single line
+                regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
+            }, {
+                token : "constant.numeric", // hex
+                regex : /0(?:[xX][0-9a-fA-F][0-9a-fA-F_]*|[bB][01][01_]*)[LlSsDdFfYy]?\b/
+            }, {
+                token : "constant.numeric", // float
+                regex : /[+-]?\d[\d_]*(?:(?:\.[\d_]*)?(?:[eE][+-]?[\d_]+)?)?[LlSsDdFfYy]?\b/
+            }, {
+                token : "constant.language.boolean",
+                regex : "(?:True|False)\\b"
+            }, {
+                token : "keyword.operator",
+                regex : ":=|\\.\\.|,|;|\\|\\||\\/\\/|\\+|\\-|\\^|\\*|>|<|>=|=>|==|&&"
+            }, {
+                token : keywordMapper,
+                regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
+            }, {
+                token : "lparen",
+                regex : "[[({]"
+            }, {
+                token : "rparen",
+                regex : "[\\])}]"
+            }, {
+                token : "text",
+                regex : "\\s+"
+            }
+        ],
+        "comment" : [
+            {
+                token : "comment", // closing comment
+                regex : "\\*\\/",
+                next : "start"
+            }, {
+                defaultToken : "comment"
+            }
+        ]
+    };
+
+    this.embedRules(DocCommentHighlightRules, "doc-",
+        [ DocCommentHighlightRules.getEndRule("start") ]);
+};
+
+oop.inherits(GobstonesHighlightRules, TextHighlightRules);
+
+exports.GobstonesHighlightRules = GobstonesHighlightRules;
+});
+
+ace.define("ace/mode/gobstones",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var JavaScriptMode = require("./javascript").Mode;
+var GobstonesHighlightRules = require("./gobstones_highlight_rules").GobstonesHighlightRules;
+
+var Mode = function() {
+    JavaScriptMode.call(this);
+    this.HighlightRules = GobstonesHighlightRules;
+    this.$behaviour = this.$defaultBehaviour;
+};
+oop.inherits(Mode, JavaScriptMode);
+
+(function() {
+    
+    this.createWorker = function(session) {
+        return null;
+    };
+
+    this.$id = "ace/mode/gobstones";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/gobstones"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 414 - 0
services/web/public/js/ace-1.4.3/mode-golang.js

@@ -0,0 +1,414 @@
+ace.define("ace/mode/doc_comment_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var DocCommentHighlightRules = function() {
+    this.$rules = {
+        "start" : [ {
+            token : "comment.doc.tag",
+            regex : "@[\\w\\d_]+" // TODO: fix email addresses
+        }, 
+        DocCommentHighlightRules.getTagRule(),
+        {
+            defaultToken : "comment.doc",
+            caseInsensitive: true
+        }]
+    };
+};
+
+oop.inherits(DocCommentHighlightRules, TextHighlightRules);
+
+DocCommentHighlightRules.getTagRule = function(start) {
+    return {
+        token : "comment.doc.tag.storage.type",
+        regex : "\\b(?:TODO|FIXME|XXX|HACK)\\b"
+    };
+};
+
+DocCommentHighlightRules.getStartRule = function(start) {
+    return {
+        token : "comment.doc", // doc comment
+        regex : "\\/\\*(?=\\*)",
+        next  : start
+    };
+};
+
+DocCommentHighlightRules.getEndRule = function (start) {
+    return {
+        token : "comment.doc", // closing comment
+        regex : "\\*\\/",
+        next  : start
+    };
+};
+
+
+exports.DocCommentHighlightRules = DocCommentHighlightRules;
+
+});
+
+ace.define("ace/mode/golang_highlight_rules",[], function(require, exports, module) {
+    var oop = require("../lib/oop");
+    var DocCommentHighlightRules = require("./doc_comment_highlight_rules").DocCommentHighlightRules;
+    var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+    var GolangHighlightRules = function() {
+        var keywords = (
+            "else|break|case|return|goto|if|const|select|" +
+            "continue|struct|default|switch|for|range|" +
+            "func|import|package|chan|defer|fallthrough|go|interface|map|range|" +
+            "select|type|var"
+        );
+        var builtinTypes = (
+            "string|uint8|uint16|uint32|uint64|int8|int16|int32|int64|float32|" +
+            "float64|complex64|complex128|byte|rune|uint|int|uintptr|bool|error"
+        );
+        var builtinFunctions = (
+            "new|close|cap|copy|panic|panicln|print|println|len|make|delete|real|recover|imag|append"
+        );
+        var builtinConstants = ("nil|true|false|iota");
+
+        var keywordMapper = this.createKeywordMapper({
+            "keyword": keywords,
+            "constant.language": builtinConstants,
+            "support.function": builtinFunctions,
+            "support.type": builtinTypes
+        }, "");
+        
+        var stringEscapeRe = "\\\\(?:[0-7]{3}|x\\h{2}|u{4}|U\\h{6}|[abfnrtv'\"\\\\])".replace(/\\h/g, "[a-fA-F\\d]");
+
+        this.$rules = {
+            "start" : [
+                {
+                    token : "comment",
+                    regex : "\\/\\/.*$"
+                },
+                DocCommentHighlightRules.getStartRule("doc-start"),
+                {
+                    token : "comment.start", // multi line comment
+                    regex : "\\/\\*",
+                    next : "comment"
+                }, {
+                    token : "string", // single line
+                    regex : /"(?:[^"\\]|\\.)*?"/
+                }, {
+                    token : "string", // raw
+                    regex : '`',
+                    next : "bqstring"
+                }, {
+                    token : "constant.numeric", // rune
+                    regex : "'(?:[^\\'\uD800-\uDBFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|" + stringEscapeRe.replace('"', '')  + ")'"
+                }, {
+                    token : "constant.numeric", // hex
+                    regex : "0[xX][0-9a-fA-F]+\\b" 
+                }, {
+                    token : "constant.numeric", // float
+                    regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
+                }, {
+                    token : ["keyword", "text", "entity.name.function"],
+                    regex : "(func)(\\s+)([a-zA-Z_$][a-zA-Z0-9_$]*)\\b"
+                }, {
+                    token : function(val) {
+                        if (val[val.length - 1] == "(") {
+                            return [{
+                                type: keywordMapper(val.slice(0, -1)) || "support.function",
+                                value: val.slice(0, -1)
+                            }, {
+                                type: "paren.lparen",
+                                value: val.slice(-1)
+                            }];
+                        }
+                        
+                        return keywordMapper(val) || "identifier";
+                    },
+                    regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b\\(?"
+                }, {
+                    token : "keyword.operator",
+                    regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|==|=|!=|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^="
+                }, {
+                    token : "punctuation.operator",
+                    regex : "\\?|\\:|\\,|\\;|\\."
+                }, {
+                    token : "paren.lparen",
+                    regex : "[[({]"
+                }, {
+                    token : "paren.rparen",
+                    regex : "[\\])}]"
+                }, {
+                    token : "text",
+                    regex : "\\s+"
+                }
+            ],
+            "comment" : [
+                {
+                    token : "comment.end",
+                    regex : "\\*\\/",
+                    next : "start"
+                }, {
+                    defaultToken : "comment"
+                }
+            ],
+            "bqstring" : [
+                {
+                    token : "string",
+                    regex : '`',
+                    next : "start"
+                }, {
+                    defaultToken : "string"
+                }
+            ]
+        };
+
+        this.embedRules(DocCommentHighlightRules, "doc-",
+            [ DocCommentHighlightRules.getEndRule("start") ]);
+    };
+    oop.inherits(GolangHighlightRules, TextHighlightRules);
+
+    exports.GolangHighlightRules = GolangHighlightRules;
+});
+
+ace.define("ace/mode/matching_brace_outdent",[], function(require, exports, module) {
+"use strict";
+
+var Range = require("../range").Range;
+
+var MatchingBraceOutdent = function() {};
+
+(function() {
+
+    this.checkOutdent = function(line, input) {
+        if (! /^\s+$/.test(line))
+            return false;
+
+        return /^\s*\}/.test(input);
+    };
+
+    this.autoOutdent = function(doc, row) {
+        var line = doc.getLine(row);
+        var match = line.match(/^(\s*\})/);
+
+        if (!match) return 0;
+
+        var column = match[1].length;
+        var openBracePos = doc.findMatchingBracket({row: row, column: column});
+
+        if (!openBracePos || openBracePos.row == row) return 0;
+
+        var indent = this.$getIndent(doc.getLine(openBracePos.row));
+        doc.replace(new Range(row, 0, row, column-1), indent);
+    };
+
+    this.$getIndent = function(line) {
+        return line.match(/^\s*/)[0];
+    };
+
+}).call(MatchingBraceOutdent.prototype);
+
+exports.MatchingBraceOutdent = MatchingBraceOutdent;
+});
+
+ace.define("ace/mode/folding/cstyle",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Range = require("../../range").Range;
+var BaseFoldMode = require("./fold_mode").FoldMode;
+
+var FoldMode = exports.FoldMode = function(commentRegex) {
+    if (commentRegex) {
+        this.foldingStartMarker = new RegExp(
+            this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start)
+        );
+        this.foldingStopMarker = new RegExp(
+            this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end)
+        );
+    }
+};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+    
+    this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/;
+    this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/;
+    this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/;
+    this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/;
+    this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/;
+    this._getFoldWidgetBase = this.getFoldWidget;
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+    
+        if (this.singleLineBlockCommentRe.test(line)) {
+            if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line))
+                return "";
+        }
+    
+        var fw = this._getFoldWidgetBase(session, foldStyle, row);
+    
+        if (!fw && this.startRegionRe.test(line))
+            return "start"; // lineCommentRegionStart
+    
+        return fw;
+    };
+
+    this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) {
+        var line = session.getLine(row);
+        
+        if (this.startRegionRe.test(line))
+            return this.getCommentRegionBlock(session, line, row);
+        
+        var match = line.match(this.foldingStartMarker);
+        if (match) {
+            var i = match.index;
+
+            if (match[1])
+                return this.openingBracketBlock(session, match[1], row, i);
+                
+            var range = session.getCommentFoldRange(row, i + match[0].length, 1);
+            
+            if (range && !range.isMultiLine()) {
+                if (forceMultiline) {
+                    range = this.getSectionRange(session, row);
+                } else if (foldStyle != "all")
+                    range = null;
+            }
+            
+            return range;
+        }
+
+        if (foldStyle === "markbegin")
+            return;
+
+        var match = line.match(this.foldingStopMarker);
+        if (match) {
+            var i = match.index + match[0].length;
+
+            if (match[1])
+                return this.closingBracketBlock(session, match[1], row, i);
+
+            return session.getCommentFoldRange(row, i, -1);
+        }
+    };
+    
+    this.getSectionRange = function(session, row) {
+        var line = session.getLine(row);
+        var startIndent = line.search(/\S/);
+        var startRow = row;
+        var startColumn = line.length;
+        row = row + 1;
+        var endRow = row;
+        var maxRow = session.getLength();
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var indent = line.search(/\S/);
+            if (indent === -1)
+                continue;
+            if  (startIndent > indent)
+                break;
+            var subRange = this.getFoldWidgetRange(session, "all", row);
+            
+            if (subRange) {
+                if (subRange.start.row <= startRow) {
+                    break;
+                } else if (subRange.isMultiLine()) {
+                    row = subRange.end.row;
+                } else if (startIndent == indent) {
+                    break;
+                }
+            }
+            endRow = row;
+        }
+        
+        return new Range(startRow, startColumn, endRow, session.getLine(endRow).length);
+    };
+    this.getCommentRegionBlock = function(session, line, row) {
+        var startColumn = line.search(/\s*$/);
+        var maxRow = session.getLength();
+        var startRow = row;
+        
+        var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/;
+        var depth = 1;
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var m = re.exec(line);
+            if (!m) continue;
+            if (m[1]) depth--;
+            else depth++;
+
+            if (!depth) break;
+        }
+
+        var endRow = row;
+        if (endRow > startRow) {
+            return new Range(startRow, startColumn, endRow, line.length);
+        }
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/golang",[], function(require, exports, module) {
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var GolangHighlightRules = require("./golang_highlight_rules").GolangHighlightRules;
+var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent;
+var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour;
+var CStyleFoldMode = require("./folding/cstyle").FoldMode;
+
+var Mode = function() {
+    this.HighlightRules = GolangHighlightRules;
+    this.$outdent = new MatchingBraceOutdent();
+    this.foldingRules = new CStyleFoldMode();
+    this.$behaviour = new CstyleBehaviour();
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+    
+    this.lineCommentStart = "//";
+    this.blockComment = {start: "/*", end: "*/"};
+
+    this.getNextLineIndent = function(state, line, tab) {
+        var indent = this.$getIndent(line);
+
+        var tokenizedLine = this.getTokenizer().getLineTokens(line, state);
+        var tokens = tokenizedLine.tokens;
+        var endState = tokenizedLine.state;
+
+        if (tokens.length && tokens[tokens.length-1].type == "comment") {
+            return indent;
+        }
+        
+        if (state == "start") {
+            var match = line.match(/^.*[\{\(\[]\s*$/);
+            if (match) {
+                indent += tab;
+            }
+        }
+
+        return indent;
+    };//end getNextLineIndent
+
+    this.checkOutdent = function(state, line, input) {
+        return this.$outdent.checkOutdent(line, input);
+    };
+
+    this.autoOutdent = function(state, doc, row) {
+        this.$outdent.autoOutdent(doc, row);
+    };
+
+    this.$id = "ace/mode/golang";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/golang"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 214 - 0
services/web/public/js/ace-1.4.3/mode-graphqlschema.js

@@ -0,0 +1,214 @@
+ace.define("ace/mode/graphqlschema_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var GraphQLSchemaHighlightRules = function() {
+
+    var keywords = (
+      "type|interface|union|enum|schema|input|implements|extends|scalar"
+    );
+
+    var dataTypes = (
+      "Int|Float|String|ID|Boolean"
+    );
+
+    var keywordMapper = this.createKeywordMapper({
+        "keyword": keywords,
+        "storage.type": dataTypes
+    }, "identifier");
+
+    this.$rules = {
+      "start" : [ {
+        token : "comment",
+        regex : "#.*$"
+      }, {
+        token : "paren.lparen",
+        regex : /[\[({]/,
+        next  : "start"
+      }, {
+        token : "paren.rparen",
+        regex : /[\])}]/
+      }, {
+        token : keywordMapper,
+        regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
+      } ]
+    };
+    this.normalizeRules();
+};
+
+oop.inherits(GraphQLSchemaHighlightRules, TextHighlightRules);
+
+exports.GraphQLSchemaHighlightRules = GraphQLSchemaHighlightRules;
+});
+
+ace.define("ace/mode/folding/cstyle",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Range = require("../../range").Range;
+var BaseFoldMode = require("./fold_mode").FoldMode;
+
+var FoldMode = exports.FoldMode = function(commentRegex) {
+    if (commentRegex) {
+        this.foldingStartMarker = new RegExp(
+            this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start)
+        );
+        this.foldingStopMarker = new RegExp(
+            this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end)
+        );
+    }
+};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+    
+    this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/;
+    this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/;
+    this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/;
+    this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/;
+    this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/;
+    this._getFoldWidgetBase = this.getFoldWidget;
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+    
+        if (this.singleLineBlockCommentRe.test(line)) {
+            if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line))
+                return "";
+        }
+    
+        var fw = this._getFoldWidgetBase(session, foldStyle, row);
+    
+        if (!fw && this.startRegionRe.test(line))
+            return "start"; // lineCommentRegionStart
+    
+        return fw;
+    };
+
+    this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) {
+        var line = session.getLine(row);
+        
+        if (this.startRegionRe.test(line))
+            return this.getCommentRegionBlock(session, line, row);
+        
+        var match = line.match(this.foldingStartMarker);
+        if (match) {
+            var i = match.index;
+
+            if (match[1])
+                return this.openingBracketBlock(session, match[1], row, i);
+                
+            var range = session.getCommentFoldRange(row, i + match[0].length, 1);
+            
+            if (range && !range.isMultiLine()) {
+                if (forceMultiline) {
+                    range = this.getSectionRange(session, row);
+                } else if (foldStyle != "all")
+                    range = null;
+            }
+            
+            return range;
+        }
+
+        if (foldStyle === "markbegin")
+            return;
+
+        var match = line.match(this.foldingStopMarker);
+        if (match) {
+            var i = match.index + match[0].length;
+
+            if (match[1])
+                return this.closingBracketBlock(session, match[1], row, i);
+
+            return session.getCommentFoldRange(row, i, -1);
+        }
+    };
+    
+    this.getSectionRange = function(session, row) {
+        var line = session.getLine(row);
+        var startIndent = line.search(/\S/);
+        var startRow = row;
+        var startColumn = line.length;
+        row = row + 1;
+        var endRow = row;
+        var maxRow = session.getLength();
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var indent = line.search(/\S/);
+            if (indent === -1)
+                continue;
+            if  (startIndent > indent)
+                break;
+            var subRange = this.getFoldWidgetRange(session, "all", row);
+            
+            if (subRange) {
+                if (subRange.start.row <= startRow) {
+                    break;
+                } else if (subRange.isMultiLine()) {
+                    row = subRange.end.row;
+                } else if (startIndent == indent) {
+                    break;
+                }
+            }
+            endRow = row;
+        }
+        
+        return new Range(startRow, startColumn, endRow, session.getLine(endRow).length);
+    };
+    this.getCommentRegionBlock = function(session, line, row) {
+        var startColumn = line.search(/\s*$/);
+        var maxRow = session.getLength();
+        var startRow = row;
+        
+        var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/;
+        var depth = 1;
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var m = re.exec(line);
+            if (!m) continue;
+            if (m[1]) depth--;
+            else depth++;
+
+            if (!depth) break;
+        }
+
+        var endRow = row;
+        if (endRow > startRow) {
+            return new Range(startRow, startColumn, endRow, line.length);
+        }
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/graphqlschema",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var GraphQLSchemaHighlightRules = require("./graphqlschema_highlight_rules").GraphQLSchemaHighlightRules;
+var FoldMode = require("./folding/cstyle").FoldMode;
+
+var Mode = function() {
+    this.HighlightRules = GraphQLSchemaHighlightRules;
+    this.foldingRules = new FoldMode();
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+    this.lineCommentStart = "#";
+    this.$id = "ace/mode/graphqlschema";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/graphqlschema"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 989 - 0
services/web/public/js/ace-1.4.3/mode-groovy.js

@@ -0,0 +1,989 @@
+ace.define("ace/mode/doc_comment_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var DocCommentHighlightRules = function() {
+    this.$rules = {
+        "start" : [ {
+            token : "comment.doc.tag",
+            regex : "@[\\w\\d_]+" // TODO: fix email addresses
+        }, 
+        DocCommentHighlightRules.getTagRule(),
+        {
+            defaultToken : "comment.doc",
+            caseInsensitive: true
+        }]
+    };
+};
+
+oop.inherits(DocCommentHighlightRules, TextHighlightRules);
+
+DocCommentHighlightRules.getTagRule = function(start) {
+    return {
+        token : "comment.doc.tag.storage.type",
+        regex : "\\b(?:TODO|FIXME|XXX|HACK)\\b"
+    };
+};
+
+DocCommentHighlightRules.getStartRule = function(start) {
+    return {
+        token : "comment.doc", // doc comment
+        regex : "\\/\\*(?=\\*)",
+        next  : start
+    };
+};
+
+DocCommentHighlightRules.getEndRule = function (start) {
+    return {
+        token : "comment.doc", // closing comment
+        regex : "\\*\\/",
+        next  : start
+    };
+};
+
+
+exports.DocCommentHighlightRules = DocCommentHighlightRules;
+
+});
+
+ace.define("ace/mode/javascript_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var DocCommentHighlightRules = require("./doc_comment_highlight_rules").DocCommentHighlightRules;
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+var identifierRe = "[a-zA-Z\\$_\u00a1-\uffff][a-zA-Z\\d\\$_\u00a1-\uffff]*";
+
+var JavaScriptHighlightRules = function(options) {
+    var keywordMapper = this.createKeywordMapper({
+        "variable.language":
+            "Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|"  + // Constructors
+            "Namespace|QName|XML|XMLList|"                                             + // E4X
+            "ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|"   +
+            "Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|"                    +
+            "Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|"   + // Errors
+            "SyntaxError|TypeError|URIError|"                                          +
+            "decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|" + // Non-constructor functions
+            "isNaN|parseFloat|parseInt|"                                               +
+            "JSON|Math|"                                                               + // Other
+            "this|arguments|prototype|window|document"                                 , // Pseudo
+        "keyword":
+            "const|yield|import|get|set|async|await|" +
+            "break|case|catch|continue|default|delete|do|else|finally|for|function|" +
+            "if|in|of|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|debugger|" +
+            "__parent__|__count__|escape|unescape|with|__proto__|" +
+            "class|enum|extends|super|export|implements|private|public|interface|package|protected|static",
+        "storage.type":
+            "const|let|var|function",
+        "constant.language":
+            "null|Infinity|NaN|undefined",
+        "support.function":
+            "alert",
+        "constant.language.boolean": "true|false"
+    }, "identifier");
+    var kwBeforeRe = "case|do|else|finally|in|instanceof|return|throw|try|typeof|yield|void";
+
+    var escapedRe = "\\\\(?:x[0-9a-fA-F]{2}|" + // hex
+        "u[0-9a-fA-F]{4}|" + // unicode
+        "u{[0-9a-fA-F]{1,6}}|" + // es6 unicode
+        "[0-2][0-7]{0,2}|" + // oct
+        "3[0-7][0-7]?|" + // oct
+        "[4-7][0-7]?|" + //oct
+        ".)";
+
+    this.$rules = {
+        "no_regex" : [
+            DocCommentHighlightRules.getStartRule("doc-start"),
+            comments("no_regex"),
+            {
+                token : "string",
+                regex : "'(?=.)",
+                next  : "qstring"
+            }, {
+                token : "string",
+                regex : '"(?=.)',
+                next  : "qqstring"
+            }, {
+                token : "constant.numeric", // hexadecimal, octal and binary
+                regex : /0(?:[xX][0-9a-fA-F]+|[oO][0-7]+|[bB][01]+)\b/
+            }, {
+                token : "constant.numeric", // decimal integers and floats
+                regex : /(?:\d\d*(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+\b)?/
+            }, {
+                token : [
+                    "storage.type", "punctuation.operator", "support.function",
+                    "punctuation.operator", "entity.name.function", "text","keyword.operator"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(prototype)(\\.)(" + identifierRe +")(\\s*)(=)",
+                next: "function_arguments"
+            }, {
+                token : [
+                    "storage.type", "punctuation.operator", "entity.name.function", "text",
+                    "keyword.operator", "text", "storage.type", "text", "paren.lparen"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",
+                next: "function_arguments"
+            }, {
+                token : [
+                    "entity.name.function", "text", "keyword.operator", "text", "storage.type",
+                    "text", "paren.lparen"
+                ],
+                regex : "(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",
+                next: "function_arguments"
+            }, {
+                token : [
+                    "storage.type", "punctuation.operator", "entity.name.function", "text",
+                    "keyword.operator", "text",
+                    "storage.type", "text", "entity.name.function", "text", "paren.lparen"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s+)(\\w+)(\\s*)(\\()",
+                next: "function_arguments"
+            }, {
+                token : [
+                    "storage.type", "text", "entity.name.function", "text", "paren.lparen"
+                ],
+                regex : "(function)(\\s+)(" + identifierRe + ")(\\s*)(\\()",
+                next: "function_arguments"
+            }, {
+                token : [
+                    "entity.name.function", "text", "punctuation.operator",
+                    "text", "storage.type", "text", "paren.lparen"
+                ],
+                regex : "(" + identifierRe + ")(\\s*)(:)(\\s*)(function)(\\s*)(\\()",
+                next: "function_arguments"
+            }, {
+                token : [
+                    "text", "text", "storage.type", "text", "paren.lparen"
+                ],
+                regex : "(:)(\\s*)(function)(\\s*)(\\()",
+                next: "function_arguments"
+            }, {
+                token : "keyword",
+                regex : "from(?=\\s*('|\"))"
+            }, {
+                token : "keyword",
+                regex : "(?:" + kwBeforeRe + ")\\b",
+                next : "start"
+            }, {
+                token : ["support.constant"],
+                regex : /that\b/
+            }, {
+                token : ["storage.type", "punctuation.operator", "support.function.firebug"],
+                regex : /(console)(\.)(warn|info|log|error|time|trace|timeEnd|assert)\b/
+            }, {
+                token : keywordMapper,
+                regex : identifierRe
+            }, {
+                token : "punctuation.operator",
+                regex : /[.](?![.])/,
+                next  : "property"
+            }, {
+                token : "storage.type",
+                regex : /=>/,
+                next  : "start"
+            }, {
+                token : "keyword.operator",
+                regex : /--|\+\+|\.{3}|===|==|=|!=|!==|<+=?|>+=?|!|&&|\|\||\?:|[!$%&*+\-~\/^]=?/,
+                next  : "start"
+            }, {
+                token : "punctuation.operator",
+                regex : /[?:,;.]/,
+                next  : "start"
+            }, {
+                token : "paren.lparen",
+                regex : /[\[({]/,
+                next  : "start"
+            }, {
+                token : "paren.rparen",
+                regex : /[\])}]/
+            }, {
+                token: "comment",
+                regex: /^#!.*$/
+            }
+        ],
+        property: [{
+                token : "text",
+                regex : "\\s+"
+            }, {
+                token : [
+                    "storage.type", "punctuation.operator", "entity.name.function", "text",
+                    "keyword.operator", "text",
+                    "storage.type", "text", "entity.name.function", "text", "paren.lparen"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(?:(\\s+)(\\w+))?(\\s*)(\\()",
+                next: "function_arguments"
+            }, {
+                token : "punctuation.operator",
+                regex : /[.](?![.])/
+            }, {
+                token : "support.function",
+                regex : /(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:op|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/
+            }, {
+                token : "support.function.dom",
+                regex : /(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName|ClassName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/
+            }, {
+                token :  "support.constant",
+                regex : /(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/
+            }, {
+                token : "identifier",
+                regex : identifierRe
+            }, {
+                regex: "",
+                token: "empty",
+                next: "no_regex"
+            }
+        ],
+        "start": [
+            DocCommentHighlightRules.getStartRule("doc-start"),
+            comments("start"),
+            {
+                token: "string.regexp",
+                regex: "\\/",
+                next: "regex"
+            }, {
+                token : "text",
+                regex : "\\s+|^$",
+                next : "start"
+            }, {
+                token: "empty",
+                regex: "",
+                next: "no_regex"
+            }
+        ],
+        "regex": [
+            {
+                token: "regexp.keyword.operator",
+                regex: "\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"
+            }, {
+                token: "string.regexp",
+                regex: "/[sxngimy]*",
+                next: "no_regex"
+            }, {
+                token : "invalid",
+                regex: /\{\d+\b,?\d*\}[+*]|[+*$^?][+*]|[$^][?]|\?{3,}/
+            }, {
+                token : "constant.language.escape",
+                regex: /\(\?[:=!]|\)|\{\d+\b,?\d*\}|[+*]\?|[()$^+*?.]/
+            }, {
+                token : "constant.language.delimiter",
+                regex: /\|/
+            }, {
+                token: "constant.language.escape",
+                regex: /\[\^?/,
+                next: "regex_character_class"
+            }, {
+                token: "empty",
+                regex: "$",
+                next: "no_regex"
+            }, {
+                defaultToken: "string.regexp"
+            }
+        ],
+        "regex_character_class": [
+            {
+                token: "regexp.charclass.keyword.operator",
+                regex: "\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"
+            }, {
+                token: "constant.language.escape",
+                regex: "]",
+                next: "regex"
+            }, {
+                token: "constant.language.escape",
+                regex: "-"
+            }, {
+                token: "empty",
+                regex: "$",
+                next: "no_regex"
+            }, {
+                defaultToken: "string.regexp.charachterclass"
+            }
+        ],
+        "function_arguments": [
+            {
+                token: "variable.parameter",
+                regex: identifierRe
+            }, {
+                token: "punctuation.operator",
+                regex: "[, ]+"
+            }, {
+                token: "punctuation.operator",
+                regex: "$"
+            }, {
+                token: "empty",
+                regex: "",
+                next: "no_regex"
+            }
+        ],
+        "qqstring" : [
+            {
+                token : "constant.language.escape",
+                regex : escapedRe
+            }, {
+                token : "string",
+                regex : "\\\\$",
+                consumeLineEnd  : true
+            }, {
+                token : "string",
+                regex : '"|$',
+                next  : "no_regex"
+            }, {
+                defaultToken: "string"
+            }
+        ],
+        "qstring" : [
+            {
+                token : "constant.language.escape",
+                regex : escapedRe
+            }, {
+                token : "string",
+                regex : "\\\\$",
+                consumeLineEnd  : true
+            }, {
+                token : "string",
+                regex : "'|$",
+                next  : "no_regex"
+            }, {
+                defaultToken: "string"
+            }
+        ]
+    };
+
+
+    if (!options || !options.noES6) {
+        this.$rules.no_regex.unshift({
+            regex: "[{}]", onMatch: function(val, state, stack) {
+                this.next = val == "{" ? this.nextState : "";
+                if (val == "{" && stack.length) {
+                    stack.unshift("start", state);
+                }
+                else if (val == "}" && stack.length) {
+                    stack.shift();
+                    this.next = stack.shift();
+                    if (this.next.indexOf("string") != -1 || this.next.indexOf("jsx") != -1)
+                        return "paren.quasi.end";
+                }
+                return val == "{" ? "paren.lparen" : "paren.rparen";
+            },
+            nextState: "start"
+        }, {
+            token : "string.quasi.start",
+            regex : /`/,
+            push  : [{
+                token : "constant.language.escape",
+                regex : escapedRe
+            }, {
+                token : "paren.quasi.start",
+                regex : /\${/,
+                push  : "start"
+            }, {
+                token : "string.quasi.end",
+                regex : /`/,
+                next  : "pop"
+            }, {
+                defaultToken: "string.quasi"
+            }]
+        });
+
+        if (!options || options.jsx != false)
+            JSX.call(this);
+    }
+
+    this.embedRules(DocCommentHighlightRules, "doc-",
+        [ DocCommentHighlightRules.getEndRule("no_regex") ]);
+
+    this.normalizeRules();
+};
+
+oop.inherits(JavaScriptHighlightRules, TextHighlightRules);
+
+function JSX() {
+    var tagRegex = identifierRe.replace("\\d", "\\d\\-");
+    var jsxTag = {
+        onMatch : function(val, state, stack) {
+            var offset = val.charAt(1) == "/" ? 2 : 1;
+            if (offset == 1) {
+                if (state != this.nextState)
+                    stack.unshift(this.next, this.nextState, 0);
+                else
+                    stack.unshift(this.next);
+                stack[2]++;
+            } else if (offset == 2) {
+                if (state == this.nextState) {
+                    stack[1]--;
+                    if (!stack[1] || stack[1] < 0) {
+                        stack.shift();
+                        stack.shift();
+                    }
+                }
+            }
+            return [{
+                type: "meta.tag.punctuation." + (offset == 1 ? "" : "end-") + "tag-open.xml",
+                value: val.slice(0, offset)
+            }, {
+                type: "meta.tag.tag-name.xml",
+                value: val.substr(offset)
+            }];
+        },
+        regex : "</?" + tagRegex + "",
+        next: "jsxAttributes",
+        nextState: "jsx"
+    };
+    this.$rules.start.unshift(jsxTag);
+    var jsxJsRule = {
+        regex: "{",
+        token: "paren.quasi.start",
+        push: "start"
+    };
+    this.$rules.jsx = [
+        jsxJsRule,
+        jsxTag,
+        {include : "reference"},
+        {defaultToken: "string"}
+    ];
+    this.$rules.jsxAttributes = [{
+        token : "meta.tag.punctuation.tag-close.xml",
+        regex : "/?>",
+        onMatch : function(value, currentState, stack) {
+            if (currentState == stack[0])
+                stack.shift();
+            if (value.length == 2) {
+                if (stack[0] == this.nextState)
+                    stack[1]--;
+                if (!stack[1] || stack[1] < 0) {
+                    stack.splice(0, 2);
+                }
+            }
+            this.next = stack[0] || "start";
+            return [{type: this.token, value: value}];
+        },
+        nextState: "jsx"
+    },
+    jsxJsRule,
+    comments("jsxAttributes"),
+    {
+        token : "entity.other.attribute-name.xml",
+        regex : tagRegex
+    }, {
+        token : "keyword.operator.attribute-equals.xml",
+        regex : "="
+    }, {
+        token : "text.tag-whitespace.xml",
+        regex : "\\s+"
+    }, {
+        token : "string.attribute-value.xml",
+        regex : "'",
+        stateName : "jsx_attr_q",
+        push : [
+            {token : "string.attribute-value.xml", regex: "'", next: "pop"},
+            {include : "reference"},
+            {defaultToken : "string.attribute-value.xml"}
+        ]
+    }, {
+        token : "string.attribute-value.xml",
+        regex : '"',
+        stateName : "jsx_attr_qq",
+        push : [
+            {token : "string.attribute-value.xml", regex: '"', next: "pop"},
+            {include : "reference"},
+            {defaultToken : "string.attribute-value.xml"}
+        ]
+    },
+    jsxTag
+    ];
+    this.$rules.reference = [{
+        token : "constant.language.escape.reference.xml",
+        regex : "(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"
+    }];
+}
+
+function comments(next) {
+    return [
+        {
+            token : "comment", // multi line comment
+            regex : /\/\*/,
+            next: [
+                DocCommentHighlightRules.getTagRule(),
+                {token : "comment", regex : "\\*\\/", next : next || "pop"},
+                {defaultToken : "comment", caseInsensitive: true}
+            ]
+        }, {
+            token : "comment",
+            regex : "\\/\\/",
+            next: [
+                DocCommentHighlightRules.getTagRule(),
+                {token : "comment", regex : "$|^", next : next || "pop"},
+                {defaultToken : "comment", caseInsensitive: true}
+            ]
+        }
+    ];
+}
+exports.JavaScriptHighlightRules = JavaScriptHighlightRules;
+});
+
+ace.define("ace/mode/matching_brace_outdent",[], function(require, exports, module) {
+"use strict";
+
+var Range = require("../range").Range;
+
+var MatchingBraceOutdent = function() {};
+
+(function() {
+
+    this.checkOutdent = function(line, input) {
+        if (! /^\s+$/.test(line))
+            return false;
+
+        return /^\s*\}/.test(input);
+    };
+
+    this.autoOutdent = function(doc, row) {
+        var line = doc.getLine(row);
+        var match = line.match(/^(\s*\})/);
+
+        if (!match) return 0;
+
+        var column = match[1].length;
+        var openBracePos = doc.findMatchingBracket({row: row, column: column});
+
+        if (!openBracePos || openBracePos.row == row) return 0;
+
+        var indent = this.$getIndent(doc.getLine(openBracePos.row));
+        doc.replace(new Range(row, 0, row, column-1), indent);
+    };
+
+    this.$getIndent = function(line) {
+        return line.match(/^\s*/)[0];
+    };
+
+}).call(MatchingBraceOutdent.prototype);
+
+exports.MatchingBraceOutdent = MatchingBraceOutdent;
+});
+
+ace.define("ace/mode/folding/cstyle",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Range = require("../../range").Range;
+var BaseFoldMode = require("./fold_mode").FoldMode;
+
+var FoldMode = exports.FoldMode = function(commentRegex) {
+    if (commentRegex) {
+        this.foldingStartMarker = new RegExp(
+            this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start)
+        );
+        this.foldingStopMarker = new RegExp(
+            this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end)
+        );
+    }
+};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+    
+    this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/;
+    this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/;
+    this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/;
+    this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/;
+    this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/;
+    this._getFoldWidgetBase = this.getFoldWidget;
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+    
+        if (this.singleLineBlockCommentRe.test(line)) {
+            if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line))
+                return "";
+        }
+    
+        var fw = this._getFoldWidgetBase(session, foldStyle, row);
+    
+        if (!fw && this.startRegionRe.test(line))
+            return "start"; // lineCommentRegionStart
+    
+        return fw;
+    };
+
+    this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) {
+        var line = session.getLine(row);
+        
+        if (this.startRegionRe.test(line))
+            return this.getCommentRegionBlock(session, line, row);
+        
+        var match = line.match(this.foldingStartMarker);
+        if (match) {
+            var i = match.index;
+
+            if (match[1])
+                return this.openingBracketBlock(session, match[1], row, i);
+                
+            var range = session.getCommentFoldRange(row, i + match[0].length, 1);
+            
+            if (range && !range.isMultiLine()) {
+                if (forceMultiline) {
+                    range = this.getSectionRange(session, row);
+                } else if (foldStyle != "all")
+                    range = null;
+            }
+            
+            return range;
+        }
+
+        if (foldStyle === "markbegin")
+            return;
+
+        var match = line.match(this.foldingStopMarker);
+        if (match) {
+            var i = match.index + match[0].length;
+
+            if (match[1])
+                return this.closingBracketBlock(session, match[1], row, i);
+
+            return session.getCommentFoldRange(row, i, -1);
+        }
+    };
+    
+    this.getSectionRange = function(session, row) {
+        var line = session.getLine(row);
+        var startIndent = line.search(/\S/);
+        var startRow = row;
+        var startColumn = line.length;
+        row = row + 1;
+        var endRow = row;
+        var maxRow = session.getLength();
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var indent = line.search(/\S/);
+            if (indent === -1)
+                continue;
+            if  (startIndent > indent)
+                break;
+            var subRange = this.getFoldWidgetRange(session, "all", row);
+            
+            if (subRange) {
+                if (subRange.start.row <= startRow) {
+                    break;
+                } else if (subRange.isMultiLine()) {
+                    row = subRange.end.row;
+                } else if (startIndent == indent) {
+                    break;
+                }
+            }
+            endRow = row;
+        }
+        
+        return new Range(startRow, startColumn, endRow, session.getLine(endRow).length);
+    };
+    this.getCommentRegionBlock = function(session, line, row) {
+        var startColumn = line.search(/\s*$/);
+        var maxRow = session.getLength();
+        var startRow = row;
+        
+        var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/;
+        var depth = 1;
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var m = re.exec(line);
+            if (!m) continue;
+            if (m[1]) depth--;
+            else depth++;
+
+            if (!depth) break;
+        }
+
+        var endRow = row;
+        if (endRow > startRow) {
+            return new Range(startRow, startColumn, endRow, line.length);
+        }
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/javascript",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var JavaScriptHighlightRules = require("./javascript_highlight_rules").JavaScriptHighlightRules;
+var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent;
+var WorkerClient = require("../worker/worker_client").WorkerClient;
+var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour;
+var CStyleFoldMode = require("./folding/cstyle").FoldMode;
+
+var Mode = function() {
+    this.HighlightRules = JavaScriptHighlightRules;
+    
+    this.$outdent = new MatchingBraceOutdent();
+    this.$behaviour = new CstyleBehaviour();
+    this.foldingRules = new CStyleFoldMode();
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+
+    this.lineCommentStart = "//";
+    this.blockComment = {start: "/*", end: "*/"};
+    this.$quotes = {'"': '"', "'": "'", "`": "`"};
+
+    this.getNextLineIndent = function(state, line, tab) {
+        var indent = this.$getIndent(line);
+
+        var tokenizedLine = this.getTokenizer().getLineTokens(line, state);
+        var tokens = tokenizedLine.tokens;
+        var endState = tokenizedLine.state;
+
+        if (tokens.length && tokens[tokens.length-1].type == "comment") {
+            return indent;
+        }
+
+        if (state == "start" || state == "no_regex") {
+            var match = line.match(/^.*(?:\bcase\b.*:|[\{\(\[])\s*$/);
+            if (match) {
+                indent += tab;
+            }
+        } else if (state == "doc-start") {
+            if (endState == "start" || endState == "no_regex") {
+                return "";
+            }
+            var match = line.match(/^\s*(\/?)\*/);
+            if (match) {
+                if (match[1]) {
+                    indent += " ";
+                }
+                indent += "* ";
+            }
+        }
+
+        return indent;
+    };
+
+    this.checkOutdent = function(state, line, input) {
+        return this.$outdent.checkOutdent(line, input);
+    };
+
+    this.autoOutdent = function(state, doc, row) {
+        this.$outdent.autoOutdent(doc, row);
+    };
+
+    this.createWorker = function(session) {
+        var worker = new WorkerClient(["ace"], "ace/mode/javascript_worker", "JavaScriptWorker");
+        worker.attachToDocument(session.getDocument());
+
+        worker.on("annotate", function(results) {
+            session.setAnnotations(results.data);
+        });
+
+        worker.on("terminate", function() {
+            session.clearAnnotations();
+        });
+
+        return worker;
+    };
+
+    this.$id = "ace/mode/javascript";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+
+ace.define("ace/mode/groovy_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var DocCommentHighlightRules = require("./doc_comment_highlight_rules").DocCommentHighlightRules;
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var GroovyHighlightRules = function() {
+
+    var keywords = (
+        "assert|with|abstract|continue|for|new|switch|" +
+        "assert|default|goto|package|synchronized|" +
+        "boolean|do|if|private|this|" +
+        "break|double|implements|protected|throw|" +
+        "byte|else|import|public|throws|" +
+        "case|enum|instanceof|return|transient|" +
+        "catch|extends|int|short|try|" +
+        "char|final|interface|static|void|" +
+        "class|finally|long|strictfp|volatile|" +
+        "def|float|native|super|while"
+    );
+
+    var buildinConstants = (
+        "null|Infinity|NaN|undefined"
+    );
+
+    var langClasses = (
+        "AbstractMethodError|AssertionError|ClassCircularityError|"+
+        "ClassFormatError|Deprecated|EnumConstantNotPresentException|"+
+        "ExceptionInInitializerError|IllegalAccessError|"+
+        "IllegalThreadStateException|InstantiationError|InternalError|"+
+        "NegativeArraySizeException|NoSuchFieldError|Override|Process|"+
+        "ProcessBuilder|SecurityManager|StringIndexOutOfBoundsException|"+
+        "SuppressWarnings|TypeNotPresentException|UnknownError|"+
+        "UnsatisfiedLinkError|UnsupportedClassVersionError|VerifyError|"+
+        "InstantiationException|IndexOutOfBoundsException|"+
+        "ArrayIndexOutOfBoundsException|CloneNotSupportedException|"+
+        "NoSuchFieldException|IllegalArgumentException|NumberFormatException|"+
+        "SecurityException|Void|InheritableThreadLocal|IllegalStateException|"+
+        "InterruptedException|NoSuchMethodException|IllegalAccessException|"+
+        "UnsupportedOperationException|Enum|StrictMath|Package|Compiler|"+
+        "Readable|Runtime|StringBuilder|Math|IncompatibleClassChangeError|"+
+        "NoSuchMethodError|ThreadLocal|RuntimePermission|ArithmeticException|"+
+        "NullPointerException|Long|Integer|Short|Byte|Double|Number|Float|"+
+        "Character|Boolean|StackTraceElement|Appendable|StringBuffer|"+
+        "Iterable|ThreadGroup|Runnable|Thread|IllegalMonitorStateException|"+
+        "StackOverflowError|OutOfMemoryError|VirtualMachineError|"+
+        "ArrayStoreException|ClassCastException|LinkageError|"+
+        "NoClassDefFoundError|ClassNotFoundException|RuntimeException|"+
+        "Exception|ThreadDeath|Error|Throwable|System|ClassLoader|"+
+        "Cloneable|Class|CharSequence|Comparable|String|Object"
+    );
+
+    var keywordMapper = this.createKeywordMapper({
+        "variable.language": "this",
+        "keyword": keywords,
+        "support.function": langClasses,
+        "constant.language": buildinConstants
+    }, "identifier");
+
+    this.$rules = {
+        "start" : [
+            {
+                token : "comment",
+                regex : "\\/\\/.*$"
+            },
+            DocCommentHighlightRules.getStartRule("doc-start"),
+            {
+                token : "comment", // multi line comment
+                regex : "\\/\\*",
+                next : "comment"
+            }, {
+                token : "string.regexp",
+                regex : "[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"
+            }, {
+                token : "string",
+                regex : '"""',
+                next  : "qqstring"
+            }, {
+                token : "string",
+                regex : "'''",
+                next  : "qstring"
+            }, {
+                token : "string", // single line
+                regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
+            }, {
+                token : "string", // single line
+                regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
+            }, {
+                token : "constant.numeric", // hex
+                regex : "0[xX][0-9a-fA-F]+\\b"
+            }, {
+                token : "constant.numeric", // float
+                regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
+            }, {
+                token : "constant.language.boolean",
+                regex : "(?:true|false)\\b"
+            }, {
+                token : keywordMapper,
+                regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
+            }, {
+                token : "keyword.operator",
+                regex : "\\?:|\\?\\.|\\*\\.|<=>|=~|==~|\\.@|\\*\\.@|\\.&|as|in|is|!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"
+            }, {
+                token : "lparen",
+                regex : "[[({]"
+            }, {
+                token : "rparen",
+                regex : "[\\])}]"
+            }, {
+                token : "text",
+                regex : "\\s+"
+            }
+        ],
+        "comment" : [
+            {
+                token : "comment", // closing comment
+                regex : "\\*\\/",
+                next : "start"
+            }, {
+                defaultToken : "comment"
+            }
+        ],
+        "qqstring" : [
+            {
+                token : "constant.language.escape",
+                regex : /\\(?:u[0-9A-Fa-f]{4}|.|$)/
+            }, {
+                token : "constant.language.escape",
+                regex : /\$[\w\d]+/
+            }, {
+                token : "constant.language.escape",
+                regex : /\$\{[^"\}]+\}?/
+            }, {
+                token : "string",
+                regex : '"{3,5}',
+                next : "start"
+            }, {
+                token : "string",
+                regex : '.+?'
+            }
+        ],
+        "qstring" : [
+            {
+                token : "constant.language.escape",
+                regex : /\\(?:u[0-9A-Fa-f]{4}|.|$)/
+            }, {
+                token : "string",
+                regex : "'{3,5}",
+                next : "start"
+            }, {
+                token : "string",
+                regex : ".+?"
+            }
+        ]
+    };
+
+    this.embedRules(DocCommentHighlightRules, "doc-",
+        [ DocCommentHighlightRules.getEndRule("start") ]);
+};
+
+oop.inherits(GroovyHighlightRules, TextHighlightRules);
+
+exports.GroovyHighlightRules = GroovyHighlightRules;
+});
+
+ace.define("ace/mode/groovy",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var JavaScriptMode = require("./javascript").Mode;
+var GroovyHighlightRules = require("./groovy_highlight_rules").GroovyHighlightRules;
+
+var Mode = function() {
+    JavaScriptMode.call(this);
+    this.HighlightRules = GroovyHighlightRules;
+};
+oop.inherits(Mode, JavaScriptMode);
+
+(function() {
+
+    this.createWorker = function(session) {
+        return null;
+    };
+
+    this.$id = "ace/mode/groovy";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/groovy"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

Fișier diff suprimat deoarece este prea mare
+ 6 - 0
services/web/public/js/ace-1.4.3/mode-haml.js


Fișier diff suprimat deoarece este prea mare
+ 797 - 0
services/web/public/js/ace-1.4.3/mode-handlebars.js


+ 380 - 0
services/web/public/js/ace-1.4.3/mode-haskell.js

@@ -0,0 +1,380 @@
+ace.define("ace/mode/haskell_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var HaskellHighlightRules = function() {
+
+    this.$rules = { start:
+       [ { token:
+            [ 'punctuation.definition.entity.haskell',
+              'keyword.operator.function.infix.haskell',
+              'punctuation.definition.entity.haskell' ],
+           regex: '(`)([a-zA-Z_\']*?)(`)',
+           comment: 'In case this regex seems unusual for an infix operator, note that Haskell allows any ordinary function application (elem 4 [1..10]) to be rewritten as an infix expression (4 `elem` [1..10]).' },
+         { token: 'constant.language.unit.haskell', regex: '\\(\\)' },
+         { token: 'constant.language.empty-list.haskell',
+           regex: '\\[\\]' },
+         { token: 'keyword.other.haskell',
+           regex: '\\b(module|signature)\\b',
+           push:
+            [ { token: 'keyword.other.haskell', regex: '\\bwhere\\b', next: 'pop' },
+              { include: '#module_name' },
+              { include: '#module_exports' },
+              { token: 'invalid', regex: '[a-z]+' },
+              { defaultToken: 'meta.declaration.module.haskell' } ] },
+         { token: 'keyword.other.haskell',
+           regex: '\\bclass\\b',
+           push:
+            [ { token: 'keyword.other.haskell',
+                regex: '\\bwhere\\b',
+                next: 'pop' },
+              { token: 'support.class.prelude.haskell',
+                regex: '\\b(?:Monad|Functor|Eq|Ord|Read|Show|Num|(?:Frac|Ra)tional|Enum|Bounded|Real(?:Frac|Float)?|Integral|Floating)\\b' },
+              { token: 'entity.other.inherited-class.haskell',
+                regex: '[A-Z][A-Za-z_\']*' },
+              { token: 'variable.other.generic-type.haskell',
+                regex: '\\b[a-z][a-zA-Z0-9_\']*\\b' },
+              { defaultToken: 'meta.declaration.class.haskell' } ] },
+         { token: 'keyword.other.haskell',
+           regex: '\\binstance\\b',
+           push:
+            [ { token: 'keyword.other.haskell',
+                regex: '\\bwhere\\b|$',
+                next: 'pop' },
+              { include: '#type_signature' },
+              { defaultToken: 'meta.declaration.instance.haskell' } ] },
+         { token: 'keyword.other.haskell',
+           regex: 'import',
+           push:
+            [ { token: 'meta.import.haskell', regex: '$|;|^', next: 'pop' },
+              { token: 'keyword.other.haskell', regex: 'qualified|as|hiding' },
+              { include: '#module_name' },
+              { include: '#module_exports' },
+              { defaultToken: 'meta.import.haskell' } ] },
+         { token: [ 'keyword.other.haskell', 'meta.deriving.haskell' ],
+           regex: '(deriving)(\\s*\\()',
+           push:
+            [ { token: 'meta.deriving.haskell', regex: '\\)', next: 'pop' },
+              { token: 'entity.other.inherited-class.haskell',
+                regex: '\\b[A-Z][a-zA-Z_\']*' },
+              { defaultToken: 'meta.deriving.haskell' } ] },
+         { token: 'keyword.other.haskell',
+           regex: '\\b(?:deriving|where|data|type|case|of|let|in|newtype|default)\\b' },
+         { token: 'keyword.operator.haskell', regex: '\\binfix[lr]?\\b' },
+         { token: 'keyword.control.haskell',
+           regex: '\\b(?:do|if|then|else)\\b' },
+         { token: 'constant.numeric.float.haskell',
+           regex: '\\b(?:[0-9]+\\.[0-9]+(?:[eE][+-]?[0-9]+)?|[0-9]+[eE][+-]?[0-9]+)\\b',
+           comment: 'Floats are always decimal' },
+         { token: 'constant.numeric.haskell',
+           regex: '\\b(?:[0-9]+|0(?:[xX][0-9a-fA-F]+|[oO][0-7]+))\\b' },
+         { token:
+            [ 'meta.preprocessor.c',
+              'punctuation.definition.preprocessor.c',
+              'meta.preprocessor.c' ],
+           regex: '^(\\s*)(#)(\\s*\\w+)',
+           comment: 'In addition to Haskell\'s "native" syntax, GHC permits the C preprocessor to be run on a source file.' },
+         { include: '#pragma' },
+         { token: 'punctuation.definition.string.begin.haskell',
+           regex: '"',
+           push:
+            [ { token: 'punctuation.definition.string.end.haskell',
+                regex: '"',
+                next: 'pop' },
+              { token: 'constant.character.escape.haskell',
+                regex: '\\\\(?:NUL|SOH|STX|ETX|EOT|ENQ|ACK|BEL|BS|HT|LF|VT|FF|CR|SO|SI|DLE|DC1|DC2|DC3|DC4|NAK|SYN|ETB|CAN|EM|SUB|ESC|FS|GS|RS|US|SP|DEL|[abfnrtv\\\\\\"\'\\&])' },
+              { token: 'constant.character.escape.octal.haskell',
+                regex: '\\\\o[0-7]+|\\\\x[0-9A-Fa-f]+|\\\\[0-9]+' },
+              { token: 'constant.character.escape.control.haskell',
+                regex: '\\^[A-Z@\\[\\]\\\\\\^_]' },
+              { defaultToken: 'string.quoted.double.haskell' } ] },
+         { token:
+            [ 'punctuation.definition.string.begin.haskell',
+              'string.quoted.single.haskell',
+              'constant.character.escape.haskell',
+              'constant.character.escape.octal.haskell',
+              'constant.character.escape.hexadecimal.haskell',
+              'constant.character.escape.control.haskell',
+              'punctuation.definition.string.end.haskell' ],
+           regex: '(\')(?:([\\ -\\[\\]-~])|(\\\\(?:NUL|SOH|STX|ETX|EOT|ENQ|ACK|BEL|BS|HT|LF|VT|FF|CR|SO|SI|DLE|DC1|DC2|DC3|DC4|NAK|SYN|ETB|CAN|EM|SUB|ESC|FS|GS|RS|US|SP|DEL|[abfnrtv\\\\\\"\'\\&]))|(\\\\o[0-7]+)|(\\\\x[0-9A-Fa-f]+)|(\\^[A-Z@\\[\\]\\\\\\^_]))(\')' },
+         { token:
+            [ 'meta.function.type-declaration.haskell',
+              'entity.name.function.haskell',
+              'meta.function.type-declaration.haskell',
+              'keyword.other.double-colon.haskell' ],
+           regex: '^(\\s*)([a-z_][a-zA-Z0-9_\']*|\\([|!%$+\\-.,=</>]+\\))(\\s*)(::)',
+           push:
+            [ { token: 'meta.function.type-declaration.haskell',
+                regex: '$',
+                next: 'pop' },
+              { include: '#type_signature' },
+              { defaultToken: 'meta.function.type-declaration.haskell' } ] },
+         { token: 'support.constant.haskell',
+           regex: '\\b(?:Just|Nothing|Left|Right|True|False|LT|EQ|GT|\\(\\)|\\[\\])\\b' },
+         { token: 'constant.other.haskell', regex: '\\b[A-Z]\\w*\\b' },
+         { include: '#comments' },
+         { token: 'support.function.prelude.haskell',
+           regex: '\\b(?:abs|acos|acosh|all|and|any|appendFile|applyM|asTypeOf|asin|asinh|atan|atan2|atanh|break|catch|ceiling|compare|concat|concatMap|const|cos|cosh|curry|cycle|decodeFloat|div|divMod|drop|dropWhile|elem|encodeFloat|enumFrom|enumFromThen|enumFromThenTo|enumFromTo|error|even|exp|exponent|fail|filter|flip|floatDigits|floatRadix|floatRange|floor|fmap|foldl|foldl1|foldr|foldr1|fromEnum|fromInteger|fromIntegral|fromRational|fst|gcd|getChar|getContents|getLine|head|id|init|interact|ioError|isDenormalized|isIEEE|isInfinite|isNaN|isNegativeZero|iterate|last|lcm|length|lex|lines|log|logBase|lookup|map|mapM|mapM_|max|maxBound|maximum|maybe|min|minBound|minimum|mod|negate|not|notElem|null|odd|or|otherwise|pi|pred|print|product|properFraction|putChar|putStr|putStrLn|quot|quotRem|read|readFile|readIO|readList|readLn|readParen|reads|readsPrec|realToFrac|recip|rem|repeat|replicate|return|reverse|round|scaleFloat|scanl|scanl1|scanr|scanr1|seq|sequence|sequence_|show|showChar|showList|showParen|showString|shows|showsPrec|significand|signum|sin|sinh|snd|span|splitAt|sqrt|subtract|succ|sum|tail|take|takeWhile|tan|tanh|toEnum|toInteger|toRational|truncate|uncurry|undefined|unlines|until|unwords|unzip|unzip3|userError|words|writeFile|zip|zip3|zipWith|zipWith3)\\b' },
+         { include: '#infix_op' },
+         { token: 'keyword.operator.haskell',
+           regex: '[|!%$?~+:\\-.=</>\\\\]+',
+           comment: 'In case this regex seems overly general, note that Haskell permits the definition of new operators which can be nearly any string of punctuation characters, such as $%^&*.' },
+         { token: 'punctuation.separator.comma.haskell', regex: ',' } ],
+      '#block_comment':
+       [ { token: 'punctuation.definition.comment.haskell',
+           regex: '\\{-(?!#)',
+           push:
+            [ { include: '#block_comment' },
+              { token: 'punctuation.definition.comment.haskell',
+                regex: '-\\}',
+                next: 'pop' },
+              { defaultToken: 'comment.block.haskell' } ] } ],
+      '#comments':
+       [ { token: 'punctuation.definition.comment.haskell',
+           regex: '--.*',
+           push_:
+            [ { token: 'comment.line.double-dash.haskell',
+                regex: '$',
+                next: 'pop' },
+              { defaultToken: 'comment.line.double-dash.haskell' } ] },
+         { include: '#block_comment' } ],
+      '#infix_op':
+       [ { token: 'entity.name.function.infix.haskell',
+           regex: '\\([|!%$+:\\-.=</>]+\\)|\\(,+\\)' } ],
+      '#module_exports':
+       [ { token: 'meta.declaration.exports.haskell',
+           regex: '\\(',
+           push:
+            [ { token: 'meta.declaration.exports.haskell.end',
+                regex: '\\)',
+                next: 'pop' },
+              { token: 'entity.name.function.haskell',
+                regex: '\\b[a-z][a-zA-Z_\']*' },
+              { token: 'storage.type.haskell', regex: '\\b[A-Z][A-Za-z_\']*' },
+              { token: 'punctuation.separator.comma.haskell', regex: ',' },
+              { include: '#infix_op' },
+              { token: 'meta.other.unknown.haskell',
+                regex: '\\(.*?\\)',
+                comment: 'So named because I don\'t know what to call this.' },
+              { defaultToken: 'meta.declaration.exports.haskell.end' } ] } ],
+      '#module_name':
+       [ { token: 'support.other.module.haskell',
+           regex: '[A-Z][A-Za-z._\']*' } ],
+      '#pragma':
+       [ { token: 'meta.preprocessor.haskell',
+           regex: '\\{-#',
+           push:
+            [ { token: 'meta.preprocessor.haskell',
+                regex: '#-\\}',
+                next: 'pop' },
+              { token: 'keyword.other.preprocessor.haskell',
+                regex: '\\b(?:LANGUAGE|UNPACK|INLINE)\\b' },
+              { defaultToken: 'meta.preprocessor.haskell' } ] } ],
+      '#type_signature':
+       [ { token:
+            [ 'meta.class-constraint.haskell',
+              'entity.other.inherited-class.haskell',
+              'meta.class-constraint.haskell',
+              'variable.other.generic-type.haskell',
+              'meta.class-constraint.haskell',
+              'keyword.other.big-arrow.haskell' ],
+           regex: '(\\(\\s*)([A-Z][A-Za-z]*)(\\s+)([a-z][A-Za-z_\']*)(\\)\\s*)(=>)' },
+         { include: '#pragma' },
+         { token: 'keyword.other.arrow.haskell', regex: '->' },
+         { token: 'keyword.other.big-arrow.haskell', regex: '=>' },
+         { token: 'support.type.prelude.haskell',
+           regex: '\\b(?:Int(?:eger)?|Maybe|Either|Bool|Float|Double|Char|String|Ordering|ShowS|ReadS|FilePath|IO(?:Error)?)\\b' },
+         { token: 'variable.other.generic-type.haskell',
+           regex: '\\b[a-z][a-zA-Z0-9_\']*\\b' },
+         { token: 'storage.type.haskell',
+           regex: '\\b[A-Z][a-zA-Z0-9_\']*\\b' },
+         { token: 'support.constant.unit.haskell', regex: '\\(\\)' },
+         { include: '#comments' } ] };
+
+    this.normalizeRules();
+};
+
+HaskellHighlightRules.metaData = { fileTypes: [ 'hs' ],
+      keyEquivalent: '^~H',
+      name: 'Haskell',
+      scopeName: 'source.haskell' };
+
+
+oop.inherits(HaskellHighlightRules, TextHighlightRules);
+
+exports.HaskellHighlightRules = HaskellHighlightRules;
+});
+
+ace.define("ace/mode/folding/cstyle",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Range = require("../../range").Range;
+var BaseFoldMode = require("./fold_mode").FoldMode;
+
+var FoldMode = exports.FoldMode = function(commentRegex) {
+    if (commentRegex) {
+        this.foldingStartMarker = new RegExp(
+            this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start)
+        );
+        this.foldingStopMarker = new RegExp(
+            this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end)
+        );
+    }
+};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+    
+    this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/;
+    this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/;
+    this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/;
+    this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/;
+    this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/;
+    this._getFoldWidgetBase = this.getFoldWidget;
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+    
+        if (this.singleLineBlockCommentRe.test(line)) {
+            if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line))
+                return "";
+        }
+    
+        var fw = this._getFoldWidgetBase(session, foldStyle, row);
+    
+        if (!fw && this.startRegionRe.test(line))
+            return "start"; // lineCommentRegionStart
+    
+        return fw;
+    };
+
+    this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) {
+        var line = session.getLine(row);
+        
+        if (this.startRegionRe.test(line))
+            return this.getCommentRegionBlock(session, line, row);
+        
+        var match = line.match(this.foldingStartMarker);
+        if (match) {
+            var i = match.index;
+
+            if (match[1])
+                return this.openingBracketBlock(session, match[1], row, i);
+                
+            var range = session.getCommentFoldRange(row, i + match[0].length, 1);
+            
+            if (range && !range.isMultiLine()) {
+                if (forceMultiline) {
+                    range = this.getSectionRange(session, row);
+                } else if (foldStyle != "all")
+                    range = null;
+            }
+            
+            return range;
+        }
+
+        if (foldStyle === "markbegin")
+            return;
+
+        var match = line.match(this.foldingStopMarker);
+        if (match) {
+            var i = match.index + match[0].length;
+
+            if (match[1])
+                return this.closingBracketBlock(session, match[1], row, i);
+
+            return session.getCommentFoldRange(row, i, -1);
+        }
+    };
+    
+    this.getSectionRange = function(session, row) {
+        var line = session.getLine(row);
+        var startIndent = line.search(/\S/);
+        var startRow = row;
+        var startColumn = line.length;
+        row = row + 1;
+        var endRow = row;
+        var maxRow = session.getLength();
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var indent = line.search(/\S/);
+            if (indent === -1)
+                continue;
+            if  (startIndent > indent)
+                break;
+            var subRange = this.getFoldWidgetRange(session, "all", row);
+            
+            if (subRange) {
+                if (subRange.start.row <= startRow) {
+                    break;
+                } else if (subRange.isMultiLine()) {
+                    row = subRange.end.row;
+                } else if (startIndent == indent) {
+                    break;
+                }
+            }
+            endRow = row;
+        }
+        
+        return new Range(startRow, startColumn, endRow, session.getLine(endRow).length);
+    };
+    this.getCommentRegionBlock = function(session, line, row) {
+        var startColumn = line.search(/\s*$/);
+        var maxRow = session.getLength();
+        var startRow = row;
+        
+        var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/;
+        var depth = 1;
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var m = re.exec(line);
+            if (!m) continue;
+            if (m[1]) depth--;
+            else depth++;
+
+            if (!depth) break;
+        }
+
+        var endRow = row;
+        if (endRow > startRow) {
+            return new Range(startRow, startColumn, endRow, line.length);
+        }
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/haskell",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var HaskellHighlightRules = require("./haskell_highlight_rules").HaskellHighlightRules;
+var FoldMode = require("./folding/cstyle").FoldMode;
+
+var Mode = function() {
+    this.HighlightRules = HaskellHighlightRules;
+    this.foldingRules = new FoldMode();
+    this.$behaviour = this.$defaultBehaviour;
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+    this.lineCommentStart = "--";
+    this.blockComment = null;
+    this.$id = "ace/mode/haskell";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/haskell"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 142 - 0
services/web/public/js/ace-1.4.3/mode-haskell_cabal.js

@@ -0,0 +1,142 @@
+ace.define("ace/mode/haskell_cabal_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var CabalHighlightRules = function() {
+    this.$rules = {
+        "start" : [
+            {
+                token : "comment",
+                regex : "^\\s*--.*$"
+            }, {
+                token: ["keyword"],
+                regex: /^(\s*\w.*?)(:(?:\s+|$))/
+            }, {
+                token : "constant.numeric", // float
+                regex : /[\d_]+(?:(?:[\.\d_]*)?)/
+            }, {
+                token : "constant.language.boolean",
+                regex : "(?:true|false|TRUE|FALSE|True|False|yes|no)\\b"
+            }, {
+                token : "markup.heading",
+                regex : /^(\w.*)$/
+            }
+        ]};
+
+};
+
+oop.inherits(CabalHighlightRules, TextHighlightRules);
+
+exports.CabalHighlightRules = CabalHighlightRules;
+});
+
+ace.define("ace/mode/folding/haskell_cabal",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var BaseFoldMode = require("./fold_mode").FoldMode;
+var Range = require("../../range").Range;
+
+var FoldMode = exports.FoldMode = function() {};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+  this.isHeading = function (session,row) {
+      var heading = "markup.heading";
+      var token = session.getTokens(row)[0];
+      return row==0 || (token && token.type.lastIndexOf(heading, 0) === 0);
+  };
+
+  this.getFoldWidget = function(session, foldStyle, row) {
+      if (this.isHeading(session,row)){
+        return "start";
+      } else if (foldStyle === "markbeginend" && !(/^\s*$/.test(session.getLine(row)))){
+        var maxRow = session.getLength();
+        while (++row < maxRow) {
+          if (!(/^\s*$/.test(session.getLine(row)))){
+              break;
+          }
+        }
+        if (row==maxRow || this.isHeading(session,row)){
+          return "end";
+        }
+      }
+      return "";
+  };
+
+
+  this.getFoldWidgetRange = function(session, foldStyle, row) {
+      var line = session.getLine(row);
+      var startColumn = line.length;
+      var maxRow = session.getLength();
+      var startRow = row;
+      var endRow = row;
+      if (this.isHeading(session,row)) {
+          while (++row < maxRow) {
+              if (this.isHeading(session,row)){
+                row--;
+                break;
+              }
+          }
+
+          endRow = row;
+          if (endRow > startRow) {
+              while (endRow > startRow && /^\s*$/.test(session.getLine(endRow)))
+                  endRow--;
+          }
+
+          if (endRow > startRow) {
+              var endColumn = session.getLine(endRow).length;
+              return new Range(startRow, startColumn, endRow, endColumn);
+          }
+      } else if (this.getFoldWidget(session, foldStyle, row)==="end"){
+        var endRow = row;
+        var endColumn = session.getLine(endRow).length;
+        while (--row>=0){
+          if (this.isHeading(session,row)){
+            break;
+          }
+        }
+        var line = session.getLine(row);
+        var startColumn = line.length;
+        return new Range(row, startColumn, endRow, endColumn);
+      }
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/haskell_cabal",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var CabalHighlightRules = require("./haskell_cabal_highlight_rules").CabalHighlightRules;
+var FoldMode = require("./folding/haskell_cabal").FoldMode;
+
+var Mode = function() {
+    this.HighlightRules = CabalHighlightRules;
+    this.foldingRules = new FoldMode();
+    this.$behaviour = this.$defaultBehaviour;
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+    this.lineCommentStart = "--";
+    this.blockComment = null;
+    this.$id = "ace/mode/haskell_cabal";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/haskell_cabal"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 387 - 0
services/web/public/js/ace-1.4.3/mode-haxe.js

@@ -0,0 +1,387 @@
+ace.define("ace/mode/doc_comment_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var DocCommentHighlightRules = function() {
+    this.$rules = {
+        "start" : [ {
+            token : "comment.doc.tag",
+            regex : "@[\\w\\d_]+" // TODO: fix email addresses
+        }, 
+        DocCommentHighlightRules.getTagRule(),
+        {
+            defaultToken : "comment.doc",
+            caseInsensitive: true
+        }]
+    };
+};
+
+oop.inherits(DocCommentHighlightRules, TextHighlightRules);
+
+DocCommentHighlightRules.getTagRule = function(start) {
+    return {
+        token : "comment.doc.tag.storage.type",
+        regex : "\\b(?:TODO|FIXME|XXX|HACK)\\b"
+    };
+};
+
+DocCommentHighlightRules.getStartRule = function(start) {
+    return {
+        token : "comment.doc", // doc comment
+        regex : "\\/\\*(?=\\*)",
+        next  : start
+    };
+};
+
+DocCommentHighlightRules.getEndRule = function (start) {
+    return {
+        token : "comment.doc", // closing comment
+        regex : "\\*\\/",
+        next  : start
+    };
+};
+
+
+exports.DocCommentHighlightRules = DocCommentHighlightRules;
+
+});
+
+ace.define("ace/mode/haxe_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+
+var DocCommentHighlightRules = require("./doc_comment_highlight_rules").DocCommentHighlightRules;
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var HaxeHighlightRules = function() {
+
+    var keywords = (
+        "break|case|cast|catch|class|continue|default|else|enum|extends|for|function|if|implements|import|in|inline|interface|new|override|package|private|public|return|static|super|switch|this|throw|trace|try|typedef|untyped|var|while|Array|Void|Bool|Int|UInt|Float|Dynamic|String|List|Hash|IntHash|Error|Unknown|Type|Std"
+    );
+
+    var buildinConstants = (
+        "null|true|false"
+    );
+
+    var keywordMapper = this.createKeywordMapper({
+        "variable.language": "this",
+        "keyword": keywords,
+        "constant.language": buildinConstants
+    }, "identifier");
+
+    this.$rules = {
+        "start" : [
+            {
+                token : "comment",
+                regex : "\\/\\/.*$"
+            },
+            DocCommentHighlightRules.getStartRule("doc-start"),
+            {
+                token : "comment", // multi line comment
+                regex : "\\/\\*",
+                next : "comment"
+            }, {
+                token : "string.regexp",
+                regex : "[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"
+            }, {
+                token : "string", // single line
+                regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
+            }, {
+                token : "string", // single line
+                regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
+            }, {
+                token : "constant.numeric", // hex
+                regex : "0[xX][0-9a-fA-F]+\\b"
+            }, {
+                token : "constant.numeric", // float
+                regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
+            }, {
+                token : "constant.language.boolean",
+                regex : "(?:true|false)\\b"
+            }, {
+                token : keywordMapper,
+                regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
+            }, {
+                token : "keyword.operator",
+                regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"
+            }, {
+                token : "punctuation.operator",
+                regex : "\\?|\\:|\\,|\\;|\\."
+            }, {
+                token : "paren.lparen",
+                regex : "[[({<]"
+            }, {
+                token : "paren.rparen",
+                regex : "[\\])}>]"
+            }, {
+                token : "text",
+                regex : "\\s+"
+            }
+        ],
+        "comment" : [
+            {
+                token : "comment", // closing comment
+                regex : "\\*\\/",
+                next : "start"
+            }, {
+                defaultToken : "comment"
+            }
+        ]
+    };
+
+    this.embedRules(DocCommentHighlightRules, "doc-",
+        [ DocCommentHighlightRules.getEndRule("start") ]);
+};
+
+oop.inherits(HaxeHighlightRules, TextHighlightRules);
+
+exports.HaxeHighlightRules = HaxeHighlightRules;
+});
+
+ace.define("ace/mode/matching_brace_outdent",[], function(require, exports, module) {
+"use strict";
+
+var Range = require("../range").Range;
+
+var MatchingBraceOutdent = function() {};
+
+(function() {
+
+    this.checkOutdent = function(line, input) {
+        if (! /^\s+$/.test(line))
+            return false;
+
+        return /^\s*\}/.test(input);
+    };
+
+    this.autoOutdent = function(doc, row) {
+        var line = doc.getLine(row);
+        var match = line.match(/^(\s*\})/);
+
+        if (!match) return 0;
+
+        var column = match[1].length;
+        var openBracePos = doc.findMatchingBracket({row: row, column: column});
+
+        if (!openBracePos || openBracePos.row == row) return 0;
+
+        var indent = this.$getIndent(doc.getLine(openBracePos.row));
+        doc.replace(new Range(row, 0, row, column-1), indent);
+    };
+
+    this.$getIndent = function(line) {
+        return line.match(/^\s*/)[0];
+    };
+
+}).call(MatchingBraceOutdent.prototype);
+
+exports.MatchingBraceOutdent = MatchingBraceOutdent;
+});
+
+ace.define("ace/mode/folding/cstyle",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Range = require("../../range").Range;
+var BaseFoldMode = require("./fold_mode").FoldMode;
+
+var FoldMode = exports.FoldMode = function(commentRegex) {
+    if (commentRegex) {
+        this.foldingStartMarker = new RegExp(
+            this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start)
+        );
+        this.foldingStopMarker = new RegExp(
+            this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end)
+        );
+    }
+};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+    
+    this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/;
+    this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/;
+    this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/;
+    this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/;
+    this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/;
+    this._getFoldWidgetBase = this.getFoldWidget;
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+    
+        if (this.singleLineBlockCommentRe.test(line)) {
+            if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line))
+                return "";
+        }
+    
+        var fw = this._getFoldWidgetBase(session, foldStyle, row);
+    
+        if (!fw && this.startRegionRe.test(line))
+            return "start"; // lineCommentRegionStart
+    
+        return fw;
+    };
+
+    this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) {
+        var line = session.getLine(row);
+        
+        if (this.startRegionRe.test(line))
+            return this.getCommentRegionBlock(session, line, row);
+        
+        var match = line.match(this.foldingStartMarker);
+        if (match) {
+            var i = match.index;
+
+            if (match[1])
+                return this.openingBracketBlock(session, match[1], row, i);
+                
+            var range = session.getCommentFoldRange(row, i + match[0].length, 1);
+            
+            if (range && !range.isMultiLine()) {
+                if (forceMultiline) {
+                    range = this.getSectionRange(session, row);
+                } else if (foldStyle != "all")
+                    range = null;
+            }
+            
+            return range;
+        }
+
+        if (foldStyle === "markbegin")
+            return;
+
+        var match = line.match(this.foldingStopMarker);
+        if (match) {
+            var i = match.index + match[0].length;
+
+            if (match[1])
+                return this.closingBracketBlock(session, match[1], row, i);
+
+            return session.getCommentFoldRange(row, i, -1);
+        }
+    };
+    
+    this.getSectionRange = function(session, row) {
+        var line = session.getLine(row);
+        var startIndent = line.search(/\S/);
+        var startRow = row;
+        var startColumn = line.length;
+        row = row + 1;
+        var endRow = row;
+        var maxRow = session.getLength();
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var indent = line.search(/\S/);
+            if (indent === -1)
+                continue;
+            if  (startIndent > indent)
+                break;
+            var subRange = this.getFoldWidgetRange(session, "all", row);
+            
+            if (subRange) {
+                if (subRange.start.row <= startRow) {
+                    break;
+                } else if (subRange.isMultiLine()) {
+                    row = subRange.end.row;
+                } else if (startIndent == indent) {
+                    break;
+                }
+            }
+            endRow = row;
+        }
+        
+        return new Range(startRow, startColumn, endRow, session.getLine(endRow).length);
+    };
+    this.getCommentRegionBlock = function(session, line, row) {
+        var startColumn = line.search(/\s*$/);
+        var maxRow = session.getLength();
+        var startRow = row;
+        
+        var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/;
+        var depth = 1;
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var m = re.exec(line);
+            if (!m) continue;
+            if (m[1]) depth--;
+            else depth++;
+
+            if (!depth) break;
+        }
+
+        var endRow = row;
+        if (endRow > startRow) {
+            return new Range(startRow, startColumn, endRow, line.length);
+        }
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/haxe",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var HaxeHighlightRules = require("./haxe_highlight_rules").HaxeHighlightRules;
+var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent;
+var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour;
+var CStyleFoldMode = require("./folding/cstyle").FoldMode;
+
+var Mode = function() {
+    this.HighlightRules = HaxeHighlightRules;
+    
+    this.$outdent = new MatchingBraceOutdent();
+    this.$behaviour = new CstyleBehaviour();
+    this.foldingRules = new CStyleFoldMode();
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+    this.lineCommentStart = "//";
+    this.blockComment = {start: "/*", end: "*/"};
+    
+    this.getNextLineIndent = function(state, line, tab) {
+        var indent = this.$getIndent(line);
+
+        var tokenizedLine = this.getTokenizer().getLineTokens(line, state);
+        var tokens = tokenizedLine.tokens;
+
+        if (tokens.length && tokens[tokens.length-1].type == "comment") {
+            return indent;
+        }
+
+        if (state == "start") {
+            var match = line.match(/^.*[\{\(\[]\s*$/);
+            if (match) {
+                indent += tab;
+            }
+        }
+
+        return indent;
+    };
+
+    this.checkOutdent = function(state, line, input) {
+        return this.$outdent.checkOutdent(line, input);
+    };
+
+    this.autoOutdent = function(state, doc, row) {
+        this.$outdent.autoOutdent(doc, row);
+    };
+
+    this.$id = "ace/mode/haxe";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/haxe"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 354 - 0
services/web/public/js/ace-1.4.3/mode-hjson.js

@@ -0,0 +1,354 @@
+ace.define("ace/mode/hjson_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var HjsonHighlightRules = function() {
+
+    this.$rules = {
+        start: [{
+            include: "#comments"
+        }, {
+            include: "#rootObject"
+        }, {
+            include: "#value"
+        }],
+        "#array": [{
+            token: "paren.lparen",
+            regex: /\[/,
+            push: [{
+                token: "paren.rparen",
+                regex: /\]/,
+                next: "pop"
+            }, {
+                include: "#value"
+            }, {
+                include: "#comments"
+            }, {
+                token: "text",
+                regex: /,|$/
+            }, {
+                token: "invalid.illegal",
+                regex: /[^\s\]]/
+            }, {
+                defaultToken: "array"
+            }]
+        }],
+        "#comments": [{
+            token: [
+                "comment.punctuation",
+                "comment.line"
+            ],
+            regex: /(#)(.*$)/
+        }, {
+            token: "comment.punctuation",
+            regex: /\/\*/,
+            push: [{
+                token: "comment.punctuation",
+                regex: /\*\//,
+                next: "pop"
+            }, {
+                defaultToken: "comment.block"
+            }]
+        }, {
+            token: [
+                "comment.punctuation",
+                "comment.line"
+            ],
+            regex: /(\/\/)(.*$)/
+        }],
+        "#constant": [{
+            token: "constant",
+            regex: /\b(?:true|false|null)\b/
+        }],
+        "#keyname": [{
+            token: "keyword",
+            regex: /(?:[^,\{\[\}\]\s]+|"(?:[^"\\]|\\.)*")\s*(?=:)/
+        }],
+        "#mstring": [{
+            token: "string",
+            regex: /'''/,
+            push: [{
+                token: "string",
+                regex: /'''/,
+                next: "pop"
+            }, {
+                defaultToken: "string"
+            }]
+        }],
+        "#number": [{
+            token: "constant.numeric",
+            regex: /-?(?:0|[1-9]\d*)(?:(?:\.\d+)?(?:[eE][+-]?\d+)?)?/,
+            comment: "handles integer and decimal numbers"
+        }],
+        "#object": [{
+            token: "paren.lparen",
+            regex: /\{/,
+            push: [{
+                token: "paren.rparen",
+                regex: /\}/,
+                next: "pop"
+            }, {
+                include: "#keyname"
+            }, {
+                include: "#value"
+            }, {
+                token: "text",
+                regex: /:/
+            }, {
+                token: "text",
+                regex: /,/
+            }, {
+                defaultToken: "paren"
+            }]
+        }],
+        "#rootObject": [{
+            token: "paren",
+            regex: /(?=\s*(?:[^,\{\[\}\]\s]+|"(?:[^"\\]|\\.)*")\s*:)/,
+            push: [{
+                token: "paren.rparen",
+                regex: /---none---/,
+                next: "pop"
+            }, {
+                include: "#keyname"
+            }, {
+                include: "#value"
+            }, {
+                token: "text",
+                regex: /:/
+            }, {
+                token: "text",
+                regex: /,/
+            }, {
+                defaultToken: "paren"
+            }]
+        }],
+        "#string": [{
+            token: "string",
+            regex: /"/,
+            push: [{
+                token: "string",
+                regex: /"/,
+                next: "pop"
+            }, {
+                token: "constant.language.escape",
+                regex: /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/
+            }, {
+                token: "invalid.illegal",
+                regex: /\\./
+            }, {
+                defaultToken: "string"
+            }]
+        }],
+        "#ustring": [{
+            token: "string",
+            regex: /\b[^:,0-9\-\{\[\}\]\s].*$/
+        }],
+        "#value": [{
+            include: "#constant"
+        }, {
+            include: "#number"
+        }, {
+            include: "#string"
+        }, {
+            include: "#array"
+        }, {
+            include: "#object"
+        }, {
+            include: "#comments"
+        }, {
+            include: "#mstring"
+        }, {
+            include: "#ustring"
+        }]
+    };
+
+    this.normalizeRules();
+};
+
+HjsonHighlightRules.metaData = {
+    fileTypes: ["hjson"],
+    foldingStartMarker: "(?x:     # turn on extended mode\n              ^    # a line beginning with\n              \\s*    # some optional space\n              [{\\[]  # the start of an object or array\n              (?!    # but not followed by\n              .*   # whatever\n              [}\\]]  # and the close of an object or array\n              ,?   # an optional comma\n              \\s*  # some optional space\n              $    # at the end of the line\n              )\n              |    # ...or...\n              [{\\[]  # the start of an object or array\n              \\s*    # some optional space\n              $    # at the end of the line\n            )",
+    foldingStopMarker: "(?x:   # turn on extended mode\n             ^    # a line beginning with\n             \\s*  # some optional space\n             [}\\]]  # and the close of an object or array\n             )",
+    keyEquivalent: "^~J",
+    name: "Hjson",
+    scopeName: "source.hjson"
+};
+
+
+oop.inherits(HjsonHighlightRules, TextHighlightRules);
+
+exports.HjsonHighlightRules = HjsonHighlightRules;
+});
+
+ace.define("ace/mode/folding/cstyle",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Range = require("../../range").Range;
+var BaseFoldMode = require("./fold_mode").FoldMode;
+
+var FoldMode = exports.FoldMode = function(commentRegex) {
+    if (commentRegex) {
+        this.foldingStartMarker = new RegExp(
+            this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start)
+        );
+        this.foldingStopMarker = new RegExp(
+            this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end)
+        );
+    }
+};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+    
+    this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/;
+    this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/;
+    this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/;
+    this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/;
+    this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/;
+    this._getFoldWidgetBase = this.getFoldWidget;
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+    
+        if (this.singleLineBlockCommentRe.test(line)) {
+            if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line))
+                return "";
+        }
+    
+        var fw = this._getFoldWidgetBase(session, foldStyle, row);
+    
+        if (!fw && this.startRegionRe.test(line))
+            return "start"; // lineCommentRegionStart
+    
+        return fw;
+    };
+
+    this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) {
+        var line = session.getLine(row);
+        
+        if (this.startRegionRe.test(line))
+            return this.getCommentRegionBlock(session, line, row);
+        
+        var match = line.match(this.foldingStartMarker);
+        if (match) {
+            var i = match.index;
+
+            if (match[1])
+                return this.openingBracketBlock(session, match[1], row, i);
+                
+            var range = session.getCommentFoldRange(row, i + match[0].length, 1);
+            
+            if (range && !range.isMultiLine()) {
+                if (forceMultiline) {
+                    range = this.getSectionRange(session, row);
+                } else if (foldStyle != "all")
+                    range = null;
+            }
+            
+            return range;
+        }
+
+        if (foldStyle === "markbegin")
+            return;
+
+        var match = line.match(this.foldingStopMarker);
+        if (match) {
+            var i = match.index + match[0].length;
+
+            if (match[1])
+                return this.closingBracketBlock(session, match[1], row, i);
+
+            return session.getCommentFoldRange(row, i, -1);
+        }
+    };
+    
+    this.getSectionRange = function(session, row) {
+        var line = session.getLine(row);
+        var startIndent = line.search(/\S/);
+        var startRow = row;
+        var startColumn = line.length;
+        row = row + 1;
+        var endRow = row;
+        var maxRow = session.getLength();
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var indent = line.search(/\S/);
+            if (indent === -1)
+                continue;
+            if  (startIndent > indent)
+                break;
+            var subRange = this.getFoldWidgetRange(session, "all", row);
+            
+            if (subRange) {
+                if (subRange.start.row <= startRow) {
+                    break;
+                } else if (subRange.isMultiLine()) {
+                    row = subRange.end.row;
+                } else if (startIndent == indent) {
+                    break;
+                }
+            }
+            endRow = row;
+        }
+        
+        return new Range(startRow, startColumn, endRow, session.getLine(endRow).length);
+    };
+    this.getCommentRegionBlock = function(session, line, row) {
+        var startColumn = line.search(/\s*$/);
+        var maxRow = session.getLength();
+        var startRow = row;
+        
+        var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/;
+        var depth = 1;
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var m = re.exec(line);
+            if (!m) continue;
+            if (m[1]) depth--;
+            else depth++;
+
+            if (!depth) break;
+        }
+
+        var endRow = row;
+        if (endRow > startRow) {
+            return new Range(startRow, startColumn, endRow, line.length);
+        }
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/hjson",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var HjsonHighlightRules = require("./hjson_highlight_rules").HjsonHighlightRules;
+var FoldMode = require("./folding/cstyle").FoldMode;
+
+var Mode = function() {
+    this.HighlightRules = HjsonHighlightRules;
+    this.foldingRules = new FoldMode();
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+    this.lineCommentStart = "//";
+    this.blockComment = { start: "/*", end: "*/" };
+    this.$id = "ace/mode/hjson";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/hjson"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

Fișier diff suprimat deoarece este prea mare
+ 797 - 0
services/web/public/js/ace-1.4.3/mode-html.js


Fișier diff suprimat deoarece este prea mare
+ 6 - 0
services/web/public/js/ace-1.4.3/mode-html_elixir.js


Fișier diff suprimat deoarece este prea mare
+ 6 - 0
services/web/public/js/ace-1.4.3/mode-html_ruby.js


+ 163 - 0
services/web/public/js/ace-1.4.3/mode-ini.js

@@ -0,0 +1,163 @@
+ace.define("ace/mode/ini_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var escapeRe = "\\\\(?:[\\\\0abtrn;#=:]|x[a-fA-F\\d]{4})";
+
+var IniHighlightRules = function() {
+    this.$rules = {
+        start: [{
+            token: 'punctuation.definition.comment.ini',
+            regex: '#.*',
+            push_: [{
+                token: 'comment.line.number-sign.ini',
+                regex: '$|^',
+                next: 'pop'
+            }, {
+                defaultToken: 'comment.line.number-sign.ini'
+            }]
+        }, {
+            token: 'punctuation.definition.comment.ini',
+            regex: ';.*',
+            push_: [{
+                token: 'comment.line.semicolon.ini',
+                regex: '$|^',
+                next: 'pop'
+            }, {
+                defaultToken: 'comment.line.semicolon.ini'
+            }]
+        }, {
+            token: ['keyword.other.definition.ini', 'text', 'punctuation.separator.key-value.ini'],
+            regex: '\\b([a-zA-Z0-9_.-]+)\\b(\\s*)(=)'
+        }, {
+            token: ['punctuation.definition.entity.ini', 'constant.section.group-title.ini', 'punctuation.definition.entity.ini'],
+            regex: '^(\\[)(.*?)(\\])'
+        }, {
+            token: 'punctuation.definition.string.begin.ini',
+            regex: "'",
+            push: [{
+                token: 'punctuation.definition.string.end.ini',
+                regex: "'",
+                next: 'pop'
+            }, {
+                token: "constant.language.escape",
+                regex: escapeRe
+            }, {
+                defaultToken: 'string.quoted.single.ini'
+            }]
+        }, {
+            token: 'punctuation.definition.string.begin.ini',
+            regex: '"',
+            push: [{
+                token: "constant.language.escape",
+                regex: escapeRe
+            }, {
+                token: 'punctuation.definition.string.end.ini',
+                regex: '"',
+                next: 'pop'
+            }, {
+                defaultToken: 'string.quoted.double.ini'
+            }]
+        }]
+    };
+
+    this.normalizeRules();
+};
+
+IniHighlightRules.metaData = {
+    fileTypes: ['ini', 'conf'],
+    keyEquivalent: '^~I',
+    name: 'Ini',
+    scopeName: 'source.ini'
+};
+
+
+oop.inherits(IniHighlightRules, TextHighlightRules);
+
+exports.IniHighlightRules = IniHighlightRules;
+});
+
+ace.define("ace/mode/folding/ini",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Range = require("../../range").Range;
+var BaseFoldMode = require("./fold_mode").FoldMode;
+
+var FoldMode = exports.FoldMode = function() {
+};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+
+    this.foldingStartMarker = /^\s*\[([^\])]*)]\s*(?:$|[;#])/;
+
+    this.getFoldWidgetRange = function(session, foldStyle, row) {
+        var re = this.foldingStartMarker;
+        var line = session.getLine(row);
+        
+        var m = line.match(re);
+        
+        if (!m) return;
+        
+        var startName = m[1] + ".";
+        
+        var startColumn = line.length;
+        var maxRow = session.getLength();
+        var startRow = row;
+        var endRow = row;
+
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            if (/^\s*$/.test(line))
+                continue;
+            m = line.match(re);
+            if (m && m[1].lastIndexOf(startName, 0) !== 0)
+                break;
+
+            endRow = row;
+        }
+
+        if (endRow > startRow) {
+            var endColumn = session.getLine(endRow).length;
+            return new Range(startRow, startColumn, endRow, endColumn);
+        }
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/ini",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var IniHighlightRules = require("./ini_highlight_rules").IniHighlightRules;
+var FoldMode = require("./folding/ini").FoldMode;
+
+var Mode = function() {
+    this.HighlightRules = IniHighlightRules;
+    this.foldingRules = new FoldMode();
+    this.$behaviour = this.$defaultBehaviour;
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+    this.lineCommentStart = ";";
+    this.blockComment = null;
+    this.$id = "ace/mode/ini";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/ini"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 254 - 0
services/web/public/js/ace-1.4.3/mode-io.js

@@ -0,0 +1,254 @@
+ace.define("ace/mode/io_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var IoHighlightRules = function() {
+
+    this.$rules = { start: 
+       [ { token: [ 'text', 'meta.empty-parenthesis.io' ],
+           regex: '(\\()(\\))',
+           comment: 'we match this to overload return inside () --Allan; scoping rules for what gets the scope have changed, so we now group the ) instead of the ( -- Rob' },
+         { token: [ 'text', 'meta.comma-parenthesis.io' ],
+           regex: '(\\,)(\\))',
+           comment: 'We want to do the same for ,) -- Seckar; same as above -- Rob' },
+         { token: 'keyword.control.io',
+           regex: '\\b(?:if|ifTrue|ifFalse|ifTrueIfFalse|for|loop|reverseForeach|foreach|map|continue|break|while|do|return)\\b' },
+         { token: 'punctuation.definition.comment.io',
+           regex: '/\\*',
+           push: 
+            [ { token: 'punctuation.definition.comment.io',
+                regex: '\\*/',
+                next: 'pop' },
+              { defaultToken: 'comment.block.io' } ] },
+         { token: 'punctuation.definition.comment.io',
+           regex: '//',
+           push: 
+            [ { token: 'comment.line.double-slash.io',
+                regex: '$',
+                next: 'pop' },
+              { defaultToken: 'comment.line.double-slash.io' } ] },
+         { token: 'punctuation.definition.comment.io',
+           regex: '#',
+           push: 
+            [ { token: 'comment.line.number-sign.io', regex: '$', next: 'pop' },
+              { defaultToken: 'comment.line.number-sign.io' } ] },
+         { token: 'variable.language.io',
+           regex: '\\b(?:self|sender|target|proto|protos|parent)\\b',
+           comment: 'I wonder if some of this isn\'t variable.other.language? --Allan; scoping this as variable.language to match Objective-C\'s handling of \'self\', which is inconsistent with C++\'s handling of \'this\' but perhaps intentionally so -- Rob' },
+         { token: 'keyword.operator.io',
+           regex: '<=|>=|=|:=|\\*|\\||\\|\\||\\+|-|/|&|&&|>|<|\\?|@|@@|\\b(?:and|or)\\b' },
+         { token: 'constant.other.io', regex: '\\bGL[\\w_]+\\b' },
+         { token: 'support.class.io', regex: '\\b[A-Z](?:\\w+)?\\b' },
+         { token: 'support.function.io',
+           regex: '\\b(?:clone|call|init|method|list|vector|block|\\w+(?=\\s*\\())\\b' },
+         { token: 'support.function.open-gl.io',
+           regex: '\\bgl(?:u|ut)?[A-Z]\\w+\\b' },
+         { token: 'punctuation.definition.string.begin.io',
+           regex: '"""',
+           push: 
+            [ { token: 'punctuation.definition.string.end.io',
+                regex: '"""',
+                next: 'pop' },
+              { token: 'constant.character.escape.io', regex: '\\\\.' },
+              { defaultToken: 'string.quoted.triple.io' } ] },
+         { token: 'punctuation.definition.string.begin.io',
+           regex: '"',
+           push: 
+            [ { token: 'punctuation.definition.string.end.io',
+                regex: '"',
+                next: 'pop' },
+              { token: 'constant.character.escape.io', regex: '\\\\.' },
+              { defaultToken: 'string.quoted.double.io' } ] },
+         { token: 'constant.numeric.io',
+           regex: '\\b(?:0(?:x|X)[0-9a-fA-F]*|(?:[0-9]+\\.?[0-9]*|\\.[0-9]+)(?:(?:e|E)(?:\\+|-)?[0-9]+)?)(?:L|l|UL|ul|u|U|F|f)?\\b' },
+         { token: 'variable.other.global.io', regex: 'Lobby\\b' },
+         { token: 'constant.language.io',
+           regex: '\\b(?:TRUE|true|FALSE|false|NULL|null|Null|Nil|nil|YES|NO)\\b' } ] };
+    
+    this.normalizeRules();
+};
+
+IoHighlightRules.metaData = { fileTypes: [ 'io' ],
+      keyEquivalent: '^~I',
+      name: 'Io',
+      scopeName: 'source.io' };
+
+
+oop.inherits(IoHighlightRules, TextHighlightRules);
+
+exports.IoHighlightRules = IoHighlightRules;
+});
+
+ace.define("ace/mode/folding/cstyle",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Range = require("../../range").Range;
+var BaseFoldMode = require("./fold_mode").FoldMode;
+
+var FoldMode = exports.FoldMode = function(commentRegex) {
+    if (commentRegex) {
+        this.foldingStartMarker = new RegExp(
+            this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start)
+        );
+        this.foldingStopMarker = new RegExp(
+            this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end)
+        );
+    }
+};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+    
+    this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/;
+    this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/;
+    this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/;
+    this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/;
+    this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/;
+    this._getFoldWidgetBase = this.getFoldWidget;
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+    
+        if (this.singleLineBlockCommentRe.test(line)) {
+            if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line))
+                return "";
+        }
+    
+        var fw = this._getFoldWidgetBase(session, foldStyle, row);
+    
+        if (!fw && this.startRegionRe.test(line))
+            return "start"; // lineCommentRegionStart
+    
+        return fw;
+    };
+
+    this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) {
+        var line = session.getLine(row);
+        
+        if (this.startRegionRe.test(line))
+            return this.getCommentRegionBlock(session, line, row);
+        
+        var match = line.match(this.foldingStartMarker);
+        if (match) {
+            var i = match.index;
+
+            if (match[1])
+                return this.openingBracketBlock(session, match[1], row, i);
+                
+            var range = session.getCommentFoldRange(row, i + match[0].length, 1);
+            
+            if (range && !range.isMultiLine()) {
+                if (forceMultiline) {
+                    range = this.getSectionRange(session, row);
+                } else if (foldStyle != "all")
+                    range = null;
+            }
+            
+            return range;
+        }
+
+        if (foldStyle === "markbegin")
+            return;
+
+        var match = line.match(this.foldingStopMarker);
+        if (match) {
+            var i = match.index + match[0].length;
+
+            if (match[1])
+                return this.closingBracketBlock(session, match[1], row, i);
+
+            return session.getCommentFoldRange(row, i, -1);
+        }
+    };
+    
+    this.getSectionRange = function(session, row) {
+        var line = session.getLine(row);
+        var startIndent = line.search(/\S/);
+        var startRow = row;
+        var startColumn = line.length;
+        row = row + 1;
+        var endRow = row;
+        var maxRow = session.getLength();
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var indent = line.search(/\S/);
+            if (indent === -1)
+                continue;
+            if  (startIndent > indent)
+                break;
+            var subRange = this.getFoldWidgetRange(session, "all", row);
+            
+            if (subRange) {
+                if (subRange.start.row <= startRow) {
+                    break;
+                } else if (subRange.isMultiLine()) {
+                    row = subRange.end.row;
+                } else if (startIndent == indent) {
+                    break;
+                }
+            }
+            endRow = row;
+        }
+        
+        return new Range(startRow, startColumn, endRow, session.getLine(endRow).length);
+    };
+    this.getCommentRegionBlock = function(session, line, row) {
+        var startColumn = line.search(/\s*$/);
+        var maxRow = session.getLength();
+        var startRow = row;
+        
+        var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/;
+        var depth = 1;
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var m = re.exec(line);
+            if (!m) continue;
+            if (m[1]) depth--;
+            else depth++;
+
+            if (!depth) break;
+        }
+
+        var endRow = row;
+        if (endRow > startRow) {
+            return new Range(startRow, startColumn, endRow, line.length);
+        }
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/io",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var IoHighlightRules = require("./io_highlight_rules").IoHighlightRules;
+var FoldMode = require("./folding/cstyle").FoldMode;
+
+var Mode = function() {
+    this.HighlightRules = IoHighlightRules;
+    this.foldingRules = new FoldMode();
+    this.$behaviour = this.$defaultBehaviour;
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+    this.lineCommentStart = "//";
+    this.blockComment = {start: "/*", end: "*/"};
+    this.$id = "ace/mode/io";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/io"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 347 - 0
services/web/public/js/ace-1.4.3/mode-jack.js

@@ -0,0 +1,347 @@
+ace.define("ace/mode/jack_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var JackHighlightRules = function() {
+    this.$rules = {
+        "start" : [
+            {
+                token : "string",
+                regex : '"',
+                next  : "string2"
+            }, {
+                token : "string",
+                regex : "'",
+                next  : "string1"
+            }, {
+                token : "constant.numeric", // hex
+                regex: "-?0[xX][0-9a-fA-F]+\\b"
+            }, {
+                token : "constant.numeric", // float
+                regex : "(?:0|[-+]?[1-9][0-9]*)\\b"
+            }, {
+                token : "constant.binary",
+                regex : "<[0-9A-Fa-f][0-9A-Fa-f](\\s+[0-9A-Fa-f][0-9A-Fa-f])*>"
+            }, {
+                token : "constant.language.boolean",
+                regex : "(?:true|false)\\b"
+            }, {
+                token : "constant.language.null",
+                regex : "null\\b"
+            }, {
+                token : "storage.type",
+                regex: "(?:Integer|Boolean|Null|String|Buffer|Tuple|List|Object|Function|Coroutine|Form)\\b"
+            }, {
+                token : "keyword",
+                regex : "(?:return|abort|vars|for|delete|in|is|escape|exec|split|and|if|elif|else|while)\\b"
+            }, {
+                token : "language.builtin",
+                regex : "(?:lines|source|parse|read-stream|interval|substr|parseint|write|print|range|rand|inspect|bind|i-values|i-pairs|i-map|i-filter|i-chunk|i-all\\?|i-any\\?|i-collect|i-zip|i-merge|i-each)\\b"
+            }, {
+                token : "comment",
+                regex : "--.*$"
+            }, {
+                token : "paren.lparen",
+                regex : "[[({]"
+            }, {
+                token : "paren.rparen",
+                regex : "[\\])}]"
+            }, {
+                token : "storage.form",
+                regex : "@[a-z]+"
+            }, {
+                token : "constant.other.symbol",
+                regex : ':+[a-zA-Z_]([-]?[a-zA-Z0-9_])*[?!]?'
+            }, {
+                token : "variable",
+                regex : '[a-zA-Z_]([-]?[a-zA-Z0-9_])*[?!]?'
+            }, {
+                token : "keyword.operator",
+                regex : "\\|\\||\\^\\^|&&|!=|==|<=|<|>=|>|\\+|-|\\*|\\/|\\^|\\%|\\#|\\!"
+            }, {
+                token : "text",
+                regex : "\\s+"
+            }
+        ],
+        "string1" : [
+            {
+                token : "constant.language.escape",
+                regex : /\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|['"\\\/bfnrt])/
+            }, {
+                token : "string",
+                regex : "[^'\\\\]+"
+            }, {
+                token : "string",
+                regex : "'",
+                next  : "start"
+            }, {
+                token : "string",
+                regex : "",
+                next  : "start"
+            }
+        ],
+        "string2" : [
+            {
+                token : "constant.language.escape",
+                regex : /\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|['"\\\/bfnrt])/
+            }, {
+                token : "string",
+                regex : '[^"\\\\]+'
+            }, {
+                token : "string",
+                regex : '"',
+                next  : "start"
+            }, {
+                token : "string",
+                regex : "",
+                next  : "start"
+            }
+        ]
+    };
+    
+};
+
+oop.inherits(JackHighlightRules, TextHighlightRules);
+
+exports.JackHighlightRules = JackHighlightRules;
+});
+
+ace.define("ace/mode/matching_brace_outdent",[], function(require, exports, module) {
+"use strict";
+
+var Range = require("../range").Range;
+
+var MatchingBraceOutdent = function() {};
+
+(function() {
+
+    this.checkOutdent = function(line, input) {
+        if (! /^\s+$/.test(line))
+            return false;
+
+        return /^\s*\}/.test(input);
+    };
+
+    this.autoOutdent = function(doc, row) {
+        var line = doc.getLine(row);
+        var match = line.match(/^(\s*\})/);
+
+        if (!match) return 0;
+
+        var column = match[1].length;
+        var openBracePos = doc.findMatchingBracket({row: row, column: column});
+
+        if (!openBracePos || openBracePos.row == row) return 0;
+
+        var indent = this.$getIndent(doc.getLine(openBracePos.row));
+        doc.replace(new Range(row, 0, row, column-1), indent);
+    };
+
+    this.$getIndent = function(line) {
+        return line.match(/^\s*/)[0];
+    };
+
+}).call(MatchingBraceOutdent.prototype);
+
+exports.MatchingBraceOutdent = MatchingBraceOutdent;
+});
+
+ace.define("ace/mode/folding/cstyle",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Range = require("../../range").Range;
+var BaseFoldMode = require("./fold_mode").FoldMode;
+
+var FoldMode = exports.FoldMode = function(commentRegex) {
+    if (commentRegex) {
+        this.foldingStartMarker = new RegExp(
+            this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start)
+        );
+        this.foldingStopMarker = new RegExp(
+            this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end)
+        );
+    }
+};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+    
+    this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/;
+    this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/;
+    this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/;
+    this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/;
+    this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/;
+    this._getFoldWidgetBase = this.getFoldWidget;
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+    
+        if (this.singleLineBlockCommentRe.test(line)) {
+            if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line))
+                return "";
+        }
+    
+        var fw = this._getFoldWidgetBase(session, foldStyle, row);
+    
+        if (!fw && this.startRegionRe.test(line))
+            return "start"; // lineCommentRegionStart
+    
+        return fw;
+    };
+
+    this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) {
+        var line = session.getLine(row);
+        
+        if (this.startRegionRe.test(line))
+            return this.getCommentRegionBlock(session, line, row);
+        
+        var match = line.match(this.foldingStartMarker);
+        if (match) {
+            var i = match.index;
+
+            if (match[1])
+                return this.openingBracketBlock(session, match[1], row, i);
+                
+            var range = session.getCommentFoldRange(row, i + match[0].length, 1);
+            
+            if (range && !range.isMultiLine()) {
+                if (forceMultiline) {
+                    range = this.getSectionRange(session, row);
+                } else if (foldStyle != "all")
+                    range = null;
+            }
+            
+            return range;
+        }
+
+        if (foldStyle === "markbegin")
+            return;
+
+        var match = line.match(this.foldingStopMarker);
+        if (match) {
+            var i = match.index + match[0].length;
+
+            if (match[1])
+                return this.closingBracketBlock(session, match[1], row, i);
+
+            return session.getCommentFoldRange(row, i, -1);
+        }
+    };
+    
+    this.getSectionRange = function(session, row) {
+        var line = session.getLine(row);
+        var startIndent = line.search(/\S/);
+        var startRow = row;
+        var startColumn = line.length;
+        row = row + 1;
+        var endRow = row;
+        var maxRow = session.getLength();
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var indent = line.search(/\S/);
+            if (indent === -1)
+                continue;
+            if  (startIndent > indent)
+                break;
+            var subRange = this.getFoldWidgetRange(session, "all", row);
+            
+            if (subRange) {
+                if (subRange.start.row <= startRow) {
+                    break;
+                } else if (subRange.isMultiLine()) {
+                    row = subRange.end.row;
+                } else if (startIndent == indent) {
+                    break;
+                }
+            }
+            endRow = row;
+        }
+        
+        return new Range(startRow, startColumn, endRow, session.getLine(endRow).length);
+    };
+    this.getCommentRegionBlock = function(session, line, row) {
+        var startColumn = line.search(/\s*$/);
+        var maxRow = session.getLength();
+        var startRow = row;
+        
+        var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/;
+        var depth = 1;
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var m = re.exec(line);
+            if (!m) continue;
+            if (m[1]) depth--;
+            else depth++;
+
+            if (!depth) break;
+        }
+
+        var endRow = row;
+        if (endRow > startRow) {
+            return new Range(startRow, startColumn, endRow, line.length);
+        }
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/jack",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var HighlightRules = require("./jack_highlight_rules").JackHighlightRules;
+var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent;
+var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour;
+var CStyleFoldMode = require("./folding/cstyle").FoldMode;
+
+var Mode = function() {
+    this.HighlightRules = HighlightRules;
+    this.$outdent = new MatchingBraceOutdent();
+    this.$behaviour = new CstyleBehaviour();
+    this.foldingRules = new CStyleFoldMode();
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+
+    this.lineCommentStart = "--";
+
+    this.getNextLineIndent = function(state, line, tab) {
+        var indent = this.$getIndent(line);
+
+        if (state == "start") {
+            var match = line.match(/^.*[\{\(\[]\s*$/);
+            if (match) {
+                indent += tab;
+            }
+        }
+
+        return indent;
+    };
+
+    this.checkOutdent = function(state, line, input) {
+        return this.$outdent.checkOutdent(line, input);
+    };
+
+    this.autoOutdent = function(state, doc, row) {
+        this.$outdent.autoOutdent(doc, row);
+    };
+
+
+    this.$id = "ace/mode/jack";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/jack"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

Fișier diff suprimat deoarece este prea mare
+ 6 - 0
services/web/public/js/ace-1.4.3/mode-jade.js


+ 1037 - 0
services/web/public/js/ace-1.4.3/mode-java.js

@@ -0,0 +1,1037 @@
+ace.define("ace/mode/doc_comment_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var DocCommentHighlightRules = function() {
+    this.$rules = {
+        "start" : [ {
+            token : "comment.doc.tag",
+            regex : "@[\\w\\d_]+" // TODO: fix email addresses
+        }, 
+        DocCommentHighlightRules.getTagRule(),
+        {
+            defaultToken : "comment.doc",
+            caseInsensitive: true
+        }]
+    };
+};
+
+oop.inherits(DocCommentHighlightRules, TextHighlightRules);
+
+DocCommentHighlightRules.getTagRule = function(start) {
+    return {
+        token : "comment.doc.tag.storage.type",
+        regex : "\\b(?:TODO|FIXME|XXX|HACK)\\b"
+    };
+};
+
+DocCommentHighlightRules.getStartRule = function(start) {
+    return {
+        token : "comment.doc", // doc comment
+        regex : "\\/\\*(?=\\*)",
+        next  : start
+    };
+};
+
+DocCommentHighlightRules.getEndRule = function (start) {
+    return {
+        token : "comment.doc", // closing comment
+        regex : "\\*\\/",
+        next  : start
+    };
+};
+
+
+exports.DocCommentHighlightRules = DocCommentHighlightRules;
+
+});
+
+ace.define("ace/mode/javascript_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var DocCommentHighlightRules = require("./doc_comment_highlight_rules").DocCommentHighlightRules;
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+var identifierRe = "[a-zA-Z\\$_\u00a1-\uffff][a-zA-Z\\d\\$_\u00a1-\uffff]*";
+
+var JavaScriptHighlightRules = function(options) {
+    var keywordMapper = this.createKeywordMapper({
+        "variable.language":
+            "Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|"  + // Constructors
+            "Namespace|QName|XML|XMLList|"                                             + // E4X
+            "ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|"   +
+            "Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|"                    +
+            "Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|"   + // Errors
+            "SyntaxError|TypeError|URIError|"                                          +
+            "decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|" + // Non-constructor functions
+            "isNaN|parseFloat|parseInt|"                                               +
+            "JSON|Math|"                                                               + // Other
+            "this|arguments|prototype|window|document"                                 , // Pseudo
+        "keyword":
+            "const|yield|import|get|set|async|await|" +
+            "break|case|catch|continue|default|delete|do|else|finally|for|function|" +
+            "if|in|of|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|debugger|" +
+            "__parent__|__count__|escape|unescape|with|__proto__|" +
+            "class|enum|extends|super|export|implements|private|public|interface|package|protected|static",
+        "storage.type":
+            "const|let|var|function",
+        "constant.language":
+            "null|Infinity|NaN|undefined",
+        "support.function":
+            "alert",
+        "constant.language.boolean": "true|false"
+    }, "identifier");
+    var kwBeforeRe = "case|do|else|finally|in|instanceof|return|throw|try|typeof|yield|void";
+
+    var escapedRe = "\\\\(?:x[0-9a-fA-F]{2}|" + // hex
+        "u[0-9a-fA-F]{4}|" + // unicode
+        "u{[0-9a-fA-F]{1,6}}|" + // es6 unicode
+        "[0-2][0-7]{0,2}|" + // oct
+        "3[0-7][0-7]?|" + // oct
+        "[4-7][0-7]?|" + //oct
+        ".)";
+
+    this.$rules = {
+        "no_regex" : [
+            DocCommentHighlightRules.getStartRule("doc-start"),
+            comments("no_regex"),
+            {
+                token : "string",
+                regex : "'(?=.)",
+                next  : "qstring"
+            }, {
+                token : "string",
+                regex : '"(?=.)',
+                next  : "qqstring"
+            }, {
+                token : "constant.numeric", // hexadecimal, octal and binary
+                regex : /0(?:[xX][0-9a-fA-F]+|[oO][0-7]+|[bB][01]+)\b/
+            }, {
+                token : "constant.numeric", // decimal integers and floats
+                regex : /(?:\d\d*(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+\b)?/
+            }, {
+                token : [
+                    "storage.type", "punctuation.operator", "support.function",
+                    "punctuation.operator", "entity.name.function", "text","keyword.operator"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(prototype)(\\.)(" + identifierRe +")(\\s*)(=)",
+                next: "function_arguments"
+            }, {
+                token : [
+                    "storage.type", "punctuation.operator", "entity.name.function", "text",
+                    "keyword.operator", "text", "storage.type", "text", "paren.lparen"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",
+                next: "function_arguments"
+            }, {
+                token : [
+                    "entity.name.function", "text", "keyword.operator", "text", "storage.type",
+                    "text", "paren.lparen"
+                ],
+                regex : "(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",
+                next: "function_arguments"
+            }, {
+                token : [
+                    "storage.type", "punctuation.operator", "entity.name.function", "text",
+                    "keyword.operator", "text",
+                    "storage.type", "text", "entity.name.function", "text", "paren.lparen"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s+)(\\w+)(\\s*)(\\()",
+                next: "function_arguments"
+            }, {
+                token : [
+                    "storage.type", "text", "entity.name.function", "text", "paren.lparen"
+                ],
+                regex : "(function)(\\s+)(" + identifierRe + ")(\\s*)(\\()",
+                next: "function_arguments"
+            }, {
+                token : [
+                    "entity.name.function", "text", "punctuation.operator",
+                    "text", "storage.type", "text", "paren.lparen"
+                ],
+                regex : "(" + identifierRe + ")(\\s*)(:)(\\s*)(function)(\\s*)(\\()",
+                next: "function_arguments"
+            }, {
+                token : [
+                    "text", "text", "storage.type", "text", "paren.lparen"
+                ],
+                regex : "(:)(\\s*)(function)(\\s*)(\\()",
+                next: "function_arguments"
+            }, {
+                token : "keyword",
+                regex : "from(?=\\s*('|\"))"
+            }, {
+                token : "keyword",
+                regex : "(?:" + kwBeforeRe + ")\\b",
+                next : "start"
+            }, {
+                token : ["support.constant"],
+                regex : /that\b/
+            }, {
+                token : ["storage.type", "punctuation.operator", "support.function.firebug"],
+                regex : /(console)(\.)(warn|info|log|error|time|trace|timeEnd|assert)\b/
+            }, {
+                token : keywordMapper,
+                regex : identifierRe
+            }, {
+                token : "punctuation.operator",
+                regex : /[.](?![.])/,
+                next  : "property"
+            }, {
+                token : "storage.type",
+                regex : /=>/,
+                next  : "start"
+            }, {
+                token : "keyword.operator",
+                regex : /--|\+\+|\.{3}|===|==|=|!=|!==|<+=?|>+=?|!|&&|\|\||\?:|[!$%&*+\-~\/^]=?/,
+                next  : "start"
+            }, {
+                token : "punctuation.operator",
+                regex : /[?:,;.]/,
+                next  : "start"
+            }, {
+                token : "paren.lparen",
+                regex : /[\[({]/,
+                next  : "start"
+            }, {
+                token : "paren.rparen",
+                regex : /[\])}]/
+            }, {
+                token: "comment",
+                regex: /^#!.*$/
+            }
+        ],
+        property: [{
+                token : "text",
+                regex : "\\s+"
+            }, {
+                token : [
+                    "storage.type", "punctuation.operator", "entity.name.function", "text",
+                    "keyword.operator", "text",
+                    "storage.type", "text", "entity.name.function", "text", "paren.lparen"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(?:(\\s+)(\\w+))?(\\s*)(\\()",
+                next: "function_arguments"
+            }, {
+                token : "punctuation.operator",
+                regex : /[.](?![.])/
+            }, {
+                token : "support.function",
+                regex : /(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:op|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/
+            }, {
+                token : "support.function.dom",
+                regex : /(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName|ClassName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/
+            }, {
+                token :  "support.constant",
+                regex : /(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/
+            }, {
+                token : "identifier",
+                regex : identifierRe
+            }, {
+                regex: "",
+                token: "empty",
+                next: "no_regex"
+            }
+        ],
+        "start": [
+            DocCommentHighlightRules.getStartRule("doc-start"),
+            comments("start"),
+            {
+                token: "string.regexp",
+                regex: "\\/",
+                next: "regex"
+            }, {
+                token : "text",
+                regex : "\\s+|^$",
+                next : "start"
+            }, {
+                token: "empty",
+                regex: "",
+                next: "no_regex"
+            }
+        ],
+        "regex": [
+            {
+                token: "regexp.keyword.operator",
+                regex: "\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"
+            }, {
+                token: "string.regexp",
+                regex: "/[sxngimy]*",
+                next: "no_regex"
+            }, {
+                token : "invalid",
+                regex: /\{\d+\b,?\d*\}[+*]|[+*$^?][+*]|[$^][?]|\?{3,}/
+            }, {
+                token : "constant.language.escape",
+                regex: /\(\?[:=!]|\)|\{\d+\b,?\d*\}|[+*]\?|[()$^+*?.]/
+            }, {
+                token : "constant.language.delimiter",
+                regex: /\|/
+            }, {
+                token: "constant.language.escape",
+                regex: /\[\^?/,
+                next: "regex_character_class"
+            }, {
+                token: "empty",
+                regex: "$",
+                next: "no_regex"
+            }, {
+                defaultToken: "string.regexp"
+            }
+        ],
+        "regex_character_class": [
+            {
+                token: "regexp.charclass.keyword.operator",
+                regex: "\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"
+            }, {
+                token: "constant.language.escape",
+                regex: "]",
+                next: "regex"
+            }, {
+                token: "constant.language.escape",
+                regex: "-"
+            }, {
+                token: "empty",
+                regex: "$",
+                next: "no_regex"
+            }, {
+                defaultToken: "string.regexp.charachterclass"
+            }
+        ],
+        "function_arguments": [
+            {
+                token: "variable.parameter",
+                regex: identifierRe
+            }, {
+                token: "punctuation.operator",
+                regex: "[, ]+"
+            }, {
+                token: "punctuation.operator",
+                regex: "$"
+            }, {
+                token: "empty",
+                regex: "",
+                next: "no_regex"
+            }
+        ],
+        "qqstring" : [
+            {
+                token : "constant.language.escape",
+                regex : escapedRe
+            }, {
+                token : "string",
+                regex : "\\\\$",
+                consumeLineEnd  : true
+            }, {
+                token : "string",
+                regex : '"|$',
+                next  : "no_regex"
+            }, {
+                defaultToken: "string"
+            }
+        ],
+        "qstring" : [
+            {
+                token : "constant.language.escape",
+                regex : escapedRe
+            }, {
+                token : "string",
+                regex : "\\\\$",
+                consumeLineEnd  : true
+            }, {
+                token : "string",
+                regex : "'|$",
+                next  : "no_regex"
+            }, {
+                defaultToken: "string"
+            }
+        ]
+    };
+
+
+    if (!options || !options.noES6) {
+        this.$rules.no_regex.unshift({
+            regex: "[{}]", onMatch: function(val, state, stack) {
+                this.next = val == "{" ? this.nextState : "";
+                if (val == "{" && stack.length) {
+                    stack.unshift("start", state);
+                }
+                else if (val == "}" && stack.length) {
+                    stack.shift();
+                    this.next = stack.shift();
+                    if (this.next.indexOf("string") != -1 || this.next.indexOf("jsx") != -1)
+                        return "paren.quasi.end";
+                }
+                return val == "{" ? "paren.lparen" : "paren.rparen";
+            },
+            nextState: "start"
+        }, {
+            token : "string.quasi.start",
+            regex : /`/,
+            push  : [{
+                token : "constant.language.escape",
+                regex : escapedRe
+            }, {
+                token : "paren.quasi.start",
+                regex : /\${/,
+                push  : "start"
+            }, {
+                token : "string.quasi.end",
+                regex : /`/,
+                next  : "pop"
+            }, {
+                defaultToken: "string.quasi"
+            }]
+        });
+
+        if (!options || options.jsx != false)
+            JSX.call(this);
+    }
+
+    this.embedRules(DocCommentHighlightRules, "doc-",
+        [ DocCommentHighlightRules.getEndRule("no_regex") ]);
+
+    this.normalizeRules();
+};
+
+oop.inherits(JavaScriptHighlightRules, TextHighlightRules);
+
+function JSX() {
+    var tagRegex = identifierRe.replace("\\d", "\\d\\-");
+    var jsxTag = {
+        onMatch : function(val, state, stack) {
+            var offset = val.charAt(1) == "/" ? 2 : 1;
+            if (offset == 1) {
+                if (state != this.nextState)
+                    stack.unshift(this.next, this.nextState, 0);
+                else
+                    stack.unshift(this.next);
+                stack[2]++;
+            } else if (offset == 2) {
+                if (state == this.nextState) {
+                    stack[1]--;
+                    if (!stack[1] || stack[1] < 0) {
+                        stack.shift();
+                        stack.shift();
+                    }
+                }
+            }
+            return [{
+                type: "meta.tag.punctuation." + (offset == 1 ? "" : "end-") + "tag-open.xml",
+                value: val.slice(0, offset)
+            }, {
+                type: "meta.tag.tag-name.xml",
+                value: val.substr(offset)
+            }];
+        },
+        regex : "</?" + tagRegex + "",
+        next: "jsxAttributes",
+        nextState: "jsx"
+    };
+    this.$rules.start.unshift(jsxTag);
+    var jsxJsRule = {
+        regex: "{",
+        token: "paren.quasi.start",
+        push: "start"
+    };
+    this.$rules.jsx = [
+        jsxJsRule,
+        jsxTag,
+        {include : "reference"},
+        {defaultToken: "string"}
+    ];
+    this.$rules.jsxAttributes = [{
+        token : "meta.tag.punctuation.tag-close.xml",
+        regex : "/?>",
+        onMatch : function(value, currentState, stack) {
+            if (currentState == stack[0])
+                stack.shift();
+            if (value.length == 2) {
+                if (stack[0] == this.nextState)
+                    stack[1]--;
+                if (!stack[1] || stack[1] < 0) {
+                    stack.splice(0, 2);
+                }
+            }
+            this.next = stack[0] || "start";
+            return [{type: this.token, value: value}];
+        },
+        nextState: "jsx"
+    },
+    jsxJsRule,
+    comments("jsxAttributes"),
+    {
+        token : "entity.other.attribute-name.xml",
+        regex : tagRegex
+    }, {
+        token : "keyword.operator.attribute-equals.xml",
+        regex : "="
+    }, {
+        token : "text.tag-whitespace.xml",
+        regex : "\\s+"
+    }, {
+        token : "string.attribute-value.xml",
+        regex : "'",
+        stateName : "jsx_attr_q",
+        push : [
+            {token : "string.attribute-value.xml", regex: "'", next: "pop"},
+            {include : "reference"},
+            {defaultToken : "string.attribute-value.xml"}
+        ]
+    }, {
+        token : "string.attribute-value.xml",
+        regex : '"',
+        stateName : "jsx_attr_qq",
+        push : [
+            {token : "string.attribute-value.xml", regex: '"', next: "pop"},
+            {include : "reference"},
+            {defaultToken : "string.attribute-value.xml"}
+        ]
+    },
+    jsxTag
+    ];
+    this.$rules.reference = [{
+        token : "constant.language.escape.reference.xml",
+        regex : "(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"
+    }];
+}
+
+function comments(next) {
+    return [
+        {
+            token : "comment", // multi line comment
+            regex : /\/\*/,
+            next: [
+                DocCommentHighlightRules.getTagRule(),
+                {token : "comment", regex : "\\*\\/", next : next || "pop"},
+                {defaultToken : "comment", caseInsensitive: true}
+            ]
+        }, {
+            token : "comment",
+            regex : "\\/\\/",
+            next: [
+                DocCommentHighlightRules.getTagRule(),
+                {token : "comment", regex : "$|^", next : next || "pop"},
+                {defaultToken : "comment", caseInsensitive: true}
+            ]
+        }
+    ];
+}
+exports.JavaScriptHighlightRules = JavaScriptHighlightRules;
+});
+
+ace.define("ace/mode/matching_brace_outdent",[], function(require, exports, module) {
+"use strict";
+
+var Range = require("../range").Range;
+
+var MatchingBraceOutdent = function() {};
+
+(function() {
+
+    this.checkOutdent = function(line, input) {
+        if (! /^\s+$/.test(line))
+            return false;
+
+        return /^\s*\}/.test(input);
+    };
+
+    this.autoOutdent = function(doc, row) {
+        var line = doc.getLine(row);
+        var match = line.match(/^(\s*\})/);
+
+        if (!match) return 0;
+
+        var column = match[1].length;
+        var openBracePos = doc.findMatchingBracket({row: row, column: column});
+
+        if (!openBracePos || openBracePos.row == row) return 0;
+
+        var indent = this.$getIndent(doc.getLine(openBracePos.row));
+        doc.replace(new Range(row, 0, row, column-1), indent);
+    };
+
+    this.$getIndent = function(line) {
+        return line.match(/^\s*/)[0];
+    };
+
+}).call(MatchingBraceOutdent.prototype);
+
+exports.MatchingBraceOutdent = MatchingBraceOutdent;
+});
+
+ace.define("ace/mode/folding/cstyle",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Range = require("../../range").Range;
+var BaseFoldMode = require("./fold_mode").FoldMode;
+
+var FoldMode = exports.FoldMode = function(commentRegex) {
+    if (commentRegex) {
+        this.foldingStartMarker = new RegExp(
+            this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start)
+        );
+        this.foldingStopMarker = new RegExp(
+            this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end)
+        );
+    }
+};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+    
+    this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/;
+    this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/;
+    this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/;
+    this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/;
+    this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/;
+    this._getFoldWidgetBase = this.getFoldWidget;
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+    
+        if (this.singleLineBlockCommentRe.test(line)) {
+            if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line))
+                return "";
+        }
+    
+        var fw = this._getFoldWidgetBase(session, foldStyle, row);
+    
+        if (!fw && this.startRegionRe.test(line))
+            return "start"; // lineCommentRegionStart
+    
+        return fw;
+    };
+
+    this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) {
+        var line = session.getLine(row);
+        
+        if (this.startRegionRe.test(line))
+            return this.getCommentRegionBlock(session, line, row);
+        
+        var match = line.match(this.foldingStartMarker);
+        if (match) {
+            var i = match.index;
+
+            if (match[1])
+                return this.openingBracketBlock(session, match[1], row, i);
+                
+            var range = session.getCommentFoldRange(row, i + match[0].length, 1);
+            
+            if (range && !range.isMultiLine()) {
+                if (forceMultiline) {
+                    range = this.getSectionRange(session, row);
+                } else if (foldStyle != "all")
+                    range = null;
+            }
+            
+            return range;
+        }
+
+        if (foldStyle === "markbegin")
+            return;
+
+        var match = line.match(this.foldingStopMarker);
+        if (match) {
+            var i = match.index + match[0].length;
+
+            if (match[1])
+                return this.closingBracketBlock(session, match[1], row, i);
+
+            return session.getCommentFoldRange(row, i, -1);
+        }
+    };
+    
+    this.getSectionRange = function(session, row) {
+        var line = session.getLine(row);
+        var startIndent = line.search(/\S/);
+        var startRow = row;
+        var startColumn = line.length;
+        row = row + 1;
+        var endRow = row;
+        var maxRow = session.getLength();
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var indent = line.search(/\S/);
+            if (indent === -1)
+                continue;
+            if  (startIndent > indent)
+                break;
+            var subRange = this.getFoldWidgetRange(session, "all", row);
+            
+            if (subRange) {
+                if (subRange.start.row <= startRow) {
+                    break;
+                } else if (subRange.isMultiLine()) {
+                    row = subRange.end.row;
+                } else if (startIndent == indent) {
+                    break;
+                }
+            }
+            endRow = row;
+        }
+        
+        return new Range(startRow, startColumn, endRow, session.getLine(endRow).length);
+    };
+    this.getCommentRegionBlock = function(session, line, row) {
+        var startColumn = line.search(/\s*$/);
+        var maxRow = session.getLength();
+        var startRow = row;
+        
+        var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/;
+        var depth = 1;
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var m = re.exec(line);
+            if (!m) continue;
+            if (m[1]) depth--;
+            else depth++;
+
+            if (!depth) break;
+        }
+
+        var endRow = row;
+        if (endRow > startRow) {
+            return new Range(startRow, startColumn, endRow, line.length);
+        }
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/javascript",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var JavaScriptHighlightRules = require("./javascript_highlight_rules").JavaScriptHighlightRules;
+var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent;
+var WorkerClient = require("../worker/worker_client").WorkerClient;
+var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour;
+var CStyleFoldMode = require("./folding/cstyle").FoldMode;
+
+var Mode = function() {
+    this.HighlightRules = JavaScriptHighlightRules;
+    
+    this.$outdent = new MatchingBraceOutdent();
+    this.$behaviour = new CstyleBehaviour();
+    this.foldingRules = new CStyleFoldMode();
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+
+    this.lineCommentStart = "//";
+    this.blockComment = {start: "/*", end: "*/"};
+    this.$quotes = {'"': '"', "'": "'", "`": "`"};
+
+    this.getNextLineIndent = function(state, line, tab) {
+        var indent = this.$getIndent(line);
+
+        var tokenizedLine = this.getTokenizer().getLineTokens(line, state);
+        var tokens = tokenizedLine.tokens;
+        var endState = tokenizedLine.state;
+
+        if (tokens.length && tokens[tokens.length-1].type == "comment") {
+            return indent;
+        }
+
+        if (state == "start" || state == "no_regex") {
+            var match = line.match(/^.*(?:\bcase\b.*:|[\{\(\[])\s*$/);
+            if (match) {
+                indent += tab;
+            }
+        } else if (state == "doc-start") {
+            if (endState == "start" || endState == "no_regex") {
+                return "";
+            }
+            var match = line.match(/^\s*(\/?)\*/);
+            if (match) {
+                if (match[1]) {
+                    indent += " ";
+                }
+                indent += "* ";
+            }
+        }
+
+        return indent;
+    };
+
+    this.checkOutdent = function(state, line, input) {
+        return this.$outdent.checkOutdent(line, input);
+    };
+
+    this.autoOutdent = function(state, doc, row) {
+        this.$outdent.autoOutdent(doc, row);
+    };
+
+    this.createWorker = function(session) {
+        var worker = new WorkerClient(["ace"], "ace/mode/javascript_worker", "JavaScriptWorker");
+        worker.attachToDocument(session.getDocument());
+
+        worker.on("annotate", function(results) {
+            session.setAnnotations(results.data);
+        });
+
+        worker.on("terminate", function() {
+            session.clearAnnotations();
+        });
+
+        return worker;
+    };
+
+    this.$id = "ace/mode/javascript";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+
+ace.define("ace/mode/java_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var DocCommentHighlightRules = require("./doc_comment_highlight_rules").DocCommentHighlightRules;
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var JavaHighlightRules = function() {
+    var keywords = (
+    "abstract|continue|for|new|switch|" +
+    "assert|default|goto|package|synchronized|" +
+    "boolean|do|if|private|this|" +
+    "break|double|implements|protected|throw|" +
+    "byte|else|import|public|throws|" +
+    "case|enum|instanceof|return|transient|" +
+    "catch|extends|int|short|try|" +
+    "char|final|interface|static|void|" +
+    "class|finally|long|strictfp|volatile|" +
+    "const|float|native|super|while|" +
+    "var"
+    );
+
+    var buildinConstants = ("null|Infinity|NaN|undefined");
+
+
+    var langClasses = (
+        "AbstractMethodError|AssertionError|ClassCircularityError|"+
+        "ClassFormatError|Deprecated|EnumConstantNotPresentException|"+
+        "ExceptionInInitializerError|IllegalAccessError|"+
+        "IllegalThreadStateException|InstantiationError|InternalError|"+
+        "NegativeArraySizeException|NoSuchFieldError|Override|Process|"+
+        "ProcessBuilder|SecurityManager|StringIndexOutOfBoundsException|"+
+        "SuppressWarnings|TypeNotPresentException|UnknownError|"+
+        "UnsatisfiedLinkError|UnsupportedClassVersionError|VerifyError|"+
+        "InstantiationException|IndexOutOfBoundsException|"+
+        "ArrayIndexOutOfBoundsException|CloneNotSupportedException|"+
+        "NoSuchFieldException|IllegalArgumentException|NumberFormatException|"+
+        "SecurityException|Void|InheritableThreadLocal|IllegalStateException|"+
+        "InterruptedException|NoSuchMethodException|IllegalAccessException|"+
+        "UnsupportedOperationException|Enum|StrictMath|Package|Compiler|"+
+        "Readable|Runtime|StringBuilder|Math|IncompatibleClassChangeError|"+
+        "NoSuchMethodError|ThreadLocal|RuntimePermission|ArithmeticException|"+
+        "NullPointerException|Long|Integer|Short|Byte|Double|Number|Float|"+
+        "Character|Boolean|StackTraceElement|Appendable|StringBuffer|"+
+        "Iterable|ThreadGroup|Runnable|Thread|IllegalMonitorStateException|"+
+        "StackOverflowError|OutOfMemoryError|VirtualMachineError|"+
+        "ArrayStoreException|ClassCastException|LinkageError|"+
+        "NoClassDefFoundError|ClassNotFoundException|RuntimeException|"+
+        "Exception|ThreadDeath|Error|Throwable|System|ClassLoader|"+
+        "Cloneable|Class|CharSequence|Comparable|String|Object"
+    );
+
+    var keywordMapper = this.createKeywordMapper({
+        "variable.language": "this",
+        "keyword": keywords,
+        "constant.language": buildinConstants,
+        "support.function": langClasses
+    }, "identifier");
+
+    this.$rules = {
+        "start" : [
+            {
+                token : "comment",
+                regex : "\\/\\/.*$"
+            },
+            DocCommentHighlightRules.getStartRule("doc-start"),
+            {
+                token : "comment", // multi line comment
+                regex : "\\/\\*",
+                next : "comment"
+            }, {
+                token : "string", // single line
+                regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
+            }, {
+                token : "string", // single line
+                regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
+            }, {
+                token : "constant.numeric", // hex
+                regex : /0(?:[xX][0-9a-fA-F][0-9a-fA-F_]*|[bB][01][01_]*)[LlSsDdFfYy]?\b/
+            }, {
+                token : "constant.numeric", // float
+                regex : /[+-]?\d[\d_]*(?:(?:\.[\d_]*)?(?:[eE][+-]?[\d_]+)?)?[LlSsDdFfYy]?\b/
+            }, {
+                token : "constant.language.boolean",
+                regex : "(?:true|false)\\b"
+            }, {
+                regex: "(open(?:\\s+))?module(?=\\s*\\w)",
+                token: "keyword",
+                next: [{
+                    regex: "{",
+                    token: "paren.lparen",
+                    next: [{
+                        regex: "}",
+                        token: "paren.rparen",
+                        next: "start"
+                    }, {
+                        regex: "\\b(requires|transitive|exports|opens|to|uses|provides|with)\\b",
+                        token: "keyword" 
+                    }]
+                }, {
+                    token : "text",
+                    regex : "\\s+"
+                }, {
+                    token : "identifier",
+                    regex : "\\w+"
+                }, {
+                    token : "punctuation.operator",
+                    regex : "."
+                }, {
+                    token : "text",
+                    regex : "\\s+"
+                }, {
+                    regex: "", // exit if there is anything else
+                    next: "start"
+                }]
+            }, {
+                token : keywordMapper,
+                regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
+            }, {
+                token : "keyword.operator",
+                regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"
+            }, {
+                token : "lparen",
+                regex : "[[({]"
+            }, {
+                token : "rparen",
+                regex : "[\\])}]"
+            }, {
+                token : "text",
+                regex : "\\s+"
+            }
+        ],
+        "comment" : [
+            {
+                token : "comment", // closing comment
+                regex : "\\*\\/",
+                next : "start"
+            }, {
+                defaultToken : "comment"
+            }
+        ]
+    };
+
+    
+    this.embedRules(DocCommentHighlightRules, "doc-",
+        [ DocCommentHighlightRules.getEndRule("start") ]);
+    this.normalizeRules();
+};
+
+oop.inherits(JavaHighlightRules, TextHighlightRules);
+
+exports.JavaHighlightRules = JavaHighlightRules;
+});
+
+ace.define("ace/mode/folding/java",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var CStyleFoldMode = require("./cstyle").FoldMode;
+var Range = require("../../range").Range;
+
+var FoldMode = exports.FoldMode = function() {};
+oop.inherits(FoldMode, CStyleFoldMode);
+
+(function() {
+    this.importRegex = /^import /;
+    this.getCStyleFoldWidget = this.getFoldWidget;
+    this.getFoldWidget = function(session, foldStyle, row) {
+        if (foldStyle === "markbegin") {
+            var line = session.getLine(row);
+            if (this.importRegex.test(line)) {
+                if (row == 0 || !this.importRegex.test(session.getLine(row - 1)))
+                    return "start";
+            }
+        }
+
+        return this.getCStyleFoldWidget(session, foldStyle, row);
+    };
+    
+    this.getCstyleFoldWidgetRange = this.getFoldWidgetRange;
+    this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) {
+        var line = session.getLine(row);
+        var match = line.match(this.importRegex);
+        if (!match || foldStyle !== "markbegin")
+            return this.getCstyleFoldWidgetRange(session, foldStyle, row, forceMultiline);
+
+        var startColumn = match[0].length;
+        var maxRow = session.getLength();
+        var startRow = row;
+        var endRow = row;
+
+        while (++row < maxRow) {
+            var line = session.getLine(row);
+            if (line.match(/^\s*$/))
+                continue;
+
+            if (!line.match(this.importRegex))
+                break;
+
+            endRow = row;
+        }
+
+        if (endRow > startRow) {
+            var endColumn = session.getLine(endRow).length;
+            return new Range(startRow, startColumn, endRow, endColumn);
+        }
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/java",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var JavaScriptMode = require("./javascript").Mode;
+var JavaHighlightRules = require("./java_highlight_rules").JavaHighlightRules;
+var JavaFoldMode = require("./folding/java").FoldMode;
+
+var Mode = function() {
+    JavaScriptMode.call(this);
+    this.HighlightRules = JavaHighlightRules;
+    this.foldingRules = new JavaFoldMode();
+};
+oop.inherits(Mode, JavaScriptMode);
+
+(function() {
+    
+    this.createWorker = function(session) {
+        return null;
+    };
+
+    this.$id = "ace/mode/java";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/java"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 798 - 0
services/web/public/js/ace-1.4.3/mode-javascript.js

@@ -0,0 +1,798 @@
+ace.define("ace/mode/doc_comment_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var DocCommentHighlightRules = function() {
+    this.$rules = {
+        "start" : [ {
+            token : "comment.doc.tag",
+            regex : "@[\\w\\d_]+" // TODO: fix email addresses
+        }, 
+        DocCommentHighlightRules.getTagRule(),
+        {
+            defaultToken : "comment.doc",
+            caseInsensitive: true
+        }]
+    };
+};
+
+oop.inherits(DocCommentHighlightRules, TextHighlightRules);
+
+DocCommentHighlightRules.getTagRule = function(start) {
+    return {
+        token : "comment.doc.tag.storage.type",
+        regex : "\\b(?:TODO|FIXME|XXX|HACK)\\b"
+    };
+};
+
+DocCommentHighlightRules.getStartRule = function(start) {
+    return {
+        token : "comment.doc", // doc comment
+        regex : "\\/\\*(?=\\*)",
+        next  : start
+    };
+};
+
+DocCommentHighlightRules.getEndRule = function (start) {
+    return {
+        token : "comment.doc", // closing comment
+        regex : "\\*\\/",
+        next  : start
+    };
+};
+
+
+exports.DocCommentHighlightRules = DocCommentHighlightRules;
+
+});
+
+ace.define("ace/mode/javascript_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var DocCommentHighlightRules = require("./doc_comment_highlight_rules").DocCommentHighlightRules;
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+var identifierRe = "[a-zA-Z\\$_\u00a1-\uffff][a-zA-Z\\d\\$_\u00a1-\uffff]*";
+
+var JavaScriptHighlightRules = function(options) {
+    var keywordMapper = this.createKeywordMapper({
+        "variable.language":
+            "Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|"  + // Constructors
+            "Namespace|QName|XML|XMLList|"                                             + // E4X
+            "ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|"   +
+            "Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|"                    +
+            "Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|"   + // Errors
+            "SyntaxError|TypeError|URIError|"                                          +
+            "decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|" + // Non-constructor functions
+            "isNaN|parseFloat|parseInt|"                                               +
+            "JSON|Math|"                                                               + // Other
+            "this|arguments|prototype|window|document"                                 , // Pseudo
+        "keyword":
+            "const|yield|import|get|set|async|await|" +
+            "break|case|catch|continue|default|delete|do|else|finally|for|function|" +
+            "if|in|of|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|debugger|" +
+            "__parent__|__count__|escape|unescape|with|__proto__|" +
+            "class|enum|extends|super|export|implements|private|public|interface|package|protected|static",
+        "storage.type":
+            "const|let|var|function",
+        "constant.language":
+            "null|Infinity|NaN|undefined",
+        "support.function":
+            "alert",
+        "constant.language.boolean": "true|false"
+    }, "identifier");
+    var kwBeforeRe = "case|do|else|finally|in|instanceof|return|throw|try|typeof|yield|void";
+
+    var escapedRe = "\\\\(?:x[0-9a-fA-F]{2}|" + // hex
+        "u[0-9a-fA-F]{4}|" + // unicode
+        "u{[0-9a-fA-F]{1,6}}|" + // es6 unicode
+        "[0-2][0-7]{0,2}|" + // oct
+        "3[0-7][0-7]?|" + // oct
+        "[4-7][0-7]?|" + //oct
+        ".)";
+
+    this.$rules = {
+        "no_regex" : [
+            DocCommentHighlightRules.getStartRule("doc-start"),
+            comments("no_regex"),
+            {
+                token : "string",
+                regex : "'(?=.)",
+                next  : "qstring"
+            }, {
+                token : "string",
+                regex : '"(?=.)',
+                next  : "qqstring"
+            }, {
+                token : "constant.numeric", // hexadecimal, octal and binary
+                regex : /0(?:[xX][0-9a-fA-F]+|[oO][0-7]+|[bB][01]+)\b/
+            }, {
+                token : "constant.numeric", // decimal integers and floats
+                regex : /(?:\d\d*(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+\b)?/
+            }, {
+                token : [
+                    "storage.type", "punctuation.operator", "support.function",
+                    "punctuation.operator", "entity.name.function", "text","keyword.operator"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(prototype)(\\.)(" + identifierRe +")(\\s*)(=)",
+                next: "function_arguments"
+            }, {
+                token : [
+                    "storage.type", "punctuation.operator", "entity.name.function", "text",
+                    "keyword.operator", "text", "storage.type", "text", "paren.lparen"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",
+                next: "function_arguments"
+            }, {
+                token : [
+                    "entity.name.function", "text", "keyword.operator", "text", "storage.type",
+                    "text", "paren.lparen"
+                ],
+                regex : "(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",
+                next: "function_arguments"
+            }, {
+                token : [
+                    "storage.type", "punctuation.operator", "entity.name.function", "text",
+                    "keyword.operator", "text",
+                    "storage.type", "text", "entity.name.function", "text", "paren.lparen"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s+)(\\w+)(\\s*)(\\()",
+                next: "function_arguments"
+            }, {
+                token : [
+                    "storage.type", "text", "entity.name.function", "text", "paren.lparen"
+                ],
+                regex : "(function)(\\s+)(" + identifierRe + ")(\\s*)(\\()",
+                next: "function_arguments"
+            }, {
+                token : [
+                    "entity.name.function", "text", "punctuation.operator",
+                    "text", "storage.type", "text", "paren.lparen"
+                ],
+                regex : "(" + identifierRe + ")(\\s*)(:)(\\s*)(function)(\\s*)(\\()",
+                next: "function_arguments"
+            }, {
+                token : [
+                    "text", "text", "storage.type", "text", "paren.lparen"
+                ],
+                regex : "(:)(\\s*)(function)(\\s*)(\\()",
+                next: "function_arguments"
+            }, {
+                token : "keyword",
+                regex : "from(?=\\s*('|\"))"
+            }, {
+                token : "keyword",
+                regex : "(?:" + kwBeforeRe + ")\\b",
+                next : "start"
+            }, {
+                token : ["support.constant"],
+                regex : /that\b/
+            }, {
+                token : ["storage.type", "punctuation.operator", "support.function.firebug"],
+                regex : /(console)(\.)(warn|info|log|error|time|trace|timeEnd|assert)\b/
+            }, {
+                token : keywordMapper,
+                regex : identifierRe
+            }, {
+                token : "punctuation.operator",
+                regex : /[.](?![.])/,
+                next  : "property"
+            }, {
+                token : "storage.type",
+                regex : /=>/,
+                next  : "start"
+            }, {
+                token : "keyword.operator",
+                regex : /--|\+\+|\.{3}|===|==|=|!=|!==|<+=?|>+=?|!|&&|\|\||\?:|[!$%&*+\-~\/^]=?/,
+                next  : "start"
+            }, {
+                token : "punctuation.operator",
+                regex : /[?:,;.]/,
+                next  : "start"
+            }, {
+                token : "paren.lparen",
+                regex : /[\[({]/,
+                next  : "start"
+            }, {
+                token : "paren.rparen",
+                regex : /[\])}]/
+            }, {
+                token: "comment",
+                regex: /^#!.*$/
+            }
+        ],
+        property: [{
+                token : "text",
+                regex : "\\s+"
+            }, {
+                token : [
+                    "storage.type", "punctuation.operator", "entity.name.function", "text",
+                    "keyword.operator", "text",
+                    "storage.type", "text", "entity.name.function", "text", "paren.lparen"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(?:(\\s+)(\\w+))?(\\s*)(\\()",
+                next: "function_arguments"
+            }, {
+                token : "punctuation.operator",
+                regex : /[.](?![.])/
+            }, {
+                token : "support.function",
+                regex : /(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:op|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/
+            }, {
+                token : "support.function.dom",
+                regex : /(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName|ClassName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/
+            }, {
+                token :  "support.constant",
+                regex : /(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/
+            }, {
+                token : "identifier",
+                regex : identifierRe
+            }, {
+                regex: "",
+                token: "empty",
+                next: "no_regex"
+            }
+        ],
+        "start": [
+            DocCommentHighlightRules.getStartRule("doc-start"),
+            comments("start"),
+            {
+                token: "string.regexp",
+                regex: "\\/",
+                next: "regex"
+            }, {
+                token : "text",
+                regex : "\\s+|^$",
+                next : "start"
+            }, {
+                token: "empty",
+                regex: "",
+                next: "no_regex"
+            }
+        ],
+        "regex": [
+            {
+                token: "regexp.keyword.operator",
+                regex: "\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"
+            }, {
+                token: "string.regexp",
+                regex: "/[sxngimy]*",
+                next: "no_regex"
+            }, {
+                token : "invalid",
+                regex: /\{\d+\b,?\d*\}[+*]|[+*$^?][+*]|[$^][?]|\?{3,}/
+            }, {
+                token : "constant.language.escape",
+                regex: /\(\?[:=!]|\)|\{\d+\b,?\d*\}|[+*]\?|[()$^+*?.]/
+            }, {
+                token : "constant.language.delimiter",
+                regex: /\|/
+            }, {
+                token: "constant.language.escape",
+                regex: /\[\^?/,
+                next: "regex_character_class"
+            }, {
+                token: "empty",
+                regex: "$",
+                next: "no_regex"
+            }, {
+                defaultToken: "string.regexp"
+            }
+        ],
+        "regex_character_class": [
+            {
+                token: "regexp.charclass.keyword.operator",
+                regex: "\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"
+            }, {
+                token: "constant.language.escape",
+                regex: "]",
+                next: "regex"
+            }, {
+                token: "constant.language.escape",
+                regex: "-"
+            }, {
+                token: "empty",
+                regex: "$",
+                next: "no_regex"
+            }, {
+                defaultToken: "string.regexp.charachterclass"
+            }
+        ],
+        "function_arguments": [
+            {
+                token: "variable.parameter",
+                regex: identifierRe
+            }, {
+                token: "punctuation.operator",
+                regex: "[, ]+"
+            }, {
+                token: "punctuation.operator",
+                regex: "$"
+            }, {
+                token: "empty",
+                regex: "",
+                next: "no_regex"
+            }
+        ],
+        "qqstring" : [
+            {
+                token : "constant.language.escape",
+                regex : escapedRe
+            }, {
+                token : "string",
+                regex : "\\\\$",
+                consumeLineEnd  : true
+            }, {
+                token : "string",
+                regex : '"|$',
+                next  : "no_regex"
+            }, {
+                defaultToken: "string"
+            }
+        ],
+        "qstring" : [
+            {
+                token : "constant.language.escape",
+                regex : escapedRe
+            }, {
+                token : "string",
+                regex : "\\\\$",
+                consumeLineEnd  : true
+            }, {
+                token : "string",
+                regex : "'|$",
+                next  : "no_regex"
+            }, {
+                defaultToken: "string"
+            }
+        ]
+    };
+
+
+    if (!options || !options.noES6) {
+        this.$rules.no_regex.unshift({
+            regex: "[{}]", onMatch: function(val, state, stack) {
+                this.next = val == "{" ? this.nextState : "";
+                if (val == "{" && stack.length) {
+                    stack.unshift("start", state);
+                }
+                else if (val == "}" && stack.length) {
+                    stack.shift();
+                    this.next = stack.shift();
+                    if (this.next.indexOf("string") != -1 || this.next.indexOf("jsx") != -1)
+                        return "paren.quasi.end";
+                }
+                return val == "{" ? "paren.lparen" : "paren.rparen";
+            },
+            nextState: "start"
+        }, {
+            token : "string.quasi.start",
+            regex : /`/,
+            push  : [{
+                token : "constant.language.escape",
+                regex : escapedRe
+            }, {
+                token : "paren.quasi.start",
+                regex : /\${/,
+                push  : "start"
+            }, {
+                token : "string.quasi.end",
+                regex : /`/,
+                next  : "pop"
+            }, {
+                defaultToken: "string.quasi"
+            }]
+        });
+
+        if (!options || options.jsx != false)
+            JSX.call(this);
+    }
+
+    this.embedRules(DocCommentHighlightRules, "doc-",
+        [ DocCommentHighlightRules.getEndRule("no_regex") ]);
+
+    this.normalizeRules();
+};
+
+oop.inherits(JavaScriptHighlightRules, TextHighlightRules);
+
+function JSX() {
+    var tagRegex = identifierRe.replace("\\d", "\\d\\-");
+    var jsxTag = {
+        onMatch : function(val, state, stack) {
+            var offset = val.charAt(1) == "/" ? 2 : 1;
+            if (offset == 1) {
+                if (state != this.nextState)
+                    stack.unshift(this.next, this.nextState, 0);
+                else
+                    stack.unshift(this.next);
+                stack[2]++;
+            } else if (offset == 2) {
+                if (state == this.nextState) {
+                    stack[1]--;
+                    if (!stack[1] || stack[1] < 0) {
+                        stack.shift();
+                        stack.shift();
+                    }
+                }
+            }
+            return [{
+                type: "meta.tag.punctuation." + (offset == 1 ? "" : "end-") + "tag-open.xml",
+                value: val.slice(0, offset)
+            }, {
+                type: "meta.tag.tag-name.xml",
+                value: val.substr(offset)
+            }];
+        },
+        regex : "</?" + tagRegex + "",
+        next: "jsxAttributes",
+        nextState: "jsx"
+    };
+    this.$rules.start.unshift(jsxTag);
+    var jsxJsRule = {
+        regex: "{",
+        token: "paren.quasi.start",
+        push: "start"
+    };
+    this.$rules.jsx = [
+        jsxJsRule,
+        jsxTag,
+        {include : "reference"},
+        {defaultToken: "string"}
+    ];
+    this.$rules.jsxAttributes = [{
+        token : "meta.tag.punctuation.tag-close.xml",
+        regex : "/?>",
+        onMatch : function(value, currentState, stack) {
+            if (currentState == stack[0])
+                stack.shift();
+            if (value.length == 2) {
+                if (stack[0] == this.nextState)
+                    stack[1]--;
+                if (!stack[1] || stack[1] < 0) {
+                    stack.splice(0, 2);
+                }
+            }
+            this.next = stack[0] || "start";
+            return [{type: this.token, value: value}];
+        },
+        nextState: "jsx"
+    },
+    jsxJsRule,
+    comments("jsxAttributes"),
+    {
+        token : "entity.other.attribute-name.xml",
+        regex : tagRegex
+    }, {
+        token : "keyword.operator.attribute-equals.xml",
+        regex : "="
+    }, {
+        token : "text.tag-whitespace.xml",
+        regex : "\\s+"
+    }, {
+        token : "string.attribute-value.xml",
+        regex : "'",
+        stateName : "jsx_attr_q",
+        push : [
+            {token : "string.attribute-value.xml", regex: "'", next: "pop"},
+            {include : "reference"},
+            {defaultToken : "string.attribute-value.xml"}
+        ]
+    }, {
+        token : "string.attribute-value.xml",
+        regex : '"',
+        stateName : "jsx_attr_qq",
+        push : [
+            {token : "string.attribute-value.xml", regex: '"', next: "pop"},
+            {include : "reference"},
+            {defaultToken : "string.attribute-value.xml"}
+        ]
+    },
+    jsxTag
+    ];
+    this.$rules.reference = [{
+        token : "constant.language.escape.reference.xml",
+        regex : "(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"
+    }];
+}
+
+function comments(next) {
+    return [
+        {
+            token : "comment", // multi line comment
+            regex : /\/\*/,
+            next: [
+                DocCommentHighlightRules.getTagRule(),
+                {token : "comment", regex : "\\*\\/", next : next || "pop"},
+                {defaultToken : "comment", caseInsensitive: true}
+            ]
+        }, {
+            token : "comment",
+            regex : "\\/\\/",
+            next: [
+                DocCommentHighlightRules.getTagRule(),
+                {token : "comment", regex : "$|^", next : next || "pop"},
+                {defaultToken : "comment", caseInsensitive: true}
+            ]
+        }
+    ];
+}
+exports.JavaScriptHighlightRules = JavaScriptHighlightRules;
+});
+
+ace.define("ace/mode/matching_brace_outdent",[], function(require, exports, module) {
+"use strict";
+
+var Range = require("../range").Range;
+
+var MatchingBraceOutdent = function() {};
+
+(function() {
+
+    this.checkOutdent = function(line, input) {
+        if (! /^\s+$/.test(line))
+            return false;
+
+        return /^\s*\}/.test(input);
+    };
+
+    this.autoOutdent = function(doc, row) {
+        var line = doc.getLine(row);
+        var match = line.match(/^(\s*\})/);
+
+        if (!match) return 0;
+
+        var column = match[1].length;
+        var openBracePos = doc.findMatchingBracket({row: row, column: column});
+
+        if (!openBracePos || openBracePos.row == row) return 0;
+
+        var indent = this.$getIndent(doc.getLine(openBracePos.row));
+        doc.replace(new Range(row, 0, row, column-1), indent);
+    };
+
+    this.$getIndent = function(line) {
+        return line.match(/^\s*/)[0];
+    };
+
+}).call(MatchingBraceOutdent.prototype);
+
+exports.MatchingBraceOutdent = MatchingBraceOutdent;
+});
+
+ace.define("ace/mode/folding/cstyle",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Range = require("../../range").Range;
+var BaseFoldMode = require("./fold_mode").FoldMode;
+
+var FoldMode = exports.FoldMode = function(commentRegex) {
+    if (commentRegex) {
+        this.foldingStartMarker = new RegExp(
+            this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start)
+        );
+        this.foldingStopMarker = new RegExp(
+            this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end)
+        );
+    }
+};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+    
+    this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/;
+    this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/;
+    this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/;
+    this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/;
+    this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/;
+    this._getFoldWidgetBase = this.getFoldWidget;
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+    
+        if (this.singleLineBlockCommentRe.test(line)) {
+            if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line))
+                return "";
+        }
+    
+        var fw = this._getFoldWidgetBase(session, foldStyle, row);
+    
+        if (!fw && this.startRegionRe.test(line))
+            return "start"; // lineCommentRegionStart
+    
+        return fw;
+    };
+
+    this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) {
+        var line = session.getLine(row);
+        
+        if (this.startRegionRe.test(line))
+            return this.getCommentRegionBlock(session, line, row);
+        
+        var match = line.match(this.foldingStartMarker);
+        if (match) {
+            var i = match.index;
+
+            if (match[1])
+                return this.openingBracketBlock(session, match[1], row, i);
+                
+            var range = session.getCommentFoldRange(row, i + match[0].length, 1);
+            
+            if (range && !range.isMultiLine()) {
+                if (forceMultiline) {
+                    range = this.getSectionRange(session, row);
+                } else if (foldStyle != "all")
+                    range = null;
+            }
+            
+            return range;
+        }
+
+        if (foldStyle === "markbegin")
+            return;
+
+        var match = line.match(this.foldingStopMarker);
+        if (match) {
+            var i = match.index + match[0].length;
+
+            if (match[1])
+                return this.closingBracketBlock(session, match[1], row, i);
+
+            return session.getCommentFoldRange(row, i, -1);
+        }
+    };
+    
+    this.getSectionRange = function(session, row) {
+        var line = session.getLine(row);
+        var startIndent = line.search(/\S/);
+        var startRow = row;
+        var startColumn = line.length;
+        row = row + 1;
+        var endRow = row;
+        var maxRow = session.getLength();
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var indent = line.search(/\S/);
+            if (indent === -1)
+                continue;
+            if  (startIndent > indent)
+                break;
+            var subRange = this.getFoldWidgetRange(session, "all", row);
+            
+            if (subRange) {
+                if (subRange.start.row <= startRow) {
+                    break;
+                } else if (subRange.isMultiLine()) {
+                    row = subRange.end.row;
+                } else if (startIndent == indent) {
+                    break;
+                }
+            }
+            endRow = row;
+        }
+        
+        return new Range(startRow, startColumn, endRow, session.getLine(endRow).length);
+    };
+    this.getCommentRegionBlock = function(session, line, row) {
+        var startColumn = line.search(/\s*$/);
+        var maxRow = session.getLength();
+        var startRow = row;
+        
+        var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/;
+        var depth = 1;
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var m = re.exec(line);
+            if (!m) continue;
+            if (m[1]) depth--;
+            else depth++;
+
+            if (!depth) break;
+        }
+
+        var endRow = row;
+        if (endRow > startRow) {
+            return new Range(startRow, startColumn, endRow, line.length);
+        }
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/javascript",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var JavaScriptHighlightRules = require("./javascript_highlight_rules").JavaScriptHighlightRules;
+var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent;
+var WorkerClient = require("../worker/worker_client").WorkerClient;
+var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour;
+var CStyleFoldMode = require("./folding/cstyle").FoldMode;
+
+var Mode = function() {
+    this.HighlightRules = JavaScriptHighlightRules;
+    
+    this.$outdent = new MatchingBraceOutdent();
+    this.$behaviour = new CstyleBehaviour();
+    this.foldingRules = new CStyleFoldMode();
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+
+    this.lineCommentStart = "//";
+    this.blockComment = {start: "/*", end: "*/"};
+    this.$quotes = {'"': '"', "'": "'", "`": "`"};
+
+    this.getNextLineIndent = function(state, line, tab) {
+        var indent = this.$getIndent(line);
+
+        var tokenizedLine = this.getTokenizer().getLineTokens(line, state);
+        var tokens = tokenizedLine.tokens;
+        var endState = tokenizedLine.state;
+
+        if (tokens.length && tokens[tokens.length-1].type == "comment") {
+            return indent;
+        }
+
+        if (state == "start" || state == "no_regex") {
+            var match = line.match(/^.*(?:\bcase\b.*:|[\{\(\[])\s*$/);
+            if (match) {
+                indent += tab;
+            }
+        } else if (state == "doc-start") {
+            if (endState == "start" || endState == "no_regex") {
+                return "";
+            }
+            var match = line.match(/^\s*(\/?)\*/);
+            if (match) {
+                if (match[1]) {
+                    indent += " ";
+                }
+                indent += "* ";
+            }
+        }
+
+        return indent;
+    };
+
+    this.checkOutdent = function(state, line, input) {
+        return this.$outdent.checkOutdent(line, input);
+    };
+
+    this.autoOutdent = function(state, doc, row) {
+        this.$outdent.autoOutdent(doc, row);
+    };
+
+    this.createWorker = function(session) {
+        var worker = new WorkerClient(["ace"], "ace/mode/javascript_worker", "JavaScriptWorker");
+        worker.attachToDocument(session.getDocument());
+
+        worker.on("annotate", function(results) {
+            session.setAnnotations(results.data);
+        });
+
+        worker.on("terminate", function() {
+            session.clearAnnotations();
+        });
+
+        return worker;
+    };
+
+    this.$id = "ace/mode/javascript";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/javascript"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 327 - 0
services/web/public/js/ace-1.4.3/mode-json.js

@@ -0,0 +1,327 @@
+ace.define("ace/mode/json_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var JsonHighlightRules = function() {
+    this.$rules = {
+        "start" : [
+            {
+                token : "variable", // single line
+                regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]\\s*(?=:)'
+            }, {
+                token : "string", // single line
+                regex : '"',
+                next  : "string"
+            }, {
+                token : "constant.numeric", // hex
+                regex : "0[xX][0-9a-fA-F]+\\b"
+            }, {
+                token : "constant.numeric", // float
+                regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
+            }, {
+                token : "constant.language.boolean",
+                regex : "(?:true|false)\\b"
+            }, {
+                token : "text", // single quoted strings are not allowed
+                regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
+            }, {
+                token : "comment", // comments are not allowed, but who cares?
+                regex : "\\/\\/.*$"
+            }, {
+                token : "comment.start", // comments are not allowed, but who cares?
+                regex : "\\/\\*",
+                next  : "comment"
+            }, {
+                token : "paren.lparen",
+                regex : "[[({]"
+            }, {
+                token : "paren.rparen",
+                regex : "[\\])}]"
+            }, {
+                token : "text",
+                regex : "\\s+"
+            }
+        ],
+        "string" : [
+            {
+                token : "constant.language.escape",
+                regex : /\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|["\\\/bfnrt])/
+            }, {
+                token : "string",
+                regex : '"|$',
+                next  : "start"
+            }, {
+                defaultToken : "string"
+            }
+        ],
+        "comment" : [
+            {
+                token : "comment.end", // comments are not allowed, but who cares?
+                regex : "\\*\\/",
+                next  : "start"
+            }, {
+                defaultToken: "comment"
+            }
+        ]
+    };
+    
+};
+
+oop.inherits(JsonHighlightRules, TextHighlightRules);
+
+exports.JsonHighlightRules = JsonHighlightRules;
+});
+
+ace.define("ace/mode/matching_brace_outdent",[], function(require, exports, module) {
+"use strict";
+
+var Range = require("../range").Range;
+
+var MatchingBraceOutdent = function() {};
+
+(function() {
+
+    this.checkOutdent = function(line, input) {
+        if (! /^\s+$/.test(line))
+            return false;
+
+        return /^\s*\}/.test(input);
+    };
+
+    this.autoOutdent = function(doc, row) {
+        var line = doc.getLine(row);
+        var match = line.match(/^(\s*\})/);
+
+        if (!match) return 0;
+
+        var column = match[1].length;
+        var openBracePos = doc.findMatchingBracket({row: row, column: column});
+
+        if (!openBracePos || openBracePos.row == row) return 0;
+
+        var indent = this.$getIndent(doc.getLine(openBracePos.row));
+        doc.replace(new Range(row, 0, row, column-1), indent);
+    };
+
+    this.$getIndent = function(line) {
+        return line.match(/^\s*/)[0];
+    };
+
+}).call(MatchingBraceOutdent.prototype);
+
+exports.MatchingBraceOutdent = MatchingBraceOutdent;
+});
+
+ace.define("ace/mode/folding/cstyle",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Range = require("../../range").Range;
+var BaseFoldMode = require("./fold_mode").FoldMode;
+
+var FoldMode = exports.FoldMode = function(commentRegex) {
+    if (commentRegex) {
+        this.foldingStartMarker = new RegExp(
+            this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start)
+        );
+        this.foldingStopMarker = new RegExp(
+            this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end)
+        );
+    }
+};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+    
+    this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/;
+    this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/;
+    this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/;
+    this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/;
+    this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/;
+    this._getFoldWidgetBase = this.getFoldWidget;
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+    
+        if (this.singleLineBlockCommentRe.test(line)) {
+            if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line))
+                return "";
+        }
+    
+        var fw = this._getFoldWidgetBase(session, foldStyle, row);
+    
+        if (!fw && this.startRegionRe.test(line))
+            return "start"; // lineCommentRegionStart
+    
+        return fw;
+    };
+
+    this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) {
+        var line = session.getLine(row);
+        
+        if (this.startRegionRe.test(line))
+            return this.getCommentRegionBlock(session, line, row);
+        
+        var match = line.match(this.foldingStartMarker);
+        if (match) {
+            var i = match.index;
+
+            if (match[1])
+                return this.openingBracketBlock(session, match[1], row, i);
+                
+            var range = session.getCommentFoldRange(row, i + match[0].length, 1);
+            
+            if (range && !range.isMultiLine()) {
+                if (forceMultiline) {
+                    range = this.getSectionRange(session, row);
+                } else if (foldStyle != "all")
+                    range = null;
+            }
+            
+            return range;
+        }
+
+        if (foldStyle === "markbegin")
+            return;
+
+        var match = line.match(this.foldingStopMarker);
+        if (match) {
+            var i = match.index + match[0].length;
+
+            if (match[1])
+                return this.closingBracketBlock(session, match[1], row, i);
+
+            return session.getCommentFoldRange(row, i, -1);
+        }
+    };
+    
+    this.getSectionRange = function(session, row) {
+        var line = session.getLine(row);
+        var startIndent = line.search(/\S/);
+        var startRow = row;
+        var startColumn = line.length;
+        row = row + 1;
+        var endRow = row;
+        var maxRow = session.getLength();
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var indent = line.search(/\S/);
+            if (indent === -1)
+                continue;
+            if  (startIndent > indent)
+                break;
+            var subRange = this.getFoldWidgetRange(session, "all", row);
+            
+            if (subRange) {
+                if (subRange.start.row <= startRow) {
+                    break;
+                } else if (subRange.isMultiLine()) {
+                    row = subRange.end.row;
+                } else if (startIndent == indent) {
+                    break;
+                }
+            }
+            endRow = row;
+        }
+        
+        return new Range(startRow, startColumn, endRow, session.getLine(endRow).length);
+    };
+    this.getCommentRegionBlock = function(session, line, row) {
+        var startColumn = line.search(/\s*$/);
+        var maxRow = session.getLength();
+        var startRow = row;
+        
+        var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/;
+        var depth = 1;
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var m = re.exec(line);
+            if (!m) continue;
+            if (m[1]) depth--;
+            else depth++;
+
+            if (!depth) break;
+        }
+
+        var endRow = row;
+        if (endRow > startRow) {
+            return new Range(startRow, startColumn, endRow, line.length);
+        }
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/json",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var HighlightRules = require("./json_highlight_rules").JsonHighlightRules;
+var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent;
+var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour;
+var CStyleFoldMode = require("./folding/cstyle").FoldMode;
+var WorkerClient = require("../worker/worker_client").WorkerClient;
+
+var Mode = function() {
+    this.HighlightRules = HighlightRules;
+    this.$outdent = new MatchingBraceOutdent();
+    this.$behaviour = new CstyleBehaviour();
+    this.foldingRules = new CStyleFoldMode();
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+
+    this.getNextLineIndent = function(state, line, tab) {
+        var indent = this.$getIndent(line);
+
+        if (state == "start") {
+            var match = line.match(/^.*[\{\(\[]\s*$/);
+            if (match) {
+                indent += tab;
+            }
+        }
+
+        return indent;
+    };
+
+    this.checkOutdent = function(state, line, input) {
+        return this.$outdent.checkOutdent(line, input);
+    };
+
+    this.autoOutdent = function(state, doc, row) {
+        this.$outdent.autoOutdent(doc, row);
+    };
+
+    this.createWorker = function(session) {
+        var worker = new WorkerClient(["ace"], "ace/mode/json_worker", "JsonWorker");
+        worker.attachToDocument(session.getDocument());
+
+        worker.on("annotate", function(e) {
+            session.setAnnotations(e.data);
+        });
+
+        worker.on("terminate", function() {
+            session.clearAnnotations();
+        });
+
+        return worker;
+    };
+
+
+    this.$id = "ace/mode/json";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/json"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

Fișier diff suprimat deoarece este prea mare
+ 1545 - 0
services/web/public/js/ace-1.4.3/mode-jsoniq.js


Fișier diff suprimat deoarece este prea mare
+ 6 - 0
services/web/public/js/ace-1.4.3/mode-jsp.js


+ 326 - 0
services/web/public/js/ace-1.4.3/mode-jssm.js

@@ -0,0 +1,326 @@
+ace.define("ace/mode/jssm_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var JSSMHighlightRules = function() {
+
+    this.$rules = {
+        start: [{
+            token: "punctuation.definition.comment.mn",
+            regex: /\/\*/,
+            push: [{
+                token: "punctuation.definition.comment.mn",
+                regex: /\*\//,
+                next: "pop"
+            }, {
+                defaultToken: "comment.block.jssm"
+            }],
+            comment: "block comment"
+        }, {
+            token: "comment.line.jssm",
+            regex: /\/\//,
+            push: [{
+                token: "comment.line.jssm",
+                regex: /$/,
+                next: "pop"
+            }, {
+                defaultToken: "comment.line.jssm"
+            }],
+            comment: "block comment"
+        }, {
+            token: "entity.name.function",
+            regex: /\${/,
+            push: [{
+                token: "entity.name.function",
+                regex: /}/,
+                next: "pop"
+            }, {
+                defaultToken: "keyword.other"
+            }],
+            comment: "js outcalls"
+        }, {
+            token: "constant.numeric",
+            regex: /[0-9]*\.[0-9]*\.[0-9]*/,
+            comment: "semver"
+        }, {
+            token: "constant.language.jssmLanguage",
+            regex: /graph_layout\s*:/,
+            comment: "jssm language tokens"
+        }, {
+            token: "constant.language.jssmLanguage",
+            regex: /machine_name\s*:/,
+            comment: "jssm language tokens"
+        }, {
+            token: "constant.language.jssmLanguage",
+            regex: /machine_version\s*:/,
+            comment: "jssm language tokens"
+        }, {
+            token: "constant.language.jssmLanguage",
+            regex: /jssm_version\s*:/,
+            comment: "jssm language tokens"
+        }, {
+            token: "keyword.control.transition.jssmArrow.legal_legal",
+            regex: /<->/,
+            comment: "transitions"
+        }, {
+            token: "keyword.control.transition.jssmArrow.legal_none",
+            regex: /<-/,
+            comment: "transitions"
+        }, {
+            token: "keyword.control.transition.jssmArrow.none_legal",
+            regex: /->/,
+            comment: "transitions"
+        }, {
+            token: "keyword.control.transition.jssmArrow.main_main",
+            regex: /<=>/,
+            comment: "transitions"
+        }, {
+            token: "keyword.control.transition.jssmArrow.none_main",
+            regex: /=>/,
+            comment: "transitions"
+        }, {
+            token: "keyword.control.transition.jssmArrow.main_none",
+            regex: /<=/,
+            comment: "transitions"
+        }, {
+            token: "keyword.control.transition.jssmArrow.forced_forced",
+            regex: /<~>/,
+            comment: "transitions"
+        }, {
+            token: "keyword.control.transition.jssmArrow.none_forced",
+            regex: /~>/,
+            comment: "transitions"
+        }, {
+            token: "keyword.control.transition.jssmArrow.forced_none",
+            regex: /<~/,
+            comment: "transitions"
+        }, {
+            token: "keyword.control.transition.jssmArrow.legal_main",
+            regex: /<-=>/,
+            comment: "transitions"
+        }, {
+            token: "keyword.control.transition.jssmArrow.main_legal",
+            regex: /<=->/,
+            comment: "transitions"
+        }, {
+            token: "keyword.control.transition.jssmArrow.legal_forced",
+            regex: /<-~>/,
+            comment: "transitions"
+        }, {
+            token: "keyword.control.transition.jssmArrow.forced_legal",
+            regex: /<~->/,
+            comment: "transitions"
+        }, {
+            token: "keyword.control.transition.jssmArrow.main_forced",
+            regex: /<=~>/,
+            comment: "transitions"
+        }, {
+            token: "keyword.control.transition.jssmArrow.forced_main",
+            regex: /<~=>/,
+            comment: "transitions"
+        }, {
+            token: "constant.numeric.jssmProbability",
+            regex: /[0-9]+%/,
+            comment: "edge probability annotation"
+        }, {
+            token: "constant.character.jssmAction",
+            regex: /\'[^']*\'/,
+            comment: "action annotation"
+        }, {
+            token: "entity.name.tag.jssmLabel.doublequoted",
+            regex: /\"[^"]*\"/,
+            comment: "jssm label annotation"
+        }, {
+            token: "entity.name.tag.jssmLabel.atom",
+            regex: /[a-zA-Z0-9_.+&()#@!?,]/,
+            comment: "jssm label annotation"
+        }]
+    };
+    
+    this.normalizeRules();
+};
+
+JSSMHighlightRules.metaData = {
+    fileTypes: ["jssm", "jssm_state"],
+    name: "JSSM",
+    scopeName: "source.jssm"
+};
+
+
+oop.inherits(JSSMHighlightRules, TextHighlightRules);
+
+exports.JSSMHighlightRules = JSSMHighlightRules;
+});
+
+ace.define("ace/mode/folding/cstyle",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Range = require("../../range").Range;
+var BaseFoldMode = require("./fold_mode").FoldMode;
+
+var FoldMode = exports.FoldMode = function(commentRegex) {
+    if (commentRegex) {
+        this.foldingStartMarker = new RegExp(
+            this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start)
+        );
+        this.foldingStopMarker = new RegExp(
+            this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end)
+        );
+    }
+};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+    
+    this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/;
+    this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/;
+    this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/;
+    this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/;
+    this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/;
+    this._getFoldWidgetBase = this.getFoldWidget;
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+    
+        if (this.singleLineBlockCommentRe.test(line)) {
+            if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line))
+                return "";
+        }
+    
+        var fw = this._getFoldWidgetBase(session, foldStyle, row);
+    
+        if (!fw && this.startRegionRe.test(line))
+            return "start"; // lineCommentRegionStart
+    
+        return fw;
+    };
+
+    this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) {
+        var line = session.getLine(row);
+        
+        if (this.startRegionRe.test(line))
+            return this.getCommentRegionBlock(session, line, row);
+        
+        var match = line.match(this.foldingStartMarker);
+        if (match) {
+            var i = match.index;
+
+            if (match[1])
+                return this.openingBracketBlock(session, match[1], row, i);
+                
+            var range = session.getCommentFoldRange(row, i + match[0].length, 1);
+            
+            if (range && !range.isMultiLine()) {
+                if (forceMultiline) {
+                    range = this.getSectionRange(session, row);
+                } else if (foldStyle != "all")
+                    range = null;
+            }
+            
+            return range;
+        }
+
+        if (foldStyle === "markbegin")
+            return;
+
+        var match = line.match(this.foldingStopMarker);
+        if (match) {
+            var i = match.index + match[0].length;
+
+            if (match[1])
+                return this.closingBracketBlock(session, match[1], row, i);
+
+            return session.getCommentFoldRange(row, i, -1);
+        }
+    };
+    
+    this.getSectionRange = function(session, row) {
+        var line = session.getLine(row);
+        var startIndent = line.search(/\S/);
+        var startRow = row;
+        var startColumn = line.length;
+        row = row + 1;
+        var endRow = row;
+        var maxRow = session.getLength();
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var indent = line.search(/\S/);
+            if (indent === -1)
+                continue;
+            if  (startIndent > indent)
+                break;
+            var subRange = this.getFoldWidgetRange(session, "all", row);
+            
+            if (subRange) {
+                if (subRange.start.row <= startRow) {
+                    break;
+                } else if (subRange.isMultiLine()) {
+                    row = subRange.end.row;
+                } else if (startIndent == indent) {
+                    break;
+                }
+            }
+            endRow = row;
+        }
+        
+        return new Range(startRow, startColumn, endRow, session.getLine(endRow).length);
+    };
+    this.getCommentRegionBlock = function(session, line, row) {
+        var startColumn = line.search(/\s*$/);
+        var maxRow = session.getLength();
+        var startRow = row;
+        
+        var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/;
+        var depth = 1;
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var m = re.exec(line);
+            if (!m) continue;
+            if (m[1]) depth--;
+            else depth++;
+
+            if (!depth) break;
+        }
+
+        var endRow = row;
+        if (endRow > startRow) {
+            return new Range(startRow, startColumn, endRow, line.length);
+        }
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/jssm",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var JSSMHighlightRules = require("./jssm_highlight_rules").JSSMHighlightRules;
+var FoldMode = require("./folding/cstyle").FoldMode;
+
+var Mode = function() {
+    this.HighlightRules = JSSMHighlightRules;
+    this.foldingRules = new FoldMode();
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+    this.lineCommentStart = "//";
+    this.blockComment = {start: "/*", end: "*/"};
+    this.$id = "ace/mode/jssm";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/jssm"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 412 - 0
services/web/public/js/ace-1.4.3/mode-jsx.js

@@ -0,0 +1,412 @@
+ace.define("ace/mode/doc_comment_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var DocCommentHighlightRules = function() {
+    this.$rules = {
+        "start" : [ {
+            token : "comment.doc.tag",
+            regex : "@[\\w\\d_]+" // TODO: fix email addresses
+        }, 
+        DocCommentHighlightRules.getTagRule(),
+        {
+            defaultToken : "comment.doc",
+            caseInsensitive: true
+        }]
+    };
+};
+
+oop.inherits(DocCommentHighlightRules, TextHighlightRules);
+
+DocCommentHighlightRules.getTagRule = function(start) {
+    return {
+        token : "comment.doc.tag.storage.type",
+        regex : "\\b(?:TODO|FIXME|XXX|HACK)\\b"
+    };
+};
+
+DocCommentHighlightRules.getStartRule = function(start) {
+    return {
+        token : "comment.doc", // doc comment
+        regex : "\\/\\*(?=\\*)",
+        next  : start
+    };
+};
+
+DocCommentHighlightRules.getEndRule = function (start) {
+    return {
+        token : "comment.doc", // closing comment
+        regex : "\\*\\/",
+        next  : start
+    };
+};
+
+
+exports.DocCommentHighlightRules = DocCommentHighlightRules;
+
+});
+
+ace.define("ace/mode/jsx_highlight_rules",[], function(require, exports, module) {
+var oop = require("../lib/oop");
+var lang = require("../lib/lang");
+var DocCommentHighlightRules = require("./doc_comment_highlight_rules").DocCommentHighlightRules;
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var JsxHighlightRules = function() {
+    var keywords = lang.arrayToMap(
+        ("break|do|instanceof|typeof|case|else|new|var|catch|finally|return|void|continue|for|switch|default|while|function|this|" +
+         "if|throw|" +
+         "delete|in|try|" +
+         "class|extends|super|import|from|into|implements|interface|static|mixin|override|abstract|final|" +
+         "number|int|string|boolean|variant|" +
+         "log|assert").split("|")
+    );
+    
+    var buildinConstants = lang.arrayToMap(
+        ("null|true|false|NaN|Infinity|__FILE__|__LINE__|undefined").split("|")
+    );
+    
+    var reserved = lang.arrayToMap(
+        ("debugger|with|" +
+         "const|export|" +
+         "let|private|public|yield|protected|" +
+         "extern|native|as|operator|__fake__|__readonly__").split("|")
+    );
+    
+    var identifierRe = "[a-zA-Z_][a-zA-Z0-9_]*\\b";
+    
+    this.$rules = {
+        "start" : [
+            {
+                token : "comment",
+                regex : "\\/\\/.*$"
+            },
+            DocCommentHighlightRules.getStartRule("doc-start"),
+            {
+                token : "comment", // multi line comment
+                regex : "\\/\\*",
+                next : "comment"
+            }, {
+                token : "string.regexp",
+                regex : "[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"
+            }, {
+                token : "string", // single line
+                regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
+            }, {
+                token : "string", // single line
+                regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
+            }, {
+                token : "constant.numeric", // hex
+                regex : "0[xX][0-9a-fA-F]+\\b"
+            }, {
+                token : "constant.numeric", // float
+                regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
+            }, {
+                token : "constant.language.boolean",
+                regex : "(?:true|false)\\b"
+            }, {
+                token : [
+                    "storage.type",
+                    "text",
+                    "entity.name.function"
+                ],
+                regex : "(function)(\\s+)(" + identifierRe + ")"
+            }, {
+                token : function(value) {
+                    if (value == "this")
+                        return "variable.language";
+                    else if (value == "function")
+                        return "storage.type";
+                    else if (keywords.hasOwnProperty(value) || reserved.hasOwnProperty(value))
+                        return "keyword";
+                    else if (buildinConstants.hasOwnProperty(value))
+                        return "constant.language";
+                    else if (/^_?[A-Z][a-zA-Z0-9_]*$/.test(value))
+                        return "language.support.class";
+                    else
+                        return "identifier";
+                },
+                regex : identifierRe
+            }, {
+                token : "keyword.operator",
+                regex : "!|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|==|=|!=|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"
+            }, {
+                token : "punctuation.operator",
+                regex : "\\?|\\:|\\,|\\;|\\."
+            }, {
+                token : "paren.lparen",
+                regex : "[[({<]"
+            }, {
+                token : "paren.rparen",
+                regex : "[\\])}>]"
+            }, {
+                token : "text",
+                regex : "\\s+"
+            }
+        ],
+        "comment" : [
+            {
+                token : "comment", // closing comment
+                regex : "\\*\\/",
+                next : "start"
+            }, {
+                defaultToken : "comment"
+            }
+        ]
+    };
+    
+    this.embedRules(DocCommentHighlightRules, "doc-",
+        [ DocCommentHighlightRules.getEndRule("start") ]);
+};
+
+oop.inherits(JsxHighlightRules, TextHighlightRules);
+
+exports.JsxHighlightRules = JsxHighlightRules;
+});
+
+ace.define("ace/mode/matching_brace_outdent",[], function(require, exports, module) {
+"use strict";
+
+var Range = require("../range").Range;
+
+var MatchingBraceOutdent = function() {};
+
+(function() {
+
+    this.checkOutdent = function(line, input) {
+        if (! /^\s+$/.test(line))
+            return false;
+
+        return /^\s*\}/.test(input);
+    };
+
+    this.autoOutdent = function(doc, row) {
+        var line = doc.getLine(row);
+        var match = line.match(/^(\s*\})/);
+
+        if (!match) return 0;
+
+        var column = match[1].length;
+        var openBracePos = doc.findMatchingBracket({row: row, column: column});
+
+        if (!openBracePos || openBracePos.row == row) return 0;
+
+        var indent = this.$getIndent(doc.getLine(openBracePos.row));
+        doc.replace(new Range(row, 0, row, column-1), indent);
+    };
+
+    this.$getIndent = function(line) {
+        return line.match(/^\s*/)[0];
+    };
+
+}).call(MatchingBraceOutdent.prototype);
+
+exports.MatchingBraceOutdent = MatchingBraceOutdent;
+});
+
+ace.define("ace/mode/folding/cstyle",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Range = require("../../range").Range;
+var BaseFoldMode = require("./fold_mode").FoldMode;
+
+var FoldMode = exports.FoldMode = function(commentRegex) {
+    if (commentRegex) {
+        this.foldingStartMarker = new RegExp(
+            this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start)
+        );
+        this.foldingStopMarker = new RegExp(
+            this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end)
+        );
+    }
+};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+    
+    this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/;
+    this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/;
+    this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/;
+    this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/;
+    this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/;
+    this._getFoldWidgetBase = this.getFoldWidget;
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+    
+        if (this.singleLineBlockCommentRe.test(line)) {
+            if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line))
+                return "";
+        }
+    
+        var fw = this._getFoldWidgetBase(session, foldStyle, row);
+    
+        if (!fw && this.startRegionRe.test(line))
+            return "start"; // lineCommentRegionStart
+    
+        return fw;
+    };
+
+    this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) {
+        var line = session.getLine(row);
+        
+        if (this.startRegionRe.test(line))
+            return this.getCommentRegionBlock(session, line, row);
+        
+        var match = line.match(this.foldingStartMarker);
+        if (match) {
+            var i = match.index;
+
+            if (match[1])
+                return this.openingBracketBlock(session, match[1], row, i);
+                
+            var range = session.getCommentFoldRange(row, i + match[0].length, 1);
+            
+            if (range && !range.isMultiLine()) {
+                if (forceMultiline) {
+                    range = this.getSectionRange(session, row);
+                } else if (foldStyle != "all")
+                    range = null;
+            }
+            
+            return range;
+        }
+
+        if (foldStyle === "markbegin")
+            return;
+
+        var match = line.match(this.foldingStopMarker);
+        if (match) {
+            var i = match.index + match[0].length;
+
+            if (match[1])
+                return this.closingBracketBlock(session, match[1], row, i);
+
+            return session.getCommentFoldRange(row, i, -1);
+        }
+    };
+    
+    this.getSectionRange = function(session, row) {
+        var line = session.getLine(row);
+        var startIndent = line.search(/\S/);
+        var startRow = row;
+        var startColumn = line.length;
+        row = row + 1;
+        var endRow = row;
+        var maxRow = session.getLength();
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var indent = line.search(/\S/);
+            if (indent === -1)
+                continue;
+            if  (startIndent > indent)
+                break;
+            var subRange = this.getFoldWidgetRange(session, "all", row);
+            
+            if (subRange) {
+                if (subRange.start.row <= startRow) {
+                    break;
+                } else if (subRange.isMultiLine()) {
+                    row = subRange.end.row;
+                } else if (startIndent == indent) {
+                    break;
+                }
+            }
+            endRow = row;
+        }
+        
+        return new Range(startRow, startColumn, endRow, session.getLine(endRow).length);
+    };
+    this.getCommentRegionBlock = function(session, line, row) {
+        var startColumn = line.search(/\s*$/);
+        var maxRow = session.getLength();
+        var startRow = row;
+        
+        var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/;
+        var depth = 1;
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var m = re.exec(line);
+            if (!m) continue;
+            if (m[1]) depth--;
+            else depth++;
+
+            if (!depth) break;
+        }
+
+        var endRow = row;
+        if (endRow > startRow) {
+            return new Range(startRow, startColumn, endRow, line.length);
+        }
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/jsx",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var JsxHighlightRules = require("./jsx_highlight_rules").JsxHighlightRules;
+var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent;
+var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour;
+var CStyleFoldMode = require("./folding/cstyle").FoldMode;
+
+function Mode() {
+    this.HighlightRules = JsxHighlightRules;
+    this.$outdent = new MatchingBraceOutdent();
+    this.$behaviour = new CstyleBehaviour();
+    this.foldingRules = new CStyleFoldMode();
+}
+oop.inherits(Mode, TextMode);
+
+(function() {
+
+    this.lineCommentStart = "//";
+    this.blockComment = {start: "/*", end: "*/"};
+
+    this.getNextLineIndent = function(state, line, tab) {
+        var indent = this.$getIndent(line);
+
+        var tokenizedLine = this.getTokenizer().getLineTokens(line, state);
+        var tokens = tokenizedLine.tokens;
+
+        if (tokens.length && tokens[tokens.length-1].type == "comment") {
+            return indent;
+        }
+
+        if (state == "start") {
+            var match = line.match(/^.*[\{\(\[]\s*$/);
+            if (match) {
+                indent += tab;
+            }
+        }
+
+        return indent;
+    };
+
+    this.checkOutdent = function(state, line, input) {
+        return this.$outdent.checkOutdent(line, input);
+    };
+
+    this.autoOutdent = function(state, doc, row) {
+        this.$outdent.autoOutdent(doc, row);
+    };
+
+    this.$id = "ace/mode/jsx";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/jsx"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 304 - 0
services/web/public/js/ace-1.4.3/mode-julia.js

@@ -0,0 +1,304 @@
+ace.define("ace/mode/julia_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var JuliaHighlightRules = function() {
+
+    this.$rules = { start: 
+       [ { include: '#function_decl' },
+         { include: '#function_call' },
+         { include: '#type_decl' },
+         { include: '#keyword' },
+         { include: '#operator' },
+         { include: '#number' },
+         { include: '#string' },
+         { include: '#comment' } ],
+      '#bracket': 
+       [ { token: 'keyword.bracket.julia',
+           regex: '\\(|\\)|\\[|\\]|\\{|\\}|,' } ],
+      '#comment': 
+       [ { token: 
+            [ 'punctuation.definition.comment.julia',
+              'comment.line.number-sign.julia' ],
+           regex: '(#)(?!\\{)(.*$)'} ],
+      '#function_call': 
+       [ { token: [ 'support.function.julia', 'text' ],
+           regex: '([a-zA-Z0-9_]+!?)([\\w\\xff-\\u218e\\u2455-\\uffff]*\\()'} ],
+      '#function_decl': 
+       [ { token: [ 'keyword.other.julia', 'meta.function.julia',
+               'entity.name.function.julia', 'meta.function.julia','text' ],
+           regex: '(function|macro)(\\s*)([a-zA-Z0-9_\\{]+!?)([\\w\\xff-\\u218e\\u2455-\\uffff]*)([(\\\\{])'} ],
+      '#keyword':
+       [ { token: 'keyword.other.julia',
+           regex: '\\b(?:function|type|immutable|macro|quote|abstract|bitstype|typealias|module|baremodule|new)\\b' },
+         { token: 'keyword.control.julia',
+           regex: '\\b(?:if|else|elseif|while|for|in|begin|let|end|do|try|catch|finally|return|break|continue)\\b' },
+         { token: 'storage.modifier.variable.julia',
+           regex: '\\b(?:global|local|const|export|import|importall|using)\\b' },
+         { token: 'variable.macro.julia', regex: '@[\\w\\xff-\\u218e\\u2455-\\uffff]+\\b' } ],
+      '#number': 
+       [ { token: 'constant.numeric.julia',
+           regex: '\\b0(?:x|X)[0-9a-fA-F]*|(?:\\b[0-9]+\\.?[0-9]*|\\.[0-9]+)(?:(?:e|E)(?:\\+|-)?[0-9]*)?(?:im)?|\\bInf(?:32)?\\b|\\bNaN(?:32)?\\b|\\btrue\\b|\\bfalse\\b' } ],
+      '#operator': 
+       [ { token: 'keyword.operator.update.julia',
+           regex: '=|:=|\\+=|-=|\\*=|/=|//=|\\.//=|\\.\\*=|\\\\=|\\.\\\\=|^=|\\.^=|%=|\\|=|&=|\\$=|<<=|>>=' },
+         { token: 'keyword.operator.ternary.julia', regex: '\\?|:' },
+         { token: 'keyword.operator.boolean.julia',
+           regex: '\\|\\||&&|!' },
+         { token: 'keyword.operator.arrow.julia', regex: '->|<-|-->' },
+         { token: 'keyword.operator.relation.julia',
+           regex: '>|<|>=|<=|==|!=|\\.>|\\.<|\\.>=|\\.>=|\\.==|\\.!=|\\.=|\\.!|<:|:>' },
+         { token: 'keyword.operator.range.julia', regex: ':' },
+         { token: 'keyword.operator.shift.julia', regex: '<<|>>' },
+         { token: 'keyword.operator.bitwise.julia', regex: '\\||\\&|~' },
+         { token: 'keyword.operator.arithmetic.julia',
+           regex: '\\+|-|\\*|\\.\\*|/|\\./|//|\\.//|%|\\.%|\\\\|\\.\\\\|\\^|\\.\\^' },
+         { token: 'keyword.operator.isa.julia', regex: '::' },
+         { token: 'keyword.operator.dots.julia',
+           regex: '\\.(?=[a-zA-Z])|\\.\\.+' },
+         { token: 'keyword.operator.interpolation.julia',
+           regex: '\\$#?(?=.)' },
+         { token: [ 'variable', 'keyword.operator.transposed-variable.julia' ],
+           regex: '([\\w\\xff-\\u218e\\u2455-\\uffff]+)((?:\'|\\.\')*\\.?\')' },
+         { token: 'text',
+           regex: '\\[|\\('},
+         { token: [ 'text', 'keyword.operator.transposed-matrix.julia' ],
+            regex: "([\\]\\)])((?:'|\\.')*\\.?')"} ],
+      '#string': 
+       [ { token: 'punctuation.definition.string.begin.julia',
+           regex: '\'',
+           push: 
+            [ { token: 'punctuation.definition.string.end.julia',
+                regex: '\'',
+                next: 'pop' },
+              { include: '#string_escaped_char' },
+              { defaultToken: 'string.quoted.single.julia' } ] },
+         { token: 'punctuation.definition.string.begin.julia',
+           regex: '"',
+           push: 
+            [ { token: 'punctuation.definition.string.end.julia',
+                regex: '"',
+                next: 'pop' },
+              { include: '#string_escaped_char' },
+              { defaultToken: 'string.quoted.double.julia' } ] },
+         { token: 'punctuation.definition.string.begin.julia',
+           regex: '\\b[\\w\\xff-\\u218e\\u2455-\\uffff]+"',
+           push: 
+            [ { token: 'punctuation.definition.string.end.julia',
+                regex: '"[\\w\\xff-\\u218e\\u2455-\\uffff]*',
+                next: 'pop' },
+              { include: '#string_custom_escaped_char' },
+              { defaultToken: 'string.quoted.custom-double.julia' } ] },
+         { token: 'punctuation.definition.string.begin.julia',
+           regex: '`',
+           push: 
+            [ { token: 'punctuation.definition.string.end.julia',
+                regex: '`',
+                next: 'pop' },
+              { include: '#string_escaped_char' },
+              { defaultToken: 'string.quoted.backtick.julia' } ] } ],
+      '#string_custom_escaped_char': [ { token: 'constant.character.escape.julia', regex: '\\\\"' } ],
+      '#string_escaped_char': 
+       [ { token: 'constant.character.escape.julia',
+           regex: '\\\\(?:\\\\|[0-3]\\d{,2}|[4-7]\\d?|x[a-fA-F0-9]{,2}|u[a-fA-F0-9]{,4}|U[a-fA-F0-9]{,8}|.)' } ],
+      '#type_decl': 
+       [ { token: 
+            [ 'keyword.control.type.julia',
+              'meta.type.julia',
+              'entity.name.type.julia',
+              'entity.other.inherited-class.julia',
+              'punctuation.separator.inheritance.julia',
+              'entity.other.inherited-class.julia' ],
+           regex: '(type|immutable)(\\s+)([a-zA-Z0-9_]+)(?:(\\s*)(<:)(\\s*[.a-zA-Z0-9_:]+))?' },
+         { token: [ 'other.typed-variable.julia', 'support.type.julia' ],
+           regex: '([a-zA-Z0-9_]+)(::[a-zA-Z0-9_{}]+)' } ] };
+    
+    this.normalizeRules();
+};
+
+JuliaHighlightRules.metaData = { fileTypes: [ 'jl' ],
+      firstLineMatch: '^#!.*\\bjulia\\s*$',
+      foldingStartMarker: '^\\s*(?:if|while|for|begin|function|macro|module|baremodule|type|immutable|let)\\b(?!.*\\bend\\b).*$',
+      foldingStopMarker: '^\\s*(?:end)\\b.*$',
+      name: 'Julia',
+      scopeName: 'source.julia' };
+
+
+oop.inherits(JuliaHighlightRules, TextHighlightRules);
+
+exports.JuliaHighlightRules = JuliaHighlightRules;
+});
+
+ace.define("ace/mode/folding/cstyle",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Range = require("../../range").Range;
+var BaseFoldMode = require("./fold_mode").FoldMode;
+
+var FoldMode = exports.FoldMode = function(commentRegex) {
+    if (commentRegex) {
+        this.foldingStartMarker = new RegExp(
+            this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start)
+        );
+        this.foldingStopMarker = new RegExp(
+            this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end)
+        );
+    }
+};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+    
+    this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/;
+    this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/;
+    this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/;
+    this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/;
+    this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/;
+    this._getFoldWidgetBase = this.getFoldWidget;
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+    
+        if (this.singleLineBlockCommentRe.test(line)) {
+            if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line))
+                return "";
+        }
+    
+        var fw = this._getFoldWidgetBase(session, foldStyle, row);
+    
+        if (!fw && this.startRegionRe.test(line))
+            return "start"; // lineCommentRegionStart
+    
+        return fw;
+    };
+
+    this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) {
+        var line = session.getLine(row);
+        
+        if (this.startRegionRe.test(line))
+            return this.getCommentRegionBlock(session, line, row);
+        
+        var match = line.match(this.foldingStartMarker);
+        if (match) {
+            var i = match.index;
+
+            if (match[1])
+                return this.openingBracketBlock(session, match[1], row, i);
+                
+            var range = session.getCommentFoldRange(row, i + match[0].length, 1);
+            
+            if (range && !range.isMultiLine()) {
+                if (forceMultiline) {
+                    range = this.getSectionRange(session, row);
+                } else if (foldStyle != "all")
+                    range = null;
+            }
+            
+            return range;
+        }
+
+        if (foldStyle === "markbegin")
+            return;
+
+        var match = line.match(this.foldingStopMarker);
+        if (match) {
+            var i = match.index + match[0].length;
+
+            if (match[1])
+                return this.closingBracketBlock(session, match[1], row, i);
+
+            return session.getCommentFoldRange(row, i, -1);
+        }
+    };
+    
+    this.getSectionRange = function(session, row) {
+        var line = session.getLine(row);
+        var startIndent = line.search(/\S/);
+        var startRow = row;
+        var startColumn = line.length;
+        row = row + 1;
+        var endRow = row;
+        var maxRow = session.getLength();
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var indent = line.search(/\S/);
+            if (indent === -1)
+                continue;
+            if  (startIndent > indent)
+                break;
+            var subRange = this.getFoldWidgetRange(session, "all", row);
+            
+            if (subRange) {
+                if (subRange.start.row <= startRow) {
+                    break;
+                } else if (subRange.isMultiLine()) {
+                    row = subRange.end.row;
+                } else if (startIndent == indent) {
+                    break;
+                }
+            }
+            endRow = row;
+        }
+        
+        return new Range(startRow, startColumn, endRow, session.getLine(endRow).length);
+    };
+    this.getCommentRegionBlock = function(session, line, row) {
+        var startColumn = line.search(/\s*$/);
+        var maxRow = session.getLength();
+        var startRow = row;
+        
+        var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/;
+        var depth = 1;
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var m = re.exec(line);
+            if (!m) continue;
+            if (m[1]) depth--;
+            else depth++;
+
+            if (!depth) break;
+        }
+
+        var endRow = row;
+        if (endRow > startRow) {
+            return new Range(startRow, startColumn, endRow, line.length);
+        }
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/julia",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var JuliaHighlightRules = require("./julia_highlight_rules").JuliaHighlightRules;
+var FoldMode = require("./folding/cstyle").FoldMode;
+
+var Mode = function() {
+    this.HighlightRules = JuliaHighlightRules;
+    this.foldingRules = new FoldMode();
+    this.$behaviour = this.$defaultBehaviour;
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+    this.lineCommentStart = "#";
+    this.blockComment = "";
+    this.$id = "ace/mode/julia";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/julia"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 796 - 0
services/web/public/js/ace-1.4.3/mode-kotlin.js

@@ -0,0 +1,796 @@
+ace.define("ace/mode/kotlin_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var KotlinHighlightRules = function() {
+
+    this.$rules = {
+        start: [{
+            include: "#comments"
+        }, {
+            token: [
+                "text",
+                "keyword.other.kotlin",
+                "text",
+                "entity.name.package.kotlin",
+                "text"
+            ],
+            regex: /^(\s*)(package)\b(?:(\s*)([^ ;$]+)(\s*))?/
+        }, {
+            include: "#imports"
+        }, {
+            include: "#statements"
+        }],
+        "#classes": [{
+            token: "text",
+            regex: /(?=\s*(?:companion|class|object|interface))/,
+            push: [{
+                token: "text",
+                regex: /}|(?=$)/,
+                next: "pop"
+            }, {
+                token: ["keyword.other.kotlin", "text"],
+                regex: /\b((?:companion\s*)?)(class|object|interface)\b/,
+                push: [{
+                    token: "text",
+                    regex: /(?=<|{|\(|:)/,
+                    next: "pop"
+                }, {
+                    token: "keyword.other.kotlin",
+                    regex: /\bobject\b/
+                }, {
+                    token: "entity.name.type.class.kotlin",
+                    regex: /\w+/
+                }]
+            }, {
+                token: "text",
+                regex: /</,
+                push: [{
+                    token: "text",
+                    regex: />/,
+                    next: "pop"
+                }, {
+                    include: "#generics"
+                }]
+            }, {
+                token: "text",
+                regex: /\(/,
+                push: [{
+                    token: "text",
+                    regex: /\)/,
+                    next: "pop"
+                }, {
+                    include: "#parameters"
+                }]
+            }, {
+                token: "keyword.operator.declaration.kotlin",
+                regex: /:/,
+                push: [{
+                    token: "text",
+                    regex: /(?={|$)/,
+                    next: "pop"
+                }, {
+                    token: "entity.other.inherited-class.kotlin",
+                    regex: /\w+/
+                }, {
+                    token: "text",
+                    regex: /\(/,
+                    push: [{
+                        token: "text",
+                        regex: /\)/,
+                        next: "pop"
+                    }, {
+                        include: "#expressions"
+                    }]
+                }]
+            }, {
+                token: "text",
+                regex: /\{/,
+                push: [{
+                    token: "text",
+                    regex: /\}/,
+                    next: "pop"
+                }, {
+                    include: "#statements"
+                }]
+            }]
+        }],
+        "#comments": [{
+            token: "punctuation.definition.comment.kotlin",
+            regex: /\/\*/,
+            push: [{
+                token: "punctuation.definition.comment.kotlin",
+                regex: /\*\//,
+                next: "pop"
+            }, {
+                defaultToken: "comment.block.kotlin"
+            }]
+        }, {
+            token: [
+                "text",
+                "punctuation.definition.comment.kotlin",
+                "comment.line.double-slash.kotlin"
+            ],
+            regex: /(\s*)(\/\/)(.*$)/
+        }],
+        "#constants": [{
+            token: "constant.language.kotlin",
+            regex: /\b(?:true|false|null|this|super)\b/
+        }, {
+            token: "constant.numeric.kotlin",
+            regex: /\b(?:0(?:x|X)[0-9a-fA-F]*|(?:[0-9]+\.?[0-9]*|\.[0-9]+)(?:(?:e|E)(?:\+|-)?[0-9]+)?)(?:[LlFfUuDd]|UL|ul)?\b/
+        }, {
+            token: "constant.other.kotlin",
+            regex: /\b[A-Z][A-Z0-9_]+\b/
+        }],
+        "#expressions": [{
+            token: "text",
+            regex: /\(/,
+            push: [{
+                token: "text",
+                regex: /\)/,
+                next: "pop"
+            }, {
+                include: "#expressions"
+            }]
+        }, {
+            include: "#types"
+        }, {
+            include: "#strings"
+        }, {
+            include: "#constants"
+        }, {
+            include: "#comments"
+        }, {
+            include: "#keywords"
+        }],
+        "#functions": [{
+            token: "text",
+            regex: /(?=\s*fun)/,
+            push: [{
+                token: "text",
+                regex: /}|(?=$)/,
+                next: "pop"
+            }, {
+                token: "keyword.other.kotlin",
+                regex: /\bfun\b/,
+                push: [{
+                    token: "text",
+                    regex: /(?=\()/,
+                    next: "pop"
+                }, {
+                    token: "text",
+                    regex: /</,
+                    push: [{
+                        token: "text",
+                        regex: />/,
+                        next: "pop"
+                    }, {
+                        include: "#generics"
+                    }]
+                }, {
+                    token: ["text", "entity.name.function.kotlin"],
+                    regex: /((?:[\.<\?>\w]+\.)?)(\w+)/
+                }]
+            }, {
+                token: "text",
+                regex: /\(/,
+                push: [{
+                    token: "text",
+                    regex: /\)/,
+                    next: "pop"
+                }, {
+                    include: "#parameters"
+                }]
+            }, {
+                token: "keyword.operator.declaration.kotlin",
+                regex: /:/,
+                push: [{
+                    token: "text",
+                    regex: /(?={|=|$)/,
+                    next: "pop"
+                }, {
+                    include: "#types"
+                }]
+            }, {
+                token: "text",
+                regex: /\{/,
+                push: [{
+                    token: "text",
+                    regex: /(?=\})/,
+                    next: "pop"
+                }, {
+                    include: "#statements"
+                }]
+            }, {
+                token: "keyword.operator.assignment.kotlin",
+                regex: /=/,
+                push: [{
+                    token: "text",
+                    regex: /(?=$)/,
+                    next: "pop"
+                }, {
+                    include: "#expressions"
+                }]
+            }]
+        }],
+        "#generics": [{
+            token: "keyword.operator.declaration.kotlin",
+            regex: /:/,
+            push: [{
+                token: "text",
+                regex: /(?=,|>)/,
+                next: "pop"
+            }, {
+                include: "#types"
+            }]
+        }, {
+            include: "#keywords"
+        }, {
+            token: "storage.type.generic.kotlin",
+            regex: /\w+/
+        }],
+        "#getters-and-setters": [{
+            token: ["entity.name.function.kotlin", "text"],
+            regex: /\b(get)\b(\s*\(\s*\))/,
+            push: [{
+                token: "text",
+                regex: /\}|(?=\bset\b)|$/,
+                next: "pop"
+            }, {
+                token: "keyword.operator.assignment.kotlin",
+                regex: /=/,
+                push: [{
+                    token: "text",
+                    regex: /(?=$|\bset\b)/,
+                    next: "pop"
+                }, {
+                    include: "#expressions"
+                }]
+            }, {
+                token: "text",
+                regex: /\{/,
+                push: [{
+                    token: "text",
+                    regex: /\}/,
+                    next: "pop"
+                }, {
+                    include: "#expressions"
+                }]
+            }]
+        }, {
+            token: ["entity.name.function.kotlin", "text"],
+            regex: /\b(set)\b(\s*)(?=\()/,
+            push: [{
+                token: "text",
+                regex: /\}|(?=\bget\b)|$/,
+                next: "pop"
+            }, {
+                token: "text",
+                regex: /\(/,
+                push: [{
+                    token: "text",
+                    regex: /\)/,
+                    next: "pop"
+                }, {
+                    include: "#parameters"
+                }]
+            }, {
+                token: "keyword.operator.assignment.kotlin",
+                regex: /=/,
+                push: [{
+                    token: "text",
+                    regex: /(?=$|\bset\b)/,
+                    next: "pop"
+                }, {
+                    include: "#expressions"
+                }]
+            }, {
+                token: "text",
+                regex: /\{/,
+                push: [{
+                    token: "text",
+                    regex: /\}/,
+                    next: "pop"
+                }, {
+                    include: "#expressions"
+                }]
+            }]
+        }],
+        "#imports": [{
+            token: [
+                "text",
+                "keyword.other.kotlin",
+                "text",
+                "keyword.other.kotlin"
+            ],
+            regex: /^(\s*)(import)(\s+[^ $]+\s+)((?:as)?)/
+        }],
+        "#keywords": [{
+            token: "storage.modifier.kotlin",
+            regex: /\b(?:var|val|public|private|protected|abstract|final|enum|open|attribute|annotation|override|inline|var|val|vararg|lazy|in|out|internal|data|tailrec|operator|infix|const|yield|typealias|typeof)\b/
+        }, {
+            token: "keyword.control.catch-exception.kotlin",
+            regex: /\b(?:try|catch|finally|throw)\b/
+        }, {
+            token: "keyword.control.kotlin",
+            regex: /\b(?:if|else|while|for|do|return|when|where|break|continue)\b/
+        }, {
+            token: "keyword.operator.kotlin",
+            regex: /\b(?:in|is|as|assert)\b/
+        }, {
+            token: "keyword.operator.comparison.kotlin",
+            regex: /==|!=|===|!==|<=|>=|<|>/
+        }, {
+            token: "keyword.operator.assignment.kotlin",
+            regex: /=/
+        }, {
+            token: "keyword.operator.declaration.kotlin",
+            regex: /:/
+        }, {
+            token: "keyword.operator.dot.kotlin",
+            regex: /\./
+        }, {
+            token: "keyword.operator.increment-decrement.kotlin",
+            regex: /\-\-|\+\+/
+        }, {
+            token: "keyword.operator.arithmetic.kotlin",
+            regex: /\-|\+|\*|\/|%/
+        }, {
+            token: "keyword.operator.arithmetic.assign.kotlin",
+            regex: /\+=|\-=|\*=|\/=/
+        }, {
+            token: "keyword.operator.logical.kotlin",
+            regex: /!|&&|\|\|/
+        }, {
+            token: "keyword.operator.range.kotlin",
+            regex: /\.\./
+        }, {
+            token: "punctuation.terminator.kotlin",
+            regex: /;/
+        }],
+        "#namespaces": [{
+            token: "keyword.other.kotlin",
+            regex: /\bnamespace\b/
+        }, {
+            token: "text",
+            regex: /\{/,
+            push: [{
+                token: "text",
+                regex: /\}/,
+                next: "pop"
+            }, {
+                include: "#statements"
+            }]
+        }],
+        "#parameters": [{
+            token: "keyword.operator.declaration.kotlin",
+            regex: /:/,
+            push: [{
+                token: "text",
+                regex: /(?=,|\)|=)/,
+                next: "pop"
+            }, {
+                include: "#types"
+            }]
+        }, {
+            token: "keyword.operator.declaration.kotlin",
+            regex: /=/,
+            push: [{
+                token: "text",
+                regex: /(?=,|\))/,
+                next: "pop"
+            }, {
+                include: "#expressions"
+            }]
+        }, {
+            include: "#keywords"
+        }, {
+            token: "variable.parameter.function.kotlin",
+            regex: /\w+/
+        }],
+        "#statements": [{
+            include: "#namespaces"
+        }, {
+            include: "#typedefs"
+        }, {
+            include: "#classes"
+        }, {
+            include: "#functions"
+        }, {
+            include: "#variables"
+        }, {
+            include: "#getters-and-setters"
+        }, {
+            include: "#expressions"
+        }],
+        "#strings": [{
+            token: "punctuation.definition.string.begin.kotlin",
+            regex: /"""/,
+            push: [{
+                token: "punctuation.definition.string.end.kotlin",
+                regex: /"""/,
+                next: "pop"
+            }, {
+                token: "variable.parameter.template.kotlin",
+                regex: /\$\w+|\$\{[^\}]+\}/
+            }, {
+                token: "constant.character.escape.kotlin",
+                regex: /\\./
+            }, {
+                defaultToken: "string.quoted.third.kotlin"
+            }]
+        }, {
+            token: "punctuation.definition.string.begin.kotlin",
+            regex: /"/,
+            push: [{
+                token: "punctuation.definition.string.end.kotlin",
+                regex: /"/,
+                next: "pop"
+            }, {
+                token: "variable.parameter.template.kotlin",
+                regex: /\$\w+|\$\{[^\}]+\}/
+            }, {
+                token: "constant.character.escape.kotlin",
+                regex: /\\./
+            }, {
+                defaultToken: "string.quoted.double.kotlin"
+            }]
+        }, {
+            token: "punctuation.definition.string.begin.kotlin",
+            regex: /'/,
+            push: [{
+                token: "punctuation.definition.string.end.kotlin",
+                regex: /'/,
+                next: "pop"
+            }, {
+                token: "constant.character.escape.kotlin",
+                regex: /\\./
+            }, {
+                defaultToken: "string.quoted.single.kotlin"
+            }]
+        }, {
+            token: "punctuation.definition.string.begin.kotlin",
+            regex: /`/,
+            push: [{
+                token: "punctuation.definition.string.end.kotlin",
+                regex: /`/,
+                next: "pop"
+            }, {
+                defaultToken: "string.quoted.single.kotlin"
+            }]
+        }],
+        "#typedefs": [{
+            token: "text",
+            regex: /(?=\s*type)/,
+            push: [{
+                token: "text",
+                regex: /(?=$)/,
+                next: "pop"
+            }, {
+                token: "keyword.other.kotlin",
+                regex: /\btype\b/
+            }, {
+                token: "text",
+                regex: /</,
+                push: [{
+                    token: "text",
+                    regex: />/,
+                    next: "pop"
+                }, {
+                    include: "#generics"
+                }]
+            }, {
+                include: "#expressions"
+            }]
+        }],
+        "#types": [{
+            token: "storage.type.buildin.kotlin",
+            regex: /\b(?:Any|Unit|String|Int|Boolean|Char|Long|Double|Float|Short|Byte|dynamic)\b/
+        }, {
+            token: "storage.type.buildin.array.kotlin",
+            regex: /\b(?:IntArray|BooleanArray|CharArray|LongArray|DoubleArray|FloatArray|ShortArray|ByteArray)\b/
+        }, {
+            token: [
+                "storage.type.buildin.collection.kotlin",
+                "text"
+            ],
+            regex: /\b(Array|List|Map)(<\b)/,
+            push: [{
+                token: "text",
+                regex: />/,
+                next: "pop"
+            }, {
+                include: "#types"
+            }, {
+                include: "#keywords"
+            }]
+        }, {
+            token: "text",
+            regex: /\w+</,
+            push: [{
+                token: "text",
+                regex: />/,
+                next: "pop"
+            }, {
+                include: "#types"
+            }, {
+                include: "#keywords"
+            }]
+        }, {
+            token: ["keyword.operator.tuple.kotlin", "text"],
+            regex: /(#)(\()/,
+            push: [{
+                token: "text",
+                regex: /\)/,
+                next: "pop"
+            }, {
+                include: "#expressions"
+            }]
+        }, {
+            token: "text",
+            regex: /\{/,
+            push: [{
+                token: "text",
+                regex: /\}/,
+                next: "pop"
+            }, {
+                include: "#statements"
+            }]
+        }, {
+            token: "text",
+            regex: /\(/,
+            push: [{
+                token: "text",
+                regex: /\)/,
+                next: "pop"
+            }, {
+                include: "#types"
+            }]
+        }, {
+            token: "keyword.operator.declaration.kotlin",
+            regex: /->/
+        }],
+        "#variables": [{
+            token: "text",
+            regex: /(?=\s*(?:var|val))/,
+            push: [{
+                token: "text",
+                regex: /(?=:|=|$)/,
+                next: "pop"
+            }, {
+                token: "keyword.other.kotlin",
+                regex: /\b(?:var|val)\b/,
+                push: [{
+                    token: "text",
+                    regex: /(?=:|=|$)/,
+                    next: "pop"
+                }, {
+                    token: "text",
+                    regex: /</,
+                    push: [{
+                        token: "text",
+                        regex: />/,
+                        next: "pop"
+                    }, {
+                        include: "#generics"
+                    }]
+                }, {
+                    token: ["text", "entity.name.variable.kotlin"],
+                    regex: /((?:[\.<\?>\w]+\.)?)(\w+)/
+                }]
+            }, {
+                token: "keyword.operator.declaration.kotlin",
+                regex: /:/,
+                push: [{
+                    token: "text",
+                    regex: /(?==|$)/,
+                    next: "pop"
+                }, {
+                    include: "#types"
+                }, {
+                    include: "#getters-and-setters"
+                }]
+            }, {
+                token: "keyword.operator.assignment.kotlin",
+                regex: /=/,
+                push: [{
+                    token: "text",
+                    regex: /(?=$)/,
+                    next: "pop"
+                }, {
+                    include: "#expressions"
+                }, {
+                    include: "#getters-and-setters"
+                }]
+            }]
+        }]
+    };
+    
+    this.normalizeRules();
+};
+
+KotlinHighlightRules.metaData = {
+    fileTypes: ["kt", "kts"],
+    name: "Kotlin",
+    scopeName: "source.Kotlin"
+};
+
+
+oop.inherits(KotlinHighlightRules, TextHighlightRules);
+
+exports.KotlinHighlightRules = KotlinHighlightRules;
+});
+
+ace.define("ace/mode/folding/cstyle",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Range = require("../../range").Range;
+var BaseFoldMode = require("./fold_mode").FoldMode;
+
+var FoldMode = exports.FoldMode = function(commentRegex) {
+    if (commentRegex) {
+        this.foldingStartMarker = new RegExp(
+            this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start)
+        );
+        this.foldingStopMarker = new RegExp(
+            this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end)
+        );
+    }
+};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+    
+    this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/;
+    this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/;
+    this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/;
+    this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/;
+    this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/;
+    this._getFoldWidgetBase = this.getFoldWidget;
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+    
+        if (this.singleLineBlockCommentRe.test(line)) {
+            if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line))
+                return "";
+        }
+    
+        var fw = this._getFoldWidgetBase(session, foldStyle, row);
+    
+        if (!fw && this.startRegionRe.test(line))
+            return "start"; // lineCommentRegionStart
+    
+        return fw;
+    };
+
+    this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) {
+        var line = session.getLine(row);
+        
+        if (this.startRegionRe.test(line))
+            return this.getCommentRegionBlock(session, line, row);
+        
+        var match = line.match(this.foldingStartMarker);
+        if (match) {
+            var i = match.index;
+
+            if (match[1])
+                return this.openingBracketBlock(session, match[1], row, i);
+                
+            var range = session.getCommentFoldRange(row, i + match[0].length, 1);
+            
+            if (range && !range.isMultiLine()) {
+                if (forceMultiline) {
+                    range = this.getSectionRange(session, row);
+                } else if (foldStyle != "all")
+                    range = null;
+            }
+            
+            return range;
+        }
+
+        if (foldStyle === "markbegin")
+            return;
+
+        var match = line.match(this.foldingStopMarker);
+        if (match) {
+            var i = match.index + match[0].length;
+
+            if (match[1])
+                return this.closingBracketBlock(session, match[1], row, i);
+
+            return session.getCommentFoldRange(row, i, -1);
+        }
+    };
+    
+    this.getSectionRange = function(session, row) {
+        var line = session.getLine(row);
+        var startIndent = line.search(/\S/);
+        var startRow = row;
+        var startColumn = line.length;
+        row = row + 1;
+        var endRow = row;
+        var maxRow = session.getLength();
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var indent = line.search(/\S/);
+            if (indent === -1)
+                continue;
+            if  (startIndent > indent)
+                break;
+            var subRange = this.getFoldWidgetRange(session, "all", row);
+            
+            if (subRange) {
+                if (subRange.start.row <= startRow) {
+                    break;
+                } else if (subRange.isMultiLine()) {
+                    row = subRange.end.row;
+                } else if (startIndent == indent) {
+                    break;
+                }
+            }
+            endRow = row;
+        }
+        
+        return new Range(startRow, startColumn, endRow, session.getLine(endRow).length);
+    };
+    this.getCommentRegionBlock = function(session, line, row) {
+        var startColumn = line.search(/\s*$/);
+        var maxRow = session.getLength();
+        var startRow = row;
+        
+        var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/;
+        var depth = 1;
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var m = re.exec(line);
+            if (!m) continue;
+            if (m[1]) depth--;
+            else depth++;
+
+            if (!depth) break;
+        }
+
+        var endRow = row;
+        if (endRow > startRow) {
+            return new Range(startRow, startColumn, endRow, line.length);
+        }
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/kotlin",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var KotlinHighlightRules = require("./kotlin_highlight_rules").KotlinHighlightRules;
+var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour;
+var FoldMode = require("./folding/cstyle").FoldMode;
+
+var Mode = function() {
+    this.HighlightRules = KotlinHighlightRules;
+    this.foldingRules = new FoldMode();
+    this.$behaviour = new CstyleBehaviour();
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+    this.$id = "ace/mode/kotlin";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+                (function() {
+                    ace.require(["ace/mode/kotlin"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

+ 712 - 0
services/web/public/js/ace-1.4.3/mode-latex.js

@@ -0,0 +1,712 @@
+ace.define("ace/mode/latex_highlight_rules",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var LatexHighlightRules = function() {  
+
+    this.$rules = {
+        "start" : [{
+            token : "comment",
+            regex : "%.*$"
+        }, {
+            token : ["keyword", "lparen", "variable.parameter", "rparen", "lparen", "storage.type", "rparen"],
+            regex : "(\\\\(?:documentclass|usepackage|input))(?:(\\[)([^\\]]*)(\\]))?({)([^}]*)(})"
+        }, {
+            token : ["keyword","lparen", "variable.parameter", "rparen"],
+            regex : "(\\\\(?:label|v?ref|cite(?:[^{]*)))(?:({)([^}]*)(}))?"
+        }, {
+            token : ["storage.type", "lparen", "variable.parameter", "rparen"],
+            regex : "(\\\\begin)({)(verbatim)(})",
+            next : "verbatim"
+        },  {
+            token : ["storage.type", "lparen", "variable.parameter", "rparen"],
+            regex : "(\\\\begin)({)(lstlisting)(})",
+            next : "lstlisting"
+        },  {
+            token : ["storage.type", "lparen", "variable.parameter", "rparen"],
+            regex : "(\\\\(?:begin|end))({)([\\w*]*)(})"
+        }, {
+            token : "storage.type",
+            regex : /\\verb\b\*?/,
+            next : [{
+                token : ["keyword.operator", "string", "keyword.operator"],
+                regex : "(.)(.*?)(\\1|$)|",
+                next : "start"
+            }]
+        }, {
+            token : "storage.type",
+            regex : "\\\\[a-zA-Z]+"
+        }, {
+            token : "lparen",
+            regex : "[[({]"
+        }, {
+            token : "rparen",
+            regex : "[\\])}]"
+        }, {
+            token : "constant.character.escape",
+            regex : "\\\\[^a-zA-Z]?"
+        }, {
+            token : "string",
+            regex : "\\${1,2}",
+            next  : "equation"
+        }],
+        "equation" : [{
+            token : "comment",
+            regex : "%.*$"
+        }, {
+            token : "string",
+            regex : "\\${1,2}",
+            next  : "start"
+        }, {
+            token : "constant.character.escape",
+            regex : "\\\\(?:[^a-zA-Z]|[a-zA-Z]+)"
+        }, {
+            token : "error", 
+            regex : "^\\s*$", 
+            next : "start" 
+        }, {
+            defaultToken : "string"
+        }],
+        "verbatim": [{
+            token : ["storage.type", "lparen", "variable.parameter", "rparen"],
+            regex : "(\\\\end)({)(verbatim)(})",
+            next : "start"
+        }, {
+            defaultToken : "text"
+        }],
+        "lstlisting": [{
+            token : ["storage.type", "lparen", "variable.parameter", "rparen"],
+            regex : "(\\\\end)({)(lstlisting)(})",
+            next : "start"
+        }, {
+            defaultToken : "text"
+        }]
+    };
+    
+    this.normalizeRules();
+};
+oop.inherits(LatexHighlightRules, TextHighlightRules);
+
+exports.LatexHighlightRules = LatexHighlightRules;
+
+});
+
+ace.define("ace/mode/folding/latex",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var BaseFoldMode = require("./fold_mode").FoldMode;
+var Range = require("../../range").Range;
+var TokenIterator = require("../../token_iterator").TokenIterator;
+var keywordLevels = {
+    "\\subparagraph": 1,
+    "\\paragraph": 2,
+    "\\subsubsubsection": 3,
+    "\\subsubsection": 4,
+    "\\subsection": 5,
+    "\\section": 6,
+    "\\chapter": 7,
+    "\\part": 8,
+    "\\begin": 9,
+    "\\end": 10
+};
+
+var FoldMode = exports.FoldMode = function() {};
+
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+
+    this.foldingStartMarker = /^\s*\\(begin)|\s*\\(part|chapter|(?:sub)*(?:section|paragraph))\b|{\s*$/;
+    this.foldingStopMarker = /^\s*\\(end)\b|^\s*}/;
+
+    this.getFoldWidgetRange = function(session, foldStyle, row) {
+        var line = session.doc.getLine(row);
+        var match = this.foldingStartMarker.exec(line);
+        if (match) {
+            if (match[1])
+                return this.latexBlock(session, row, match[0].length - 1);
+            if (match[2])
+                return this.latexSection(session, row, match[0].length - 1);
+
+            return this.openingBracketBlock(session, "{", row, match.index);
+        }
+
+        var match = this.foldingStopMarker.exec(line);
+        if (match) {
+            if (match[1])
+                return this.latexBlock(session, row, match[0].length - 1);
+
+            return this.closingBracketBlock(session, "}", row, match.index + match[0].length);
+        }
+    };
+
+    this.latexBlock = function(session, row, column, returnRange) {
+        var keywords = {
+            "\\begin": 1,
+            "\\end": -1
+        };
+
+        var stream = new TokenIterator(session, row, column);
+        var token = stream.getCurrentToken();
+        if (!token || !(token.type == "storage.type" || token.type == "constant.character.escape"))
+            return;
+
+        var val = token.value;
+        var dir = keywords[val];
+
+        var getType = function() {
+            var token = stream.stepForward();
+            var type = token.type == "lparen" ?stream.stepForward().value : "";
+            if (dir === -1) {
+                stream.stepBackward();
+                if (type)
+                    stream.stepBackward();
+            }
+            return type;
+        };
+        var stack = [getType()];
+        var startColumn = dir === -1 ? stream.getCurrentTokenColumn() : session.getLine(row).length;
+        var startRow = row;
+
+        stream.step = dir === -1 ? stream.stepBackward : stream.stepForward;
+        while(token = stream.step()) {
+            if (!token || !(token.type == "storage.type" || token.type == "constant.character.escape"))
+                continue;
+            var level = keywords[token.value];
+            if (!level)
+                continue;
+            var type = getType();
+            if (level === dir)
+                stack.unshift(type);
+            else if (stack.shift() !== type || !stack.length)
+                break;
+        }
+
+        if (stack.length)
+            return;
+        
+        if (dir == 1) {
+            stream.stepBackward();
+            stream.stepBackward();
+        }
+        
+        if (returnRange)
+            return stream.getCurrentTokenRange();
+
+        var row = stream.getCurrentTokenRow();
+        if (dir === -1)
+            return new Range(row, session.getLine(row).length, startRow, startColumn);
+        else
+            return new Range(startRow, startColumn, row, stream.getCurrentTokenColumn());
+    };
+
+    this.latexSection = function(session, row, column) {
+        var stream = new TokenIterator(session, row, column);
+        var token = stream.getCurrentToken();
+        if (!token || token.type != "storage.type")
+            return;
+
+        var startLevel = keywordLevels[token.value] || 0;
+        var stackDepth = 0;
+        var endRow = row;
+
+        while(token = stream.stepForward()) {
+            if (token.type !== "storage.type")
+                continue;
+            var level = keywordLevels[token.value] || 0;
+
+            if (level >= 9) {
+                if (!stackDepth)
+                    endRow = stream.getCurrentTokenRow() - 1;
+                stackDepth += level == 9 ? 1 : - 1;
+                if (stackDepth < 0)
+                    break;
+            } else if (level >= startLevel)
+                break;
+        }
+
+        if (!stackDepth)
+            endRow = stream.getCurrentTokenRow() - 1;
+
+        while (endRow > row && !/\S/.test(session.getLine(endRow)))
+            endRow--;
+
+        return new Range(
+            row, session.getLine(row).length,
+            endRow, session.getLine(endRow).length
+        );
+    };
+
+}).call(FoldMode.prototype);
+
+});
+
+ace.define("ace/mode/behaviour/latex",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Behaviour = require("../behaviour").Behaviour;
+var TokenIterator = require("../../token_iterator").TokenIterator;
+var lang = require("../../lib/lang");
+
+var SAFE_INSERT_IN_TOKENS =
+    ["text", "paren.rparen", "punctuation.operator"];
+var SAFE_INSERT_BEFORE_TOKENS =
+    ["text", "paren.rparen", "punctuation.operator", "comment"];
+
+var context;
+var contextCache = {};
+var initContext = function(editor) {
+    var id = -1;
+    if (editor.multiSelect) {
+        id = editor.selection.index;
+        if (contextCache.rangeCount != editor.multiSelect.rangeCount)
+            contextCache = {rangeCount: editor.multiSelect.rangeCount};
+    }
+    if (contextCache[id])
+        return context = contextCache[id];
+    context = contextCache[id] = {
+        autoInsertedBrackets: 0,
+        autoInsertedRow: -1,
+        autoInsertedLineEnd: "",
+        maybeInsertedBrackets: 0,
+        maybeInsertedRow: -1,
+        maybeInsertedLineStart: "",
+        maybeInsertedLineEnd: ""
+    };
+};
+
+var getWrapped = function(selection, selected, opening, closing) {
+    var rowDiff = selection.end.row - selection.start.row;
+    return {
+        text: opening + selected + closing,
+        selection: [
+                0,
+                selection.start.column + 1,
+                rowDiff,
+                selection.end.column + (rowDiff ? 0 : 1)
+            ]
+    };
+};
+
+var LatexBehaviour = function() {
+    this.add("braces", "insertion", function(state, action, editor, session, text) {
+				if (editor.completer && editor.completer.popup && editor.completer.popup.isOpen) {
+					return;
+				}
+        var cursor = editor.getCursorPosition();
+        var line = session.doc.getLine(cursor.row);
+        var lastChar = line[cursor.column-1];
+        if (lastChar === '\\') {
+          return;
+        }
+        if (text == '{') {
+            initContext(editor);
+            var selection = editor.getSelectionRange();
+            var selected = session.doc.getTextRange(selection);
+            if (selected !== "" && editor.getWrapBehavioursEnabled()) {
+                return getWrapped(selection, selected, '{', '}');
+            } else if (LatexBehaviour.isSaneInsertion(editor, session)) {
+                LatexBehaviour.recordAutoInsert(editor, session, "}");
+                return {
+                    text: '{}',
+                    selection: [1, 1]
+                };
+            }
+        } else if (text == '}') {
+            initContext(editor);
+            var rightChar = line.substring(cursor.column, cursor.column + 1);
+            if (rightChar == '}') {
+                var matching = session.$findOpeningBracket('}', {column: cursor.column + 1, row: cursor.row});
+                if (matching !== null && LatexBehaviour.isAutoInsertedClosing(cursor, line, text)) {
+                    LatexBehaviour.popAutoInsertedClosing();
+                    return {
+                        text: '',
+                        selection: [1, 1]
+                    };
+                }
+            }
+        }
+    });
+
+    this.add("braces", "deletion", function(state, action, editor, session, range) {
+			if (editor.completer && editor.completer.popup && editor.completer.popup.isOpen) {
+				return;
+			}
+      var selected = session.doc.getTextRange(range);
+      if (!range.isMultiLine() && selected == '{') {
+        initContext(editor);
+        var line = session.doc.getLine(range.start.row);
+        var rightChar = line.substring(range.start.column + 1, range.start.column + 2);
+        if (rightChar == '}') {
+          range.end.column++;
+          return range;
+        }
+      }
+    });
+
+    this.add("brackets", "insertion", function(state, action, editor, session, text) {
+				if (editor.completer && editor.completer.popup && editor.completer.popup.isOpen) {
+					return;
+				}
+        var cursor = editor.getCursorPosition();
+        var line = session.doc.getLine(cursor.row);
+        var lastChar = line[cursor.column-1];
+        if (lastChar === '\\') {
+          return;
+        }
+        if (text == '[') {
+            initContext(editor);
+            var selection = editor.getSelectionRange();
+            var selected = session.doc.getTextRange(selection);
+            if (selected !== "" && editor.getWrapBehavioursEnabled()) {
+                return getWrapped(selection, selected, '[', ']');
+            } else if (LatexBehaviour.isSaneInsertion(editor, session)) {
+                LatexBehaviour.recordAutoInsert(editor, session, "]");
+                return {
+                    text: '[]',
+                    selection: [1, 1]
+                };
+            }
+        } else if (text == ']') {
+            initContext(editor);
+            var rightChar = line.substring(cursor.column, cursor.column + 1);
+            if (rightChar == ']') {
+                var matching = session.$findOpeningBracket(']', {column: cursor.column + 1, row: cursor.row});
+                if (matching !== null && LatexBehaviour.isAutoInsertedClosing(cursor, line, text)) {
+                    LatexBehaviour.popAutoInsertedClosing();
+                    return {
+                        text: '',
+                        selection: [1, 1]
+                    };
+                }
+            }
+        }
+    });
+
+    this.add("brackets", "deletion", function(state, action, editor, session, range) {
+				if (editor.completer && editor.completer.popup && editor.completer.popup.isOpen) {
+					return;
+				}
+        var selected = session.doc.getTextRange(range);
+        if (!range.isMultiLine() && selected == '[') {
+            initContext(editor);
+            var line = session.doc.getLine(range.start.row);
+            var rightChar = line.substring(range.start.column + 1, range.start.column + 2);
+            if (rightChar == ']') {
+                range.end.column++;
+                return range;
+            }
+        }
+    });
+
+    this.add("dollars", "insertion", function(state, action, editor, session, text) {
+        var cursor = editor.getCursorPosition();
+        var line = session.doc.getLine(cursor.row);
+        var lastChar = line[cursor.column-1];
+        if (lastChar === '\\') {
+          return;
+        }
+        if (text == '$') {
+            if (this.lineCommentStart && this.lineCommentStart.indexOf(text) != -1)
+                return;
+            initContext(editor);
+            var quote = text;
+            var selection = editor.getSelectionRange();
+            var selected = session.doc.getTextRange(selection);
+            if (selected !== "" && selected !== "$" && editor.getWrapBehavioursEnabled()) {
+                return getWrapped(selection, selected, quote, quote);
+            } else if (!selected) {
+                var leftChar = line.substring(cursor.column-1, cursor.column);
+                var rightChar = line.substring(cursor.column, cursor.column + 1);
+
+                var token = session.getTokenAt(cursor.row, cursor.column);
+                var rightToken = session.getTokenAt(cursor.row, cursor.column + 1);
+
+                var stringBefore = token && /string|escape/.test(token.type);
+                var stringAfter = !rightToken || /string|escape/.test(rightToken.type);
+
+                var pair;
+                if (rightChar == quote) {
+                    pair = stringBefore !== stringAfter;
+                    if (pair && /string\.end/.test(rightToken.type))
+                        pair = false;
+                } else {
+                    if (stringBefore && !stringAfter)
+                        return null; // wrap string with different quote
+                    if (stringBefore && stringAfter)
+                        return null; // do not pair quotes inside strings
+                    var wordRe = session.$mode.tokenRe;
+                    wordRe.lastIndex = 0;
+                    var isWordBefore = wordRe.test(leftChar);
+                    wordRe.lastIndex = 0;
+                    var isWordAfter = wordRe.test(leftChar);
+                    if (isWordBefore || isWordAfter)
+                        return null; // before or after alphanumeric
+                    if (rightChar && !/[\s;,.})\]\\]/.test(rightChar))
+                        return null; // there is rightChar and it isn't closing
+                    pair = true;
+                }
+                return {
+                    text: pair ? quote + quote : "",
+                    selection: [1,1]
+                };
+            }
+        }
+    });
+
+    this.add("dollars", "deletion", function(state, action, editor, session, range) {
+        var selected = session.doc.getTextRange(range);
+        if (!range.isMultiLine() && (selected == '$')) {
+            initContext(editor);
+            var line = session.doc.getLine(range.start.row);
+            var rightChar = line.substring(range.start.column + 1, range.start.column + 2);
+            if (rightChar == selected) {
+                range.end.column++;
+                return range;
+            }
+        }
+    });
+
+};
+
+
+LatexBehaviour.isSaneInsertion = function(editor, session) {
+    var cursor = editor.getCursorPosition();
+    var iterator = new TokenIterator(session, cursor.row, cursor.column);
+    if (!this.$matchTokenType(iterator.getCurrentToken() || "text", SAFE_INSERT_IN_TOKENS)) {
+        var iterator2 = new TokenIterator(session, cursor.row, cursor.column + 1);
+        if (!this.$matchTokenType(iterator2.getCurrentToken() || "text", SAFE_INSERT_IN_TOKENS))
+            return false;
+    }
+    iterator.stepForward();
+    return iterator.getCurrentTokenRow() !== cursor.row ||
+        this.$matchTokenType(iterator.getCurrentToken() || "text", SAFE_INSERT_BEFORE_TOKENS);
+};
+
+LatexBehaviour.$matchTokenType = function(token, types) {
+    return types.indexOf(token.type || token) > -1;
+};
+
+LatexBehaviour.recordAutoInsert = function(editor, session, bracket) {
+    var cursor = editor.getCursorPosition();
+    var line = session.doc.getLine(cursor.row);
+    if (!this.isAutoInsertedClosing(cursor, line, context.autoInsertedLineEnd[0]))
+        context.autoInsertedBrackets = 0;
+    context.autoInsertedRow = cursor.row;
+    context.autoInsertedLineEnd = bracket + line.substr(cursor.column);
+    context.autoInsertedBrackets++;
+};
+
+LatexBehaviour.isAutoInsertedClosing = function(cursor, line, bracket) {
+    return context.autoInsertedBrackets > 0 &&
+        cursor.row === context.autoInsertedRow &&
+        bracket === context.autoInsertedLineEnd[0] &&
+        line.substr(cursor.column) === context.autoInsertedLineEnd;
+};
+
+LatexBehaviour.popAutoInsertedClosing = function() {
+    context.autoInsertedLineEnd = context.autoInsertedLineEnd.substr(1);
+    context.autoInsertedBrackets--;
+};
+
+
+oop.inherits(LatexBehaviour, Behaviour);
+
+exports.LatexBehaviour = LatexBehaviour;
+});
+
+ace.define("ace/mode/latex",[], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var LatexHighlightRules = require("./latex_highlight_rules").LatexHighlightRules;
+var LatexFoldMode = require("./folding/latex").FoldMode;
+var Range = require("../range").Range;
+var WorkerClient = require("ace/worker/worker_client").WorkerClient;
+var LatexBehaviour = require("./behaviour/latex").LatexBehaviour;
+
+var createLatexWorker = function (session) {
+    var doc = session.getDocument();
+    var selection = session.getSelection();
+    var cursorAnchor = selection.lead;
+
+    var savedRange = {};
+    var suppressions = [];
+    var hints = [];
+    var changeHandler = null;
+    var docChangePending = false;
+    var firstPass = true;
+
+    var worker = new WorkerClient(["ace"], "ace/mode/latex_worker", "LatexWorker");
+    worker.attachToDocument(doc);
+    var docChangeHandler = doc.on("change", function () {
+        docChangePending = true;
+        if(changeHandler) {
+            clearTimeout(changeHandler);
+            changeHandler = null;
+        }
+    });
+
+    var cursorHandler = selection.on("changeCursor", function () {
+        if (docChangePending) { return; } ;
+        changeHandler = setTimeout(function () {
+            updateMarkers({cursorMoveOnly:true});
+            suppressions = [];
+            changeHandler = null;
+        }, 100);
+    });
+
+    var updateMarkers = function (options) {
+        if (!options) { options = {};};
+        var cursorMoveOnly = options.cursorMoveOnly;
+        var annotations = [];
+        var newRange = {};
+        var cursor = selection.getCursor();
+        var maxRow = session.getLength() - 1;
+        var maxCol = (maxRow > 0) ? session.getLine(maxRow).length : 0;
+        var cursorAtEndOfDocument = (cursor.row == maxRow) && (cursor.column === maxCol);
+
+        suppressions = [];
+
+        for (var i = 0, len = hints.length; i<len; i++) {
+            var hint = hints[i];
+
+            var suppressedChanges = 0;
+            var hintRange = new Range(hint.start_row, hint.start_col, hint.end_row, hint.end_col);
+
+            var cursorInRange = hintRange.insideEnd(cursor.row, cursor.column);
+            var cursorAtStart = hintRange.isStart(cursor.row, cursor.column - 1); // cursor after start not before
+            var cursorAtEnd = hintRange.isEnd(cursor.row, cursor.column);
+            if (hint.suppressIfEditing && (cursorAtStart || cursorAtEnd)) {
+                suppressions.push(hintRange);
+                if (!hint.suppressed) { suppressedChanges++; };
+                hint.suppressed = true;
+                continue;
+            }
+            var isCascadeError = false;
+            for (var j = 0, suplen = suppressions.length; j < suplen; j++) {
+                var badRange = suppressions[j];
+                if (badRange.intersects(hintRange)) {
+                    isCascadeError = true;
+                    break;
+                }
+            }
+            if(isCascadeError) {
+                if (!hint.suppressed) { suppressedChanges++; };
+                hint.suppressed = true;
+                continue;
+            };
+
+            if (hint.suppressed) { suppressedChanges++; };
+            hint.suppressed = false;
+
+            annotations.push(hint);
+            if (hint.type === "info") {
+                continue;
+            };
+            var key = hintRange.toString() + (cursorInRange ? "+cursor" : "");
+            newRange[key] = {hint: hint, cursorInRange: cursorInRange, range: hintRange};
+        }
+        for (key in newRange) {
+            if (!savedRange[key]) {  // doesn't exist in already displayed errors
+                var new_range = newRange[key].range;
+                cursorInRange = newRange[key].cursorInRange;
+                hint = newRange[key].hint;
+                var errorAtStart = (hint.row === hint.start_row && hint.column === hint.start_col);
+                var movableStart = (cursorInRange && !errorAtStart) && !cursorAtEndOfDocument;
+                var movableEnd = (cursorInRange && errorAtStart) && !cursorAtEndOfDocument;
+                var a = movableStart ? cursorAnchor : doc.createAnchor(new_range.start);
+                var b = movableEnd ? cursorAnchor : doc.createAnchor(new_range.end);
+                var range = new Range();
+                range.start = a;
+                range.end = b;
+                var cssClass = "ace_error-marker";
+                if (hint.type === "warning") { cssClass = "ace_highlight-marker"; };
+                range.id = session.addMarker(range, cssClass, "text");
+                savedRange[key] = range;
+            }
+        }
+        for (key in savedRange) {
+            if (!newRange[key]) {  // no longer present in list of errors to display
+                range = savedRange[key];
+                if (range.start !== cursorAnchor) { range.start.detach(); }
+                if (range.end !== cursorAnchor) { range.end.detach(); }
+                session.removeMarker(range.id);
+                delete savedRange[key];
+            }
+        }
+        if (!cursorMoveOnly || suppressedChanges) {
+            if (firstPass) {
+                if (annotations.length > 0) {
+                    var originalAnnotations = session.getAnnotations();
+                    session.setAnnotations(originalAnnotations.concat(annotations));
+                };
+                firstPass = false;
+            } else {
+                session.setAnnotations(annotations);
+            }
+        };
+
+    };
+    worker.on("lint", function(results) {
+        if(docChangePending) { docChangePending = false; };
+        hints = results.data.errors;
+        if (hints.length > 100) {
+            hints = hints.slice(0, 100); // limit to 100 errors
+        };
+        updateMarkers();
+    });
+    worker.on("terminate", function() {
+        if(changeHandler) {
+            clearTimeout(changeHandler);
+            changeHandler = null;
+        }
+        doc.off("change", docChangeHandler);
+        selection.off("changeCursor", cursorHandler);
+        for (var key in savedRange) {
+            var range = savedRange[key];
+            if (range.start !== cursorAnchor) { range.start.detach(); }
+            if (range.end !== cursorAnchor) { range.end.detach(); }
+            session.removeMarker(range.id);
+        }
+        savedRange = {};
+        hints = [];
+        suppressions = [];
+        session.clearAnnotations();
+    });
+
+    return worker;
+};
+
+var Mode = function() {
+    this.HighlightRules = LatexHighlightRules;
+    this.foldingRules = new LatexFoldMode();
+    this.$behaviour = new LatexBehaviour();
+    this.createWorker = createLatexWorker;
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+    this.type = "text";
+
+    this.lineCommentStart = "%";
+
+    this.$id = "ace/mode/latex";
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+
+});
+                (function() {
+                    ace.require(["ace/mode/latex"], function(m) {
+                        if (typeof module == "object" && typeof exports == "object" && module) {
+                            module.exports = m;
+                        }
+                    });
+                })();
+            

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff