feat(miscellaneous): add console operation functions
This commit is contained in:
parent
88e330336a
commit
8d3fa1ac98
462
Redcraft.Utility/Source/Private/Miscellaneous/Console.cpp
Normal file
462
Redcraft.Utility/Source/Private/Miscellaneous/Console.cpp
Normal file
@ -0,0 +1,462 @@
|
|||||||
|
#include "Miscellaneous/Console.h"
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
#if PLATFORM_WINDOWS
|
||||||
|
# undef TEXT
|
||||||
|
# include <windows.h>
|
||||||
|
#elif PLATFORM_LINUX
|
||||||
|
# include <sys/ioctl.h>
|
||||||
|
# include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
NAMESPACE_REDCRAFT_BEGIN
|
||||||
|
NAMESPACE_MODULE_BEGIN(Redcraft)
|
||||||
|
NAMESPACE_MODULE_BEGIN(Utility)
|
||||||
|
|
||||||
|
#if PLATFORM_WINDOWS
|
||||||
|
|
||||||
|
NODISCARD bool InitANSIConsole()
|
||||||
|
{
|
||||||
|
static bool bResult = []
|
||||||
|
{
|
||||||
|
HANDLE Console = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
|
||||||
|
if (Console == INVALID_HANDLE_VALUE) return false;
|
||||||
|
|
||||||
|
DWORD ConsoleMode = 0;
|
||||||
|
|
||||||
|
if (!GetConsoleMode(Console, &ConsoleMode)) return false;
|
||||||
|
|
||||||
|
ConsoleMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||||
|
|
||||||
|
if (!SetConsoleMode(Console, ConsoleMode)) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
();
|
||||||
|
|
||||||
|
return bResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
EColor GForegroundColor = EColor::Default;
|
||||||
|
EColor GBackgroundColor = EColor::Default;
|
||||||
|
|
||||||
|
EColor GetForegroundColor()
|
||||||
|
{
|
||||||
|
# if PLATFORM_WINDOWS
|
||||||
|
{
|
||||||
|
if (InitANSIConsole()) return GForegroundColor;
|
||||||
|
|
||||||
|
const HANDLE Console = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
|
||||||
|
if (Console == INVALID_HANDLE_VALUE) return EColor::Default;
|
||||||
|
|
||||||
|
CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
|
||||||
|
|
||||||
|
if (!GetConsoleScreenBufferInfo(Console, &ConsoleInfo)) return EColor::Default;
|
||||||
|
|
||||||
|
const WORD Color = ConsoleInfo.wAttributes;
|
||||||
|
|
||||||
|
EColor Result = EColor::Black;
|
||||||
|
|
||||||
|
if (Color & FOREGROUND_RED) Result |= EColor::Red;
|
||||||
|
if (Color & FOREGROUND_GREEN) Result |= EColor::Green;
|
||||||
|
if (Color & FOREGROUND_BLUE) Result |= EColor::Blue;
|
||||||
|
if (Color & FOREGROUND_INTENSITY) Result |= EColor::Intensity;
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
return GForegroundColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
EColor GetBackgroundColor()
|
||||||
|
{
|
||||||
|
# if PLATFORM_WINDOWS
|
||||||
|
{
|
||||||
|
if (InitANSIConsole()) return GBackgroundColor;
|
||||||
|
|
||||||
|
const HANDLE Console = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
|
||||||
|
if (Console == INVALID_HANDLE_VALUE) return EColor::Default;
|
||||||
|
|
||||||
|
CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
|
||||||
|
|
||||||
|
if (!GetConsoleScreenBufferInfo(Console, &ConsoleInfo)) return EColor::Default;
|
||||||
|
|
||||||
|
const WORD Color = ConsoleInfo.wAttributes;
|
||||||
|
|
||||||
|
EColor Result = EColor::Black;
|
||||||
|
|
||||||
|
if (Color & BACKGROUND_RED) Result |= EColor::Red;
|
||||||
|
if (Color & BACKGROUND_GREEN) Result |= EColor::Green;
|
||||||
|
if (Color & BACKGROUND_BLUE) Result |= EColor::Blue;
|
||||||
|
if (Color & BACKGROUND_INTENSITY) Result |= EColor::Intensity;
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
return GBackgroundColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
EColor SetForegroundColor(EColor InColor)
|
||||||
|
{
|
||||||
|
if (IsOutputRedirected()) return GetForegroundColor();
|
||||||
|
|
||||||
|
# if PLATFORM_WINDOWS
|
||||||
|
{
|
||||||
|
if (!InitANSIConsole())
|
||||||
|
{
|
||||||
|
const HANDLE Console = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
|
||||||
|
if (Console == INVALID_HANDLE_VALUE) return GetForegroundColor();
|
||||||
|
|
||||||
|
CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
|
||||||
|
|
||||||
|
if (!GetConsoleScreenBufferInfo(Console, &ConsoleInfo)) return GetForegroundColor();
|
||||||
|
|
||||||
|
WORD Color = ConsoleInfo.wAttributes & ~(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
|
||||||
|
|
||||||
|
if (InColor == EColor::Default) InColor = EColor::White;
|
||||||
|
|
||||||
|
if (!!(InColor & EColor::Red)) Color |= FOREGROUND_RED;
|
||||||
|
if (!!(InColor & EColor::Green)) Color |= FOREGROUND_GREEN;
|
||||||
|
if (!!(InColor & EColor::Blue)) Color |= FOREGROUND_BLUE;
|
||||||
|
if (!!(InColor & EColor::Intensity)) Color |= FOREGROUND_INTENSITY;
|
||||||
|
|
||||||
|
if (!SetConsoleTextAttribute(Console, Color)) return GetForegroundColor();
|
||||||
|
|
||||||
|
return InColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# if PLATFORM_WINDOWS || PLATFORM_LINUX
|
||||||
|
{
|
||||||
|
int Result;
|
||||||
|
|
||||||
|
switch (InColor)
|
||||||
|
{
|
||||||
|
case EColor::Black: Result = std::fputs("\033[30m", stdout); break;
|
||||||
|
case EColor::Red: Result = std::fputs("\033[31m", stdout); break;
|
||||||
|
case EColor::Green: Result = std::fputs("\033[32m", stdout); break;
|
||||||
|
case EColor::Yellow: Result = std::fputs("\033[33m", stdout); break;
|
||||||
|
case EColor::Blue: Result = std::fputs("\033[34m", stdout); break;
|
||||||
|
case EColor::Magenta: Result = std::fputs("\033[35m", stdout); break;
|
||||||
|
case EColor::Cyan: Result = std::fputs("\033[36m", stdout); break;
|
||||||
|
case EColor::White: Result = std::fputs("\033[37m", stdout); break;
|
||||||
|
case EColor::BrightBlack: Result = std::fputs("\033[90m", stdout); break;
|
||||||
|
case EColor::BrightRed: Result = std::fputs("\033[91m", stdout); break;
|
||||||
|
case EColor::BrightGreen: Result = std::fputs("\033[92m", stdout); break;
|
||||||
|
case EColor::BrightYellow: Result = std::fputs("\033[93m", stdout); break;
|
||||||
|
case EColor::BrightBlue: Result = std::fputs("\033[94m", stdout); break;
|
||||||
|
case EColor::BrightMagenta: Result = std::fputs("\033[95m", stdout); break;
|
||||||
|
case EColor::BrightCyan: Result = std::fputs("\033[96m", stdout); break;
|
||||||
|
case EColor::BrightWhite: Result = std::fputs("\033[97m", stdout); break;
|
||||||
|
default: Result = std::fputs("\033[39m", stdout); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Result == EOF) return GetForegroundColor();
|
||||||
|
|
||||||
|
return GForegroundColor = InColor;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
return GetForegroundColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
EColor SetBackgroundColor(EColor InColor)
|
||||||
|
{
|
||||||
|
if (IsOutputRedirected()) return GetBackgroundColor();
|
||||||
|
|
||||||
|
# if PLATFORM_WINDOWS
|
||||||
|
{
|
||||||
|
if (!InitANSIConsole())
|
||||||
|
{
|
||||||
|
const HANDLE Console = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
|
||||||
|
if (Console == INVALID_HANDLE_VALUE) return GetBackgroundColor();
|
||||||
|
|
||||||
|
CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
|
||||||
|
|
||||||
|
if (!GetConsoleScreenBufferInfo(Console, &ConsoleInfo)) return GetBackgroundColor();
|
||||||
|
|
||||||
|
WORD Color = ConsoleInfo.wAttributes & ~(BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY);
|
||||||
|
|
||||||
|
if (InColor == EColor::Default) InColor = EColor::Black;
|
||||||
|
|
||||||
|
if (!!(InColor & EColor::Red)) Color |= BACKGROUND_RED;
|
||||||
|
if (!!(InColor & EColor::Green)) Color |= BACKGROUND_GREEN;
|
||||||
|
if (!!(InColor & EColor::Blue)) Color |= BACKGROUND_BLUE;
|
||||||
|
if (!!(InColor & EColor::Intensity)) Color |= BACKGROUND_INTENSITY;
|
||||||
|
|
||||||
|
if (!SetConsoleTextAttribute(Console, Color)) return GetBackgroundColor();
|
||||||
|
|
||||||
|
return InColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# if PLATFORM_WINDOWS || PLATFORM_LINUX
|
||||||
|
{
|
||||||
|
int Result;
|
||||||
|
|
||||||
|
switch (InColor)
|
||||||
|
{
|
||||||
|
case EColor::Black: Result = std::fputs("\033[40m", stdout); break;
|
||||||
|
case EColor::Red: Result = std::fputs("\033[41m", stdout); break;
|
||||||
|
case EColor::Green: Result = std::fputs("\033[42m", stdout); break;
|
||||||
|
case EColor::Yellow: Result = std::fputs("\033[43m", stdout); break;
|
||||||
|
case EColor::Blue: Result = std::fputs("\033[44m", stdout); break;
|
||||||
|
case EColor::Magenta: Result = std::fputs("\033[45m", stdout); break;
|
||||||
|
case EColor::Cyan: Result = std::fputs("\033[46m", stdout); break;
|
||||||
|
case EColor::White: Result = std::fputs("\033[47m", stdout); break;
|
||||||
|
case EColor::BrightBlack: Result = std::fputs("\033[100m", stdout); break;
|
||||||
|
case EColor::BrightRed: Result = std::fputs("\033[101m", stdout); break;
|
||||||
|
case EColor::BrightGreen: Result = std::fputs("\033[102m", stdout); break;
|
||||||
|
case EColor::BrightYellow: Result = std::fputs("\033[103m", stdout); break;
|
||||||
|
case EColor::BrightBlue: Result = std::fputs("\033[104m", stdout); break;
|
||||||
|
case EColor::BrightMagenta: Result = std::fputs("\033[105m", stdout); break;
|
||||||
|
case EColor::BrightCyan: Result = std::fputs("\033[106m", stdout); break;
|
||||||
|
case EColor::BrightWhite: Result = std::fputs("\033[107m", stdout); break;
|
||||||
|
default: Result = std::fputs("\033[49m", stdout); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Result == EOF) return GetBackgroundColor();
|
||||||
|
|
||||||
|
return GBackgroundColor = InColor;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
return GetBackgroundColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint GetWindowWidth()
|
||||||
|
{
|
||||||
|
# if PLATFORM_WINDOWS
|
||||||
|
{
|
||||||
|
const HANDLE Console = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
|
||||||
|
if (Console == INVALID_HANDLE_VALUE) return static_cast<uint>(-1);
|
||||||
|
|
||||||
|
CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
|
||||||
|
|
||||||
|
if (!GetConsoleScreenBufferInfo(Console, &ConsoleInfo)) return static_cast<uint>(-1);
|
||||||
|
|
||||||
|
return static_cast<uint>(ConsoleInfo.srWindow.Right - ConsoleInfo.srWindow.Left + 1);
|
||||||
|
}
|
||||||
|
# elif PLATFORM_LINUX
|
||||||
|
{
|
||||||
|
winsize Size;
|
||||||
|
|
||||||
|
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &Size) == -1) return static_cast<uint>(-1);
|
||||||
|
|
||||||
|
return static_cast<uint>(Size.ws_col);
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
return static_cast<uint>(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint GetWindowHeight()
|
||||||
|
{
|
||||||
|
# if PLATFORM_WINDOWS
|
||||||
|
{
|
||||||
|
const HANDLE Console = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
|
||||||
|
if (Console == INVALID_HANDLE_VALUE) return static_cast<uint>(-1);
|
||||||
|
|
||||||
|
CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
|
||||||
|
|
||||||
|
if (!GetConsoleScreenBufferInfo(Console, &ConsoleInfo)) return static_cast<uint>(-1);
|
||||||
|
|
||||||
|
return static_cast<uint>(ConsoleInfo.srWindow.Bottom - ConsoleInfo.srWindow.Top + 1);
|
||||||
|
}
|
||||||
|
# elif PLATFORM_LINUX
|
||||||
|
{
|
||||||
|
winsize Size;
|
||||||
|
|
||||||
|
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &Size) == -1) return static_cast<uint>(-1);
|
||||||
|
|
||||||
|
return static_cast<uint>(Size.ws_row);
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
return static_cast<uint>(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsInputRedirected()
|
||||||
|
{
|
||||||
|
# if PLATFORM_WINDOWS
|
||||||
|
{
|
||||||
|
const HANDLE StandardInput = GetStdHandle(STD_INPUT_HANDLE);
|
||||||
|
|
||||||
|
if (StandardInput == INVALID_HANDLE_VALUE) return false;
|
||||||
|
|
||||||
|
DWORD FileType = GetFileType(StandardInput);
|
||||||
|
|
||||||
|
return FileType != FILE_TYPE_CHAR;
|
||||||
|
}
|
||||||
|
# elif PLATFORM_LINUX
|
||||||
|
{
|
||||||
|
return isatty(fileno(stdin)) == 0;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsOutputRedirected()
|
||||||
|
{
|
||||||
|
# if PLATFORM_WINDOWS
|
||||||
|
{
|
||||||
|
const HANDLE StandardOutput = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
|
||||||
|
if (StandardOutput == INVALID_HANDLE_VALUE) return false;
|
||||||
|
|
||||||
|
DWORD FileType = GetFileType(StandardOutput);
|
||||||
|
|
||||||
|
return FileType != FILE_TYPE_CHAR;
|
||||||
|
}
|
||||||
|
# elif PLATFORM_LINUX
|
||||||
|
{
|
||||||
|
return isatty(fileno(stdout)) == 0;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsErrorRedirected()
|
||||||
|
{
|
||||||
|
# if PLATFORM_WINDOWS
|
||||||
|
{
|
||||||
|
const HANDLE StandardError = GetStdHandle(STD_ERROR_HANDLE);
|
||||||
|
|
||||||
|
if (StandardError == INVALID_HANDLE_VALUE) return false;
|
||||||
|
|
||||||
|
DWORD FileType = GetFileType(StandardError);
|
||||||
|
|
||||||
|
return FileType != FILE_TYPE_CHAR;
|
||||||
|
}
|
||||||
|
# elif PLATFORM_LINUX
|
||||||
|
{
|
||||||
|
return isatty(fileno(stderr)) == 0;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Clear()
|
||||||
|
{
|
||||||
|
if (IsOutputRedirected()) return;
|
||||||
|
|
||||||
|
# if PLATFORM_WINDOWS
|
||||||
|
{
|
||||||
|
std::system("cls");
|
||||||
|
}
|
||||||
|
# elif PLATFORM_LINUX
|
||||||
|
{
|
||||||
|
Ignore = std::fputs("\033[2J\033[1;1H", stdout);
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
char Input(bool bEcho)
|
||||||
|
{
|
||||||
|
if (bEcho || IsOutputRedirected())
|
||||||
|
{
|
||||||
|
const int Result = std::getchar();
|
||||||
|
|
||||||
|
if (Result == EOF) return static_cast<char>(-1);
|
||||||
|
|
||||||
|
return static_cast<char>(Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
# if PLATFORM_WINDOWS
|
||||||
|
{
|
||||||
|
const HANDLE Console = GetStdHandle(STD_INPUT_HANDLE);
|
||||||
|
|
||||||
|
if (Console == INVALID_HANDLE_VALUE) return static_cast<char>(-1);
|
||||||
|
|
||||||
|
DWORD ConsoleMode = 0;
|
||||||
|
|
||||||
|
GetConsoleMode(Console, &ConsoleMode);
|
||||||
|
|
||||||
|
SetConsoleMode(Console, ConsoleMode & ~ENABLE_ECHO_INPUT);
|
||||||
|
|
||||||
|
const char Result = Input();
|
||||||
|
|
||||||
|
SetConsoleMode(Console, ConsoleMode);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
# elif PLATFORM_LINUX
|
||||||
|
{ }
|
||||||
|
# endif
|
||||||
|
|
||||||
|
return static_cast<char>(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
FString InputLn(bool bEcho)
|
||||||
|
{
|
||||||
|
if (bEcho || IsOutputRedirected())
|
||||||
|
{
|
||||||
|
FString Result;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
const int Char = std::getchar();
|
||||||
|
|
||||||
|
if (Char == EOF || Char == '\n') break;
|
||||||
|
|
||||||
|
Result.PushBack(static_cast<char>(Char));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
# if PLATFORM_WINDOWS
|
||||||
|
{
|
||||||
|
const HANDLE Console = GetStdHandle(STD_INPUT_HANDLE);
|
||||||
|
|
||||||
|
if (Console == INVALID_HANDLE_VALUE) return "";
|
||||||
|
|
||||||
|
DWORD ConsoleMode = 0;
|
||||||
|
|
||||||
|
GetConsoleMode(Console, &ConsoleMode);
|
||||||
|
|
||||||
|
SetConsoleMode(Console, ConsoleMode & ~ENABLE_ECHO_INPUT);
|
||||||
|
|
||||||
|
const FString Result = InputLn();
|
||||||
|
|
||||||
|
SetConsoleMode(Console, ConsoleMode);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
# elif PLATFORM_LINUX
|
||||||
|
{ }
|
||||||
|
# endif
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Print(char Char)
|
||||||
|
{
|
||||||
|
return std::putchar(Char) != EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Error(char Char)
|
||||||
|
{
|
||||||
|
return std::fputc(Char, stderr) != EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
NAMESPACE_MODULE_END(Utility)
|
||||||
|
NAMESPACE_MODULE_END(Redcraft)
|
||||||
|
NAMESPACE_REDCRAFT_END
|
217
Redcraft.Utility/Source/Public/Miscellaneous/Console.h
Normal file
217
Redcraft.Utility/Source/Public/Miscellaneous/Console.h
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreTypes.h"
|
||||||
|
#include "TypeTraits/TypeTraits.h"
|
||||||
|
#include "Templates/Utility.h"
|
||||||
|
#include "Iterators/Utility.h"
|
||||||
|
#include "Strings/Formatting.h"
|
||||||
|
#include "Strings/StringView.h"
|
||||||
|
#include "Strings/String.h"
|
||||||
|
#include "Miscellaneous/BitwiseEnum.h"
|
||||||
|
|
||||||
|
NAMESPACE_REDCRAFT_BEGIN
|
||||||
|
NAMESPACE_MODULE_BEGIN(Redcraft)
|
||||||
|
NAMESPACE_MODULE_BEGIN(Utility)
|
||||||
|
|
||||||
|
/** An enumeration that defines the color of the console. */
|
||||||
|
enum class EColor : uint8
|
||||||
|
{
|
||||||
|
Default = 0xFF,
|
||||||
|
|
||||||
|
Black = 0b0000,
|
||||||
|
Red = 0b0001,
|
||||||
|
Green = 0b0010,
|
||||||
|
Blue = 0b0100,
|
||||||
|
Intensity = 0b1000,
|
||||||
|
|
||||||
|
Cyan = Green | Blue,
|
||||||
|
Magenta = Blue | Red,
|
||||||
|
Yellow = Red | Green,
|
||||||
|
|
||||||
|
White = Red | Green | Blue,
|
||||||
|
|
||||||
|
BrightBlack = Intensity | Black,
|
||||||
|
BrightRed = Intensity | Red,
|
||||||
|
BrightGreen = Intensity | Green,
|
||||||
|
BrightBlue = Intensity | Blue,
|
||||||
|
BrightYellow = Intensity | Yellow,
|
||||||
|
BrightMagenta = Intensity | Magenta,
|
||||||
|
BrightCyan = Intensity | Cyan,
|
||||||
|
BrightWhite = Intensity | White
|
||||||
|
};
|
||||||
|
|
||||||
|
ENABLE_ENUM_CLASS_BITWISE_OPERATIONS(EColor)
|
||||||
|
|
||||||
|
/** @return The color of the console. */
|
||||||
|
NODISCARD REDCRAFTUTILITY_API EColor GetForegroundColor();
|
||||||
|
NODISCARD REDCRAFTUTILITY_API EColor GetBackgroundColor();
|
||||||
|
|
||||||
|
/** Set the color of the console. Returns the color that was successfully set. */
|
||||||
|
REDCRAFTUTILITY_API EColor SetForegroundColor(EColor InColor);
|
||||||
|
REDCRAFTUTILITY_API EColor SetBackgroundColor(EColor InColor);
|
||||||
|
|
||||||
|
/** @return The size of the console window. */
|
||||||
|
NODISCARD REDCRAFTUTILITY_API uint GetWindowWidth();
|
||||||
|
NODISCARD REDCRAFTUTILITY_API uint GetWindowHeight();
|
||||||
|
|
||||||
|
/** @return true if the standard stream is redirected. */
|
||||||
|
NODISCARD REDCRAFTUTILITY_API bool IsInputRedirected();
|
||||||
|
NODISCARD REDCRAFTUTILITY_API bool IsOutputRedirected();
|
||||||
|
NODISCARD REDCRAFTUTILITY_API bool IsErrorRedirected();
|
||||||
|
|
||||||
|
/** Clear the console screen. */
|
||||||
|
REDCRAFTUTILITY_API void Clear();
|
||||||
|
|
||||||
|
/** @return The input character from the standard input. */
|
||||||
|
NODISCARD REDCRAFTUTILITY_API char Input(bool bEcho = true);
|
||||||
|
|
||||||
|
/** @return The input line from the standard input. */
|
||||||
|
NODISCARD REDCRAFTUTILITY_API FString InputLn(bool bEcho = true);
|
||||||
|
|
||||||
|
/** Print the character to the standard output. */
|
||||||
|
REDCRAFTUTILITY_API bool Print(char Char);
|
||||||
|
|
||||||
|
/** Print the formatted string to the standard output. */
|
||||||
|
template <CFormattable... Ts>
|
||||||
|
FORCEINLINE bool Print(FStringView Fmt, Ts&&... Args)
|
||||||
|
{
|
||||||
|
struct FStandardOutputIterator
|
||||||
|
{
|
||||||
|
FORCEINLINE constexpr FStandardOutputIterator& operator=(char Char)
|
||||||
|
{
|
||||||
|
bError |= !Print(Char);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE constexpr bool operator==(FDefaultSentinel) const { return bError; }
|
||||||
|
|
||||||
|
FORCEINLINE constexpr FStandardOutputIterator& operator*() { return *this; }
|
||||||
|
FORCEINLINE constexpr FStandardOutputIterator& operator++() { return *this; }
|
||||||
|
FORCEINLINE constexpr FStandardOutputIterator& operator++(int) { return *this; }
|
||||||
|
|
||||||
|
bool bError = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(COutputIterator<FStandardOutputIterator, char>);
|
||||||
|
|
||||||
|
FStandardOutputIterator Iter;
|
||||||
|
|
||||||
|
auto Range = Ranges::View(Iter, DefaultSentinel);
|
||||||
|
|
||||||
|
Iter = Algorithms::Format(Range, Fmt, Forward<Ts>(Args)...);
|
||||||
|
|
||||||
|
return Iter != DefaultSentinel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Print the value to the standard output. */
|
||||||
|
template <CFormattable T>
|
||||||
|
FORCEINLINE bool Print(T&& Value)
|
||||||
|
{
|
||||||
|
if constexpr (CSameAs<TRemoveCVRef<T>, char>)
|
||||||
|
{
|
||||||
|
return Print(static_cast<char>(Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
else if constexpr (CConvertibleTo<T, FStringView>)
|
||||||
|
{
|
||||||
|
return Print(static_cast<FStringView>(Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
else return Print(TEXT("{0}"), Forward<T>(Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Print the newline character to the standard output. */
|
||||||
|
FORCEINLINE bool PrintLn()
|
||||||
|
{
|
||||||
|
return Print(TEXT("\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Print the string to the standard output and append the newline character. */
|
||||||
|
template <CFormattable... Ts>
|
||||||
|
FORCEINLINE bool PrintLn(FStringView Fmt, Ts&&... Args)
|
||||||
|
{
|
||||||
|
return Print(Fmt, Forward<Ts>(Args)...) && Print(TEXT("\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Print the value to the standard output and append the newline character. */
|
||||||
|
template <CFormattable T>
|
||||||
|
FORCEINLINE bool PrintLn(T&& Value)
|
||||||
|
{
|
||||||
|
return Print(Forward<T>(Value)) && Print(TEXT("\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Print the character to the standard error. */
|
||||||
|
REDCRAFTUTILITY_API bool Error(char Char);
|
||||||
|
|
||||||
|
/** Print the formatted string to the standard error. */
|
||||||
|
template <CFormattable... Ts>
|
||||||
|
FORCEINLINE bool Error(FStringView Fmt, Ts&&... Args)
|
||||||
|
{
|
||||||
|
struct FStandardOutputIterator
|
||||||
|
{
|
||||||
|
FORCEINLINE constexpr FStandardOutputIterator& operator=(char Char)
|
||||||
|
{
|
||||||
|
bError |= !Error(Char);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE constexpr bool operator==(FDefaultSentinel) const { return bError; }
|
||||||
|
|
||||||
|
FORCEINLINE constexpr FStandardOutputIterator& operator*() { return *this; }
|
||||||
|
FORCEINLINE constexpr FStandardOutputIterator& operator++() { return *this; }
|
||||||
|
FORCEINLINE constexpr FStandardOutputIterator& operator++(int) { return *this; }
|
||||||
|
|
||||||
|
bool bError = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(COutputIterator<FStandardOutputIterator, char>);
|
||||||
|
|
||||||
|
FStandardOutputIterator Iter;
|
||||||
|
|
||||||
|
auto Range = Ranges::View(Iter, DefaultSentinel);
|
||||||
|
|
||||||
|
Iter = Algorithms::Format(Range, Fmt, Forward<Ts>(Args)...);
|
||||||
|
|
||||||
|
return Iter != DefaultSentinel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Print the value to the standard error. */
|
||||||
|
template <CFormattable T>
|
||||||
|
FORCEINLINE bool Error(T&& Value)
|
||||||
|
{
|
||||||
|
if constexpr (CSameAs<TRemoveCVRef<T>, char>)
|
||||||
|
{
|
||||||
|
return Error(static_cast<char>(Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
else if constexpr (CConvertibleTo<T, FStringView>)
|
||||||
|
{
|
||||||
|
return Error(static_cast<FStringView>(Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
else return Error(TEXT("{0}"), Forward<T>(Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Print the newline character to the standard error. */
|
||||||
|
FORCEINLINE bool ErrorLn()
|
||||||
|
{
|
||||||
|
return Error(TEXT("\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Print the string to the standard error and append the newline character. */
|
||||||
|
template <CFormattable... Ts>
|
||||||
|
FORCEINLINE bool ErrorLn(FStringView Fmt, Ts&&... Args)
|
||||||
|
{
|
||||||
|
return Error(Fmt, Forward<Ts>(Args)...) && Error(TEXT("\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Print the value to the standard error and append the newline character. */
|
||||||
|
template <CFormattable T>
|
||||||
|
FORCEINLINE bool ErrorLn(T&& Value)
|
||||||
|
{
|
||||||
|
return Error(Forward<T>(Value)) && Error(TEXT("\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
NAMESPACE_MODULE_END(Utility)
|
||||||
|
NAMESPACE_MODULE_END(Redcraft)
|
||||||
|
NAMESPACE_REDCRAFT_END
|
Loading…
x
Reference in New Issue
Block a user