1 module nxt.getoptx; 2 3 public import std.getopt; 4 5 import std.meta; 6 import std.typecons; 7 import std.conv; 8 import std.array; 9 10 alias GetOptRslt = Tuple!(bool, "help", Option[], "options"); 11 12 GetOptRslt getoptX(T...)(ref string[] args, T opts) 13 { 14 Option[] helpMsg = getoptHelp(opts); // extract all help strings 15 16 bool helpPrinted = false; // state tells if called with "--help" 17 18 getopt(args, GetoptEx!(opts), "h|help", &helpPrinted); 19 20 GetOptRslt rslt; 21 rslt.help = helpPrinted; 22 rslt.options = helpMsg; 23 24 return rslt; 25 } 26 27 private template GetoptEx(TList...) 28 { 29 static if (TList.length) 30 { 31 static if (is(typeof(TList[0]) : config)) 32 { 33 // it's a configuration flag, lets move on 34 alias TypeTuple!(TList[0],GetoptEx!(TList[1 .. $])) GetoptEx; 35 } 36 else 37 { 38 // it's an option string, eat help string 39 alias TypeTuple!(TList[0],TList[2],GetoptEx!(TList[3 .. $])) GetoptEx; 40 } 41 } 42 else 43 { 44 alias TList GetoptEx; 45 } 46 } 47 48 alias Tuple!(string, "optShort", string, "optLong", string, "help") Option; 49 50 private Option[] getoptHelp(T...)(T opts) 51 { 52 static if (opts.length) 53 { 54 static if (is(typeof(opts[0]) : config)) 55 { 56 // it's a configuration flag, skip it 57 return getoptHelp(opts[1 .. $]); 58 } 59 else 60 { 61 // it's an option string 62 auto sp = split(opts[0], "|"); 63 Option ret; 64 if (sp.length > 1) 65 { 66 ret.optShort = "-" ~ (sp[0].length < sp[1].length ? 67 sp[0] : sp[1]); 68 ret.optLong = "--" ~ (sp[0].length > sp[1].length ? 69 sp[0] : sp[1]); 70 } 71 else 72 { 73 ret.optLong = "--" ~ sp[0]; 74 } 75 ret.help = opts[1]; 76 77 return([ret]~getoptHelp(opts[3 .. $]) ); 78 } 79 } 80 else 81 { 82 Option help; 83 help.optShort = "-h"; 84 help.optLong = "--help"; 85 help.help = "This help."; 86 return [help]; 87 } 88 } 89 90 void defaultGetoptPrinter(string text, Option[] opt) 91 { 92 import std.stdio : write, writeln, writef, writefln; 93 import std.algorithm : min, max; 94 95 writeln(text); 96 writeln(); 97 size_t ls, ll; 98 foreach (it; opt) 99 { 100 ls = max(ls, it.optShort.length); 101 ll = max(ll, it.optLong.length); 102 } 103 104 size_t argLength = ls + ll + 2; 105 size_t rest = 79 - argLength; 106 107 foreach (it; opt) 108 { 109 writef("%*s %*s ", ls, it.optShort, ll, it.optLong); 110 string helpMsg = it.help; 111 auto curLine = helpMsg[0 .. min($, rest)]; 112 write(curLine); 113 helpMsg = helpMsg[min($, rest) .. $]; 114 if (curLine.back != ' ' && !helpMsg.empty) 115 { 116 writeln('-'); 117 } 118 else 119 { 120 writeln(); 121 } 122 123 while (!helpMsg.empty) 124 { 125 curLine = helpMsg[0 .. min($, rest)]; 126 helpMsg = helpMsg[min($, rest) .. $]; 127 writef("%*s", argLength, " "); 128 write(curLine); 129 if (curLine.back != ' ' && !helpMsg.empty) 130 { 131 writeln('-'); 132 } 133 else 134 { 135 writeln(); 136 } 137 } 138 } 139 }