1 /** 2 Proof of concept of injecting environment and command line arguments. 3 4 License: 5 Boost Software License - Version 1.0 - August 17th, 2003 6 7 Permission is hereby granted, free of charge, to any person or organization 8 obtaining a copy of the software and accompanying documentation covered by 9 this license (the "Software") to use, reproduce, display, distribute, 10 execute, and transmit the Software, and to prepare derivative works of the 11 Software, and to permit third-parties to whom the Software is furnished to 12 do so, all subject to the following: 13 14 The copyright notices in the Software and this entire statement, including 15 the above license grant, this restriction and the following disclaimer, 16 must be included in all copies of the Software, in whole or in part, and 17 all derivative works of the Software, unless such copies or derivative 18 works are solely in the form of machine-executable object code generated by 19 a source language processor. 20 21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 24 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 25 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 26 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 27 DEALINGS IN THE SOFTWARE. 28 29 Authors: 30 aermicioi 31 **/ 32 module aermicioi.aedi.configurer.register.environment; 33 34 import aermicioi.aedi.configurer.register.register; 35 import aermicioi.aedi.storage.storage; 36 import aermicioi.aedi.storage.locator; 37 import aermicioi.aedi.exception; 38 39 import std.process; 40 41 auto env(T)(Storage!(Object, string) storage, string variable, T default_) { 42 import std.conv; 43 string stringValueRepresentation = environment.get(variable); 44 45 return storage.register(stringValueRepresentation !is null ? stringValueRepresentation.to!T : default_, variable); 46 } 47 48 auto env(T)(Storage!(Object, string) storage, string variable) { 49 return storage.env!T(variable, T.init); 50 } 51 52 auto envs(T)(Storage!(Object, string) storage) 53 if (is(T == struct)) { 54 55 return storage.envs(T.init); 56 } 57 58 auto envs(T)(Storage!(Object, string) storage, T init) 59 if (is(T == struct)) { 60 61 foreach (member; publicFields!T) { 62 import std.conv; 63 import std.process; 64 import std.array; 65 66 string variable = environment.get(member.replace("__", ".")); 67 68 if (variable !is null) { 69 storage.register( 70 variable.to!(typeof(getMember!(T, member))), 71 member.replace("__", ".") 72 ); 73 } else { 74 storage.register( 75 __traits(getMember, init, member), 76 member.replace("__", ".") 77 ); 78 } 79 } 80 81 return storage; 82 } 83 84 auto args(T)(Storage!(Object, string) storage, string[] args, auto ref T container) 85 if (is(T == struct)) { 86 87 import std.getopt; 88 import std.array; 89 90 string generate(T)() { 91 import std.algorithm; 92 93 string statement; 94 95 string[] members = [ publicFields!T ]; 96 sort(members); 97 98 string[] getWithCommonPrefix(string[] args) { 99 if (args.length > 0) { 100 string[] res; 101 res ~= args[0]; 102 103 foreach (arg; args[1 .. $]) { 104 if (commonPrefix(res[$ - 1], arg).length > 0) { 105 res ~= arg; 106 } 107 } 108 109 return res; 110 } 111 112 return null; 113 } 114 while (!members.empty) { 115 string[] common = getWithCommonPrefix(members); 116 if (common.length == 1) { 117 statement ~= "\"" ~ common[0][0] ~ "|" ~ common[0].replace("__", ".") ~ "\", &container." ~ common[0] ~ ","; 118 } else { 119 120 foreach (element; common) { 121 statement ~= '"' ~ element.replace("__", ".") ~ "\", &container." ~ element ~ ","; 122 } 123 } 124 125 members = members[common.length .. $]; 126 } 127 128 return statement; 129 } 130 mixin ("auto options = getopt(args, config.passThrough," ~ generate!T ~ ");"); 131 132 foreach (member; publicFields!T) { 133 storage.register( 134 __traits(getMember, container, member), 135 member.replace("__", ".") 136 ); 137 } 138 139 return storage; 140 } 141 142 auto args(T)(Storage!(Object, string) storage, string[] args) { 143 storage.args(args, T.init); 144 } 145 146 auto envs(T, R : Locator!())(R locator, string storageId = "parameters") 147 if (!is(R : Storage!(Object, string)) && is(T == struct)) { 148 import std.algorithm; 149 150 auto storage = locator.locate!(Storage!(Object, string))(storageId); 151 152 storage.envs!T; 153 return locator; 154 } 155 156 auto args(T, R : Locator!())(R locator, string[] args, T initial, string storageId = "parameters") 157 if (!is(R : Storage!(Object, string)) && is(T == struct)) { 158 import std.algorithm; 159 160 auto storage = locator.locate!(Storage!(Object, string))(storageId); 161 162 storage.args(args, initial); 163 return locator; 164 } 165 166 auto args(T, R : Locator!())(R locator, string[] args, string storageId = "parameters") 167 if (!is(R : Storage!(Object, string))) { 168 169 locator.args!T(args, T.init, storageId); 170 return locator; 171 } 172 173 private { 174 import aermicioi.util.traits; 175 import std.meta; 176 177 template publicFields(T) { 178 alias publicFieldsImpl = chain!( 179 partialPrefixed!( 180 Filter, 181 partialPrefixed!( 182 isField, 183 T 184 ) 185 ), 186 partialPrefixed!( 187 Filter, 188 partialSuffixed!( 189 partialPrefixed!( 190 isProtection, 191 T 192 ), 193 "public" 194 ) 195 ), 196 allMembers 197 ); 198 199 alias publicFields = publicFieldsImpl!T; 200 } 201 }