1 module workspaced.com.snippets.smart; 2 3 import workspaced.api; 4 import workspaced.com.snippets; 5 6 import std.conv; 7 8 class SmartSnippetProvider : SnippetProvider 9 { 10 Future!(Snippet[]) provideSnippets(scope const WorkspaceD.Instance instance, 11 scope const(char)[] file, scope const(char)[] code, int position, const SnippetInfo info) 12 { 13 if (info.loopScope.supported) 14 { 15 Snippet[] res; 16 if (info.loopScope.numItems > 1) 17 { 18 res ~= ndForeach(info.loopScope.numItems, info.loopScope.iterator); 19 res ~= simpleForeach(); 20 res ~= stringIterators(); 21 } 22 else if (info.loopScope.stringIterator) 23 { 24 res ~= simpleForeach(); 25 res ~= stringIterators(info.loopScope.iterator); 26 } 27 else 28 { 29 res ~= simpleForeach(info.loopScope.iterator, info.loopScope.type); 30 res ~= stringIterators(); 31 } 32 return Future!(Snippet[]).fromResult(res); 33 } 34 else 35 return Future!(Snippet[]).fromResult(null); 36 } 37 38 Future!Snippet resolveSnippet(scope const WorkspaceD.Instance instance, 39 scope const(char)[] file, scope const(char)[] code, int position, 40 const SnippetInfo info, Snippet snippet) 41 { 42 return Future!Snippet.fromResult(snippet); 43 } 44 45 Snippet ndForeach(int n, string name = null) 46 { 47 Snippet ret; 48 ret.providerId = typeid(this).name; 49 ret.id = "nd"; 50 ret.title = "foreach over " ~ n.to!string ~ " keys"; 51 if (name.length) 52 ret.title ~= " (over " ~ name ~ ")"; 53 ret.shortcut = "foreach"; 54 ret.documentation = "Foreach over locally defined variable with " ~ n.to!string ~ " keys."; 55 string keys; 56 if (n == 2) 57 { 58 keys = "key, value"; 59 } 60 else if (n <= 4) 61 { 62 foreach (i; 0 .. n - 1) 63 { 64 keys ~= cast(char)('i' + i) ~ ", "; 65 } 66 keys ~= "value"; 67 } 68 else 69 { 70 foreach (i; 0 .. n - 1) 71 { 72 keys ~= "k" ~ (i + 1).to!string ~ ", "; 73 } 74 keys ~= "value"; 75 } 76 77 if (name.length) 78 { 79 ret.plain = "foreach (" ~ keys ~ "; " ~ name ~ ") {\n\t\n}"; 80 ret.snippet = "foreach (${1:" ~ keys ~ "}; ${2:" ~ name ~ "}) {\n\t$0\n}"; 81 } 82 else 83 { 84 ret.plain = "foreach (" ~ keys ~ "; map) {\n\t\n}"; 85 ret.snippet = "foreach (${1:" ~ keys ~ "}; ${2:map}) {\n\t$0\n}"; 86 } 87 ret.resolved = true; 88 return ret; 89 } 90 91 Snippet simpleForeach(string name = null, string type = null) 92 { 93 Snippet ret; 94 ret.providerId = typeid(this).name; 95 ret.id = "simple"; 96 ret.title = "foreach loop"; 97 if (name.length) 98 ret.title ~= " (over " ~ name ~ ")"; 99 ret.shortcut = "foreach"; 100 ret.documentation = name.length 101 ? "Foreach over locally defined variable." : "Foreach over a variable or range."; 102 string t = type.length ? type ~ " " : null; 103 if (name.length) 104 { 105 ret.plain = "foreach (" ~ t ~ "key; " ~ name ~ ") {\n\t\n}"; 106 ret.snippet = "foreach (" ~ t ~ "${1:key}; ${2:" ~ name ~ "}) {\n\t$0\n}"; 107 } 108 else 109 { 110 ret.plain = "foreach (" ~ t ~ "key; list) {\n\t\n}"; 111 ret.snippet = "foreach (" ~ t ~ "${1:key}; ${2:list}) {\n\t$0\n}"; 112 } 113 ret.resolved = true; 114 return ret; 115 } 116 117 Snippet stringIterators(string name = null) 118 { 119 Snippet ret; 120 ret.providerId = typeid(this).name; 121 ret.id = "str"; 122 ret.title = "foreach loop"; 123 if (name.length) 124 ret.title ~= " (unicode over " ~ name ~ ")"; 125 else 126 ret.title ~= " (unicode)"; 127 ret.shortcut = "foreach_utf"; 128 ret.documentation = name.length 129 ? "Foreach over locally defined variable." : "Foreach over a variable or range."; 130 if (name.length) 131 { 132 ret.plain = "foreach (char key; " ~ name ~ ") {\n\t\n}"; 133 ret.snippet = "foreach (${1|char,wchar,dchar|} ${2:key}; ${3:" ~ name ~ "}) {\n\t$0\n}"; 134 } 135 else 136 { 137 ret.plain = "foreach (char key; str) {\n\t\n}"; 138 ret.snippet = "foreach (${1|char,wchar,dchar|} ${2:key}; ${3:str}) {\n\t$0\n}"; 139 } 140 ret.resolved = true; 141 return ret; 142 } 143 }