commonlisp.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. (function(mod) {
  2. if (typeof exports == "object" && typeof module == "object") // CommonJS
  3. mod(require("../../lib/codemirror"));
  4. else if (typeof define == "function" && define.amd) // AMD
  5. define(["../../lib/codemirror"], mod);
  6. else // Plain browser env
  7. mod(CodeMirror);
  8. })(function(CodeMirror) {
  9. "use strict";
  10. CodeMirror.defineMode("commonlisp", function (config) {
  11. var assumeBody = /^with|^def|^do|^prog|case$|^cond$|bind$|when$|unless$/;
  12. var numLiteral = /^(?:[+\-]?(?:\d+|\d*\.\d+)(?:[efd][+\-]?\d+)?|[+\-]?\d+(?:\/[+\-]?\d+)?|#b[+\-]?[01]+|#o[+\-]?[0-7]+|#x[+\-]?[\da-f]+)/;
  13. var symbol = /[^\s'`,@()\[\]";]/;
  14. var type;
  15. function readSym(stream) {
  16. var ch;
  17. while (ch = stream.next()) {
  18. if (ch == "\\") stream.next();
  19. else if (!symbol.test(ch)) { stream.backUp(1); break; }
  20. }
  21. return stream.current();
  22. }
  23. function base(stream, state) {
  24. if (stream.eatSpace()) {type = "ws"; return null;}
  25. if (stream.match(numLiteral)) return "number";
  26. var ch = stream.next();
  27. if (ch == "\\") ch = stream.next();
  28. if (ch == '"') return (state.tokenize = inString)(stream, state);
  29. else if (ch == "(") { type = "open"; return "bracket"; }
  30. else if (ch == ")" || ch == "]") { type = "close"; return "bracket"; }
  31. else if (ch == ";") { stream.skipToEnd(); type = "ws"; return "comment"; }
  32. else if (/['`,@]/.test(ch)) return null;
  33. else if (ch == "|") {
  34. if (stream.skipTo("|")) { stream.next(); return "symbol"; }
  35. else { stream.skipToEnd(); return "error"; }
  36. } else if (ch == "#") {
  37. var ch = stream.next();
  38. if (ch == "[") { type = "open"; return "bracket"; }
  39. else if (/[+\-=\.']/.test(ch)) return null;
  40. else if (/\d/.test(ch) && stream.match(/^\d*#/)) return null;
  41. else if (ch == "|") return (state.tokenize = inComment)(stream, state);
  42. else if (ch == ":") { readSym(stream); return "meta"; }
  43. else return "error";
  44. } else {
  45. var name = readSym(stream);
  46. if (name == ".") return null;
  47. type = "symbol";
  48. if (name == "nil" || name == "t") return "atom";
  49. if (name.charAt(0) == ":") return "keyword";
  50. if (name.charAt(0) == "&") return "variable-2";
  51. return "variable";
  52. }
  53. }
  54. function inString(stream, state) {
  55. var escaped = false, next;
  56. while (next = stream.next()) {
  57. if (next == '"' && !escaped) { state.tokenize = base; break; }
  58. escaped = !escaped && next == "\\";
  59. }
  60. return "string";
  61. }
  62. function inComment(stream, state) {
  63. var next, last;
  64. while (next = stream.next()) {
  65. if (next == "#" && last == "|") { state.tokenize = base; break; }
  66. last = next;
  67. }
  68. type = "ws";
  69. return "comment";
  70. }
  71. return {
  72. startState: function () {
  73. return {ctx: {prev: null, start: 0, indentTo: 0}, tokenize: base};
  74. },
  75. token: function (stream, state) {
  76. if (stream.sol() && typeof state.ctx.indentTo != "number")
  77. state.ctx.indentTo = state.ctx.start + 1;
  78. type = null;
  79. var style = state.tokenize(stream, state);
  80. if (type != "ws") {
  81. if (state.ctx.indentTo == null) {
  82. if (type == "symbol" && assumeBody.test(stream.current()))
  83. state.ctx.indentTo = state.ctx.start + config.indentUnit;
  84. else
  85. state.ctx.indentTo = "next";
  86. } else if (state.ctx.indentTo == "next") {
  87. state.ctx.indentTo = stream.column();
  88. }
  89. }
  90. if (type == "open") state.ctx = {prev: state.ctx, start: stream.column(), indentTo: null};
  91. else if (type == "close") state.ctx = state.ctx.prev || state.ctx;
  92. return style;
  93. },
  94. indent: function (state, _textAfter) {
  95. var i = state.ctx.indentTo;
  96. return typeof i == "number" ? i : state.ctx.start + 1;
  97. },
  98. lineComment: ";;",
  99. blockCommentStart: "#|",
  100. blockCommentEnd: "|#"
  101. };
  102. });
  103. CodeMirror.defineMIME("text/x-common-lisp", "commonlisp");
  104. });