livescript.ls 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. /**
  2. * Link to the project's GitHub page:
  3. * https://github.com/duralog/CodeMirror
  4. */
  5. CodeMirror.defineMode 'livescript', (conf) ->
  6. tokenBase = (stream, state) ->
  7. #indent =
  8. if next_rule = state.next or \start
  9. state.next = state.next
  10. if Array.isArray nr = Rules[next_rule]
  11. for r in nr
  12. if r.regex and m = stream.match r.regex
  13. state.next = r.next
  14. return r.token
  15. stream.next!
  16. return \error
  17. if stream.match r = Rules[next_rule]
  18. if r.regex and stream.match r.regex
  19. state.next = r.next
  20. return r.token
  21. else
  22. stream.next!
  23. return \error
  24. stream.next!
  25. return 'error'
  26. external = {
  27. startState: (basecolumn) ->
  28. {
  29. next: \start
  30. lastToken: null
  31. }
  32. token: (stream, state) ->
  33. style = tokenBase stream, state #tokenLexer stream, state
  34. state.lastToken = {
  35. style: style
  36. indent: stream.indentation!
  37. content: stream.current!
  38. }
  39. style.replace /\./g, ' '
  40. indent: (state, textAfter) ->
  41. # XXX this won't work with backcalls
  42. indentation = state.lastToken.indent
  43. if state.lastToken.content.match indenter then indentation += 2
  44. return indentation
  45. }
  46. external
  47. ### Highlight Rules
  48. # taken from mode-ls.ls
  49. indenter = // (?
  50. : [({[=:]
  51. | [-~]>
  52. | \b (?: e(?:lse|xport) | d(?:o|efault) | t(?:ry|hen) | finally |
  53. import (?:\s* all)? | const | var |
  54. let | new | catch (?:\s* #identifier)? )
  55. ) \s* $ //
  56. identifier = /(?![\d\s])[$\w\xAA-\uFFDC](?:(?!\s)[$\w\xAA-\uFFDC]|-[A-Za-z])*/$
  57. keywordend = /(?![$\w]|-[A-Za-z]|\s*:(?![:=]))/$
  58. stringfill = token: \string, regex: '.+'
  59. Rules =
  60. start:
  61. * token: \comment.doc
  62. regex: '/\\*'
  63. next : \comment
  64. * token: \comment
  65. regex: '#.*'
  66. * token: \keyword
  67. regex: //(?
  68. :t(?:h(?:is|row|en)|ry|ypeof!?)
  69. |c(?:on(?:tinue|st)|a(?:se|tch)|lass)
  70. |i(?:n(?:stanceof)?|mp(?:ort(?:\s+all)?|lements)|[fs])
  71. |d(?:e(?:fault|lete|bugger)|o)
  72. |f(?:or(?:\s+own)?|inally|unction)
  73. |s(?:uper|witch)
  74. |e(?:lse|x(?:tends|port)|val)
  75. |a(?:nd|rguments)
  76. |n(?:ew|ot)
  77. |un(?:less|til)
  78. |w(?:hile|ith)
  79. |o[fr]|return|break|let|var|loop
  80. )//$ + keywordend
  81. * token: \constant.language
  82. regex: '(?:true|false|yes|no|on|off|null|void|undefined)' + keywordend
  83. * token: \invalid.illegal
  84. regex: '(?
  85. :p(?:ackage|r(?:ivate|otected)|ublic)
  86. |i(?:mplements|nterface)
  87. |enum|static|yield
  88. )' + keywordend
  89. * token: \language.support.class
  90. regex: '(?
  91. :R(?:e(?:gExp|ferenceError)|angeError)
  92. |S(?:tring|yntaxError)
  93. |E(?:rror|valError)
  94. |Array|Boolean|Date|Function|Number|Object|TypeError|URIError
  95. )' + keywordend
  96. * token: \language.support.function
  97. regex: '(?
  98. :is(?:NaN|Finite)
  99. |parse(?:Int|Float)
  100. |Math|JSON
  101. |(?:en|de)codeURI(?:Component)?
  102. )' + keywordend
  103. * token: \variable.language
  104. regex: '(?:t(?:hat|il|o)|f(?:rom|allthrough)|it|by|e)' + keywordend
  105. * token: \identifier
  106. regex: identifier + /\s*:(?![:=])/$
  107. * token: \variable
  108. regex: identifier
  109. * token: \keyword.operator
  110. regex: /(?:\.{3}|\s+\?)/$
  111. * token: \keyword.variable
  112. regex: /(?:@+|::|\.\.)/$
  113. next : \key
  114. * token: \keyword.operator
  115. regex: /\.\s*/$
  116. next : \key
  117. * token: \string
  118. regex: /\\\S[^\s,;)}\]]*/$
  119. * token: \string.doc
  120. regex: \'''
  121. next : \qdoc
  122. * token: \string.doc
  123. regex: \"""
  124. next : \qqdoc
  125. * token: \string
  126. regex: \'
  127. next : \qstring
  128. * token: \string
  129. regex: \"
  130. next : \qqstring
  131. * token: \string
  132. regex: \`
  133. next : \js
  134. * token: \string
  135. regex: '<\\['
  136. next : \words
  137. * token: \string.regex
  138. regex: \//
  139. next : \heregex
  140. * token: \string.regex
  141. regex: //
  142. /(?: [^ [ / \n \\ ]*
  143. (?: (?: \\.
  144. | \[ [^\]\n\\]* (?:\\.[^\]\n\\]*)* \]
  145. ) [^ [ / \n \\ ]*
  146. )*
  147. )/ [gimy$]{0,4}
  148. //$
  149. next : \key
  150. * token: \constant.numeric
  151. regex: '(?:0x[\\da-fA-F][\\da-fA-F_]*
  152. |(?:[2-9]|[12]\\d|3[0-6])r[\\da-zA-Z][\\da-zA-Z_]*
  153. |(?:\\d[\\d_]*(?:\\.\\d[\\d_]*)?|\\.\\d[\\d_]*)
  154. (?:e[+-]?\\d[\\d_]*)?[\\w$]*)'
  155. * token: \lparen
  156. regex: '[({[]'
  157. * token: \rparen
  158. regex: '[)}\\]]'
  159. next : \key
  160. * token: \keyword.operator
  161. regex: \\\S+
  162. * token: \text
  163. regex: \\\s+
  164. heregex:
  165. * token: \string.regex
  166. regex: '.*?//[gimy$?]{0,4}'
  167. next : \start
  168. * token: \string.regex
  169. regex: '\\s*#{'
  170. * token: \comment.regex
  171. regex: '\\s+(?:#.*)?'
  172. * token: \string.regex
  173. regex: '\\S+'
  174. key:
  175. * token: \keyword.operator
  176. regex: '[.?@!]+'
  177. * token: \identifier
  178. regex: identifier
  179. next : \start
  180. * token: \text
  181. regex: '.'
  182. next : \start
  183. comment:
  184. * token: \comment.doc
  185. regex: '.*?\\*/'
  186. next : \start
  187. * token: \comment.doc
  188. regex: '.+'
  189. qdoc:
  190. token: \string
  191. regex: ".*?'''"
  192. next : \key
  193. stringfill
  194. qqdoc:
  195. token: \string
  196. regex: '.*?"""'
  197. next : \key
  198. stringfill
  199. qstring:
  200. token: \string
  201. regex: /[^\\']*(?:\\.[^\\']*)*'/$
  202. next : \key
  203. stringfill
  204. qqstring:
  205. token: \string
  206. regex: /[^\\"]*(?:\\.[^\\"]*)*"/$
  207. next : \key
  208. stringfill
  209. js:
  210. token: \string
  211. regex: /[^\\`]*(?:\\.[^\\`]*)*`/$
  212. next : \key
  213. stringfill
  214. words:
  215. token: \string
  216. regex: '.*?\\]>'
  217. next : \key
  218. stringfill
  219. # for optimization, precompile the regexps
  220. for idx, r of Rules
  221. if Array.isArray r
  222. for rr, i in r
  223. if rr.regex then Rules[idx][i].regex = new RegExp '^'+rr.regex
  224. else if r.regex then Rules[idx].regex = new RegExp '^'+r.regex
  225. CodeMirror.defineMIME 'text/x-livescript', 'livescript'