├── Comments.tmPreferences
├── LICENSE
├── README.md
├── Swift.sublime-syntax
├── package.json
└── syntax_test.swift
/Comments.tmPreferences:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | name
6 | Comments
7 | scope
8 | source.swift
9 | settings
10 |
11 | shellVariables
12 |
13 |
14 | name
15 | TM_COMMENT_START
16 | value
17 | //
18 |
19 |
20 | name
21 | TM_COMMENT_START_2
22 | value
23 | /*
24 |
25 |
26 | name
27 | TM_COMMENT_END_2
28 | value
29 | */
30 |
31 |
32 |
33 | uuid
34 | 66529EE0-35DE-11E4-8C21-0800200C9A66
35 |
36 |
37 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2019, Colin Gray
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Decent Swift Syntax
2 | ===================
3 |
4 | Uses the new 'sublime-syntax' format, which is super easy to work with.
5 |
6 | Still a work in progress. I think there's room for improvement in which symbols
7 | to include, like class and instance `var`/`let`.
8 |
--------------------------------------------------------------------------------
/Swift.sublime-syntax:
--------------------------------------------------------------------------------
1 | %YAML 1.2
2 | ---
3 | name: Swift
4 | file_extensions: [swift, swiftinterface]
5 | scope: source.swift
6 | prototype:
7 | - include: main
8 |
9 | contexts:
10 | main:
11 | ###################################################### COMMENTS
12 | - match: (//+\s+MARK:) ?(.*)
13 | scope: comment.line
14 | captures:
15 | 1: punctuation.definition.comment
16 | 2: meta.toc-list
17 | - match: (//+\s+TODO:) ?(.*)
18 | scope: comment.line
19 | captures:
20 | 1: punctuation.definition.comment
21 | 2: meta.toc-list
22 | - match: (//+\s+FIXME:) ?(.*)
23 | scope: comment.line
24 | captures:
25 | 1: punctuation.definition.comment
26 | 2: meta.toc-list
27 | - match: (//+).*(\n|$)
28 | scope: comment.line
29 | captures:
30 | 1: punctuation.definition.comment
31 | - match: (/\*)
32 | scope: punctuation.definition.comment
33 | push: comment_block
34 | ###################################################### PRECOMPILED
35 | - match: ^\s*(#)(\w+)(.*)$
36 | captures:
37 | 1: punctuation.definition.preprocessor meta.preprocessor.swift
38 | 2: punctuation.definition.preprocessor meta.preprocessor.swift
39 | ###################################################### ENUMS
40 | - match: "(?:[^\\?\\!\\)\\\"\\w]|^)(\\.[a-zA-Z]\\w*)\\("
41 | captures:
42 | 1: constant.language.enum
43 | push: enum
44 | - match: "(?<=[^\\?\\!\\)\\\"\\w]|^)(\\.[a-zA-Z]\\w*)"
45 | captures:
46 | 1: constant.language.enum
47 | ###################################################### CONSTANTS
48 | - match: \btrue\b
49 | scope: constant.language.true
50 | - match: \bfalse\b
51 | scope: constant.language.false
52 | - match: \bnil\b
53 | scope: constant.language.nil
54 | ###################################################### NUMERICS
55 | - match: \b0[XOB]
56 | scope: invalid illegal.invalid
57 | - match: '0x([[:xdigit:]][[:xdigit:]_]*)((\.\g<1>)?[pP][-+]?\d[\d_]*)?'
58 | scope: constant.numeric.hex
59 | - match: 0o[0-7][0-7_]*
60 | scope: constant.numeric.octal
61 | - match: 0b[01][01_]*
62 | scope: constant.numeric.binary
63 | - match: '(\d[\d_]*)(\.\g<1>)([eE][-+]?\g<1>)?'
64 | scope: constant.numeric.float
65 | - match: '(\d[\d_]*)([eE][-+]?\g<1>)'
66 | scope: constant.numeric.float
67 | - match: '(\d[\d_]*)'
68 | scope: constant.numeric.decimal
69 | ###################################################### TYPES
70 | # class func
71 | - match: \b(class)\s+(?=func)
72 | scope: meta.function storage.type.function
73 | - match: \b(enum|class|struct|protocol|extension)\s+((\w+)\s*(:)\s+(\w+))
74 | scope: entity.name.type
75 | captures:
76 | 1: keyword.entity
77 | 2: entity.name.type
78 | 3: support.class
79 | 4: keyword.operator
80 | 5: support.class
81 | - match: \b(enum|class|struct|protocol|extension)\s+(\w+)
82 | scope: entity.name.type
83 | captures:
84 | 1: keyword.entity
85 | 2: entity.name.type support.class
86 | ###################################################### KEYWORDS
87 | - match: \b(self|super)\b
88 | scope: keyword.variable
89 | - match: \b_\b
90 | scope: constant.language.other
91 | - match: \b(import)\b
92 | scope: keyword.other.import
93 | ###################################################### CONTROL
94 | - match: \b(if|where|else|for|in|is|as|while|switch|do|defer|repeat)\b
95 | scope: keyword.control
96 | - match: \b(break|fallthrough|guard|try|catch|throws?|rethrows|return|case|continue|default|didSet|willSet|get|set)\b
97 | scope: keyword.control
98 | - match: \b(async|await)\b
99 | scope: keyword.control
100 | - match: \b(some|any)\b
101 | scope: keyword.control
102 | - match: '#(available)\b'
103 | scope: keyword.control
104 | ###################################################### VARIABLES
105 | - match: \b(var|let|typealias|unowned)\b
106 | captures:
107 | 1: keyword.variable
108 | ###################################################### STRING
109 | - match: '"""'
110 | push: string_multiline
111 | - match: '#"'
112 | push: string_raw_1
113 | - match: '##"'
114 | push: string_raw_2
115 | - match: '###"'
116 | push: string_raw_3
117 | - match: '"'
118 | push: string_double
119 | ###################################################### MODIFIERS
120 | - match: \b(weak|lazy|mutating|convenience|associatedtype|public|internal|private|fileprivate|final|static|override|required|prefix|postfix|infix|indirect|inout|open)\b
121 | scope: storage.modifier
122 | - match: '@\w+'
123 | scope: storage.type.decorator
124 | ###################################################### SUPPORT
125 | # "system" classes:
126 | - match: \b([A-Z]{2})\w+
127 | scope: support.class
128 | - match: \b(String|Array|Int\d*|Float|Double)\w+
129 | scope: support.class
130 | # user classes:
131 | - match: \b([A-Z])\w*
132 | scope: support.class
133 | ###################################################### FUNCTIONS
134 | - match: '\b(func|operator)\s+(\w+)\s*\('
135 | captures:
136 | 1: storage.type.function
137 | 2: entity.name.function variable.function
138 | push: function_params
139 | - match: '\b(deinit|init(\??))\s*\('
140 | captures:
141 | 1: storage.type.function
142 | 2: entity.name.function variable.function
143 | push: function_params
144 | - match: \b(func)\s+(\w+)
145 | captures:
146 | 1: storage.type.function
147 | 2: entity.name.function variable.function
148 | - match: \b(func|deinit|init(\??))\b
149 | scope: entity.name.type storage.type.function
150 | ###################################################### VARIABLES
151 | - match: '(\w+):'
152 | captures:
153 | 1: variable.parameter
154 | - match: '\b\w+'
155 | scope: ''
156 | - match: '[-+=<>^$#@!~*\\|&?\/%.]*'
157 | scope: keyword.operator
158 | - match: '\('
159 | push: paren_expr
160 | ######################################################
161 | comment_block:
162 | - meta_scope: comment.block
163 | - match: /\*
164 | push: comment_block
165 | - match: \*/
166 | pop: true
167 | function_params:
168 | - include: main
169 | - meta_scope: meta.function meta.toc-list
170 | - match: '\)'
171 | pop: true
172 | string_multiline:
173 | - meta_scope: string.quoted.double string.quoted.multiline
174 | - match: \\\(
175 | scope: punctuation.section.embedded
176 | set: embedded_multiline
177 | - match: \\[ntr0\\"']
178 | scope: constant.character.escape.c
179 | - match: \\u{[[:xdigit:]]{1,8}}
180 | scope: constant.character.escape.c
181 | - match: \\\n
182 | scope: constant.character.escape.c
183 | - match: \\
184 | scope: invalid.illegal
185 | - match: '"""'
186 | pop: true
187 | string_raw_1:
188 | - meta_scope: string.quoted.double string.quoted.raw
189 | - match: \\\(
190 | scope: punctuation.section.embedded
191 | set: embedded_raw_1
192 | - match: \\[ntr0\\"']
193 | scope: constant.character.escape.c
194 | - match: \\u{[[:xdigit:]]{1,8}}
195 | scope: constant.character.escape.c
196 | - match: \\\n
197 | scope: constant.character.escape.c
198 | - match: \\
199 | scope: invalid.illegal
200 | - match: '"#'
201 | pop: true
202 | string_raw_2:
203 | - meta_scope: string.quoted.double string.quoted.raw
204 | - match: \\\(
205 | scope: punctuation.section.embedded
206 | set: embedded_raw_2
207 | - match: \\[ntr0\\"']
208 | scope: constant.character.escape.c
209 | - match: \\u{[[:xdigit:]]{1,8}}
210 | scope: constant.character.escape.c
211 | - match: \\\n
212 | scope: constant.character.escape.c
213 | - match: \\
214 | scope: invalid.illegal
215 | - match: '"##'
216 | pop: true
217 | string_raw_3:
218 | - meta_scope: string.quoted.double string.quoted.raw
219 | - match: \\\(
220 | scope: punctuation.section.embedded
221 | set: embedded_raw_3
222 | - match: \\[ntr0\\"']
223 | scope: constant.character.escape.c
224 | - match: \\u{[[:xdigit:]]{1,8}}
225 | scope: constant.character.escape.c
226 | - match: \\\n
227 | scope: constant.character.escape.c
228 | - match: \\
229 | scope: invalid.illegal
230 | - match: '"###'
231 | pop: true
232 | string_double:
233 | - meta_scope: string.quoted.double
234 | - match: \\\(
235 | scope: punctuation.section.embedded
236 | set: embedded_double
237 | - match: \\[ntr0\\"']
238 | scope: constant.character.escape.c
239 | - match: \\u{[[:xdigit:]]{1,8}}
240 | # Unicode scalar escape
241 | # feels like this needs a different scope
242 | scope: constant.character.escape.c
243 | - match: \\
244 | scope: invalid.illegal
245 | - match: '"'
246 | pop: true
247 | embedded_double:
248 | - include: main
249 | - match: \(
250 | push: nested
251 | - match: \)
252 | scope: punctuation.section.embedded
253 | set: string_double
254 | embedded_multiline:
255 | - include: main
256 | - match: \(
257 | push: nested
258 | - match: \)
259 | scope: punctuation.section.embedded
260 | set: string_multiline
261 | embedded_raw_1:
262 | - include: main
263 | - match: \(
264 | push: nested
265 | - match: \)
266 | scope: punctuation.section.embedded
267 | set: string_raw_1
268 | embedded_raw_2:
269 | - include: main
270 | - match: \(
271 | push: nested
272 | - match: \)
273 | scope: punctuation.section.embedded
274 | set: string_raw_2
275 | embedded_raw_3:
276 | - include: main
277 | - match: \(
278 | push: nested
279 | - match: \)
280 | scope: punctuation.section.embedded
281 | set: string_raw_3
282 | nested:
283 | - include: main
284 | - match: \(
285 | push: nested
286 | - match: \)
287 | pop: true
288 | paren_expr:
289 | - include: main
290 | - match: '\)'
291 | pop: true
292 | enum:
293 | - meta_scope: internal.enum
294 | - include: main
295 | - match: '\)'
296 | pop: true
297 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Decent Swift Syntax",
3 | "details": "https://github.com/colinta/decent-swift-syntax",
4 | "description": "Swift language grammar that doesn't suck.",
5 | "author": "Colin T.A. Gray (colinta)",
6 | "labels": [
7 | "language syntax"
8 | ],
9 | "previous_names": [
10 | "Swift for F*ing Sublime"
11 | ],
12 | "releases": [
13 | {
14 | "tags": true,
15 | "sublime_text": ">=3084"
16 | }
17 | ]
18 | }
19 |
--------------------------------------------------------------------------------
/syntax_test.swift:
--------------------------------------------------------------------------------
1 | // SYNTAX TEST "Packages/Decent-Swift-Syntax/Swift.sublime-syntax"
2 |
3 | // comment
4 | // ^ comment.line
5 | // <- punctuation.definition.comment
6 |
7 | // MARK: testing!
8 | // ^ comment.line
9 | // ^ punctuation.definition.comment
10 | // ^ meta.toc-list
11 |
12 | /* comment */
13 | // ^comment.block
14 | /* 000 */
15 | // ^comment.block
16 | // ^ comment - constant
17 | 000 /* "string" */
18 | // <- -comment
19 | // ^comment.block
20 | // ^-string
21 |
22 | true
23 | // <- constant.language
24 | // <- constant.language.true
25 | false
26 | // <- constant.language
27 | // <- constant.language.false
28 | nil
29 | // <- constant.language
30 | // <- constant.language.nil
31 |
32 | 1.1 100.001
33 | // <- constant.numeric
34 | // <- constant.numeric.float
35 | // ^ constant.numeric
36 | // ^^^^^^^ constant.numeric.float
37 | // ^ source.swift
38 | 100
39 | // <- constant.numeric
40 | // <- constant.numeric.decimal
41 | 1_000_000
42 | // ^ constant.numeric.decimal
43 | 0xDEADBEEF
44 | // <- constant.numeric.hex
45 | // ^ constant.numeric.hex
46 | 0xGGGGG
47 | // ^ -constant.numeric.hex
48 | 0o12345670
49 | // <- constant.numeric.octal
50 | // ^ constant.numeric.octal
51 | 0o8888
52 | // ^ -constant.numeric.octal
53 | 0b01010110101
54 | // <- constant.numeric.binary
55 | // ^ constant.numeric.binary
56 | 0b22222
57 | // ^ -constant.numeric.binary
58 | word123
59 | // ^ -constant.numeric
60 |
61 | if { /**/ }
62 | // <- keyword.control
63 | where { /**/ }
64 | // <- keyword.control
65 |
66 | #if FOO
67 | // <- punctuation.definition.preprocessor
68 | #endif
69 | // ^ source.swift punctuation.definition.preprocessor meta.preprocessor.swift
70 |
71 | if a || b
72 | // <- keyword
73 | // ^ keyword.operator
74 |
75 | public func foo
76 | // <- storage.modifier
77 | // ^ storage.type
78 | // ^ storage.type.function
79 | // ^ variable
80 | // ^ entity.name.function
81 |
82 | self
83 | // <- keyword.variable
84 | super
85 | // <- keyword.variable
86 |
87 | Color
88 | // <- support.class
89 | UIColor
90 | // <- support.class
91 |
92 | enum Foo1 { case value }
93 | // <- keyword.entity
94 | // ^ support.class
95 | // ^ entity.name.type
96 | enum Foo2 : String { case value }
97 | // <- keyword.entity
98 | // ^ support.class
99 | // ^ entity.name.type
100 | // ^ support.class
101 |
102 | enum Foo3 : String {
103 | case value
104 | // ^ keyword.control
105 | }
106 |
107 | if foo {}
108 | // <- keyword.control
109 | else {}
110 | // <- keyword.control
111 | for {}
112 | // <- keyword.control
113 | while true {}
114 | // <- keyword.control
115 | // ^ constant
116 | switch foo { case .bar: }
117 | // <- keyword.control
118 | // ^ keyword.control
119 | break
120 | // <- keyword.control
121 | return
122 | // <- keyword.control
123 | case 0..0
124 | // <- keyword.control
125 | // ^ constant.numeric
126 | // ^ keyword.operator
127 | // ^ constant.numeric
128 | continue
129 | // <- keyword.control
130 | default
131 | // <- keyword.control
132 |
133 | enum Foo4
134 | // <- keyword.entity
135 | // ^ support.class
136 | enum Foo5 : Bar {}
137 | // <- keyword.entity
138 | // ^ support.class
139 | // ^ support.class
140 | enum Foo6 { indirect case foo(Foo6) }
141 | // <- keyword.entity
142 | // ^ support.class
143 | // ^ storage.modifier
144 | // ^ keyword.control
145 | // ^ support.class
146 | struct Foo7
147 | // <- keyword.entity
148 | // ^ support.class
149 | struct Foo8 : Bar
150 | // ^ -invalid
151 | // ^ -invalid
152 | // ^ support.class
153 | class Foo9
154 | // <- keyword.entity
155 | // ^ support.class
156 | class Foo10 : Bar {}
157 | // <- keyword.entity
158 | // ^ support.class
159 | // ^ support.class
160 | protocol Foo11
161 | // <- keyword.entity
162 | // ^ support.class
163 | protocol Foo12 : Bar {}
164 | // <- keyword.entity
165 | // ^ support.class
166 | // ^ support.class
167 | extension Foo13
168 | // <- keyword.entity
169 | // ^ support.class
170 | extension Foo14 : Bar
171 | // <- keyword.entity
172 | // ^ support.class
173 | // ^ keyword.operator
174 | // ^ support.class
175 |
176 | func foo()
177 | // ^ variable.function
178 | class func foo()
179 | // <- meta.function
180 | // <- storage.type.function
181 | // ^ storage.type.function
182 |
183 | func foo() { foo }
184 | // ^ variable.function
185 | // ^ meta.function
186 |
187 | func foo(abc, def: String) { foo }
188 | // ^ variable.function
189 | // ^ meta.function
190 | // ^ variable.parameter
191 |
192 | func foo(abc: inout String) { foo }
193 | // ^ variable.function
194 | // ^ variable.parameter
195 | // ^ storage.modifier
196 |
197 | "foo"
198 | // <- string
199 | // <- string.quoted
200 |
201 | "foo\"" foo
202 | // <- string
203 | // ^ constant.character.escape
204 | // ^ constant.character.escape
205 | // ^ string
206 | // ^ -string
207 |
208 | ".foo"
209 | // <- string
210 | //^ string
211 | // ^ string
212 |
213 | "foo \(bar + (foo * bar))"
214 | // <- string
215 | // ^ punctuation.section
216 | // ^ punctuation.section
217 | // ^ -string
218 | // ^ -punctuation.section
219 |
220 | """f"oo"""
221 | // <- string.quoted.multiline
222 | // ^ string.quoted
223 |
224 | """
225 | f"oo\("bar")
226 | // <- string
227 | // <- string.quoted.multiline
228 | // ^ punctuation.section.embedded
229 | // ^ string.quoted.double
230 | // ^ punctuation.section.embedded
231 | """
232 | .bar
233 | // <- constant.language.enum
234 |
235 | #"te"st"#
236 | // <- string
237 | // <- string.quoted.raw
238 | // ^ string.quoted
239 |
240 | ##"te"#st"##
241 | // <- string
242 | // <- string.quoted.raw
243 | // ^ string.quoted
244 |
245 | a = (.foo(.bar))
246 | // ^ constant.language.enum
247 | // ^ constant.language.enum
248 |
249 | .foo + .bar
250 | // <- constant.language.enum
251 | // ^ -constant.language.enum
252 | // ^ constant.language.enum
253 |
254 | a.foo + a?.bar()
255 | // <- -constant.language.enum
256 | //^ -constant.language.enum
257 | // ^ -constant.language.enum
258 |
--------------------------------------------------------------------------------