1 module nxt.casing; 2 3 import std.traits : isSomeString; 4 import nxt.string_traits : isASCIIString; 5 6 version (unittest) { 7 import std.algorithm : equal; 8 } 9 10 /** Convert string $(S s) to lower-case. 11 * 12 * String must contain ASCII characters only. 13 */ 14 auto toLowerASCII_(S)(S s) 15 if (isSomeString!S) { 16 import std.algorithm.iteration : map; 17 import std.ascii : toLower; 18 import std.traits : isNarrowString; 19 static if (isNarrowString!S) { 20 import std.utf : byUTF; 21 return s.byUTF!dchar.map!(ch => ch.toLower); 22 } 23 else 24 return t.map!(ch => ch.toLower); 25 } 26 27 /++ Return `s` lowercased if `s` is an ASCII-string, otherwise `defaultValue`. +/ 28 string toLowerIfASCII(scope const(char)[] s, string defaultValue) @safe pure nothrow { 29 if (!s.isASCIIString) 30 return defaultValue; 31 typeof(return) result; 32 result.reserve(s.length); 33 foreach (const c; s) { 34 import std.ascii : toLower; 35 result ~= c.toLower; 36 } 37 return result; 38 } 39 40 /++ Return `s` lowercased if `s` is an ASCII-string, otherwise `s`. +/ 41 inout(char)[] toLowerIfASCII(return scope inout(char)[] s) @safe pure nothrow { 42 if (!s.isASCIIString) 43 return s; 44 typeof(return) result; 45 result.reserve(s.length); 46 foreach (const c; s) { 47 import std.ascii : toLower; 48 result ~= c.toLower; 49 } 50 return result; 51 } 52 53 /// 54 @safe pure /*TODO: nothrow @nogc*/ unittest { 55 assert("Lasse".toLowerIfASCII("Lasse").equal("lasse")); 56 assert("Åberg".toLowerIfASCII("Åberg").equal("Åberg")); 57 assert("Lasse".toLowerIfASCII.equal("lasse")); 58 assert("Åberg".toLowerIfASCII.equal("Åberg")); 59 } 60 61 /** Convert string $(S s) to lower-case. 62 * 63 * String may contain Unicode characters. 64 */ 65 auto toLowerUnicode(S)(S s) 66 if (isSomeString!S) { 67 import std.algorithm.iteration : map; 68 import std.uni : toLower; 69 import std.traits : isNarrowString; 70 /+ TODO: functionize +/ 71 static if (isNarrowString!S) { 72 import std.utf : byUTF; 73 return s.byUTF!dchar.map!(ch => ch.toLower); 74 } 75 else 76 return t.map!(ch => ch.toLower); 77 } 78 79 /// 80 @safe pure /*TODO: nothrow @nogc*/ unittest { 81 assert("Lasse".toLowerUnicode.equal("lasse")); 82 assert("Åberg".toLowerUnicode.equal("åberg")); 83 } 84 85 /** Convert D-style camel-cased string $(S s) to lower-cased words. 86 */ 87 auto camelCasedToLower(S)(S s) 88 if (isSomeString!S) { 89 import std.algorithm.iteration : map; 90 import std.ascii : isUpper; // D symbol names can only be in ASCII 91 /+ TODO: Instead of this add std.ascii.as[Lower|Upper]Case and import std.ascii.asLowerCase +/ 92 import std.uni : asLowerCase; 93 import nxt.slicing : preSlicer; 94 return s.preSlicer!isUpper.map!asLowerCase; 95 } 96 97 /// 98 pure @safe unittest { 99 auto x = "doThis".camelCasedToLower; 100 assert(x.front.equal("do")); 101 x.popFront(); 102 assert(x.front.equal("this")); 103 } 104 105 /** Convert D-Style camel-cased string $(S s) to space-separated lower-cased words. 106 */ 107 auto camelCasedToLowerSpaced(S, Separator)(S s, const Separator separator = " ") 108 if (isSomeString!S) { 109 import std.algorithm.iteration : joiner; 110 return camelCasedToLower(s).joiner(separator); 111 } 112 113 /// 114 pure @safe unittest { 115 assert(equal("doThis".camelCasedToLowerSpaced, 116 "do this")); 117 } 118 119 /** Convert enumeration value (enumerator) $(D t) to a range chars. 120 */ 121 auto toLowerSpacedChars(T, Separator)(const T t, 122 const Separator separator = " ") 123 if (is(T == enum)) { 124 import nxt.enum_ex : toStringFromEnumWithConsecutiveAliases; 125 return t.toStringFromEnumWithConsecutiveAliases 126 .camelCasedToLowerSpaced(separator); 127 } 128 129 /// 130 pure @safe unittest { 131 enum Things { isUri, isLink } 132 assert(Things.isUri.toLowerSpacedChars.equal("is uri")); 133 assert(Things.isLink.toLowerSpacedChars.equal("is link")); 134 } 135 136 /// 137 pure @safe unittest { 138 enum Things { isURI, isLink } 139 auto r = Things.isURI.toLowerSpacedChars; 140 alias R = typeof(r); 141 import std.range.primitives : ElementType; 142 alias E = ElementType!R; 143 static assert(is(E == dchar)); 144 }