1 /++
2 Enum utils
3 +/
4 module sily.meta.enums;
5 
6 import std.uni: isUpper, toUpper, isAlphaNum;
7 
8 /++
9 Expands enum into single members, keeps case
10 Example:
11 ---
12 enum Elements {
13     One,
14     Two,
15     Three,
16     Four
17 }
18 mixin(expandEnum!Elements);
19 /// Is going to be turned into
20 enum {
21     One = Elements.One,
22     Two = Elements.Two,
23     Three = Elements.Three,
24     Four = Elements.Four
25 }
26 /// And can be used as single value
27 void main() {
28     import std.stdio;
29     /// Both are valid
30     writeln(One);
31     writeln(Elements.One);
32 }
33 ---
34 +/
35 enum expandEnum(EnumType, string fqnEnumType = EnumType.stringof) = (){
36     string expandEnum = "enum {";
37     foreach(m;__traits(allMembers, EnumType)) {
38         expandEnum ~= m ~ " = " ~ fqnEnumType ~ "." ~ m ~ ",";
39     }
40     expandEnum  ~= "}";
41     return expandEnum;
42 }();
43 
44 /++
45 Expands enum into single members, transforms members to CAMEL_CASE with "_" on case change, see example
46 Example:
47 ---
48 enum Elements {
49     One,
50     Two,
51     Three,
52     Four,
53     FifthElement,
54     ELEMENT_FIVE,
55     ElementWith_Separation,
56     E1emen7Number,
57     E1emen7number,
58 }
59 mixin(expandEnumUpper!Elements);
60 /// Is going to be turned into
61 enum {
62     ONE = Elements.One,
63     TWO = Elements.Two,
64     THREE = Elements.Three,
65     FOUR = Elements.Four
66     FIFTH_ELEMENT = Elements.FifthElement,
67     ELEMENT_FIVE = Elements.ELEMENT_FIVE,
68     ELEMENT_WITH_SEPARATION = Elements.ElementWith_Separation,
69     E1EMEN7_NUMBER = Elements.E1emen7Number,
70     E1EMEN7NUMBER = Elements.E1emen7number,
71 }
72 /// And can be used as single value
73 void main() {
74     import std.stdio;
75     /// Both are valid
76     writeln(One);
77     writeln(Elements.One);
78 }
79 ---
80 +/
81 enum expandEnumUpper(EnumType, string fqnEnumType = EnumType.stringof) = (){
82     string expandEnum = "enum {";
83     foreach(string member; __traits(allMembers, EnumType)) {
84         string newMember = "";
85         bool prevUpper = false;
86         for (int i = 0; i < member.length; ++i) {
87             if (member[i].isUpper && !prevUpper && i != 0) {
88                 newMember ~= "_";
89             }
90             newMember ~= member[i].toUpper();
91             prevUpper = member[i].isUpper || !member[i].isAlphaNum;
92         }
93         expandEnum ~= newMember ~ " = " ~ fqnEnumType ~ "." ~ member ~ ",";
94     }
95     expandEnum  ~= "}";
96     return expandEnum;
97 }();