1 module cmdline.event; 2 3 import std.stdio; 4 import cmdline.command; 5 6 alias EventCallback_1 = void delegate(); 7 alias EventCallback_2 = void delegate(string val); 8 alias EventCallback_3 = void delegate(bool isErrMode); 9 alias EventCallback_4 = void delegate(string[] vals); 10 11 struct EventFn { 12 EventCallback_1 _fn1; 13 EventCallback_2 _fn2; 14 EventCallback_3 _fn3; 15 EventCallback_4 _fn4; 16 17 void opCall() const { 18 _fn1(); 19 } 20 21 void opCall(string val) const { 22 _fn2(val); 23 } 24 25 void opCall(bool isErrMode) const { 26 _fn3(isErrMode); 27 } 28 29 void opCall(string[] vals) const { 30 _fn4(vals); 31 } 32 33 auto opAssign(EventCallback_1 value) { 34 this._fn1 = value; 35 return this; 36 } 37 38 auto opAssign(EventCallback_2 value) { 39 this._fn2 = value; 40 return this; 41 } 42 43 auto opAssign(EventCallback_3 value) { 44 this._fn3 = value; 45 return this; 46 } 47 48 auto opAssign(EventCallback_4 value) { 49 this._fn4 = value; 50 return this; 51 } 52 } 53 54 class EventManager { 55 private: 56 EventFn[string] eventMap; 57 58 public: 59 alias Self = typeof(this); 60 61 Self on(string eventName, EventCallback_1 callback) { 62 auto ptr = eventName in eventMap; 63 assert(!ptr || (*ptr)._fn1 is null); 64 if (ptr) { 65 eventMap[eventName] = callback; 66 return this; 67 } 68 EventFn fn; 69 eventMap[eventName] = fn = callback; 70 return this; 71 } 72 73 Self on(string eventName, EventCallback_2 callback) { 74 auto ptr = eventName in eventMap; 75 assert(!ptr || (*ptr)._fn2 is null); 76 if (ptr) { 77 eventMap[eventName] = callback; 78 return this; 79 } 80 EventFn fn; 81 eventMap[eventName] = fn = callback; 82 eventMap[eventName] = callback; 83 return this; 84 } 85 86 Self on(string eventName, EventCallback_3 callback) { 87 auto ptr = eventName in eventMap; 88 assert(!ptr || (*ptr)._fn3 is null); 89 if (ptr) { 90 eventMap[eventName] = callback; 91 return this; 92 } 93 EventFn fn; 94 eventMap[eventName] = fn = callback; 95 eventMap[eventName] = callback; 96 return this; 97 } 98 99 Self on(string eventName, EventCallback_4 callback) { 100 auto ptr = eventName in eventMap; 101 assert(!ptr || (*ptr)._fn4 is null); 102 if (ptr) { 103 eventMap[eventName] = callback; 104 return this; 105 } 106 EventFn fn; 107 eventMap[eventName] = fn = callback; 108 eventMap[eventName] = callback; 109 return this; 110 } 111 112 bool emit(string eventName, string val) const { 113 auto fn_ptr = eventName in eventMap; 114 if (!fn_ptr) 115 return false; 116 auto fn = *fn_ptr; 117 fn(val); 118 return true; 119 } 120 121 bool emit(string eventName, string[] vals) const { 122 auto fn_ptr = eventName in eventMap; 123 if (!fn_ptr) 124 return false; 125 auto fn = *fn_ptr; 126 fn(vals); 127 return true; 128 } 129 130 bool emit(string eventName) const { 131 auto fn_ptr = eventName in eventMap; 132 if (!fn_ptr) 133 return false; 134 auto fn = *fn_ptr; 135 fn(); 136 return true; 137 } 138 139 bool emit(string eventName, bool isErrMode) const { 140 auto fn_ptr = eventName in eventMap; 141 if (!fn_ptr) 142 return false; 143 auto fn = *fn_ptr; 144 fn(isErrMode); 145 return true; 146 } 147 148 bool removeEvent(string eventName) { 149 return this.eventMap.remove(eventName); 150 } 151 } 152 153 unittest { 154 import std.conv; 155 156 int count = 0; 157 bool fn1_called, fn2_called; 158 159 EventManager em = new EventManager; 160 161 em.on("fn1", () { count += 12; fn1_called = true; }); 162 em.on("fn2", () { count -= 12; fn2_called = true; }); 163 em.emit("fn1"); 164 em.emit("fn2"); 165 assert(!count && fn1_called && fn2_called); 166 }