swift.js 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  2. // Distributed under an MIT license: http://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")
  6. mod(require("../../lib/codemirror"))
  7. else if (typeof define == "function" && define.amd)
  8. define(["../../lib/codemirror"], mod)
  9. else
  10. mod(CodeMirror)
  11. })(function(CodeMirror) {
  12. "use strict"
  13. function wordSet(words) {
  14. var set = {}
  15. for (var i = 0; i < words.length; i++) set[words[i]] = true
  16. return set
  17. }
  18. var keywords = wordSet(["_","var","let","class","enum","extension","import","protocol","struct","func","typealias","associatedtype",
  19. "open","public","internal","fileprivate","private","deinit","init","new","override","self","subscript","super",
  20. "convenience","dynamic","final","indirect","lazy","required","static","unowned","unowned(safe)","unowned(unsafe)","weak","as","is",
  21. "break","case","continue","default","else","fallthrough","for","guard","if","in","repeat","switch","where","while",
  22. "defer","return","inout","mutating","nonmutating","catch","do","rethrows","throw","throws","try","didSet","get","set","willSet",
  23. "assignment","associativity","infix","left","none","operator","postfix","precedence","precedencegroup","prefix","right",
  24. "Any","AnyObject","Type","dynamicType","Self","Protocol","__COLUMN__","__FILE__","__FUNCTION__","__LINE__"])
  25. var definingKeywords = wordSet(["var","let","class","enum","extension","import","protocol","struct","func","typealias","associatedtype","for"])
  26. var atoms = wordSet(["true","false","nil","self","super","_"])
  27. var types = wordSet(["Array","Bool","Character","Dictionary","Double","Float","Int","Int8","Int16","Int32","Int64","Never","Optional","Set","String",
  28. "UInt8","UInt16","UInt32","UInt64","Void"])
  29. var operators = "+-/*%=|&<>~^?!"
  30. var punc = ":;,.(){}[]"
  31. var binary = /^\-?0b[01][01_]*/
  32. var octal = /^\-?0o[0-7][0-7_]*/
  33. var hexadecimal = /^\-?0x[\dA-Fa-f][\dA-Fa-f_]*(?:(?:\.[\dA-Fa-f][\dA-Fa-f_]*)?[Pp]\-?\d[\d_]*)?/
  34. var decimal = /^\-?\d[\d_]*(?:\.\d[\d_]*)?(?:[Ee]\-?\d[\d_]*)?/
  35. var identifier = /^\$\d+|(`?)[_A-Za-z][_A-Za-z$0-9]*\1/
  36. var property = /^\.(?:\$\d+|(`?)[_A-Za-z][_A-Za-z$0-9]*\1)/
  37. var instruction = /^\#[A-Za-z]+/
  38. var attribute = /^@(?:\$\d+|(`?)[_A-Za-z][_A-Za-z$0-9]*\1)/
  39. //var regexp = /^\/(?!\s)(?:\/\/)?(?:\\.|[^\/])+\//
  40. function tokenBase(stream, state, prev) {
  41. if (stream.sol()) state.indented = stream.indentation()
  42. if (stream.eatSpace()) return null
  43. var ch = stream.peek()
  44. if (ch == "/") {
  45. if (stream.match("//")) {
  46. stream.skipToEnd()
  47. return "comment"
  48. }
  49. if (stream.match("/*")) {
  50. state.tokenize.push(tokenComment)
  51. return tokenComment(stream, state)
  52. }
  53. }
  54. if (stream.match(instruction)) return "builtin"
  55. if (stream.match(attribute)) return "attribute"
  56. if (stream.match(binary)) return "number"
  57. if (stream.match(octal)) return "number"
  58. if (stream.match(hexadecimal)) return "number"
  59. if (stream.match(decimal)) return "number"
  60. if (stream.match(property)) return "property"
  61. if (operators.indexOf(ch) > -1) {
  62. stream.next()
  63. return "operator"
  64. }
  65. if (punc.indexOf(ch) > -1) {
  66. stream.next()
  67. stream.match("..")
  68. return "punctuation"
  69. }
  70. if (ch == '"' || ch == "'") {
  71. stream.next()
  72. var tokenize = tokenString(ch)
  73. state.tokenize.push(tokenize)
  74. return tokenize(stream, state)
  75. }
  76. if (stream.match(identifier)) {
  77. var ident = stream.current()
  78. if (types.hasOwnProperty(ident)) return "variable-2"
  79. if (atoms.hasOwnProperty(ident)) return "atom"
  80. if (keywords.hasOwnProperty(ident)) {
  81. if (definingKeywords.hasOwnProperty(ident))
  82. state.prev = "define"
  83. return "keyword"
  84. }
  85. if (prev == "define") return "def"
  86. return "variable"
  87. }
  88. stream.next()
  89. return null
  90. }
  91. function tokenUntilClosingParen() {
  92. var depth = 0
  93. return function(stream, state, prev) {
  94. var inner = tokenBase(stream, state, prev)
  95. if (inner == "punctuation") {
  96. if (stream.current() == "(") ++depth
  97. else if (stream.current() == ")") {
  98. if (depth == 0) {
  99. stream.backUp(1)
  100. state.tokenize.pop()
  101. return state.tokenize[state.tokenize.length - 1](stream, state)
  102. }
  103. else --depth
  104. }
  105. }
  106. return inner
  107. }
  108. }
  109. function tokenString(quote) {
  110. return function(stream, state) {
  111. var ch, escaped = false
  112. while (ch = stream.next()) {
  113. if (escaped) {
  114. if (ch == "(") {
  115. state.tokenize.push(tokenUntilClosingParen())
  116. return "string"
  117. }
  118. escaped = false
  119. } else if (ch == quote) {
  120. break
  121. } else {
  122. escaped = ch == "\\"
  123. }
  124. }
  125. state.tokenize.pop()
  126. return "string"
  127. }
  128. }
  129. function tokenComment(stream, state) {
  130. stream.match(/^(?:[^*]|\*(?!\/))*/)
  131. if (stream.match("*/")) state.tokenize.pop()
  132. return "comment"
  133. }
  134. function Context(prev, align, indented) {
  135. this.prev = prev
  136. this.align = align
  137. this.indented = indented
  138. }
  139. function pushContext(state, stream) {
  140. var align = stream.match(/^\s*($|\/[\/\*])/, false) ? null : stream.column() + 1
  141. state.context = new Context(state.context, align, state.indented)
  142. }
  143. function popContext(state) {
  144. if (state.context) {
  145. state.indented = state.context.indented
  146. state.context = state.context.prev
  147. }
  148. }
  149. CodeMirror.defineMode("swift", function(config) {
  150. return {
  151. startState: function() {
  152. return {
  153. prev: null,
  154. context: null,
  155. indented: 0,
  156. tokenize: []
  157. }
  158. },
  159. token: function(stream, state) {
  160. var prev = state.prev
  161. state.prev = null
  162. var tokenize = state.tokenize[state.tokenize.length - 1] || tokenBase
  163. var style = tokenize(stream, state, prev)
  164. if (!style || style == "comment") state.prev = prev
  165. else if (!state.prev) state.prev = style
  166. if (style == "punctuation") {
  167. var bracket = /[\(\[\{]|([\]\)\}])/.exec(stream.current())
  168. if (bracket) (bracket[1] ? popContext : pushContext)(state, stream)
  169. }
  170. return style
  171. },
  172. indent: function(state, textAfter) {
  173. var cx = state.context
  174. if (!cx) return 0
  175. var closing = /^[\]\}\)]/.test(textAfter)
  176. if (cx.align != null) return cx.align - (closing ? 1 : 0)
  177. return cx.indented + (closing ? 0 : config.indentUnit)
  178. },
  179. electricInput: /^\s*[\)\}\]]$/,
  180. lineComment: "//",
  181. blockCommentStart: "/*",
  182. blockCommentEnd: "*/",
  183. fold: "brace",
  184. closeBrackets: "()[]{}''\"\"``"
  185. }
  186. })
  187. CodeMirror.defineMIME("text/x-swift","swift")
  188. });