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