ace.define("ace/mode/coffee_highlight_rules", ["require", "exports", "module", "ace/lib/oop", "ace/mode/text_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 onMatch(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", ["require", "exports", "module", "ace/range"], function (require, exports, module) {
  "use strict";

  var Range = require("../range").Range;

  var MatchingBraceOutdent = function MatchingBraceOutdent() {};

  (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", ["require", "exports", "module", "ace/lib/oop", "ace/mode/folding/fold_mode", "ace/range"], 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", ["require", "exports", "module", "ace/mode/coffee_highlight_rules", "ace/mode/matching_brace_outdent", "ace/mode/folding/coffee", "ace/range", "ace/mode/text", "ace/worker/worker_client", "ace/lib/oop"], 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";
    this.snippetFileId = "ace/snippets/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;
    }
  });
})();