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