1 module util.replace; 2 //import std.metastrings; 3 import std.conv; 4 5 /** 6 Performs compile time string replacements on $(D base) 7 8 Parameters: 9 10 T = replacement specs, alternating between string to be replaced and $(D toStringNow)-able object to replace with. 11 12 Example: 13 --- 14 import std.metastrings; 15 import std.stdio; 16 17 void main() 18 { 19 string s = Replace!(q{$ret func(T)(T t){ return new $ret(t+$i); }}, 20 "$ret", "C", 21 "$i", 5000); 22 writeln(s); // "C func(T)(T t){ return new C(t+5000); }" 23 } 24 --- 25 If there is ambiguity between two substrings to replace, the longer one is preferred: 26 --- 27 enum s = Replace!("boy eats boysenberry", "boy", "girl", "boysenberry", "plum"); 28 writeln(s) // "girl eats plum" 29 --- 30 */ 31 template Replace(string base, T...) 32 { 33 import std.algorithm; 34 static assert(T.length % 2 == 0); 35 template NextAt(string base, string longest_spec, 36 size_t _at0, size_t _ti0, T...) 37 { 38 static assert(T.length % 2 == 0); 39 static if(T.length == 0) 40 { 41 static if(_at0 == -1) 42 { 43 enum size_t at = base.length; 44 enum size_t ti = -1; 45 } 46 else 47 { 48 enum at = _at0; 49 enum ti = _ti0; 50 } 51 } 52 else 53 { 54 enum size_t _at1 = countUntil(base, T[$-2]); 55 static if(_at1 < _at0 || 56 _at1 == _at0 && T[$-2].length > longest_spec.length) 57 { 58 alias NextAt!(base, T[$-2], _at1, T.length-2,T[0 .. $-2]) N2; 59 } 60 else 61 { 62 alias NextAt!(base,longest_spec,_at0,_ti0,T[0 .. $-2]) N2; 63 } 64 enum at = N2.at; 65 enum ti = N2.ti; 66 } 67 } 68 69 70 alias NextAt!(base,"",-1,-1,T) N; 71 static if(N.ti == -1) 72 enum Replace = base; 73 else 74 enum Replace = base[0 .. N.at] ~ to!string(T[N.ti+1]) ~ 75 Replace!(base[N.at + T[N.ti].length .. $], T); 76 } 77