comparison mde/lookup/Options.d @ 98:49e7cfed4b34

All types of Option have been converted to use ValueContent classes, and their values can be displayed.
author Diggory Hardy <diggory.hardy@gmail.com>
date Wed, 12 Nov 2008 13:18:51 +0000
parents 2a364c7d82c9
children 71f0f1f83620
comparison
equal deleted inserted replaced
97:30470bc19ca4 98:49e7cfed4b34
79 protected this() {} /// Do not instantiate directly. 79 protected this() {} /// Do not instantiate directly.
80 80
81 // All supported types, for generic handling via templates. It should be possible to change 81 // All supported types, for generic handling via templates. It should be possible to change
82 // the supported types simply by changing this list now (untested). 82 // the supported types simply by changing this list now (untested).
83 template store(A...) { alias A store; } 83 template store(A...) { alias A store; }
84 alias store!(bool, int, double, char[]) TYPES; 84 // NOTE: currently all types have transitioned to the new method, but the old method remains
85 alias store!(int, double, char[]) TYPES2; 85 alias store!(bool, int, double, char[]) TYPES; // all types
86 alias store!(bool, int, double, char[]) CTYPES; // types stored with a content
86 //BEGIN Templates: internal 87 //BEGIN Templates: internal
87 private { 88 private {
88 // Get name of a type. Basically just stringof, but special handling for arrays. 89 // Get name of a type. Basically just stringof, but special handling for arrays.
89 // Use TName!(T) for a valid symbol name, and T.stringof for a type. 90 // Use TName!(T) for a valid symbol name, and T.stringof for a type.
90 template TName(T : T[]) { 91 template TName(T : T[]) {
95 } 96 }
96 97
97 // Pointer lists 98 // Pointer lists
98 template PLists(A...) { 99 template PLists(A...) {
99 static if (A.length) { 100 static if (A.length) {
100 static if (is (T == bool)) { 101 static if (TIsIn!(A[0], CTYPES)) {
101 const char[] PLists = PLists!(A[1..$]); 102 const char[] PLists = PLists!(A[1..$]);
102 } else 103 } else
103 const char[] PLists = A[0].stringof~"*[ID] opts"~TName!(A[0])~";\n" ~ PLists!(A[1..$]); 104 const char[] PLists = A[0].stringof~"*[ID] opts"~TName!(A[0])~";\n" ~ PLists!(A[1..$]);
104 } else 105 } else
105 const char[] PLists = ""; 106 const char[] PLists = "";
116 const bool TIsIn = false; // no more possibilities 117 const bool TIsIn = false; // no more possibilities
117 } 118 }
118 119
119 // For addTag 120 // For addTag
120 template addTagMixin(T, A...) { 121 template addTagMixin(T, A...) {
121 static if (is(T == bool)) { 122 static if (TIsIn!(T, CTYPES)) {
122 const char[] ifBlock = `if (tp == "`~T.stringof~`") { 123 const char[] ifBlock = `if (tp == "`~T.stringof~`") {
123 auto p = id in opts; 124 auto p = id in opts;
124 if (p) { 125 if (p) {
125 auto q = cast(BoolContent) (*p); 126 auto q = cast(`~VContentN!(T)~`) (*p);
126 if (q) q.v = parseTo!(`~T.stringof~`) (dt); 127 if (q) q.v = parseTo!(`~T.stringof~`) (dt);
127 } 128 }
128 }`; 129 }`;
129 } else 130 } else
130 const char[] ifBlock = `if (tp == "`~T.stringof~`") { 131 const char[] ifBlock = `if (tp == "`~T.stringof~`") {
138 } 139 }
139 140
140 // For list 141 // For list
141 template listMixin(A...) { 142 template listMixin(A...) {
142 static if (A.length) { 143 static if (A.length) {
143 const char[] listMixin = `ret ~= opts`~TName!(A[0])~`.keys;` ~ listMixin!(A[1..$]); 144 static if (TIsIn!(A, CTYPES))
145 const char[] listMixin = listMixin!(A[1..$]);
146 else
147 const char[] listMixin = `ret ~= opts`~TName!(A[0])~`.keys;` ~ listMixin!(A[1..$]);
144 } else 148 } else
145 const char[] listMixin = ``; 149 const char[] listMixin = ``;
146 } 150 }
147 } 151 }
148 //END Templates: internal 152 //END Templates: internal
246 * 250 *
247 * Due to the way options are handled generically, string IDs must be used to access the options 251 * Due to the way options are handled generically, string IDs must be used to access the options
248 * via hash-maps, which is a little slower than direct access but necessary since the option 252 * via hash-maps, which is a little slower than direct access but necessary since the option
249 * must be changed in two separate places. */ 253 * must be changed in two separate places. */
250 void set(T) (char[] symbol, T val) { 254 void set(T) (char[] symbol, T val) {
251 static assert (TIsIn!(T,TYPES) && !is(T == bool), "Options does not support type "~T.stringof); 255 static assert (TIsIn!(T,TYPES) && !TIsIn!(T, CTYPES), "Options.set does not support type "~T.stringof);
252 256
253 changed = true; // something got set (don't bother checking this isn't what it already was) 257 changed = true; // something got set (don't bother checking this isn't what it already was)
254 258
255 try { 259 try {
256 mixin (`*(opts`~TName!(T)~`[cast(ID) symbol]) = val;`); 260 mixin (`*(opts`~TName!(T)~`[cast(ID) symbol]) = val;`);
278 }+/ 282 }+/
279 283
280 /** List the names of all options of a specific type. */ 284 /** List the names of all options of a specific type. */
281 char[][] list () { 285 char[][] list () {
282 char[][] ret; 286 char[][] ret;
283 mixin (listMixin!(TYPES2)); 287 mixin (listMixin!(TYPES));
284 return ret; 288 return ret;
285 } 289 }
286 290
287 /// Get all Options stored with a ValueContent. 291 /// Get all Options stored with a ValueContent.
288 ValueContent[char[]] content() { 292 ValueContent[char[]] content() {
295 protected { 299 protected {
296 char[] secName; // name of this option setting; set null after translation is loaded 300 char[] secName; // name of this option setting; set null after translation is loaded
297 OptionChanges optionChanges; // all changes to options (for saving) 301 OptionChanges optionChanges; // all changes to options (for saving)
298 302
299 // The "pointer lists", e.g. char[]*[ID] optscharA; 303 // The "pointer lists", e.g. char[]*[ID] optscharA;
300 mixin (PLists!(TYPES2)); //FIXME 304 mixin (PLists!(TYPES));
301 ValueContent[char[]] opts; // generic list of option values 305 ValueContent[char[]] opts; // generic list of option values
302 } 306 }
303 307
304 //BEGIN Mergetag loading/saving code 308 //BEGIN Mergetag loading/saving code
305 void addTag (char[] tp, ID id, char[] dt) { 309 void addTag (char[] tp, ID id, char[] dt) {
313 317
314 //BEGIN Templates: impl & optionsThis 318 //BEGIN Templates: impl & optionsThis
315 private { 319 private {
316 // Replace, e.g., bool, with BoolContent 320 // Replace, e.g., bool, with BoolContent
317 template contentName(A) { 321 template contentName(A) {
318 static if (is(A == bool)) { 322 static if (TIsIn!(A, CTYPES)) {
319 const char[] contentName = "BoolContent"; 323 const char[] contentName = VContentN!(A);
320 } else static if (is(A == int)) { 324 } else
321 const char[] contentName = "int";// no IntContent yet 325 const char[] contentName = A.stringof;
322 } else static if (is(A == double)) {
323 const char[] contentName = "double";
324 } else static if (is(A == char[])) {
325 const char[] contentName = "char[]";
326 } else
327 static assert (false, "unsuppurted type: "~ A);
328 } 326 }
329 // Return index of first comma, or halts if not found. 327 // Return index of first comma, or halts if not found.
330 template cIndex(char[] A) { 328 template cIndex(char[] A) {
331 static if (A.length == 0) 329 static if (A.length == 0)
332 static assert (false, "Error in implementation"); 330 static assert (false, "Error in implementation");
368 else 366 else
369 const char[] aaVars = "\""~A[0..cIndex!(A)]~"\"[]:&"~A[0..cIndex!(A)] ~ "," ~ 367 const char[] aaVars = "\""~A[0..cIndex!(A)]~"\"[]:&"~A[0..cIndex!(A)] ~ "," ~
370 aaVars!(A[cIndex!(A)+1..$]); 368 aaVars!(A[cIndex!(A)+1..$]);
371 } 369 }
372 // May have a trailing comma. Assumes cIndex always returns less than A.$ . 370 // May have a trailing comma. Assumes cIndex always returns less than A.$ .
373 template aaVarsBool(char[] A) {//FIXME 371 template aaVarsContent(char[] A) {//FIXME
374 static if (A.length == 0) 372 static if (A.length == 0)
375 const char[] aaVarsBool = ""; 373 const char[] aaVarsContent = "";
376 else static if (A[0] == ' ') 374 else static if (A[0] == ' ')
377 const char[] aaVarsBool = aaVarsBool!(A[1..$]); 375 const char[] aaVarsContent = aaVarsContent!(A[1..$]);
378 else 376 else
379 const char[] aaVarsBool = "\""~A[0..cIndex!(A)]~"\"[]:"~A[0..cIndex!(A)] ~ "," ~ 377 const char[] aaVarsContent = "\""~A[0..cIndex!(A)]~"\"[]:cast(ValueContent)"~A[0..cIndex!(A)] ~ "," ~
380 aaVarsBool!(A[cIndex!(A)+1..$]); 378 aaVarsContent!(A[cIndex!(A)+1..$]);
381 } 379 }
382 // strip Trailing Comma 380 // strip Trailing Comma
383 template sTC(char[] A) { 381 template sTC(char[] A) {
384 static if (A.length && A[$-1] == ',') 382 static if (A.length && A[$-1] == ',')
385 const char[] sTC = A[0..$-1]; 383 const char[] sTC = A[0..$-1];
401 const char[] catOrNothing = A~` `~sTC!(B)~";\n"; 399 const char[] catOrNothing = A~` `~sTC!(B)~";\n";
402 else 400 else
403 const char[] catOrNothing = ``; 401 const char[] catOrNothing = ``;
404 } 402 }
405 // foreach decl... 403 // foreach decl...
406 template createBCs(char[] A) { 404 template createContents(T, char[] A) {
407 static if (A.length == 0) 405 static if (A.length == 0)
408 const char[] createBCs = ""; 406 const char[] createContents = "";
409 else static if (A[0] == ' ') 407 else static if (A[0] == ' ')
410 const char[] createBCs = createBCs!(A[1..$]); 408 const char[] createContents = createContents!(T,A[1..$]);
411 else 409 else
412 const char[] createBCs = A[0..cIndex!(A)]~ ` = (new BoolContent ("`~A[0..cIndex!(A)]~"\")).addChangeCb (&optionChanges.set);\n"~ 410 const char[] createContents = "opts[\""~A[0..cIndex!(A)]~"\"] = " ~ A[0..cIndex!(A)]~ " = (new "~VContentN!(T)~" (\""~A[0..cIndex!(A)]~"\")).addChangeCb (&optionChanges.set);\n"~
413 createBCs!(A[cIndex!(A)+1..$]); 411 createContents!(T,A[cIndex!(A)+1..$]);
414 } 412 }
415 // for recursing on TYPES 413 // for recursing on TYPES
416 template optionsThisInternal(char[] A, B...) { 414 template optionsThisInternal(char[] A, B...) {
417 static if (B.length) { 415 static if (B.length) {
418 static if (is(B[0] == bool)) {//FIXME 416 static if (TIsIn!(B[0], CTYPES)) {
419 const char[] optionsThisInternal = createBCs!(parseT!(B[0].stringof,A))~ 417 const char[] optionsThisInternal = createContents!(B[0],parseT!(B[0].stringof,A))~
420 `opts = `~listOrNull!(sTC!(aaVarsBool!(parseT!(B[0].stringof,A))))~";\n" ~
421 optionsThisInternal!(A,B[1..$]); 418 optionsThisInternal!(A,B[1..$]);
422 } else 419 } else
423 const char[] optionsThisInternal = `opts`~TName!(B[0])~` = `~listOrNull!(sTC!(aaVars!(parseT!(B[0].stringof,A))))~";\n" ~ optionsThisInternal!(A,B[1..$]); 420 const char[] optionsThisInternal = `opts`~TName!(B[0])~` = `~listOrNull!(sTC!(aaVars!(parseT!(B[0].stringof,A))))~";\n" ~ optionsThisInternal!(A,B[1..$]);
424 } else 421 } else
425 const char[] optionsThisInternal = ``; 422 const char[] optionsThisInternal = ``;
555 */ 552 */
556 553
557 /** A home for all miscellaneous options, at least for now. */ 554 /** A home for all miscellaneous options, at least for now. */
558 MiscOptions miscOpts; 555 MiscOptions miscOpts;
559 class MiscOptions : Options { 556 class MiscOptions : Options {
560 const A = "bool exitImmediately; int maxThreads, logOptions; double pollInterval; char[] L10n;"; 557 const A = "bool exitImmediately; int maxThreads, logLevel, logOutput; double pollInterval; char[] L10n;";
561 //pragma (msg, impl!(A)); 558 //pragma (msg, impl!(A));
562 mixin (impl!(A)); 559 mixin (impl!(A));
563 560
564 void validate() { 561 void validate() {
565 // Try to enforce sensible values, whilst being reasonably flexible: 562 // Try to enforce sensible values, whilst being reasonably flexible:
566 if (miscOpts.maxThreads < 1 || miscOpts.maxThreads > 64) { 563 if (maxThreads() < 1 || maxThreads() > 64) {
567 logger.warn ("maxThreads must be in the range 1-64. Defaulting to 4."); 564 logger.warn ("maxThreads must be in the range 1-64. Defaulting to 4.");
568 miscOpts.set!(int)("maxThreads", 4); 565 maxThreads = 4;
569 } 566 }
570 if (pollInterval !<= 1.0 || pollInterval !>= 0.0) 567 if (pollInterval() !<= 1.0 || pollInterval() !>= 0.0)
571 set!(double) ("pollInterval", 0.01); 568 pollInterval = 0.01;
572 } 569 }
573 570
574 static this() { 571 static this() {
575 miscOpts = new MiscOptions; 572 miscOpts = new MiscOptions;
576 Options.addOptionsClass (miscOpts, "MiscOptions"); 573 Options.addOptionsClass (miscOpts, "MiscOptions");