1 module sily.getopt; 2 3 import std.algorithm : max; 4 import std.getopt : Option; 5 import std.stdio : writefln; 6 /** 7 Helper function to get std.getopt.Option 8 Params: 9 _long = Option name 10 _help = Option help 11 Returns: std.getopt.Option 12 */ 13 Option customOption(string _long, string _help) { return Option("", _long, _help, false); } 14 15 private enum bool isOptionArray(T) = is(T == Option[]); 16 private enum bool isOption(T) = is(T == Option); 17 private enum bool isString(T) = is(T == string); 18 19 /** 20 * Prints passed **Option**s and text in aligned manner on stdout, i.e: 21 * ``` 22 * A simple cli tool 23 * 24 * Usage: 25 * scli [options] [script] \ 26 * scli run [script] 27 * 28 * Options: 29 * -h, --help This help information. \ 30 * -c, --check Check syntax without running. \ 31 * --quiet Run silently (no output). 32 * 33 * Commands: 34 * run Runs script. \ 35 * compile Compiles script. 36 * ``` 37 * Can be used like: 38 * --------- 39 * printGetopt("Usage", "Options", help.options, "CustomOptions", customArray, customOption("opt", "-h")); 40 * --------- 41 * Params: 42 * S = Can be either std.getopt.Option[], std.getopt.Option or string 43 */ 44 void printGetopt(S...)(S args) { // string text, string usage, Option[] opt, 45 size_t maxLen = 0; 46 bool[] isNextOpt = []; 47 48 foreach (arg; args) { 49 alias A = typeof(arg); 50 51 static if(isOptionArray!A) { 52 foreach (it; arg) { 53 int sep = it.optShort == "" ? 0 : 2; 54 maxLen = max(maxLen, it.optShort.length + it.optLong.length + sep); 55 } 56 isNextOpt ~= true; 57 continue; 58 } else 59 static if(isOption!A) { 60 int sep = arg.optShort == "" ? 0 : 2; 61 maxLen = max(maxLen, arg.optShort.length + arg.optLong.length + sep); 62 isNextOpt ~= true; 63 continue; 64 } else 65 static if(isString!A) { 66 isNextOpt ~= false; 67 continue; 68 } 69 } 70 71 int i = 0; 72 foreach (arg; args) { 73 alias A = typeof(arg); 74 static if(isOptionArray!A) { 75 foreach (it; arg) { 76 string opts = it.optShort ~ (it.optShort == "" ? "" : ", ") ~ it.optLong; 77 writefln(" %-*s %s", maxLen, opts, it.help); 78 } 79 } else 80 static if(isOption!A) { 81 string opts = arg.optShort ~ (arg.optShort == "" ? "" : ", ") ~ arg.optLong; 82 writefln(" %-*s %s", maxLen, opts, arg.help); 83 } else 84 static if(isString!A) { 85 bool nopt = i + 1 < isNextOpt.length ? (isNextOpt[ i + 1 ]) : (false); 86 bool popt = i - 1 > 0 ? (isNextOpt[ i - 1 ]) : (false); 87 writefln((popt ? "\n" : "") ~ arg ~ (nopt ? ":" : "\n")); 88 } 89 90 ++i; 91 } 92 }