Newer
Older
dub_jkp / source / configy / Utils.d
  1. /*******************************************************************************
  2.  
  3. Utilities used internally by the config parser.
  4.  
  5. Compile this library with `-debug=ConfigFillerDebug` to get verbose output.
  6. This can be achieved with `debugVersions` in dub, or by depending on the
  7. `debug` configuration provided by `dub.json`.
  8.  
  9. Copyright:
  10. Copyright (c) 2019-2022 BOSAGORA Foundation
  11. All rights reserved.
  12.  
  13. License:
  14. MIT License. See LICENSE for details.
  15.  
  16. *******************************************************************************/
  17.  
  18. module configy.Utils;
  19.  
  20. import std.format;
  21.  
  22. /// Type of sink used by the `toString`
  23. package alias SinkType = void delegate (in char[]) @safe;
  24.  
  25. /*******************************************************************************
  26.  
  27. Debugging utility for config filler
  28.  
  29. Since this module does a lot of meta-programming, some things can easily
  30. go wrong. For example, a condition being false might happen because it is
  31. genuinely false or because the condition is buggy.
  32.  
  33. To make figuring out if a config is properly parsed or not, a little utility
  34. (config-dumper) exists, which will provide a verbose output of what the
  35. config filler does. To do this, `config-dumper` is compiled with
  36. the below `debug` version.
  37.  
  38. *******************************************************************************/
  39.  
  40. debug (ConfigFillerDebug)
  41. {
  42. /// A thin wrapper around `stderr.writefln` with indentation
  43. package void dbgWrite (Args...) (string fmt, Args args)
  44. {
  45. import std.stdio;
  46. stderr.write(IndentChars[0 .. indent >= IndentChars.length ? $ : indent]);
  47. stderr.writefln(fmt, args);
  48. }
  49.  
  50. /// Log a value that is to be returned
  51. /// The value will be the first argument and painted yellow
  52. package T dbgWriteRet (T, Args...) (auto ref T return_, string fmt, Args args)
  53. {
  54. dbgWrite(fmt, return_.paint(Yellow), args);
  55. return return_;
  56. }
  57.  
  58. /// The current indentation
  59. package size_t indent;
  60.  
  61. /// Helper for indentation (who needs more than 16 levels of indent?)
  62. private immutable IndentChars = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
  63. }
  64. else
  65. {
  66. /// No-op
  67. package void dbgWrite (Args...) (string fmt, lazy Args args) {}
  68.  
  69. /// Ditto
  70. package T dbgWriteRet (T, Args...) (auto ref T return_, string fmt, lazy Args args)
  71. {
  72. return return_;
  73. }
  74. }
  75.  
  76. /// Thin wrapper to simplify colorization
  77. package struct Colored (T)
  78. {
  79. /// Color used
  80. private string color;
  81.  
  82. /// Value to print
  83. private T value;
  84.  
  85. /// Hook for `formattedWrite`
  86. public void toString (scope SinkType sink)
  87. {
  88. static if (is(typeof(T.init.length) : size_t))
  89. if (this.value.length == 0) return;
  90.  
  91. formattedWrite(sink, "%s%s%s", this.color, this.value, Reset);
  92. }
  93. }
  94.  
  95. /// Ditto
  96. package Colored!T paint (T) (T arg, string color)
  97. {
  98. return Colored!T(color, arg);
  99. }
  100.  
  101. /// Paint `arg` in color `ifTrue` if `cond` evaluates to `true`, use color `ifFalse` otherwise
  102. package Colored!T paintIf (T) (T arg, bool cond, string ifTrue, string ifFalse)
  103. {
  104. return Colored!T(cond ? ifTrue : ifFalse, arg);
  105. }
  106.  
  107. /// Paint a boolean in green if `true`, red otherwise, unless `reverse` is set to `true`,
  108. /// in which case the colors are swapped
  109. package Colored!bool paintBool (bool value, bool reverse = false)
  110. {
  111. return value.paintIf(reverse ^ value, Green, Red);
  112. }
  113.  
  114. /// Reset the foreground color used
  115. package immutable Reset = "\u001b[0m";
  116. /// Set the foreground color to red, used for `false`, missing, errors, etc...
  117. package immutable Red = "\u001b[31m";
  118. /// Set the foreground color to red, used for warnings and other things
  119. /// that should draw attention but do not pose an immediate issue
  120. package immutable Yellow = "\u001b[33m";
  121. /// Set the foreground color to green, used for `true`, present, etc...
  122. package immutable Green = "\u001b[32m";
  123. /// Set the foreground color to green, used field names / path
  124. package immutable Cyan = "\u001b[36m";