- /*******************************************************************************
-
- Utilities used internally by the config parser.
-
- Compile this library with `-debug=ConfigFillerDebug` to get verbose output.
- This can be achieved with `debugVersions` in dub, or by depending on the
- `debug` configuration provided by `dub.json`.
-
- Copyright:
- Copyright (c) 2019-2022 BOSAGORA Foundation
- All rights reserved.
-
- License:
- MIT License. See LICENSE for details.
-
- *******************************************************************************/
-
- module configy.Utils;
-
- import std.format;
-
- /// Type of sink used by the `toString`
- package alias SinkType = void delegate (in char[]) @safe;
-
- /*******************************************************************************
-
- Debugging utility for config filler
-
- Since this module does a lot of meta-programming, some things can easily
- go wrong. For example, a condition being false might happen because it is
- genuinely false or because the condition is buggy.
-
- To make figuring out if a config is properly parsed or not, a little utility
- (config-dumper) exists, which will provide a verbose output of what the
- config filler does. To do this, `config-dumper` is compiled with
- the below `debug` version.
-
- *******************************************************************************/
-
- debug (ConfigFillerDebug)
- {
- /// A thin wrapper around `stderr.writefln` with indentation
- package void dbgWrite (Args...) (string fmt, Args args)
- {
- import std.stdio;
- stderr.write(IndentChars[0 .. indent >= IndentChars.length ? $ : indent]);
- stderr.writefln(fmt, args);
- }
-
- /// Log a value that is to be returned
- /// The value will be the first argument and painted yellow
- package T dbgWriteRet (T, Args...) (auto ref T return_, string fmt, Args args)
- {
- dbgWrite(fmt, return_.paint(Yellow), args);
- return return_;
- }
-
- /// The current indentation
- package size_t indent;
-
- /// Helper for indentation (who needs more than 16 levels of indent?)
- private immutable IndentChars = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
- }
- else
- {
- /// No-op
- package void dbgWrite (Args...) (string fmt, lazy Args args) {}
-
- /// Ditto
- package T dbgWriteRet (T, Args...) (auto ref T return_, string fmt, lazy Args args)
- {
- return return_;
- }
- }
-
- /// Thin wrapper to simplify colorization
- package struct Colored (T)
- {
- /// Color used
- private string color;
-
- /// Value to print
- private T value;
-
- /// Hook for `formattedWrite`
- public void toString (scope SinkType sink)
- {
- static if (is(typeof(T.init.length) : size_t))
- if (this.value.length == 0) return;
-
- formattedWrite(sink, "%s%s%s", this.color, this.value, Reset);
- }
- }
-
- /// Ditto
- package Colored!T paint (T) (T arg, string color)
- {
- return Colored!T(color, arg);
- }
-
- /// Paint `arg` in color `ifTrue` if `cond` evaluates to `true`, use color `ifFalse` otherwise
- package Colored!T paintIf (T) (T arg, bool cond, string ifTrue, string ifFalse)
- {
- return Colored!T(cond ? ifTrue : ifFalse, arg);
- }
-
- /// Paint a boolean in green if `true`, red otherwise, unless `reverse` is set to `true`,
- /// in which case the colors are swapped
- package Colored!bool paintBool (bool value, bool reverse = false)
- {
- return value.paintIf(reverse ^ value, Green, Red);
- }
-
- /// Reset the foreground color used
- package immutable Reset = "\u001b[0m";
- /// Set the foreground color to red, used for `false`, missing, errors, etc...
- package immutable Red = "\u001b[31m";
- /// Set the foreground color to red, used for warnings and other things
- /// that should draw attention but do not pose an immediate issue
- package immutable Yellow = "\u001b[33m";
- /// Set the foreground color to green, used for `true`, present, etc...
- package immutable Green = "\u001b[32m";
- /// Set the foreground color to green, used field names / path
- package immutable Cyan = "\u001b[36m";