swift.js 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  2. // Distributed under an MIT license: https://codemirror.net/LICENSE
  3. // Swift mode created by Michael Kaminsky https://github.com/mkaminsky11
  4. ;(function (mod) {
  5. if (typeof exports == 'object' && typeof module == 'object') mod(require('../../lib/codemirror'))
  6. else if (typeof define == 'function' && define.amd) define(['../../lib/codemirror'], mod)
  7. else mod(CodeMirror)
  8. })(function (CodeMirror) {
  9. 'use strict'
  10. function wordSet(words) {
  11. var set = {}
  12. for (var i = 0; i < words.length; i++) set[words[i]] = true
  13. return set
  14. }
  15. var keywords = wordSet([
  16. '_',
  17. 'var',
  18. 'let',
  19. 'class',
  20. 'enum',
  21. 'extension',
  22. 'import',
  23. 'protocol',
  24. 'struct',
  25. 'func',
  26. 'typealias',
  27. 'associatedtype',
  28. 'open',
  29. 'public',
  30. 'internal',
  31. 'fileprivate',
  32. 'private',
  33. 'deinit',
  34. 'init',
  35. 'new',
  36. 'override',
  37. 'self',
  38. 'subscript',
  39. 'super',
  40. 'convenience',
  41. 'dynamic',
  42. 'final',
  43. 'indirect',
  44. 'lazy',
  45. 'required',
  46. 'static',
  47. 'unowned',
  48. 'unowned(safe)',
  49. 'unowned(unsafe)',
  50. 'weak',
  51. 'as',
  52. 'is',
  53. 'break',
  54. 'case',
  55. 'continue',
  56. 'default',
  57. 'else',
  58. 'fallthrough',
  59. 'for',
  60. 'guard',
  61. 'if',
  62. 'in',
  63. 'repeat',
  64. 'switch',
  65. 'where',
  66. 'while',
  67. 'defer',
  68. 'return',
  69. 'inout',
  70. 'mutating',
  71. 'nonmutating',
  72. 'catch',
  73. 'do',
  74. 'rethrows',
  75. 'throw',
  76. 'throws',
  77. 'try',
  78. 'didSet',
  79. 'get',
  80. 'set',
  81. 'willSet',
  82. 'assignment',
  83. 'associativity',
  84. 'infix',
  85. 'left',
  86. 'none',
  87. 'operator',
  88. 'postfix',
  89. 'precedence',
  90. 'precedencegroup',
  91. 'prefix',
  92. 'right',
  93. 'Any',
  94. 'AnyObject',
  95. 'Type',
  96. 'dynamicType',
  97. 'Self',
  98. 'Protocol',
  99. '__COLUMN__',
  100. '__FILE__',
  101. '__FUNCTION__',
  102. '__LINE__',
  103. ])
  104. var definingKeywords = wordSet(['var', 'let', 'class', 'enum', 'extension', 'import', 'protocol', 'struct', 'func', 'typealias', 'associatedtype', 'for'])
  105. var atoms = wordSet(['true', 'false', 'nil', 'self', 'super', '_'])
  106. var types = wordSet([
  107. 'Array',
  108. 'Bool',
  109. 'Character',
  110. 'Dictionary',
  111. 'Double',
  112. 'Float',
  113. 'Int',
  114. 'Int8',
  115. 'Int16',
  116. 'Int32',
  117. 'Int64',
  118. 'Never',
  119. 'Optional',
  120. 'Set',
  121. 'String',
  122. 'UInt8',
  123. 'UInt16',
  124. 'UInt32',
  125. 'UInt64',
  126. 'Void',
  127. ])
  128. var operators = '+-/*%=|&<>~^?!'
  129. var punc = ':;,.(){}[]'
  130. var binary = /^\-?0b[01][01_]*/
  131. var octal = /^\-?0o[0-7][0-7_]*/
  132. var hexadecimal = /^\-?0x[\dA-Fa-f][\dA-Fa-f_]*(?:(?:\.[\dA-Fa-f][\dA-Fa-f_]*)?[Pp]\-?\d[\d_]*)?/
  133. var decimal = /^\-?\d[\d_]*(?:\.\d[\d_]*)?(?:[Ee]\-?\d[\d_]*)?/
  134. var identifier = /^\$\d+|(`?)[_A-Za-z][_A-Za-z$0-9]*\1/
  135. var property = /^\.(?:\$\d+|(`?)[_A-Za-z][_A-Za-z$0-9]*\1)/
  136. var instruction = /^\#[A-Za-z]+/
  137. var attribute = /^@(?:\$\d+|(`?)[_A-Za-z][_A-Za-z$0-9]*\1)/
  138. //var regexp = /^\/(?!\s)(?:\/\/)?(?:\\.|[^\/])+\//
  139. function tokenBase(stream, state, prev) {
  140. if (stream.sol()) state.indented = stream.indentation()
  141. if (stream.eatSpace()) return null
  142. var ch = stream.peek()
  143. if (ch == '/') {
  144. if (stream.match('//')) {
  145. stream.skipToEnd()
  146. return 'comment'
  147. }
  148. if (stream.match('/*')) {
  149. state.tokenize.push(tokenComment)
  150. return tokenComment(stream, state)
  151. }
  152. }
  153. if (stream.match(instruction)) return 'builtin'
  154. if (stream.match(attribute)) return 'attribute'
  155. if (stream.match(binary)) return 'number'
  156. if (stream.match(octal)) return 'number'
  157. if (stream.match(hexadecimal)) return 'number'
  158. if (stream.match(decimal)) return 'number'
  159. if (stream.match(property)) return 'property'
  160. if (operators.indexOf(ch) > -1) {
  161. stream.next()
  162. return 'operator'
  163. }
  164. if (punc.indexOf(ch) > -1) {
  165. stream.next()
  166. stream.match('..')
  167. return 'punctuation'
  168. }
  169. var stringMatch
  170. if ((stringMatch = stream.match(/("""|"|')/))) {
  171. var tokenize = tokenString.bind(null, stringMatch[0])
  172. state.tokenize.push(tokenize)
  173. return tokenize(stream, state)
  174. }
  175. if (stream.match(identifier)) {
  176. var ident = stream.current()
  177. if (types.hasOwnProperty(ident)) return 'variable-2'
  178. if (atoms.hasOwnProperty(ident)) return 'atom'
  179. if (keywords.hasOwnProperty(ident)) {
  180. if (definingKeywords.hasOwnProperty(ident)) state.prev = 'define'
  181. return 'keyword'
  182. }
  183. if (prev == 'define') return 'def'
  184. return 'variable'
  185. }
  186. stream.next()
  187. return null
  188. }
  189. function tokenUntilClosingParen() {
  190. var depth = 0
  191. return function (stream, state, prev) {
  192. var inner = tokenBase(stream, state, prev)
  193. if (inner == 'punctuation') {
  194. if (stream.current() == '(') ++depth
  195. else if (stream.current() == ')') {
  196. if (depth == 0) {
  197. stream.backUp(1)
  198. state.tokenize.pop()
  199. return state.tokenize[state.tokenize.length - 1](stream, state)
  200. } else --depth
  201. }
  202. }
  203. return inner
  204. }
  205. }
  206. function tokenString(openQuote, stream, state) {
  207. var singleLine = openQuote.length == 1
  208. var ch,
  209. escaped = false
  210. while ((ch = stream.peek())) {
  211. if (escaped) {
  212. stream.next()
  213. if (ch == '(') {
  214. state.tokenize.push(tokenUntilClosingParen())
  215. return 'string'
  216. }
  217. escaped = false
  218. } else if (stream.match(openQuote)) {
  219. state.tokenize.pop()
  220. return 'string'
  221. } else {
  222. stream.next()
  223. escaped = ch == '\\'
  224. }
  225. }
  226. if (singleLine) {
  227. state.tokenize.pop()
  228. }
  229. return 'string'
  230. }
  231. function tokenComment(stream, state) {
  232. var ch
  233. while (true) {
  234. stream.match(/^[^/*]+/, true)
  235. ch = stream.next()
  236. if (!ch) break
  237. if (ch === '/' && stream.eat('*')) {
  238. state.tokenize.push(tokenComment)
  239. } else if (ch === '*' && stream.eat('/')) {
  240. state.tokenize.pop()
  241. }
  242. }
  243. return 'comment'
  244. }
  245. function Context(prev, align, indented) {
  246. this.prev = prev
  247. this.align = align
  248. this.indented = indented
  249. }
  250. function pushContext(state, stream) {
  251. var align = stream.match(/^\s*($|\/[\/\*])/, false) ? null : stream.column() + 1
  252. state.context = new Context(state.context, align, state.indented)
  253. }
  254. function popContext(state) {
  255. if (state.context) {
  256. state.indented = state.context.indented
  257. state.context = state.context.prev
  258. }
  259. }
  260. CodeMirror.defineMode('swift', function (config) {
  261. return {
  262. startState: function () {
  263. return {
  264. prev: null,
  265. context: null,
  266. indented: 0,
  267. tokenize: [],
  268. }
  269. },
  270. token: function (stream, state) {
  271. var prev = state.prev
  272. state.prev = null
  273. var tokenize = state.tokenize[state.tokenize.length - 1] || tokenBase
  274. var style = tokenize(stream, state, prev)
  275. if (!style || style == 'comment') state.prev = prev
  276. else if (!state.prev) state.prev = style
  277. if (style == 'punctuation') {
  278. var bracket = /[\(\[\{]|([\]\)\}])/.exec(stream.current())
  279. if (bracket) (bracket[1] ? popContext : pushContext)(state, stream)
  280. }
  281. return style
  282. },
  283. indent: function (state, textAfter) {
  284. var cx = state.context
  285. if (!cx) return 0
  286. var closing = /^[\]\}\)]/.test(textAfter)
  287. if (cx.align != null) return cx.align - (closing ? 1 : 0)
  288. return cx.indented + (closing ? 0 : config.indentUnit)
  289. },
  290. electricInput: /^\s*[\)\}\]]$/,
  291. lineComment: '//',
  292. blockCommentStart: '/*',
  293. blockCommentEnd: '*/',
  294. fold: 'brace',
  295. closeBrackets: '()[]{}\'\'""``',
  296. }
  297. })
  298. CodeMirror.defineMIME('text/x-swift', 'swift')
  299. })