Implement --color=auto|always|never, fix #2410 (#2552)
* Implement --color=auto|always|never, fix #2410

Also improves error message output for unsupported --color values.

* fix compile error with certain D versions
1 parent 1330c9d commit e3a6d298f5b618cf589ff8b2b5ad88012147462c
@Jan Jurzitza Jan Jurzitza authored on 2 Jan 2023
GitHub committed on 2 Jan 2023
Showing 3 changed files
View
7
changelog/colors.dd 0 → 100644
The `--color` argument now accepts values `auto`, `never`, `always`
 
The previous `automatic`, `on`, `off` values are still supported, but
undocumented, because they are used in almost no other program like this. For
consistency, with other Linux tools especially, we have implemented and switched
the defaults to the widely-used `auto`, `never`, `always` values.
View
50
source/dub/commandline.d
{
options.root_path = options.root_path.expandTilde.absolutePath.buildNormalizedPath;
}
 
final switch (options.color_mode) with (options.color)
final switch (options.colorMode) with (options.Color)
{
case automatic:
// Use default determined in internal.logging.initLogging().
break;
bool verbose, vverbose, quiet, vquiet, verror, version_;
bool help, annotate, bare;
string[] registry_urls;
string root_path;
enum color { automatic, on, off } // Lower case "color" in support of invalid option error formatting.
color color_mode = color.automatic;
enum Color { automatic, on, off }
Color colorMode = Color.automatic;
SkipPackageSuppliers skipRegistry = SkipPackageSuppliers.none;
PlacementLocation placementLocation = PlacementLocation.user;
 
deprecated("Use `Color` instead, the previous naming was a limitation of error message formatting")
alias color = Color;
deprecated("Use `colorMode` instead")
alias color_mode = colorMode;
 
private void parseColor(string option, string value) @safe
{
// `automatic`, `on`, `off` are there for backwards compatibility
// `auto`, `always`, `never` is being used for compatibility with most
// other development and linux tools, after evaluating what other tools
// are doing, to help users intuitively pick correct values.
// See https://github.com/dlang/dub/issues/2410 for discussion
if (!value.length || value == "auto" || value == "automatic")
colorMode = Color.automatic;
else if (value == "always" || value == "on")
colorMode = Color.on;
else if (value == "never" || value == "off")
colorMode = Color.off;
else
throw new ConvException("Unable to parse argument '--" ~ option ~ "=" ~ value
~ "', supported values: --color[=auto], --color=always, --color=never");
}
 
/// Parses all common options and stores the result in the struct instance.
void prepare(CommandArgs args)
{
args.getopt("vverbose", &vverbose, ["Print debug output"]);
args.getopt("q|quiet", &quiet, ["Only print warnings and errors"]);
args.getopt("verror", &verror, ["Only print errors"]);
args.getopt("vquiet", &vquiet, ["Print no messages"]);
args.getopt("color", &color_mode, [
args.getopt("color", &colorMode, &parseColor, [
"Configure colored output. Accepted values:",
" automatic: Colored output on console/terminal,",
" auto: Colored output on console/terminal,",
" unless NO_COLOR is set and non-empty (default)",
" on: Force colors enabled",
" off: Force colors disabled"
" always: Force colors enabled",
" never: Force colors disabled"
]);
args.getopt("cache", &placementLocation, ["Puts any fetched packages in the specified location [local|system|user]."]);
 
version_ = args.hasAppVersion;
@property const(Arg)[] recognizedArgs() { return m_recognizedArgs; }
 
void getopt(T)(string names, T* var, string[] help_text = null, bool hidden=false)
{
getopt!T(names, var, null, help_text, hidden);
}
 
void getopt(T)(string names, T* var, void delegate(string, string) @safe parseValue, string[] help_text = null, bool hidden=false)
{
foreach (ref arg; m_recognizedArgs)
if (names == arg.names) {
assert(help_text is null, format!("Duplicated argument '%s' must not change helptext, consider to remove the duplication")(names));
*var = arg.value.get!T;
arg.defaultValue = *var;
arg.names = names;
arg.helpText = help_text;
arg.hidden = hidden;
m_args.getopt(config.passThrough, names, var);
if (parseValue is null)
m_args.getopt(config.passThrough, names, var);
else
m_args.getopt(config.passThrough, names, parseValue);
arg.value = *var;
m_recognizedArgs ~= arg;
}
 
View
test/colored-output.sh