1 /** 2 * Copyright © DiamondMVC 2018 3 * License: MIT (https://github.com/DiamondMVC/emeralD/blob/master/LICENSE) 4 * Author: Jacob Jensen (bausshf) 5 */ 6 module cmd; 7 8 import std.conv : to; 9 import std.array : replace, array, split, join; 10 import std.algorithm : map, endsWith, startsWith, filter; 11 import std.stdio : File; 12 import std.file : write, append, read, isFile, mkdirRecurse, dirEntries, SpanMode, exists; 13 import std.string : indexOf; 14 import std.path : dirName; 15 import std.process : executeShell; 16 17 import meta : thisExeDir; 18 19 /** 20 * Executes an array of command-line args. 21 * Params: 22 * args = The command-line args. 23 */ 24 void executeCommands(string[] args) 25 { 26 if (!args || !args.length) 27 { 28 return; 29 } 30 31 if (args[0] == "--shell" || args[0] == "-sh") 32 { 33 if (args.length > 1) 34 { 35 executeShell(args[1 .. $].join(" ")); 36 } 37 38 return; 39 } 40 41 if (args[0] == "--remote" || args[0] == "-rm") 42 { 43 if (args.length == 4) 44 { 45 import templates; 46 47 if (args[1] == "--scaffold" || args[1] == "-sc") 48 { 49 addRemoteScaffold(args[2], args[3]); 50 } 51 else 52 { 53 addRemoteTemplate(args[1], args[2], args[3]); 54 loadRemoteTemplates(); 55 } 56 } 57 58 return; 59 } 60 61 if (args[0] == "--scaffold" || args[0] == "-sc") 62 { 63 if ((args.length == 2 || args.length == 3 || args.length == 4) && args[1] && args[1].length) 64 { 65 bool excludeScaffoldName; 66 67 foreach (arg; args.dup) 68 { 69 if (arg && arg.length && (arg == "--exclude" || arg == "-ex")) 70 { 71 excludeScaffoldName = true; 72 args = args.filter!(a => a != "--exclude" && a != "-ex").array; 73 break; 74 } 75 } 76 77 auto scaffoldTemplate = args[1]; 78 auto scaffoldPath = (args.length == 3 ? (args[2] ~ "/") : null); 79 80 if (scaffoldTemplate && scaffoldTemplate.length) 81 { 82 foreach (string item; dirEntries(thisExeDir ~ "/scaffold/" ~ scaffoldTemplate, SpanMode.depth)) 83 { 84 auto itemDir = dirName(item); 85 string dirReplace = (thisExeDir ~ "/scaffold/").replace("\\", "/"); 86 87 string dest = (item.replace("\\", "/")).replace(dirReplace, ""); 88 89 if (scaffoldPath && scaffoldPath.length) 90 { 91 dest = scaffoldPath ~ "/" ~ dest; 92 } 93 94 if (excludeScaffoldName) 95 { 96 dest = dest.replace(scaffoldTemplate ~ "/", ""); 97 } 98 99 if (!exists(dest)) 100 { 101 mkdirRecurse(dest); 102 } 103 104 if (dest.isFile) 105 { 106 write(dest, read(item)); 107 } 108 } 109 } 110 111 return; 112 } 113 114 return; 115 } 116 117 string path; 118 bool appending; 119 string root; 120 string templateName; 121 string name; 122 string[] arguments; 123 string remoteUrl; 124 string fileName; 125 126 foreach (arg; args) 127 { 128 if (!arg || !arg.length) 129 { 130 continue; 131 } 132 133 if (arg.startsWith("--path=") || arg.startsWith("-p=")) 134 { 135 auto pathEndIndex = arg.indexOf('='); 136 137 if (pathEndIndex < (arg.length - 1)) 138 { 139 path = arg[pathEndIndex + 1 .. $]; 140 } 141 } 142 else if (arg == "--append" || arg == "-a") 143 { 144 appending = true; 145 } 146 else if (arg.startsWith("--file=") || arg.startsWith("-f=")) 147 { 148 auto pathEndIndex = arg.indexOf('='); 149 150 if (pathEndIndex < (arg.length - 1)) 151 { 152 fileName = arg[pathEndIndex + 1 .. $]; 153 } 154 } 155 else 156 { 157 if (!root) 158 { 159 root = arg; 160 } 161 else if (!templateName) 162 { 163 templateName = arg; 164 } 165 else if (!name) 166 { 167 name ~= arg; 168 } 169 else 170 { 171 arguments ~= arg; 172 } 173 } 174 } 175 176 if (!root || !root.length || !templateName || !templateName.length) 177 { 178 return; 179 } 180 181 if (fileName && fileName.length) 182 { 183 fileName = fileName.replace("$1", name); 184 185 foreach (i; 0 .. arguments.length) 186 { 187 fileName = fileName.replace("$" ~ to!string(i + 2), arguments[i]); 188 } 189 } 190 191 if (templateName.endsWith(".emd")) 192 { 193 auto cmdArgs = File(thisExeDir ~ "/templates/" ~ root ~ "/" ~ templateName); 194 195 foreach (line; cmdArgs.byLine.map!(a => a.replace("\r", ""))) 196 { 197 if (!line || !line.length) 198 { 199 continue; 200 } 201 202 executeCommands(line.split(" ").map!((lineArg) 203 { 204 if (name && name.length) 205 { 206 lineArg = lineArg.replace("$1", name); 207 } 208 209 foreach (i; 0 .. arguments.length) 210 { 211 lineArg = lineArg.replace("$" ~ to!string(i + 2), arguments[i]); 212 } 213 214 return cast(string)lineArg; 215 }).array); 216 } 217 218 return; 219 } 220 221 if (!name || !name.length) 222 { 223 return; 224 } 225 226 import templates; 227 228 auto templateContent = readTemplate(root, templateName); 229 230 if (!templateContent || !templateContent.length) 231 { 232 return; 233 } 234 235 templateContent = templateContent.replace("$1", name); 236 237 foreach (i; 0 .. arguments.length) 238 { 239 templateContent = templateContent.replace("$" ~ to!string(i + 2), arguments[i]); 240 } 241 242 if (appending) 243 { 244 append(path, templateContent); 245 } 246 else 247 { 248 fileName = fileName ? fileName : name ~ templateName[templateName.indexOf('.') .. $]; 249 250 if (path) 251 { 252 path ~= "/" ~ fileName; 253 } 254 else 255 { 256 path = fileName; 257 } 258 259 write(path, templateContent); 260 } 261 }