From aa28dd481bf7491609ca07a84b0ff6646001ee64 Mon Sep 17 00:00:00 2001 From: Abdelrahman Said Date: Sun, 9 Jun 2024 22:30:21 +0100 Subject: [PATCH] Platform abstraction for terminal colour --- src/termcolour/termcolour.c | 101 ++++++++++++++++++++++++++++++++++++ src/termcolour/termcolour.h | 86 ++++++++++++++++-------------- src/tester/tester.c | 25 +++++---- 3 files changed, 164 insertions(+), 48 deletions(-) create mode 100644 src/termcolour/termcolour.c diff --git a/src/termcolour/termcolour.c b/src/termcolour/termcolour.c new file mode 100644 index 0000000..6ed6e28 --- /dev/null +++ b/src/termcolour/termcolour.c @@ -0,0 +1,101 @@ +#include "termcolour.h" +#include "aliases.h" +#include "platform.h" +#include + +internal void print_coloured_text(const TerminalColourist *colourist, + const char *text); + +#ifdef WAPP_PLATFORM_WINDOWS +#define WIN32_LEAN_AND_MEAN +#include + +internal WORD colours[COUNT_TERM_COLOUR] = { + [WAPP_TERM_COLOUR_FG_BLACK] = 0, + [WAPP_TERM_COLOUR_FG_RED] = FOREGROUND_RED, + [WAPP_TERM_COLOUR_FG_GREEN] = FOREGROUND_GREEN, + [WAPP_TERM_COLOUR_FG_BLUE] = FOREGROUND_BLUE, + [WAPP_TERM_COLOUR_FG_CYAN] = FOREGROUND_GREEN | FOREGROUND_BLUE, + [WAPP_TERM_COLOUR_FG_MAGENTA] = FOREGROUND_RED | FOREGROUND_BLUE, + [WAPP_TERM_COLOUR_FG_YELLOW] = FOREGROUND_RED | FOREGROUND_GREEN, + [WAPP_TERM_COLOUR_FG_WHITE] = + FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE, + [WAPP_TERM_COLOUR_FG_BR_BLACK] = FOREGROUND_INTENSITY, + [WAPP_TERM_COLOUR_FG_BR_RED] = FOREGROUND_RED | FOREGROUND_INTENSITY, + [WAPP_TERM_COLOUR_FG_BR_GREEN] = FOREGROUND_GREEN | FOREGROUND_INTENSITY, + [WAPP_TERM_COLOUR_FG_BR_BLUE] = FOREGROUND_BLUE | FOREGROUND_INTENSITY, + [WAPP_TERM_COLOUR_FG_BR_CYAN] = + FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY, + [WAPP_TERM_COLOUR_FG_BR_MAGENTA] = + FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY, + [WAPP_TERM_COLOUR_FG_BR_YELLOW] = + FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY, + [WAPP_TERM_COLOUR_FG_BR_WHITE] = FOREGROUND_RED | FOREGROUND_GREEN | + FOREGROUND_BLUE | FOREGROUND_INTENSITY, +}; +#else +internal const char *colours[COUNT_TERM_COLOUR] = { + [WAPP_TERM_COLOUR_FG_BLACK] = "\033[30m", + [WAPP_TERM_COLOUR_FG_RED] = "\033[31m", + [WAPP_TERM_COLOUR_FG_GREEN] = "\033[32m", + [WAPP_TERM_COLOUR_FG_BLUE] = "\033[34m", + [WAPP_TERM_COLOUR_FG_CYAN] = "\033[36m", + [WAPP_TERM_COLOUR_FG_MAGENTA] = "\033[35m", + [WAPP_TERM_COLOUR_FG_YELLOW] = "\033[33m", + [WAPP_TERM_COLOUR_FG_WHITE] = "\033[37m", + [WAPP_TERM_COLOUR_FG_BR_BLACK] = "\033[90m", + [WAPP_TERM_COLOUR_FG_BR_RED] = "\033[91m", + [WAPP_TERM_COLOUR_FG_BR_GREEN] = "\033[92m", + [WAPP_TERM_COLOUR_FG_BR_BLUE] = "\033[94m", + [WAPP_TERM_COLOUR_FG_BR_CYAN] = "\033[96m", + [WAPP_TERM_COLOUR_FG_BR_MAGENTA] = "\033[95m", + [WAPP_TERM_COLOUR_FG_BR_YELLOW] = "\033[93m", + [WAPP_TERM_COLOUR_FG_BR_WHITE] = "\033[97m", +}; +#endif /* ifdef WAPP_PLATFORM_WINDOWS */ + +TerminalColourist wapp_termcolour_get_colourist(void) { + TerminalColourist colourist; + +#ifdef WAPP_PLATFORM_WINDOWS + // create handle + colourist.handle = GetStdHandle(STD_OUTPUT_HANDLE); + + // get console colour information + CONSOLE_SCREEN_BUFFER_INFO csbi; + GetConsoleScreenBufferInfo(colourist.handle, &csbi); + colourist.default_colour = csbi.wAttributes; +#else + colourist.default_colour = "\033[0m"; +#endif // ifdef WAPP_PLATFORM_WINDOWS + + colourist.current_colour = colourist.default_colour; + + return colourist; +} + +void wapp_termcolour_print_text(TerminalColourist *colourist, const char *text, + TerminalColour colour) { + if (colour < WAPP_TERM_COLOUR_FG_BLACK || + colour > WAPP_TERM_COLOUR_FG_BR_WHITE) { + return; + } + + colourist->current_colour = colours[colour]; + print_coloured_text(colourist, text); +} + +void wapp_termcolour_clear_colour(TerminalColourist *colourist) { + colourist->current_colour = colourist->default_colour; + print_coloured_text(colourist, ""); +} + +internal void print_coloured_text(const TerminalColourist *colourist, + const char *text) { +#ifdef WAPP_PLATFORM_WINDOWS + SetConsoleTextAttribute(colourist->handle, colourist->current_colour); + printf("%s", text); +#else + printf("%s%s", colourist->current_colour, text); +#endif // ifdef WAPP_PLATFORM_WINDOWS +} diff --git a/src/termcolour/termcolour.h b/src/termcolour/termcolour.h index 4d6af0a..238e672 100644 --- a/src/termcolour/termcolour.h +++ b/src/termcolour/termcolour.h @@ -1,48 +1,56 @@ #ifndef TERM_COLOUR_H #define TERM_COLOUR_H +#include "aliases.h" +#include "misc_utils.h" #include "platform.h" +typedef enum { + WAPP_TERM_COLOUR_FG_BLACK, + WAPP_TERM_COLOUR_FG_RED, + WAPP_TERM_COLOUR_FG_GREEN, + WAPP_TERM_COLOUR_FG_BLUE, + WAPP_TERM_COLOUR_FG_CYAN, + WAPP_TERM_COLOUR_FG_MAGENTA, + WAPP_TERM_COLOUR_FG_YELLOW, + WAPP_TERM_COLOUR_FG_WHITE, + WAPP_TERM_COLOUR_FG_BR_BLACK, + WAPP_TERM_COLOUR_FG_BR_RED, + WAPP_TERM_COLOUR_FG_BR_GREEN, + WAPP_TERM_COLOUR_FG_BR_BLUE, + WAPP_TERM_COLOUR_FG_BR_CYAN, + WAPP_TERM_COLOUR_FG_BR_MAGENTA, + WAPP_TERM_COLOUR_FG_BR_YELLOW, + WAPP_TERM_COLOUR_FG_BR_WHITE, + + COUNT_TERM_COLOUR, +} TerminalColour; + +typedef struct terminal_colourist TerminalColourist; + // clang-format off -#if defined(WAPP_PLATFORM_WINDOWS) - #define TERM_COLOUR_CLEAR "" - #define TERM_COLOUR_BOLD "" - #define TERM_COLOUR_FG_BLACK "" - #define TERM_COLOUR_FG_RED "" - #define TERM_COLOUR_FG_GREEN "" - #define TERM_COLOUR_FG_YELLOW "" - #define TERM_COLOUR_FG_BLUE "" - #define TERM_COLOUR_FG_MAGENTA "" - #define TERM_COLOUR_FG_CYAN "" - #define TERM_COLOUR_FG_WHITE "" - #define TERM_COLOUR_FG_BR_BLACK "" - #define TERM_COLOUR_FG_BR_RED "" - #define TERM_COLOUR_FG_BR_GREEN "" - #define TERM_COLOUR_FG_BR_YELLOW "" - #define TERM_COLOUR_FG_BR_BLUE "" - #define TERM_COLOUR_FG_BR_MAGENTA "" - #define TERM_COLOUR_FG_BR_CYAN "" - #define TERM_COLOUR_FG_BR_WHITE "" -#elif defined(WAPP_PLATFORM_POSIX) - #define TERM_COLOUR_CLEAR "\033[0m" - #define TERM_COLOUR_BOLD "\033[1m" - #define TERM_COLOUR_FG_BLACK "\033[30m" - #define TERM_COLOUR_FG_RED "\033[31m" - #define TERM_COLOUR_FG_GREEN "\033[32m" - #define TERM_COLOUR_FG_YELLOW "\033[33m" - #define TERM_COLOUR_FG_BLUE "\033[34m" - #define TERM_COLOUR_FG_MAGENTA "\033[35m" - #define TERM_COLOUR_FG_CYAN "\033[36m" - #define TERM_COLOUR_FG_WHITE "\033[37m" - #define TERM_COLOUR_FG_BR_BLACK "\033[90m" - #define TERM_COLOUR_FG_BR_RED "\033[91m" - #define TERM_COLOUR_FG_BR_GREEN "\033[92m" - #define TERM_COLOUR_FG_BR_YELLOW "\033[93m" - #define TERM_COLOUR_FG_BR_BLUE "\033[94m" - #define TERM_COLOUR_FG_BR_MAGENTA "\033[95m" - #define TERM_COLOUR_FG_BR_CYAN "\033[96m" - #define TERM_COLOUR_FG_BR_WHITE "\033[97m" -#endif +#ifdef WAPP_PLATFORM_WINDOWS +#define WIN32_LEAN_AND_MEAN +#include +#include + +struct terminal_colourist { + HANDLE handle; + WORD default_colour; + WORD current_colour; + wapp_misc_utils_padding_size(sizeof(HANDLE) + sizeof(WORD) + sizeof(WORD)); +}; +#else +struct terminal_colourist { + const char *default_colour; + const char *current_colour; +}; +#endif // WAPP_PLATFORM_WINDOWS // clang-format on +TerminalColourist wapp_termcolour_get_colourist(void); +void wapp_termcolour_print_text(TerminalColourist *colourist, const char *text, + TerminalColour colour); +void wapp_termcolour_clear_colour(TerminalColourist *colourist); + #endif // !TERM_COLOUR_H diff --git a/src/tester/tester.c b/src/tester/tester.c index b2a9329..1758d03 100644 --- a/src/tester/tester.c +++ b/src/tester/tester.c @@ -1,16 +1,20 @@ #include "tester.h" #include "aliases.h" +#include "platform.h" #include "termcolour.h" #include #include #include -internal void print_test_result(TestFuncResult result); +internal void print_test_result(TerminalColourist *colourist, + TestFuncResult result); void run_tests(TestFunc *func1, ...) { + TerminalColourist colourist = wapp_termcolour_get_colourist(); + printf("\n"); - print_test_result(func1()); + print_test_result(&colourist, func1()); va_list args; va_start(args, func1); @@ -19,7 +23,7 @@ void run_tests(TestFunc *func1, ...) { while (func) { TestFuncResult result = func(); - print_test_result(result); + print_test_result(&colourist, result); if (!result.passed) { exit(EXIT_FAILURE); @@ -33,18 +37,21 @@ void run_tests(TestFunc *func1, ...) { printf("\n"); } -internal void print_test_result(TestFuncResult result) { - const char *colour; +internal void print_test_result(TerminalColourist *colourist, + TestFuncResult result) { + TerminalColour colour; const char *result_text; if (result.passed) { - colour = TERM_COLOUR_FG_BR_GREEN; + colour = WAPP_TERM_COLOUR_FG_BR_GREEN; result_text = "PASSED"; } else { - colour = TERM_COLOUR_FG_BR_RED; + colour = WAPP_TERM_COLOUR_FG_BR_RED; result_text = "FAILED"; } - printf("[%s%s%s%s] %s\n", colour, TERM_COLOUR_BOLD, result_text, - TERM_COLOUR_CLEAR, result.name); + printf("["); + wapp_termcolour_print_text(colourist, result_text, colour); + wapp_termcolour_clear_colour(colourist); + printf("] %s\n", result.name); }