diff --git a/source/HTML.cpp b/source/HTML.cpp index e0e2053..b2d7b67 100644 --- a/source/HTML.cpp +++ b/source/HTML.cpp @@ -184,6 +184,11 @@ void ToHTML::NewLine() const noexcept { Write("
"); Write(Instance.TimeStampStyle); Write(GetSimpleTime()); + Write("|"); + if (Instance.CurrentIntent != Intent::Ignore) + Write(Instance.IntentStyle[int(Instance.CurrentIntent)].prefix); + else + Write(" "); Write("| "); auto tabs = Instance.GetTabs(); @@ -214,7 +219,7 @@ void ToHTML::WriteHeader() const { /// Write file footer - just the official shutdown timestamp void ToHTML::WriteFooter() const { - Write("

Log ended - "); + Write("

Log ended - "); Write(GetAdvancedTime()); Write("

"); } diff --git a/source/Logger.cpp b/source/Logger.cpp index 0d2c500..a2f9a60 100644 --- a/source/Logger.cpp +++ b/source/Logger.cpp @@ -75,9 +75,7 @@ ScopedTabs::~ScopedTabs() noexcept { } /// Logger construction -Interface::Interface() { - mStyleStack.push(DefaultStyle); -} +Interface::Interface() {} /// Logger copy-construction Interface::Interface(const Interface& other) @@ -109,6 +107,9 @@ Text Logger::A::Interface::GetSimpleTime() noexcept { /// Write a string view to stdout /// @param stdString - the text view to write void Interface::Write(const TextView& stdString) const noexcept { + if (CurrentIntent == Intent::Ignore) + return; + // Dispatch to redirectors if (not mRedirectors.empty()) { for (auto attachment : mRedirectors) @@ -129,6 +130,9 @@ void Interface::Write(const TextView& stdString) const noexcept { /// Change the style /// @param s - the style void Interface::Write(Style s) const noexcept { + if (CurrentIntent == Intent::Ignore) + return; + // Dispatch to redirectors if (not mRedirectors.empty()) { for (auto attachment : mRedirectors) @@ -147,6 +151,9 @@ void Interface::Write(Style s) const noexcept { /// Add a new line, tabulating properly, but continuing the previous style void Interface::NewLine() const noexcept { + if (CurrentIntent == Intent::Ignore) + return; + // Dispatch to redirectors if (not mRedirectors.empty()) { for (auto attachment : mRedirectors) @@ -159,7 +166,11 @@ void Interface::NewLine() const noexcept { // Clear formatting, add new line, simple time stamp, and tabs fmt::print("\n"); FmtPrintStyle(TimeStampStyle); - fmt::print("{}| ", GetSimpleTime()); + + if (CurrentIntent == Intent::Ignore) + fmt::print("{}| | ", GetSimpleTime()); + else + fmt::print("{}|{}| ", GetSimpleTime(), IntentStyle[int(CurrentIntent)].prefix); if (mTabulator) { auto tabs = mTabulator; @@ -170,6 +181,11 @@ void Interface::NewLine() const noexcept { } } + if (mStyleStack.empty()) { + const_cast(mStyleStack) + .push(GetCurrentStyle()); + } + FmtPrintStyle(mStyleStack.top()); // Dispatch to duplicators @@ -215,7 +231,11 @@ void Interface::RunCommand(Command c) noexcept { case Command::Reset: while (not mStyleStack.empty()) mStyleStack.pop(); - mStyleStack.push(DefaultStyle); + + if (CurrentIntent == Intent::Ignore) + CurrentIntent = DefaultIntent; + + mStyleStack.push(GetCurrentStyle()); Write(mStyleStack.top()); break; case Command::Time: @@ -225,19 +245,27 @@ void Interface::RunCommand(Command c) noexcept { Write(GetAdvancedTime()); break; case Command::Pop: - if (mStyleStack.size() > 1) + if (not mStyleStack.empty()) mStyleStack.pop(); + + if (mStyleStack.empty()) + mStyleStack.push(GetCurrentStyle()); + Write(mStyleStack.top()); break; case Command::Push: mStyleStack.push(mStyleStack.top()); break; case Command::PopAndPush: - if (mStyleStack.size() > 1) + if (not mStyleStack.empty()) mStyleStack.pop(); + mStyleStack.push(mStyleStack.top()); break; case Command::Stylize: + if (mStyleStack.empty()) + mStyleStack.push(GetCurrentStyle()); + Write(mStyleStack.top()); break; case Command::Tab: @@ -250,10 +278,13 @@ void Interface::RunCommand(Command c) noexcept { } } -/// Change the foreground/background color +/// Change the foreground/background color by modifying the current style /// @param c_with_flags - the color with optional mixing flags /// @return the last style, with coloring applied -const Style& Interface::SetColor(Color c_with_flags) noexcept { +auto Interface::SetColor(Color c_with_flags) noexcept -> const Style& { + if (mStyleStack.empty()) + mStyleStack.push(GetCurrentStyle()); + if (static_cast(c_with_flags) & static_cast(Color::PreviousColor)) { // We have to pop @@ -309,21 +340,40 @@ const Style& Interface::SetColor(Color c_with_flags) noexcept { return style; } -/// Change the emphasis -/// @param c - the color -const Style& Interface::SetEmphasis(Emphasis e) noexcept { +/// Change the emphasis by modifying the current style +/// @param e - the emphasis +auto Interface::SetEmphasis(Emphasis e) noexcept -> const Style& { + if (mStyleStack.empty()) + mStyleStack.push(GetCurrentStyle()); + auto& style = mStyleStack.top(); style |= static_cast(e); return style; } -/// Change the style +/// Change the style by overwriting the current one /// @param s - the style -const Style& Interface::SetStyle(Style s) noexcept { - mStyleStack.top() = s; +auto Interface::SetStyle(Style s) noexcept -> const Style& { + if (mStyleStack.empty()) + mStyleStack.emplace(s); + else + mStyleStack.top() = s; return mStyleStack.top(); } +/// Get the current style +/// @returns either the top of the style stack, or the style of the current +/// intent (or a default style if current intent is Ignore) +auto Interface::GetCurrentStyle() const noexcept -> Style { + if (mStyleStack.empty()) { + if (CurrentIntent != Intent::Ignore) + return IntentStyle[int(CurrentIntent)].style; + else + return {}; + } + else return mStyleStack.top(); +} + /// Attach another logger, if no redirectors are attached, any logging /// will be duplicated to the provided interface /// @attention the logger doesn't have ownership of the attachment @@ -411,6 +461,19 @@ Logger::A::Interface& Logger::A::Interface::operator << (::std::nullptr_t) noexc return *this; } +/// Sets the current intent, and sylizes accordingly, unles Intent::Ignore +/// @return a reference to the logger for chaining +Logger::A::Interface& Logger::A::Interface::operator << (Intent i) noexcept { + if (i != Intent::Counter) + Instance.CurrentIntent = i; + + if (i < Intent::Counter) { + Instance.SetStyle(Instance.IntentStyle[int(i)].style); + Instance.RunCommand(Command::Stylize); + } + return *this; +} + /// Push a number of tabs /// @param t - the tabs to push /// @return a reference to the logger for chaining diff --git a/source/Logger.hpp b/source/Logger.hpp index 7975836..c71b89e 100644 --- a/source/Logger.hpp +++ b/source/Logger.hpp @@ -259,6 +259,33 @@ namespace Langulus::Logger /// GCC equates templates with enum types as their underlying type, so we /// are forced to define these anums as enum class, and then do using enum using enum Command; + + /// Types of predefined messages, each with its unique style and search + /// patterns. + enum class Intent { + FatalError = 0, + Error, + Warning, + Verbose, + Info, + Message, + Special, + Flow, + Input, + Network, + OS, + Prompt, + + Counter, + Ignore + }; + + /// Can be used to specify each intent's style and search patterns + struct IntentProperties { + TextView prefix; + Style style; + bool silenced = false; + }; /// Tabulation marker (can be pushed to log) struct Tabs { @@ -319,6 +346,7 @@ namespace Langulus::Logger LANGULUS_API(LOGGER) Interface& operator << (Emphasis) noexcept; LANGULUS_API(LOGGER) Interface& operator << (Style) noexcept; LANGULUS_API(LOGGER) Interface& operator << (::std::nullptr_t) noexcept; + LANGULUS_API(LOGGER) Interface& operator << (Intent) noexcept; LANGULUS_API(LOGGER) Interface& operator << (const Tabs&) noexcept; LANGULUS_API(LOGGER) ScopedTabs operator << (Tabs&&) noexcept; @@ -351,11 +379,31 @@ namespace Langulus::Logger ::std::list mDuplicators; public: - // Tabulator color and formatting - static constexpr Style DefaultStyle = {}; - static constexpr Style TabStyle = fmt::fg(fmt::terminal_color::bright_black); - static constexpr Style TimeStampStyle = TabStyle; - static constexpr TextView TabString = "| "; + // Current intent + Intent CurrentIntent = Intent::Info; + + // Intent style customization point + IntentProperties IntentStyle[int(Intent::Counter)] = { + {"F", fmt::fg(fmt::terminal_color::red)}, // FatalError + {"E", fmt::fg(fmt::terminal_color::bright_red)}, // Error + {"W", fmt::fg(fmt::terminal_color::yellow)}, // Warning + {"V", fmt::fg(fmt::terminal_color::bright_black)}, // Verbose + {"I", fmt::fg(fmt::terminal_color::white)}, // Info + {"M", fmt::fg(fmt::terminal_color::bright_white)}, // Message + {"S", fmt::fg(fmt::terminal_color::bright_magenta)}, // Special + {"L", fmt::fg(fmt::terminal_color::cyan)}, // Flow + {"N", fmt::fg(fmt::terminal_color::bright_blue)}, // Input + {"T", fmt::fg(fmt::terminal_color::bright_yellow)}, // Network + {"O", fmt::fg(fmt::terminal_color::blue)}, // OS + {"P", fmt::fg(fmt::terminal_color::bright_green)} // Prompt + }; + + // Tabulator color and formatting customization + Intent DefaultIntent = Intent::Info; + Style TabStyle = fmt::fg(fmt::terminal_color::bright_black); + Style TimeStampStyle = TabStyle; + TextView TabString = "| "; + size_t GetTabs() const noexcept { return mTabulator; } LANGULUS_API(LOGGER) Interface(); @@ -374,9 +422,10 @@ namespace Langulus::Logger /// State changers /// LANGULUS_API(LOGGER) void RunCommand(Command) noexcept; - LANGULUS_API(LOGGER) const Style& SetStyle(Style) noexcept; - LANGULUS_API(LOGGER) const Style& SetColor(Color) noexcept; - LANGULUS_API(LOGGER) const Style& SetEmphasis(Emphasis) noexcept; + LANGULUS_API(LOGGER) auto GetCurrentStyle() const noexcept -> Style; + LANGULUS_API(LOGGER) auto SetStyle(Style) noexcept -> const Style&; + LANGULUS_API(LOGGER) auto SetColor(Color) noexcept -> const Style&; + LANGULUS_API(LOGGER) auto SetEmphasis(Emphasis) noexcept -> const Style&; /// /// Attachments diff --git a/source/Logger.inl b/source/Logger.inl index b61fa50..978b5f1 100644 --- a/source/Logger.inl +++ b/source/Logger.inl @@ -102,7 +102,7 @@ namespace Langulus::Logger return operator << (TextView {formatted}); } - /// A general new-line write function that continues the last style + /// A general new-line write function that continues the last intent/style /// @tparam ...T - a sequence of elements to log (deducible) /// @return a reference to the logger for chaining template LANGULUS(INLINED) @@ -115,7 +115,7 @@ namespace Langulus::Logger return (Instance); } - /// A general same-line write function that continues the last style + /// A general same-line write function that continues the last style/intent /// @tparam ...T - a sequence of elements to log (deducible) /// @return a reference to the logger for chaining template LANGULUS(INLINED) @@ -127,15 +127,18 @@ namespace Langulus::Logger /// Write a section on a new line, tab all consecutive lines, bold it, /// and return the scoped tabs, that will be untabbed automatically at the - /// scope's end + /// scope's end. Section color is context dependent on the current style /// @tparam ...T - a sequence of elements to log (deducible) /// @return a scoped tab template LANGULUS(INLINED) decltype(auto) Section(T&&...arguments) noexcept { if constexpr (sizeof...(arguments) > 0) { + const auto currentStyle = Instance.GetCurrentStyle(); Instance.NewLine(); - Instance << Interface::TabStyle << "┌─ " - << Color::PushWhite << Emphasis::Bold << Emphasis::Underline; + Instance << Command::Push + << Instance.TabStyle << "┌─ " + << currentStyle + << Emphasis::Underline; (Instance << ... << ::std::forward(arguments)); return (Instance << Command::Pop << Tabs {}); } @@ -148,15 +151,15 @@ namespace Langulus::Logger template LANGULUS(INLINED) decltype(auto) Fatal([[maybe_unused]] T&&...arguments) noexcept { #ifdef LANGULUS_LOGGER_ENABLE_FATALERRORS + Instance << Intent::FatalError; Instance.NewLine(); - Instance << Command::PopAndPush << Color::DarkRed; - if constexpr (sizeof...(arguments) > 0) { - Instance << "FATAL ERROR: "; + if constexpr (sizeof...(arguments) > 0) return (Instance << ... << ::std::forward(arguments)); - } - else return (Instance); + else + return (Instance); #else + Instance << Intent::Ignore; return (Instance); #endif } @@ -166,8 +169,13 @@ namespace Langulus::Logger /// @return a scoped tab, that will untab when destroyed template LANGULUS(INLINED) ScopedTabs FatalTab([[maybe_unused]] T&&...arguments) noexcept { - Fatal(::std::forward(arguments)...); - return (Instance << Tabs {}); + #ifdef LANGULUS_LOGGER_ENABLE_FATALERRORS + Fatal(::std::forward(arguments)...); + return (Instance << Tabs {}); + #else + Instance << Intent::Ignore; + return ScopedTabs {0}; + #endif } /// Write a new-line error @@ -176,15 +184,15 @@ namespace Langulus::Logger template LANGULUS(INLINED) decltype(auto) Error([[maybe_unused]] T&&...arguments) noexcept { #ifdef LANGULUS_LOGGER_ENABLE_ERRORS + Instance << Intent::Error; Instance.NewLine(); - Instance << Command::PopAndPush << Color::Red; - if constexpr (sizeof...(arguments) > 0) { - Instance << "ERROR: "; + if constexpr (sizeof...(arguments) > 0) return (Instance << ... << ::std::forward(arguments)); - } - else return (Instance); + else + return (Instance); #else + Instance << Intent::Ignore; return (Instance); #endif } @@ -194,8 +202,13 @@ namespace Langulus::Logger /// @return a scoped tab, that will untab when destroyed template LANGULUS(INLINED) ScopedTabs ErrorTab([[maybe_unused]] T&&...arguments) noexcept { - Error(::std::forward(arguments)...); - return (Instance << Tabs {}); + #ifdef LANGULUS_LOGGER_ENABLE_ERRORS + Error(::std::forward(arguments)...); + return (Instance << Tabs {}); + #else + Instance << Intent::Ignore; + return ScopedTabs {0}; + #endif } /// Write a new-line warning @@ -204,15 +217,15 @@ namespace Langulus::Logger template LANGULUS(INLINED) decltype(auto) Warning([[maybe_unused]] T&&...arguments) noexcept { #ifdef LANGULUS_LOGGER_ENABLE_WARNINGS + Instance << Intent::Warning; Instance.NewLine(); - Instance << Command::PopAndPush << Color::DarkYellow; - if constexpr (sizeof...(arguments) > 0) { - Instance << "WARNING: "; + if constexpr (sizeof...(arguments) > 0) return (Instance << ... << ::std::forward(arguments)); - } - else return (Instance); + else + return (Instance); #else + Instance << Intent::Ignore; return (Instance); #endif } @@ -222,8 +235,13 @@ namespace Langulus::Logger /// @return a scoped tab, that will untab when destroyed template LANGULUS(INLINED) ScopedTabs WarningTab([[maybe_unused]] T&&...arguments) noexcept { - Warning(::std::forward(arguments)...); - return (Instance << Tabs {}); + #ifdef LANGULUS_LOGGER_ENABLE_WARNINGS + Warning(::std::forward(arguments)...); + return (Instance << Tabs {}); + #else + Instance << Intent::Ignore; + return ScopedTabs {0}; + #endif } /// Write a new-line with verbose information @@ -232,15 +250,15 @@ namespace Langulus::Logger template LANGULUS(INLINED) decltype(auto) Verbose([[maybe_unused]] T&&...arguments) noexcept { #ifdef LANGULUS_LOGGER_ENABLE_VERBOSE + Instance << Intent::Verbose; Instance.NewLine(); - Instance << Command::PopAndPush << Color::DarkGray; - if constexpr (sizeof...(arguments) > 0) { - Instance << "VERBOSE: "; + if constexpr (sizeof...(arguments) > 0) return (Instance << ... << ::std::forward(arguments)); - } - else return (Instance); + else + return (Instance); #else + Instance << Intent::Ignore; return (Instance); #endif } @@ -250,8 +268,13 @@ namespace Langulus::Logger /// @return a scoped tab, that will untab when destroyed template LANGULUS(INLINED) ScopedTabs VerboseTab([[maybe_unused]] T&&...arguments) noexcept { - Verbose(::std::forward(arguments)...); - return (Instance << Tabs {}); + #ifdef LANGULUS_LOGGER_ENABLE_VERBOSE + Verbose(::std::forward(arguments)...); + return (Instance << Tabs {}); + #else + Instance << Intent::Ignore; + return ScopedTabs {0}; + #endif } /// Write a new-line with information @@ -260,15 +283,15 @@ namespace Langulus::Logger template LANGULUS(INLINED) decltype(auto) Info([[maybe_unused]] T&&...arguments) noexcept { #ifdef LANGULUS_LOGGER_ENABLE_INFOS + Instance << Intent::Info; Instance.NewLine(); - Instance << Command::PopAndPush << Color::Gray; - if constexpr (sizeof...(arguments) > 0) { - Instance << "INFO: "; + if constexpr (sizeof...(arguments) > 0) return (Instance << ... << ::std::forward(arguments)); - } - else return (Instance); + else + return (Instance); #else + Instance << Intent::Ignore; return (Instance); #endif } @@ -278,8 +301,13 @@ namespace Langulus::Logger /// @return a scoped tab, that will untab when destroyed template LANGULUS(INLINED) ScopedTabs InfoTab([[maybe_unused]] T&&...arguments) noexcept { - Info(::std::forward(arguments)...); - return (Instance << Tabs {}); + #ifdef LANGULUS_LOGGER_ENABLE_INFOS + Info(::std::forward(arguments)...); + return (Instance << Tabs {}); + #else + Instance << Intent::Ignore; + return ScopedTabs {0}; + #endif } /// Write a new-line with a personal message @@ -288,15 +316,15 @@ namespace Langulus::Logger template LANGULUS(INLINED) decltype(auto) Message([[maybe_unused]] T&&...arguments) noexcept { #ifdef LANGULUS_LOGGER_ENABLE_MESSAGES + Instance << Intent::Message; Instance.NewLine(); - Instance << Command::PopAndPush << Color::White; - if constexpr (sizeof...(arguments) > 0) { - Instance << "MESSAGE: "; + if constexpr (sizeof...(arguments) > 0) return (Instance << ... << ::std::forward(arguments)); - } - else return (Instance); + else + return (Instance); #else + Instance << Intent::Ignore; return (Instance); #endif } @@ -306,8 +334,13 @@ namespace Langulus::Logger /// @return a scoped tab, that will untab when destroyed template LANGULUS(INLINED) ScopedTabs MessageTab([[maybe_unused]] T&&...arguments) noexcept { - Message(::std::forward(arguments)...); - return (Instance << Tabs {}); + #ifdef LANGULUS_LOGGER_ENABLE_MESSAGES + Message(::std::forward(arguments)...); + return (Instance << Tabs {}); + #else + Instance << Intent::Ignore; + return ScopedTabs {0}; + #endif } /// Write a new-line with special text @@ -316,15 +349,15 @@ namespace Langulus::Logger template LANGULUS(INLINED) decltype(auto) Special([[maybe_unused]] T&&...arguments) noexcept { #ifdef LANGULUS_LOGGER_ENABLE_SPECIALS + Instance << Intent::Special; Instance.NewLine(); - Instance << Command::PopAndPush << Color::Purple; - if constexpr (sizeof...(arguments) > 0) { - Instance << "SPECIAL: "; + if constexpr (sizeof...(arguments) > 0) return (Instance << ... << ::std::forward(arguments)); - } - else return (Instance); + else + return (Instance); #else + Instance << Intent::Ignore; return (Instance); #endif } @@ -334,8 +367,13 @@ namespace Langulus::Logger /// @return a scoped tab, that will untab when destroyed template LANGULUS(INLINED) ScopedTabs SpecialTab([[maybe_unused]] T&&...arguments) noexcept { - Special(::std::forward(arguments)...); - return (Instance << Tabs {}); + #ifdef LANGULUS_LOGGER_ENABLE_SPECIALS + Special(::std::forward(arguments)...); + return (Instance << Tabs {}); + #else + Instance << Intent::Ignore; + return ScopedTabs {0}; + #endif } /// Write a new-line with flow information @@ -344,15 +382,15 @@ namespace Langulus::Logger template LANGULUS(INLINED) decltype(auto) Flow([[maybe_unused]] T&&...arguments) noexcept { #ifdef LANGULUS_LOGGER_ENABLE_FLOWS + Instance << Intent::Flow; Instance.NewLine(); - Instance << Command::PopAndPush << Color::DarkCyan; - if constexpr (sizeof...(arguments) > 0) { - Instance << "FLOW: "; + if constexpr (sizeof...(arguments) > 0) return (Instance << ... << ::std::forward(arguments)); - } - else return (Instance); + else + return (Instance); #else + Instance << Intent::Ignore; return (Instance); #endif } @@ -362,8 +400,13 @@ namespace Langulus::Logger /// @return a scoped tab, that will untab when destroyed template LANGULUS(INLINED) ScopedTabs FlowTab([[maybe_unused]] T&&...arguments) noexcept { - Flow(::std::forward(arguments)...); - return (Instance << Tabs {}); + #ifdef LANGULUS_LOGGER_ENABLE_FLOWS + Flow(::std::forward(arguments)...); + return (Instance << Tabs {}); + #else + Instance << Intent::Ignore; + return ScopedTabs {0}; + #endif } /// Write a new-line on user input @@ -372,15 +415,15 @@ namespace Langulus::Logger template LANGULUS(INLINED) decltype(auto) Input([[maybe_unused]] T&&...arguments) noexcept { #ifdef LANGULUS_LOGGER_ENABLE_INPUTS + Instance << Intent::Input; Instance.NewLine(); - Instance << Command::PopAndPush << Color::Blue; - if constexpr (sizeof...(arguments) > 0) { - Instance << "INPUT: "; + if constexpr (sizeof...(arguments) > 0) return (Instance << ... << ::std::forward(arguments)); - } - else return (Instance); + else + return (Instance); #else + Instance << Intent::Ignore; return (Instance); #endif } @@ -390,8 +433,13 @@ namespace Langulus::Logger /// @return a scoped tab, that will untab when destroyed template LANGULUS(INLINED) ScopedTabs InputTab([[maybe_unused]] T&&...arguments) noexcept { - Input(::std::forward(arguments)...); - return (Instance << Tabs {}); + #ifdef LANGULUS_LOGGER_ENABLE_INPUTS + Input(::std::forward(arguments)...); + return (Instance << Tabs {}); + #else + Instance << Intent::Ignore; + return ScopedTabs {0}; + #endif } /// Write a new-line with network message @@ -400,15 +448,15 @@ namespace Langulus::Logger template LANGULUS(INLINED) decltype(auto) Network([[maybe_unused]] T&&...arguments) noexcept { #ifdef LANGULUS_LOGGER_ENABLE_NETWORKS + Instance << Intent::Network; Instance.NewLine(); - Instance << Command::PopAndPush << Color::Yellow; - if constexpr (sizeof...(arguments) > 0) { - Instance << "NETWORK: "; + if constexpr (sizeof...(arguments) > 0) return (Instance << ... << ::std::forward(arguments)); - } - else return (Instance); + else + return (Instance); #else + Instance << Intent::Ignore; return (Instance); #endif } @@ -418,8 +466,13 @@ namespace Langulus::Logger /// @return a scoped tab, that will untab when destroyed template LANGULUS(INLINED) ScopedTabs NetworkTab([[maybe_unused]] T&&...arguments) noexcept { - Network(::std::forward(arguments)...); - return (Instance << Tabs {}); + #ifdef LANGULUS_LOGGER_ENABLE_NETWORKS + Network(::std::forward(arguments)...); + return (Instance << Tabs {}); + #else + Instance << Intent::Ignore; + return ScopedTabs {0}; + #endif } /// Write a new-line with a message from OS @@ -428,15 +481,15 @@ namespace Langulus::Logger template LANGULUS(INLINED) decltype(auto) OS([[maybe_unused]] T&&...arguments) noexcept { #ifdef LANGULUS_LOGGER_ENABLE_OS + Instance << Intent::OS; Instance.NewLine(); - Instance << Command::PopAndPush << Color::DarkBlue; - if constexpr (sizeof...(arguments) > 0) { - Instance << "OS: "; + if constexpr (sizeof...(arguments) > 0) return (Instance << ... << ::std::forward(arguments)); - } - else return (Instance); + else + return (Instance); #else + Instance << Intent::Ignore; return (Instance); #endif } @@ -446,8 +499,13 @@ namespace Langulus::Logger /// @return a scoped tab, that will untab when destroyed template LANGULUS(INLINED) ScopedTabs OSTab([[maybe_unused]] T&&...arguments) noexcept { - OS(::std::forward(arguments)...); - return (Instance << Tabs {}); + #ifdef LANGULUS_LOGGER_ENABLE_OS + OS(::std::forward(arguments)...); + return (Instance << Tabs {}); + #else + Instance << Intent::Ignore; + return ScopedTabs {0}; + #endif } /// Write a new-line with an input prompt @@ -456,15 +514,15 @@ namespace Langulus::Logger template LANGULUS(INLINED) decltype(auto) Prompt([[maybe_unused]] T&&...arguments) noexcept { #ifdef LANGULUS_LOGGER_ENABLE_PROMPTS + Instance << Intent::Prompt; Instance.NewLine(); - Instance << Command::PopAndPush << Color::Green; - if constexpr (sizeof...(arguments) > 0) { - Instance << "PROMPT: "; + if constexpr (sizeof...(arguments) > 0) return (Instance << ... << ::std::forward(arguments)); - } - else return (Instance); + else + return (Instance); #else + Instance << Intent::Ignore; return (Instance); #endif } @@ -474,8 +532,13 @@ namespace Langulus::Logger /// @return a scoped tab, that will untab when destroyed template LANGULUS(INLINED) ScopedTabs PromptTab([[maybe_unused]] T&&...arguments) noexcept { - Prompt(::std::forward(arguments)...); - return (Instance << Tabs {}); + #ifdef LANGULUS_LOGGER_ENABLE_PROMPTS + Prompt(::std::forward(arguments)...); + return (Instance << Tabs {}); + #else + Instance << Intent::Ignore; + return ScopedTabs {0}; + #endif } } // namespace Langulus::Logger diff --git a/source/TXT.cpp b/source/TXT.cpp index 0f10a84..3c6613c 100644 --- a/source/TXT.cpp +++ b/source/TXT.cpp @@ -42,6 +42,11 @@ void ToTXT::Write(Style) const noexcept { void ToTXT::NewLine() const noexcept { Write("\n"); Write(GetSimpleTime()); + Write("|"); + if (Instance.CurrentIntent != Intent::Ignore) + Write(Instance.IntentStyle[int(Instance.CurrentIntent)].prefix); + else + Write(" "); Write("| "); auto tabs = Instance.GetTabs(); diff --git a/test/TestLogger.cpp b/test/TestLogger.cpp index eaf1bf6..90c4f80 100644 --- a/test/TestLogger.cpp +++ b/test/TestLogger.cpp @@ -61,88 +61,123 @@ SCENARIO("Logging to console", "[logger]") { } WHEN("Calling Logger::Fatal()") { - Logger::Fatal("This should be a fatal error and should be prefixed with FATAL ERROR"); - Logger::Line("This should be a continued fatal error on a new line, without any prefix"); + Logger::Fatal("This should be a fatal error and should be prefixed with |F|"); + Logger::Line("This should be a continued fatal error on a new line, with |F| prefix"); Logger::Append(", and this should be appended"); + auto scope = Logger::Section("This should be a section inside a fatal error"); + Logger::Line("This should be a line inside a section, inside a fatal error"); } WHEN("Calling Logger::Error()") { - Logger::Error("This should be a non-fatal error, and should be prefixed with ERROR"); - Logger::Line("This should be a continued non-fatal error on a new line, without any prefix"); + Logger::Error("This should be a non-fatal error, and should be prefixed with |E|"); + Logger::Line("This should be a continued non-fatal error on a new line, with |E| prefix"); Logger::Append(", and this should be appended"); + auto scope = Logger::Section("This should be a section inside an error"); + Logger::Line("This should be a line inside a section, inside an error"); } WHEN("Calling Logger::Warning()") { - Logger::Warning("This should be a warning, and should be prefixed with WARNING"); - Logger::Line("This should be a continued warning on a new line, without any prefix"); + Logger::Warning("This should be a warning, and should be prefixed with |W|"); + Logger::Line("This should be a continued warning on a new line, with |W| prefix"); Logger::Append(", and this should be appended"); + auto scope = Logger::Section("This should be a section inside a warning"); + Logger::Line("This should be a line inside a section, inside a warning"); } WHEN("Calling Logger::Verbose()") { - Logger::Verbose("This is a verbose info message"); - Logger::Line("This should be a continued verbose on a new line, without any prefix"); + Logger::Verbose("This is a verbose info message, and should be prefixed with |V|"); + Logger::Line("This should be a continued verbose on a new line, with |V| prefix"); Logger::Append(", and this should be appended"); + auto scope = Logger::Section("This should be a section inside a verbose message"); + Logger::Line("This should be a line inside a section, inside a verbose message"); } WHEN("Calling Logger::Info()") { - Logger::Info("This is an info message"); - Logger::Line("This should be a continued info on a new line, without any prefix"); + Logger::Info("This is an info message, and should be prefixed with |I|"); + Logger::Line("This should be a continued info on a new line, with |I| prefix"); Logger::Append(", and this should be appended"); + auto scope = Logger::Section("This should be a section inside an info message"); + Logger::Line("This should be a line inside a section, inside an info message"); } WHEN("Calling Logger::Message()") { - Logger::Message("This is a message directed towards the user"); - Logger::Line("This should be a continued message on a new line, without any prefix"); + Logger::Message("This is a message directed towards the user, and should be prefixed with |M|"); + Logger::Line("This should be a continued message on a new line, with |M| prefix"); Logger::Append(", and this should be appended"); + auto scope = Logger::Section("This should be a section inside a message"); + Logger::Line("This should be a line inside a section, inside a message"); } WHEN("Calling Logger::Special()") { - Logger::Special("This is a special message for a special user, like you"); - Logger::Line("This should be a continued special message on a new line, without any prefix"); + Logger::Special("This is a special message for a special user, like you, and should be prefixed with |S|"); + Logger::Line("This should be a continued special message on a new line, with |S| prefix"); Logger::Append(", and this should be appended"); + auto scope = Logger::Section("This should be a section inside a special message"); + Logger::Line("This should be a line inside a section, inside a special message"); } WHEN("Calling Logger::Flow()") { - Logger::Flow("This is a flow control message"); - Logger::Line("This should be a continued flow on a new line, without any prefix"); + Logger::Flow("This is a flow control message, and should be prefixed with |L|"); + Logger::Line("This should be a continued flow on a new line, with |L| prefix"); Logger::Append(", and this should be appended"); + auto scope = Logger::Section("This should be a section inside a flow message"); + Logger::Line("This should be a line inside a section, inside a flow message"); } WHEN("Calling Logger::Input()") { - Logger::Input("This is an input event message"); - Logger::Line("This should be a continued input on a new line, without any prefix"); + Logger::Input("This is an input event message, and should be prefixed with |N|"); + Logger::Line("This should be a continued input on a new line, with |N| prefix"); Logger::Append(", and this should be appended"); + auto scope = Logger::Section("This should be a section inside an input message"); + Logger::Line("This should be a line inside a section, inside an input message"); } WHEN("Calling Logger::Network()") { - Logger::Network("This is a network message"); - Logger::Line("This should be a continued network on a new line, without any prefix"); + Logger::Network("This is a network message, and should be prefixed with |T|"); + Logger::Line("This should be a continued network on a new line, with |T| prefix"); Logger::Append(", and this should be appended"); + auto scope = Logger::Section("This should be a section inside a network message"); + Logger::Line("This should be a line inside a section, inside a network message"); } WHEN("Calling Logger::OS()") { - Logger::OS("This is an OS event message"); - Logger::Line("This should be a continued OS event on a new line, without any prefix"); + Logger::OS("This is an OS event message, and should be prefixed with |O|"); + Logger::Line("This should be a continued OS event on a new line, with |O| prefix"); Logger::Append(", and this should be appended"); + auto scope = Logger::Section("This should be a section inside an OS message"); + Logger::Line("This should be a line inside a section, inside an OS message"); } WHEN("Calling Logger::Prompt()") { - Logger::Prompt("This is an input prompt, that blocks execution and waits for console input (TODO)"); - Logger::Line("This should be a continued Prompt on a new line, without any prefix"); + Logger::Prompt("This is an input prompt, that blocks execution and waits for console input (TODO), and should be prefixed with |P|"); + Logger::Line("This should be a continued Prompt on a new line, with |P| prefix"); Logger::Append(", and this should be appended"); + auto scope = Logger::Section("This should be a section inside a prompt"); + Logger::Line("This should be a line inside a section, inside a prompt"); } WHEN("Logging numbers, characters and booleans") { - Logger::Special() << "The answer is " << 42 << '!' << " It's " << true << ", I tell ya!"; + Logger::Special() << "#1 The answer is " << 42 << '!' << " It's " << true << ", I tell ya!"; + Logger::Special("#2 The answer is ", 42, '!', " It's ", true, ", I tell ya!"); + } + + WHEN("You shouldn't see these") { + Logger::Line() << "#1 You shouldn't see the following: " << Logger::Intent::Ignore << 42 << '!' << " It's " << true << ", I tell ya!" << Logger::Reset; + Logger::Line("#2 You shouldn't see the following (color should be reset to default intent): ", Logger::Intent::Ignore, 42, '!', " It's ", true, ", I tell ya!"); + auto scope1 = Logger::Section("This section should be invisible, too"); + Logger::Line("#3 You shouldn't see this line AT ALL: ", 42, '!', " It's ", true, ", I tell ya!"); + auto scope2 = Logger::Section("As well as this one"); } WHEN("Pushing and popping styles") { - Logger::Warning("This is a warning, ", + Logger::Warning(Logger::Color::Cyan, "This is actually a warning, ", Logger::Push, Logger::Underline, "but now we underline it, ", Logger::PushRedBgr, "then we even change color, ", Logger::Pop, "but then we return to underlined warning, ", Logger::Pop, "and finally, back to warning, ", - Logger::Pop, "but if we actually pop once more, we return to default Logger style\n\n"); + Logger::Pop, "but if we actually pop once more, we return to the original intent", + Logger::Pop, ", and any subsequent pop shouldn't change anything"); + Logger::Line("^ just checking the above statement\n\n"); } } }