mirror of
https://github.com/aristocratos/btop.git
synced 2024-09-28 07:11:24 +12:00
Small improvements
This commit is contained in:
parent
9bf7da049b
commit
ce34cbb8d0
7 changed files with 142 additions and 153 deletions
161
btop.cpp
161
btop.cpp
|
@ -39,17 +39,15 @@ namespace Global {
|
|||
{"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"},
|
||||
{"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"},
|
||||
};
|
||||
const uint banner_width = 49;
|
||||
|
||||
const std::string Version = "0.0.10";
|
||||
const std::string Version = "0.0.20";
|
||||
}
|
||||
|
||||
#include <btop_globs.h>
|
||||
#include <btop_tools.h>
|
||||
#include <btop_config.h>
|
||||
#include <btop_input.h>
|
||||
#include <btop_theme.h>
|
||||
#include <btop_draw.h>
|
||||
#include <btop_menu.h>
|
||||
|
||||
#if defined(__linux__)
|
||||
#define LINUX 1
|
||||
|
@ -79,6 +77,7 @@ using namespace Tools;
|
|||
|
||||
namespace Global {
|
||||
string banner;
|
||||
size_t banner_width = 0;
|
||||
|
||||
fs::path self_path;
|
||||
|
||||
|
@ -113,35 +112,6 @@ void argumentParser(int argc, char **argv){
|
|||
}
|
||||
}
|
||||
|
||||
//* Generate the btop++ banner
|
||||
string createBanner(){
|
||||
size_t z = 0;
|
||||
string b_color, bg, fg, out, oc, letter;
|
||||
bool truecolor = Config::getB("truecolor");
|
||||
int bg_i;
|
||||
for (auto line: Global::Banner_src) {
|
||||
fg = Theme::hex_to_color(line[0], !truecolor);
|
||||
bg_i = 120-z*12;
|
||||
bg = Theme::dec_to_color(bg_i, bg_i, bg_i, !truecolor);
|
||||
for (size_t i = 0; i < line[1].size(); i += 3) {
|
||||
if (line[1][i] == ' '){
|
||||
letter = ' ';
|
||||
i -= 2;
|
||||
} else{
|
||||
letter = line[1].substr(i, 3);
|
||||
}
|
||||
b_color = (letter == "█") ? fg : bg;
|
||||
if (b_color != oc) out += b_color;
|
||||
out += letter;
|
||||
oc = b_color;
|
||||
}
|
||||
if (++z < Global::Banner_src.size()) out += Mv::l(ulen(line[1])) + Mv::d(1);
|
||||
}
|
||||
out += Mv::r(18 - Global::Version.size()) + Fx::i + Theme::dec_to_color(0,0,0, !truecolor, "bg") +
|
||||
Theme::dec_to_color(150, 150, 150, !truecolor) + "v" + Global::Version + Fx::ui;
|
||||
return out;
|
||||
}
|
||||
|
||||
void clean_quit(int signal){
|
||||
if (Global::quitting) return;
|
||||
if (Term::initialized) {
|
||||
|
@ -155,15 +125,46 @@ void clean_quit(int signal){
|
|||
|
||||
void _exit_handler() { clean_quit(-1); }
|
||||
|
||||
//* Threading test function
|
||||
string my_worker(int x){
|
||||
for (int i = 0; i < 100 + (x * 100); i++){
|
||||
sleep_ms(10);
|
||||
if (Global::stop_all.load()) return "Thread stopped! x=" + to_string(x);
|
||||
//? Generate the btop++ banner
|
||||
void banner_gen() {
|
||||
size_t z = 0, w = 0;
|
||||
string b_color, bg, fg, oc, letter;
|
||||
bool truecolor = Config::getB("truecolor");
|
||||
int bg_i;
|
||||
Global::banner.clear();
|
||||
Global::banner_width = 0;
|
||||
for (auto line: Global::Banner_src) {
|
||||
if ( (w = ulen(line[1])) > Global::banner_width) Global::banner_width = w;
|
||||
fg = Theme::hex_to_color(line[0], !truecolor);
|
||||
bg_i = 120-z*12;
|
||||
bg = Theme::dec_to_color(bg_i, bg_i, bg_i, !truecolor);
|
||||
for (size_t i = 0; i < line[1].size(); i += 3) {
|
||||
if (line[1][i] == ' '){
|
||||
letter = ' ';
|
||||
i -= 2;
|
||||
} else{
|
||||
letter = line[1].substr(i, 3);
|
||||
}
|
||||
b_color = (letter == "█") ? fg : bg;
|
||||
if (b_color != oc) Global::banner += b_color;
|
||||
Global::banner += letter;
|
||||
oc = b_color;
|
||||
}
|
||||
if (++z < Global::Banner_src.size()) Global::banner += Mv::l(ulen(line[1])) + Mv::d(1);
|
||||
}
|
||||
return "Thread done! x=" + to_string(x);
|
||||
Global::banner += Mv::r(18 - Global::Version.size()) + Fx::i + Theme::dec_to_color(0,0,0, !truecolor, "bg") +
|
||||
Theme::dec_to_color(150, 150, 150, !truecolor) + "v" + Global::Version + Fx::ui;
|
||||
}
|
||||
|
||||
//* Threading test function
|
||||
// string my_worker(int x){
|
||||
// for (int i = 0; i < 100 + (x * 100); i++){
|
||||
// sleep_ms(10);
|
||||
// if (Global::stop_all.load()) return "Thread stopped! x=" + to_string(x);
|
||||
// }
|
||||
// return "Thread done! x=" + to_string(x);
|
||||
// }
|
||||
|
||||
|
||||
//? --------------------------------------------- Main starts here! ---------------------------------------------------
|
||||
int main(int argc, char **argv){
|
||||
|
@ -254,7 +255,7 @@ int main(int argc, char **argv){
|
|||
Theme::set(Theme::Default_theme);
|
||||
|
||||
//? Create the btop++ banner
|
||||
Global::banner = createBanner();
|
||||
banner_gen();
|
||||
|
||||
|
||||
//* ------------------------------------------------ TESTING ------------------------------------------------------
|
||||
|
@ -263,7 +264,7 @@ int main(int argc, char **argv){
|
|||
Global::debuginit = true;
|
||||
|
||||
// cout << Theme("main_bg") << Term::clear << flush;
|
||||
bool thread_test = false;
|
||||
// bool thread_test = false;
|
||||
|
||||
if (!Global::debuginit) cout << Term::alt_screen << Term::hide_cursor << flush;
|
||||
|
||||
|
@ -343,53 +344,53 @@ int main(int argc, char **argv){
|
|||
for (long long i = 100; i >= 0; i--) mydata.push_back(i);
|
||||
// mydata.push_back(0);
|
||||
// mydata.push_back(0);
|
||||
// mydata.push_back(50);
|
||||
mydata.push_back(50);
|
||||
|
||||
|
||||
// for (long long i = 0; i <= 100; i++) mydata.push_back(i);
|
||||
// for (long long i = 100; i >= 0; i--) mydata.push_back(i);
|
||||
|
||||
Draw::Graph kgraph {};
|
||||
Draw::Meter kmeter {};
|
||||
Draw::Graph kgraph2 {};
|
||||
Draw::Graph kgraph3 {};
|
||||
cout << Draw::createBox({.x = 5, .y = 10, .width = Term::width - 10, .height = 12, .line_color = Theme::c("proc_box"), .title = "graph", .fill = false, .num = 7}) << Mv::save << flush;
|
||||
// Draw::Meter kmeter {};
|
||||
// Draw::Graph kgraph2 {};
|
||||
// Draw::Graph kgraph3 {};
|
||||
|
||||
auto kts = time_micros();
|
||||
kgraph(Term::width, 10, "process", mydata, false, false);
|
||||
kmeter(Term::width, "process");
|
||||
kgraph(Term::width - 12, 10, "cpu", mydata, false, false);
|
||||
// kmeter(Term::width - 12, "process");
|
||||
// cout << Mv::save << kgraph(mydata) << "\n\nInit took " << time_micros() - kts << " μs. " << endl;
|
||||
|
||||
// exit(0);
|
||||
kgraph2(Term::width, 10, "process", mydata, true, false);
|
||||
kgraph3(Term::width, 1, "process", mydata, false, false);
|
||||
// kgraph2(Term::width, 10, "process", mydata, true, false);
|
||||
// kgraph3(Term::width, 1, "process", mydata, false, false);
|
||||
// cout << kgraph() << endl;
|
||||
// cout << kgraph2() << endl;
|
||||
// exit(0);
|
||||
|
||||
// cout << Mv::save << kgraph(mydata) << "\n" << kmeter(mydata.back()) << "\n\nInit took " << time_micros() - kts << " μs. " << endl;
|
||||
cout << Mv::save << kgraph(mydata, true) << "\n" << kgraph2(mydata, true) << "\n" << kgraph3(mydata, true) << "\n" << kmeter(mydata.back()) << "\n\nInit took " << time_micros() - kts << " μs. " << endl;
|
||||
cout << Mv::restore << kgraph(mydata, true) << "\n\n" << Mv::d(1) << "Init took " << time_micros() - kts << " μs. " << endl;
|
||||
// cout << Mv::save << kgraph(mydata, true) << "\n" << kgraph2(mydata, true) << "\n" << kgraph3(mydata, true) << "\n" << kmeter(mydata.back()) << "\n\nInit took " << time_micros() - kts << " μs. " << endl;
|
||||
// sleep_ms(1000);
|
||||
// mydata.push_back(50);
|
||||
// cout << Mv::restore << kgraph(mydata) << "\n" << kgraph2(mydata) << "\n\nInit took " << time_micros() - kts << " μs. " << endl;
|
||||
// exit(0);
|
||||
|
||||
// int x = 0q;
|
||||
long long y = 0;
|
||||
bool flip = false;
|
||||
// long long y = 0;
|
||||
// bool flip = false;
|
||||
list<uint64_t> ktavg;
|
||||
while (true) {
|
||||
// mydata.back() = std::rand() % 101;
|
||||
mydata.back() = y;
|
||||
mydata.back() = std::rand() % 101;
|
||||
// mydata.back() = y;
|
||||
kts = time_micros();
|
||||
// cout << Mv::restore << " "s * Term::width << "\n" << " "s * Term::width << endl;
|
||||
// cout << Mv::restore << kgraph(mydata) << "\n" << kmeter(mydata.back()) << endl;
|
||||
cout << Mv::restore << kgraph(mydata) << "\n" << kgraph2(mydata) << "\n" << " "s * Term::width << Mv::l(Term::width) << kgraph3(mydata) << "\n" << kmeter(mydata.back()) << endl;
|
||||
cout << Mv::restore << kgraph(mydata) << endl;
|
||||
// cout << Mv::restore << kgraph(mydata) << "\n" << kgraph2(mydata) << "\n" << " "s * Term::width << Mv::l(Term::width) << kgraph3(mydata) << "\n" << kmeter(mydata.back()) << endl;
|
||||
ktavg.push_front(time_micros() - kts);
|
||||
if (ktavg.size() > 100) ktavg.pop_back();
|
||||
cout << "Time: " << ktavg.front() << " μs. Avg: " << accumulate(ktavg.begin(), ktavg.end(), 0) / ktavg.size() << " μs. " << flush;
|
||||
if (flip) y--;
|
||||
else y++;
|
||||
if (y == 100 || y == 0) flip = !flip;
|
||||
cout << Mv::d(1) << "Time: " << ktavg.front() << " μs. Avg: " << accumulate(ktavg.begin(), ktavg.end(), 0) / ktavg.size() << " μs. " << flush;
|
||||
// if (flip) y--;
|
||||
// else y++;
|
||||
// if (y == 100 || y == 0) flip = !flip;
|
||||
if (Input::poll()) {
|
||||
if (Input::get() == "space") Input::wait(true);
|
||||
else break;
|
||||
|
@ -403,28 +404,28 @@ int main(int argc, char **argv){
|
|||
}
|
||||
|
||||
|
||||
if (thread_test){
|
||||
// if (thread_test){
|
||||
|
||||
unordered_flat_map<int, future<string>> runners;
|
||||
unordered_flat_map<int, string> outputs;
|
||||
// unordered_flat_map<int, future<string>> runners;
|
||||
// unordered_flat_map<int, string> outputs;
|
||||
|
||||
for (int i : iota(0, 10)){
|
||||
runners[i] = async(my_worker, i);
|
||||
}
|
||||
// uint i = 0;
|
||||
while (outputs.size() < 10){
|
||||
// for (int i : iota(0, 10)){
|
||||
// runners[i] = async(my_worker, i);
|
||||
// }
|
||||
// // uint i = 0;
|
||||
// while (outputs.size() < 10){
|
||||
|
||||
for (int i : iota(0, 10)){
|
||||
if (runners[i].valid() && runners[i].wait_for(std::chrono::milliseconds(10)) == future_status::ready) {
|
||||
outputs[i] = runners[i].get();
|
||||
cout << "Thread " << i << " : " << outputs[i] << endl;
|
||||
}
|
||||
}
|
||||
// for (int i : iota(0, 10)){
|
||||
// if (runners[i].valid() && runners[i].wait_for(std::chrono::milliseconds(10)) == future_status::ready) {
|
||||
// outputs[i] = runners[i].get();
|
||||
// cout << "Thread " << i << " : " << outputs[i] << endl;
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (++i >= 10) i = 0;
|
||||
if (outputs.size() >= 8) Global::stop_all.store(true);
|
||||
}
|
||||
}
|
||||
// // if (++i >= 10) i = 0;
|
||||
// if (outputs.size() >= 8) Global::stop_all.store(true);
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -71,6 +71,8 @@ namespace Symbols {
|
|||
|
||||
namespace Draw {
|
||||
|
||||
using namespace Tools;
|
||||
|
||||
struct BoxConf {
|
||||
uint x=0, y=0;
|
||||
uint width=0, height=0;
|
||||
|
@ -101,9 +103,9 @@ namespace Draw {
|
|||
|
||||
//* Draw corners
|
||||
out += Mv::to(c.y, c.x) + Symbols::left_up +
|
||||
Mv::to(c.y, c.x + c.width) + Symbols::right_up +
|
||||
Mv::to(c.y, c.x + c.width - 1) + Symbols::right_up +
|
||||
Mv::to(c.y + c.height - 1, c.x) + Symbols::left_down +
|
||||
Mv::to(c.y + c.height - 1, c.x + c.width) + Symbols::right_down;
|
||||
Mv::to(c.y + c.height - 1, c.x + c.width - 1) + Symbols::right_down;
|
||||
|
||||
//* Draw titles if defined
|
||||
if (!c.title.empty()){
|
||||
|
@ -115,12 +117,12 @@ namespace Draw {
|
|||
Fx::ub + lcolor + Symbols::title_right;
|
||||
}
|
||||
|
||||
return out + Fx::reset + Mv::to(c.y + 1, c.x + 2);
|
||||
return out + Fx::reset + Mv::to(c.y + 1, c.x + 1);
|
||||
}
|
||||
|
||||
//* Class holding a percentage meter
|
||||
class Meter {
|
||||
string out, color_gradient;
|
||||
string color_gradient;
|
||||
int width = 0;
|
||||
bool invert = false;
|
||||
vector<string> cache;
|
||||
|
@ -130,20 +132,18 @@ namespace Draw {
|
|||
this->width = width;
|
||||
this->color_gradient = color_gradient;
|
||||
this->invert = invert;
|
||||
out.clear();
|
||||
cache.clear();
|
||||
cache.insert(cache.begin(), 101, "");
|
||||
}
|
||||
|
||||
//* Return a string representation of the meter with given value
|
||||
string operator()(int value) {
|
||||
if (width < 1) return out;
|
||||
if (width < 1) return "";
|
||||
value = clamp(value, 0, 100);
|
||||
if (!cache.at(value).empty()) return out = cache.at(value);
|
||||
out.clear();
|
||||
int y;
|
||||
if (!cache.at(value).empty()) return cache.at(value);
|
||||
string& out = cache.at(value);
|
||||
for (int i : iota(1, width + 1)) {
|
||||
y = round((double)i * 100.0 / width);
|
||||
int y = round((double)i * 100.0 / width);
|
||||
if (value >= y)
|
||||
out += Theme::g(color_gradient)[invert ? 100 - y : y] + Symbols::meter;
|
||||
else {
|
||||
|
@ -152,28 +152,25 @@ namespace Draw {
|
|||
}
|
||||
}
|
||||
out += Fx::reset;
|
||||
return cache.at(value) = out;
|
||||
}
|
||||
|
||||
string operator()() {
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
//* Class holding a graph
|
||||
class Graph {
|
||||
string out, color_gradient;
|
||||
int width = 0, height = 0, lowest = 0;
|
||||
int width = 0, height = 0;
|
||||
long long last = 0, max_value = 0, offset = 0;
|
||||
bool current = true, no_zero = false, invert = false;
|
||||
unordered_flat_map<bool, vector<string>> graphs = { {true, {}}, {false, {}}};
|
||||
vector<string> graph_symbol;
|
||||
|
||||
//* Create two representations of the graph to switch between to represent two values for each braille character
|
||||
void _create(const vector<long long>& data, int data_offset) {
|
||||
const bool mult = (data.size() - data_offset > 1);
|
||||
if (mult && (data.size() - data_offset) % 2 != 0) data_offset--;
|
||||
auto& graph_symbol = (invert) ? Symbols::graph_down : Symbols::graph_up;
|
||||
array<int, 2> result;
|
||||
const float mod = (height == 1) ? 0.3 : 0.1;
|
||||
long long data_value = 0;
|
||||
|
@ -183,10 +180,10 @@ namespace Draw {
|
|||
}
|
||||
|
||||
//? Horizontal iteration over values in <data>
|
||||
for (int i = data_offset; i < (int)data.size(); i++) {
|
||||
for (int i : iota(data_offset, (int)data.size())) {
|
||||
current = !current;
|
||||
if (i == -1) { data_value = 0; last = 0; }
|
||||
else data_value = data[i];
|
||||
if (mult) current = !current;
|
||||
if (max_value > 0) data_value = clamp((data_value + offset) * 100 / max_value, 0ll, 100ll);
|
||||
//? Vertical iteration over height of graph
|
||||
for (int horizon : iota(0, height)){
|
||||
|
@ -197,7 +194,7 @@ namespace Draw {
|
|||
for (auto value : {last, data_value}) {
|
||||
if (value >= cur_high)
|
||||
result[ai] = 4;
|
||||
else if (value < cur_low)
|
||||
else if (value <= cur_low)
|
||||
result[ai] = 0;
|
||||
else {
|
||||
result[ai] = round((float)(value - cur_low) * 4 / (cur_high - cur_low) + mod);
|
||||
|
@ -233,40 +230,34 @@ namespace Draw {
|
|||
this->invert = invert; this->offset = offset;
|
||||
this->no_zero = no_zero; this->max_value = max_value;
|
||||
this->color_gradient = color_gradient;
|
||||
// if (height == 1) graph_symbol = (invert) ? Symbols::graph_down_small : Symbols::graph_up_small;
|
||||
graph_symbol = (invert) ? Symbols::graph_down : Symbols::graph_up;
|
||||
if (no_zero) lowest = 1;
|
||||
// current = true;
|
||||
int value_width = ceil((float)data.size() / 2);
|
||||
int data_offset = 0;
|
||||
if (value_width > width) data_offset = data.size() - width * 2;
|
||||
|
||||
//? Populate the two switching graph vectors and fill empty space if width > data size
|
||||
for (int i : iota(0, height)) {
|
||||
(void) i;
|
||||
graphs[true].push_back((value_width < width) ? graph_symbol[0.0] * (width - value_width) : "");
|
||||
graphs[false].push_back((value_width < width) ? graph_symbol[0.0] * (width - value_width) : "");
|
||||
//? Populate the two switching graph vectors and fill empty space if data size < width
|
||||
auto& graph_symbol = (invert) ? Symbols::graph_down : Symbols::graph_up;
|
||||
for (int i : iota(0, height * 2)) {
|
||||
graphs[(i % 2 != 0)].push_back((value_width < width) ? ((height == 1) ? Mv::r(1) : graph_symbol[0]) * (width - value_width) : "");
|
||||
}
|
||||
if (data.size() == 0) return;
|
||||
this->_create(data, data_offset);
|
||||
}
|
||||
|
||||
//* Add last value from back of <data> and return string representation of graph
|
||||
string operator()(const vector<long long>& data, bool data_same = false) {
|
||||
string& operator()(const vector<long long>& data, bool data_same = false) {
|
||||
if (data_same) return out;
|
||||
current = !current;
|
||||
|
||||
//? Make room for new characters on graph
|
||||
for (int i : iota(0, height)) {
|
||||
if (graphs[current][i].starts_with(Fx::e)) graphs[current][i].erase(0, 4);
|
||||
else graphs[current][i].erase(0, 3);
|
||||
if (graphs[(!current)][i].starts_with(Fx::e)) graphs[current][i].erase(0, 4);
|
||||
else graphs[(!current)][i].erase(0, 3);
|
||||
}
|
||||
this->_create(data, (int)data.size() - 1);
|
||||
return out;
|
||||
}
|
||||
|
||||
//* Return string representation of graph
|
||||
string operator()() {
|
||||
string& operator()() {
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -81,11 +81,10 @@ namespace Input {
|
|||
//* Poll keyboard & mouse input for <timeout> ms and return input availabilty as a bool
|
||||
bool poll(int timeout=0){
|
||||
if (timeout < 1) return cin.rdbuf()->in_avail() > 0;
|
||||
auto timer = 0;
|
||||
while (timer * 10 <= timeout) {
|
||||
int timer = 0;
|
||||
while (timer++ * 10 <= timeout) {
|
||||
if (cin.rdbuf()->in_avail() > 0) return true;
|
||||
sleep_ms(10);
|
||||
++timer;
|
||||
sleep_ms( (timer * 10 <= timeout) ? 10 : timeout % 10);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -36,7 +36,6 @@ tab-size = 4
|
|||
#include <unistd.h>
|
||||
|
||||
#include <btop_config.h>
|
||||
#include <btop_globs.h>
|
||||
#include <btop_tools.h>
|
||||
|
||||
|
||||
|
|
|
@ -16,8 +16,8 @@ indent = tab
|
|||
tab-size = 4
|
||||
*/
|
||||
|
||||
#ifndef _btop_globs_included_
|
||||
#define _btop_globs_included_ 1
|
||||
#ifndef _btop_menu_included_
|
||||
#define _btop_menu_included_ 1
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
@ -27,11 +27,9 @@ tab-size = 4
|
|||
|
||||
using std::string, std::vector, std::unordered_map, std::array, std::atomic, robin_hood::unordered_flat_map;
|
||||
|
||||
namespace Global {
|
||||
|
||||
atomic<bool> stop_all(false);
|
||||
|
||||
namespace Menu {
|
||||
|
||||
atomic<bool> active(false);
|
||||
|
||||
const unordered_flat_map<string, unordered_map<string, vector<string>>> Menus = {
|
||||
{ "options", {
|
|
@ -27,7 +27,6 @@ tab-size = 4
|
|||
#include <ranges>
|
||||
#include <algorithm>
|
||||
|
||||
#include <btop_globs.h>
|
||||
#include <btop_tools.h>
|
||||
#include <btop_config.h>
|
||||
|
||||
|
|
|
@ -38,9 +38,7 @@ tab-size = 4
|
|||
#include <termios.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <btop_globs.h>
|
||||
|
||||
using std::string, std::vector, std::regex, std::max, std::to_string, std::cin, std::atomic, robin_hood::unordered_flat_map;
|
||||
using std::string, std::vector, std::array, std::regex, std::max, std::to_string, std::cin, std::atomic, robin_hood::unordered_flat_map;
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
//? ------------------------------------------------- NAMESPACES ------------------------------------------------------
|
||||
|
@ -95,19 +93,19 @@ namespace Fx {
|
|||
//* Collection of escape codes and functions for cursor manipulation
|
||||
namespace Mv {
|
||||
//* Move cursor to <line>, <column>
|
||||
inline string to(int line, int col){ return Fx::e + to_string(line) + ";" + to_string(col) + "f";}
|
||||
const string to(int line, int col){ return Fx::e + to_string(line) + ";" + to_string(col) + "f";}
|
||||
|
||||
//* Move cursor right <x> columns
|
||||
inline string r(int x){ return Fx::e + to_string(x) + "C";}
|
||||
const string r(int x){ return Fx::e + to_string(x) + "C";}
|
||||
|
||||
//* Move cursor left <x> columns
|
||||
inline string l(int x){ return Fx::e + to_string(x) + "D";}
|
||||
const string l(int x){ return Fx::e + to_string(x) + "D";}
|
||||
|
||||
//* Move cursor up x lines
|
||||
inline string u(int x){ return Fx::e + to_string(x) + "A";}
|
||||
const string u(int x){ return Fx::e + to_string(x) + "A";}
|
||||
|
||||
//* Move cursor down x lines
|
||||
inline string d(int x) { return Fx::e + to_string(x) + "B";}
|
||||
const string d(int x) { return Fx::e + to_string(x) + "B";}
|
||||
|
||||
//* Save cursor position
|
||||
const string save = Fx::e + "s";
|
||||
|
@ -229,51 +227,51 @@ namespace Term {
|
|||
namespace Tools {
|
||||
|
||||
//* Return number of UTF8 characters in a string with option to disregard escape sequences
|
||||
inline size_t ulen(string s, bool escape=false){
|
||||
size_t ulen(string s, bool escape=false){
|
||||
if (escape) s = std::regex_replace(s, Fx::escape_regex, "");
|
||||
return std::count_if(s.begin(), s.end(),
|
||||
[](char c) { return (static_cast<unsigned char>(c) & 0xC0) != 0x80; } );
|
||||
}
|
||||
|
||||
//* Return current time since epoch in seconds
|
||||
inline uint64_t time_s(){
|
||||
uint64_t time_s(){
|
||||
return std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()).count();
|
||||
}
|
||||
|
||||
//* Return current time since epoch in milliseconds
|
||||
inline uint64_t time_ms(){
|
||||
uint64_t time_ms(){
|
||||
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
|
||||
}
|
||||
|
||||
//* Return current time since epoch in milliseconds
|
||||
inline uint64_t time_micros(){
|
||||
//* Return current time since epoch in microseconds
|
||||
uint64_t time_micros(){
|
||||
return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
|
||||
}
|
||||
|
||||
//* Check if a string is a valid bool value
|
||||
inline bool isbool(string& str){
|
||||
bool isbool(string& str){
|
||||
return (str == "true") || (str == "false") || (str == "True") || (str == "False");
|
||||
}
|
||||
|
||||
//* Check if a string is a valid integer value
|
||||
inline bool isint(string& str){
|
||||
bool isint(string& str){
|
||||
return all_of(str.begin(), str.end(), ::isdigit);
|
||||
}
|
||||
|
||||
//* Left-trim <t_str> from <str> and return string
|
||||
inline string ltrim(string str, string t_str = " "){
|
||||
string ltrim(string str, string t_str = " "){
|
||||
while (str.starts_with(t_str)) str.erase(0, t_str.size());
|
||||
return str;
|
||||
}
|
||||
|
||||
//* Right-trim <t_str> from <str> and return string
|
||||
inline string rtrim(string str, string t_str = " "){
|
||||
string rtrim(string str, string t_str = " "){
|
||||
while (str.ends_with(t_str)) str.resize(str.size() - t_str.size());
|
||||
return str;
|
||||
}
|
||||
|
||||
//* Left-right-trim <t_str> from <str> and return string
|
||||
inline string trim(string str, string t_str = " "){
|
||||
string trim(string str, string t_str = " "){
|
||||
return ltrim(rtrim(str, t_str), t_str);
|
||||
}
|
||||
|
||||
|
@ -452,8 +450,6 @@ namespace Tools {
|
|||
namespace Logger {
|
||||
namespace {
|
||||
std::atomic<bool> busy (false);
|
||||
fs::path logfile;
|
||||
uint loglevel = 2;
|
||||
bool first = true;
|
||||
string tdf = "%Y/%m/%d (%T) | ";
|
||||
unordered_flat_map<uint, string> log_levels = {
|
||||
|
@ -465,19 +461,25 @@ namespace Logger {
|
|||
};
|
||||
}
|
||||
|
||||
fs::path logfile;
|
||||
uint loglevel = 2;
|
||||
|
||||
void log_write(uint level, string& msg){
|
||||
if (logfile.empty() || loglevel < level) return;
|
||||
if (loglevel < level || logfile.empty()) return;
|
||||
busy.wait(true); busy.store(true);
|
||||
if (fs::exists(logfile) && fs::file_size(logfile) > 1024 << 10) {
|
||||
std::error_code ec;
|
||||
if (fs::file_size(logfile, ec) > 1024 << 10) {
|
||||
auto old_log = logfile;
|
||||
old_log += ".1";
|
||||
if (fs::exists(old_log)) fs::remove(old_log);
|
||||
fs::rename(logfile, old_log);
|
||||
if (fs::exists(old_log)) fs::remove(old_log, ec);
|
||||
fs::rename(logfile, old_log, ec);
|
||||
}
|
||||
if (!ec) {
|
||||
std::ofstream lwrite(logfile, std::ios::app);
|
||||
if (first) { first = false; lwrite << "\n" << Tools::strf_time(tdf) << "===> btop++ v." << Global::Version << "\n";}
|
||||
lwrite << Tools::strf_time(tdf) << log_levels[level] << ": " << msg << "\n";
|
||||
lwrite.close();
|
||||
}
|
||||
std::ofstream lwrite(logfile, std::ios::app);
|
||||
if (first) { first = false; lwrite << "\n" << Tools::strf_time(tdf) << "===> btop++ v." << Global::Version << "\n";}
|
||||
lwrite << Tools::strf_time(tdf) << log_levels[level] << ": " << msg << "\n";
|
||||
lwrite.close();
|
||||
busy.store(false);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue