lua.js 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  2. // Distributed under an MIT license: https://codemirror.net/LICENSE
  3. // LUA mode. Ported to CodeMirror 2 from Franciszek Wawrzak's
  4. // CodeMirror 1 mode.
  5. // highlights keywords, strings, comments (no leveling supported! ("[==[")), tokens, basic indenting
  6. ;(function (mod) {
  7. if (typeof exports == 'object' && typeof module == 'object')
  8. // CommonJS
  9. mod(require('../../lib/codemirror'))
  10. else if (typeof define == 'function' && define.amd)
  11. // AMD
  12. define(['../../lib/codemirror'], mod)
  13. // Plain browser env
  14. else mod(CodeMirror)
  15. })(function (CodeMirror) {
  16. 'use strict'
  17. CodeMirror.defineMode('lua', function (config, parserConfig) {
  18. var indentUnit = config.indentUnit
  19. function prefixRE(words) {
  20. return new RegExp('^(?:' + words.join('|') + ')', 'i')
  21. }
  22. function wordRE(words) {
  23. return new RegExp('^(?:' + words.join('|') + ')$', 'i')
  24. }
  25. var specials = wordRE(parserConfig.specials || [])
  26. // long list of standard functions from lua manual
  27. var builtins = wordRE([
  28. '_G',
  29. '_VERSION',
  30. 'assert',
  31. 'collectgarbage',
  32. 'dofile',
  33. 'error',
  34. 'getfenv',
  35. 'getmetatable',
  36. 'ipairs',
  37. 'load',
  38. 'loadfile',
  39. 'loadstring',
  40. 'module',
  41. 'next',
  42. 'pairs',
  43. 'pcall',
  44. 'print',
  45. 'rawequal',
  46. 'rawget',
  47. 'rawset',
  48. 'require',
  49. 'select',
  50. 'setfenv',
  51. 'setmetatable',
  52. 'tonumber',
  53. 'tostring',
  54. 'type',
  55. 'unpack',
  56. 'xpcall',
  57. 'coroutine.create',
  58. 'coroutine.resume',
  59. 'coroutine.running',
  60. 'coroutine.status',
  61. 'coroutine.wrap',
  62. 'coroutine.yield',
  63. 'debug.debug',
  64. 'debug.getfenv',
  65. 'debug.gethook',
  66. 'debug.getinfo',
  67. 'debug.getlocal',
  68. 'debug.getmetatable',
  69. 'debug.getregistry',
  70. 'debug.getupvalue',
  71. 'debug.setfenv',
  72. 'debug.sethook',
  73. 'debug.setlocal',
  74. 'debug.setmetatable',
  75. 'debug.setupvalue',
  76. 'debug.traceback',
  77. 'close',
  78. 'flush',
  79. 'lines',
  80. 'read',
  81. 'seek',
  82. 'setvbuf',
  83. 'write',
  84. 'io.close',
  85. 'io.flush',
  86. 'io.input',
  87. 'io.lines',
  88. 'io.open',
  89. 'io.output',
  90. 'io.popen',
  91. 'io.read',
  92. 'io.stderr',
  93. 'io.stdin',
  94. 'io.stdout',
  95. 'io.tmpfile',
  96. 'io.type',
  97. 'io.write',
  98. 'math.abs',
  99. 'math.acos',
  100. 'math.asin',
  101. 'math.atan',
  102. 'math.atan2',
  103. 'math.ceil',
  104. 'math.cos',
  105. 'math.cosh',
  106. 'math.deg',
  107. 'math.exp',
  108. 'math.floor',
  109. 'math.fmod',
  110. 'math.frexp',
  111. 'math.huge',
  112. 'math.ldexp',
  113. 'math.log',
  114. 'math.log10',
  115. 'math.max',
  116. 'math.min',
  117. 'math.modf',
  118. 'math.pi',
  119. 'math.pow',
  120. 'math.rad',
  121. 'math.random',
  122. 'math.randomseed',
  123. 'math.sin',
  124. 'math.sinh',
  125. 'math.sqrt',
  126. 'math.tan',
  127. 'math.tanh',
  128. 'os.clock',
  129. 'os.date',
  130. 'os.difftime',
  131. 'os.execute',
  132. 'os.exit',
  133. 'os.getenv',
  134. 'os.remove',
  135. 'os.rename',
  136. 'os.setlocale',
  137. 'os.time',
  138. 'os.tmpname',
  139. 'package.cpath',
  140. 'package.loaded',
  141. 'package.loaders',
  142. 'package.loadlib',
  143. 'package.path',
  144. 'package.preload',
  145. 'package.seeall',
  146. 'string.byte',
  147. 'string.char',
  148. 'string.dump',
  149. 'string.find',
  150. 'string.format',
  151. 'string.gmatch',
  152. 'string.gsub',
  153. 'string.len',
  154. 'string.lower',
  155. 'string.match',
  156. 'string.rep',
  157. 'string.reverse',
  158. 'string.sub',
  159. 'string.upper',
  160. 'table.concat',
  161. 'table.insert',
  162. 'table.maxn',
  163. 'table.remove',
  164. 'table.sort',
  165. ])
  166. var keywords = wordRE([
  167. 'and',
  168. 'break',
  169. 'elseif',
  170. 'false',
  171. 'nil',
  172. 'not',
  173. 'or',
  174. 'return',
  175. 'true',
  176. 'function',
  177. 'end',
  178. 'if',
  179. 'then',
  180. 'else',
  181. 'do',
  182. 'while',
  183. 'repeat',
  184. 'until',
  185. 'for',
  186. 'in',
  187. 'local',
  188. ])
  189. var indentTokens = wordRE(['function', 'if', 'repeat', 'do', '\\(', '{'])
  190. var dedentTokens = wordRE(['end', 'until', '\\)', '}'])
  191. var dedentPartial = prefixRE(['end', 'until', '\\)', '}', 'else', 'elseif'])
  192. function readBracket(stream) {
  193. var level = 0
  194. while (stream.eat('=')) ++level
  195. stream.eat('[')
  196. return level
  197. }
  198. function normal(stream, state) {
  199. var ch = stream.next()
  200. if (ch == '-' && stream.eat('-')) {
  201. if (stream.eat('[') && stream.eat('[')) return (state.cur = bracketed(readBracket(stream), 'comment'))(stream, state)
  202. stream.skipToEnd()
  203. return 'comment'
  204. }
  205. if (ch == '"' || ch == "'") return (state.cur = string(ch))(stream, state)
  206. if (ch == '[' && /[\[=]/.test(stream.peek())) return (state.cur = bracketed(readBracket(stream), 'string'))(stream, state)
  207. if (/\d/.test(ch)) {
  208. stream.eatWhile(/[\w.%]/)
  209. return 'number'
  210. }
  211. if (/[\w_]/.test(ch)) {
  212. stream.eatWhile(/[\w\\\-_.]/)
  213. return 'variable'
  214. }
  215. return null
  216. }
  217. function bracketed(level, style) {
  218. return function (stream, state) {
  219. var curlev = null,
  220. ch
  221. while ((ch = stream.next()) != null) {
  222. if (curlev == null) {
  223. if (ch == ']') curlev = 0
  224. } else if (ch == '=') ++curlev
  225. else if (ch == ']' && curlev == level) {
  226. state.cur = normal
  227. break
  228. } else curlev = null
  229. }
  230. return style
  231. }
  232. }
  233. function string(quote) {
  234. return function (stream, state) {
  235. var escaped = false,
  236. ch
  237. while ((ch = stream.next()) != null) {
  238. if (ch == quote && !escaped) break
  239. escaped = !escaped && ch == '\\'
  240. }
  241. if (!escaped) state.cur = normal
  242. return 'string'
  243. }
  244. }
  245. return {
  246. startState: function (basecol) {
  247. return { basecol: basecol || 0, indentDepth: 0, cur: normal }
  248. },
  249. token: function (stream, state) {
  250. if (stream.eatSpace()) return null
  251. var style = state.cur(stream, state)
  252. var word = stream.current()
  253. if (style == 'variable') {
  254. if (keywords.test(word)) style = 'keyword'
  255. else if (builtins.test(word)) style = 'builtin'
  256. else if (specials.test(word)) style = 'variable-2'
  257. }
  258. if (style != 'comment' && style != 'string') {
  259. if (indentTokens.test(word)) ++state.indentDepth
  260. else if (dedentTokens.test(word)) --state.indentDepth
  261. }
  262. return style
  263. },
  264. indent: function (state, textAfter) {
  265. var closing = dedentPartial.test(textAfter)
  266. return state.basecol + indentUnit * (state.indentDepth - (closing ? 1 : 0))
  267. },
  268. electricInput: /^\s*(?:end|until|else|\)|\})$/,
  269. lineComment: '--',
  270. blockCommentStart: '--[[',
  271. blockCommentEnd: ']]',
  272. }
  273. })
  274. CodeMirror.defineMIME('text/x-lua', 'lua')
  275. })