clike.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  2. // Distributed under an MIT license: http://codemirror.net/LICENSE
  3. (function(mod) {
  4. if (typeof exports == "object" && typeof module == "object") // CommonJS
  5. mod(require("../../lib/codemirror"));
  6. else if (typeof define == "function" && define.amd) // AMD
  7. define(["../../lib/codemirror"], mod);
  8. else // Plain browser env
  9. mod(CodeMirror);
  10. })(function(CodeMirror) {
  11. "use strict";
  12. CodeMirror.defineMode("clike", function(config, parserConfig) {
  13. var indentUnit = config.indentUnit,
  14. statementIndentUnit = parserConfig.statementIndentUnit || indentUnit,
  15. dontAlignCalls = parserConfig.dontAlignCalls,
  16. keywords = parserConfig.keywords || {},
  17. builtin = parserConfig.builtin || {},
  18. blockKeywords = parserConfig.blockKeywords || {},
  19. atoms = parserConfig.atoms || {},
  20. hooks = parserConfig.hooks || {},
  21. multiLineStrings = parserConfig.multiLineStrings,
  22. indentStatements = parserConfig.indentStatements !== false;
  23. var isOperatorChar = /[+\-*&%=<>!?|\/]/;
  24. var curPunc;
  25. function tokenBase(stream, state) {
  26. var ch = stream.next();
  27. if (hooks[ch]) {
  28. var result = hooks[ch](stream, state);
  29. if (result !== false) return result;
  30. }
  31. if (ch == '"' || ch == "'") {
  32. state.tokenize = tokenString(ch);
  33. return state.tokenize(stream, state);
  34. }
  35. if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
  36. curPunc = ch;
  37. return null;
  38. }
  39. if (/\d/.test(ch)) {
  40. stream.eatWhile(/[\w\.]/);
  41. return "number";
  42. }
  43. if (ch == "/") {
  44. if (stream.eat("*")) {
  45. state.tokenize = tokenComment;
  46. return tokenComment(stream, state);
  47. }
  48. if (stream.eat("/")) {
  49. stream.skipToEnd();
  50. return "comment";
  51. }
  52. }
  53. if (isOperatorChar.test(ch)) {
  54. stream.eatWhile(isOperatorChar);
  55. return "operator";
  56. }
  57. stream.eatWhile(/[\w\$_\xa1-\uffff]/);
  58. var cur = stream.current();
  59. if (keywords.propertyIsEnumerable(cur)) {
  60. if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
  61. return "keyword";
  62. }
  63. if (builtin.propertyIsEnumerable(cur)) {
  64. if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
  65. return "builtin";
  66. }
  67. if (atoms.propertyIsEnumerable(cur)) return "atom";
  68. return "variable";
  69. }
  70. function tokenString(quote) {
  71. return function(stream, state) {
  72. var escaped = false, next, end = false;
  73. while ((next = stream.next()) != null) {
  74. if (next == quote && !escaped) {end = true; break;}
  75. escaped = !escaped && next == "\\";
  76. }
  77. if (end || !(escaped || multiLineStrings))
  78. state.tokenize = null;
  79. return "string";
  80. };
  81. }
  82. function tokenComment(stream, state) {
  83. var maybeEnd = false, ch;
  84. while (ch = stream.next()) {
  85. if (ch == "/" && maybeEnd) {
  86. state.tokenize = null;
  87. break;
  88. }
  89. maybeEnd = (ch == "*");
  90. }
  91. return "comment";
  92. }
  93. function Context(indented, column, type, align, prev) {
  94. this.indented = indented;
  95. this.column = column;
  96. this.type = type;
  97. this.align = align;
  98. this.prev = prev;
  99. }
  100. function pushContext(state, col, type) {
  101. var indent = state.indented;
  102. if (state.context && state.context.type == "statement")
  103. indent = state.context.indented;
  104. return state.context = new Context(indent, col, type, null, state.context);
  105. }
  106. function popContext(state) {
  107. var t = state.context.type;
  108. if (t == ")" || t == "]" || t == "}")
  109. state.indented = state.context.indented;
  110. return state.context = state.context.prev;
  111. }
  112. // Interface
  113. return {
  114. startState: function(basecolumn) {
  115. return {
  116. tokenize: null,
  117. context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
  118. indented: 0,
  119. startOfLine: true
  120. };
  121. },
  122. token: function(stream, state) {
  123. var ctx = state.context;
  124. if (stream.sol()) {
  125. if (ctx.align == null) ctx.align = false;
  126. state.indented = stream.indentation();
  127. state.startOfLine = true;
  128. }
  129. if (stream.eatSpace()) return null;
  130. curPunc = null;
  131. var style = (state.tokenize || tokenBase)(stream, state);
  132. if (style == "comment" || style == "meta") return style;
  133. if (ctx.align == null) ctx.align = true;
  134. if ((curPunc == ";" || curPunc == ":" || curPunc == ",") && ctx.type == "statement") popContext(state);
  135. else if (curPunc == "{") pushContext(state, stream.column(), "}");
  136. else if (curPunc == "[") pushContext(state, stream.column(), "]");
  137. else if (curPunc == "(") pushContext(state, stream.column(), ")");
  138. else if (curPunc == "}") {
  139. while (ctx.type == "statement") ctx = popContext(state);
  140. if (ctx.type == "}") ctx = popContext(state);
  141. while (ctx.type == "statement") ctx = popContext(state);
  142. }
  143. else if (curPunc == ctx.type) popContext(state);
  144. else if (indentStatements &&
  145. (((ctx.type == "}" || ctx.type == "top") && curPunc != ';') ||
  146. (ctx.type == "statement" && curPunc == "newstatement")))
  147. pushContext(state, stream.column(), "statement");
  148. state.startOfLine = false;
  149. return style;
  150. },
  151. indent: function(state, textAfter) {
  152. if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass;
  153. var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
  154. if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;
  155. var closing = firstChar == ctx.type;
  156. if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit);
  157. else if (ctx.align && (!dontAlignCalls || ctx.type != ")")) return ctx.column + (closing ? 0 : 1);
  158. else if (ctx.type == ")" && !closing) return ctx.indented + statementIndentUnit;
  159. else return ctx.indented + (closing ? 0 : indentUnit);
  160. },
  161. electricChars: "{}",
  162. blockCommentStart: "/*",
  163. blockCommentEnd: "*/",
  164. lineComment: "//",
  165. fold: "brace"
  166. };
  167. });
  168. function words(str) {
  169. var obj = {}, words = str.split(" ");
  170. for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
  171. return obj;
  172. }
  173. var cKeywords = "auto if break int case long char register continue return default short do sizeof " +
  174. "double static else struct entry switch extern typedef float union for unsigned " +
  175. "goto while enum void const signed volatile";
  176. function cppHook(stream, state) {
  177. if (!state.startOfLine) return false;
  178. for (;;) {
  179. if (stream.skipTo("\\")) {
  180. stream.next();
  181. if (stream.eol()) {
  182. state.tokenize = cppHook;
  183. break;
  184. }
  185. } else {
  186. stream.skipToEnd();
  187. state.tokenize = null;
  188. break;
  189. }
  190. }
  191. return "meta";
  192. }
  193. function cpp11StringHook(stream, state) {
  194. stream.backUp(1);
  195. // Raw strings.
  196. if (stream.match(/(R|u8R|uR|UR|LR)/)) {
  197. var match = stream.match(/"([^\s\\()]{0,16})\(/);
  198. if (!match) {
  199. return false;
  200. }
  201. state.cpp11RawStringDelim = match[1];
  202. state.tokenize = tokenRawString;
  203. return tokenRawString(stream, state);
  204. }
  205. // Unicode strings/chars.
  206. if (stream.match(/(u8|u|U|L)/)) {
  207. if (stream.match(/["']/, /* eat */ false)) {
  208. return "string";
  209. }
  210. return false;
  211. }
  212. // Ignore this hook.
  213. stream.next();
  214. return false;
  215. }
  216. // C#-style strings where "" escapes a quote.
  217. function tokenAtString(stream, state) {
  218. var next;
  219. while ((next = stream.next()) != null) {
  220. if (next == '"' && !stream.eat('"')) {
  221. state.tokenize = null;
  222. break;
  223. }
  224. }
  225. return "string";
  226. }
  227. // C++11 raw string literal is <prefix>"<delim>( anything )<delim>", where
  228. // <delim> can be a string up to 16 characters long.
  229. function tokenRawString(stream, state) {
  230. // Escape characters that have special regex meanings.
  231. var delim = state.cpp11RawStringDelim.replace(/[^\w\s]/g, '\\$&');
  232. var match = stream.match(new RegExp(".*?\\)" + delim + '"'));
  233. if (match)
  234. state.tokenize = null;
  235. else
  236. stream.skipToEnd();
  237. return "string";
  238. }
  239. function def(mimes, mode) {
  240. if (typeof mimes == "string") mimes = [mimes];
  241. var words = [];
  242. function add(obj) {
  243. if (obj) for (var prop in obj) if (obj.hasOwnProperty(prop))
  244. words.push(prop);
  245. }
  246. add(mode.keywords);
  247. add(mode.builtin);
  248. add(mode.atoms);
  249. if (words.length) {
  250. mode.helperType = mimes[0];
  251. CodeMirror.registerHelper("hintWords", mimes[0], words);
  252. }
  253. for (var i = 0; i < mimes.length; ++i)
  254. CodeMirror.defineMIME(mimes[i], mode);
  255. }
  256. def(["text/x-csrc", "text/x-c", "text/x-chdr"], {
  257. name: "clike",
  258. keywords: words(cKeywords),
  259. blockKeywords: words("case do else for if switch while struct"),
  260. atoms: words("null"),
  261. hooks: {"#": cppHook},
  262. modeProps: {fold: ["brace", "include"]}
  263. });
  264. def(["text/x-c++src", "text/x-c++hdr"], {
  265. name: "clike",
  266. keywords: words(cKeywords + " asm dynamic_cast namespace reinterpret_cast try bool explicit new " +
  267. "static_cast typeid catch operator template typename class friend private " +
  268. "this using const_cast inline public throw virtual delete mutable protected " +
  269. "wchar_t alignas alignof constexpr decltype nullptr noexcept thread_local final " +
  270. "static_assert override"),
  271. blockKeywords: words("catch class do else finally for if struct switch try while"),
  272. atoms: words("true false null"),
  273. hooks: {
  274. "#": cppHook,
  275. "u": cpp11StringHook,
  276. "U": cpp11StringHook,
  277. "L": cpp11StringHook,
  278. "R": cpp11StringHook
  279. },
  280. modeProps: {fold: ["brace", "include"]}
  281. });
  282. def("text/x-java", {
  283. name: "clike",
  284. keywords: words("abstract assert boolean break byte case catch char class const continue default " +
  285. "do double else enum extends final finally float for goto if implements import " +
  286. "instanceof int interface long native new package private protected public " +
  287. "return short static strictfp super switch synchronized this throw throws transient " +
  288. "try void volatile while"),
  289. blockKeywords: words("catch class do else finally for if switch try while"),
  290. atoms: words("true false null"),
  291. hooks: {
  292. "@": function(stream) {
  293. stream.eatWhile(/[\w\$_]/);
  294. return "meta";
  295. }
  296. },
  297. modeProps: {fold: ["brace", "import"]}
  298. });
  299. def("text/x-csharp", {
  300. name: "clike",
  301. keywords: words("abstract as base break case catch checked class const continue" +
  302. " default delegate do else enum event explicit extern finally fixed for" +
  303. " foreach goto if implicit in interface internal is lock namespace new" +
  304. " operator out override params private protected public readonly ref return sealed" +
  305. " sizeof stackalloc static struct switch this throw try typeof unchecked" +
  306. " unsafe using virtual void volatile while add alias ascending descending dynamic from get" +
  307. " global group into join let orderby partial remove select set value var yield"),
  308. blockKeywords: words("catch class do else finally for foreach if struct switch try while"),
  309. builtin: words("Boolean Byte Char DateTime DateTimeOffset Decimal Double" +
  310. " Guid Int16 Int32 Int64 Object SByte Single String TimeSpan UInt16 UInt32" +
  311. " UInt64 bool byte char decimal double short int long object" +
  312. " sbyte float string ushort uint ulong"),
  313. atoms: words("true false null"),
  314. hooks: {
  315. "@": function(stream, state) {
  316. if (stream.eat('"')) {
  317. state.tokenize = tokenAtString;
  318. return tokenAtString(stream, state);
  319. }
  320. stream.eatWhile(/[\w\$_]/);
  321. return "meta";
  322. }
  323. }
  324. });
  325. function tokenTripleString(stream, state) {
  326. var escaped = false;
  327. while (!stream.eol()) {
  328. if (!escaped && stream.match('"""')) {
  329. state.tokenize = null;
  330. break;
  331. }
  332. escaped = stream.next() == "\\" && !escaped;
  333. }
  334. return "string";
  335. }
  336. def("text/x-scala", {
  337. name: "clike",
  338. keywords: words(
  339. /* scala */
  340. "abstract case catch class def do else extends false final finally for forSome if " +
  341. "implicit import lazy match new null object override package private protected return " +
  342. "sealed super this throw trait try trye type val var while with yield _ : = => <- <: " +
  343. "<% >: # @ " +
  344. /* package scala */
  345. "assert assume require print println printf readLine readBoolean readByte readShort " +
  346. "readChar readInt readLong readFloat readDouble " +
  347. "AnyVal App Application Array BufferedIterator BigDecimal BigInt Char Console Either " +
  348. "Enumeration Equiv Error Exception Fractional Function IndexedSeq Integral Iterable " +
  349. "Iterator List Map Numeric Nil NotNull Option Ordered Ordering PartialFunction PartialOrdering " +
  350. "Product Proxy Range Responder Seq Serializable Set Specializable Stream StringBuilder " +
  351. "StringContext Symbol Throwable Traversable TraversableOnce Tuple Unit Vector :: #:: " +
  352. /* package java.lang */
  353. "Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable " +
  354. "Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " +
  355. "Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " +
  356. "StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void"
  357. ),
  358. multiLineStrings: true,
  359. blockKeywords: words("catch class do else finally for forSome if match switch try while"),
  360. atoms: words("true false null"),
  361. indentStatements: false,
  362. hooks: {
  363. "@": function(stream) {
  364. stream.eatWhile(/[\w\$_]/);
  365. return "meta";
  366. },
  367. '"': function(stream, state) {
  368. if (!stream.match('""')) return false;
  369. state.tokenize = tokenTripleString;
  370. return state.tokenize(stream, state);
  371. },
  372. "'": function(stream) {
  373. stream.eatWhile(/[\w\$_\xa1-\uffff]/);
  374. return "atom";
  375. }
  376. }
  377. });
  378. def(["x-shader/x-vertex", "x-shader/x-fragment"], {
  379. name: "clike",
  380. keywords: words("float int bool void " +
  381. "vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 " +
  382. "mat2 mat3 mat4 " +
  383. "sampler1D sampler2D sampler3D samplerCube " +
  384. "sampler1DShadow sampler2DShadow " +
  385. "const attribute uniform varying " +
  386. "break continue discard return " +
  387. "for while do if else struct " +
  388. "in out inout"),
  389. blockKeywords: words("for while do if else struct"),
  390. builtin: words("radians degrees sin cos tan asin acos atan " +
  391. "pow exp log exp2 sqrt inversesqrt " +
  392. "abs sign floor ceil fract mod min max clamp mix step smoothstep " +
  393. "length distance dot cross normalize ftransform faceforward " +
  394. "reflect refract matrixCompMult " +
  395. "lessThan lessThanEqual greaterThan greaterThanEqual " +
  396. "equal notEqual any all not " +
  397. "texture1D texture1DProj texture1DLod texture1DProjLod " +
  398. "texture2D texture2DProj texture2DLod texture2DProjLod " +
  399. "texture3D texture3DProj texture3DLod texture3DProjLod " +
  400. "textureCube textureCubeLod " +
  401. "shadow1D shadow2D shadow1DProj shadow2DProj " +
  402. "shadow1DLod shadow2DLod shadow1DProjLod shadow2DProjLod " +
  403. "dFdx dFdy fwidth " +
  404. "noise1 noise2 noise3 noise4"),
  405. atoms: words("true false " +
  406. "gl_FragColor gl_SecondaryColor gl_Normal gl_Vertex " +
  407. "gl_MultiTexCoord0 gl_MultiTexCoord1 gl_MultiTexCoord2 gl_MultiTexCoord3 " +
  408. "gl_MultiTexCoord4 gl_MultiTexCoord5 gl_MultiTexCoord6 gl_MultiTexCoord7 " +
  409. "gl_FogCoord gl_PointCoord " +
  410. "gl_Position gl_PointSize gl_ClipVertex " +
  411. "gl_FrontColor gl_BackColor gl_FrontSecondaryColor gl_BackSecondaryColor " +
  412. "gl_TexCoord gl_FogFragCoord " +
  413. "gl_FragCoord gl_FrontFacing " +
  414. "gl_FragData gl_FragDepth " +
  415. "gl_ModelViewMatrix gl_ProjectionMatrix gl_ModelViewProjectionMatrix " +
  416. "gl_TextureMatrix gl_NormalMatrix gl_ModelViewMatrixInverse " +
  417. "gl_ProjectionMatrixInverse gl_ModelViewProjectionMatrixInverse " +
  418. "gl_TexureMatrixTranspose gl_ModelViewMatrixInverseTranspose " +
  419. "gl_ProjectionMatrixInverseTranspose " +
  420. "gl_ModelViewProjectionMatrixInverseTranspose " +
  421. "gl_TextureMatrixInverseTranspose " +
  422. "gl_NormalScale gl_DepthRange gl_ClipPlane " +
  423. "gl_Point gl_FrontMaterial gl_BackMaterial gl_LightSource gl_LightModel " +
  424. "gl_FrontLightModelProduct gl_BackLightModelProduct " +
  425. "gl_TextureColor gl_EyePlaneS gl_EyePlaneT gl_EyePlaneR gl_EyePlaneQ " +
  426. "gl_FogParameters " +
  427. "gl_MaxLights gl_MaxClipPlanes gl_MaxTextureUnits gl_MaxTextureCoords " +
  428. "gl_MaxVertexAttribs gl_MaxVertexUniformComponents gl_MaxVaryingFloats " +
  429. "gl_MaxVertexTextureImageUnits gl_MaxTextureImageUnits " +
  430. "gl_MaxFragmentUniformComponents gl_MaxCombineTextureImageUnits " +
  431. "gl_MaxDrawBuffers"),
  432. hooks: {"#": cppHook},
  433. modeProps: {fold: ["brace", "include"]}
  434. });
  435. def("text/x-nesc", {
  436. name: "clike",
  437. keywords: words(cKeywords + "as atomic async call command component components configuration event generic " +
  438. "implementation includes interface module new norace nx_struct nx_union post provides " +
  439. "signal task uses abstract extends"),
  440. blockKeywords: words("case do else for if switch while struct"),
  441. atoms: words("null"),
  442. hooks: {"#": cppHook},
  443. modeProps: {fold: ["brace", "include"]}
  444. });
  445. def("text/x-objectivec", {
  446. name: "clike",
  447. keywords: words(cKeywords + "inline restrict _Bool _Complex _Imaginery BOOL Class bycopy byref id IMP in " +
  448. "inout nil oneway out Protocol SEL self super atomic nonatomic retain copy readwrite readonly"),
  449. atoms: words("YES NO NULL NILL ON OFF"),
  450. hooks: {
  451. "@": function(stream) {
  452. stream.eatWhile(/[\w\$]/);
  453. return "keyword";
  454. },
  455. "#": cppHook
  456. },
  457. modeProps: {fold: "brace"}
  458. });
  459. });