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