From b617473fd7545b59940a7381558dcadd36e05b28 Mon Sep 17 00:00:00 2001 From: Giacomo De Lazzari Date: Sat, 9 Jun 2018 01:15:58 +0200 Subject: [PATCH 01/42] New logging module - initial functionality The new module replaces dub.internal.vibecompat.core.log by using the same function names, but implementing colored output and the left fixed-width tag. Overloaded functions are provided to output colored text. Still missing initLogging() and non-TTY stdout/stderr detection --- source/dub/commandline.d | 2 +- source/dub/compilers/compiler.d | 3 +- source/dub/compilers/dmd.d | 2 +- source/dub/compilers/gdc.d | 2 +- source/dub/compilers/ldc.d | 2 +- source/dub/compilers/utils.d | 4 +- source/dub/dependency.d | 2 +- source/dub/dependencyresolver.d | 2 +- source/dub/dub.d | 2 +- source/dub/generators/build.d | 2 +- source/dub/generators/cmake.d | 2 +- source/dub/generators/generator.d | 2 +- source/dub/generators/sublimetext.d | 2 +- source/dub/generators/visuald.d | 2 +- source/dub/init.d | 2 +- source/dub/internal/colorize/colors.d | 193 ++++++++++++++ source/dub/internal/colorize/cwrite.d | 74 ++++++ source/dub/internal/colorize/package.d | 10 + source/dub/internal/colorize/winterm.d | 161 ++++++++++++ source/dub/internal/utils.d | 2 +- source/dub/internal/vibecompat/core/file.d | 2 +- source/dub/internal/vibecompat/core/log.d | 99 -------- source/dub/internal/vibecompat/data/json.d | 1 - source/dub/logging.d | 279 +++++++++++++++++++++ source/dub/package_.d | 2 +- source/dub/packagemanager.d | 2 +- source/dub/packagesuppliers/fallback.d | 8 +- source/dub/packagesuppliers/filesystem.d | 3 +- source/dub/packagesuppliers/maven.d | 2 +- source/dub/packagesuppliers/registry.d | 3 +- source/dub/project.d | 2 +- source/dub/recipe/packagerecipe.d | 2 +- source/dub/recipe/sdl.d | 2 +- 33 files changed, 749 insertions(+), 131 deletions(-) create mode 100644 source/dub/internal/colorize/colors.d create mode 100644 source/dub/internal/colorize/cwrite.d create mode 100644 source/dub/internal/colorize/package.d create mode 100644 source/dub/internal/colorize/winterm.d delete mode 100644 source/dub/internal/vibecompat/core/log.d create mode 100644 source/dub/logging.d diff --git a/source/dub/commandline.d b/source/dub/commandline.d index e428d6156..13a02c89b 100644 --- a/source/dub/commandline.d +++ b/source/dub/commandline.d @@ -12,9 +12,9 @@ import dub.dependency; import dub.dub; import dub.generators.generator; import dub.internal.vibecompat.core.file; -import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.data.json; import dub.internal.vibecompat.inet.path; +import dub.logging; import dub.package_; import dub.packagemanager; import dub.packagesuppliers; diff --git a/source/dub/compilers/compiler.d b/source/dub/compilers/compiler.d index ff59b26c5..b8e210783 100644 --- a/source/dub/compilers/compiler.d +++ b/source/dub/compilers/compiler.d @@ -11,9 +11,10 @@ public import dub.compilers.buildsettings; deprecated("Please `import dub.dependency : Dependency` instead") public import dub.dependency : Dependency; public import dub.platform : BuildPlatform, matchesSpecification; -import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.inet.path; +import dub.logging; + import std.algorithm; import std.array; import std.exception; diff --git a/source/dub/compilers/dmd.d b/source/dub/compilers/dmd.d index 7c0bb32a8..ba49e90ca 100644 --- a/source/dub/compilers/dmd.d +++ b/source/dub/compilers/dmd.d @@ -10,8 +10,8 @@ module dub.compilers.dmd; import dub.compilers.compiler; import dub.compilers.utils; import dub.internal.utils; -import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.inet.path; +import dub.logging; import std.algorithm; import std.array; diff --git a/source/dub/compilers/gdc.d b/source/dub/compilers/gdc.d index fd47d0136..cab47595a 100644 --- a/source/dub/compilers/gdc.d +++ b/source/dub/compilers/gdc.d @@ -10,8 +10,8 @@ module dub.compilers.gdc; import dub.compilers.compiler; import dub.compilers.utils; import dub.internal.utils; -import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.inet.path; +import dub.logging; import std.algorithm; import std.array; diff --git a/source/dub/compilers/ldc.d b/source/dub/compilers/ldc.d index f37409dea..a85090765 100644 --- a/source/dub/compilers/ldc.d +++ b/source/dub/compilers/ldc.d @@ -10,8 +10,8 @@ module dub.compilers.ldc; import dub.compilers.compiler; import dub.compilers.utils; import dub.internal.utils; -import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.inet.path; +import dub.logging; import std.algorithm; import std.array; diff --git a/source/dub/compilers/utils.d b/source/dub/compilers/utils.d index e04711348..86bde9025 100644 --- a/source/dub/compilers/utils.d +++ b/source/dub/compilers/utils.d @@ -9,10 +9,10 @@ module dub.compilers.utils; import dub.compilers.buildsettings; import dub.platform : BuildPlatform, archCheck, compilerCheck, platformCheck; -import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.inet.path; -import std.algorithm : canFind, endsWith, filter; +import dub.logging; +import std.algorithm : canFind, endsWith, filter; /** Alters the build options to comply with the specified build requirements. diff --git a/source/dub/dependency.d b/source/dub/dependency.d index 678d7bafd..16210db6c 100644 --- a/source/dub/dependency.d +++ b/source/dub/dependency.d @@ -8,12 +8,12 @@ module dub.dependency; import dub.internal.utils; -import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.data.json; import dub.internal.vibecompat.inet.path; import dub.package_; import dub.semver; +import dub.logging; import std.algorithm; import std.array; diff --git a/source/dub/dependencyresolver.d b/source/dub/dependencyresolver.d index 8ec82cc73..527b63215 100644 --- a/source/dub/dependencyresolver.d +++ b/source/dub/dependencyresolver.d @@ -8,7 +8,7 @@ module dub.dependencyresolver; import dub.dependency; -import dub.internal.vibecompat.core.log; +import dub.logging; import std.algorithm : all, canFind, filter, map, sort; import std.array : appender, array, join; diff --git a/source/dub/dub.d b/source/dub/dub.d index f0a8466a4..c80e7cbe7 100644 --- a/source/dub/dub.d +++ b/source/dub/dub.d @@ -12,9 +12,9 @@ import dub.dependency; import dub.dependencyresolver; import dub.internal.utils; import dub.internal.vibecompat.core.file; -import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.data.json; import dub.internal.vibecompat.inet.url; +import dub.logging; import dub.package_; import dub.packagemanager; import dub.packagesuppliers; diff --git a/source/dub/generators/build.d b/source/dub/generators/build.d index 490b47d12..d9f9113df 100644 --- a/source/dub/generators/build.d +++ b/source/dub/generators/build.d @@ -12,8 +12,8 @@ import dub.compilers.utils; import dub.generators.generator; import dub.internal.utils; import dub.internal.vibecompat.core.file; -import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.inet.path; +import dub.logging; import dub.package_; import dub.packagemanager; import dub.project; diff --git a/source/dub/generators/cmake.d b/source/dub/generators/cmake.d index 595442dbd..3bf84bb1a 100644 --- a/source/dub/generators/cmake.d +++ b/source/dub/generators/cmake.d @@ -9,9 +9,9 @@ module dub.generators.cmake; import dub.compilers.buildsettings; import dub.generators.generator; -import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.inet.path; +import dub.logging; import dub.project; import std.algorithm: map, uniq; diff --git a/source/dub/generators/generator.d b/source/dub/generators/generator.d index 534b38c72..a88affc37 100644 --- a/source/dub/generators/generator.d +++ b/source/dub/generators/generator.d @@ -13,8 +13,8 @@ import dub.generators.build; import dub.generators.sublimetext; import dub.generators.visuald; import dub.internal.vibecompat.core.file; -import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.inet.path; +import dub.logging; import dub.package_; import dub.packagemanager; import dub.project; diff --git a/source/dub/generators/sublimetext.d b/source/dub/generators/sublimetext.d index f53ae530d..880d0beca 100644 --- a/source/dub/generators/sublimetext.d +++ b/source/dub/generators/sublimetext.d @@ -9,9 +9,9 @@ module dub.generators.sublimetext; import dub.compilers.compiler; import dub.generators.generator; -import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.data.json; import dub.internal.vibecompat.inet.path; +import dub.logging; import dub.packagemanager; import dub.project; diff --git a/source/dub/generators/visuald.d b/source/dub/generators/visuald.d index 7f4512237..1eef903d3 100644 --- a/source/dub/generators/visuald.d +++ b/source/dub/generators/visuald.d @@ -11,7 +11,7 @@ import dub.compilers.compiler; import dub.generators.generator; import dub.internal.utils; import dub.internal.vibecompat.core.file; -import dub.internal.vibecompat.core.log; +import dub.logging; import dub.package_; import dub.packagemanager; import dub.project; diff --git a/source/dub/init.d b/source/dub/init.d index 876b79139..160449be4 100644 --- a/source/dub/init.d +++ b/source/dub/init.d @@ -8,7 +8,7 @@ module dub.init; import dub.internal.vibecompat.core.file; -import dub.internal.vibecompat.core.log; +import dub.logging; import dub.package_ : PackageFormat, packageInfoFiles, defaultPackageFilename; import dub.recipe.packagerecipe; import dub.dependency; diff --git a/source/dub/internal/colorize/colors.d b/source/dub/internal/colorize/colors.d new file mode 100644 index 000000000..255588726 --- /dev/null +++ b/source/dub/internal/colorize/colors.d @@ -0,0 +1,193 @@ +/** + * Authors: Pedro Tacla Yamada + * Date: June 9, 2014 + * License: Licensed under the MIT license. See LICENSE for more information + * Version: 1.0.2 + */ +module dub.internal.colorize.colors; + +import std.string : format; + +private template color_type(int offset) +{ + static enum type : int + { + init = 39 + offset, + + black = 30 + offset, + red = 31 + offset, + green = 32 + offset, + yellow = 33 + offset, + blue = 34 + offset, + magenta = 35 + offset, + cyan = 36 + offset, + white = 37 + offset, + + light_black = 90 + offset, + light_red = 91 + offset, + light_green = 92 + offset, + light_yellow = 93 + offset, + light_blue = 94 + offset, + light_magenta = 95 + offset, + light_cyan = 96 + offset, + light_white = 97 + offset + } +} + +alias color_type!0 .type fg; +alias color_type!10 .type bg; + +// Text modes +static enum mode : int +{ + init = 0, + bold = 1, + underline = 4, + blink = 5, + swap = 7, + hide = 8 +} + +/** + * Wraps a string around color escape sequences. + * + * Params: + * str = The string to wrap with colors and modes + * c = The foreground color (see the fg enum type) + * b = The background color (see the bg enum type) + * m = The text mode (see the mode enum type) + * Example: + * --- + * writeln("This is blue".color(fg.blue)); + * writeln( + * color("This is red over green blinking", fg.blue, bg.green, mode.blink) + * ); + * --- + */ + +string color( + const string str, + const fg c=fg.init, + const bg b=bg.init, + const mode m=mode.init +) pure +{ + return format("\033[%d;%d;%dm%s\033[0m", m, c, b, str); +} + +unittest +{ + import colorize.cwrite; + string ret; + + ret = "This is yellow".color(fg.yellow); + cwriteln(ret); + assert(ret == "\033[33mThis is yellow\033[0m"); + + ret = "This is light green".color(fg.light_green); + cwriteln(ret); + assert(ret == "\033[92mThis is light green\033[0m"); + + ret = "This is light blue with red background".color(fg.light_blue, bg.red); + cwriteln(ret); + assert(ret == "\033[0;94;41mThis is light blue with red background\033[0m"); + + ret = "This is red on blue blinking".color(fg.red, bg.blue, mode.blink); + cwriteln(ret); + assert(ret == "\033[5;31;44mThis is red on blue blinking\033[0m"); + + ret = color("This is magenta", "magenta"); + cwriteln(ret); + assert(ret == "\033[35mThis is magenta\033[0m"); +} + +string colorHelper(const string str, const string name) pure +{ + int code; + + switch(name) + { + case "init": code = 39; break; + + case "black" : code = 30; break; + case "red" : code = 31; break; + case "green" : code = 32; break; + case "yellow" : code = 33; break; + case "blue" : code = 34; break; + case "magenta": code = 35; break; + case "cyan" : code = 36; break; + case "white" : code = 37; break; + + case "light_black" : code = 90; break; + case "light_red" : code = 91; break; + case "light_green" : code = 92; break; + case "light_yellow" : code = 93; break; + case "light_blue" : code = 94; break; + case "light_magenta": code = 95; break; + case "light_cyan" : code = 96; break; + case "light_white" : code = 97; break; + + case "bg_init": code = 49; break; + + case "bg_black" : code = 40; break; + case "bg_red" : code = 41; break; + case "bg_green" : code = 42; break; + case "bg_yellow" : code = 43; break; + case "bg_blue" : code = 44; break; + case "bg_magenta": code = 45; break; + case "bg_cyan" : code = 46; break; + case "bg_white" : code = 47; break; + + case "bg_light_black" : code = 100; break; + case "bg_light_red" : code = 101; break; + case "bg_light_green" : code = 102; break; + case "bg_light_yellow" : code = 103; break; + case "bg_light_blue" : code = 104; break; + case "bg_light_magenta": code = 105; break; + case "bg_light_cyan" : code = 106; break; + case "bg_light_white" : code = 107; break; + + case "mode_init": code = 0; break; + case "mode_bold" : code = 1; break; + case "mode_underline": code = 4; break; + case "mode_blink" : code = 5; break; + case "mode_swap" : code = 7; break; + case "mode_hide" : code = 8; break; + + default: + throw new Exception( + "Unknown fg color, bg color or mode \"" ~ name ~ "\"" + ); + } + + return format("\033[%dm%s\033[0m", code, str); +} + +string colorHelper(T)(const string str, const T t=T.init) pure + if(is(T : fg) || is(T : bg) || is(T : mode)) +{ + return format("\033[%dm%s\033[0m", t, str); +} + +alias colorHelper!bg background; +alias colorHelper!fg foreground; +alias colorHelper!mode style; + +alias background color; +alias foreground color; +alias style color; +alias colorHelper color; + +unittest +{ + import colorize.cwrite; + string ret; + + ret = "This is red on blue blinking" + .foreground(fg.red) + .background(bg.blue) + .style(mode.blink); + + cwriteln(ret); + assert(ret == "\033[5m\033[44m\033[31mThis is red on blue blinking\033[0m\033[0m\033[0m"); +} diff --git a/source/dub/internal/colorize/cwrite.d b/source/dub/internal/colorize/cwrite.d new file mode 100644 index 000000000..8c8c26996 --- /dev/null +++ b/source/dub/internal/colorize/cwrite.d @@ -0,0 +1,74 @@ +/** + * Authors: ponce + * Date: July 28, 2014 + * License: Licensed under the MIT license. See LICENSE for more information + * Version: 1.0.2 + */ +module dub.internal.colorize.cwrite; + +import std.stdio : File, stdout; + +import dub.internal.colorize.winterm; + +/// Coloured write. +void cwrite(T...)(T args) if (!is(T[0] : File)) +{ + stdout.cwrite(args); +} + +/// Coloured writef. +void cwritef(Char, T...)(in Char[] fmt, T args) if (!is(T[0] : File)) +{ + stdout.cwritef(fmt, args); +} + +/// Coloured writefln. +void cwritefln(Char, T...)(in Char[] fmt, T args) +{ + stdout.cwritef(fmt ~ "\n", args); +} + +/// Coloured writeln. +void cwriteln(T...)(T args) +{ + // Most general instance + stdout.cwrite(args, '\n'); +} + +/// Coloured writef to a File. +void cwritef(Char, A...)(File f, in Char[] fmt, A args) +{ + import std.string : format; + auto s = format(fmt, args); + f.cwrite(s); +} + +/// Coloured writef to a File. +void cwrite(S...)(File f, S args) +{ + import std.conv : to; + + string s = ""; + foreach(arg; args) + s ~= to!string(arg); + + version(Windows) + { + WinTermEmulation winterm; + winterm.initialize(); + foreach(dchar c ; s) + { + auto charAction = winterm.feed(c); + final switch(charAction) with (WinTermEmulation.CharAction) + { + case drop: break; + case write: f.write(c); break; + case flush: f.flush(); break; + } + } + } + else + { + f.write(s); + } +} diff --git a/source/dub/internal/colorize/package.d b/source/dub/internal/colorize/package.d new file mode 100644 index 000000000..b4ff384b5 --- /dev/null +++ b/source/dub/internal/colorize/package.d @@ -0,0 +1,10 @@ +/** + * Authors: ponce + * Date: July 28, 2014 + * License: Licensed under the MIT license. See LICENSE for more information + * Version: 1.0.2 + */ +module dub.internal.colorize; + +public import dub.internal.colorize.colors; +public import dub.internal.colorize.cwrite; diff --git a/source/dub/internal/colorize/winterm.d b/source/dub/internal/colorize/winterm.d new file mode 100644 index 000000000..ef21981dc --- /dev/null +++ b/source/dub/internal/colorize/winterm.d @@ -0,0 +1,161 @@ +/** + * Authors: ponce + * Date: July 28, 2014 + * License: Licensed under the MIT license. See LICENSE for more information + * Version: 1.0.2 + */ +module dub.internal.colorize.winterm; + +version(Windows) +{ + import core.sys.windows.windows; + + // Patch for DMD 2.065 compatibility + static if( __VERSION__ < 2066 ) private enum nogc = 1; + + // This is a state machine to enable terminal colors on Windows. + // Parses and interpret ANSI/VT100 Terminal Control Escape Sequences. + // Only supports colour sequences, will output char incorrectly on invalid input. + struct WinTermEmulation + { + public: + @nogc void initialize() nothrow + { + // saves console attributes + _console = GetStdHandle(STD_OUTPUT_HANDLE); + _savedInitialColor = (0 != GetConsoleScreenBufferInfo(_console, &consoleInfo)); + _state = State.initial; + } + + @nogc ~this() nothrow + { + // Restore initial text attributes on release + if (_savedInitialColor) + { + SetConsoleTextAttribute(_console, consoleInfo.wAttributes); + _savedInitialColor = false; + } + } + + enum CharAction + { + write, + drop, + flush + } + + // Eat one character and update color state accordingly. + // Returns what to do with the fed character. + @nogc CharAction feed(dchar d) nothrow + { + final switch(_state) with (State) + { + case initial: + if (d == '\x1B') + { + _state = escaped; + return CharAction.flush; + } + break; + + case escaped: + if (d == '[') + { + _state = readingAttribute; + _parsedAttr = 0; + return CharAction.drop; + } + break; + + + case readingAttribute: + if (d >= '0' && d <= '9') + { + _parsedAttr = _parsedAttr * 10 + (d - '0'); + return CharAction.drop; + } + else if (d == ';') + { + executeAttribute(_parsedAttr); + _parsedAttr = 0; + return CharAction.drop; + } + else if (d == 'm') + { + executeAttribute(_parsedAttr); + _state = State.initial; + return CharAction.drop; + } + break; + } + return CharAction.write; + } + + private: + HANDLE _console; + bool _savedInitialColor; + CONSOLE_SCREEN_BUFFER_INFO consoleInfo; + State _state; + WORD _currentAttr; + int _parsedAttr; + + enum State + { + initial, + escaped, + readingAttribute + } + + @nogc void setForegroundColor(WORD fgFlags) nothrow + { + _currentAttr = _currentAttr & ~(FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY); + _currentAttr = _currentAttr | fgFlags; + SetConsoleTextAttribute(_console, _currentAttr); + } + + @nogc void setBackgroundColor(WORD bgFlags) nothrow + { + _currentAttr = _currentAttr & ~(BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY); + _currentAttr = _currentAttr | bgFlags; + SetConsoleTextAttribute(_console, _currentAttr); + } + + @nogc void executeAttribute(int attr) nothrow + { + switch (attr) + { + case 0: + // reset all attributes + SetConsoleTextAttribute(_console, consoleInfo.wAttributes); + break; + + default: + if ( (30 <= attr && attr <= 37) || (90 <= attr && attr <= 97) ) + { + WORD color = 0; + if (90 <= attr && attr <= 97) + { + color = FOREGROUND_INTENSITY; + attr -= 60; + } + attr -= 30; + color |= (attr & 1 ? FOREGROUND_RED : 0) | (attr & 2 ? FOREGROUND_GREEN : 0) | (attr & 4 ? FOREGROUND_BLUE : 0); + setForegroundColor(color); + } + + if ( (40 <= attr && attr <= 47) || (100 <= attr && attr <= 107) ) + { + WORD color = 0; + if (100 <= attr && attr <= 107) + { + color = BACKGROUND_INTENSITY; + attr -= 60; + } + attr -= 40; + color |= (attr & 1 ? BACKGROUND_RED : 0) | (attr & 2 ? BACKGROUND_GREEN : 0) | (attr & 4 ? BACKGROUND_BLUE : 0); + setBackgroundColor(color); + } + } + } + } +} diff --git a/source/dub/internal/utils.d b/source/dub/internal/utils.d index c53d7084c..16fdfdf82 100644 --- a/source/dub/internal/utils.d +++ b/source/dub/internal/utils.d @@ -8,11 +8,11 @@ module dub.internal.utils; import dub.internal.vibecompat.core.file; -import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.data.json; import dub.internal.vibecompat.inet.url; import dub.compilers.buildsettings : BuildSettings; import dub.version_; +import dub.logging; import core.time : Duration; import std.algorithm : canFind, startsWith; diff --git a/source/dub/internal/vibecompat/core/file.d b/source/dub/internal/vibecompat/core/file.d index 6ee345dd8..d1b55e650 100644 --- a/source/dub/internal/vibecompat/core/file.d +++ b/source/dub/internal/vibecompat/core/file.d @@ -9,7 +9,7 @@ module dub.internal.vibecompat.core.file; public import dub.internal.vibecompat.inet.url; -import dub.internal.vibecompat.core.log; +import dub.logging; import std.conv; import core.stdc.stdio; diff --git a/source/dub/internal/vibecompat/core/log.d b/source/dub/internal/vibecompat/core/log.d deleted file mode 100644 index e48569e4d..000000000 --- a/source/dub/internal/vibecompat/core/log.d +++ /dev/null @@ -1,99 +0,0 @@ -/** - Central logging facility for vibe. - - Copyright: © 2012 rejectedsoftware e.K. - License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. - Authors: Sönke Ludwig -*/ -module dub.internal.vibecompat.core.log; - -import std.array; -import std.datetime; -import std.format; -import std.stdio; -import core.thread; - -private { - shared LogLevel s_minLevel = LogLevel.info; - shared LogLevel s_logFileLevel; -} - -/// Sets the minimum log level to be printed. -void setLogLevel(LogLevel level) nothrow -{ - s_minLevel = level; -} - -LogLevel getLogLevel() -{ - return s_minLevel; -} - -/** - Logs a message. - - Params: - level = The log level for the logged message - fmt = See http://dlang.org/phobos/std_format.html#format-string -*/ -void logDebug(T...)(string fmt, lazy T args) nothrow { log(LogLevel.debug_, fmt, args); } -/// ditto -void logDiagnostic(T...)(string fmt, lazy T args) nothrow { log(LogLevel.diagnostic, fmt, args); } -/// ditto -void logInfo(T...)(string fmt, lazy T args) nothrow { log(LogLevel.info, fmt, args); } -/// ditto -void logWarn(T...)(string fmt, lazy T args) nothrow { log(LogLevel.warn, fmt, args); } -/// ditto -void logError(T...)(string fmt, lazy T args) nothrow { log(LogLevel.error, fmt, args); } - -/// ditto -void log(T...)(LogLevel level, string fmt, lazy T args) -nothrow { - if( level < s_minLevel ) return; - string pref; - final switch( level ){ - case LogLevel.debug_: pref = "trc"; break; - case LogLevel.diagnostic: pref = "dbg"; break; - case LogLevel.info: pref = "INF"; break; - case LogLevel.warn: pref = "WRN"; break; - case LogLevel.error: pref = "ERR"; break; - case LogLevel.fatal: pref = "FATAL"; break; - case LogLevel.none: assert(false); - } - - try { - auto txt = appender!string(); - txt.reserve(256); - formattedWrite(txt, fmt, args); - - auto threadid = () @trusted { return cast(ulong)cast(void*)Thread.getThis(); } (); - auto fiberid = () @trusted { return cast(ulong)cast(void*)Fiber.getThis(); } (); - threadid ^= threadid >> 32; - fiberid ^= fiberid >> 32; - - if (level >= s_minLevel) { - File output; - if (level == LogLevel.info) () @trusted { output = stdout; } (); - else () @trusted { output = stderr; } (); - if (output.isOpen) { - output.writeln(txt.data); - output.flush(); - } - } - } catch( Exception e ){ - // this is bad but what can we do.. - debug assert(false, e.msg); - } -} - -/// Specifies the log level for a particular log message. -enum LogLevel { - debug_, - diagnostic, - info, - warn, - error, - fatal, - none -} - diff --git a/source/dub/internal/vibecompat/data/json.d b/source/dub/internal/vibecompat/data/json.d index b55166a7a..aced94025 100644 --- a/source/dub/internal/vibecompat/data/json.d +++ b/source/dub/internal/vibecompat/data/json.d @@ -869,7 +869,6 @@ Json parseJson(R)(ref R range, int* line = null, string filename = null) skipWhitespace(range, line); version(JsonLineNumbers) { - import dub.internal.vibecompat.core.log; int curline = line ? *line : 0; } diff --git a/source/dub/logging.d b/source/dub/logging.d new file mode 100644 index 000000000..0ad1db458 --- /dev/null +++ b/source/dub/logging.d @@ -0,0 +1,279 @@ +/** + Handles all the console output of the Dub package manager, by providing useful + methods for handling colored text. The module also disables colors when stdout + and stderr are not a TTY in order to avoid ASCII escape sequences in piped + output. The module can autodetect and configure itself in this regard by + calling initLogging() at the beginning of the program. But, whether to color + text or not can also be set manually with printColorsInLog(bool). + + The output for the log levels error, warn and info is formatted like this: + + " " + '----------' + fixed width + + the "tag" part can be colored (most oftenly will be) and always has a fixed + width, which is defined as a const at the beginning of this module. + + The output for the log levels debug and diagnostic will be just the plain + string. + + There are some default tag string and color values for some logging levels: + - warn: "Warning", yellow bold + - error: "Error", red bold + + Actually, for error and warn levels, the tag color is fixed to the ones listed + above. + + Also, the default tag string for the info level is "" (the empty string) and + the default color is white (usually it's manually set when calling logInfo + with the wanted tag string, but this allows to just logInfo("text") without + having to worry about the tag if it's not needed). + + Usage: + After initializing the logging module with initLogging(), the functions + logDebug(..), logDiagnostic(..), logInfo(..), logWarning(..) and logError(..) + can be used to print log messages. Whether the messages are printed on stdout + or stderr depends on the log level (warning and error go to stderr). + The log(..) function can also be used. Check the signature and documentation + of the functions for more information. + + The minimum log level to print can be configured using setLogLevel(..), and + whether to color outputted text or not can be set with printColorsInLog(..). + + The color(str, color) function can be used to color text within a log + message, for instance like this: + + logInfo("Tag", Color.green, "My %s message", "colored".color(Color.red)) + + Copyright: © 2018 Giacomo De Lazzari + License: Subject to the terms of the MIT license, as written in the included LICENSE file. + Authors: Giacomo De Lazzari +*/ + +module dub.logging; + +import std.stdio; +import std.array; +import std.format; +import std.string; + +import dub.internal.colorize : fg; + +/** + An enum listing possible colors for terminal output, useful to set the color + of a tag +*/ +public alias Color = fg; + +/// The tag width in chars +private const int TAG_WIDTH = 12; + +/// Possible log levels supported +enum LogLevel { + debug_, + diagnostic, + info, + warn, + error, + none +} + +// The current minimum log level to be printed +private LogLevel _minLevel = LogLevel.info; + +/* + Whether to print text with colors or not, defaults to true but will be set + to false in initLogging() if stdout or stderr are not a TTY (which means the + output is probably being piped and we don't want ASCII escape chars in it) +*/ +private bool _printColors = true; + +/// Sets the minimum log level to be printed +void setLogLevel(LogLevel level) nothrow +{ + _minLevel = level; +} + +/// Gets the minimum log level to be printed +LogLevel getLogLevel() +{ + return _minLevel; +} + +/// Set whether to print colors or not +void printColorsInLog(bool enabled) +{ + _printColors = enabled; +} + +/** + Shorthand function to log a message with debug/diagnostic level, no tag string + or tag color required (since there will be no tag). + + Params: + level = The log level for the logged message + fmt = See http://dlang.org/phobos/std_format.html#format-string +*/ +void logDebug(T...)(string fmt, lazy T args) nothrow +{ + log(LogLevel.debug_, "", Color.init, fmt, args); +} + +/// ditto +void logDiagnostic(T...)(string fmt, lazy T args) nothrow +{ + log(LogLevel.diagnostic, "", Color.init, fmt, args); +} + +/** + Shorthand function to log a message with info level, with custom tag string + and tag color. + + Params: + tag = The string the tag at the beginning of the line should contain + tagColor = The color the tag string should have + level = The log level for the logged message + fmt = See http://dlang.org/phobos/std_format.html#format-string +*/ +void logInfo(T...)(string tag, Color tagColor, string fmt, lazy T args) nothrow +{ + log(LogLevel.info, tag, tagColor, fmt, args); +} + +/** + Shorthand function to log a message with info level, this version prints an + empty tag automatically (which is different from not having a tag - in this + case there will be an identation of TAG_WIDTH chars on the left anyway). + + Params: + level = The log level for the logged message + fmt = See http://dlang.org/phobos/std_format.html#format-string +*/ +void logInfo(T...)(string fmt, lazy T args) nothrow +{ + log(LogLevel.info, "", Color.init, fmt, args); +} + +/** + Shorthand function to log a message with warning level, with custom tag string. + The tag color is fixed to yellow. + + Params: + tag = The string the tag at the beginning of the line should contain + level = The log level for the logged message + fmt = See http://dlang.org/phobos/std_format.html#format-string +*/ +void logWarnTag(T...)(string tag, string fmt, lazy T args) nothrow +{ + log(LogLevel.warn, tag, Color.yellow, fmt, args); +} + +/** + Shorthand function to log a message with warning level, using the default + tag "Warning". The tag color is also fixed to yellow. + + Params: + level = The log level for the logged message + fmt = See http://dlang.org/phobos/std_format.html#format-string +*/ +void logWarn(T...)(string fmt, lazy T args) nothrow +{ + log(LogLevel.warn, "Warning", Color.yellow, fmt, args); +} + +/** + Shorthand function to log a message with error level, with custom tag string. + The tag color is fixed to red. + + Params: + tag = The string the tag at the beginning of the line should contain + level = The log level for the logged message + fmt = See http://dlang.org/phobos/std_format.html#format-string +*/ +void logErrorTag(T...)(string tag, string fmt, lazy T args) nothrow +{ + log(LogLevel.error, tag, Color.red, fmt, args); +} + +/** + Shorthand function to log a message with error level, using the default + tag "Error". The tag color is also fixed to red. + + Params: + level = The log level for the logged message + fmt = See http://dlang.org/phobos/std_format.html#format-string +*/ +void logError(T...)(string fmt, lazy T args) nothrow +{ + log(LogLevel.error, "Error", Color.red, fmt, args); +} + +/** + Log a message with the specified log level and with the specified tag string + and color. If the log level is debug or diagnostic, the tag is not printed + thus the tag string and tag color will be ignored. + + Params: + level = The log level for the logged message + tag = The string the tag at the beginning of the line should contain + tagColor = The color the tag string should have + fmt = See http://dlang.org/phobos/std_format.html#format-string +*/ +void log(T...)( + LogLevel level, + string tag, + Color tagColor, + string fmt, + lazy T args +) nothrow +{ + if (level < _minLevel) + return; + + auto hasTag = true; + if (level <= LogLevel.diagnostic) + hasTag = false; + + try + { + string result = format(fmt, args); + + if (hasTag) + result = tag.rightJustify(TAG_WIDTH, ' ').color(tagColor) ~ " " ~ result; + + import dub.internal.colorize : cwrite; + + File output = (level <= LogLevel.info) ? stdout : stderr; + + if (output.isOpen) + { + output.cwrite(result, "\n"); + output.flush(); + } + } + catch (Exception e) + { + debug assert(false, e.msg); + } +} + +/** + Colors the specified string with the specified color. The function is used to + print colored text within a log message. The function also checks whether + color output is enabled or disabled (when not outputting to a TTY) and, in the + last case, just returns the plain string. This allows to use it like so: + + logInfo("Tag", Color.green, "My %s log message", "colored".color(Color.red)); + + without worring whether or not colored output is enabled or not. +*/ +string color(const string str, const Color c = Color.init) +{ + import dub.internal.colorize; + + if (_printColors == true) + return dub.internal.colorize.color(str, c); + else + return str; +} diff --git a/source/dub/package_.d b/source/dub/package_.d index 40a8eda77..71d019ad7 100644 --- a/source/dub/package_.d +++ b/source/dub/package_.d @@ -12,11 +12,11 @@ public import dub.recipe.packagerecipe; import dub.compilers.compiler; import dub.dependency; import dub.description; +import dub.logging; import dub.recipe.json; import dub.recipe.sdl; import dub.internal.utils; -import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.data.json; import dub.internal.vibecompat.inet.path; diff --git a/source/dub/packagemanager.d b/source/dub/packagemanager.d index 845f4cac0..42445266f 100644 --- a/source/dub/packagemanager.d +++ b/source/dub/packagemanager.d @@ -11,9 +11,9 @@ import dub.dependency; static import dub.dependency; import dub.internal.utils; import dub.internal.vibecompat.core.file; -import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.data.json; import dub.internal.vibecompat.inet.path; +import dub.logging; import dub.package_; import std.algorithm : countUntil, filter, sort, canFind, remove; diff --git a/source/dub/packagesuppliers/fallback.d b/source/dub/packagesuppliers/fallback.d index 39a61e62d..d7793e4df 100644 --- a/source/dub/packagesuppliers/fallback.d +++ b/source/dub/packagesuppliers/fallback.d @@ -46,14 +46,14 @@ private template fallback(T, alias func) { import std.format : format; enum fallback = q{ - import dub.internal.vibecompat.core.log : logDiagnostic; + import dub.logging : logDebug; Exception firstEx; try return m_suppliers[0].ps.%1$s(args); catch (Exception e) { - logDiagnostic("Package supplier %%s failed with '%%s', trying fallbacks.", + logDebug("Package supplier %%s failed with '%%s', trying fallbacks.", m_suppliers[0].ps.description, e.msg); firstEx = e; } @@ -65,13 +65,13 @@ private template fallback(T, alias func) continue; try { - scope (success) logDiagnostic("Fallback %%s succeeded", pair.ps.description); + scope (success) logDebug("Fallback %%s succeeded", pair.ps.description); return pair.ps.%1$s(args); } catch (Exception e) { pair.failTime = now; - logDiagnostic("Fallback package supplier %%s failed with '%%s'.", + logDebug("Fallback package supplier %%s failed with '%%s'.", pair.ps.description, e.msg); } } diff --git a/source/dub/packagesuppliers/filesystem.d b/source/dub/packagesuppliers/filesystem.d index fa752bd3b..1e53f0034 100644 --- a/source/dub/packagesuppliers/filesystem.d +++ b/source/dub/packagesuppliers/filesystem.d @@ -9,7 +9,8 @@ import dub.packagesuppliers.packagesupplier; the form "[package name]-[version].zip". */ class FileSystemPackageSupplier : PackageSupplier { - import dub.internal.vibecompat.core.log; + import dub.logging; + version (Have_vibe_core) import dub.internal.vibecompat.inet.path : toNativeString; import std.exception : enforce; private { diff --git a/source/dub/packagesuppliers/maven.d b/source/dub/packagesuppliers/maven.d index 387269dd1..8d85b9d4e 100644 --- a/source/dub/packagesuppliers/maven.d +++ b/source/dub/packagesuppliers/maven.d @@ -11,8 +11,8 @@ import dub.packagesuppliers.packagesupplier; class MavenRegistryPackageSupplier : PackageSupplier { import dub.internal.utils : retryDownload, HTTPStatusException; import dub.internal.vibecompat.data.json : serializeToJson; - import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.inet.url : URL; + import dub.logging; import std.datetime : Clock, Duration, hours, SysTime, UTC; diff --git a/source/dub/packagesuppliers/registry.d b/source/dub/packagesuppliers/registry.d index 83b01e56c..2e132adaf 100644 --- a/source/dub/packagesuppliers/registry.d +++ b/source/dub/packagesuppliers/registry.d @@ -12,9 +12,9 @@ package enum PackagesPath = "packages"; */ class RegistryPackageSupplier : PackageSupplier { import dub.internal.utils : download, retryDownload, HTTPStatusException; - import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.data.json : parseJson, parseJsonString, serializeToJson; import dub.internal.vibecompat.inet.url : URL; + import dub.logging; import std.uri : encodeComponent; import std.datetime : Clock, Duration, hours, SysTime, UTC; @@ -131,4 +131,3 @@ class RegistryPackageSupplier : PackageSupplier { .array; } } - diff --git a/source/dub/project.d b/source/dub/project.d index 2e184335b..4b514a2ac 100644 --- a/source/dub/project.d +++ b/source/dub/project.d @@ -13,9 +13,9 @@ import dub.description; import dub.generators.generator; import dub.internal.utils; import dub.internal.vibecompat.core.file; -import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.data.json; import dub.internal.vibecompat.inet.path; +import dub.logging; import dub.package_; import dub.packagemanager; import dub.recipe.selection; diff --git a/source/dub/recipe/packagerecipe.d b/source/dub/recipe/packagerecipe.d index 14bb98305..8509d12ba 100644 --- a/source/dub/recipe/packagerecipe.d +++ b/source/dub/recipe/packagerecipe.d @@ -10,9 +10,9 @@ module dub.recipe.packagerecipe; import dub.compilers.compiler; import dub.compilers.utils : warnOnSpecialCompilerFlags; import dub.dependency; +import dub.logging; import dub.internal.vibecompat.core.file; -import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.inet.path; import std.algorithm : findSplit, sort; diff --git a/source/dub/recipe/sdl.d b/source/dub/recipe/sdl.d index 31ac460fb..779beb896 100644 --- a/source/dub/recipe/sdl.d +++ b/source/dub/recipe/sdl.d @@ -9,8 +9,8 @@ module dub.recipe.sdl; import dub.compilers.compiler; import dub.dependency; +import dub.logging; import dub.internal.sdlang; -import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.inet.path; import dub.recipe.packagerecipe; From 5b9a5cf5a6d543fdfc901bd3277358d8053a3848 Mon Sep 17 00:00:00 2001 From: Giacomo De Lazzari Date: Sat, 9 Jun 2018 01:37:29 +0200 Subject: [PATCH 02/42] Fixed different logInfo variants colliding --- source/dub/logging.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/dub/logging.d b/source/dub/logging.d index 0ad1db458..99ea62de2 100644 --- a/source/dub/logging.d +++ b/source/dub/logging.d @@ -150,7 +150,7 @@ void logInfo(T...)(string tag, Color tagColor, string fmt, lazy T args) nothrow level = The log level for the logged message fmt = See http://dlang.org/phobos/std_format.html#format-string */ -void logInfo(T...)(string fmt, lazy T args) nothrow +void logInfo(T...)(string fmt, lazy T args) nothrow if (!is(T[0] : Color)) { log(LogLevel.info, "", Color.init, fmt, args); } From 003dd64390e1d169f146139d12960281f84af802 Mon Sep 17 00:00:00 2001 From: Giacomo De Lazzari Date: Sat, 9 Jun 2018 01:48:38 +0200 Subject: [PATCH 03/42] Added support for text mode in color() function This allows to output text bold, underlined, blinking, etc... --- source/dub/logging.d | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/source/dub/logging.d b/source/dub/logging.d index 99ea62de2..f3dd5c12b 100644 --- a/source/dub/logging.d +++ b/source/dub/logging.d @@ -58,13 +58,14 @@ import std.array; import std.format; import std.string; -import dub.internal.colorize : fg; +import dub.internal.colorize : fg, mode; /** An enum listing possible colors for terminal output, useful to set the color of a tag */ public alias Color = fg; +public alias Mode = mode; /// The tag width in chars private const int TAG_WIDTH = 12; @@ -267,13 +268,30 @@ void log(T...)( logInfo("Tag", Color.green, "My %s log message", "colored".color(Color.red)); without worring whether or not colored output is enabled or not. + + Also a mode can be specified, such as bold/underline/etc... +*/ +string color(const string str, const Color c, const Mode m = Mode.init) +{ + import dub.internal.colorize; + + if (_printColors == true) + return dub.internal.colorize.color(str, c, bg.init, m); + else + return str; +} + +/** + This function is the same as the above one, but just accepts a mode. + It's useful, for instance, when outputting bold text without changing the + color. */ -string color(const string str, const Color c = Color.init) +string color(const string str, const Mode m = Mode.init) { import dub.internal.colorize; if (_printColors == true) - return dub.internal.colorize.color(str, c); + return dub.internal.colorize.color(str, fg.init, bg.init, m); else return str; } From e7ff2338816deed8d87b8e5f51b6f12d9cd27941 Mon Sep 17 00:00:00 2001 From: Giacomo De Lazzari Date: Sat, 9 Jun 2018 01:49:24 +0200 Subject: [PATCH 04/42] Making the output prettier - first changes --- source/dub/dub.d | 13 +++++++------ source/dub/generators/build.d | 34 +++++++++++++++++++--------------- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/source/dub/dub.d b/source/dub/dub.d index c80e7cbe7..bdd59bbc6 100644 --- a/source/dub/dub.d +++ b/source/dub/dub.d @@ -557,11 +557,12 @@ class Dub { auto sver = m_project.selections.getSelectedVersion(basename); if (!sver.path.empty || !sver.repository.empty) continue; if (ver.version_ <= sver.version_) continue; - logInfo("Package %s would be upgraded from %s to %s.", - basename, sver, ver); + logInfo("Upgrade", Color.yellow, + "%s would be upgraded %s to %s.", + basename.color(Mode.bold), sver, ver); any = true; } - if (any) logInfo("Use \"dub upgrade\" to perform those changes."); + if (any) logInfo("Use \"dub upgrade\" to perform those changes"); return; } @@ -727,7 +728,7 @@ class Dub { /// Cleans intermediate/cache files of the given package void cleanPackage(NativePath path) { - logInfo("Cleaning package at %s...", path.toNativeString()); + logInfo("Cleaning", Color.green, "package at %s", path.toNativeString()); enforce(!Package.findPackageFile(path).empty, "No package found.", path.toNativeString()); // TODO: clear target files and copy files @@ -798,8 +799,8 @@ class Dub { } } - if (reason.length) logInfo("Fetching %s %s (%s)...", packageId, ver, reason); - else logInfo("Fetching %s %s...", packageId, ver); + if (reason.length) logInfo("Fetching", Color.yellow, "%s %s (%s)", packageId, ver, reason); + else logInfo("Fetching", Color.yellow, "%s %s", packageId, ver); if (m_dryRun) return null; logDebug("Acquiring package zip file"); diff --git a/source/dub/generators/build.d b/source/dub/generators/build.d index d9f9113df..b7f0bb153 100644 --- a/source/dub/generators/build.d +++ b/source/dub/generators/build.d @@ -82,8 +82,10 @@ class BuildGenerator : ProjectGenerator { enforce(!(settings.rdmd && root_ti.buildSettings.targetType == TargetType.none), "Building package with target type \"none\" with rdmd is not supported yet."); - logInfo("Performing \"%s\" build using %s for %-(%s, %).", - settings.buildType, settings.platform.compilerBinary, settings.platform.architecture); + logInfo("Starting", Color.green, + "Performing \"%s\" build using %s for %-(%s, %).", + settings.buildType.color(Color.magenta), settings.platform.compilerBinary, + settings.platform.architecture); bool any_cached = false; @@ -152,7 +154,9 @@ class BuildGenerator : ProjectGenerator { buildTargetRec(m_project.rootPackage.name); if (any_cached) { - logInfo("To force a rebuild of up-to-date targets, run again with --force."); + logInfo("Finished", Color.green, + "To force a rebuild of up-to-date targets, run again with --force" + ); } } } @@ -203,7 +207,7 @@ class BuildGenerator : ProjectGenerator { // run post-build commands if (!cached && buildsettings.postBuildCommands.length) { - logInfo("Running post-build commands..."); + logInfo("Post-build", Color.green, "Running commands"); runBuildCommands(CommandType.postBuild, buildsettings.postBuildCommands, pack, m_project, settings, buildsettings, [["DUB_BUILD_PATH" : target_path.parentPath.toNativeString.absolutePath]]); } @@ -224,7 +228,7 @@ class BuildGenerator : ProjectGenerator { else target_path = pack.path ~ format(".dub/build/%s/", build_id); if (!settings.force && isUpToDate(target_path, buildsettings, settings, pack, packages, additional_dep_files)) { - logInfo("%s %s: target for configuration \"%s\" is up to date.", pack.name, pack.version_, config); + logInfo("Up-to-date", Color.green, "%s %s [%s]", pack.name.color(Mode.bold), pack.version_, config); logDiagnostic("Using existing build in %s.", target_path.toNativeString()); target_binary_path = target_path ~ settings.compiler.getTargetFileName(buildsettings, settings.platform); if (!settings.tempBuild) @@ -239,10 +243,10 @@ class BuildGenerator : ProjectGenerator { return false; } - logInfo("%s %s: building configuration \"%s\"...", pack.name, pack.version_, config); + logInfo("Building", Color.green, "%s %s [%s]", pack.name.color(Mode.bold), pack.version_, config.color(Color.blue)); if( buildsettings.preBuildCommands.length ){ - logInfo("Running pre-build commands..."); + logInfo("Pre-build", Color.green, "Running commands"); runBuildCommands(CommandType.preBuild, buildsettings.preBuildCommands, pack, m_project, settings, buildsettings); } @@ -304,11 +308,11 @@ class BuildGenerator : ProjectGenerator { flags ~= mainsrc.relativeTo(cwd).toNativeString(); if (buildsettings.preBuildCommands.length){ - logInfo("Running pre-build commands..."); + logInfo("Pre-build", Color.green, "Running commands"); runCommands(buildsettings.preBuildCommands); } - logInfo("%s %s: building configuration \"%s\"...", pack.name, pack.version_, config); + logInfo("Building", Color.green, "%s %s [%s]", pack.name.color(Mode.bold), pack.version_, config.color(Color.blue)); logInfo("Running rdmd..."); logDiagnostic("rdmd %s", join(flags, " ")); @@ -335,7 +339,7 @@ class BuildGenerator : ProjectGenerator { f = fp.toNativeString(); } - logInfo("%s %s: building configuration \"%s\"...", pack.name, pack.version_, config); + logInfo("Building", Color.green, "%s %s [%s]", pack.name.color(Mode.bold), pack.version_, config.color(Color.blue)); // make all target/import paths relative string makeRelative(string path) { @@ -362,7 +366,7 @@ class BuildGenerator : ProjectGenerator { } if( buildsettings.preBuildCommands.length ){ - logInfo("Running pre-build commands..."); + logInfo("Pre-build", Color.green, "Running commands"); runBuildCommands(CommandType.preBuild, buildsettings.preBuildCommands, pack, m_project, settings, buildsettings); } @@ -525,7 +529,7 @@ class BuildGenerator : ProjectGenerator { auto objs = new string[](srcs.walkLength); void compileSource(size_t i, string src) { - logInfo("Compiling %s...", src); + logInfo("Compiling", Color.green, "%s", src); const objPath = pathToObjName(settings.platform, src); objs[i] = compileUnit(src, objPath, buildsettings, settings); } @@ -536,7 +540,7 @@ class BuildGenerator : ProjectGenerator { foreach (i, src; srcs.array) compileSource(i, src); } - logInfo("Linking..."); + logInfo("Linking", Color.green, "%s", buildsettings.targetName.color(Mode.bold)); lbuildsettings.sourceFiles = is_static_library ? [] : lbuildsettings.sourceFiles.filter!(f => isLinkerFile(settings.platform, f)).array; settings.compiler.setTarget(lbuildsettings, settings.platform); settings.compiler.prepareBuildSettings(lbuildsettings, settings.platform, BuildSetting.commandLineSeparate|BuildSetting.sourceFiles); @@ -575,7 +579,7 @@ class BuildGenerator : ProjectGenerator { settings.compiler.invoke(buildsettings, settings.platform, settings.compileCallback); if (generate_binary) { - logInfo("Linking..."); + logInfo("Linking", Color.green, "%s", buildsettings.targetName.color(Mode.bold)); settings.compiler.invokeLinker(lbuildsettings, settings.platform, [tempobj.toNativeString()], settings.linkCallback); } } @@ -592,7 +596,7 @@ class BuildGenerator : ProjectGenerator { } if (!exe_file_path.absolute) exe_file_path = cwd ~ exe_file_path; runPreRunCommands(m_project.rootPackage, m_project, settings, buildsettings); - logInfo("Running %s %s", exe_file_path.relativeTo(runcwd), run_args.join(" ")); + logInfo("Running", Color.green, "%s %s", exe_file_path.relativeTo(runcwd), run_args.join(" ")); string[string] env; foreach (aa; [buildsettings.environments, buildsettings.runEnvironments]) foreach (k, v; aa) From c0d919cac0b1b534267d803a68d992f9b459569d Mon Sep 17 00:00:00 2001 From: Giacomo De Lazzari Date: Sat, 9 Jun 2018 02:00:03 +0200 Subject: [PATCH 05/42] Fix tabs in logging module (using spaces) --- source/dub/logging.d | 94 ++++++++++++++++++++++---------------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/source/dub/logging.d b/source/dub/logging.d index f3dd5c12b..6be615ddf 100644 --- a/source/dub/logging.d +++ b/source/dub/logging.d @@ -1,5 +1,5 @@ /** - Handles all the console output of the Dub package manager, by providing useful + Handles all the console output of the Dub package manager, by providing useful methods for handling colored text. The module also disables colors when stdout and stderr are not a TTY in order to avoid ASCII escape sequences in piped output. The module can autodetect and configure itself in this regard by @@ -46,9 +46,9 @@ logInfo("Tag", Color.green, "My %s message", "colored".color(Color.red)) - Copyright: © 2018 Giacomo De Lazzari - License: Subject to the terms of the MIT license, as written in the included LICENSE file. - Authors: Giacomo De Lazzari + Copyright: © 2018 Giacomo De Lazzari + License: Subject to the terms of the MIT license, as written in the included LICENSE file. + Authors: Giacomo De Lazzari */ module dub.logging; @@ -72,12 +72,12 @@ private const int TAG_WIDTH = 12; /// Possible log levels supported enum LogLevel { - debug_, - diagnostic, - info, - warn, - error, - none + debug_, + diagnostic, + info, + warn, + error, + none } // The current minimum log level to be printed @@ -93,13 +93,13 @@ private bool _printColors = true; /// Sets the minimum log level to be printed void setLogLevel(LogLevel level) nothrow { - _minLevel = level; + _minLevel = level; } /// Gets the minimum log level to be printed LogLevel getLogLevel() { - return _minLevel; + return _minLevel; } /// Set whether to print colors or not @@ -109,12 +109,12 @@ void printColorsInLog(bool enabled) } /** - Shorthand function to log a message with debug/diagnostic level, no tag string + Shorthand function to log a message with debug/diagnostic level, no tag string or tag color required (since there will be no tag). - Params: - level = The log level for the logged message - fmt = See http://dlang.org/phobos/std_format.html#format-string + Params: + level = The log level for the logged message + fmt = See http://dlang.org/phobos/std_format.html#format-string */ void logDebug(T...)(string fmt, lazy T args) nothrow { @@ -128,14 +128,14 @@ void logDiagnostic(T...)(string fmt, lazy T args) nothrow } /** - Shorthand function to log a message with info level, with custom tag string + Shorthand function to log a message with info level, with custom tag string and tag color. - Params: + Params: tag = The string the tag at the beginning of the line should contain tagColor = The color the tag string should have - level = The log level for the logged message - fmt = See http://dlang.org/phobos/std_format.html#format-string + level = The log level for the logged message + fmt = See http://dlang.org/phobos/std_format.html#format-string */ void logInfo(T...)(string tag, Color tagColor, string fmt, lazy T args) nothrow { @@ -143,13 +143,13 @@ void logInfo(T...)(string tag, Color tagColor, string fmt, lazy T args) nothrow } /** - Shorthand function to log a message with info level, this version prints an + Shorthand function to log a message with info level, this version prints an empty tag automatically (which is different from not having a tag - in this case there will be an identation of TAG_WIDTH chars on the left anyway). - Params: - level = The log level for the logged message - fmt = See http://dlang.org/phobos/std_format.html#format-string + Params: + level = The log level for the logged message + fmt = See http://dlang.org/phobos/std_format.html#format-string */ void logInfo(T...)(string fmt, lazy T args) nothrow if (!is(T[0] : Color)) { @@ -157,13 +157,13 @@ void logInfo(T...)(string fmt, lazy T args) nothrow if (!is(T[0] : Color)) } /** - Shorthand function to log a message with warning level, with custom tag string. + Shorthand function to log a message with warning level, with custom tag string. The tag color is fixed to yellow. - Params: + Params: tag = The string the tag at the beginning of the line should contain - level = The log level for the logged message - fmt = See http://dlang.org/phobos/std_format.html#format-string + level = The log level for the logged message + fmt = See http://dlang.org/phobos/std_format.html#format-string */ void logWarnTag(T...)(string tag, string fmt, lazy T args) nothrow { @@ -171,12 +171,12 @@ void logWarnTag(T...)(string tag, string fmt, lazy T args) nothrow } /** - Shorthand function to log a message with warning level, using the default + Shorthand function to log a message with warning level, using the default tag "Warning". The tag color is also fixed to yellow. - Params: - level = The log level for the logged message - fmt = See http://dlang.org/phobos/std_format.html#format-string + Params: + level = The log level for the logged message + fmt = See http://dlang.org/phobos/std_format.html#format-string */ void logWarn(T...)(string fmt, lazy T args) nothrow { @@ -184,13 +184,13 @@ void logWarn(T...)(string fmt, lazy T args) nothrow } /** - Shorthand function to log a message with error level, with custom tag string. + Shorthand function to log a message with error level, with custom tag string. The tag color is fixed to red. - Params: + Params: tag = The string the tag at the beginning of the line should contain - level = The log level for the logged message - fmt = See http://dlang.org/phobos/std_format.html#format-string + level = The log level for the logged message + fmt = See http://dlang.org/phobos/std_format.html#format-string */ void logErrorTag(T...)(string tag, string fmt, lazy T args) nothrow { @@ -198,12 +198,12 @@ void logErrorTag(T...)(string tag, string fmt, lazy T args) nothrow } /** - Shorthand function to log a message with error level, using the default + Shorthand function to log a message with error level, using the default tag "Error". The tag color is also fixed to red. - Params: - level = The log level for the logged message - fmt = See http://dlang.org/phobos/std_format.html#format-string + Params: + level = The log level for the logged message + fmt = See http://dlang.org/phobos/std_format.html#format-string */ void logError(T...)(string fmt, lazy T args) nothrow { @@ -211,15 +211,15 @@ void logError(T...)(string fmt, lazy T args) nothrow } /** - Log a message with the specified log level and with the specified tag string + Log a message with the specified log level and with the specified tag string and color. If the log level is debug or diagnostic, the tag is not printed thus the tag string and tag color will be ignored. - Params: - level = The log level for the logged message + Params: + level = The log level for the logged message tag = The string the tag at the beginning of the line should contain tagColor = The color the tag string should have - fmt = See http://dlang.org/phobos/std_format.html#format-string + fmt = See http://dlang.org/phobos/std_format.html#format-string */ void log(T...)( LogLevel level, @@ -229,7 +229,7 @@ void log(T...)( lazy T args ) nothrow { - if (level < _minLevel) + if (level < _minLevel) return; auto hasTag = true; @@ -255,8 +255,8 @@ void log(T...)( } catch (Exception e) { - debug assert(false, e.msg); - } + debug assert(false, e.msg); + } } /** From d943fae3fdf2857afdfb3d709a46eb3c06021f75 Mon Sep 17 00:00:00 2001 From: Giacomo De Lazzari Date: Sat, 9 Jun 2018 20:26:36 +0200 Subject: [PATCH 06/42] Fix build script --- build-files.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/build-files.txt b/build-files.txt index ed0aaa791..e22bcd508 100644 --- a/build-files.txt +++ b/build-files.txt @@ -34,12 +34,16 @@ source/dub/internal/sdlang/util.d source/dub/internal/undead/xml.d source/dub/internal/utils.d source/dub/internal/vibecompat/core/file.d -source/dub/internal/vibecompat/core/log.d source/dub/internal/vibecompat/data/json.d source/dub/internal/vibecompat/data/serialization.d source/dub/internal/vibecompat/data/utils.d source/dub/internal/vibecompat/inet/path.d source/dub/internal/vibecompat/inet/url.d +source/dub/internal/colorize/colors.d +source/dub/internal/colorize/cwrite.d +source/dub/internal/colorize/package.d +source/dub/internal/colorize/winterm.d +source/dub/logging.d source/dub/package_.d source/dub/packagemanager.d source/dub/packagesupplier.d From 86d785bfa491e0923a67ade533d8f54a87690a14 Mon Sep 17 00:00:00 2001 From: Giacomo De Lazzari Date: Mon, 11 Jun 2018 12:33:07 +0200 Subject: [PATCH 07/42] Add possibility to log without tag Added logging helper function logInfoNoTag --- source/dub/logging.d | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/source/dub/logging.d b/source/dub/logging.d index 6be615ddf..d81b3ce0e 100644 --- a/source/dub/logging.d +++ b/source/dub/logging.d @@ -118,13 +118,13 @@ void printColorsInLog(bool enabled) */ void logDebug(T...)(string fmt, lazy T args) nothrow { - log(LogLevel.debug_, "", Color.init, fmt, args); + log(LogLevel.debug_, false, "", Color.init, fmt, args); } /// ditto void logDiagnostic(T...)(string fmt, lazy T args) nothrow { - log(LogLevel.diagnostic, "", Color.init, fmt, args); + log(LogLevel.diagnostic, false, "", Color.init, fmt, args); } /** @@ -139,7 +139,7 @@ void logDiagnostic(T...)(string fmt, lazy T args) nothrow */ void logInfo(T...)(string tag, Color tagColor, string fmt, lazy T args) nothrow { - log(LogLevel.info, tag, tagColor, fmt, args); + log(LogLevel.info, false, tag, tagColor, fmt, args); } /** @@ -153,7 +153,20 @@ void logInfo(T...)(string tag, Color tagColor, string fmt, lazy T args) nothrow */ void logInfo(T...)(string fmt, lazy T args) nothrow if (!is(T[0] : Color)) { - log(LogLevel.info, "", Color.init, fmt, args); + log(LogLevel.info, false, "", Color.init, fmt, args); +} + +/** + Shorthand function to log a message with info level, this version doesn't + print a tag at all, it effectively just prints the given string. + + Params: + level = The log level for the logged message + fmt = See http://dlang.org/phobos/std_format.html#format-string +*/ +void logInfoNoTag(T...)(string fmt, lazy T args) nothrow if (!is(T[0] : Color)) +{ + log(LogLevel.info, true, "", Color.init, fmt, args); } /** @@ -167,7 +180,7 @@ void logInfo(T...)(string fmt, lazy T args) nothrow if (!is(T[0] : Color)) */ void logWarnTag(T...)(string tag, string fmt, lazy T args) nothrow { - log(LogLevel.warn, tag, Color.yellow, fmt, args); + log(LogLevel.warn, false, tag, Color.yellow, fmt, args); } /** @@ -180,7 +193,7 @@ void logWarnTag(T...)(string tag, string fmt, lazy T args) nothrow */ void logWarn(T...)(string fmt, lazy T args) nothrow { - log(LogLevel.warn, "Warning", Color.yellow, fmt, args); + log(LogLevel.warn, false, "Warning", Color.yellow, fmt, args); } /** @@ -194,7 +207,7 @@ void logWarn(T...)(string fmt, lazy T args) nothrow */ void logErrorTag(T...)(string tag, string fmt, lazy T args) nothrow { - log(LogLevel.error, tag, Color.red, fmt, args); + log(LogLevel.error, false, tag, Color.red, fmt, args); } /** @@ -207,7 +220,7 @@ void logErrorTag(T...)(string tag, string fmt, lazy T args) nothrow */ void logError(T...)(string fmt, lazy T args) nothrow { - log(LogLevel.error, "Error", Color.red, fmt, args); + log(LogLevel.error, false, "Error", Color.red, fmt, args); } /** @@ -217,12 +230,14 @@ void logError(T...)(string fmt, lazy T args) nothrow Params: level = The log level for the logged message + disableTag = Setting this to true disables the tag, no matter what tag = The string the tag at the beginning of the line should contain tagColor = The color the tag string should have fmt = See http://dlang.org/phobos/std_format.html#format-string */ void log(T...)( LogLevel level, + bool disableTag, string tag, Color tagColor, string fmt, @@ -235,6 +250,8 @@ void log(T...)( auto hasTag = true; if (level <= LogLevel.diagnostic) hasTag = false; + if (disableTag) + hasTag = false; try { From 081d1a9d8d469fdb35d72ae72d457151041d2e49 Mon Sep 17 00:00:00 2001 From: Giacomo De Lazzari Date: Mon, 11 Jun 2018 12:51:31 +0200 Subject: [PATCH 08/42] Fixed output of some commands Some commands look ugly with the tag-based logging, now using logInfoNoTag to print "normally" like before. --- source/dub/commandline.d | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/source/dub/commandline.d b/source/dub/commandline.d index 13a02c89b..864b07310 100644 --- a/source/dub/commandline.d +++ b/source/dub/commandline.d @@ -1875,9 +1875,9 @@ class FetchCommand : FetchRemoveCommand { } else { try { dub.fetch(name, Dependency.any, location, fetchOpts); - logInfo( - "Please note that you need to use `dub run ` " ~ - "or add it to dependencies of your package to actually use/run it."); + logInfo("Finished", Color.green, "package fetched"); + logInfo("Please note that you need to use `dub run ` or add it"); + logInfo("to dependencies of your package to actually use/run it."); } catch(Exception e){ logInfo("Getting a release version failed: %s", e.msg); @@ -2086,10 +2086,10 @@ class ListCommand : Command { const pname = pinfo.name; const pvlim = Dependency(pinfo.version_ == "" ? "*" : pinfo.version_); enforceUsage(app_args.length == 0, "The list command supports no application arguments."); - logInfo("Packages present in the system and known to dub:"); + logInfoNoTag("Packages present in the system and known to dub:"); foreach (p; dub.packageManager.getPackageIterator()) { if ((pname == "" || pname == p.name) && pvlim.matches(p.version_)) - logInfo(" %s %s: %s", p.name, p.version_, p.path.toNativeString()); + logInfo(" %s %s: %s", p.name.color(Mode.bold), p.version_, p.path.toNativeString()); } logInfo(""); return 0; @@ -2124,9 +2124,9 @@ class SearchCommand : Command { justify += (~justify & 3) + 1; // round to next multiple of 4 foreach (desc, matches; res) { - logInfo("==== %s ====", desc); + logInfoNoTag("%s", desc); foreach (m; matches) - logInfo("%s%s", leftJustify(m.name ~ " (" ~ m.version_ ~ ")", justify), m.description); + logInfoNoTag(" %s%s", leftJustify(m.name ~ " (" ~ m.version_ ~ ")", justify), m.description); } return 0; } From 6fd58d4d272dae5cfc7a4df2d3689d94da71b9f9 Mon Sep 17 00:00:00 2001 From: Giacomo De Lazzari Date: Sun, 10 Jun 2018 01:13:00 +0200 Subject: [PATCH 09/42] Now checks if the output is a console or not This allows to disable colors accordingly, to avoid ASCII escape sequences in piped output. !!! tested only on Linux. Also: minor documentation improvements --- source/dub/commandline.d | 4 +++ source/dub/logging.d | 71 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 71 insertions(+), 4 deletions(-) diff --git a/source/dub/commandline.d b/source/dub/commandline.d index 864b07310..6cfe40afa 100644 --- a/source/dub/commandline.d +++ b/source/dub/commandline.d @@ -398,6 +398,10 @@ int runDubCommandLine(string[] args) return [args0, "run", "-q", "--temp-build", "--single", file, "--"] ~ trailing; } + // Initialize the logging module, ensure that whether stdout/stderr are a TTY + // or not is detected in order to disable colors if the output isn't a console + initLogging(); + logDiagnostic("DUB version %s", getDUBVersion()); version(Windows){ diff --git a/source/dub/logging.d b/source/dub/logging.d index d81b3ce0e..18fb642d3 100644 --- a/source/dub/logging.d +++ b/source/dub/logging.d @@ -62,12 +62,20 @@ import dub.internal.colorize : fg, mode; /** An enum listing possible colors for terminal output, useful to set the color - of a tag + of a tag. Re-exported from d-colorize in dub.internal.colorize. See the enum + definition there for a list of possible values. */ public alias Color = fg; + +/** + An enum listing possible text "modes" for terminal output, useful to set the + text to bold, underline, blinking, etc... + Re-exported from d-colorize in dub.internal.colorize. See the enum definition + there for a list of possible values. +*/ public alias Mode = mode; -/// The tag width in chars +/// The tag width in chars, defined as a constant here private const int TAG_WIDTH = 12; /// Possible log levels supported @@ -90,6 +98,52 @@ private LogLevel _minLevel = LogLevel.info; */ private bool _printColors = true; +// isatty() is used in initLogging() to detect whether or not we are on a TTY +extern (C) int isatty(int); + +/** + This function must be called at the beginning for the program, before any + logging occurs. It will detect whether or not stdout/stderr are a console/TTY + and will consequently disable colored output if needed. + + Forgetting to call the function will result in ASCII escape sequences in the + piped output, probably an undesiderable thing. +*/ +void initLogging() +{ + import core.stdc.stdio; + + // Initially enable colors, we'll disable them during this functions if we + // find any reason to + _printColors = true; + + // The following stuff depends on the platform + version (Windows) + { + version (CRuntime_DigitalMars) + { + if (!isatty(core.stdc.stdio.stdout) || + !isatty(core.stdc.stdio.stderr)) + _printColors = false; + } + else version (CRuntime_Microsoft) + { + if (!isatty(fileno(core.stdc.stdio.stdout)) || + !isatty(fileno(core.stdc.stdio.stderr))) + _printColors = false; + } + else + _printColors = false; + } + else version (Posix) + { + import core.sys.posix.unistd; + + if (!isatty(STDERR_FILENO) || !isatty(STDOUT_FILENO)) + _printColors = false; + } +} + /// Sets the minimum log level to be printed void setLogLevel(LogLevel level) nothrow { @@ -287,13 +341,18 @@ void log(T...)( without worring whether or not colored output is enabled or not. Also a mode can be specified, such as bold/underline/etc... + + Params: + str = The string to color + color = The color to apply + mode = An optional mode, such as bold/underline/etc... */ -string color(const string str, const Color c, const Mode m = Mode.init) +string color(const string str, const Color color, const Mode mode = Mode.init) { import dub.internal.colorize; if (_printColors == true) - return dub.internal.colorize.color(str, c, bg.init, m); + return dub.internal.colorize.color(str, color, bg.init, mode); else return str; } @@ -302,6 +361,10 @@ string color(const string str, const Color c, const Mode m = Mode.init) This function is the same as the above one, but just accepts a mode. It's useful, for instance, when outputting bold text without changing the color. + + Params: + str = The string to color + mode = The mode, such as bold/underline/etc... */ string color(const string str, const Mode m = Mode.init) { From 3bfc2e947ed3746b989ef9b418fd03f68cb3cd8d Mon Sep 17 00:00:00 2001 From: Giacomo De Lazzari Date: Mon, 11 Jun 2018 15:13:07 +0200 Subject: [PATCH 10/42] Fix logging module settings with threads Settings such as minimum log output level or whether to print colors or not were thread-local and thus caused problems when multiple threads were spawned (such as with --parallel) --- source/dub/logging.d | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/dub/logging.d b/source/dub/logging.d index 18fb642d3..42235ddff 100644 --- a/source/dub/logging.d +++ b/source/dub/logging.d @@ -89,14 +89,14 @@ enum LogLevel { } // The current minimum log level to be printed -private LogLevel _minLevel = LogLevel.info; +private shared LogLevel _minLevel = LogLevel.info; /* Whether to print text with colors or not, defaults to true but will be set to false in initLogging() if stdout or stderr are not a TTY (which means the output is probably being piped and we don't want ASCII escape chars in it) */ -private bool _printColors = true; +private shared bool _printColors = true; // isatty() is used in initLogging() to detect whether or not we are on a TTY extern (C) int isatty(int); From 658e20d00ce39febcb4fc79e5401fed10bba6e61 Mon Sep 17 00:00:00 2001 From: Giacomo De Lazzari Date: Mon, 11 Jun 2018 15:26:36 +0200 Subject: [PATCH 11/42] Removed cwrite from colorize unittests --- source/dub/internal/colorize/colors.d | 8 -------- 1 file changed, 8 deletions(-) diff --git a/source/dub/internal/colorize/colors.d b/source/dub/internal/colorize/colors.d index 255588726..f125ac31c 100644 --- a/source/dub/internal/colorize/colors.d +++ b/source/dub/internal/colorize/colors.d @@ -77,27 +77,21 @@ string color( unittest { - import colorize.cwrite; string ret; ret = "This is yellow".color(fg.yellow); - cwriteln(ret); assert(ret == "\033[33mThis is yellow\033[0m"); ret = "This is light green".color(fg.light_green); - cwriteln(ret); assert(ret == "\033[92mThis is light green\033[0m"); ret = "This is light blue with red background".color(fg.light_blue, bg.red); - cwriteln(ret); assert(ret == "\033[0;94;41mThis is light blue with red background\033[0m"); ret = "This is red on blue blinking".color(fg.red, bg.blue, mode.blink); - cwriteln(ret); assert(ret == "\033[5;31;44mThis is red on blue blinking\033[0m"); ret = color("This is magenta", "magenta"); - cwriteln(ret); assert(ret == "\033[35mThis is magenta\033[0m"); } @@ -180,7 +174,6 @@ alias colorHelper color; unittest { - import colorize.cwrite; string ret; ret = "This is red on blue blinking" @@ -188,6 +181,5 @@ unittest .background(bg.blue) .style(mode.blink); - cwriteln(ret); assert(ret == "\033[5m\033[44m\033[31mThis is red on blue blinking\033[0m\033[0m\033[0m"); } From 262c6604794f0f9a1490c9b0e48f691555f56370 Mon Sep 17 00:00:00 2001 From: Giacomo De Lazzari Date: Mon, 11 Jun 2018 15:30:52 +0200 Subject: [PATCH 12/42] Re-added dub.internal.vibecompat.core.log as deprecated I simply aliases the new dub.logging module, printing a deprecation message while compiling --- source/dub/internal/vibecompat/core/log.d | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 source/dub/internal/vibecompat/core/log.d diff --git a/source/dub/internal/vibecompat/core/log.d b/source/dub/internal/vibecompat/core/log.d new file mode 100644 index 000000000..d352e8a35 --- /dev/null +++ b/source/dub/internal/vibecompat/core/log.d @@ -0,0 +1,14 @@ +/** +deprecated("Please use dub.logging") + This module contained logging functions, but has been replaced by dub.logging + which provides colored output and other facilities. + + Copyright: © 2012 rejectedsoftware e.K., © 2018 Giacomo De Lazzari + License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. + Authors: Sönke Ludwig, Giacomo De Lazzari +*/ + +deprecated("Please use dub.logging") + +module dub.internal.vibecompat.core.log; + +public import dub.logging; From 7cbb18fc1885dc80fa9f0d2a347dcab823f0b339 Mon Sep 17 00:00:00 2001 From: Giacomo De Lazzari Date: Mon, 11 Jun 2018 15:37:01 +0200 Subject: [PATCH 13/42] Updated file list for build script Added back dub/internal/vibecompat/code/log.d, not sure if necessary. dub/packagesupplier.d is in the list even if it's deprecated, so let's keep things consistent --- build-files.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/build-files.txt b/build-files.txt index e22bcd508..8c32a0f30 100644 --- a/build-files.txt +++ b/build-files.txt @@ -34,6 +34,7 @@ source/dub/internal/sdlang/util.d source/dub/internal/undead/xml.d source/dub/internal/utils.d source/dub/internal/vibecompat/core/file.d +source/dub/internal/vibecompat/core/log.d source/dub/internal/vibecompat/data/json.d source/dub/internal/vibecompat/data/serialization.d source/dub/internal/vibecompat/data/utils.d From e4dddef813f6ea493c8395eb9812788f5915a8cf Mon Sep 17 00:00:00 2001 From: Giacomo De Lazzari Date: Mon, 11 Jun 2018 15:53:11 +0200 Subject: [PATCH 14/42] Bold tag for errors and warnings Minor documentation improvements --- source/dub/logging.d | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/source/dub/logging.d b/source/dub/logging.d index 42235ddff..a9b147f6c 100644 --- a/source/dub/logging.d +++ b/source/dub/logging.d @@ -280,7 +280,9 @@ void logError(T...)(string fmt, lazy T args) nothrow /** Log a message with the specified log level and with the specified tag string and color. If the log level is debug or diagnostic, the tag is not printed - thus the tag string and tag color will be ignored. + thus the tag string and tag color will be ignored. If the log level is error + or warning, the tag will be in bold text. Also the tag can be disabled (for + any log level) by passing true as the second argument. Params: level = The log level for the logged message @@ -307,12 +309,16 @@ void log(T...)( if (disableTag) hasTag = false; + auto boldTag = false; + if (level >= LogLevel.warn) + boldTag = true; + try { string result = format(fmt, args); if (hasTag) - result = tag.rightJustify(TAG_WIDTH, ' ').color(tagColor) ~ " " ~ result; + result = tag.rightJustify(TAG_WIDTH, ' ').color(tagColor, boldTag ? Mode.bold : Mode.init) ~ " " ~ result; import dub.internal.colorize : cwrite; From 3875a570eefbdf0ae4f2f50a4d72698d80b15ede Mon Sep 17 00:00:00 2001 From: Giacomo De Lazzari Date: Mon, 11 Jun 2018 16:11:51 +0200 Subject: [PATCH 15/42] More improvements and replacements Adapted generators output to new style, small change for non-selected packages --- source/dub/dub.d | 4 ++-- source/dub/generators/cmake.d | 7 ++++++- source/dub/generators/generator.d | 4 ++-- source/dub/generators/sublimetext.d | 2 +- source/dub/generators/visuald.d | 2 +- 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/source/dub/dub.d b/source/dub/dub.d index bdd59bbc6..5d8e46cbd 100644 --- a/source/dub/dub.d +++ b/source/dub/dub.d @@ -549,8 +549,8 @@ class Dub { if (basename == rootbasename) continue; if (!m_project.selections.hasSelectedVersion(basename)) { - logInfo("Package %s would be selected with version %s.", - basename, ver); + logInfo("Upgrade", Color.yellow, + "Package %s would be selected with version %s", basename, ver); any = true; continue; } diff --git a/source/dub/generators/cmake.d b/source/dub/generators/cmake.d index 3bf84bb1a..97e67bd50 100644 --- a/source/dub/generators/cmake.d +++ b/source/dub/generators/cmake.d @@ -114,13 +114,16 @@ class CMakeGenerator: ProjectGenerator file.close; script.shrinkTo(0); scripts.put(filename); + + logInfo("Generated", Color.green, "%s.cmake", name); } if(!cmakeListsPath.existsFile) { logWarn("You must use a fork of CMake which has D support for these scripts to function properly."); logWarn("It is available at https://github.com/trentforkert/cmake"); - logInfo("Generating default CMakeLists.txt"); + logDiagnostic("Generating default CMakeLists.txt"); + script.put("cmake_minimum_required(VERSION 3.0)\n"); script.put("project(%s D)\n".format(m_project.rootPackage.name)); @@ -131,6 +134,8 @@ class CMakeGenerator: ProjectGenerator file.write(script.data); file.close; + + logInfo("Generated", Color.green, "CMakeLists.txt (default)"); } } } diff --git a/source/dub/generators/generator.d b/source/dub/generators/generator.d index a88affc37..e3e9571be 100644 --- a/source/dub/generators/generator.d +++ b/source/dub/generators/generator.d @@ -891,7 +891,7 @@ private void prepareGeneration(in Package pack, in Project proj, in GeneratorSet in BuildSettings buildsettings) { if (buildsettings.preGenerateCommands.length && !isRecursiveInvocation(pack.name)) { - logInfo("Running pre-generate commands for %s...", pack.name); + logInfo("Pre-gen", Color.green, "Running commands for %s", pack.name); runBuildCommands(CommandType.preGenerate, buildsettings.preGenerateCommands, pack, proj, settings, buildsettings); } } @@ -903,7 +903,7 @@ private void finalizeGeneration(in Package pack, in Project proj, in GeneratorSe in BuildSettings buildsettings, NativePath target_path, bool generate_binary) { if (buildsettings.postGenerateCommands.length && !isRecursiveInvocation(pack.name)) { - logInfo("Running post-generate commands for %s...", pack.name); + logInfo("Post-gen", Color.green, "Running commands for %s", pack.name); runBuildCommands(CommandType.postGenerate, buildsettings.postGenerateCommands, pack, proj, settings, buildsettings); } diff --git a/source/dub/generators/sublimetext.d b/source/dub/generators/sublimetext.d index 880d0beca..fd873ebcc 100644 --- a/source/dub/generators/sublimetext.d +++ b/source/dub/generators/sublimetext.d @@ -45,7 +45,7 @@ class SublimeTextGenerator : ProjectGenerator { write(projectPath, jsonString.data); - logInfo("Project '%s' generated.", projectPath); + logInfo("Generated", Color.green, "%s", projectPath); } } diff --git a/source/dub/generators/visuald.d b/source/dub/generators/visuald.d index 1eef903d3..f63ffc7bf 100644 --- a/source/dub/generators/visuald.d +++ b/source/dub/generators/visuald.d @@ -124,7 +124,7 @@ class VisualDGenerator : ProjectGenerator { sln.put(ret.data); sln.flush(); - logInfo("Solution '%s' generated.", solutionFileName()); + logInfo("Generated", Color.green, "%s (solution)", solutionFileName()); } From 543c89550608378122b1570b4e557a79678d9234 Mon Sep 17 00:00:00 2001 From: Giacomo De Lazzari Date: Mon, 11 Jun 2018 16:24:15 +0200 Subject: [PATCH 16/42] Improved dub init output Remove duplicate message (package created in ...) and using colored tag --- source/dub/dub.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/dub/dub.d b/source/dub/dub.d index 5d8e46cbd..786db3071 100644 --- a/source/dub/dub.d +++ b/source/dub/dub.d @@ -1142,7 +1142,7 @@ class Dub { } //Act smug to the user. - logInfo("Successfully created an empty project in '%s'.", path.toNativeString()); + logInfo("Success", Color.green, "created empty project in %s", path.toNativeString()); } private void runCustomInitialization(NativePath path, string type, string[] runArgs) From 2299775bcda034eb3a3e46843fa0d0f1e1966cc8 Mon Sep 17 00:00:00 2001 From: Giacomo De Lazzari Date: Mon, 11 Jun 2018 16:38:55 +0200 Subject: [PATCH 17/42] Output improvements in package management (dub fetch and dub remove) --- source/dub/commandline.d | 2 +- source/dub/dub.d | 9 ++++----- source/dub/packagemanager.d | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/source/dub/commandline.d b/source/dub/commandline.d index 6cfe40afa..3cf51216c 100644 --- a/source/dub/commandline.d +++ b/source/dub/commandline.d @@ -1879,7 +1879,7 @@ class FetchCommand : FetchRemoveCommand { } else { try { dub.fetch(name, Dependency.any, location, fetchOpts); - logInfo("Finished", Color.green, "package fetched"); + logInfo("Finished", Color.green, "%s fetched", name.color(Mode.bold)); logInfo("Please note that you need to use `dub run ` or add it"); logInfo("to dependencies of your package to actually use/run it."); } diff --git a/source/dub/dub.d b/source/dub/dub.d index 786db3071..529b685cb 100644 --- a/source/dub/dub.d +++ b/source/dub/dub.d @@ -794,13 +794,13 @@ class Dub { packageId, ver, placement); return existing; } else { - logInfo("Removing %s %s to prepare replacement with a new version.", packageId, ver); + logInfo("Removing", Color.yellow, "%s %s to prepare replacement with a new version", packageId.color(Mode.bold), ver); if (!m_dryRun) m_packageManager.remove(existing); } } - if (reason.length) logInfo("Fetching", Color.yellow, "%s %s (%s)", packageId, ver, reason); - else logInfo("Fetching", Color.yellow, "%s %s", packageId, ver); + if (reason.length) logInfo("Fetching", Color.yellow, "%s %s (%s)", packageId.color(Mode.bold), ver, reason); + else logInfo("Fetching", Color.yellow, "%s %s", packageId.color(Mode.bold), ver); if (m_dryRun) return null; logDebug("Acquiring package zip file"); @@ -852,7 +852,7 @@ class Dub { */ void remove(in Package pack) { - logInfo("Removing %s in %s", pack.name, pack.path.toNativeString()); + logInfo("Removing", Color.yellow, "%s (in %s)", pack.name.color(Mode.bold), pack.path.toNativeString()); if (!m_dryRun) m_packageManager.remove(pack); } @@ -915,7 +915,6 @@ class Dub { foreach(pack; packages) { try { remove(pack); - logInfo("Removed %s, version %s.", package_id, pack.version_); } catch (Exception e) { logError("Failed to remove %s %s: %s", package_id, pack.version_, e.msg); logInfo("Continuing with other packages (if any)."); diff --git a/source/dub/packagemanager.d b/source/dub/packagemanager.d index 42445266f..afab9de9a 100644 --- a/source/dub/packagemanager.d +++ b/source/dub/packagemanager.d @@ -633,7 +633,7 @@ class PackageManager { logDebug("About to delete root folder for package '%s'.", pack.path); rmdirRecurse(pack.path.toNativeString()); - logInfo("Removed package: '%s'", pack.name); + logInfo("Removed", Color.yellow, "%s %s", pack.name.color(Mode.bold), pack.version_); } /// Compatibility overload. Use the version without a `force_remove` argument instead. From 1793acec2934b245587a333b07c830dfb467d6e1 Mon Sep 17 00:00:00 2001 From: Giacomo De Lazzari Date: Mon, 11 Jun 2018 16:51:20 +0200 Subject: [PATCH 18/42] Fixed blue color missing for config in up-to-date --- source/dub/generators/build.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/dub/generators/build.d b/source/dub/generators/build.d index b7f0bb153..85e141a27 100644 --- a/source/dub/generators/build.d +++ b/source/dub/generators/build.d @@ -228,7 +228,7 @@ class BuildGenerator : ProjectGenerator { else target_path = pack.path ~ format(".dub/build/%s/", build_id); if (!settings.force && isUpToDate(target_path, buildsettings, settings, pack, packages, additional_dep_files)) { - logInfo("Up-to-date", Color.green, "%s %s [%s]", pack.name.color(Mode.bold), pack.version_, config); + logInfo("Up-to-date", Color.green, "%s %s [%s]", pack.name.color(Mode.bold), pack.version_, config.color(Color.blue)); logDiagnostic("Using existing build in %s.", target_path.toNativeString()); target_binary_path = target_path ~ settings.compiler.getTargetFileName(buildsettings, settings.platform); if (!settings.tempBuild) From b25779769f43fdbec7b12002e048792faf2e9bbc Mon Sep 17 00:00:00 2001 From: Giacomo De Lazzari Date: Mon, 11 Jun 2018 17:13:29 +0200 Subject: [PATCH 19/42] Fixed project upgrade message --- source/dub/commandline.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/dub/commandline.d b/source/dub/commandline.d index 3cf51216c..92a314a5a 100644 --- a/source/dub/commandline.d +++ b/source/dub/commandline.d @@ -1766,7 +1766,7 @@ class UpgradeCommand : Command { enforceUsage(app_args.length == 0, "Unexpected application arguments."); enforceUsage(!m_verify, "--verify is not yet implemented."); enforce(loadCwdPackage(dub, true), "Failed to load package."); - logInfo("Upgrading project in %s", dub.projectPath.toNativeString()); + logInfo("Upgrading", Color.yellow, "project in %s", dub.projectPath.toNativeString()); auto options = UpgradeOptions.upgrade|UpgradeOptions.select; if (m_missingOnly) options &= ~UpgradeOptions.upgrade; if (m_prerelease) options |= UpgradeOptions.preRelease; From 9b37a797a31a69483e673fd02fc6296183fadd77 Mon Sep 17 00:00:00 2001 From: Giacomo De Lazzari Date: Mon, 11 Jun 2018 17:56:07 +0200 Subject: [PATCH 20/42] Fix build on Windows --- source/dub/logging.d | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/dub/logging.d b/source/dub/logging.d index a9b147f6c..daa7a4f22 100644 --- a/source/dub/logging.d +++ b/source/dub/logging.d @@ -122,8 +122,8 @@ void initLogging() { version (CRuntime_DigitalMars) { - if (!isatty(core.stdc.stdio.stdout) || - !isatty(core.stdc.stdio.stderr)) + if (!isatty(core.stdc.stdio.stdout._file) || + !isatty(core.stdc.stdio.stderr._file)) _printColors = false; } else version (CRuntime_Microsoft) From 2426703aaaddc2fa2e6554bdc5eb1200a91d8750 Mon Sep 17 00:00:00 2001 From: Giacomo De Lazzari Date: Mon, 11 Jun 2018 23:43:50 +0200 Subject: [PATCH 21/42] Fixed 3 failing test cases Some test cases were failing because of the different output that Dub now has --- test/expected-issue1037-output | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/expected-issue1037-output b/test/expected-issue1037-output index 06fdbb100..9cbae8475 100644 --- a/test/expected-issue1037-output +++ b/test/expected-issue1037-output @@ -1,3 +1,3 @@ -Unresolvable dependencies to package gitcompatibledubpackage: + Error Unresolvable dependencies to package gitcompatibledubpackage: b @DIR/b depends on gitcompatibledubpackage ~>1.0.2 issue1037-better-dependency-messages ~master depends on gitcompatibledubpackage 1.0.1 From 3e62997d60d2df2a810720e3182850c66365d480 Mon Sep 17 00:00:00 2001 From: Giacomo De Lazzari Date: Mon, 11 Jun 2018 23:50:08 +0200 Subject: [PATCH 22/42] Fix PowerShell messed-up colors Now winterm.d (which provides partial ANSI/VT100 emulation for Windows console) respects bg.init and fg.init (Color.init in logging.d) and, when encountered, restores the background/foreground color that there was before instead of just setting it to black --- source/dub/internal/colorize/winterm.d | 30 ++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/source/dub/internal/colorize/winterm.d b/source/dub/internal/colorize/winterm.d index ef21981dc..3b12bb558 100644 --- a/source/dub/internal/colorize/winterm.d +++ b/source/dub/internal/colorize/winterm.d @@ -120,6 +120,28 @@ version(Windows) SetConsoleTextAttribute(_console, _currentAttr); } + // resets to the same foreground color that was set on initialize() + @nogc void resetForegroundColor() nothrow + { + if (!_savedInitialColor) + return; + + _currentAttr = _currentAttr & ~(FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY); + _currentAttr = _currentAttr | (consoleInfo.wAttributes & (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY)); + SetConsoleTextAttribute(_console, _currentAttr); + } + + // resets to the same background color that was set on initialize() + @nogc void resetBackgroundColor() nothrow + { + if (!_savedInitialColor) + return; + + _currentAttr = _currentAttr & ~(BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY); + _currentAttr = _currentAttr | (consoleInfo.wAttributes & (BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY)); + SetConsoleTextAttribute(_console, _currentAttr); + } + @nogc void executeAttribute(int attr) nothrow { switch (attr) @@ -142,6 +164,10 @@ version(Windows) color |= (attr & 1 ? FOREGROUND_RED : 0) | (attr & 2 ? FOREGROUND_GREEN : 0) | (attr & 4 ? FOREGROUND_BLUE : 0); setForegroundColor(color); } + else if (attr == 39) // fg.init + { + resetForegroundColor(); + } if ( (40 <= attr && attr <= 47) || (100 <= attr && attr <= 107) ) { @@ -155,6 +181,10 @@ version(Windows) color |= (attr & 1 ? BACKGROUND_RED : 0) | (attr & 2 ? BACKGROUND_GREEN : 0) | (attr & 4 ? BACKGROUND_BLUE : 0); setBackgroundColor(color); } + else if (attr == 49) // bg.init + { + resetBackgroundColor(); + } } } } From d3ee6a0837c0c55233b6f5de2925ef17941be9b1 Mon Sep 17 00:00:00 2001 From: Giacomo De Lazzari Date: Tue, 12 Jun 2018 00:31:18 +0200 Subject: [PATCH 23/42] Fix indentation style, now using tabs --- source/dub/generators/build.d | 4 +- source/dub/internal/colorize/colors.d | 220 +++++------ source/dub/internal/colorize/cwrite.d | 62 +-- source/dub/internal/colorize/winterm.d | 360 ++++++++--------- source/dub/internal/vibecompat/core/log.d | 4 +- source/dub/logging.d | 454 +++++++++++----------- source/dub/packagesuppliers/maven.d | 2 +- 7 files changed, 553 insertions(+), 553 deletions(-) diff --git a/source/dub/generators/build.d b/source/dub/generators/build.d index 85e141a27..80b678131 100644 --- a/source/dub/generators/build.d +++ b/source/dub/generators/build.d @@ -155,8 +155,8 @@ class BuildGenerator : ProjectGenerator { if (any_cached) { logInfo("Finished", Color.green, - "To force a rebuild of up-to-date targets, run again with --force" - ); + "To force a rebuild of up-to-date targets, run again with --force" + ); } } } diff --git a/source/dub/internal/colorize/colors.d b/source/dub/internal/colorize/colors.d index f125ac31c..f62ab2632 100644 --- a/source/dub/internal/colorize/colors.d +++ b/source/dub/internal/colorize/colors.d @@ -10,28 +10,28 @@ import std.string : format; private template color_type(int offset) { - static enum type : int - { - init = 39 + offset, - - black = 30 + offset, - red = 31 + offset, - green = 32 + offset, - yellow = 33 + offset, - blue = 34 + offset, - magenta = 35 + offset, - cyan = 36 + offset, - white = 37 + offset, - - light_black = 90 + offset, - light_red = 91 + offset, - light_green = 92 + offset, - light_yellow = 93 + offset, - light_blue = 94 + offset, - light_magenta = 95 + offset, - light_cyan = 96 + offset, - light_white = 97 + offset - } + static enum type : int + { + init = 39 + offset, + + black = 30 + offset, + red = 31 + offset, + green = 32 + offset, + yellow = 33 + offset, + blue = 34 + offset, + magenta = 35 + offset, + cyan = 36 + offset, + white = 37 + offset, + + light_black = 90 + offset, + light_red = 91 + offset, + light_green = 92 + offset, + light_yellow = 93 + offset, + light_blue = 94 + offset, + light_magenta = 95 + offset, + light_cyan = 96 + offset, + light_white = 97 + offset + } } alias color_type!0 .type fg; @@ -40,12 +40,12 @@ alias color_type!10 .type bg; // Text modes static enum mode : int { - init = 0, - bold = 1, - underline = 4, - blink = 5, - swap = 7, - hide = 8 + init = 0, + bold = 1, + underline = 4, + blink = 5, + swap = 7, + hide = 8 } /** @@ -66,101 +66,101 @@ static enum mode : int */ string color( - const string str, - const fg c=fg.init, - const bg b=bg.init, - const mode m=mode.init + const string str, + const fg c=fg.init, + const bg b=bg.init, + const mode m=mode.init ) pure { - return format("\033[%d;%d;%dm%s\033[0m", m, c, b, str); + return format("\033[%d;%d;%dm%s\033[0m", m, c, b, str); } unittest { - string ret; + string ret; - ret = "This is yellow".color(fg.yellow); - assert(ret == "\033[33mThis is yellow\033[0m"); + ret = "This is yellow".color(fg.yellow); + assert(ret == "\033[33mThis is yellow\033[0m"); - ret = "This is light green".color(fg.light_green); - assert(ret == "\033[92mThis is light green\033[0m"); + ret = "This is light green".color(fg.light_green); + assert(ret == "\033[92mThis is light green\033[0m"); - ret = "This is light blue with red background".color(fg.light_blue, bg.red); - assert(ret == "\033[0;94;41mThis is light blue with red background\033[0m"); + ret = "This is light blue with red background".color(fg.light_blue, bg.red); + assert(ret == "\033[0;94;41mThis is light blue with red background\033[0m"); - ret = "This is red on blue blinking".color(fg.red, bg.blue, mode.blink); - assert(ret == "\033[5;31;44mThis is red on blue blinking\033[0m"); + ret = "This is red on blue blinking".color(fg.red, bg.blue, mode.blink); + assert(ret == "\033[5;31;44mThis is red on blue blinking\033[0m"); - ret = color("This is magenta", "magenta"); - assert(ret == "\033[35mThis is magenta\033[0m"); + ret = color("This is magenta", "magenta"); + assert(ret == "\033[35mThis is magenta\033[0m"); } string colorHelper(const string str, const string name) pure { - int code; - - switch(name) - { - case "init": code = 39; break; - - case "black" : code = 30; break; - case "red" : code = 31; break; - case "green" : code = 32; break; - case "yellow" : code = 33; break; - case "blue" : code = 34; break; - case "magenta": code = 35; break; - case "cyan" : code = 36; break; - case "white" : code = 37; break; - - case "light_black" : code = 90; break; - case "light_red" : code = 91; break; - case "light_green" : code = 92; break; - case "light_yellow" : code = 93; break; - case "light_blue" : code = 94; break; - case "light_magenta": code = 95; break; - case "light_cyan" : code = 96; break; - case "light_white" : code = 97; break; - - case "bg_init": code = 49; break; - - case "bg_black" : code = 40; break; - case "bg_red" : code = 41; break; - case "bg_green" : code = 42; break; - case "bg_yellow" : code = 43; break; - case "bg_blue" : code = 44; break; - case "bg_magenta": code = 45; break; - case "bg_cyan" : code = 46; break; - case "bg_white" : code = 47; break; - - case "bg_light_black" : code = 100; break; - case "bg_light_red" : code = 101; break; - case "bg_light_green" : code = 102; break; - case "bg_light_yellow" : code = 103; break; - case "bg_light_blue" : code = 104; break; - case "bg_light_magenta": code = 105; break; - case "bg_light_cyan" : code = 106; break; - case "bg_light_white" : code = 107; break; - - case "mode_init": code = 0; break; - case "mode_bold" : code = 1; break; - case "mode_underline": code = 4; break; - case "mode_blink" : code = 5; break; - case "mode_swap" : code = 7; break; - case "mode_hide" : code = 8; break; - - default: - throw new Exception( - "Unknown fg color, bg color or mode \"" ~ name ~ "\"" - ); - } - - return format("\033[%dm%s\033[0m", code, str); + int code; + + switch(name) + { + case "init": code = 39; break; + + case "black" : code = 30; break; + case "red" : code = 31; break; + case "green" : code = 32; break; + case "yellow" : code = 33; break; + case "blue" : code = 34; break; + case "magenta": code = 35; break; + case "cyan" : code = 36; break; + case "white" : code = 37; break; + + case "light_black" : code = 90; break; + case "light_red" : code = 91; break; + case "light_green" : code = 92; break; + case "light_yellow" : code = 93; break; + case "light_blue" : code = 94; break; + case "light_magenta": code = 95; break; + case "light_cyan" : code = 96; break; + case "light_white" : code = 97; break; + + case "bg_init": code = 49; break; + + case "bg_black" : code = 40; break; + case "bg_red" : code = 41; break; + case "bg_green" : code = 42; break; + case "bg_yellow" : code = 43; break; + case "bg_blue" : code = 44; break; + case "bg_magenta": code = 45; break; + case "bg_cyan" : code = 46; break; + case "bg_white" : code = 47; break; + + case "bg_light_black" : code = 100; break; + case "bg_light_red" : code = 101; break; + case "bg_light_green" : code = 102; break; + case "bg_light_yellow" : code = 103; break; + case "bg_light_blue" : code = 104; break; + case "bg_light_magenta": code = 105; break; + case "bg_light_cyan" : code = 106; break; + case "bg_light_white" : code = 107; break; + + case "mode_init": code = 0; break; + case "mode_bold" : code = 1; break; + case "mode_underline": code = 4; break; + case "mode_blink" : code = 5; break; + case "mode_swap" : code = 7; break; + case "mode_hide" : code = 8; break; + + default: + throw new Exception( + "Unknown fg color, bg color or mode \"" ~ name ~ "\"" + ); + } + + return format("\033[%dm%s\033[0m", code, str); } string colorHelper(T)(const string str, const T t=T.init) pure - if(is(T : fg) || is(T : bg) || is(T : mode)) + if(is(T : fg) || is(T : bg) || is(T : mode)) { - return format("\033[%dm%s\033[0m", t, str); + return format("\033[%dm%s\033[0m", t, str); } alias colorHelper!bg background; @@ -174,12 +174,12 @@ alias colorHelper color; unittest { - string ret; + string ret; - ret = "This is red on blue blinking" - .foreground(fg.red) - .background(bg.blue) - .style(mode.blink); + ret = "This is red on blue blinking" + .foreground(fg.red) + .background(bg.blue) + .style(mode.blink); - assert(ret == "\033[5m\033[44m\033[31mThis is red on blue blinking\033[0m\033[0m\033[0m"); + assert(ret == "\033[5m\033[44m\033[31mThis is red on blue blinking\033[0m\033[0m\033[0m"); } diff --git a/source/dub/internal/colorize/cwrite.d b/source/dub/internal/colorize/cwrite.d index 8c8c26996..0f5d1f2f6 100644 --- a/source/dub/internal/colorize/cwrite.d +++ b/source/dub/internal/colorize/cwrite.d @@ -13,62 +13,62 @@ import dub.internal.colorize.winterm; /// Coloured write. void cwrite(T...)(T args) if (!is(T[0] : File)) { - stdout.cwrite(args); + stdout.cwrite(args); } /// Coloured writef. void cwritef(Char, T...)(in Char[] fmt, T args) if (!is(T[0] : File)) { - stdout.cwritef(fmt, args); + stdout.cwritef(fmt, args); } /// Coloured writefln. void cwritefln(Char, T...)(in Char[] fmt, T args) { - stdout.cwritef(fmt ~ "\n", args); + stdout.cwritef(fmt ~ "\n", args); } /// Coloured writeln. void cwriteln(T...)(T args) { - // Most general instance - stdout.cwrite(args, '\n'); + // Most general instance + stdout.cwrite(args, '\n'); } /// Coloured writef to a File. void cwritef(Char, A...)(File f, in Char[] fmt, A args) { - import std.string : format; - auto s = format(fmt, args); - f.cwrite(s); + import std.string : format; + auto s = format(fmt, args); + f.cwrite(s); } /// Coloured writef to a File. void cwrite(S...)(File f, S args) { - import std.conv : to; + import std.conv : to; - string s = ""; - foreach(arg; args) - s ~= to!string(arg); + string s = ""; + foreach(arg; args) + s ~= to!string(arg); - version(Windows) - { - WinTermEmulation winterm; - winterm.initialize(); - foreach(dchar c ; s) - { - auto charAction = winterm.feed(c); - final switch(charAction) with (WinTermEmulation.CharAction) - { - case drop: break; - case write: f.write(c); break; - case flush: f.flush(); break; - } - } - } - else - { - f.write(s); - } + version(Windows) + { + WinTermEmulation winterm; + winterm.initialize(); + foreach(dchar c ; s) + { + auto charAction = winterm.feed(c); + final switch(charAction) with (WinTermEmulation.CharAction) + { + case drop: break; + case write: f.write(c); break; + case flush: f.flush(); break; + } + } + } + else + { + f.write(s); + } } diff --git a/source/dub/internal/colorize/winterm.d b/source/dub/internal/colorize/winterm.d index 3b12bb558..32b7be2be 100644 --- a/source/dub/internal/colorize/winterm.d +++ b/source/dub/internal/colorize/winterm.d @@ -8,184 +8,184 @@ module dub.internal.colorize.winterm; version(Windows) { - import core.sys.windows.windows; - - // Patch for DMD 2.065 compatibility - static if( __VERSION__ < 2066 ) private enum nogc = 1; - - // This is a state machine to enable terminal colors on Windows. - // Parses and interpret ANSI/VT100 Terminal Control Escape Sequences. - // Only supports colour sequences, will output char incorrectly on invalid input. - struct WinTermEmulation - { - public: - @nogc void initialize() nothrow - { - // saves console attributes - _console = GetStdHandle(STD_OUTPUT_HANDLE); - _savedInitialColor = (0 != GetConsoleScreenBufferInfo(_console, &consoleInfo)); - _state = State.initial; - } - - @nogc ~this() nothrow - { - // Restore initial text attributes on release - if (_savedInitialColor) - { - SetConsoleTextAttribute(_console, consoleInfo.wAttributes); - _savedInitialColor = false; - } - } - - enum CharAction - { - write, - drop, - flush - } - - // Eat one character and update color state accordingly. - // Returns what to do with the fed character. - @nogc CharAction feed(dchar d) nothrow - { - final switch(_state) with (State) - { - case initial: - if (d == '\x1B') - { - _state = escaped; - return CharAction.flush; - } - break; - - case escaped: - if (d == '[') - { - _state = readingAttribute; - _parsedAttr = 0; - return CharAction.drop; - } - break; - - - case readingAttribute: - if (d >= '0' && d <= '9') - { - _parsedAttr = _parsedAttr * 10 + (d - '0'); - return CharAction.drop; - } - else if (d == ';') - { - executeAttribute(_parsedAttr); - _parsedAttr = 0; - return CharAction.drop; - } - else if (d == 'm') - { - executeAttribute(_parsedAttr); - _state = State.initial; - return CharAction.drop; - } - break; - } - return CharAction.write; - } - - private: - HANDLE _console; - bool _savedInitialColor; - CONSOLE_SCREEN_BUFFER_INFO consoleInfo; - State _state; - WORD _currentAttr; - int _parsedAttr; - - enum State - { - initial, - escaped, - readingAttribute - } - - @nogc void setForegroundColor(WORD fgFlags) nothrow - { - _currentAttr = _currentAttr & ~(FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY); - _currentAttr = _currentAttr | fgFlags; - SetConsoleTextAttribute(_console, _currentAttr); - } - - @nogc void setBackgroundColor(WORD bgFlags) nothrow - { - _currentAttr = _currentAttr & ~(BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY); - _currentAttr = _currentAttr | bgFlags; - SetConsoleTextAttribute(_console, _currentAttr); - } - - // resets to the same foreground color that was set on initialize() - @nogc void resetForegroundColor() nothrow - { - if (!_savedInitialColor) - return; - - _currentAttr = _currentAttr & ~(FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY); - _currentAttr = _currentAttr | (consoleInfo.wAttributes & (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY)); - SetConsoleTextAttribute(_console, _currentAttr); - } - - // resets to the same background color that was set on initialize() - @nogc void resetBackgroundColor() nothrow - { - if (!_savedInitialColor) - return; - - _currentAttr = _currentAttr & ~(BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY); - _currentAttr = _currentAttr | (consoleInfo.wAttributes & (BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY)); - SetConsoleTextAttribute(_console, _currentAttr); - } - - @nogc void executeAttribute(int attr) nothrow - { - switch (attr) - { - case 0: - // reset all attributes - SetConsoleTextAttribute(_console, consoleInfo.wAttributes); - break; - - default: - if ( (30 <= attr && attr <= 37) || (90 <= attr && attr <= 97) ) - { - WORD color = 0; - if (90 <= attr && attr <= 97) - { - color = FOREGROUND_INTENSITY; - attr -= 60; - } - attr -= 30; - color |= (attr & 1 ? FOREGROUND_RED : 0) | (attr & 2 ? FOREGROUND_GREEN : 0) | (attr & 4 ? FOREGROUND_BLUE : 0); - setForegroundColor(color); - } - else if (attr == 39) // fg.init - { - resetForegroundColor(); - } - - if ( (40 <= attr && attr <= 47) || (100 <= attr && attr <= 107) ) - { - WORD color = 0; - if (100 <= attr && attr <= 107) - { - color = BACKGROUND_INTENSITY; - attr -= 60; - } - attr -= 40; - color |= (attr & 1 ? BACKGROUND_RED : 0) | (attr & 2 ? BACKGROUND_GREEN : 0) | (attr & 4 ? BACKGROUND_BLUE : 0); - setBackgroundColor(color); - } - else if (attr == 49) // bg.init - { - resetBackgroundColor(); - } - } - } - } + import core.sys.windows.windows; + + // Patch for DMD 2.065 compatibility + static if( __VERSION__ < 2066 ) private enum nogc = 1; + + // This is a state machine to enable terminal colors on Windows. + // Parses and interpret ANSI/VT100 Terminal Control Escape Sequences. + // Only supports colour sequences, will output char incorrectly on invalid input. + struct WinTermEmulation + { + public: + @nogc void initialize() nothrow + { + // saves console attributes + _console = GetStdHandle(STD_OUTPUT_HANDLE); + _savedInitialColor = (0 != GetConsoleScreenBufferInfo(_console, &consoleInfo)); + _state = State.initial; + } + + @nogc ~this() nothrow + { + // Restore initial text attributes on release + if (_savedInitialColor) + { + SetConsoleTextAttribute(_console, consoleInfo.wAttributes); + _savedInitialColor = false; + } + } + + enum CharAction + { + write, + drop, + flush + } + + // Eat one character and update color state accordingly. + // Returns what to do with the fed character. + @nogc CharAction feed(dchar d) nothrow + { + final switch(_state) with (State) + { + case initial: + if (d == '\x1B') + { + _state = escaped; + return CharAction.flush; + } + break; + + case escaped: + if (d == '[') + { + _state = readingAttribute; + _parsedAttr = 0; + return CharAction.drop; + } + break; + + case readingAttribute: + if (d >= '0' && d <= '9') + { + _parsedAttr = _parsedAttr * 10 + (d - '0'); + return CharAction.drop; + } + else if (d == ';') + { + executeAttribute(_parsedAttr); + _parsedAttr = 0; + return CharAction.drop; + } + else if (d == 'm') + { + executeAttribute(_parsedAttr); + _state = State.initial; + return CharAction.drop; + } + break; + } + + return CharAction.write; + } + + private: + HANDLE _console; + bool _savedInitialColor; + CONSOLE_SCREEN_BUFFER_INFO consoleInfo; + State _state; + WORD _currentAttr; + int _parsedAttr; + + enum State + { + initial, + escaped, + readingAttribute + } + + @nogc void setForegroundColor(WORD fgFlags) nothrow + { + _currentAttr = _currentAttr & ~(FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY); + _currentAttr = _currentAttr | fgFlags; + SetConsoleTextAttribute(_console, _currentAttr); + } + + @nogc void setBackgroundColor(WORD bgFlags) nothrow + { + _currentAttr = _currentAttr & ~(BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY); + _currentAttr = _currentAttr | bgFlags; + SetConsoleTextAttribute(_console, _currentAttr); + } + + // resets to the same foreground color that was set on initialize() + @nogc void resetForegroundColor() nothrow + { + if (!_savedInitialColor) + return; + + _currentAttr = _currentAttr & ~(FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY); + _currentAttr = _currentAttr | (consoleInfo.wAttributes & (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY)); + SetConsoleTextAttribute(_console, _currentAttr); + } + + // resets to the same background color that was set on initialize() + @nogc void resetBackgroundColor() nothrow + { + if (!_savedInitialColor) + return; + + _currentAttr = _currentAttr & ~(BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY); + _currentAttr = _currentAttr | (consoleInfo.wAttributes & (BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY)); + SetConsoleTextAttribute(_console, _currentAttr); + } + + @nogc void executeAttribute(int attr) nothrow + { + switch (attr) + { + case 0: + // reset all attributes + SetConsoleTextAttribute(_console, consoleInfo.wAttributes); + break; + + default: + if ( (30 <= attr && attr <= 37) || (90 <= attr && attr <= 97) ) + { + WORD color = 0; + if (90 <= attr && attr <= 97) + { + color = FOREGROUND_INTENSITY; + attr -= 60; + } + attr -= 30; + color |= (attr & 1 ? FOREGROUND_RED : 0) | (attr & 2 ? FOREGROUND_GREEN : 0) | (attr & 4 ? FOREGROUND_BLUE : 0); + setForegroundColor(color); + } + else if (attr == 39) // fg.init + { + resetForegroundColor(); + } + + if ( (40 <= attr && attr <= 47) || (100 <= attr && attr <= 107) ) + { + WORD color = 0; + if (100 <= attr && attr <= 107) + { + color = BACKGROUND_INTENSITY; + attr -= 60; + } + attr -= 40; + color |= (attr & 1 ? BACKGROUND_RED : 0) | (attr & 2 ? BACKGROUND_GREEN : 0) | (attr & 4 ? BACKGROUND_BLUE : 0); + setBackgroundColor(color); + } + else if (attr == 49) // bg.init + { + resetBackgroundColor(); + } + } + } + } } diff --git a/source/dub/internal/vibecompat/core/log.d b/source/dub/internal/vibecompat/core/log.d index d352e8a35..404e4b5e5 100644 --- a/source/dub/internal/vibecompat/core/log.d +++ b/source/dub/internal/vibecompat/core/log.d @@ -1,8 +1,8 @@ /** +deprecated("Please use dub.logging") This module contained logging functions, but has been replaced by dub.logging - which provides colored output and other facilities. + which provides colored output and other facilities. - Copyright: © 2012 rejectedsoftware e.K., © 2018 Giacomo De Lazzari + Copyright: © 2012 rejectedsoftware e.K., © 2018 Giacomo De Lazzari License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Sönke Ludwig, Giacomo De Lazzari */ diff --git a/source/dub/logging.d b/source/dub/logging.d index daa7a4f22..eb8339501 100644 --- a/source/dub/logging.d +++ b/source/dub/logging.d @@ -1,54 +1,54 @@ /** - Handles all the console output of the Dub package manager, by providing useful - methods for handling colored text. The module also disables colors when stdout - and stderr are not a TTY in order to avoid ASCII escape sequences in piped - output. The module can autodetect and configure itself in this regard by - calling initLogging() at the beginning of the program. But, whether to color - text or not can also be set manually with printColorsInLog(bool). + Handles all the console output of the Dub package manager, by providing useful + methods for handling colored text. The module also disables colors when stdout + and stderr are not a TTY in order to avoid ASCII escape sequences in piped + output. The module can autodetect and configure itself in this regard by + calling initLogging() at the beginning of the program. But, whether to color + text or not can also be set manually with printColorsInLog(bool). - The output for the log levels error, warn and info is formatted like this: + The output for the log levels error, warn and info is formatted like this: - " " - '----------' - fixed width + " " + '----------' + fixed width - the "tag" part can be colored (most oftenly will be) and always has a fixed - width, which is defined as a const at the beginning of this module. + the "tag" part can be colored (most oftenly will be) and always has a fixed + width, which is defined as a const at the beginning of this module. - The output for the log levels debug and diagnostic will be just the plain - string. + The output for the log levels debug and diagnostic will be just the plain + string. - There are some default tag string and color values for some logging levels: - - warn: "Warning", yellow bold - - error: "Error", red bold + There are some default tag string and color values for some logging levels: + - warn: "Warning", yellow bold + - error: "Error", red bold - Actually, for error and warn levels, the tag color is fixed to the ones listed - above. + Actually, for error and warn levels, the tag color is fixed to the ones listed + above. - Also, the default tag string for the info level is "" (the empty string) and - the default color is white (usually it's manually set when calling logInfo - with the wanted tag string, but this allows to just logInfo("text") without - having to worry about the tag if it's not needed). + Also, the default tag string for the info level is "" (the empty string) and + the default color is white (usually it's manually set when calling logInfo + with the wanted tag string, but this allows to just logInfo("text") without + having to worry about the tag if it's not needed). - Usage: - After initializing the logging module with initLogging(), the functions - logDebug(..), logDiagnostic(..), logInfo(..), logWarning(..) and logError(..) - can be used to print log messages. Whether the messages are printed on stdout - or stderr depends on the log level (warning and error go to stderr). - The log(..) function can also be used. Check the signature and documentation - of the functions for more information. + Usage: + After initializing the logging module with initLogging(), the functions + logDebug(..), logDiagnostic(..), logInfo(..), logWarning(..) and logError(..) + can be used to print log messages. Whether the messages are printed on stdout + or stderr depends on the log level (warning and error go to stderr). + The log(..) function can also be used. Check the signature and documentation + of the functions for more information. - The minimum log level to print can be configured using setLogLevel(..), and - whether to color outputted text or not can be set with printColorsInLog(..). + The minimum log level to print can be configured using setLogLevel(..), and + whether to color outputted text or not can be set with printColorsInLog(..). - The color(str, color) function can be used to color text within a log - message, for instance like this: + The color(str, color) function can be used to color text within a log + message, for instance like this: - logInfo("Tag", Color.green, "My %s message", "colored".color(Color.red)) + logInfo("Tag", Color.green, "My %s message", "colored".color(Color.red)) - Copyright: © 2018 Giacomo De Lazzari - License: Subject to the terms of the MIT license, as written in the included LICENSE file. - Authors: Giacomo De Lazzari + Copyright: © 2018 Giacomo De Lazzari + License: Subject to the terms of the MIT license, as written in the included LICENSE file. + Authors: Giacomo De Lazzari */ module dub.logging; @@ -61,17 +61,17 @@ import std.string; import dub.internal.colorize : fg, mode; /** - An enum listing possible colors for terminal output, useful to set the color - of a tag. Re-exported from d-colorize in dub.internal.colorize. See the enum - definition there for a list of possible values. + An enum listing possible colors for terminal output, useful to set the color + of a tag. Re-exported from d-colorize in dub.internal.colorize. See the enum + definition there for a list of possible values. */ public alias Color = fg; /** - An enum listing possible text "modes" for terminal output, useful to set the - text to bold, underline, blinking, etc... - Re-exported from d-colorize in dub.internal.colorize. See the enum definition - there for a list of possible values. + An enum listing possible text "modes" for terminal output, useful to set the + text to bold, underline, blinking, etc... + Re-exported from d-colorize in dub.internal.colorize. See the enum definition + there for a list of possible values. */ public alias Mode = mode; @@ -80,21 +80,21 @@ private const int TAG_WIDTH = 12; /// Possible log levels supported enum LogLevel { - debug_, - diagnostic, - info, - warn, - error, - none + debug_, + diagnostic, + info, + warn, + error, + none } // The current minimum log level to be printed private shared LogLevel _minLevel = LogLevel.info; /* - Whether to print text with colors or not, defaults to true but will be set - to false in initLogging() if stdout or stderr are not a TTY (which means the - output is probably being piped and we don't want ASCII escape chars in it) + Whether to print text with colors or not, defaults to true but will be set + to false in initLogging() if stdout or stderr are not a TTY (which means the + output is probably being piped and we don't want ASCII escape chars in it) */ private shared bool _printColors = true; @@ -102,282 +102,282 @@ private shared bool _printColors = true; extern (C) int isatty(int); /** - This function must be called at the beginning for the program, before any - logging occurs. It will detect whether or not stdout/stderr are a console/TTY - and will consequently disable colored output if needed. + This function must be called at the beginning for the program, before any + logging occurs. It will detect whether or not stdout/stderr are a console/TTY + and will consequently disable colored output if needed. - Forgetting to call the function will result in ASCII escape sequences in the - piped output, probably an undesiderable thing. + Forgetting to call the function will result in ASCII escape sequences in the + piped output, probably an undesiderable thing. */ void initLogging() { - import core.stdc.stdio; - - // Initially enable colors, we'll disable them during this functions if we - // find any reason to - _printColors = true; - - // The following stuff depends on the platform - version (Windows) - { - version (CRuntime_DigitalMars) - { - if (!isatty(core.stdc.stdio.stdout._file) || - !isatty(core.stdc.stdio.stderr._file)) - _printColors = false; - } - else version (CRuntime_Microsoft) - { - if (!isatty(fileno(core.stdc.stdio.stdout)) || - !isatty(fileno(core.stdc.stdio.stderr))) - _printColors = false; - } - else - _printColors = false; - } - else version (Posix) - { - import core.sys.posix.unistd; - - if (!isatty(STDERR_FILENO) || !isatty(STDOUT_FILENO)) - _printColors = false; - } + import core.stdc.stdio; + + // Initially enable colors, we'll disable them during this functions if we + // find any reason to + _printColors = true; + + // The following stuff depends on the platform + version (Windows) + { + version (CRuntime_DigitalMars) + { + if (!isatty(core.stdc.stdio.stdout._file) || + !isatty(core.stdc.stdio.stderr._file)) + _printColors = false; + } + else version (CRuntime_Microsoft) + { + if (!isatty(fileno(core.stdc.stdio.stdout)) || + !isatty(fileno(core.stdc.stdio.stderr))) + _printColors = false; + } + else + _printColors = false; + } + else version (Posix) + { + import core.sys.posix.unistd; + + if (!isatty(STDERR_FILENO) || !isatty(STDOUT_FILENO)) + _printColors = false; + } } /// Sets the minimum log level to be printed void setLogLevel(LogLevel level) nothrow { - _minLevel = level; + _minLevel = level; } /// Gets the minimum log level to be printed LogLevel getLogLevel() { - return _minLevel; + return _minLevel; } /// Set whether to print colors or not void printColorsInLog(bool enabled) { - _printColors = enabled; + _printColors = enabled; } /** - Shorthand function to log a message with debug/diagnostic level, no tag string - or tag color required (since there will be no tag). + Shorthand function to log a message with debug/diagnostic level, no tag string + or tag color required (since there will be no tag). - Params: - level = The log level for the logged message - fmt = See http://dlang.org/phobos/std_format.html#format-string + Params: + level = The log level for the logged message + fmt = See http://dlang.org/phobos/std_format.html#format-string */ void logDebug(T...)(string fmt, lazy T args) nothrow { - log(LogLevel.debug_, false, "", Color.init, fmt, args); + log(LogLevel.debug_, false, "", Color.init, fmt, args); } /// ditto void logDiagnostic(T...)(string fmt, lazy T args) nothrow { - log(LogLevel.diagnostic, false, "", Color.init, fmt, args); + log(LogLevel.diagnostic, false, "", Color.init, fmt, args); } /** - Shorthand function to log a message with info level, with custom tag string - and tag color. - - Params: - tag = The string the tag at the beginning of the line should contain - tagColor = The color the tag string should have - level = The log level for the logged message - fmt = See http://dlang.org/phobos/std_format.html#format-string + Shorthand function to log a message with info level, with custom tag string + and tag color. + + Params: + tag = The string the tag at the beginning of the line should contain + tagColor = The color the tag string should have + level = The log level for the logged message + fmt = See http://dlang.org/phobos/std_format.html#format-string */ void logInfo(T...)(string tag, Color tagColor, string fmt, lazy T args) nothrow { - log(LogLevel.info, false, tag, tagColor, fmt, args); + log(LogLevel.info, false, tag, tagColor, fmt, args); } /** - Shorthand function to log a message with info level, this version prints an - empty tag automatically (which is different from not having a tag - in this - case there will be an identation of TAG_WIDTH chars on the left anyway). + Shorthand function to log a message with info level, this version prints an + empty tag automatically (which is different from not having a tag - in this + case there will be an identation of TAG_WIDTH chars on the left anyway). - Params: - level = The log level for the logged message - fmt = See http://dlang.org/phobos/std_format.html#format-string + Params: + level = The log level for the logged message + fmt = See http://dlang.org/phobos/std_format.html#format-string */ void logInfo(T...)(string fmt, lazy T args) nothrow if (!is(T[0] : Color)) { - log(LogLevel.info, false, "", Color.init, fmt, args); + log(LogLevel.info, false, "", Color.init, fmt, args); } /** - Shorthand function to log a message with info level, this version doesn't - print a tag at all, it effectively just prints the given string. + Shorthand function to log a message with info level, this version doesn't + print a tag at all, it effectively just prints the given string. - Params: - level = The log level for the logged message - fmt = See http://dlang.org/phobos/std_format.html#format-string + Params: + level = The log level for the logged message + fmt = See http://dlang.org/phobos/std_format.html#format-string */ void logInfoNoTag(T...)(string fmt, lazy T args) nothrow if (!is(T[0] : Color)) { - log(LogLevel.info, true, "", Color.init, fmt, args); + log(LogLevel.info, true, "", Color.init, fmt, args); } /** - Shorthand function to log a message with warning level, with custom tag string. - The tag color is fixed to yellow. + Shorthand function to log a message with warning level, with custom tag string. + The tag color is fixed to yellow. - Params: - tag = The string the tag at the beginning of the line should contain - level = The log level for the logged message - fmt = See http://dlang.org/phobos/std_format.html#format-string + Params: + tag = The string the tag at the beginning of the line should contain + level = The log level for the logged message + fmt = See http://dlang.org/phobos/std_format.html#format-string */ void logWarnTag(T...)(string tag, string fmt, lazy T args) nothrow { - log(LogLevel.warn, false, tag, Color.yellow, fmt, args); + log(LogLevel.warn, false, tag, Color.yellow, fmt, args); } /** - Shorthand function to log a message with warning level, using the default - tag "Warning". The tag color is also fixed to yellow. + Shorthand function to log a message with warning level, using the default + tag "Warning". The tag color is also fixed to yellow. - Params: - level = The log level for the logged message - fmt = See http://dlang.org/phobos/std_format.html#format-string + Params: + level = The log level for the logged message + fmt = See http://dlang.org/phobos/std_format.html#format-string */ void logWarn(T...)(string fmt, lazy T args) nothrow { - log(LogLevel.warn, false, "Warning", Color.yellow, fmt, args); + log(LogLevel.warn, false, "Warning", Color.yellow, fmt, args); } /** - Shorthand function to log a message with error level, with custom tag string. - The tag color is fixed to red. + Shorthand function to log a message with error level, with custom tag string. + The tag color is fixed to red. - Params: - tag = The string the tag at the beginning of the line should contain - level = The log level for the logged message - fmt = See http://dlang.org/phobos/std_format.html#format-string + Params: + tag = The string the tag at the beginning of the line should contain + level = The log level for the logged message + fmt = See http://dlang.org/phobos/std_format.html#format-string */ void logErrorTag(T...)(string tag, string fmt, lazy T args) nothrow { - log(LogLevel.error, false, tag, Color.red, fmt, args); + log(LogLevel.error, false, tag, Color.red, fmt, args); } /** - Shorthand function to log a message with error level, using the default - tag "Error". The tag color is also fixed to red. + Shorthand function to log a message with error level, using the default + tag "Error". The tag color is also fixed to red. - Params: - level = The log level for the logged message - fmt = See http://dlang.org/phobos/std_format.html#format-string + Params: + level = The log level for the logged message + fmt = See http://dlang.org/phobos/std_format.html#format-string */ void logError(T...)(string fmt, lazy T args) nothrow { - log(LogLevel.error, false, "Error", Color.red, fmt, args); + log(LogLevel.error, false, "Error", Color.red, fmt, args); } /** - Log a message with the specified log level and with the specified tag string - and color. If the log level is debug or diagnostic, the tag is not printed - thus the tag string and tag color will be ignored. If the log level is error - or warning, the tag will be in bold text. Also the tag can be disabled (for - any log level) by passing true as the second argument. - - Params: - level = The log level for the logged message - disableTag = Setting this to true disables the tag, no matter what - tag = The string the tag at the beginning of the line should contain - tagColor = The color the tag string should have - fmt = See http://dlang.org/phobos/std_format.html#format-string + Log a message with the specified log level and with the specified tag string + and color. If the log level is debug or diagnostic, the tag is not printed + thus the tag string and tag color will be ignored. If the log level is error + or warning, the tag will be in bold text. Also the tag can be disabled (for + any log level) by passing true as the second argument. + + Params: + level = The log level for the logged message + disableTag = Setting this to true disables the tag, no matter what + tag = The string the tag at the beginning of the line should contain + tagColor = The color the tag string should have + fmt = See http://dlang.org/phobos/std_format.html#format-string */ void log(T...)( - LogLevel level, - bool disableTag, - string tag, - Color tagColor, - string fmt, - lazy T args + LogLevel level, + bool disableTag, + string tag, + Color tagColor, + string fmt, + lazy T args ) nothrow { - if (level < _minLevel) - return; - - auto hasTag = true; - if (level <= LogLevel.diagnostic) - hasTag = false; - if (disableTag) - hasTag = false; - - auto boldTag = false; - if (level >= LogLevel.warn) - boldTag = true; - - try - { - string result = format(fmt, args); - - if (hasTag) - result = tag.rightJustify(TAG_WIDTH, ' ').color(tagColor, boldTag ? Mode.bold : Mode.init) ~ " " ~ result; - - import dub.internal.colorize : cwrite; - - File output = (level <= LogLevel.info) ? stdout : stderr; - - if (output.isOpen) - { - output.cwrite(result, "\n"); - output.flush(); - } - } - catch (Exception e) - { - debug assert(false, e.msg); - } + if (level < _minLevel) + return; + + auto hasTag = true; + if (level <= LogLevel.diagnostic) + hasTag = false; + if (disableTag) + hasTag = false; + + auto boldTag = false; + if (level >= LogLevel.warn) + boldTag = true; + + try + { + string result = format(fmt, args); + + if (hasTag) + result = tag.rightJustify(TAG_WIDTH, ' ').color(tagColor, boldTag ? Mode.bold : Mode.init) ~ " " ~ result; + + import dub.internal.colorize : cwrite; + + File output = (level <= LogLevel.info) ? stdout : stderr; + + if (output.isOpen) + { + output.cwrite(result, "\n"); + output.flush(); + } + } + catch (Exception e) + { + debug assert(false, e.msg); + } } /** - Colors the specified string with the specified color. The function is used to - print colored text within a log message. The function also checks whether - color output is enabled or disabled (when not outputting to a TTY) and, in the - last case, just returns the plain string. This allows to use it like so: + Colors the specified string with the specified color. The function is used to + print colored text within a log message. The function also checks whether + color output is enabled or disabled (when not outputting to a TTY) and, in the + last case, just returns the plain string. This allows to use it like so: - logInfo("Tag", Color.green, "My %s log message", "colored".color(Color.red)); + logInfo("Tag", Color.green, "My %s log message", "colored".color(Color.red)); - without worring whether or not colored output is enabled or not. + without worring whether or not colored output is enabled or not. - Also a mode can be specified, such as bold/underline/etc... + Also a mode can be specified, such as bold/underline/etc... - Params: - str = The string to color - color = The color to apply - mode = An optional mode, such as bold/underline/etc... + Params: + str = The string to color + color = The color to apply + mode = An optional mode, such as bold/underline/etc... */ string color(const string str, const Color color, const Mode mode = Mode.init) { - import dub.internal.colorize; + import dub.internal.colorize; - if (_printColors == true) - return dub.internal.colorize.color(str, color, bg.init, mode); - else - return str; + if (_printColors == true) + return dub.internal.colorize.color(str, color, bg.init, mode); + else + return str; } /** - This function is the same as the above one, but just accepts a mode. - It's useful, for instance, when outputting bold text without changing the - color. + This function is the same as the above one, but just accepts a mode. + It's useful, for instance, when outputting bold text without changing the + color. - Params: - str = The string to color - mode = The mode, such as bold/underline/etc... + Params: + str = The string to color + mode = The mode, such as bold/underline/etc... */ string color(const string str, const Mode m = Mode.init) { - import dub.internal.colorize; + import dub.internal.colorize; - if (_printColors == true) - return dub.internal.colorize.color(str, fg.init, bg.init, m); - else - return str; + if (_printColors == true) + return dub.internal.colorize.color(str, fg.init, bg.init, m); + else + return str; } diff --git a/source/dub/packagesuppliers/maven.d b/source/dub/packagesuppliers/maven.d index 8d85b9d4e..816381974 100644 --- a/source/dub/packagesuppliers/maven.d +++ b/source/dub/packagesuppliers/maven.d @@ -12,7 +12,7 @@ class MavenRegistryPackageSupplier : PackageSupplier { import dub.internal.utils : retryDownload, HTTPStatusException; import dub.internal.vibecompat.data.json : serializeToJson; import dub.internal.vibecompat.inet.url : URL; - import dub.logging; + import dub.logging; import std.datetime : Clock, Duration, hours, SysTime, UTC; From 5371819c450e0e837188384aff055a74b6787e77 Mon Sep 17 00:00:00 2001 From: Giacomo De Lazzari Date: Tue, 12 Jun 2018 00:32:25 +0200 Subject: [PATCH 24/42] Minor code style fix --- source/dub/logging.d | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/dub/logging.d b/source/dub/logging.d index eb8339501..41f07813a 100644 --- a/source/dub/logging.d +++ b/source/dub/logging.d @@ -357,7 +357,7 @@ string color(const string str, const Color color, const Mode mode = Mode.init) { import dub.internal.colorize; - if (_printColors == true) + if (_printColors) return dub.internal.colorize.color(str, color, bg.init, mode); else return str; @@ -376,7 +376,7 @@ string color(const string str, const Mode m = Mode.init) { import dub.internal.colorize; - if (_printColors == true) + if (_printColors) return dub.internal.colorize.color(str, fg.init, bg.init, m); else return str; From b4c45c52e48e4d40bc834cce376a6b39da3e1292 Mon Sep 17 00:00:00 2001 From: Giacomo De Lazzari Date: Tue, 12 Jun 2018 00:39:02 +0200 Subject: [PATCH 25/42] Revert logInfo to print a single line after a fetch --- source/dub/commandline.d | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/source/dub/commandline.d b/source/dub/commandline.d index 92a314a5a..9d22453e0 100644 --- a/source/dub/commandline.d +++ b/source/dub/commandline.d @@ -1880,8 +1880,10 @@ class FetchCommand : FetchRemoveCommand { try { dub.fetch(name, Dependency.any, location, fetchOpts); logInfo("Finished", Color.green, "%s fetched", name.color(Mode.bold)); - logInfo("Please note that you need to use `dub run ` or add it"); - logInfo("to dependencies of your package to actually use/run it."); + logInfo( + "Please note that you need to use `dub run ` " ~ + "or add it to dependencies of your package to actually use/run it. " + ); } catch(Exception e){ logInfo("Getting a release version failed: %s", e.msg); From d9a33fc03b8bca37c1a4bcf4d0e924b6b32c7b4c Mon Sep 17 00:00:00 2001 From: Giacomo De Lazzari Date: Tue, 12 Jun 2018 01:01:06 +0200 Subject: [PATCH 26/42] Add --no-colors option to disable colors in terminal Minor: changed function name in logging module --- source/dub/commandline.d | 4 +++- source/dub/logging.d | 9 +++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/source/dub/commandline.d b/source/dub/commandline.d index 9d22453e0..43726e8e2 100644 --- a/source/dub/commandline.d +++ b/source/dub/commandline.d @@ -457,6 +457,7 @@ int runDubCommandLine(string[] args) try handler.prepareOptions(common_args); catch (Exception e) { + if (options.noColors) setLoggingColorsEnabled(false); logError("Error processing arguments: %s", e.msg); logDiagnostic("Full exception: %s", e.toString().sanitize); logInfo("Run 'dub help' for usage information."); @@ -537,7 +538,7 @@ int runDubCommandLine(string[] args) */ struct CommonOptions { bool verbose, vverbose, quiet, vquiet, verror, version_; - bool help, annotate, bare; + bool help, annotate, bare, noColors; string[] registry_urls; string root_path; SkipPackageSuppliers skipRegistry = SkipPackageSuppliers.none; @@ -567,6 +568,7 @@ struct CommonOptions { 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("no-colors", &noColors, ["Disable color output"]); args.getopt("cache", &placementLocation, ["Puts any fetched packages in the specified location [local|system|user]."]); version_ = args.hasAppVersion; diff --git a/source/dub/logging.d b/source/dub/logging.d index 41f07813a..9865e8a70 100644 --- a/source/dub/logging.d +++ b/source/dub/logging.d @@ -4,7 +4,7 @@ and stderr are not a TTY in order to avoid ASCII escape sequences in piped output. The module can autodetect and configure itself in this regard by calling initLogging() at the beginning of the program. But, whether to color - text or not can also be set manually with printColorsInLog(bool). + text or not can also be set manually with setLoggingColorsEnabled(bool). The output for the log levels error, warn and info is formatted like this: @@ -38,8 +38,9 @@ The log(..) function can also be used. Check the signature and documentation of the functions for more information. - The minimum log level to print can be configured using setLogLevel(..), and - whether to color outputted text or not can be set with printColorsInLog(..). + The minimum log level to print can be configured using setLogLevel(..), + and whether to color outputted text or not can be set with + setLoggingColorsEnabled(..) The color(str, color) function can be used to color text within a log message, for instance like this: @@ -157,7 +158,7 @@ LogLevel getLogLevel() } /// Set whether to print colors or not -void printColorsInLog(bool enabled) +void setLoggingColorsEnabled(bool enabled) { _printColors = enabled; } From a6e99067275288a14931e6e55a3bc95c41ec202a Mon Sep 17 00:00:00 2001 From: Giacomo De Lazzari Date: Tue, 12 Jun 2018 10:41:01 +0200 Subject: [PATCH 27/42] Add --force-colors option to force colors enabled --- source/dub/commandline.d | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/source/dub/commandline.d b/source/dub/commandline.d index 43726e8e2..d74551fd2 100644 --- a/source/dub/commandline.d +++ b/source/dub/commandline.d @@ -457,7 +457,15 @@ int runDubCommandLine(string[] args) try handler.prepareOptions(common_args); catch (Exception e) { + if (options.noColors && options.forceColors) { + logError("Incompatible options: --no-colors and --force-colors"); + logInfo("Run 'dub help' for usage information."); + } + + // based on --no-colors or --force-colors we override whether initLogging() + // enabled colors or not in the first place if (options.noColors) setLoggingColorsEnabled(false); + if (options.forceColors) setLoggingColorsEnabled(true); logError("Error processing arguments: %s", e.msg); logDiagnostic("Full exception: %s", e.toString().sanitize); logInfo("Run 'dub help' for usage information."); @@ -538,7 +546,7 @@ int runDubCommandLine(string[] args) */ struct CommonOptions { bool verbose, vverbose, quiet, vquiet, verror, version_; - bool help, annotate, bare, noColors; + bool help, annotate, bare, noColors, forceColors; string[] registry_urls; string root_path; SkipPackageSuppliers skipRegistry = SkipPackageSuppliers.none; @@ -569,6 +577,7 @@ struct CommonOptions { args.getopt("verror", &verror, ["Only print errors"]); args.getopt("vquiet", &vquiet, ["Print no messages"]); args.getopt("no-colors", &noColors, ["Disable color output"]); + args.getopt("force-colors", &forceColors, ["Force output to be always colored"]); args.getopt("cache", &placementLocation, ["Puts any fetched packages in the specified location [local|system|user]."]); version_ = args.hasAppVersion; From fd520aa97cf1d74829e958fc0fd836b494d54c77 Mon Sep 17 00:00:00 2001 From: Giacomo De Lazzari Date: Tue, 12 Jun 2018 17:57:48 +0200 Subject: [PATCH 28/42] Replace --no-colors & --force-colors with --colors={auto|on|off} --- source/dub/commandline.d | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/source/dub/commandline.d b/source/dub/commandline.d index d74551fd2..9239481eb 100644 --- a/source/dub/commandline.d +++ b/source/dub/commandline.d @@ -457,15 +457,18 @@ int runDubCommandLine(string[] args) try handler.prepareOptions(common_args); catch (Exception e) { - if (options.noColors && options.forceColors) { - logError("Incompatible options: --no-colors and --force-colors"); + if (options.colors_mode == "auto") { + // we already detected whether to enable colors or not with initLogging() above + // this if case is here just to make the else below work correctly + } else if (options.colors_mode == "on") { + setLoggingColorsEnabled(true); // enable colors, no matter what + } else if (options.colors_mode == "off") { + setLoggingColorsEnabled(false); // disable colors, no matter what + } else { + logError("Invalid value for --colors option, expected {auto | on | off}"); logInfo("Run 'dub help' for usage information."); + return 1; } - - // based on --no-colors or --force-colors we override whether initLogging() - // enabled colors or not in the first place - if (options.noColors) setLoggingColorsEnabled(false); - if (options.forceColors) setLoggingColorsEnabled(true); logError("Error processing arguments: %s", e.msg); logDiagnostic("Full exception: %s", e.toString().sanitize); logInfo("Run 'dub help' for usage information."); @@ -546,9 +549,10 @@ int runDubCommandLine(string[] args) */ struct CommonOptions { bool verbose, vverbose, quiet, vquiet, verror, version_; - bool help, annotate, bare, noColors, forceColors; + bool help, annotate, bare; string[] registry_urls; string root_path; + string colors_mode; SkipPackageSuppliers skipRegistry = SkipPackageSuppliers.none; PlacementLocation placementLocation = PlacementLocation.user; @@ -576,8 +580,12 @@ struct CommonOptions { 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("no-colors", &noColors, ["Disable color output"]); - args.getopt("force-colors", &forceColors, ["Force output to be always colored"]); + args.getopt("colors", &colors_mode, [ + "Confiugre color output", + " auto: Automatically turn on/off colors (default)", + " on: Force colors enabled", + " off: Force colors disabled" + ]); args.getopt("cache", &placementLocation, ["Puts any fetched packages in the specified location [local|system|user]."]); version_ = args.hasAppVersion; From ad874d843c73a909748efce15c6f51a911111800 Mon Sep 17 00:00:00 2001 From: Giacomo De Lazzari Date: Tue, 12 Jun 2018 18:01:11 +0200 Subject: [PATCH 29/42] Fix really stupid error in previous commit --- source/dub/commandline.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/dub/commandline.d b/source/dub/commandline.d index 9239481eb..9d9e2c58d 100644 --- a/source/dub/commandline.d +++ b/source/dub/commandline.d @@ -457,7 +457,7 @@ int runDubCommandLine(string[] args) try handler.prepareOptions(common_args); catch (Exception e) { - if (options.colors_mode == "auto") { + if (options.colors_mode == "" || options.colors_mode == "auto") { // we already detected whether to enable colors or not with initLogging() above // this if case is here just to make the else below work correctly } else if (options.colors_mode == "on") { From 2ab6340f0ec03eacc15bcbde8611ad163fd09b76 Mon Sep 17 00:00:00 2001 From: Giacomo De Lazzari Date: Tue, 12 Jun 2018 18:17:14 +0200 Subject: [PATCH 30/42] Fix some older DMD frontend versions not compiling logging.d --- source/dub/logging.d | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/dub/logging.d b/source/dub/logging.d index 9865e8a70..8da4ee63e 100644 --- a/source/dub/logging.d +++ b/source/dub/logging.d @@ -354,12 +354,12 @@ void log(T...)( color = The color to apply mode = An optional mode, such as bold/underline/etc... */ -string color(const string str, const Color color, const Mode mode = Mode.init) +string color(const string str, const Color c, const Mode m = Mode.init) { import dub.internal.colorize; if (_printColors) - return dub.internal.colorize.color(str, color, bg.init, mode); + return dub.internal.colorize.color(str, c, bg.init, m); else return str; } From 027c4b1d89f17f3b3228729d287eb42bed9f198c Mon Sep 17 00:00:00 2001 From: Giacomo De Lazzari Date: Wed, 13 Jun 2018 14:03:30 +0200 Subject: [PATCH 31/42] Add new test for colored output --- test/colored-output.sh | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100755 test/colored-output.sh diff --git a/test/colored-output.sh b/test/colored-output.sh new file mode 100755 index 000000000..349e2cb6a --- /dev/null +++ b/test/colored-output.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +. $(dirname "${BASH_SOURCE[0]}")/common.sh + +cd ${CURR_DIR}/1-exec-simple + +# Test --colors=off disabling colors correctly +${DUB} build --colors=off --compiler=${DC} 2>&1 | { ! grep -P '\e\[' -c; } + +# Test --colors=auto detecting no TTY +${DUB} build --colors=auto --compiler=${DC} 2>&1 | { ! grep -P '\e\[' -c; } + +# Test no --colors= option defaulting to auto +${DUB} build --compiler=${DC} 2>&1 | { ! grep -P '\e\[' -c; } + +# Test --colors=on enabling colors in any case +${DUB} build --colors=on --compiler=${DC} 2>&1 | grep -P '\e\[' -c From 1ff762cc977d1474c46fc798a63235006577ee18 Mon Sep 17 00:00:00 2001 From: Giacomo De Lazzari Date: Wed, 13 Jun 2018 14:17:58 +0200 Subject: [PATCH 32/42] Fix non robust test (issue1091-bogus-rebuild) The test was susceptible to interference from other tests, because it assumed the 1-exec-simple project was clean, which may be not. The reason that made the test work until now was that it happened to execute before other tests that use the same project. Now it ensures the project is clean before running. This commit is part of PR #1490 because it was needed in order to make the new colored-output test pass (which was interfering with this one). --- test/issue361-optional-deps/cmp.tmp | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 test/issue361-optional-deps/cmp.tmp diff --git a/test/issue361-optional-deps/cmp.tmp b/test/issue361-optional-deps/cmp.tmp new file mode 100644 index 000000000..633ce9ca0 --- /dev/null +++ b/test/issue361-optional-deps/cmp.tmp @@ -0,0 +1,6 @@ +{ + "fileVersion": 1, + "versions": { + "a": "~master" + } +} From 395d4d438ff099dd2e65adb7c7d19bec43de1c66 Mon Sep 17 00:00:00 2001 From: Giacomo De Lazzari Date: Wed, 13 Jun 2018 14:23:01 +0200 Subject: [PATCH 33/42] Fixed stuff that shouldn't have been committed (the .gitignore should be updated for people that runs tests locally...) --- test/issue361-optional-deps/cmp.tmp | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 test/issue361-optional-deps/cmp.tmp diff --git a/test/issue361-optional-deps/cmp.tmp b/test/issue361-optional-deps/cmp.tmp deleted file mode 100644 index 633ce9ca0..000000000 --- a/test/issue361-optional-deps/cmp.tmp +++ /dev/null @@ -1,6 +0,0 @@ -{ - "fileVersion": 1, - "versions": { - "a": "~master" - } -} From 79b63443994ea5ec80c7bcc131ac6057c0e5e1d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Panadero=20Guarde=C3=B1o?= Date: Sat, 3 Apr 2021 20:21:13 +0200 Subject: [PATCH 34/42] Fix rebase errors --- source/dub/commandline.d | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/source/dub/commandline.d b/source/dub/commandline.d index 9d9e2c58d..b28361e42 100644 --- a/source/dub/commandline.d +++ b/source/dub/commandline.d @@ -165,6 +165,15 @@ struct CommandLineHandler { options.root_path = options.root_path.expandTilde.absolutePath.buildNormalizedPath; } + + if (options.colors_mode == "" || options.colors_mode == "auto") { + // we already detected whether to enable colors or not with initLogging() above + // this if case is here just to make the else below work correctly + } else if (options.colors_mode == "on") { + setLoggingColorsEnabled(true); // enable colors, no matter what + } else if (options.colors_mode == "off") { + setLoggingColorsEnabled(false); // disable colors, no matter what + } } /** Get an instance of the requested command. @@ -457,18 +466,6 @@ int runDubCommandLine(string[] args) try handler.prepareOptions(common_args); catch (Exception e) { - if (options.colors_mode == "" || options.colors_mode == "auto") { - // we already detected whether to enable colors or not with initLogging() above - // this if case is here just to make the else below work correctly - } else if (options.colors_mode == "on") { - setLoggingColorsEnabled(true); // enable colors, no matter what - } else if (options.colors_mode == "off") { - setLoggingColorsEnabled(false); // disable colors, no matter what - } else { - logError("Invalid value for --colors option, expected {auto | on | off}"); - logInfo("Run 'dub help' for usage information."); - return 1; - } logError("Error processing arguments: %s", e.msg); logDiagnostic("Full exception: %s", e.toString().sanitize); logInfo("Run 'dub help' for usage information."); From 29229f69e1fbd7b8f2f7b111ba68babbf6ab2987 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Panadero=20Guarde=C3=B1o?= Date: Sun, 4 Apr 2021 09:32:43 +0200 Subject: [PATCH 35/42] Fix/Update some tests and make some info messages more similar to original version of Dub --- source/dub/commandline.d | 2 +- source/dub/generators/build.d | 5 +++-- test/feat663-search.sh | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/source/dub/commandline.d b/source/dub/commandline.d index b28361e42..15605d4f6 100644 --- a/source/dub/commandline.d +++ b/source/dub/commandline.d @@ -2146,7 +2146,7 @@ class SearchCommand : Command { justify += (~justify & 3) + 1; // round to next multiple of 4 foreach (desc, matches; res) { - logInfoNoTag("%s", desc); + logInfoNoTag("==== %s ====", desc); foreach (m; matches) logInfoNoTag(" %s%s", leftJustify(m.name ~ " (" ~ m.version_ ~ ")", justify), m.description); } diff --git a/source/dub/generators/build.d b/source/dub/generators/build.d index 80b678131..272f93ce6 100644 --- a/source/dub/generators/build.d +++ b/source/dub/generators/build.d @@ -228,7 +228,8 @@ class BuildGenerator : ProjectGenerator { else target_path = pack.path ~ format(".dub/build/%s/", build_id); if (!settings.force && isUpToDate(target_path, buildsettings, settings, pack, packages, additional_dep_files)) { - logInfo("Up-to-date", Color.green, "%s %s [%s]", pack.name.color(Mode.bold), pack.version_, config.color(Color.blue)); + logInfo("Up-to-date", Color.green, "%s %s: target for configuration [%s] is up to date.", + pack.name.color(Mode.bold), pack.version_, config.color(Color.blue)); logDiagnostic("Using existing build in %s.", target_path.toNativeString()); target_binary_path = target_path ~ settings.compiler.getTargetFileName(buildsettings, settings.platform); if (!settings.tempBuild) @@ -243,7 +244,7 @@ class BuildGenerator : ProjectGenerator { return false; } - logInfo("Building", Color.green, "%s %s [%s]", pack.name.color(Mode.bold), pack.version_, config.color(Color.blue)); + logInfo("Building", Color.green, "%s %s: building configuration [%s]", pack.name.color(Mode.bold), pack.version_, config.color(Color.blue)); if( buildsettings.preBuildCommands.length ){ logInfo("Pre-build", Color.green, "Running commands"); diff --git a/test/feat663-search.sh b/test/feat663-search.sh index 21cea3ede..77289a688 100755 --- a/test/feat663-search.sh +++ b/test/feat663-search.sh @@ -10,6 +10,6 @@ fi if ! OUTPUT=$(${DUB} search '"dub-registry"' -v 2>&1); then die $LINENO '`dub search "dub-registry"` failed' "$OUTPUT" fi -if ! grep -q '^dub-registry (.*)\s'<<<"$OUTPUT"; then - die $LINENO '`grep -q '"'"'^dub-registry (.*)\s'"'"'` failed' "$OUTPUT" +if ! grep -q '^\s\sdub-registry (.*)\s'<<<"$OUTPUT"; then + die $LINENO '`grep -q '"'"'^\s\sdub-registry (.*)\s'"'"'` failed' "$OUTPUT" fi From 19da0884b7a903434d93cfbdbe7009bcfcaded27 Mon Sep 17 00:00:00 2001 From: Bastiaan Veelo Date: Mon, 13 Jun 2022 18:35:16 +0200 Subject: [PATCH 36/42] Keep logging functionality out of the public API as requested in https://github.com/dlang/dub/pull/2124#issuecomment-813016939. --- source/dub/commandline.d | 2 +- source/dub/compilers/compiler.d | 2 +- source/dub/compilers/dmd.d | 2 +- source/dub/compilers/gdc.d | 2 +- source/dub/compilers/ldc.d | 2 +- source/dub/compilers/utils.d | 2 +- source/dub/dependency.d | 2 +- source/dub/dependencyresolver.d | 2 +- source/dub/dub.d | 2 +- source/dub/generators/build.d | 2 +- source/dub/generators/cmake.d | 2 +- source/dub/generators/generator.d | 2 +- source/dub/generators/sublimetext.d | 2 +- source/dub/generators/visuald.d | 2 +- source/dub/init.d | 2 +- source/dub/{ => internal}/logging.d | 2 +- source/dub/internal/utils.d | 2 +- source/dub/internal/vibecompat/core/file.d | 2 +- source/dub/internal/vibecompat/core/log.d | 8 ++++---- source/dub/package_.d | 2 +- source/dub/packagemanager.d | 2 +- source/dub/packagesuppliers/fallback.d | 2 +- source/dub/packagesuppliers/filesystem.d | 2 +- source/dub/packagesuppliers/maven.d | 2 +- source/dub/packagesuppliers/registry.d | 2 +- source/dub/project.d | 2 +- source/dub/recipe/packagerecipe.d | 2 +- source/dub/recipe/sdl.d | 2 +- 28 files changed, 31 insertions(+), 31 deletions(-) rename source/dub/{ => internal}/logging.d (99%) diff --git a/source/dub/commandline.d b/source/dub/commandline.d index 15605d4f6..ccdd8afc8 100644 --- a/source/dub/commandline.d +++ b/source/dub/commandline.d @@ -14,7 +14,7 @@ import dub.generators.generator; import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.data.json; import dub.internal.vibecompat.inet.path; -import dub.logging; +import dub.internal.logging; import dub.package_; import dub.packagemanager; import dub.packagesuppliers; diff --git a/source/dub/compilers/compiler.d b/source/dub/compilers/compiler.d index b8e210783..a8dacd013 100644 --- a/source/dub/compilers/compiler.d +++ b/source/dub/compilers/compiler.d @@ -13,7 +13,7 @@ public import dub.platform : BuildPlatform, matchesSpecification; import dub.internal.vibecompat.inet.path; -import dub.logging; +import dub.internal.logging; import std.algorithm; import std.array; diff --git a/source/dub/compilers/dmd.d b/source/dub/compilers/dmd.d index ba49e90ca..4224518e4 100644 --- a/source/dub/compilers/dmd.d +++ b/source/dub/compilers/dmd.d @@ -11,7 +11,7 @@ import dub.compilers.compiler; import dub.compilers.utils; import dub.internal.utils; import dub.internal.vibecompat.inet.path; -import dub.logging; +import dub.internal.logging; import std.algorithm; import std.array; diff --git a/source/dub/compilers/gdc.d b/source/dub/compilers/gdc.d index cab47595a..82216dfe2 100644 --- a/source/dub/compilers/gdc.d +++ b/source/dub/compilers/gdc.d @@ -11,7 +11,7 @@ import dub.compilers.compiler; import dub.compilers.utils; import dub.internal.utils; import dub.internal.vibecompat.inet.path; -import dub.logging; +import dub.internal.logging; import std.algorithm; import std.array; diff --git a/source/dub/compilers/ldc.d b/source/dub/compilers/ldc.d index a85090765..848760910 100644 --- a/source/dub/compilers/ldc.d +++ b/source/dub/compilers/ldc.d @@ -11,7 +11,7 @@ import dub.compilers.compiler; import dub.compilers.utils; import dub.internal.utils; import dub.internal.vibecompat.inet.path; -import dub.logging; +import dub.internal.logging; import std.algorithm; import std.array; diff --git a/source/dub/compilers/utils.d b/source/dub/compilers/utils.d index 86bde9025..19b1419f3 100644 --- a/source/dub/compilers/utils.d +++ b/source/dub/compilers/utils.d @@ -10,7 +10,7 @@ module dub.compilers.utils; import dub.compilers.buildsettings; import dub.platform : BuildPlatform, archCheck, compilerCheck, platformCheck; import dub.internal.vibecompat.inet.path; -import dub.logging; +import dub.internal.logging; import std.algorithm : canFind, endsWith, filter; diff --git a/source/dub/dependency.d b/source/dub/dependency.d index 16210db6c..27288baa4 100644 --- a/source/dub/dependency.d +++ b/source/dub/dependency.d @@ -13,7 +13,7 @@ import dub.internal.vibecompat.data.json; import dub.internal.vibecompat.inet.path; import dub.package_; import dub.semver; -import dub.logging; +import dub.internal.logging; import std.algorithm; import std.array; diff --git a/source/dub/dependencyresolver.d b/source/dub/dependencyresolver.d index 527b63215..5cb2e134a 100644 --- a/source/dub/dependencyresolver.d +++ b/source/dub/dependencyresolver.d @@ -8,7 +8,7 @@ module dub.dependencyresolver; import dub.dependency; -import dub.logging; +import dub.internal.logging; import std.algorithm : all, canFind, filter, map, sort; import std.array : appender, array, join; diff --git a/source/dub/dub.d b/source/dub/dub.d index 529b685cb..108f124f0 100644 --- a/source/dub/dub.d +++ b/source/dub/dub.d @@ -14,7 +14,7 @@ import dub.internal.utils; import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.data.json; import dub.internal.vibecompat.inet.url; -import dub.logging; +import dub.internal.logging; import dub.package_; import dub.packagemanager; import dub.packagesuppliers; diff --git a/source/dub/generators/build.d b/source/dub/generators/build.d index 272f93ce6..c87511b99 100644 --- a/source/dub/generators/build.d +++ b/source/dub/generators/build.d @@ -13,7 +13,7 @@ import dub.generators.generator; import dub.internal.utils; import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.inet.path; -import dub.logging; +import dub.internal.logging; import dub.package_; import dub.packagemanager; import dub.project; diff --git a/source/dub/generators/cmake.d b/source/dub/generators/cmake.d index 97e67bd50..3be3d625f 100644 --- a/source/dub/generators/cmake.d +++ b/source/dub/generators/cmake.d @@ -11,7 +11,7 @@ import dub.compilers.buildsettings; import dub.generators.generator; import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.inet.path; -import dub.logging; +import dub.internal.logging; import dub.project; import std.algorithm: map, uniq; diff --git a/source/dub/generators/generator.d b/source/dub/generators/generator.d index e3e9571be..c428df441 100644 --- a/source/dub/generators/generator.d +++ b/source/dub/generators/generator.d @@ -14,7 +14,7 @@ import dub.generators.sublimetext; import dub.generators.visuald; import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.inet.path; -import dub.logging; +import dub.internal.logging; import dub.package_; import dub.packagemanager; import dub.project; diff --git a/source/dub/generators/sublimetext.d b/source/dub/generators/sublimetext.d index fd873ebcc..d46fbd996 100644 --- a/source/dub/generators/sublimetext.d +++ b/source/dub/generators/sublimetext.d @@ -11,7 +11,7 @@ import dub.compilers.compiler; import dub.generators.generator; import dub.internal.vibecompat.data.json; import dub.internal.vibecompat.inet.path; -import dub.logging; +import dub.internal.logging; import dub.packagemanager; import dub.project; diff --git a/source/dub/generators/visuald.d b/source/dub/generators/visuald.d index f63ffc7bf..3e90d6af1 100644 --- a/source/dub/generators/visuald.d +++ b/source/dub/generators/visuald.d @@ -11,7 +11,7 @@ import dub.compilers.compiler; import dub.generators.generator; import dub.internal.utils; import dub.internal.vibecompat.core.file; -import dub.logging; +import dub.internal.logging; import dub.package_; import dub.packagemanager; import dub.project; diff --git a/source/dub/init.d b/source/dub/init.d index 160449be4..b4c887c98 100644 --- a/source/dub/init.d +++ b/source/dub/init.d @@ -8,7 +8,7 @@ module dub.init; import dub.internal.vibecompat.core.file; -import dub.logging; +import dub.internal.logging; import dub.package_ : PackageFormat, packageInfoFiles, defaultPackageFilename; import dub.recipe.packagerecipe; import dub.dependency; diff --git a/source/dub/logging.d b/source/dub/internal/logging.d similarity index 99% rename from source/dub/logging.d rename to source/dub/internal/logging.d index 8da4ee63e..cc068c09e 100644 --- a/source/dub/logging.d +++ b/source/dub/internal/logging.d @@ -52,7 +52,7 @@ Authors: Giacomo De Lazzari */ -module dub.logging; +module dub.internal.logging; import std.stdio; import std.array; diff --git a/source/dub/internal/utils.d b/source/dub/internal/utils.d index 16fdfdf82..bf27d195d 100644 --- a/source/dub/internal/utils.d +++ b/source/dub/internal/utils.d @@ -12,7 +12,7 @@ import dub.internal.vibecompat.data.json; import dub.internal.vibecompat.inet.url; import dub.compilers.buildsettings : BuildSettings; import dub.version_; -import dub.logging; +import dub.internal.logging; import core.time : Duration; import std.algorithm : canFind, startsWith; diff --git a/source/dub/internal/vibecompat/core/file.d b/source/dub/internal/vibecompat/core/file.d index d1b55e650..15ee2550e 100644 --- a/source/dub/internal/vibecompat/core/file.d +++ b/source/dub/internal/vibecompat/core/file.d @@ -9,7 +9,7 @@ module dub.internal.vibecompat.core.file; public import dub.internal.vibecompat.inet.url; -import dub.logging; +import dub.internal.logging; import std.conv; import core.stdc.stdio; diff --git a/source/dub/internal/vibecompat/core/log.d b/source/dub/internal/vibecompat/core/log.d index 404e4b5e5..5c6573718 100644 --- a/source/dub/internal/vibecompat/core/log.d +++ b/source/dub/internal/vibecompat/core/log.d @@ -1,5 +1,5 @@ -/** +deprecated("Please use dub.logging") - This module contained logging functions, but has been replaced by dub.logging +/** +deprecated("Please use dub.internal.logging") + This module contained logging functions, but has been replaced by dub.internal.logging which provides colored output and other facilities. Copyright: © 2012 rejectedsoftware e.K., © 2018 Giacomo De Lazzari @@ -7,8 +7,8 @@ Authors: Sönke Ludwig, Giacomo De Lazzari */ -deprecated("Please use dub.logging") +deprecated("Please use dub.internal.logging") module dub.internal.vibecompat.core.log; -public import dub.logging; +public import dub.internal.logging; diff --git a/source/dub/package_.d b/source/dub/package_.d index 71d019ad7..d5daff7cc 100644 --- a/source/dub/package_.d +++ b/source/dub/package_.d @@ -12,10 +12,10 @@ public import dub.recipe.packagerecipe; import dub.compilers.compiler; import dub.dependency; import dub.description; -import dub.logging; import dub.recipe.json; import dub.recipe.sdl; +import dub.internal.logging; import dub.internal.utils; import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.data.json; diff --git a/source/dub/packagemanager.d b/source/dub/packagemanager.d index afab9de9a..4e1464ded 100644 --- a/source/dub/packagemanager.d +++ b/source/dub/packagemanager.d @@ -13,7 +13,7 @@ import dub.internal.utils; import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.data.json; import dub.internal.vibecompat.inet.path; -import dub.logging; +import dub.internal.logging; import dub.package_; import std.algorithm : countUntil, filter, sort, canFind, remove; diff --git a/source/dub/packagesuppliers/fallback.d b/source/dub/packagesuppliers/fallback.d index d7793e4df..1103e376c 100644 --- a/source/dub/packagesuppliers/fallback.d +++ b/source/dub/packagesuppliers/fallback.d @@ -46,7 +46,7 @@ private template fallback(T, alias func) { import std.format : format; enum fallback = q{ - import dub.logging : logDebug; + import dub.internal.logging : logDebug; Exception firstEx; try diff --git a/source/dub/packagesuppliers/filesystem.d b/source/dub/packagesuppliers/filesystem.d index 1e53f0034..fcb9efddf 100644 --- a/source/dub/packagesuppliers/filesystem.d +++ b/source/dub/packagesuppliers/filesystem.d @@ -9,7 +9,7 @@ import dub.packagesuppliers.packagesupplier; the form "[package name]-[version].zip". */ class FileSystemPackageSupplier : PackageSupplier { - import dub.logging; + import dub.internal.logging; version (Have_vibe_core) import dub.internal.vibecompat.inet.path : toNativeString; import std.exception : enforce; diff --git a/source/dub/packagesuppliers/maven.d b/source/dub/packagesuppliers/maven.d index 816381974..489984443 100644 --- a/source/dub/packagesuppliers/maven.d +++ b/source/dub/packagesuppliers/maven.d @@ -12,7 +12,7 @@ class MavenRegistryPackageSupplier : PackageSupplier { import dub.internal.utils : retryDownload, HTTPStatusException; import dub.internal.vibecompat.data.json : serializeToJson; import dub.internal.vibecompat.inet.url : URL; - import dub.logging; + import dub.internal.logging; import std.datetime : Clock, Duration, hours, SysTime, UTC; diff --git a/source/dub/packagesuppliers/registry.d b/source/dub/packagesuppliers/registry.d index 2e132adaf..a5afa644a 100644 --- a/source/dub/packagesuppliers/registry.d +++ b/source/dub/packagesuppliers/registry.d @@ -14,7 +14,7 @@ class RegistryPackageSupplier : PackageSupplier { import dub.internal.utils : download, retryDownload, HTTPStatusException; import dub.internal.vibecompat.data.json : parseJson, parseJsonString, serializeToJson; import dub.internal.vibecompat.inet.url : URL; - import dub.logging; + import dub.internal.logging; import std.uri : encodeComponent; import std.datetime : Clock, Duration, hours, SysTime, UTC; diff --git a/source/dub/project.d b/source/dub/project.d index 4b514a2ac..8d9e419cb 100644 --- a/source/dub/project.d +++ b/source/dub/project.d @@ -15,7 +15,7 @@ import dub.internal.utils; import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.data.json; import dub.internal.vibecompat.inet.path; -import dub.logging; +import dub.internal.logging; import dub.package_; import dub.packagemanager; import dub.recipe.selection; diff --git a/source/dub/recipe/packagerecipe.d b/source/dub/recipe/packagerecipe.d index 8509d12ba..99964099b 100644 --- a/source/dub/recipe/packagerecipe.d +++ b/source/dub/recipe/packagerecipe.d @@ -10,7 +10,7 @@ module dub.recipe.packagerecipe; import dub.compilers.compiler; import dub.compilers.utils : warnOnSpecialCompilerFlags; import dub.dependency; -import dub.logging; +import dub.internal.logging; import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.inet.path; diff --git a/source/dub/recipe/sdl.d b/source/dub/recipe/sdl.d index 779beb896..b7de2d2b2 100644 --- a/source/dub/recipe/sdl.d +++ b/source/dub/recipe/sdl.d @@ -9,7 +9,7 @@ module dub.recipe.sdl; import dub.compilers.compiler; import dub.dependency; -import dub.logging; +import dub.internal.logging; import dub.internal.sdlang; import dub.internal.vibecompat.inet.path; import dub.recipe.packagerecipe; From 9f2d74d681a4892704b827b3d33638745f124cbd Mon Sep 17 00:00:00 2001 From: Bastiaan Veelo Date: Mon, 13 Jun 2022 18:42:30 +0200 Subject: [PATCH 37/42] Resolve deprecations. --- build-files.txt | 1 - source/dub/internal/git.d | 2 +- source/dub/internal/vibecompat/core/log.d | 14 -------------- 3 files changed, 1 insertion(+), 16 deletions(-) delete mode 100644 source/dub/internal/vibecompat/core/log.d diff --git a/build-files.txt b/build-files.txt index 8c32a0f30..e22bcd508 100644 --- a/build-files.txt +++ b/build-files.txt @@ -34,7 +34,6 @@ source/dub/internal/sdlang/util.d source/dub/internal/undead/xml.d source/dub/internal/utils.d source/dub/internal/vibecompat/core/file.d -source/dub/internal/vibecompat/core/log.d source/dub/internal/vibecompat/data/json.d source/dub/internal/vibecompat/data/serialization.d source/dub/internal/vibecompat/data/utils.d diff --git a/source/dub/internal/git.d b/source/dub/internal/git.d index 24e3e7bce..c8a371e4f 100644 --- a/source/dub/internal/git.d +++ b/source/dub/internal/git.d @@ -1,7 +1,7 @@ module dub.internal.git; import dub.internal.vibecompat.core.file; -import dub.internal.vibecompat.core.log; +import dub.internal.logging; import std.file; import std.string; diff --git a/source/dub/internal/vibecompat/core/log.d b/source/dub/internal/vibecompat/core/log.d deleted file mode 100644 index 5c6573718..000000000 --- a/source/dub/internal/vibecompat/core/log.d +++ /dev/null @@ -1,14 +0,0 @@ -/** +deprecated("Please use dub.internal.logging") - This module contained logging functions, but has been replaced by dub.internal.logging - which provides colored output and other facilities. - - Copyright: © 2012 rejectedsoftware e.K., © 2018 Giacomo De Lazzari - License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. - Authors: Sönke Ludwig, Giacomo De Lazzari -*/ - -deprecated("Please use dub.internal.logging") - -module dub.internal.vibecompat.core.log; - -public import dub.internal.logging; From d2a54aa7a85ea6e0a9dac44a29803c7c7f1166bd Mon Sep 17 00:00:00 2001 From: Bastiaan Veelo Date: Wed, 20 Jul 2022 15:10:16 +0200 Subject: [PATCH 38/42] Address review by WebFreak001. --- source/dub/commandline.d | 32 ++++++----- source/dub/dub.d | 8 +-- source/dub/generators/build.d | 22 +++---- source/dub/generators/generator.d | 4 +- source/dub/internal/colorize/colors.d | 82 ++------------------------- source/dub/internal/logging.d | 12 ++-- 6 files changed, 47 insertions(+), 113 deletions(-) diff --git a/source/dub/commandline.d b/source/dub/commandline.d index ccdd8afc8..e7eaf35f5 100644 --- a/source/dub/commandline.d +++ b/source/dub/commandline.d @@ -166,13 +166,17 @@ struct CommandLineHandler options.root_path = options.root_path.expandTilde.absolutePath.buildNormalizedPath; } - if (options.colors_mode == "" || options.colors_mode == "auto") { - // we already detected whether to enable colors or not with initLogging() above - // this if case is here just to make the else below work correctly - } else if (options.colors_mode == "on") { - setLoggingColorsEnabled(true); // enable colors, no matter what - } else if (options.colors_mode == "off") { - setLoggingColorsEnabled(false); // disable colors, no matter what + final switch (options.colors_mode) with (options.colors) + { + case automatic: + // Use default determined in internal.logging.initLogging(). + break; + case on: + setLoggingColorsEnabled(true); // enable colors, no matter what + break; + case off: + setLoggingColorsEnabled(false); // disable colors, no matter what + break; } } @@ -549,7 +553,8 @@ struct CommonOptions { bool help, annotate, bare; string[] registry_urls; string root_path; - string colors_mode; + enum colors { automatic, on, off } // Style violation in support of invalid option error formatting. + colors colors_mode = colors.automatic; SkipPackageSuppliers skipRegistry = SkipPackageSuppliers.none; PlacementLocation placementLocation = PlacementLocation.user; @@ -578,10 +583,11 @@ struct CommonOptions { args.getopt("verror", &verror, ["Only print errors"]); args.getopt("vquiet", &vquiet, ["Print no messages"]); args.getopt("colors", &colors_mode, [ - "Confiugre color output", - " auto: Automatically turn on/off colors (default)", - " on: Force colors enabled", - " off: Force colors disabled" + "Configure colored output. Accepted values:", + " automatic: Colored output on console/terminal,", + " unless NO_COLOR is defined (default)", + " on: Force colors enabled", + " off: Force colors disabled" ]); args.getopt("cache", &placementLocation, ["Puts any fetched packages in the specified location [local|system|user]."]); @@ -1782,7 +1788,7 @@ class UpgradeCommand : Command { enforceUsage(app_args.length == 0, "Unexpected application arguments."); enforceUsage(!m_verify, "--verify is not yet implemented."); enforce(loadCwdPackage(dub, true), "Failed to load package."); - logInfo("Upgrading", Color.yellow, "project in %s", dub.projectPath.toNativeString()); + logInfo("Upgrading", Color.cyan, "project in %s", dub.projectPath.toNativeString().color(Mode.bold)); auto options = UpgradeOptions.upgrade|UpgradeOptions.select; if (m_missingOnly) options &= ~UpgradeOptions.upgrade; if (m_prerelease) options |= UpgradeOptions.preRelease; diff --git a/source/dub/dub.d b/source/dub/dub.d index 108f124f0..c3f87274f 100644 --- a/source/dub/dub.d +++ b/source/dub/dub.d @@ -549,7 +549,7 @@ class Dub { if (basename == rootbasename) continue; if (!m_project.selections.hasSelectedVersion(basename)) { - logInfo("Upgrade", Color.yellow, + logInfo("Upgrade", Color.cyan, "Package %s would be selected with version %s", basename, ver); any = true; continue; @@ -557,7 +557,7 @@ class Dub { auto sver = m_project.selections.getSelectedVersion(basename); if (!sver.path.empty || !sver.repository.empty) continue; if (ver.version_ <= sver.version_) continue; - logInfo("Upgrade", Color.yellow, + logInfo("Upgrade", Color.cyan, "%s would be upgraded %s to %s.", basename.color(Mode.bold), sver, ver); any = true; @@ -728,7 +728,7 @@ class Dub { /// Cleans intermediate/cache files of the given package void cleanPackage(NativePath path) { - logInfo("Cleaning", Color.green, "package at %s", path.toNativeString()); + logInfo("Cleaning", Color.green, "package at %s", path.toNativeString().color(Mode.bold)); enforce(!Package.findPackageFile(path).empty, "No package found.", path.toNativeString()); // TODO: clear target files and copy files @@ -1141,7 +1141,7 @@ class Dub { } //Act smug to the user. - logInfo("Success", Color.green, "created empty project in %s", path.toNativeString()); + logInfo("Success", Color.green, "created empty project in %s", path.toNativeString().color(Mode.bold)); } private void runCustomInitialization(NativePath path, string type, string[] runArgs) diff --git a/source/dub/generators/build.d b/source/dub/generators/build.d index c87511b99..09ef0fa42 100644 --- a/source/dub/generators/build.d +++ b/source/dub/generators/build.d @@ -82,7 +82,7 @@ class BuildGenerator : ProjectGenerator { enforce(!(settings.rdmd && root_ti.buildSettings.targetType == TargetType.none), "Building package with target type \"none\" with rdmd is not supported yet."); - logInfo("Starting", Color.green, + logInfo("Starting", Color.light_green, "Performing \"%s\" build using %s for %-(%s, %).", settings.buildType.color(Color.magenta), settings.platform.compilerBinary, settings.platform.architecture); @@ -207,7 +207,7 @@ class BuildGenerator : ProjectGenerator { // run post-build commands if (!cached && buildsettings.postBuildCommands.length) { - logInfo("Post-build", Color.green, "Running commands"); + logInfo("Post-build", Color.light_green, "Running commands"); runBuildCommands(CommandType.postBuild, buildsettings.postBuildCommands, pack, m_project, settings, buildsettings, [["DUB_BUILD_PATH" : target_path.parentPath.toNativeString.absolutePath]]); } @@ -244,10 +244,10 @@ class BuildGenerator : ProjectGenerator { return false; } - logInfo("Building", Color.green, "%s %s: building configuration [%s]", pack.name.color(Mode.bold), pack.version_, config.color(Color.blue)); + logInfo("Building", Color.light_green, "%s %s: building configuration [%s]", pack.name.color(Mode.bold), pack.version_, config.color(Color.blue)); if( buildsettings.preBuildCommands.length ){ - logInfo("Pre-build", Color.green, "Running commands"); + logInfo("Pre-build", Color.light_green, "Running commands"); runBuildCommands(CommandType.preBuild, buildsettings.preBuildCommands, pack, m_project, settings, buildsettings); } @@ -309,11 +309,11 @@ class BuildGenerator : ProjectGenerator { flags ~= mainsrc.relativeTo(cwd).toNativeString(); if (buildsettings.preBuildCommands.length){ - logInfo("Pre-build", Color.green, "Running commands"); + logInfo("Pre-build", Color.light_green, "Running commands"); runCommands(buildsettings.preBuildCommands); } - logInfo("Building", Color.green, "%s %s [%s]", pack.name.color(Mode.bold), pack.version_, config.color(Color.blue)); + logInfo("Building", Color.light_green, "%s %s [%s]", pack.name.color(Mode.bold), pack.version_, config.color(Color.blue)); logInfo("Running rdmd..."); logDiagnostic("rdmd %s", join(flags, " ")); @@ -340,7 +340,7 @@ class BuildGenerator : ProjectGenerator { f = fp.toNativeString(); } - logInfo("Building", Color.green, "%s %s [%s]", pack.name.color(Mode.bold), pack.version_, config.color(Color.blue)); + logInfo("Building", Color.light_green, "%s %s [%s]", pack.name.color(Mode.bold), pack.version_, config.color(Color.blue)); // make all target/import paths relative string makeRelative(string path) { @@ -367,7 +367,7 @@ class BuildGenerator : ProjectGenerator { } if( buildsettings.preBuildCommands.length ){ - logInfo("Pre-build", Color.green, "Running commands"); + logInfo("Pre-build", Color.light_green, "Running commands"); runBuildCommands(CommandType.preBuild, buildsettings.preBuildCommands, pack, m_project, settings, buildsettings); } @@ -530,7 +530,7 @@ class BuildGenerator : ProjectGenerator { auto objs = new string[](srcs.walkLength); void compileSource(size_t i, string src) { - logInfo("Compiling", Color.green, "%s", src); + logInfo("Compiling", Color.light_green, "%s", src); const objPath = pathToObjName(settings.platform, src); objs[i] = compileUnit(src, objPath, buildsettings, settings); } @@ -541,7 +541,7 @@ class BuildGenerator : ProjectGenerator { foreach (i, src; srcs.array) compileSource(i, src); } - logInfo("Linking", Color.green, "%s", buildsettings.targetName.color(Mode.bold)); + logInfo("Linking", Color.light_green, "%s", buildsettings.targetName.color(Mode.bold)); lbuildsettings.sourceFiles = is_static_library ? [] : lbuildsettings.sourceFiles.filter!(f => isLinkerFile(settings.platform, f)).array; settings.compiler.setTarget(lbuildsettings, settings.platform); settings.compiler.prepareBuildSettings(lbuildsettings, settings.platform, BuildSetting.commandLineSeparate|BuildSetting.sourceFiles); @@ -580,7 +580,7 @@ class BuildGenerator : ProjectGenerator { settings.compiler.invoke(buildsettings, settings.platform, settings.compileCallback); if (generate_binary) { - logInfo("Linking", Color.green, "%s", buildsettings.targetName.color(Mode.bold)); + logInfo("Linking", Color.light_green, "%s", buildsettings.targetName.color(Mode.bold)); settings.compiler.invokeLinker(lbuildsettings, settings.platform, [tempobj.toNativeString()], settings.linkCallback); } } diff --git a/source/dub/generators/generator.d b/source/dub/generators/generator.d index c428df441..ba1427853 100644 --- a/source/dub/generators/generator.d +++ b/source/dub/generators/generator.d @@ -891,7 +891,7 @@ private void prepareGeneration(in Package pack, in Project proj, in GeneratorSet in BuildSettings buildsettings) { if (buildsettings.preGenerateCommands.length && !isRecursiveInvocation(pack.name)) { - logInfo("Pre-gen", Color.green, "Running commands for %s", pack.name); + logInfo("Pre-gen", Color.light_green, "Running commands for %s", pack.name); runBuildCommands(CommandType.preGenerate, buildsettings.preGenerateCommands, pack, proj, settings, buildsettings); } } @@ -903,7 +903,7 @@ private void finalizeGeneration(in Package pack, in Project proj, in GeneratorSe in BuildSettings buildsettings, NativePath target_path, bool generate_binary) { if (buildsettings.postGenerateCommands.length && !isRecursiveInvocation(pack.name)) { - logInfo("Post-gen", Color.green, "Running commands for %s", pack.name); + logInfo("Post-gen", Color.light_green, "Running commands for %s", pack.name); runBuildCommands(CommandType.postGenerate, buildsettings.postGenerateCommands, pack, proj, settings, buildsettings); } diff --git a/source/dub/internal/colorize/colors.d b/source/dub/internal/colorize/colors.d index f62ab2632..e0e1f51f4 100644 --- a/source/dub/internal/colorize/colors.d +++ b/source/dub/internal/colorize/colors.d @@ -10,7 +10,7 @@ import std.string : format; private template color_type(int offset) { - static enum type : int + enum type : int { init = 39 + offset, @@ -38,7 +38,7 @@ alias color_type!0 .type fg; alias color_type!10 .type bg; // Text modes -static enum mode : int +enum mode : int { init = 0, bold = 1, @@ -64,7 +64,6 @@ static enum mode : int * ); * --- */ - string color( const string str, const fg c=fg.init, @@ -90,71 +89,6 @@ unittest ret = "This is red on blue blinking".color(fg.red, bg.blue, mode.blink); assert(ret == "\033[5;31;44mThis is red on blue blinking\033[0m"); - - ret = color("This is magenta", "magenta"); - assert(ret == "\033[35mThis is magenta\033[0m"); -} - -string colorHelper(const string str, const string name) pure -{ - int code; - - switch(name) - { - case "init": code = 39; break; - - case "black" : code = 30; break; - case "red" : code = 31; break; - case "green" : code = 32; break; - case "yellow" : code = 33; break; - case "blue" : code = 34; break; - case "magenta": code = 35; break; - case "cyan" : code = 36; break; - case "white" : code = 37; break; - - case "light_black" : code = 90; break; - case "light_red" : code = 91; break; - case "light_green" : code = 92; break; - case "light_yellow" : code = 93; break; - case "light_blue" : code = 94; break; - case "light_magenta": code = 95; break; - case "light_cyan" : code = 96; break; - case "light_white" : code = 97; break; - - case "bg_init": code = 49; break; - - case "bg_black" : code = 40; break; - case "bg_red" : code = 41; break; - case "bg_green" : code = 42; break; - case "bg_yellow" : code = 43; break; - case "bg_blue" : code = 44; break; - case "bg_magenta": code = 45; break; - case "bg_cyan" : code = 46; break; - case "bg_white" : code = 47; break; - - case "bg_light_black" : code = 100; break; - case "bg_light_red" : code = 101; break; - case "bg_light_green" : code = 102; break; - case "bg_light_yellow" : code = 103; break; - case "bg_light_blue" : code = 104; break; - case "bg_light_magenta": code = 105; break; - case "bg_light_cyan" : code = 106; break; - case "bg_light_white" : code = 107; break; - - case "mode_init": code = 0; break; - case "mode_bold" : code = 1; break; - case "mode_underline": code = 4; break; - case "mode_blink" : code = 5; break; - case "mode_swap" : code = 7; break; - case "mode_hide" : code = 8; break; - - default: - throw new Exception( - "Unknown fg color, bg color or mode \"" ~ name ~ "\"" - ); - } - - return format("\033[%dm%s\033[0m", code, str); } string colorHelper(T)(const string str, const T t=T.init) pure @@ -163,14 +97,10 @@ string colorHelper(T)(const string str, const T t=T.init) pure return format("\033[%dm%s\033[0m", t, str); } -alias colorHelper!bg background; -alias colorHelper!fg foreground; -alias colorHelper!mode style; - -alias background color; -alias foreground color; -alias style color; -alias colorHelper color; +alias background = colorHelper!bg; +alias foreground = colorHelper!fg; +alias style = colorHelper!mode; +alias color = colorHelper; unittest { diff --git a/source/dub/internal/logging.d b/source/dub/internal/logging.d index cc068c09e..ecada5562 100644 --- a/source/dub/internal/logging.d +++ b/source/dub/internal/logging.d @@ -105,20 +105,18 @@ extern (C) int isatty(int); /** This function must be called at the beginning for the program, before any logging occurs. It will detect whether or not stdout/stderr are a console/TTY - and will consequently disable colored output if needed. + and will consequently disable colored output if needed. Also, if a NO_COLOR + environment variable is defined, colors are disabled (https://no-color.org/). Forgetting to call the function will result in ASCII escape sequences in the - piped output, probably an undesiderable thing. + piped output, probably an undesirable thing. */ void initLogging() { + import std.process : environment; import core.stdc.stdio; - // Initially enable colors, we'll disable them during this functions if we - // find any reason to - _printColors = true; - - // The following stuff depends on the platform + _printColors = environment.get("NO_COLOR") == ""; version (Windows) { version (CRuntime_DigitalMars) From f0122be87425af886f04acfc48726a02abdb3ebf Mon Sep 17 00:00:00 2001 From: Bastiaan Veelo Date: Wed, 20 Jul 2022 16:21:28 +0200 Subject: [PATCH 39/42] Make unittest independent of byte value escape sequence. --- source/dub/internal/colorize/colors.d | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/source/dub/internal/colorize/colors.d b/source/dub/internal/colorize/colors.d index e0e1f51f4..5d6729466 100644 --- a/source/dub/internal/colorize/colors.d +++ b/source/dub/internal/colorize/colors.d @@ -76,19 +76,21 @@ string color( unittest { + import std.string : representation; + string ret; ret = "This is yellow".color(fg.yellow); - assert(ret == "\033[33mThis is yellow\033[0m"); + assert(ret.representation == "\033[0;33;49mThis is yellow\033[0m".representation); ret = "This is light green".color(fg.light_green); - assert(ret == "\033[92mThis is light green\033[0m"); + assert(ret.representation == "\033[0;92;49mThis is light green\033[0m".representation); ret = "This is light blue with red background".color(fg.light_blue, bg.red); - assert(ret == "\033[0;94;41mThis is light blue with red background\033[0m"); + assert(ret.representation == "\033[0;94;41mThis is light blue with red background\033[0m".representation); ret = "This is red on blue blinking".color(fg.red, bg.blue, mode.blink); - assert(ret == "\033[5;31;44mThis is red on blue blinking\033[0m"); + assert(ret.representation == "\033[5;31;44mThis is red on blue blinking\033[0m".representation); } string colorHelper(T)(const string str, const T t=T.init) pure @@ -104,12 +106,13 @@ alias color = colorHelper; unittest { + import std.string : representation; + string ret; ret = "This is red on blue blinking" .foreground(fg.red) .background(bg.blue) .style(mode.blink); - - assert(ret == "\033[5m\033[44m\033[31mThis is red on blue blinking\033[0m\033[0m\033[0m"); + assert(ret.representation == "\033[5m\033[44m\033[31mThis is red on blue blinking\033[0m\033[0m\033[0m".representation); } From 48d7c11cab0318f765b420fb64e419d0f54c0f7d Mon Sep 17 00:00:00 2001 From: Bastiaan Veelo Date: Wed, 20 Jul 2022 17:37:33 +0200 Subject: [PATCH 40/42] Don't require PERL regex in unittest. --- test/colored-output.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/colored-output.sh b/test/colored-output.sh index 349e2cb6a..afc1bb373 100755 --- a/test/colored-output.sh +++ b/test/colored-output.sh @@ -5,13 +5,13 @@ cd ${CURR_DIR}/1-exec-simple # Test --colors=off disabling colors correctly -${DUB} build --colors=off --compiler=${DC} 2>&1 | { ! grep -P '\e\[' -c; } +${DUB} build --colors=off --compiler=${DC} 2>&1 | { ! \grep $'^\x1b\[' -c; } -# Test --colors=auto detecting no TTY -${DUB} build --colors=auto --compiler=${DC} 2>&1 | { ! grep -P '\e\[' -c; } +# Test --colors=automatic detecting no TTY +${DUB} build --colors=automatic --compiler=${DC} 2>&1 | { ! \grep $'^\x1b\[' -c; } -# Test no --colors= option defaulting to auto -${DUB} build --compiler=${DC} 2>&1 | { ! grep -P '\e\[' -c; } +# Test no --colors= option defaulting to automatic +${DUB} build --compiler=${DC} 2>&1 | { ! \grep $'^\x1b\[' -c; } # Test --colors=on enabling colors in any case -${DUB} build --colors=on --compiler=${DC} 2>&1 | grep -P '\e\[' -c +${DUB} build --colors=on --compiler=${DC} 2>&1 | \grep $'^\x1b\[' -c From 8b5c680c2a4647723cde9003beca63ff08b2ddc9 Mon Sep 17 00:00:00 2001 From: Bastiaan Veelo Date: Thu, 28 Jul 2022 20:17:54 +0200 Subject: [PATCH 41/42] Incorporate review by Jan Jurzitza . --- source/dub/commandline.d | 2 +- source/dub/dub.d | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/dub/commandline.d b/source/dub/commandline.d index e7eaf35f5..671b715e7 100644 --- a/source/dub/commandline.d +++ b/source/dub/commandline.d @@ -585,7 +585,7 @@ struct CommonOptions { args.getopt("colors", &colors_mode, [ "Configure colored output. Accepted values:", " automatic: Colored output on console/terminal,", - " unless NO_COLOR is defined (default)", + " unless NO_COLOR is set and non-empty (default)", " on: Force colors enabled", " off: Force colors disabled" ]); diff --git a/source/dub/dub.d b/source/dub/dub.d index c3f87274f..964059a54 100644 --- a/source/dub/dub.d +++ b/source/dub/dub.d @@ -558,7 +558,7 @@ class Dub { if (!sver.path.empty || !sver.repository.empty) continue; if (ver.version_ <= sver.version_) continue; logInfo("Upgrade", Color.cyan, - "%s would be upgraded %s to %s.", + "%s would be upgraded from %s to %s.", basename.color(Mode.bold), sver, ver); any = true; } From 60417cf2ae0b83b50800b5dc5ca6b020ab004dbc Mon Sep 17 00:00:00 2001 From: Bastiaan Veelo Date: Thu, 28 Jul 2022 21:13:22 +0200 Subject: [PATCH 42/42] File has moved. --- build-files.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build-files.txt b/build-files.txt index e22bcd508..e1ba691a1 100644 --- a/build-files.txt +++ b/build-files.txt @@ -43,7 +43,7 @@ source/dub/internal/colorize/colors.d source/dub/internal/colorize/cwrite.d source/dub/internal/colorize/package.d source/dub/internal/colorize/winterm.d -source/dub/logging.d +source/dub/internal/logging.d source/dub/package_.d source/dub/packagemanager.d source/dub/packagesupplier.d