Initial Commit
This commit is contained in:
47
CMakeLists.txt
Normal file
47
CMakeLists.txt
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.18..27)
|
||||||
|
PROJECT(jlog
|
||||||
|
VERSION 1.0
|
||||||
|
LANGUAGES CXX
|
||||||
|
)
|
||||||
|
|
||||||
|
if (PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR)
|
||||||
|
message(FATAL_ERROR "In-source builds are not allowed!")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
|
|
||||||
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||||
|
|
||||||
|
include(cmake/CPM.cmake)
|
||||||
|
|
||||||
|
|
||||||
|
file(GLOB_RECURSE jlog_HEADERS "include/*.h" "include/*.hpp")
|
||||||
|
file(GLOB_RECURSE jlog_SRC "src/*.c" "src/*.cpp")
|
||||||
|
|
||||||
|
include_directories("include")
|
||||||
|
|
||||||
|
|
||||||
|
CPMAddPackage(
|
||||||
|
NAME Event
|
||||||
|
URL https://git.redacted.cc/josh/Event/archive/Release-6.zip
|
||||||
|
)
|
||||||
|
|
||||||
|
include_directories(${Event_SOURCE_DIR}/include)
|
||||||
|
|
||||||
|
if (UNIX)
|
||||||
|
add_library(jlog SHARED ${jlog_SRC})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (WIN32)
|
||||||
|
add_library(jlog STATIC ${jlog_SRC})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set_target_properties(jlog PROPERTIES LINKER_LANGUAGE CXX)
|
||||||
|
|
||||||
|
install(TARGETS ${PROJECT_NAME} DESTINATION lib/${PROJECT_NAME})
|
||||||
|
install(FILES ${jlog_HEADERS} DESTINATION include/${PROJECT_NAME})
|
||||||
|
|
||||||
|
#add_subdirectory(tests)
|
||||||
|
|
||||||
|
add_executable(LoggerDemo main.cpp)
|
||||||
|
target_link_libraries(LoggerDemo ${PROJECT_NAME} Event)
|
24
cmake/CPM.cmake
Normal file
24
cmake/CPM.cmake
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
#
|
||||||
|
# SPDX-FileCopyrightText: Copyright (c) 2019-2023 Lars Melchior and contributors
|
||||||
|
|
||||||
|
set(CPM_DOWNLOAD_VERSION 0.38.7)
|
||||||
|
set(CPM_HASH_SUM "83e5eb71b2bbb8b1f2ad38f1950287a057624e385c238f6087f94cdfc44af9c5")
|
||||||
|
|
||||||
|
if(CPM_SOURCE_CACHE)
|
||||||
|
set(CPM_DOWNLOAD_LOCATION "${CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
|
||||||
|
elseif(DEFINED ENV{CPM_SOURCE_CACHE})
|
||||||
|
set(CPM_DOWNLOAD_LOCATION "$ENV{CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
|
||||||
|
else()
|
||||||
|
set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Expand relative path. This is important if the provided path contains a tilde (~)
|
||||||
|
get_filename_component(CPM_DOWNLOAD_LOCATION ${CPM_DOWNLOAD_LOCATION} ABSOLUTE)
|
||||||
|
|
||||||
|
file(DOWNLOAD
|
||||||
|
https://github.com/cpm-cmake/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake
|
||||||
|
${CPM_DOWNLOAD_LOCATION} EXPECTED_HASH SHA256=${CPM_HASH_SUM}
|
||||||
|
)
|
||||||
|
|
||||||
|
include(${CPM_DOWNLOAD_LOCATION})
|
106
include/ansi_escape_codes.hpp
Normal file
106
include/ansi_escape_codes.hpp
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <format>
|
||||||
|
|
||||||
|
#define ESC "\033["
|
||||||
|
|
||||||
|
namespace jlog::ansi_escape_codes
|
||||||
|
{
|
||||||
|
static const std::string CURSOR_HOME = "\033[H";
|
||||||
|
|
||||||
|
static const std::string ERASE_SCREEN_AFTER_CURSOR = "\033[0J";
|
||||||
|
static const std::string ERASE_SCREEN_BEFORE_CURSOR = "\033[1J";
|
||||||
|
static const std::string ERASE_SCREEN_ALL = "\033[2J";
|
||||||
|
static const std::string ERASE_LINE_AFTER_CURSOR = "\033[0K";
|
||||||
|
static const std::string ERASE_LINE_BEFORE_CURSOR = "\033[1K";
|
||||||
|
static const std::string ERASE_LINE_ALL = "\033[2K";
|
||||||
|
|
||||||
|
static const std::string RESET = "\033[0m";
|
||||||
|
static const std::string BOLD = "\033[1m";
|
||||||
|
static const std::string DIM = "\033[2m";
|
||||||
|
|
||||||
|
/// These are some examples of private modes, which are not defined by the spec, but are implemented in most terminals.
|
||||||
|
/// @see xterm control sequences for a more in-depth list.
|
||||||
|
/// https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
|
||||||
|
/// @note While these modes may be supported by most terminals, some may not work in multiplexers like tmux.
|
||||||
|
|
||||||
|
static const std::string CURSOR_INVISIBLE = "\033[?25l";
|
||||||
|
static const std::string CURSOR_VISIBLE = "\033[?25h";
|
||||||
|
static const std::string RESTORE_SCREEN = "\033[?47l";
|
||||||
|
static const std::string SAVE_SCREEN = "\033[?47h";
|
||||||
|
|
||||||
|
|
||||||
|
static const std::string FG_BLACK = "\033[30m";
|
||||||
|
static const std::string FG_RED = "\033[31m";
|
||||||
|
static const std::string FG_GREEN = "\033[32m";
|
||||||
|
static const std::string FG_YELLOW = "\033[33m";
|
||||||
|
static const std::string FG_BLUE = "\033[34m";
|
||||||
|
static const std::string FG_MAGENTA = "\033[35m";
|
||||||
|
static const std::string FG_CYAN = "\033[36m";
|
||||||
|
static const std::string FG_WHITE = "\033[37m";
|
||||||
|
static const std::string FG_DEFAULT = "\033[39m";
|
||||||
|
|
||||||
|
|
||||||
|
static const std::string FG_BRIGHT_BLACK = "90";
|
||||||
|
static const std::string FG_BRIGHT_RED = "91";
|
||||||
|
static const std::string FG_BRIGHT_GREEN = "92";
|
||||||
|
static const std::string FG_BRIGHT_YELLOW = "93";
|
||||||
|
static const std::string FG_BRIGHT_BLUE = "94";
|
||||||
|
static const std::string FG_BRIGHT_MAGENTA = "95";
|
||||||
|
static const std::string FG_BRIGHT_CYAN = "96";
|
||||||
|
static const std::string FG_BRIGHT_WHITE = "97";
|
||||||
|
|
||||||
|
|
||||||
|
static const std::string BG_BLACK = "40";
|
||||||
|
static const std::string BG_RED = "41";
|
||||||
|
static const std::string BG_GREEN = "42";
|
||||||
|
static const std::string BG_YELLOW = "43";
|
||||||
|
static const std::string BG_BLUE = "44";
|
||||||
|
static const std::string BG_MAGENTA = "45";
|
||||||
|
static const std::string BG_CYAN = "46";
|
||||||
|
static const std::string BG_WHITE = "47";
|
||||||
|
static const std::string BG_DEFAULT = "49";
|
||||||
|
|
||||||
|
static const std::string BG_BRIGHT_BLACK = "100";
|
||||||
|
static const std::string BG_BRIGHT_RED = "101";
|
||||||
|
static const std::string BG_BRIGHT_GREEN = "102";
|
||||||
|
static const std::string BG_BRIGHT_YELLOW = "103";
|
||||||
|
static const std::string BG_BRIGHT_BLUE = "104";
|
||||||
|
|
||||||
|
std::string true_color(uint8_t r, uint8_t g, uint8_t b)
|
||||||
|
{
|
||||||
|
return std::format("\033[38;2;{};{};{}m", r, g, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string cursor_to(int line, int col)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string cursor_up(int lines)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string cursor_down(int lines)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string cursor_left(int cols)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string cursor_right(int cols)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string cursor_to_col(int col)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
109
include/jlog.hpp
Normal file
109
include/jlog.hpp
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <format>
|
||||||
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
#include <chrono>
|
||||||
|
#include <Event.h>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
namespace jlog
|
||||||
|
{
|
||||||
|
enum class severity
|
||||||
|
{
|
||||||
|
none,
|
||||||
|
verbose,
|
||||||
|
debug,
|
||||||
|
warning,
|
||||||
|
error,
|
||||||
|
fatal
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static std::string get_timestamp()
|
||||||
|
{
|
||||||
|
using namespace std::chrono;
|
||||||
|
auto const timestamp = current_zone()->to_local(system_clock::now());
|
||||||
|
auto dp = floor<days>(timestamp);
|
||||||
|
year_month_day ymd{floor<days>(timestamp)};
|
||||||
|
hh_mm_ss time{floor<milliseconds>(timestamp-dp)};
|
||||||
|
auto y = ymd.year();
|
||||||
|
auto m = ymd.month();
|
||||||
|
auto d = ymd.day();
|
||||||
|
auto h = time.hours();
|
||||||
|
auto M = time.minutes();
|
||||||
|
auto s = time.seconds();
|
||||||
|
auto ms = time.subseconds();
|
||||||
|
return std::format("{}-{}-{} {}:{}:{}.{}", y, m, d, h.count(), M.count(), s.count(), ms.count());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool lib_initialized = false;
|
||||||
|
static std::vector<std::shared_ptr<std::ostream>> outputs;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void add_output(std::ostream* output)
|
||||||
|
{
|
||||||
|
if (!lib_initialized)
|
||||||
|
throw std::runtime_error("jlog::init() ya dumbfuck!!!");
|
||||||
|
|
||||||
|
|
||||||
|
outputs.push_back(std::shared_ptr<std::ostream>(output));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void add_output(std::shared_ptr<std::ofstream> output) {
|
||||||
|
outputs.push_back(std::move(output));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct LogEntry
|
||||||
|
{
|
||||||
|
severity level;
|
||||||
|
std::string content;
|
||||||
|
std::string timestamp;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void log_to_console(const std::string& message) {
|
||||||
|
std::cout << message << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void log_to_file(const std::string& message) {
|
||||||
|
std::ofstream latest_log("latest.log");
|
||||||
|
latest_log << message << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Event<LogEntry> on_log;
|
||||||
|
|
||||||
|
static std::vector<LogEntry> log_history;
|
||||||
|
|
||||||
|
static void log(const std::string& message) {
|
||||||
|
auto output = std::format("[{}] {}", get_timestamp(), message);
|
||||||
|
log_to_console(output);
|
||||||
|
log_to_file(output);
|
||||||
|
on_log({.level = severity::none, .content = message, .timestamp = get_timestamp()});
|
||||||
|
}
|
||||||
|
|
||||||
|
static void log(const std::string& contextColorCode, const std::string& context, const std::string& message) {
|
||||||
|
log_to_console(std::format("[{}] {}[{}]{} {}", get_timestamp(), contextColorCode, context, ansi_escape_codes::RESET, message));
|
||||||
|
log_to_file(std::format("[{}] [{}] {}", get_timestamp(), context, message));
|
||||||
|
on_log({.level = severity::none, .content = message, .timestamp = get_timestamp()});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void direct(const std::string& message) { log(message);};
|
||||||
|
void info(const std::string& message) {log(ansi_escape_codes::FG_WHITE, "INFO", message); }
|
||||||
|
static void verbose(const std::string& message) { log(ansi_escape_codes::FG_CYAN, "VERBOSE", message); }
|
||||||
|
static void debug (const std::string& message) { log(ansi_escape_codes::FG_GREEN, "DEBUG", message); }
|
||||||
|
static void warning(const std::string& message) { log(ansi_escape_codes::FG_YELLOW, "WARNING", message); }
|
||||||
|
static void error (const std::string& message) { log(ansi_escape_codes::FG_BRIGHT_RED, "ERROR", message); }
|
||||||
|
static void fatal (const std::string& message) { log(ansi_escape_codes::FG_RED, "FATAL", message); }
|
||||||
|
|
||||||
|
|
||||||
|
static void init() {}
|
||||||
|
|
||||||
|
static void flush() {}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
15
main.cpp
Normal file
15
main.cpp
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#include "include/ansi_escape_codes.hpp"
|
||||||
|
#include "include/jlog.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
jlog::init();
|
||||||
|
jlog::log("Test Program");
|
||||||
|
jlog::fatal("FUCK BRO");
|
||||||
|
|
||||||
|
jlog::flush();
|
||||||
|
return 0;
|
||||||
|
///
|
||||||
|
}
|
3
src/jlog.cpp
Normal file
3
src/jlog.cpp
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
//
|
||||||
|
// Created by dawsh on 6/11/24.
|
||||||
|
//
|
Reference in New Issue
Block a user