feat: update console output method

- remove the macros disable the warning and error of std functions in MSVC because YYCC has disable them in header.
- update console input output functions. provide CSharp-like interface for UTF8 console input output.
	- console output function is done by WriteConsoleW and WriteFile.
	- console input function still work in progress.
- rename console ASCII color macros
- add console ASCII color test.
- remove EnableUTF8Console because no longer needed.
- add a bunch of annotation to describe YYCC UTF8 console strategy.
- add UNICODE macro in CMakeLists.txt to order CMake generate Visual Studio solution with UNICODE charset enabled, not MBCS.
This commit is contained in:
2024-06-09 21:34:28 +08:00
parent 019034a9c2
commit 1e990b74ae
5 changed files with 187 additions and 87 deletions

View File

@ -7,63 +7,92 @@
namespace YYCC::ConsoleHelper {
#define YYCC_TERMCOLHDR_BLACK "\033[30m"
#define YYCC_TERMCOLHDR_RED "\033[31m"
#define YYCC_TERMCOLHDR_GREEN "\033[32m"
#define YYCC_TERMCOLHDR_YELLOW "\033[33m"
#define YYCC_TERMCOLHDR_BLUE "\033[34m"
#define YYCC_TERMCOLHDR_MAGENTA "\033[35m"
#define YYCC_TERMCOLHDR_CYAN "\033[36m"
#define YYCC_TERMCOLHDR_WHITE "\033[37m"
#define YYCC_COLORHDR_BLACK "\033[30m"
#define YYCC_COLORHDR_RED "\033[31m"
#define YYCC_COLORHDR_GREEN "\033[32m"
#define YYCC_COLORHDR_YELLOW "\033[33m"
#define YYCC_COLORHDR_BLUE "\033[34m"
#define YYCC_COLORHDR_MAGENTA "\033[35m"
#define YYCC_COLORHDR_CYAN "\033[36m"
#define YYCC_COLORHDR_WHITE "\033[37m"
#define YYCC_TERMCOLHDR_LIGHT_BLACK "\033[90m"
#define YYCC_TERMCOLHDR_LIGHT_RED "\033[91m"
#define YYCC_TERMCOLHDR_LIGHT_GREEN "\033[92m"
#define YYCC_TERMCOLHDR_LIGHT_YELLOW "\033[93m"
#define YYCC_TERMCOLHDR_LIGHT_BLUE "\033[94m"
#define YYCC_TERMCOLHDR_LIGHT_MAGENTA "\033[95m"
#define YYCC_TERMCOLHDR_LIGHT_CYAN "\033[96m"
#define YYCC_TERMCOLHDR_LIGHT_WHITE "\033[97m"
#define YYCC_COLORHDR_LIGHT_BLACK "\033[90m"
#define YYCC_COLORHDR_LIGHT_RED "\033[91m"
#define YYCC_COLORHDR_LIGHT_GREEN "\033[92m"
#define YYCC_COLORHDR_LIGHT_YELLOW "\033[93m"
#define YYCC_COLORHDR_LIGHT_BLUE "\033[94m"
#define YYCC_COLORHDR_LIGHT_MAGENTA "\033[95m"
#define YYCC_COLORHDR_LIGHT_CYAN "\033[96m"
#define YYCC_COLORHDR_LIGHT_WHITE "\033[97m"
#define YYCC_TERMCOLTAIL "\033[0m"
#define YYCC_COLORTAIL "\033[0m"
#define YYCC_TERMCOL_BLACK(T) "\033[30m" T "\033[0m"
#define YYCC_TERMCOL_RED(T) "\033[31m" T "\033[0m"
#define YYCC_TERMCOL_GREEN(T) "\033[32m" T "\033[0m"
#define YYCC_TERMCOL_YELLOW(T) "\033[33m" T "\033[0m"
#define YYCC_TERMCOL_BLUE(T) "\033[34m" T "\033[0m"
#define YYCC_TERMCOL_MAGENTA(T) "\033[35m" T "\033[0m"
#define YYCC_TERMCOL_CYAN(T) "\033[36m" T "\033[0m"
#define YYCC_TERMCOL_WHITE(T) "\033[37m" T "\033[0m"
#define YYCC_COLOR_BLACK(T) "\033[30m" T "\033[0m"
#define YYCC_COLOR_RED(T) "\033[31m" T "\033[0m"
#define YYCC_COLOR_GREEN(T) "\033[32m" T "\033[0m"
#define YYCC_COLOR_YELLOW(T) "\033[33m" T "\033[0m"
#define YYCC_COLOR_BLUE(T) "\033[34m" T "\033[0m"
#define YYCC_COLOR_MAGENTA(T) "\033[35m" T "\033[0m"
#define YYCC_COLOR_CYAN(T) "\033[36m" T "\033[0m"
#define YYCC_COLOR_WHITE(T) "\033[37m" T "\033[0m"
#define YYCC_TERMCOL_LIGHT_BLACK(T) "\033[90m" T "\033[0m"
#define YYCC_TERMCOL_LIGHT_RED(T) "\033[91m" T "\033[0m"
#define YYCC_TERMCOL_LIGHT_GREEN(T) "\033[92m" T "\033[0m"
#define YYCC_TERMCOL_LIGHT_YELLOW(T) "\033[93m" T "\033[0m"
#define YYCC_TERMCOL_LIGHT_BLUE(T) "\033[94m" T "\033[0m"
#define YYCC_TERMCOL_LIGHT_MAGENTA(T) "\033[95m" T "\033[0m"
#define YYCC_TERMCOL_LIGHT_CYAN(T) "\033[96m" T "\033[0m"
#define YYCC_TERMCOL_LIGHT_WHITE(T) "\033[97m" T "\033[0m"
#define YYCC_COLOR_LIGHT_BLACK(T) "\033[90m" T "\033[0m"
#define YYCC_COLOR_LIGHT_RED(T) "\033[91m" T "\033[0m"
#define YYCC_COLOR_LIGHT_GREEN(T) "\033[92m" T "\033[0m"
#define YYCC_COLOR_LIGHT_YELLOW(T) "\033[93m" T "\033[0m"
#define YYCC_COLOR_LIGHT_BLUE(T) "\033[94m" T "\033[0m"
#define YYCC_COLOR_LIGHT_MAGENTA(T) "\033[95m" T "\033[0m"
#define YYCC_COLOR_LIGHT_CYAN(T) "\033[96m" T "\033[0m"
#define YYCC_COLOR_LIGHT_WHITE(T) "\033[97m" T "\033[0m"
/**
* @brief Try letting terminal support ASCII color schema.
* @param fs[in] The stream to be set.
* @return true if success, otherwise false.
*/
bool EnsureTerminalColor(FILE* fs);
/**
* @brief Try setting terminal to UTF8 encoding.
* @param fs[in] The stream to be set.
* @return true if success, otherwise false.
* @remarks If you enable UTF8 for a stream, you must use stream functions provided in this namespace to operate that stream,
* because after UTF8 modification, some old standard functions are not work and it may takes a little bit performance reduction.
*/
bool EnsureTerminalUTF8(FILE* fs);
bool EnableColorfulConsole(FILE* fs);
bool FGets(std::string& u8_buf, FILE* stream);
void FPuts(const char* u8_buf, FILE* stream);
void FPrintf(FILE* stream, const char* u8_fmt, ...);
/*
Reference:
* https://stackoverflow.com/questions/45575863/how-to-print-utf-8-strings-to-stdcout-on-windows
* https://stackoverflow.com/questions/69830460/reading-utf-8-input
There is 3 way to make Windows console enable UTF8 mode.
First one is calling SetConsoleCP and SetConsoleOutputCP.
The side effect of this is std::cin and std::cout is broken,
however there is a patch for this issue.
Second one is calling _set_mode with _O_U8TEXT or _O_U16TEXT to enable Unicode mode for Windows console.
This also have side effect which is stronger than first one.
All puts family functions (ASCII-based output functions) will throw assertion exception.
You only can use putws family functions (wide-char-based output functions).
However these functions can not be used without calling _set_mode in Windows design.
There still is another method, using WriteConsoleW directly visiting console.
This function family can output correct string without calling any extra functions!
This method is what we adopted.
*/
/**
* @brief
* @return
*/
std::string ReadLine();
/**
* @brief
* @param u8_fmt The format, or a simple string (format related chars still need escape).
* @param ...[in] The parameter for formatter.
*/
void Write(const char* u8_fmt, ...);
/**
* @brief
* @param u8_fmt
* @param
*/
void WriteLine(const char* u8_fmt, ...);
}
#endif