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