1 module workspaced.com.snippets.plain;
2 
3 import std.regex;
4 
5 import workspaced.api;
6 import workspaced.com.snippets;
7 
8 struct PlainSnippet
9 {
10 	SnippetLevel[] levels;
11 	string shortcut;
12 	string title;
13 	string snippet;
14 	string documentation;
15 	string plain;
16 }
17 
18 //dfmt off
19 static immutable PlainSnippet[] plainSnippets = [
20 
21 	// entry points
22 
23 	PlainSnippet(
24 		[SnippetLevel.global],
25 		"main",
26 		"void main(string[] args)",
27 		"void main(string[] args) {\n\t$0\n}",
28 		"Normal D entry point main function with arguments and no return value"
29 	),
30 	PlainSnippet(
31 		[SnippetLevel.global],
32 		"maini",
33 		"int main(string[] args)",
34 		"int main(string[] args) {\n\t${0:return 0;}\n}",
35 		"Normal D entry point main function with arguments and integer status return value"
36 	),
37 	PlainSnippet(
38 		[SnippetLevel.global],
39 		"mainc",
40 		"-betterC void main(int argc, const(char)** argv)",
41 		"void main(int argc, const(char)** argv) {\n\t$0\n}",
42 		"C entry point when using D with -betterC with no return value"
43 	),
44 	PlainSnippet(
45 		[SnippetLevel.global],
46 		"mainci",
47 		"-betterC int main(int argc, const(char)** argv)",
48 		"int main(int argc, const(char)** argv) {\n\t${0:return 0;}\n}",
49 		"C entry point when using D with -betterC with integer status return value"
50 	),
51 
52 	// properties
53 
54 	PlainSnippet(
55 		[SnippetLevel.global, SnippetLevel.type],
56 		"refproperty",
57 		"ref property as getter + setter",
58 		"ref ${3:auto} ${1:value}() @property { return ${2:_${1:value}}; }",
59 		"property returning a value as ref for use as getter & setter",
60 		"ref auto value() @property { return _value; }"
61 	),
62 	PlainSnippet(
63 		[SnippetLevel.global, SnippetLevel.type],
64 		"getset",
65 		"getter + setter",
66 		"void ${1:value}(${3:auto} value) @property { ${2:_${1:value}} = value; }\n" ~
67 			"${3:auto} ${1:value}() @property const { return ${2:_${1:value}}; }",
68 		"separate methods for getter and setter",
69 		"void value(auto value) @property { _value = value; }\n" ~
70 			"auto value() @property const { return _value; }"
71 	),
72 	PlainSnippet(
73 		[SnippetLevel.global, SnippetLevel.type],
74 		"get",
75 		"getter property",
76 		"${3:auto} ${1:value}() @property const { return ${2:_${1:value}}; }",
77 		"methods for a getter of any value",
78 		"auto value() @property const { return _value; }"
79 	),
80 	PlainSnippet(
81 		[SnippetLevel.global, SnippetLevel.type],
82 		"set",
83 		"setter property",
84 		"void ${1:value}(${3:auto} value) @property { ${2:_${1:value}} = value; }",
85 		"method for use as setter for any value",
86 		"void value(auto value) @property { _value = value; }"
87 	),
88 
89 	// operator overloading
90 	// todo: automatic generation of types and differences in classes
91 
92 	PlainSnippet(
93 		[SnippetLevel.type],
94 		"opUnary",
95 		"auto opUnary!(op)()",
96 		"${1:auto} opUnary(string op)() {\n\t$0\n}",
97 		"Unary operators in form of `<op>this` which only work on this object.\n\n"
98 			~ "Overloadable unary operators: `-`, `+`, `~`, `*`, `++` (pre-increment), `--` (pre-decrement)\n\n"
99 			~ "Reference: [https://dlang.org/spec/operatoroverloading.html#unary]"
100 	),
101 	PlainSnippet(
102 		[SnippetLevel.type],
103 		"opIndexUnary",
104 		"auto opIndexUnary!(op)(index)",
105 		"${1:auto} opIndexUnary(string op)(${2:size_t index}) {\n\t$0\n}",
106 		"Unary operators in form of `<op>this[index1, index2...]` which only work on this object.\n\n"
107 			~ "Valid unary operators: `-`, `+`, `~`, `*`, `++` (pre-increment), `--` (pre-decrement)\n\n"
108 			~ "Reference: [https://dlang.org/spec/operatoroverloading.html#index_unary_operators]"
109 	),
110 	PlainSnippet(
111 		[SnippetLevel.type],
112 		"opIndexUnarySlice",
113 		"auto opIndexUnary!(op)(slice)",
114 		"${1:auto} opIndexUnary(string op)($2) {\n\t$0\n}",
115 		"Unary operators in form of `<op>this[start .. end]` or `<op>this[]` which only work on this object.\n\n"
116 			~ "Valid unary operators: `-`, `+`, `~`, `*`, `++` (pre-increment), `--` (pre-decrement)\n\n"
117 			~ "The argument for this function is either empty to act on an entire slice like `<op>this[]` or a "
118 				~ "helper object returned by `opSlice`.\n\n"
119 			~ "Reference: [https://dlang.org/spec/operatoroverloading.html#slice_unary_operators]"
120 	),
121 	PlainSnippet(
122 		[SnippetLevel.type],
123 		"opSliceUnary",
124 		"auto opSliceUnary!(op)(slice)",
125 		"${1:auto} opSliceUnary(string op)(${2:size_t start, size_t end}) {\n\t$0\n}",
126 		"Unary operators in form of `<op>this[start .. end]` or `<op>this[]` which only work on this object.\n\n"
127 			~ "Valid unary operators: `-`, `+`, `~`, `*`, `++` (pre-increment), `--` (pre-decrement)\n\n"
128 			~ "The argument for this function is either empty to act on an entire slice like `<op>this[]` or "
129 				~ "the start and end indices to operate on.\n\n"
130 			~ "Reference: [https://dlang.org/spec/operatoroverloading.html#slice_unary_operators]"
131 	),
132 	PlainSnippet(
133 		[SnippetLevel.type],
134 		"opCast",
135 		"T opCast!(T)()",
136 		"${1:T} opCast(${1:T})() const {\n\t$0\n}",
137 		"Explicit cast operator in form of `cast(<T>)this` which works on this object.\n\n"
138 			~ "Used when explicitly casting to any type or when implicitly casting to bool.\n\n"
139 			~ "Reference: [https://dlang.org/spec/operatoroverloading.html#cast]"
140 	),
141 	PlainSnippet(
142 		[SnippetLevel.type],
143 		"opCastBool",
144 		"bool opCast!(T : bool)()",
145 		"bool opCast(T : bool)() const {\n\t$0\n}",
146 		"Explicit cast operator in form of `cast(bool)this` or implicit boolean conversion with "
147 			~ "`!!this` or `if (this)` which works on this object.\n\n"
148 			~ "Reference: [https://dlang.org/spec/operatoroverloading.html#boolean_operators]"
149 	),
150 	PlainSnippet(
151 		[SnippetLevel.type],
152 		"opBinary",
153 		"auto opBinary(rhs)",
154 		"${1:auto} opBinary(string op, R)(${2:const R rhs}) const {\n\t$0\n}",
155 		"Binary operators in form of `this <op> rhs` which return a new instance based off this object.\n\n"
156 			~ "Overloadable binary operators: `+`, `-`, `*`, `/`, `%`, `^^`, `&`, `|`, `^`, `<<`, `>>`, `>>>`, `~`, `in`\n\n"
157 			~ "Reference: [https://dlang.org/spec/operatoroverloading.html#binary]"
158 	),
159 	PlainSnippet(
160 		[SnippetLevel.type],
161 		"opBinaryRight",
162 		"auto opBinaryRight(lhs)",
163 		"${1:auto} opBinaryRight(string op, L)(${2:const L lhs}) const {\n\t$0\n}",
164 		"Binary operators in form of `lhs <op> this` which return a new instance based off this object.\n\n"
165 			~ "Overloadable binary operators: `+`, `-`, `*`, `/`, `%`, `^^`, `&`, `|`, `^`, `<<`, `>>`, `>>>`, `~`, `in`\n\n"
166 			~ "This overload has the same importance as opBinary. It is an error if both opBinary and opBinaryRight match with "
167 				~ "the same specificity.\n\n"
168 			~ "Reference: [https://dlang.org/spec/operatoroverloading.html#binary]"
169 	),
170 	PlainSnippet(
171 		[SnippetLevel.type],
172 		"opEquals",
173 		"bool opEquals(other) in struct",
174 		"bool opEquals(R)(${1:const R other}) const {\n\t$0\n}",
175 		"Equality operators in form of `this == other` or `other == this` and also used for `!=`.\n\n"
176 			~ "Reference: [https://dlang.org/spec/operatoroverloading.html#equals]"
177 	),
178 	PlainSnippet(
179 		[SnippetLevel.type],
180 		"opEqualsClass",
181 		"bool opEquals(other) in class",
182 		"override bool opEquals(${1:Object other}) {\n\t$0\n}",
183 		"Equality operators in form of `this == other` or `other == this` and also used for `!=`.\n\n"
184 			~ "Reference: [https://dlang.org/spec/operatoroverloading.html#equals]"
185 	),
186 	PlainSnippet(
187 		[SnippetLevel.type],
188 		"opCmp",
189 		"int opCmp(other) in struct",
190 		"int opCmp(R)(${1:const R other}) const {\n\t$0\n}",
191 		"Comparision operator in form of `this.opCmp(rhs) < 0` for `<`, `<=`, `>` and `>=`.\n\n"
192 			~ "Reference: [https://dlang.org/spec/operatoroverloading.html#compare]"
193 	),
194 	PlainSnippet(
195 		[SnippetLevel.type],
196 		"opCmpClass",
197 		"int opCmp(other) in class",
198 		"override int opCmp(${1:Object other}) {\n\t$0\n}",
199 		"Comparision operator in form of `this.opCmp(rhs) < 0` for `<`, `<=`, `>` and `>=`.\n\n"
200 			~ "Reference: [https://dlang.org/spec/operatoroverloading.html#compare]"
201 	),
202 	PlainSnippet(
203 		[SnippetLevel.type],
204 		"opCall",
205 		"auto opCall(args)",
206 		"${1:auto} opCall($2) {\n\t$0\n}",
207 		"Calling operator in form of `this(args)`.\n\n"
208 			~ "Note that inside a struct this automatically disables the struct literal syntax. "
209 				~ "You need to declare a constructor which takes priority to avoid this limitation.\n\n"
210 			~ "This operator can be overloaded statically too to mimic constructors as normal calls.\n\n"
211 			~ "Reference: [https://dlang.org/spec/operatoroverloading.html#function-call]"
212 	),
213 	PlainSnippet(
214 		[SnippetLevel.type],
215 		"opAssign",
216 		"auto opAssign(value)",
217 		"auto opAssign(T)(${1:T value}) {\n\t$0\n\treturn this;\n}",
218 		"Assignment operator overload in form of `this = value`.\n\n"
219 			~ "For classes `value` may not be of the same type as `this` (identity assignment). However other values "
220 				~ "are still allowed. For structs no such restriction exists.\n\n"
221 			~ "Reference: [https://dlang.org/spec/operatoroverloading.html#assignment]"
222 	),
223 	PlainSnippet(
224 		[SnippetLevel.type],
225 		"opIndexAssign",
226 		"auto opIndexAssign(value, indices...)",
227 		"auto opIndexAssign(T)(${1:T value}, ${2:size_t index}) {\n\t${0:return value;}\n}",
228 		"Assignment operator overload in form of `this[index1, index2...] = value`.\n\n"
229 			~ "Reference: [https://dlang.org/spec/operatoroverloading.html#index_assignment_operator]"
230 	),
231 	PlainSnippet(
232 		[SnippetLevel.type],
233 		"opIndexAssignSlice",
234 		"auto opIndexAssign(value, slice)",
235 		"auto opIndexAssign(T)(${1:T value}) {\n\t${0:return value;}\n}",
236 		"Assignment operator overload in form of `this[start .. end] = value` or `this[] = value`.\n\n"
237 			~ "The argument for this function is either empty to act on an entire slice like `this[] = value` or a "
238 				~ "helper object returned by `opSlice` after the value to assign.\n\n"
239 			~ "Reference: [https://dlang.org/spec/operatoroverloading.html#index_assignment_operator]"
240 	),
241 	PlainSnippet(
242 		[SnippetLevel.type],
243 		"opSliceAssign",
244 		"auto opSliceAssign(value, slice)",
245 		"auto opSliceAssign(T)(${1:T value}, ${2:size_t start, size_t end}) {\n\t${0:return value;}\n}",
246 		"Assignment operator overload in form of `this[start .. end] = value` or `this[] = value`.\n\n"
247 			~ "The argument for this function is either empty to act on an entire slice like `this[] = value` "
248 				~ "or the start and end indices after the value to assign.\n\n"
249 			~ "Reference: [https://dlang.org/spec/operatoroverloading.html#index_assignment_operator]"
250 	),
251 	PlainSnippet(
252 		[SnippetLevel.type],
253 		"opOpAssign",
254 		"auto opOpAssign!(op)(value)",
255 		"auto opOpAssign(string op, T)(${1:T value}) {\n\t$0;\n\treturn this;\n}",
256 		"Operator assignment operator overload in form of `this op= value`.\n\n"
257 			~ "Overloadable operators: `+=`, `-=`, `*=`, `/=`, `%=`, `^^=`, `&=`, `|=`, `^=`, `<<=`, `>>=`, `>>>=`, `~=`\n\n"
258 			~ "Reference: [https://dlang.org/spec/operatoroverloading.html#op-assign]"
259 	),
260 	PlainSnippet(
261 		[SnippetLevel.type],
262 		"opIndexOpAssign",
263 		"auto opIndexOpAssign!(op)(value, index)",
264 		"auto opIndexOpAssign(string op, T)(${1:T value}, ${2:size_t index}) {\n\t${0:return value;}\n}",
265 		"Operator index assignment operator overload in form of `this[index1, index2...] op= value`.\n\n"
266 			~ "Overloadable operators: `+=`, `-=`, `*=`, `/=`, `%=`, `^^=`, `&=`, `|=`, `^=`, `<<=`, `>>=`, `>>>=`, `~=`\n\n"
267 			~ "Reference: [https://dlang.org/spec/operatoroverloading.html#index_op_assignment]"
268 	),
269 	PlainSnippet(
270 		[SnippetLevel.type],
271 		"opIndexOpAssignSlice",
272 		"auto opIndexOpAssign!(op)(value, slice)",
273 		"auto opIndexOpAssign(string op, T)(${1:T value}) {\n\t${0:return value;}\n}",
274 		"Operator index assignment operator overload in form of `this[start .. end] op= value`.\n\n"
275 			~ "Overloadable operators: `+=`, `-=`, `*=`, `/=`, `%=`, `^^=`, `&=`, `|=`, `^=`, `<<=`, `>>=`, `>>>=`, `~=`\n\n"
276 			~ "The argument for this function is either empty to act on an entire slice like `this[] op= value` or a "
277 				~ "helper object returned by `opSlice` after the value to assign.\n\n"
278 			~ "Reference: [https://dlang.org/spec/operatoroverloading.html#slice_op_assignment]"
279 	),
280 	PlainSnippet(
281 		[SnippetLevel.type],
282 		"opSliceOpAssign",
283 		"auto opSliceOpAssign!(op)(value, start, end)",
284 		"auto opSliceOpAssign(string op, T)(${1:T value}, ${2:size_t start, size_t end}) {\n\t${0:return value;}\n}",
285 		"Operator index assignment operator overload in form of `this[start .. end] op= value`.\n\n"
286 			~ "Overloadable operators: `+=`, `-=`, `*=`, `/=`, `%=`, `^^=`, `&=`, `|=`, `^=`, `<<=`, `>>=`, `>>>=`, `~=`\n\n"
287 			~ "The argument for this function is either empty to act on an entire slice like `this[] = value` "
288 				~ "or the start and end indices after the value to assign.\n\n"
289 			~ "Reference: [https://dlang.org/spec/operatoroverloading.html#slice_op_assignment]"
290 	),
291 	PlainSnippet(
292 		[SnippetLevel.type],
293 		"opIndex",
294 		"auto opIndex(index)",
295 		"${1:ref auto} opIndex(${2:size_t index}) {\n\t$0\n}",
296 		"Array index operator overload in form of `this[index1, index2...]`.\n\n"
297 			~ "Indices may specify any type and may also be the helper objects returned by opSlice.\n\n"
298 			~ "Leaving the index arguments empty means this returns a slice of the whole object. (often a shallow copy)\n\n"
299 			~ "Reference: [https://dlang.org/spec/operatoroverloading.html#array-ops]"
300 	),
301 	PlainSnippet(
302 		[SnippetLevel.type],
303 		"opSlice",
304 		"auto opSlice(index)",
305 		"${1:size_t[2]} opSlice(${2:size_t start, size_t end}) {\n\t${0:return [start, end];}\n}",
306 		"Array slice operator overload in form of `this[start .. end]`.\n\n"
307 			~ "`opSlice` returns a helper object which is used in the index methods to operate on. "
308 				~ "It does not return the value of the array slice result, use opIndex for this.\n\n"
309 			~ "This snippet defines an overload for any dimension of the array (any comma count), "
310 				~ "use `opSliceN` for any dimensionality.\n\n"
311 			~ "Reference: [https://dlang.org/spec/operatoroverloading.html#array-ops]"
312 	),
313 	PlainSnippet(
314 		[SnippetLevel.type],
315 		"opSliceN",
316 		"auto opSlice!(n)(index)",
317 		"${1:size_t[2]} opSlice(size_t dim : ${2:0})(${3:size_t start, size_t end}) {\n\t${0:return [start, end];}\n}",
318 		"Array slice operator overload in form of `this[start .. end]`.\n\n"
319 			~ "`opSlice` returns a helper object which is used in the index methods to operate on. "
320 				~ "It does not return the value of the array slice result, use opIndex for this.\n\n"
321 			~ "This snippet defines an overload for n-th dimension of the array, meaning this is the "
322 				~ "`n`th value in the comma separated index list, starting at n=0.\n\n"
323 			~ "Reference: [https://dlang.org/spec/operatoroverloading.html#array-ops]"
324 	),
325 	PlainSnippet(
326 		[SnippetLevel.type],
327 		"opDollar",
328 		"auto opDollar()",
329 		"${1:size_t} opDollar() {\n\t${0:return length;}\n}",
330 		"Dollar operator overload in form of `this[$]`.\n\n"
331 			~ "`opDollar` returns a the value which the dollar sign in the index call returns. "
332 				~ "Commonly this is the length of the array.\n\n"
333 			~ "This snippet defines an overload for any dimension of the array (any comma count), "
334 				~ "use `opDollarN` for any dimensionality.\n\n"
335 			~ "Reference: [https://dlang.org/spec/operatoroverloading.html#array-ops]"
336 	),
337 	PlainSnippet(
338 		[SnippetLevel.type],
339 		"opDollarN",
340 		"auto opDollar!(n)()",
341 		"${1:size_t} opDollar(size_t dim : ${2:0})() {\n\t${0:return length;}\n}",
342 		"Dollar operator overload in form of `this[$]`.\n\n"
343 			~ "`opDollar` returns a the value which the dollar sign in the index call returns. "
344 				~ "Commonly this is the length of the array.\n\n"
345 			~ "This snippet defines an overload for n-th dimension of the array, meaning this is the "
346 				~ "`n`th length in the comma separated index list, starting at n=0.\n\n"
347 			~ "Reference: [https://dlang.org/spec/operatoroverloading.html#array-ops]"
348 	),
349 	PlainSnippet(
350 		[SnippetLevel.type],
351 		"opDispatch",
352 		"auto opDispatch!(member)()",
353 		"${1:auto} opDispatch(${2:string member})() {\n\t$0\n}",
354 		"Compile-Time dynamic dispatch operator forwarding unknown member calls and properties in form of `this.member`.\n\n"
355 			~ "`opDispatch` will be executed for any method call or property access not matching another one. This should "
356 				~ "be used on special wrapper types without many other fields to avoid false calls in case of non-matching "
357 				~ "overloads. Defining this operator may also cause issues when trying to use CTFE functions with matching "
358 				~ "names.\n\n"
359 			~ "Reference: [https://dlang.org/spec/operatoroverloading.html#dispatch]"
360 	),
361 	PlainSnippet(
362 		[SnippetLevel.type],
363 		"opApply",
364 		"int opApply(dg)",
365 		"int opApply(scope int delegate(${1:ref Item}) ${2:dg}) {\n"
366 			~ "\tint result = 0;\n"
367 			~ "\n"
368 			~ "\t${3:foreach (item; array)} {\n"
369 			~ "\t\tresult = dg(item);\n"
370 			~ "\t\tif (result)\n"
371 			~ "\t\t\tbreak;\n"
372 			~ "\t}\n"
373 			~ "\n"
374 			~ "\treturn result;\n"
375 			~ "}",
376 		"Explicit foreach overload when calling `foreach (items...; this)`.\n\n"
377 			~ "Note that you can also implement this functionality through a forward range."
378 				~ "`opApply` has higher precedence over range functionality.\n\n"
379 			~ "Reference: [https://dlang.org/spec/statement.html#foreach_over_struct_and_classes]"
380 	),
381 	PlainSnippet(
382 		[SnippetLevel.type],
383 		"opApplyReverse",
384 		"int opApplyReverse(dg)",
385 		"int opApplyReverse(scope int delegate(${1:ref Item}) ${2:dg}) {\n"
386 			~ "\tint result = 0;\n"
387 			~ "\n"
388 			~ "\t${3:foreach_reverse (item; array)} {\n"
389 			~ "\t\tresult = dg(item);\n"
390 			~ "\t\tif (result)\n"
391 			~ "\t\t\tbreak;\n"
392 			~ "\t}\n"
393 			~ "\n"
394 			~ "\treturn result;\n"
395 			~ "}",
396 		"Explicit foreach overload when calling `foreach_reverse (items...; this)`.\n\n"
397 			~ "Note that you can also implement this functionality through a backward range. "
398 				~ "`opApplyReverse` has higher precedence over range functionality.\n\n"
399 			~ "Reference: [https://dlang.org/spec/statement.html#foreach_over_struct_and_classes]"
400 	),
401 
402 	// Exception snippets
403 
404 	PlainSnippet(
405 		[SnippetLevel.global, SnippetLevel.type],
406 		"Exception",
407 		"class MyException : Exception",
408 		"class ${1:MyException} : ${2:Exception} {\n"
409 			~ "\tthis(${3:string msg, string file = __FILE__, size_t line = __LINE__, Throwable nextInChain = null}) pure nothrow @nogc @safe {\n"
410 			~ "\t\tsuper(${4:msg, file, line, nextInChain});\n"
411 			~ "\t}\n"
412 			~ "}\n$0",
413 		"Class extending Exception. Use this for recoverable errors that may be catched in the application.\n\n"
414 			~ "Reference: [https://dlang.org/phobos/object.html#.Exception]"
415 	),
416 	PlainSnippet(
417 		[SnippetLevel.global, SnippetLevel.type],
418 		"Error",
419 		"class MyError : Error",
420 		"class ${1:MyError} : ${2:Error} {\n"
421 			~ "\tthis(${3:string msg, Throwable nextInChain = null}) pure nothrow @nogc @safe {\n"
422 			~ "\t\tsuper(${4:msg, nextInChain});\n"
423 			~ "\t}\n"
424 			~ "}\n$0",
425 		"Class extending Error. Use this for unrecoverable errors that applications should not catch.\n\n"
426 			~ "Reference: [https://dlang.org/phobos/object.html#.Exception]"
427 	),
428 
429 	// Builtin Types (keywords)
430 	PlainSnippet(
431 		[SnippetLevel.global, SnippetLevel.type, SnippetLevel.method],
432 		"import",
433 		"import module",
434 		"import ${1:std};\n$0",
435 		"Imports a module given a name.\n\nReference: [https://dlang.org/spec/module.html#import-declaration]"
436 	),
437 	PlainSnippet(
438 		[SnippetLevel.global, SnippetLevel.type, SnippetLevel.method],
439 		"class",
440 		"class MyClass",
441 		"class ${1:MyClass} {\n\t$0\n}",
442 		"Defines a simple class type.\n\nReference: [https://dlang.org/spec/class.html]"
443 	),
444 	PlainSnippet(
445 		[SnippetLevel.global, SnippetLevel.type, SnippetLevel.method],
446 		"interface",
447 		"interface MyInterface",
448 		"interface ${1:MyInterface} {\n\t$0\n}",
449 		"Defines a simple interface type.\n\nReference: [https://dlang.org/spec/interface.html]"
450 	),
451 	PlainSnippet(
452 		[SnippetLevel.global, SnippetLevel.type, SnippetLevel.method],
453 		"struct",
454 		"struct MyStruct",
455 		"struct ${1:MyStruct} {\n\t$0\n}",
456 		"Defines a simple struct type.\n\nReference: [https://dlang.org/spec/struct.html]"
457 	),
458 	PlainSnippet(
459 		[SnippetLevel.global, SnippetLevel.type, SnippetLevel.method],
460 		"union",
461 		"union MyUnion",
462 		"union ${1:MyUnion} {\n\t$0\n}",
463 		"Defines a simple union type.\n\nReference: [https://dlang.org/spec/struct.html]"
464 	),
465 	PlainSnippet(
466 		[SnippetLevel.global, SnippetLevel.type, SnippetLevel.method],
467 		"template",
468 		"template MyTemplate()",
469 		"template ${1:MyTemplate}($2) {\n\t$0\n}",
470 		"Defines a simple union type.\n\nReference: [https://dlang.org/spec/struct.html]"
471 	),
472 	PlainSnippet(
473 		[SnippetLevel.global, SnippetLevel.type, SnippetLevel.method],
474 		"enums",
475 		"enum MyEnum { ... }",
476 		"enum ${1:MyEnum} {\n\t${0:init,}\n}",
477 		"Defines a simple enumeration.\n\nReference: [https://dlang.org/spec/enum.html]"
478 	),
479 	PlainSnippet(
480 		[SnippetLevel.global, SnippetLevel.type, SnippetLevel.method],
481 		"enumv",
482 		"enum EnumValue = ...",
483 		"enum ${1:EnumValue} = $2;\n$0",
484 		"Defines a simple compile time constant using enum.\n\nReference: [https://dlang.org/spec/enum.html#manifest_constants]"
485 	),
486 
487 	// Types using phobos or some code idioms
488 	PlainSnippet(
489 		[SnippetLevel.global, SnippetLevel.type, SnippetLevel.method],
490 		"typedef",
491 		"typedef MyType : BaseType",
492 		"enum ${1:MyType} : ${2:BaseType} {\n\t${0:init = 0}\n}",
493 		"Creates a typesafe alias not allowing implicit casting from base type, but allows implicit conversion to "
494 			~ "the base type in most cases. Therefore the implicit casting works a lot like class/interface inheritance.\n\n"
495 			~ "Reference: (17.1.5) [https://dlang.org/spec/enum.html#named_enums]"
496 	),
497 	PlainSnippet(
498 		[SnippetLevel.global, SnippetLevel.type, SnippetLevel.method],
499 		"Proxy",
500 		"struct MyType { mixin Proxy }",
501 		"struct ${1:MyType} {\n\t${2:BaseType} base;\n\tmixin Proxy!(${2:BaseType});\n}",
502 		"Creates a typesafe alias not allowing implicit casting to the base type, but allows implicit conversion "
503 				~ "from the base type in most cases. Basically allows copying any base type with new properties and "
504 				~ "methods as new and separate type. Imports `std.typecons : Proxy`.\n\n"
505 			~ "Reference: [https://dlang.org/phobos/std_typecons.html#Proxy]"
506 	),
507 	PlainSnippet(
508 		[SnippetLevel.global],
509 		"IUnknown",
510 		"interface COMInterface : IUnknown",
511 		"interface ${1:COMInterface} : IUnknown {\nextern(Windows):\n\t$0\n}",
512 		"Win32 COM interface without implementation to talk to other applications.\n\n"
513 			~ "Reference: [https://wiki.dlang.org/COM_Programming]"
514 	),
515 	PlainSnippet(
516 		[SnippetLevel.global],
517 		"ComObject",
518 		"class MyObject : ComObject",
519 		"class ${1:MyObject} : ComObject {\nextern(Windows):\n\t$0\n}",
520 		"Win32 COM interface with implementation to serve to other applications.\n\n"
521 			~ "Reference: [https://wiki.dlang.org/COM_Programming]"
522 	),
523 
524 	// range methods
525 
526 	PlainSnippet(
527 		[SnippetLevel.type],
528 		"InputRange",
529 		"InputRange (popFront, empty, front)",
530 		"${1:auto} front() @property { ${2:return myElement;} }\n"
531 			~ "bool empty() @property const { ${3:return true;} }\n"
532 			~ "void popFront() { $4 }\n$0",
533 		"Implements an input range for iteration support in range functions and foreach.\n\n"
534 			~ "Functions can only iterate over an InputRange exactly one time.\n\n"
535 			~ "Reference: [https://dlang.org/phobos/std_range_primitives.html#isInputRange]"
536 	),
537 	PlainSnippet(
538 		[SnippetLevel.type],
539 		"OutputRange",
540 		"OutputRange (put)",
541 		"void put(${1:Item} item) {\n\t$2\n}\n$0",
542 		"Implements the put function which allows to put one or more items into this range.\n\n"
543 			~ "Reference: [https://dlang.org/phobos/std_range_primitives.html#isOutputRange]"
544 	),
545 	PlainSnippet(
546 		[SnippetLevel.type],
547 		"ForwardRange",
548 		"ForwardRange (InputRange, save)",
549 		"${1:auto} front() @property { ${2:return myElement;} }\n"
550 			~ "bool empty() @property const { ${3:return true;} }\n"
551 			~ "void popFront() { $4 }\n"
552 			~ "typeof(this) save() { ${5:return this;} }\n$0",
553 		"Implements a forward range for iteration support in range functions and foreach.\n\n"
554 			~ "As opposed to InputRange this supports iterating over the same range multiple times.\n\n"
555 			~ "Reference: [https://dlang.org/phobos/std_range_primitives.html#isForwardRange]"
556 	),
557 	PlainSnippet(
558 		[SnippetLevel.type],
559 		"InfiniteRange",
560 		"InfiniteRange (empty = false)",
561 		"enum bool empty = false;\n$0",
562 		"Makes this range appear as infinite by adding `empty` as always `false` enum constant value.\n\n"
563 			~ "Reference: [https://dlang.org/phobos/std_range_primitives.html#isInfinite]"
564 	),
565 	PlainSnippet(
566 		[SnippetLevel.type],
567 		"BidirectionalRange",
568 		"BidirectionalRange (InputRange, back, popBack)",
569 		"${1:auto} front() @property { ${2:return myElement;} }\n"
570 			~ "${1:auto} back() @property { ${3:return myElement;} }\n"
571 			~ "bool empty() @property const { ${4:return true;} }\n"
572 			~ "void popFront() { $5 }\n"
573 			~ "void popBack() { $6 }\n$0",
574 		"Implements a bidirectional range for iteration support in range functions, foreach and foreach_reverse.\n\n"
575 			~ "Reference: [https://dlang.org/phobos/std_range_primitives.html#isBidirectionalRange]"
576 	),
577 	PlainSnippet(
578 		[SnippetLevel.type],
579 		"RandomAccessRange",
580 		"RandomAccessRange (BidirectionalRange, opIndex, length)",
581 		"${1:auto} front() @property { ${2:return myElement;} }\n"
582 			~ "${1:auto} back() @property { ${3:return myElement;} }\n"
583 			~ "bool empty() @property const { ${4:return true;} }\n"
584 			~ "void popFront() { $5 }\n"
585 			~ "void popBack() { $6 }\n"
586 			~ "ref ${1:auto} opIndex(${7:size_t index}) { $8 }\n"
587 			~ "size_t length() { $9 }\n"
588 			~ "alias opDollar = length;$0",
589 		"Implements a bidirectional range with random access indexing support for full array emulation.\n\n"
590 			~ "Reference: [https://dlang.org/phobos/std_range_primitives.html#isBidirectionalRange]"
591 	),
592 	PlainSnippet(
593 		[SnippetLevel.type],
594 		"RandomAccessRangeInf",
595 		"RandomAccessRange (InfiniteForwardRange, opIndex)",
596 		"${1:auto} front() @property { ${2:return myElement;} }\n"
597 			~ "enum bool empty = false;\n"
598 			~ "void popFront() { $3 }\n"
599 			~ "${1:auto} opIndex(${4:size_t index}) { $5 }\n$0",
600 		"Implements an infinite forward range with random access indexing support.\n\n"
601 			~ "Reference: [https://dlang.org/phobos/std_range_primitives.html#isBidirectionalRange]"
602 	),
603 ];
604 //dfmt on
605 
606 class PlainSnippetProvider : SnippetProvider
607 {
608 	protected Snippet[][SnippetLevel] prebuilt;
609 
610 	this()
611 	{
612 		foreach (s; plainSnippets)
613 		{
614 			Snippet built;
615 			built.providerId = typeid(this).name;
616 			built.title = s.title;
617 			built.shortcut = s.shortcut;
618 			built.documentation = s.documentation;
619 			built.snippet = s.snippet;
620 			built.plain = s.plain.length ? s.plain
621 				: s.snippet.replaceAll(ctRegex!`\$(\d+|[A-Z_]+|\{.*?\})`, "");
622 			built.resolved = true;
623 
624 			foreach (level; s.levels)
625 				prebuilt[level] ~= built;
626 		}
627 	}
628 
629 	Future!(Snippet[]) provideSnippets(scope const WorkspaceD.Instance instance,
630 			scope const(char)[] file, scope const(char)[] code, int position, const SnippetInfo info)
631 	{
632 		Snippet[] ret;
633 		if (auto p = info.level in prebuilt)
634 			ret = *p;
635 		return Future!(Snippet[]).fromResult(ret);
636 	}
637 
638 	Future!Snippet resolveSnippet(scope const WorkspaceD.Instance instance,
639 			scope const(char)[] file, scope const(char)[] code, int position,
640 			const SnippetInfo info, Snippet snippet)
641 	{
642 		snippet.resolved = true;
643 		return Future!Snippet.fromResult(snippet);
644 	}
645 }