2021-05-08 14:56:48 +02:00
|
|
|
/* Copyright 2021 Aristocratos (jakob@qvantnet.com)
|
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
you may not use this file except in compliance with the License.
|
|
|
|
You may obtain a copy of the License at
|
|
|
|
|
2021-05-10 23:46:41 +02:00
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
2021-05-08 14:56:48 +02:00
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
limitations under the License.
|
|
|
|
|
|
|
|
indent = tab
|
|
|
|
tab-size = 4
|
|
|
|
*/
|
|
|
|
|
2021-06-19 14:57:27 +02:00
|
|
|
#pragma once
|
2021-05-08 14:56:48 +02:00
|
|
|
|
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
2021-05-14 18:54:37 +02:00
|
|
|
#include <regex>
|
2021-05-23 22:25:07 +02:00
|
|
|
#include <atomic>
|
|
|
|
#include <filesystem>
|
2021-06-19 14:57:27 +02:00
|
|
|
#include <ranges>
|
2021-07-15 23:49:16 +02:00
|
|
|
#include <chrono>
|
|
|
|
#include <thread>
|
2021-05-08 20:37:36 +02:00
|
|
|
|
2021-05-08 14:56:48 +02:00
|
|
|
|
2021-07-15 23:49:16 +02:00
|
|
|
using std::string, std::vector, std::atomic;
|
2021-06-19 14:57:27 +02:00
|
|
|
|
2021-05-08 14:56:48 +02:00
|
|
|
|
|
|
|
//? ------------------------------------------------- NAMESPACES ------------------------------------------------------
|
|
|
|
|
|
|
|
//* Collection of escape codes for text style and formatting
|
|
|
|
namespace Fx {
|
2021-06-19 14:57:27 +02:00
|
|
|
extern const string e; //* Escape sequence start
|
|
|
|
extern const string b; //* Bold on/off
|
|
|
|
extern const string ub; //* Bold off
|
|
|
|
extern const string d; //* Dark on
|
|
|
|
extern const string ud; //* Dark off
|
|
|
|
extern const string i; //* Italic on
|
|
|
|
extern const string ui; //* Italic off
|
|
|
|
extern const string ul; //* Underline on
|
|
|
|
extern const string uul; //* Underline off
|
|
|
|
extern const string bl; //* Blink on
|
|
|
|
extern const string ubl; //* Blink off
|
|
|
|
extern const string s; //* Strike/crossed-out on
|
|
|
|
extern const string us; //* Strike/crossed-out on/off
|
2021-05-09 00:18:51 +02:00
|
|
|
|
2021-05-08 14:56:48 +02:00
|
|
|
//* Reset foreground/background color and text effects
|
2021-06-19 14:57:27 +02:00
|
|
|
extern const string reset_base;
|
2021-05-09 00:18:51 +02:00
|
|
|
|
2021-06-19 14:57:27 +02:00
|
|
|
//* Reset text effects and restore theme foregrund and background color
|
|
|
|
extern string reset;
|
2021-05-14 18:54:37 +02:00
|
|
|
|
|
|
|
//* Regex for matching color, style and curse move escape sequences
|
2021-06-19 14:57:27 +02:00
|
|
|
extern const std::regex escape_regex;
|
2021-05-14 18:54:37 +02:00
|
|
|
|
|
|
|
//* Regex for matching only color and style escape sequences
|
2021-06-19 14:57:27 +02:00
|
|
|
extern const std::regex color_regex;
|
2021-05-14 18:54:37 +02:00
|
|
|
|
|
|
|
//* Return a string with all colors and text styling removed
|
2021-07-15 23:49:16 +02:00
|
|
|
inline string uncolor(const string& s){
|
|
|
|
return regex_replace(s, color_regex, "");
|
|
|
|
};
|
2021-05-18 22:11:34 +02:00
|
|
|
}
|
2021-05-08 14:56:48 +02:00
|
|
|
|
|
|
|
//* Collection of escape codes and functions for cursor manipulation
|
|
|
|
namespace Mv {
|
|
|
|
//* Move cursor to <line>, <column>
|
2021-06-19 14:57:27 +02:00
|
|
|
const string to(int line, int col);
|
2021-05-09 00:18:51 +02:00
|
|
|
|
2021-05-08 14:56:48 +02:00
|
|
|
//* Move cursor right <x> columns
|
2021-06-19 14:57:27 +02:00
|
|
|
const string r(int x);
|
2021-05-09 00:18:51 +02:00
|
|
|
|
2021-05-08 14:56:48 +02:00
|
|
|
//* Move cursor left <x> columns
|
2021-06-19 14:57:27 +02:00
|
|
|
const string l(int x);
|
2021-05-09 00:18:51 +02:00
|
|
|
|
2021-05-08 14:56:48 +02:00
|
|
|
//* Move cursor up x lines
|
2021-06-19 14:57:27 +02:00
|
|
|
const string u(int x);
|
2021-05-09 00:18:51 +02:00
|
|
|
|
2021-05-08 14:56:48 +02:00
|
|
|
//* Move cursor down x lines
|
2021-06-19 14:57:27 +02:00
|
|
|
const string d(int x);
|
2021-05-09 00:18:51 +02:00
|
|
|
|
2021-05-08 14:56:48 +02:00
|
|
|
//* Save cursor position
|
2021-06-19 14:57:27 +02:00
|
|
|
extern const string save;
|
2021-05-09 00:18:51 +02:00
|
|
|
|
2021-05-08 14:56:48 +02:00
|
|
|
//* Restore saved cursor postion
|
2021-06-19 14:57:27 +02:00
|
|
|
extern const string restore;
|
2021-05-18 22:11:34 +02:00
|
|
|
}
|
2021-05-08 14:56:48 +02:00
|
|
|
|
2021-05-14 18:54:37 +02:00
|
|
|
//* Collection of escape codes and functions for terminal manipulation
|
|
|
|
namespace Term {
|
2021-07-15 23:49:16 +02:00
|
|
|
extern atomic<bool> initialized;
|
|
|
|
extern atomic<int> width;
|
|
|
|
extern atomic<int> height;
|
2021-06-19 14:57:27 +02:00
|
|
|
extern string fg, bg, current_tty;
|
2021-05-14 18:54:37 +02:00
|
|
|
|
|
|
|
//* Hide terminal cursor
|
2021-06-19 14:57:27 +02:00
|
|
|
extern const string hide_cursor;
|
2021-05-14 18:54:37 +02:00
|
|
|
|
|
|
|
//* Show terminal cursor
|
2021-06-19 14:57:27 +02:00
|
|
|
extern const string show_cursor;
|
2021-05-14 18:54:37 +02:00
|
|
|
|
|
|
|
//* Switch to alternate screen
|
2021-06-19 14:57:27 +02:00
|
|
|
extern const string alt_screen;
|
2021-05-14 18:54:37 +02:00
|
|
|
|
|
|
|
//* Switch to normal screen
|
2021-06-19 14:57:27 +02:00
|
|
|
extern const string normal_screen;
|
2021-05-14 18:54:37 +02:00
|
|
|
|
|
|
|
//* Clear screen and set cursor to position 0,0
|
2021-06-19 14:57:27 +02:00
|
|
|
extern const string clear;
|
2021-05-14 18:54:37 +02:00
|
|
|
|
|
|
|
//* Clear from cursor to end of screen
|
2021-06-19 14:57:27 +02:00
|
|
|
extern const string clear_end;
|
2021-05-14 18:54:37 +02:00
|
|
|
|
|
|
|
//* Clear from cursor to beginning of screen
|
2021-06-19 14:57:27 +02:00
|
|
|
extern const string clear_begin;
|
2021-05-14 18:54:37 +02:00
|
|
|
|
|
|
|
//* Enable reporting of mouse position on click and release
|
2021-06-19 14:57:27 +02:00
|
|
|
extern const string mouse_on;
|
2021-05-14 18:54:37 +02:00
|
|
|
|
|
|
|
//* Disable mouse reporting
|
2021-06-19 14:57:27 +02:00
|
|
|
extern const string mouse_off;
|
2021-05-14 18:54:37 +02:00
|
|
|
|
|
|
|
//* Enable reporting of mouse position at any movement
|
2021-06-19 14:57:27 +02:00
|
|
|
extern const string mouse_direct_on;
|
2021-05-14 18:54:37 +02:00
|
|
|
|
|
|
|
//* Disable direct mouse reporting
|
2021-06-19 14:57:27 +02:00
|
|
|
extern const string mouse_direct_off;
|
2021-05-14 18:54:37 +02:00
|
|
|
|
2021-07-15 23:49:16 +02:00
|
|
|
//* Escape sequence for start of synchronized output
|
|
|
|
extern const string sync_start;
|
|
|
|
|
|
|
|
//* Escape sequence for end of synchronized output
|
|
|
|
extern const string sync_end;
|
|
|
|
|
|
|
|
//* Returns true if terminal has been resized, updates width and height if update=true
|
|
|
|
bool refresh(bool update=true);
|
2021-05-14 18:54:37 +02:00
|
|
|
|
|
|
|
//* Check for a valid tty, save terminal options and set new options
|
2021-06-19 14:57:27 +02:00
|
|
|
bool init();
|
2021-05-14 18:54:37 +02:00
|
|
|
|
|
|
|
//* Restore terminal options
|
2021-06-19 14:57:27 +02:00
|
|
|
void restore();
|
2021-05-18 22:11:34 +02:00
|
|
|
}
|
2021-05-14 18:54:37 +02:00
|
|
|
|
2021-05-08 20:37:36 +02:00
|
|
|
//? --------------------------------------------------- FUNCTIONS -----------------------------------------------------
|
|
|
|
|
2021-05-16 22:58:16 +02:00
|
|
|
namespace Tools {
|
2021-07-15 23:49:16 +02:00
|
|
|
constexpr auto SSmax = std::numeric_limits<std::streamsize>::max();
|
2021-06-12 18:49:27 +02:00
|
|
|
|
2021-07-15 23:49:16 +02:00
|
|
|
//* Return number of UTF8 characters in a string
|
|
|
|
inline size_t ulen(const string& str){
|
|
|
|
return std::ranges::count_if(str, [](char c) { return (static_cast<unsigned char>(c) & 0xC0) != 0x80; } );
|
|
|
|
};
|
2021-05-08 20:37:36 +02:00
|
|
|
|
2021-06-06 01:41:36 +02:00
|
|
|
//* Resize a string consisting of UTF8 characters (only reduces size)
|
2021-07-15 23:49:16 +02:00
|
|
|
string uresize(const string str, const size_t len);
|
2021-06-06 01:41:36 +02:00
|
|
|
|
2021-06-22 19:19:14 +02:00
|
|
|
//* Return <str> with only uppercase characters
|
2021-07-15 23:49:16 +02:00
|
|
|
inline string str_to_upper(string str){
|
|
|
|
std::ranges::for_each(str, [](auto& c){ c = ::toupper(c); } );
|
|
|
|
return str;
|
|
|
|
}
|
2021-06-22 19:19:14 +02:00
|
|
|
|
|
|
|
//* Return <str> with only lowercase characters
|
2021-07-15 23:49:16 +02:00
|
|
|
inline string str_to_lower(string str){
|
|
|
|
std::ranges::for_each(str, [](char& c){ c = ::tolower(c); } );
|
|
|
|
return str;
|
|
|
|
}
|
2021-06-22 19:19:14 +02:00
|
|
|
|
2021-06-12 18:49:27 +02:00
|
|
|
//* Check if vector <vec> contains value <find_val>
|
2021-07-04 22:02:31 +02:00
|
|
|
template <typename T, typename T2>
|
2021-07-15 23:49:16 +02:00
|
|
|
inline bool v_contains(const vector<T>& vec, const T2& find_val) {
|
2021-06-12 18:49:27 +02:00
|
|
|
return std::ranges::find(vec, find_val) != vec.end();
|
|
|
|
}
|
|
|
|
|
2021-07-04 22:02:31 +02:00
|
|
|
//* Check if string <str> contains value <find_val>
|
|
|
|
template <typename T>
|
2021-07-15 23:49:16 +02:00
|
|
|
inline bool s_contains(const string& str, const T& find_val) {
|
2021-07-04 22:02:31 +02:00
|
|
|
return str.find(find_val) != string::npos;
|
|
|
|
}
|
|
|
|
|
2021-06-12 18:49:27 +02:00
|
|
|
//* Return index of <find_val> from vector <vec>, returns size of <vec> if <find_val> is not present
|
|
|
|
template <typename T>
|
2021-07-15 23:49:16 +02:00
|
|
|
inline size_t v_index(const vector<T>& vec, const T& find_val) {
|
2021-06-12 18:49:27 +02:00
|
|
|
return std::ranges::distance(vec.begin(), std::ranges::find(vec, find_val));
|
|
|
|
}
|
|
|
|
|
2021-07-15 23:49:16 +02:00
|
|
|
//* Compare <first> with all following values
|
|
|
|
template<typename First, typename ... T>
|
|
|
|
bool is_in(First &&first, T && ... t) {
|
|
|
|
return ((first == t) || ...);
|
|
|
|
}
|
|
|
|
|
2021-05-29 02:32:36 +02:00
|
|
|
//* Return current time since epoch in seconds
|
2021-07-15 23:49:16 +02:00
|
|
|
inline uint64_t time_s(){
|
|
|
|
return std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()).count();
|
|
|
|
}
|
2021-05-29 02:32:36 +02:00
|
|
|
|
2021-05-16 22:58:16 +02:00
|
|
|
//* Return current time since epoch in milliseconds
|
2021-07-15 23:49:16 +02:00
|
|
|
inline uint64_t time_ms(){
|
|
|
|
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
|
|
|
|
}
|
2021-05-08 20:37:36 +02:00
|
|
|
|
2021-06-02 21:33:26 +02:00
|
|
|
//* Return current time since epoch in microseconds
|
2021-07-15 23:49:16 +02:00
|
|
|
inline uint64_t time_micros(){
|
|
|
|
return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
|
|
|
|
}
|
2021-05-27 22:29:36 +02:00
|
|
|
|
2021-05-16 22:58:16 +02:00
|
|
|
//* Check if a string is a valid bool value
|
2021-07-15 23:49:16 +02:00
|
|
|
inline bool isbool(const string& str){
|
|
|
|
return (str == "true") or (str == "false") or (str == "True") or (str == "False");
|
|
|
|
}
|
2021-05-08 20:37:36 +02:00
|
|
|
|
2021-06-12 18:49:27 +02:00
|
|
|
//* Convert string to bool, returning any value not equal to "true" or "True" as false
|
2021-07-15 23:49:16 +02:00
|
|
|
inline bool stobool(const string& str){
|
|
|
|
return (str == "true" or str == "True");
|
|
|
|
}
|
2021-05-08 20:37:36 +02:00
|
|
|
|
2021-06-12 18:49:27 +02:00
|
|
|
//* Check if a string is a valid integer value
|
2021-07-15 23:49:16 +02:00
|
|
|
inline bool isint(const string& str){
|
|
|
|
return all_of(str.begin() + (str[0] == '-' ? 1 : 0), str.end(), ::isdigit);
|
|
|
|
}
|
2021-05-08 20:37:36 +02:00
|
|
|
|
2021-06-12 18:49:27 +02:00
|
|
|
//* Left-trim <t_str> from <str> and return new string
|
2021-07-15 23:49:16 +02:00
|
|
|
string ltrim(const string& str, const string& t_str = " ");
|
2021-06-12 18:49:27 +02:00
|
|
|
|
|
|
|
//* Right-trim <t_str> from <str> and return new string
|
2021-07-15 23:49:16 +02:00
|
|
|
string rtrim(const string& str, const string& t_str = " ");
|
2021-05-08 20:37:36 +02:00
|
|
|
|
2021-07-15 23:49:16 +02:00
|
|
|
//* Left/right-trim <t_str> from <str> and return new string
|
|
|
|
inline string trim(const string& str, const string& t_str = " "){
|
|
|
|
return ltrim(rtrim(str, t_str), t_str);
|
|
|
|
};
|
2021-05-09 00:18:51 +02:00
|
|
|
|
2021-06-19 14:57:27 +02:00
|
|
|
//* Split <string> at all occurrences of <delim> and return as vector of strings
|
2021-07-15 23:49:16 +02:00
|
|
|
vector<string> ssplit(const string& str, const char& delim = ' ');
|
2021-05-16 22:58:16 +02:00
|
|
|
|
|
|
|
//* Put current thread to sleep for <ms> milliseconds
|
2021-07-15 23:49:16 +02:00
|
|
|
inline void sleep_ms(const size_t& ms) { std::this_thread::sleep_for(std::chrono::milliseconds(ms)); };
|
2021-05-09 00:18:51 +02:00
|
|
|
|
2021-05-16 22:58:16 +02:00
|
|
|
//* Left justify string <str> if <x> is greater than <str> length, limit return size to <x> by default
|
2021-07-15 23:49:16 +02:00
|
|
|
string ljust(string str, const size_t x, const bool utf=false, const bool limit=true);
|
2021-05-09 00:18:51 +02:00
|
|
|
|
2021-05-16 22:58:16 +02:00
|
|
|
//* Right justify string <str> if <x> is greater than <str> length, limit return size to <x> by default
|
2021-07-15 23:49:16 +02:00
|
|
|
string rjust(string str, const size_t x, const bool utf=false, const bool limit=true);
|
2021-05-09 00:18:51 +02:00
|
|
|
|
2021-05-16 22:58:16 +02:00
|
|
|
//* Replace whitespaces " " with escape code for move right
|
2021-06-19 14:57:27 +02:00
|
|
|
string trans(const string& str);
|
2021-05-13 21:11:10 +02:00
|
|
|
|
2021-05-16 22:58:16 +02:00
|
|
|
//* Convert seconds to format "Xd HH:MM:SS" and return string
|
2021-06-27 22:13:32 +02:00
|
|
|
string sec_to_dhms(size_t sec);
|
2021-05-22 02:13:56 +02:00
|
|
|
|
2021-05-16 22:58:16 +02:00
|
|
|
//* Scales up in steps of 1024 to highest possible unit and returns string with unit suffixed
|
|
|
|
//* bit=True or defaults to bytes
|
|
|
|
//* start=int to set 1024 multiplier starting unit
|
|
|
|
//* short=True always returns 0 decimals and shortens unit to 1 character
|
2021-06-27 22:13:32 +02:00
|
|
|
string floating_humanizer(uint64_t value, bool shorten=false, size_t start=0, bool bit=false, bool per_second=false);
|
2021-05-16 22:58:16 +02:00
|
|
|
|
2021-06-05 01:41:24 +02:00
|
|
|
//* Add std::string operator "*" : Repeat string <str> <n> number of times
|
2021-06-19 14:57:27 +02:00
|
|
|
std::string operator*(string str, size_t n);
|
2021-05-13 21:11:10 +02:00
|
|
|
|
2021-05-23 01:59:13 +02:00
|
|
|
//* Return current time in <strf> format
|
2021-07-15 23:49:16 +02:00
|
|
|
string strf_time(const string& strf);
|
2021-06-06 01:41:36 +02:00
|
|
|
|
2021-05-23 01:59:13 +02:00
|
|
|
}
|
|
|
|
|
2021-05-29 02:32:36 +02:00
|
|
|
//* Simple logging implementation
|
2021-05-23 01:59:13 +02:00
|
|
|
namespace Logger {
|
2021-07-15 23:49:16 +02:00
|
|
|
extern const vector<string> log_levels;
|
2021-06-19 14:57:27 +02:00
|
|
|
extern std::filesystem::path logfile;
|
|
|
|
|
2021-07-15 23:49:16 +02:00
|
|
|
void set(const string level); //* Set log level, valid arguments: "DISABLED", "ERROR", "WARNING", "INFO" and "DEBUG"
|
|
|
|
void log_write(const size_t level, const string& msg);
|
|
|
|
inline void error(const string msg){ log_write(1, msg); }
|
|
|
|
inline void warning(const string msg){ log_write(2, msg); }
|
|
|
|
inline void info(const string msg){ log_write(3, msg); }
|
|
|
|
inline void debug(const string msg){ log_write(4, msg); }
|
2021-05-13 21:11:10 +02:00
|
|
|
}
|
2021-05-09 22:25:41 +02:00
|
|
|
|