Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: CI

on:
push:
pull_request:

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Compile library
run: g++ -std=c++11 -Wall -Wextra -c text_support.cpp -o text_support.o

- name: Build test binary
run: g++ -std=c++11 -Wall -Wextra text_support.cpp test_main.cpp -o test_runner

- name: Run tests
run: ./test_runner
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.o
test_runner
83 changes: 82 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,85 @@
# TextSupport
Colored text & console log support for C++
Colored text & console log support for C++

![ScreenShot](https://github.com/FL1NE/TextSupport/blob/master/screenshot.png "ScreenShot")

## Requirements

- C++11 or later
- POSIX-compatible environment (Linux, macOS)

## Usage

### Include

```cpp
#include "text_support.h"
```

### Named log functions

```cpp
textSupport::debugMessage("something happened");
textSupport::infoMessage("server started");
textSupport::warningMessage("retrying connection");
textSupport::errorMessage("file not found");
textSupport::fatalMessage("unrecoverable error");
```

### Log with LogLevel enum

Use `log()` to select the level at call site:

```cpp
textSupport::log(textSupport::LogLevel::Debug, "debug message");
textSupport::log(textSupport::LogLevel::Info, "info message");
textSupport::log(textSupport::LogLevel::Warning, "warning message");
textSupport::log(textSupport::LogLevel::Error, "error message");
textSupport::log(textSupport::LogLevel::Fatal, "fatal message");
```

### Adding a new log level

Edit `LOG_TABLE` in `text_support.cpp` and add a corresponding entry to the `LogLevel` enum in `text_support.h`:

```cpp
// text_support.h
enum class LogLevel { Debug, Info, Warning, Error, Fatal, Verbose }; // add here

// text_support.cpp
static const LogEntry LOG_TABLE[] = {
/* Debug */ { "DBG", TEXT_SUPPORT_BLUE, &std::cout },
/* Info */ { "INFO", TEXT_SUPPORT_CYAN, &std::cout },
/* Warning */ { "WARN", TEXT_SUPPORT_YELLOW, &std::cout },
/* Error */ { "ERR", TEXT_SUPPORT_RED, &std::cerr },
/* Fatal */ { "FATAL", TEXT_SUPPORT_BOLDRED, &std::cerr },
/* Verbose */ { "VERBOSE", TEXT_SUPPORT_WHITE, &std::cout }, // add here
};
```

### Color macros

The following macros are available for direct use:

| Macro | Color |
|---|---|
| `TEXT_SUPPORT_RESET` | Reset |
| `TEXT_SUPPORT_BLACK` | Black |
| `TEXT_SUPPORT_RED` | Red |
| `TEXT_SUPPORT_GREEN` | Green |
| `TEXT_SUPPORT_YELLOW` | Yellow |
| `TEXT_SUPPORT_BLUE` | Blue |
| `TEXT_SUPPORT_MAGENTA` | Magenta |
| `TEXT_SUPPORT_CYAN` | Cyan |
| `TEXT_SUPPORT_WHITE` | White |
| `TEXT_SUPPORT_BOLD*` | Bold variants of the above |

## Build

```sh
g++ -std=c++11 your_program.cpp text_support.cpp -o your_program
```

## License

Copyright (c) 2017 FRONTL1NE All rights reserved
19 changes: 19 additions & 0 deletions test_main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#include "text_support.h"

int main() {
// Named functions
textSupport::debugMessage("debugMessage OK");
textSupport::infoMessage("infoMessage OK");
textSupport::warningMessage("warningMessage OK");
textSupport::errorMessage("errorMessage OK");
textSupport::fatalMessage("fatalMessage OK");

// Direct log() with LogLevel enum
textSupport::log(textSupport::LogLevel::Debug, "log(Debug) OK");
textSupport::log(textSupport::LogLevel::Info, "log(Info) OK");
textSupport::log(textSupport::LogLevel::Warning, "log(Warning) OK");
textSupport::log(textSupport::LogLevel::Error, "log(Error) OK");
textSupport::log(textSupport::LogLevel::Fatal, "log(Fatal) OK");

return 0;
}
230 changes: 51 additions & 179 deletions text_support.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,200 +16,72 @@
#include "text_support.h"


void textSupport::debugMessage(const char* message){
static std::string getTimestamp() {
time_t timer;
struct tm *t_st;
struct tm t_st;
time(&timer);
t_st = localtime(&timer);


std::cout << "[" << TEXT_SUPPORT_BLUE << "DBG" << TEXT_SUPPORT_RESET << "]" << " "
<< std::setw(4) << std::setfill('0') << t_st->tm_year + 1900 << "-"
<< std::setw(2) << std::setfill('0') << t_st->tm_mon + 1 << "-"
<< std::setw(2) << std::setfill('0') << t_st->tm_mday << " "
<< std::setw(2) << std::setfill('0') << t_st->tm_hour << ":"
<< std::setw(2) << std::setfill('0') << t_st->tm_min << ":"
<< std::setw(2) << std::setfill('0') << t_st->tm_sec << " "
<< message << std::endl;
localtime_r(&timer, &t_st);

std::ostringstream oss;
oss << std::setw(4) << std::setfill('0') << t_st.tm_year + 1900 << "-"
<< std::setw(2) << std::setfill('0') << t_st.tm_mon + 1 << "-"
<< std::setw(2) << std::setfill('0') << t_st.tm_mday << " "
<< std::setw(2) << std::setfill('0') << t_st.tm_hour << ":"
<< std::setw(2) << std::setfill('0') << t_st.tm_min << ":"
<< std::setw(2) << std::setfill('0') << t_st.tm_sec;
return oss.str();
}

void textSupport::debugMessage(std::string message){
time_t timer;
struct tm *t_st;
time(&timer);
t_st = localtime(&timer);


std::cout << "[" << TEXT_SUPPORT_BLUE << "DBG" << TEXT_SUPPORT_RESET << "]" << " "
<< std::setw(4) << std::setfill('0') << t_st->tm_year + 1900 << "-"
<< std::setw(2) << std::setfill('0') << t_st->tm_mon + 1 << "-"
<< std::setw(2) << std::setfill('0') << t_st->tm_mday << " "
<< std::setw(2) << std::setfill('0') << t_st->tm_hour << ":"
<< std::setw(2) << std::setfill('0') << t_st->tm_min << ":"
<< std::setw(2) << std::setfill('0') << t_st->tm_sec << " "
<< message << std::endl;
}

struct LogEntry {
const char* label;
const char* color;
std::ostream* stream;
};

void textSupport::infoMessage(const char* message){
time_t timer;
struct tm *t_st;
time(&timer);
t_st = localtime(&timer);
static const LogEntry LOG_TABLE[] = {
/* Debug */ { "DBG", TEXT_SUPPORT_BLUE, &std::cout },
/* Info */ { "INFO", TEXT_SUPPORT_CYAN, &std::cout },
/* Warning */ { "WARN", TEXT_SUPPORT_YELLOW, &std::cout },
/* Error */ { "ERR", TEXT_SUPPORT_RED, &std::cerr },
/* Fatal */ { "FATAL", TEXT_SUPPORT_BOLDRED, &std::cerr },
};


std::cout << "[" << TEXT_SUPPORT_CYAN << "INFO" << TEXT_SUPPORT_RESET << "]" << " "
<< std::setw(4) << std::setfill('0') << t_st->tm_year + 1900 << "-"
<< std::setw(2) << std::setfill('0') << t_st->tm_mon + 1 << "-"
<< std::setw(2) << std::setfill('0') << t_st->tm_mday << " "
<< std::setw(2) << std::setfill('0') << t_st->tm_hour << ":"
<< std::setw(2) << std::setfill('0') << t_st->tm_min << ":"
<< std::setw(2) << std::setfill('0') << t_st->tm_sec << " "
<< message << std::endl;
void textSupport::log(LogLevel level, const std::string& message) {
const LogEntry& e = LOG_TABLE[static_cast<int>(level)];
const std::string lbl(e.label);
*e.stream << "[" << e.color << lbl << TEXT_SUPPORT_RESET << "]"
<< std::string(7 - lbl.size(), ' ')
<< getTimestamp() << " " << message << std::endl;
}

void textSupport::infoMessage(std::string message){
time_t timer;
struct tm *t_st;
time(&timer);
t_st = localtime(&timer);


std::cout << "[" << TEXT_SUPPORT_CYAN << "INFO" << TEXT_SUPPORT_RESET << "]" << " "
<< std::setw(4) << std::setfill('0') << t_st->tm_year + 1900 << "-"
<< std::setw(2) << std::setfill('0') << t_st->tm_mon + 1 << "-"
<< std::setw(2) << std::setfill('0') << t_st->tm_mday << " "
<< std::setw(2) << std::setfill('0') << t_st->tm_hour << ":"
<< std::setw(2) << std::setfill('0') << t_st->tm_min << ":"
<< std::setw(2) << std::setfill('0') << t_st->tm_sec << " "
<< message << std::endl;
}


void textSupport::warningMessage(const char* message){
time_t timer;
struct tm *t_st;
time(&timer);
t_st = localtime(&timer);


std::cout << "[" << TEXT_SUPPORT_YELLOW << "WARN" << TEXT_SUPPORT_RESET << "]" << " "
<< std::setw(4) << std::setfill('0') << t_st->tm_year + 1900 << "-"
<< std::setw(2) << std::setfill('0') << t_st->tm_mon + 1 << "-"
<< std::setw(2) << std::setfill('0') << t_st->tm_mday << " "
<< std::setw(2) << std::setfill('0') << t_st->tm_hour << ":"
<< std::setw(2) << std::setfill('0') << t_st->tm_min << ":"
<< std::setw(2) << std::setfill('0') << t_st->tm_sec << " "
<< message << std::endl;
}

void textSupport::warningMessage(std::string message){
time_t timer;
struct tm *t_st;
time(&timer);
t_st = localtime(&timer);


std::cout << "[" << TEXT_SUPPORT_YELLOW << "WARN" << TEXT_SUPPORT_RESET << "]" << " "
<< std::setw(4) << std::setfill('0') << t_st->tm_year + 1900 << "-"
<< std::setw(2) << std::setfill('0') << t_st->tm_mon + 1 << "-"
<< std::setw(2) << std::setfill('0') << t_st->tm_mday << " "
<< std::setw(2) << std::setfill('0') << t_st->tm_hour << ":"
<< std::setw(2) << std::setfill('0') << t_st->tm_min << ":"
<< std::setw(2) << std::setfill('0') << t_st->tm_sec << " "
<< message << std::endl;
}


void textSupport::errorMessage(const char* message){
time_t timer;
struct tm *t_st;
time(&timer);
t_st = localtime(&timer);


std::cerr << "[" << TEXT_SUPPORT_RED << "ERR" << TEXT_SUPPORT_RESET << "]" << " "
<< std::setw(4) << std::setfill('0') << t_st->tm_year + 1900 << "-"
<< std::setw(2) << std::setfill('0') << t_st->tm_mon + 1 << "-"
<< std::setw(2) << std::setfill('0') << t_st->tm_mday << " "
<< std::setw(2) << std::setfill('0') << t_st->tm_hour << ":"
<< std::setw(2) << std::setfill('0') << t_st->tm_min << ":"
<< std::setw(2) << std::setfill('0') << t_st->tm_sec << " "
<< message << std::endl;
}

void textSupport::errorMessage(std::string message){
time_t timer;
struct tm *t_st;
time(&timer);
t_st = localtime(&timer);


std::cerr << "[" << TEXT_SUPPORT_RED << "ERR" << TEXT_SUPPORT_RESET << "]" << " "
<< std::setw(4) << std::setfill('0') << t_st->tm_year + 1900 << "-"
<< std::setw(2) << std::setfill('0') << t_st->tm_mon + 1 << "-"
<< std::setw(2) << std::setfill('0') << t_st->tm_mday << " "
<< std::setw(2) << std::setfill('0') << t_st->tm_hour << ":"
<< std::setw(2) << std::setfill('0') << t_st->tm_min << ":"
<< std::setw(2) << std::setfill('0') << t_st->tm_sec << " "
<< message << std::endl;
}


void textSupport::fatalMessage(const char* message){
time_t timer;
struct tm *t_st;
time(&timer);
t_st = localtime(&timer);


std::cerr << "[" << TEXT_SUPPORT_BOLDRED << "FATAL" << TEXT_SUPPORT_RESET << "]" << " "
<< std::setw(4) << std::setfill('0') << t_st->tm_year + 1900 << "-"
<< std::setw(2) << std::setfill('0') << t_st->tm_mon + 1 << "-"
<< std::setw(2) << std::setfill('0') << t_st->tm_mday << " "
<< std::setw(2) << std::setfill('0') << t_st->tm_hour << ":"
<< std::setw(2) << std::setfill('0') << t_st->tm_min << ":"
<< std::setw(2) << std::setfill('0') << t_st->tm_sec << " "
<< message << std::endl;
}

void textSupport::fatalMessage(std::string message){
time_t timer;
struct tm *t_st;
time(&timer);
t_st = localtime(&timer);


std::cerr << "[" << TEXT_SUPPORT_BOLDRED << "FATAL" << TEXT_SUPPORT_RESET << "]" << " "
<< std::setw(4) << std::setfill('0') << t_st->tm_year + 1900 << "-"
<< std::setw(2) << std::setfill('0') << t_st->tm_mon + 1 << "-"
<< std::setw(2) << std::setfill('0') << t_st->tm_mday << " "
<< std::setw(2) << std::setfill('0') << t_st->tm_hour << ":"
<< std::setw(2) << std::setfill('0') << t_st->tm_min << ":"
<< std::setw(2) << std::setfill('0') << t_st->tm_sec << " "
<< message << std::endl;
}
void textSupport::debugMessage(const std::string& message) { log(LogLevel::Debug, message); }
void textSupport::infoMessage(const std::string& message) { log(LogLevel::Info, message); }
void textSupport::warningMessage(const std::string& message) { log(LogLevel::Warning, message); }
void textSupport::errorMessage(const std::string& message) { log(LogLevel::Error, message); }
void textSupport::fatalMessage(const std::string& message) { log(LogLevel::Fatal, message); }


void textSupport::testMessage(){
void textSupport::testMessage() {
std::cout
<< TEXT_SUPPORT_RESET << "RESET "
<< TEXT_SUPPORT_BLACK << "BLACK "
<< TEXT_SUPPORT_RED << "RED "
<< TEXT_SUPPORT_GREEN << "GREEN "
<< TEXT_SUPPORT_YELLOW << "YELLOW "
<< TEXT_SUPPORT_BLUE << "BLUE "
<< TEXT_SUPPORT_RESET << "RESET "
<< TEXT_SUPPORT_BLACK << "BLACK "
<< TEXT_SUPPORT_RED << "RED "
<< TEXT_SUPPORT_GREEN << "GREEN "
<< TEXT_SUPPORT_YELLOW << "YELLOW "
<< TEXT_SUPPORT_BLUE << "BLUE "
<< TEXT_SUPPORT_MAGENTA << "MAGENTA "
<< TEXT_SUPPORT_CYAN << "CYAN "
<< TEXT_SUPPORT_WHITE << "WHITE "
<< TEXT_SUPPORT_BOLDBLACK << "BOLDBLACK "
<< TEXT_SUPPORT_BOLDRED << "BOLDRED "
<< TEXT_SUPPORT_BOLDGREEN << "BOLDGREEN "
<< TEXT_SUPPORT_BOLDYELLOW << "BOLDYELLOW "
<< TEXT_SUPPORT_BOLDBLUE << "BOLDBLUE "
<< TEXT_SUPPORT_CYAN << "CYAN "
<< TEXT_SUPPORT_WHITE << "WHITE "
<< TEXT_SUPPORT_BOLDBLACK << "BOLDBLACK "
<< TEXT_SUPPORT_BOLDRED << "BOLDRED "
<< TEXT_SUPPORT_BOLDGREEN << "BOLDGREEN "
<< TEXT_SUPPORT_BOLDYELLOW << "BOLDYELLOW "
<< TEXT_SUPPORT_BOLDBLUE << "BOLDBLUE "
<< TEXT_SUPPORT_BOLDMAGENTA << "BOLDMAGENTA "
<< TEXT_SUPPORT_BOLDCYAN << "BOLDCYAN "
<< TEXT_SUPPORT_BOLDWHITE << "BOLDWHITE "
<< TEXT_SUPPORT_BOLDCYAN << "BOLDCYAN "
<< TEXT_SUPPORT_BOLDWHITE << "BOLDWHITE "
<< TEXT_SUPPORT_RESET << std::endl;

textSupport::debugMessage("This is DEBUG Message.");
Expand Down
Loading