mirror of
https://github.com/aristocratos/btop.git
synced 2024-05-18 19:33:03 +12:00
Proc optimization
This commit is contained in:
parent
881b90f4f3
commit
81f2284a75
31
btop.cpp
31
btop.cpp
|
@ -26,6 +26,8 @@ tab-size = 4
|
|||
#include <atomic>
|
||||
#include <numeric>
|
||||
#include <ranges>
|
||||
#include <filesystem>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <btop_globs.h>
|
||||
#include <btop_tools.h>
|
||||
|
@ -56,6 +58,7 @@ tab-size = 4
|
|||
|
||||
using std::string, std::vector, std::array, std::map, std::atomic, std::endl, std::cout, std::views::iota, std::list, std::accumulate;
|
||||
using std::flush, std::endl, std::future, std::string_literals::operator""s, std::future_status;
|
||||
namespace fs = std::filesystem;
|
||||
using namespace Tools;
|
||||
|
||||
|
||||
|
@ -151,9 +154,9 @@ int main(int argc, char **argv){
|
|||
|
||||
#if defined(LINUX)
|
||||
//? Linux init
|
||||
Global::proc_path = (fs::is_directory(fs::path("/proc"))) ? fs::path("/proc") : Global::proc_path;
|
||||
Global::proc_path = (fs::is_directory(fs::path("/proc")) && access("/proc", R_OK) != -1) ? fs::path("/proc") : Global::proc_path;
|
||||
if (Global::proc_path.empty()) {
|
||||
cout << "ERROR: Proc filesystem not detected!" << endl;
|
||||
cout << "ERROR: Proc filesystem not found/readable!" << endl;
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
@ -161,7 +164,7 @@ int main(int argc, char **argv){
|
|||
//? Initialize terminal and set options
|
||||
if (!Term::init()) {
|
||||
cout << "ERROR: No tty detected!" << endl;
|
||||
cout << "Sorry, btop++ needs an interactive shell to run." << endl;
|
||||
cout << "btop++ needs an interactive shell to run." << endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
@ -171,7 +174,7 @@ int main(int argc, char **argv){
|
|||
auto thts = time_ms();
|
||||
|
||||
//? Generate the theme
|
||||
Theme::set(Global::Default_theme);
|
||||
Theme::set(Theme::Default_theme);
|
||||
|
||||
//? Create the btop++ banner
|
||||
Global::banner = createBanner();
|
||||
|
@ -233,7 +236,6 @@ int main(int argc, char **argv){
|
|||
}
|
||||
|
||||
|
||||
|
||||
if (thread_test){
|
||||
|
||||
map<int, future<string>> runners;
|
||||
|
@ -263,26 +265,17 @@ int main(int argc, char **argv){
|
|||
|
||||
|
||||
|
||||
//------>>>>>>
|
||||
//*------>>>>>> Proc testing
|
||||
|
||||
|
||||
auto timestamp = time_ms();
|
||||
Proc::init();
|
||||
|
||||
cout << "Total Processes init: " << time_ms() - timestamp << "ms" << endl;
|
||||
cout << "Press any key to start!" << Mv::l(100) << flush;
|
||||
|
||||
// sleep_ms(1000);
|
||||
// Input::wait();
|
||||
// Input::clear();
|
||||
|
||||
|
||||
// insert Processes call here
|
||||
|
||||
|
||||
uint lc;
|
||||
string ostring;
|
||||
uint64_t tsl, timestamp2;
|
||||
uint64_t tsl, timestamp2, rcount = 0;
|
||||
list<uint64_t> avgtimes;
|
||||
uint timer = 1000;
|
||||
bool filtering = false;
|
||||
|
@ -326,8 +319,8 @@ int main(int argc, char **argv){
|
|||
avgtimes.push_front(timestamp);
|
||||
if (avgtimes.size() > 100) avgtimes.pop_back();
|
||||
cout << pbox << ostring << Fx::reset << "\n" << endl;
|
||||
cout << Mv::to(Term::height - 4, 1) << "Processes call took: " << timestamp << "ms. Average: " << accumulate(avgtimes.begin(), avgtimes.end(), 0) / avgtimes.size() <<
|
||||
"ms of " << avgtimes.size() << " samples. Drawing took: " << time_ms() - timestamp2 << "ms. " << endl;
|
||||
cout << Mv::to(Term::height - 4, 1) << "Processes call took: " << rjust(to_string(timestamp), 4) << "ms. Average: " << rjust(to_string(accumulate(avgtimes.begin(), avgtimes.end(), 0) / avgtimes.size()), 3) <<
|
||||
"ms of " << avgtimes.size() << " samples. Drawing took: " << time_ms() - timestamp2 << "ms. Number of processes: " << Proc::numpids << ". Run count: " << ++rcount << " " << endl;
|
||||
|
||||
while (time_ms() < tsl) {
|
||||
if (Input::poll(tsl - time_ms())) key = Input::get();
|
||||
|
@ -353,7 +346,7 @@ int main(int argc, char **argv){
|
|||
|
||||
// cout << "Found " << plist.size() << " pids\n" << endl;
|
||||
|
||||
//-----<<<<<
|
||||
//*-----<<<<<
|
||||
|
||||
//cout << pw->pw_name << "/" << gr->gr_name << endl;
|
||||
|
||||
|
|
|
@ -23,7 +23,6 @@ tab-size = 4
|
|||
#include <map>
|
||||
#include <ranges>
|
||||
|
||||
#include <btop_globs.h>
|
||||
#include <btop_config.h>
|
||||
#include <btop_tools.h>
|
||||
|
||||
|
|
|
@ -31,50 +31,7 @@ namespace Global {
|
|||
|
||||
atomic<bool> stop_all(false);
|
||||
|
||||
const unordered_map<string, string> Default_theme = {
|
||||
{ "main_bg", "#00" },
|
||||
{ "main_fg", "#cc" },
|
||||
{ "title", "#ee" },
|
||||
{ "hi_fg", "#969696" },
|
||||
{ "selected_bg", "#7e2626" },
|
||||
{ "selected_fg", "#ee" },
|
||||
{ "inactive_fg", "#40" },
|
||||
{ "graph_text", "#60" },
|
||||
{ "meter_bg", "#40" },
|
||||
{ "proc_misc", "#0de756" },
|
||||
{ "cpu_box", "#3d7b46" },
|
||||
{ "mem_box", "#8a882e" },
|
||||
{ "net_box", "#423ba5" },
|
||||
{ "proc_box", "#923535" },
|
||||
{ "div_line", "#30" },
|
||||
{ "temp_start", "#4897d4" },
|
||||
{ "temp_mid", "#5474e8" },
|
||||
{ "temp_end", "#ff40b6" },
|
||||
{ "cpu_start", "#50f095" },
|
||||
{ "cpu_mid", "#f2e266" },
|
||||
{ "cpu_end", "#fa1e1e" },
|
||||
{ "free_start", "#223014" },
|
||||
{ "free_mid", "#b5e685" },
|
||||
{ "free_end", "#dcff85" },
|
||||
{ "cached_start", "#0b1a29" },
|
||||
{ "cached_mid", "#74e6fc" },
|
||||
{ "cached_end", "#26c5ff" },
|
||||
{ "available_start", "#292107" },
|
||||
{ "available_mid", "#ffd77a" },
|
||||
{ "available_end", "#ffb814" },
|
||||
{ "used_start", "#3b1f1c" },
|
||||
{ "used_mid", "#d9626d" },
|
||||
{ "used_end", "#ff4769" },
|
||||
{ "download_start", "#231a63" },
|
||||
{ "download_mid", "#4f43a3" },
|
||||
{ "download_end", "#b0a9de" },
|
||||
{ "upload_start", "#510554" },
|
||||
{ "upload_mid", "#7d4180" },
|
||||
{ "upload_end", "#dcafde" },
|
||||
{ "process_start", "#80d0a3" },
|
||||
{ "process_mid", "#dcd179" },
|
||||
{ "process_end", "#d45454" }
|
||||
};
|
||||
|
||||
|
||||
const unordered_map<string, unordered_map<string, vector<string>>> Menus = {
|
||||
{ "options", {
|
||||
|
@ -115,25 +72,10 @@ namespace Global {
|
|||
} }
|
||||
};
|
||||
|
||||
//? Units for floating_humanizer function
|
||||
const array<string, 11> Units_bit = {"bit", "Kib", "Mib", "Gib", "Tib", "Pib", "Eib", "Zib", "Yib", "Bib", "GEb"};
|
||||
const array<string, 11> Units_byte = {"Byte", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB", "BiB", "GEB"};
|
||||
|
||||
|
||||
}
|
||||
|
||||
namespace Symbols {
|
||||
const string h_line = "─";
|
||||
const string v_line = "│";
|
||||
const string left_up = "┌";
|
||||
const string right_up = "┐";
|
||||
const string left_down = "└";
|
||||
const string right_down = "┘";
|
||||
const string title_left = "┤";
|
||||
const string title_right = "├";
|
||||
const string div_up = "┬";
|
||||
const string div_down = "┴";
|
||||
|
||||
const array<string, 10> superscript = { "⁰", "¹", "²", "³", "⁴", "⁵", "⁶", "⁷", "⁸", "⁹" };
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -23,12 +23,16 @@ tab-size = 4
|
|||
#include <unordered_map>
|
||||
#include <iostream>
|
||||
|
||||
#include <btop_globs.h>
|
||||
#include <btop_tools.h>
|
||||
|
||||
using std::string, std::unordered_map, std::cin;
|
||||
using namespace Tools;
|
||||
|
||||
/* The input functions relies on the following std::cin options being set:
|
||||
cin.sync_with_stdio(false);
|
||||
cin.tie(NULL);
|
||||
These will automatically be set when running Term::init() from btop_tools.h
|
||||
*/
|
||||
|
||||
//* Functions and variables for handling keyboard and mouse input
|
||||
namespace Input {
|
||||
|
|
183
src/btop_linux.h
183
src/btop_linux.h
|
@ -30,7 +30,6 @@ tab-size = 4
|
|||
#include <ranges>
|
||||
#include <list>
|
||||
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <btop_config.h>
|
||||
|
@ -39,12 +38,13 @@ tab-size = 4
|
|||
|
||||
|
||||
using std::string, std::vector, std::array, std::ifstream, std::atomic, std::numeric_limits, std::streamsize, std::unordered_map, std::deque, std::list;
|
||||
using std::cout, std::flush, std::endl;
|
||||
namespace fs = std::filesystem;
|
||||
using namespace Tools;
|
||||
const auto SSmax = std::numeric_limits<streamsize>::max();
|
||||
|
||||
namespace Global {
|
||||
|
||||
const string System = "linux";
|
||||
fs::path proc_path;
|
||||
|
||||
}
|
||||
|
@ -64,8 +64,6 @@ double system_uptime(){
|
|||
namespace Proc {
|
||||
namespace {
|
||||
uint64_t tstamp;
|
||||
size_t numpids = 500;
|
||||
long int clk_tck;
|
||||
struct p_cache {
|
||||
string name, cmd, user;
|
||||
uint64_t cpu_t = 0, cpu_s = 0;
|
||||
|
@ -75,10 +73,12 @@ namespace Proc {
|
|||
fs::path passwd_path;
|
||||
fs::file_time_type passwd_time;
|
||||
uint counter = 0;
|
||||
long page_size = sysconf(_SC_PAGE_SIZE);
|
||||
auto page_size = sysconf(_SC_PAGE_SIZE);
|
||||
auto clk_tck = sysconf(_SC_CLK_TCK);
|
||||
|
||||
}
|
||||
|
||||
size_t numpids = 500;
|
||||
atomic<bool> stop (false);
|
||||
atomic<bool> running (false);
|
||||
array<string, 8> sort_array = {
|
||||
|
@ -116,15 +116,13 @@ namespace Proc {
|
|||
bool new_cache;
|
||||
char state;
|
||||
int cpu_n, p_nice;
|
||||
size_t threads;
|
||||
size_t threads, s_pos, c_pos, s_count;
|
||||
ifstream pread;
|
||||
string pid_str, name, cmd, attr, user, instr, uid, status, tmpstr;
|
||||
auto since_last = time_ms() - tstamp;
|
||||
if (since_last < 1) since_last = 1;
|
||||
auto uptime = system_uptime();
|
||||
auto sortint = (sort_map.contains(sorting)) ? sort_map[sorting] : 7;
|
||||
vector<string> pstat;
|
||||
pstat.reserve(40);
|
||||
vector<proc_info> procs;
|
||||
procs.reserve((numpids + 10));
|
||||
vector<uint> c_pids;
|
||||
|
@ -136,35 +134,35 @@ namespace Proc {
|
|||
string r_uid, r_user;
|
||||
passwd_time = fs::last_write_time(passwd_path);
|
||||
uid_user.clear();
|
||||
ifstream pread(passwd_path);
|
||||
pread.open(passwd_path);
|
||||
if (pread.good()) {
|
||||
while (true){
|
||||
getline(pread, r_user, ':');
|
||||
pread.ignore(numeric_limits<streamsize>::max(), ':');
|
||||
pread.ignore(SSmax, ':');
|
||||
getline(pread, r_uid, ':');
|
||||
uid_user[r_uid] = r_user;
|
||||
pread.ignore(numeric_limits<streamsize>::max(), '\n');
|
||||
pread.ignore(SSmax, '\n');
|
||||
if (pread.eof()) break;
|
||||
}
|
||||
}
|
||||
pread.close();
|
||||
}
|
||||
|
||||
|
||||
//* Iterate over all pids in /proc and get relevant values
|
||||
for (auto& d: fs::directory_iterator(Global::proc_path)){
|
||||
if (pread.is_open()) pread.close();
|
||||
if (stop.load()) {
|
||||
procs.clear();
|
||||
running.store(false);
|
||||
stop.store(false);
|
||||
return procs;
|
||||
}
|
||||
numpids++;
|
||||
pid_str = fs::path(d.path()).filename();
|
||||
pid_str = d.path().filename();
|
||||
cpu = 0.0; cpu_s = 0.0; cpu_t = 0; cpu_n = 0;
|
||||
rss_mem = 0; threads = 0; state = '0'; ppid = 0; p_nice = 0;
|
||||
new_cache = false;
|
||||
if (d.is_directory() && isdigit(pid_str[0])) {
|
||||
numpids++;
|
||||
pid = stoul(pid_str);
|
||||
c_pids.push_back(pid);
|
||||
|
||||
|
@ -172,76 +170,106 @@ namespace Proc {
|
|||
if (!cache.contains(pid)) {
|
||||
name.clear(); cmd.clear(); user.clear();
|
||||
new_cache = true;
|
||||
if (fs::exists((string)d.path() + "/comm")) {
|
||||
pread.clear(); name.clear();
|
||||
ifstream pread((string)d.path() + "/comm");
|
||||
if (pread.good()) getline(pread, name);
|
||||
pread.open(d.path() / "comm");
|
||||
if (pread.good()) {
|
||||
getline(pread, name);
|
||||
pread.close();
|
||||
}
|
||||
if (fs::exists((string)d.path() + "/cmdline")) {
|
||||
pread.clear(); cmd.clear(); tmpstr.clear();
|
||||
ifstream pread((string)d.path() + "/cmdline");
|
||||
if (pread.good()) while(getline(pread, tmpstr, '\0')) cmd += tmpstr + " ";
|
||||
else continue;
|
||||
|
||||
pread.open(d.path() / "cmdline");
|
||||
if (pread.good()) {
|
||||
tmpstr.clear();
|
||||
while(getline(pread, tmpstr, '\0')) cmd += tmpstr + " ";
|
||||
pread.close();
|
||||
if (!cmd.empty()) cmd.pop_back();
|
||||
}
|
||||
if (fs::exists((string)d.path() + "/status")) {
|
||||
pread.clear(); status.clear(); uid.clear();
|
||||
ifstream pread((string)d.path() + "/status");
|
||||
if (pread.good()) {
|
||||
while (!pread.eof()){
|
||||
getline(pread, status, ':');
|
||||
if (status == "Uid") {
|
||||
pread.ignore();
|
||||
getline(pread, uid, '\t');
|
||||
break;
|
||||
} else {
|
||||
pread.ignore(numeric_limits<streamsize>::max(), '\n');
|
||||
}
|
||||
else continue;
|
||||
|
||||
pread.open(d.path() / "status");
|
||||
if (pread.good()) {
|
||||
status.clear(); uid.clear();
|
||||
while (!pread.eof()){
|
||||
getline(pread, status, ':');
|
||||
if (status == "Uid") {
|
||||
pread.ignore();
|
||||
getline(pread, uid, '\t');
|
||||
break;
|
||||
} else {
|
||||
pread.ignore(SSmax, '\n');
|
||||
}
|
||||
}
|
||||
pread.close();
|
||||
user = (!uid.empty() && uid_user.contains(uid)) ? uid_user.at(uid) : uid;
|
||||
}
|
||||
else continue;
|
||||
cache[pid] = p_cache(name, cmd, user);
|
||||
}
|
||||
|
||||
//* Match filter if defined
|
||||
if (!filter.empty() && pid_str.find(filter) == string::npos &&
|
||||
cache[pid].name.find(filter) == string::npos &&
|
||||
cache[pid].cmd.find(filter) == string::npos &&
|
||||
cache[pid].user.find(filter) == string::npos) {
|
||||
if (new_cache) cache.erase(pid);
|
||||
continue;
|
||||
}
|
||||
|
||||
//* Get cpu usage, cpu cumulative and threads from /proc/[pid]/stat
|
||||
if (fs::exists((string)d.path() + "/stat")) {
|
||||
pread.clear(); instr.clear(); pstat.clear();
|
||||
ifstream pread((string)d.path() + "/stat");
|
||||
if (pread.good() && getline(pread, instr)) {
|
||||
//? Skip pid and comm field and find comm fields closing ')' from right to avoid names with whitespace or parenthesis
|
||||
pstat = ssplit(instr.substr(instr.rfind(')') + 1), " ", 37, true);
|
||||
}
|
||||
pread.open(d.path() / "stat");
|
||||
if (pread.good()) {
|
||||
instr.clear(); s_pos = 0; c_pos = 0; s_count = 0;
|
||||
getline(pread, instr);
|
||||
pread.close();
|
||||
|
||||
if (pstat.size() < 20) continue;
|
||||
//? Skip pid and comm field and find comm fields closing ')' to avoid names with whitespace or parenthesis
|
||||
s_pos = instr.find_last_of(')') + 2;
|
||||
|
||||
//? Process state
|
||||
state = pstat[0][0];
|
||||
do {
|
||||
c_pos = instr.find(' ', s_pos);
|
||||
if (c_pos == string::npos) break;
|
||||
|
||||
//? Process parent pid
|
||||
ppid = stoul(pstat[1]);
|
||||
|
||||
//? Process nice value
|
||||
p_nice = stoi(pstat[16]);
|
||||
|
||||
//? Process number of threads
|
||||
threads = stoul(pstat[17]);
|
||||
|
||||
//? Process utime + stime
|
||||
cpu_t = stoull(pstat[11]) + stoull(pstat[12]);
|
||||
|
||||
//? Cache cpu times and cpu seconds
|
||||
if (new_cache) {
|
||||
cache[pid].cpu_t = cpu_t;
|
||||
cache[pid].cpu_s = stoull(pstat[19]);
|
||||
}
|
||||
|
||||
//? CPU number last executed on
|
||||
if (pstat.size() > 36) cpu_n = stoi(pstat[36]);
|
||||
switch (s_count) {
|
||||
case 0: { //? Process state
|
||||
state = instr[s_pos];
|
||||
break;
|
||||
}
|
||||
case 1: { //? Process parent pid
|
||||
ppid = stoul(instr.substr(s_pos, c_pos - s_pos));
|
||||
break;
|
||||
}
|
||||
case 11: { //? Process utime
|
||||
cpu_t = stoull(instr.substr(s_pos, c_pos - s_pos));
|
||||
break;
|
||||
}
|
||||
case 12: { //? Process stime
|
||||
cpu_t += stoull(instr.substr(s_pos, c_pos - s_pos));
|
||||
break;
|
||||
}
|
||||
case 16: { //? Process nice value
|
||||
p_nice = stoi(instr.substr(s_pos, c_pos - s_pos));
|
||||
break;
|
||||
}
|
||||
case 17: { //? Process number of threads
|
||||
threads = stoul(instr.substr(s_pos, c_pos - s_pos));
|
||||
break;
|
||||
}
|
||||
case 19: { //? Cache cpu times and cpu seconds
|
||||
if (new_cache) {
|
||||
cache[pid].cpu_t = cpu_t;
|
||||
cache[pid].cpu_s = stoull(instr.substr(s_pos, c_pos - s_pos));
|
||||
};
|
||||
break;
|
||||
}
|
||||
case 36: { //? CPU number last executed on
|
||||
cpu_n = stoi(instr.substr(s_pos, c_pos - s_pos));
|
||||
break;
|
||||
}
|
||||
}
|
||||
s_pos = c_pos + 1;
|
||||
} while (s_count++ < 36);
|
||||
|
||||
if (s_count < 20) continue;
|
||||
|
||||
//? Process cpu usage since last update, 100'000 because (100 percent * 1000 milliseconds) for correct conversion
|
||||
cpu = static_cast<double>(100000 * (cpu_t - cache[pid].cpu_t) / since_last) / clk_tck;
|
||||
|
@ -252,27 +280,17 @@ namespace Proc {
|
|||
//? Update cache with latest cpu times
|
||||
cache[pid].cpu_t = cpu_t;
|
||||
}
|
||||
else continue;
|
||||
|
||||
//* Get RSS memory in bytes from /proc/[pid]/statm
|
||||
if (fs::exists((string)d.path() + "/statm")) {
|
||||
pread.clear();
|
||||
ifstream pread((string)d.path() + "/statm");
|
||||
if (pread.good()) {
|
||||
pread.ignore(numeric_limits<streamsize>::max(), ' ');
|
||||
pread >> rss_mem;
|
||||
rss_mem *= page_size;
|
||||
}
|
||||
pread.open(d.path() / "statm");
|
||||
if (pread.good()) {
|
||||
pread.ignore(SSmax, ' ');
|
||||
pread >> rss_mem;
|
||||
rss_mem *= page_size;
|
||||
pread.close();
|
||||
}
|
||||
|
||||
//* Match filter if defined
|
||||
if (!filter.empty() &&
|
||||
pid_str.find(filter) == string::npos &&
|
||||
cache[pid].name.find(filter) == string::npos &&
|
||||
cache[pid].cmd.find(filter) == string::npos &&
|
||||
cache[pid].user.find(filter) == string::npos
|
||||
) continue;
|
||||
|
||||
//* Create proc_info
|
||||
procs.push_back(proc_info(pid, cache[pid].name, cache[pid].cmd, threads, cache[pid].user, rss_mem, cpu, cpu_s, state, cpu_n, p_nice, ppid));
|
||||
}
|
||||
|
@ -322,9 +340,8 @@ namespace Proc {
|
|||
|
||||
//* Initialize needed variables for collect
|
||||
void init(){
|
||||
clk_tck = sysconf(_SC_CLK_TCK);
|
||||
tstamp = time_ms();
|
||||
passwd_path = (fs::exists(fs::path("/etc/passwd"))) ? fs::path("/etc/passwd") : passwd_path;
|
||||
passwd_path = (access("/etc/passwd", R_OK) != -1) ? fs::path("/etc/passwd") : passwd_path;
|
||||
uint i = 0;
|
||||
for (auto& item : sort_array) sort_map[item] = i++;
|
||||
}
|
||||
|
|
|
@ -35,6 +35,51 @@ using namespace Tools;
|
|||
|
||||
namespace Theme {
|
||||
|
||||
const unordered_map<string, string> Default_theme = {
|
||||
{ "main_bg", "#00" },
|
||||
{ "main_fg", "#cc" },
|
||||
{ "title", "#ee" },
|
||||
{ "hi_fg", "#969696" },
|
||||
{ "selected_bg", "#7e2626" },
|
||||
{ "selected_fg", "#ee" },
|
||||
{ "inactive_fg", "#40" },
|
||||
{ "graph_text", "#60" },
|
||||
{ "meter_bg", "#40" },
|
||||
{ "proc_misc", "#0de756" },
|
||||
{ "cpu_box", "#3d7b46" },
|
||||
{ "mem_box", "#8a882e" },
|
||||
{ "net_box", "#423ba5" },
|
||||
{ "proc_box", "#923535" },
|
||||
{ "div_line", "#30" },
|
||||
{ "temp_start", "#4897d4" },
|
||||
{ "temp_mid", "#5474e8" },
|
||||
{ "temp_end", "#ff40b6" },
|
||||
{ "cpu_start", "#50f095" },
|
||||
{ "cpu_mid", "#f2e266" },
|
||||
{ "cpu_end", "#fa1e1e" },
|
||||
{ "free_start", "#223014" },
|
||||
{ "free_mid", "#b5e685" },
|
||||
{ "free_end", "#dcff85" },
|
||||
{ "cached_start", "#0b1a29" },
|
||||
{ "cached_mid", "#74e6fc" },
|
||||
{ "cached_end", "#26c5ff" },
|
||||
{ "available_start", "#292107" },
|
||||
{ "available_mid", "#ffd77a" },
|
||||
{ "available_end", "#ffb814" },
|
||||
{ "used_start", "#3b1f1c" },
|
||||
{ "used_mid", "#d9626d" },
|
||||
{ "used_end", "#ff4769" },
|
||||
{ "download_start", "#231a63" },
|
||||
{ "download_mid", "#4f43a3" },
|
||||
{ "download_end", "#b0a9de" },
|
||||
{ "upload_start", "#510554" },
|
||||
{ "upload_mid", "#7d4180" },
|
||||
{ "upload_end", "#dcafde" },
|
||||
{ "process_start", "#80d0a3" },
|
||||
{ "process_mid", "#dcd179" },
|
||||
{ "process_end", "#d45454" }
|
||||
};
|
||||
|
||||
namespace {
|
||||
//* Convert 24-bit colors to 256 colors using 6x6x6 color cube
|
||||
int truecolor_to_256(uint r, uint g, uint b){
|
||||
|
@ -146,7 +191,7 @@ namespace Theme {
|
|||
vector<string> t_rgb;
|
||||
string depth;
|
||||
colors.clear(); rgbs.clear();
|
||||
for (auto& [name, color] : Global::Default_theme) {
|
||||
for (auto& [name, color] : Default_theme) {
|
||||
depth = (name.ends_with("bg")) ? "bg" : "fg";
|
||||
if (source.contains(name)) {
|
||||
if (source.at(name)[0] == '#') {
|
||||
|
|
|
@ -37,6 +37,21 @@ using std::string, std::vector, std::regex, std::max, std::to_string, std::cin;
|
|||
|
||||
//? ------------------------------------------------- NAMESPACES ------------------------------------------------------
|
||||
|
||||
namespace Symbols {
|
||||
const string h_line = "─";
|
||||
const string v_line = "│";
|
||||
const string left_up = "┌";
|
||||
const string right_up = "┐";
|
||||
const string left_down = "└";
|
||||
const string right_down = "┘";
|
||||
const string title_left = "┤";
|
||||
const string title_right = "├";
|
||||
const string div_up = "┬";
|
||||
const string div_down = "┴";
|
||||
|
||||
const array<string, 10> superscript = { "⁰", "¹", "²", "³", "⁴", "⁵", "⁶", "⁷", "⁸", "⁹" };
|
||||
}
|
||||
|
||||
//* Collection of escape codes for text style and formatting
|
||||
namespace Fx {
|
||||
//* Escape sequence start
|
||||
|
@ -228,34 +243,34 @@ namespace Tools {
|
|||
}
|
||||
|
||||
//* Return current time since epoch in milliseconds
|
||||
uint64_t time_ms(){
|
||||
inline uint64_t time_ms(){
|
||||
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
|
||||
}
|
||||
|
||||
//* Check if a string is a valid bool value
|
||||
bool isbool(string str){
|
||||
inline bool isbool(string& str){
|
||||
return (str == "true") || (str == "false") || (str == "True") || (str == "False");
|
||||
}
|
||||
|
||||
//* Check if a string is a valid integer value
|
||||
bool isint(string str){
|
||||
inline bool isint(string& str){
|
||||
return all_of(str.begin(), str.end(), ::isdigit);
|
||||
}
|
||||
|
||||
//* Left-trim <t_str> from <str> and return string
|
||||
string ltrim(string str, string t_str = " "){
|
||||
inline 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
|
||||
string rtrim(string str, string t_str = " "){
|
||||
inline 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
|
||||
string trim(string str, string t_str = " "){
|
||||
inline string trim(string str, string t_str = " "){
|
||||
return ltrim(rtrim(str, t_str), t_str);
|
||||
}
|
||||
|
||||
|
@ -352,6 +367,10 @@ namespace Tools {
|
|||
return out;
|
||||
}
|
||||
|
||||
//? Units for floating_humanizer function
|
||||
const array<string, 11> Units_bit = {"bit", "Kib", "Mib", "Gib", "Tib", "Pib", "Eib", "Zib", "Yib", "Bib", "GEb"};
|
||||
const array<string, 11> Units_byte = {"Byte", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB", "BiB", "GEB"};
|
||||
|
||||
//* 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
|
||||
|
@ -359,7 +378,7 @@ namespace Tools {
|
|||
string floating_humanizer(uint64_t value, bool shorten=false, uint start=0, bool bit=false, bool per_second=false){
|
||||
string out;
|
||||
uint mult = (bit) ? 8 : 1;
|
||||
auto& units = (bit) ? Global::Units_bit : Global::Units_byte;
|
||||
auto& units = (bit) ? Units_bit : Units_byte;
|
||||
|
||||
value *= 100 * mult;
|
||||
|
||||
|
|
Loading…
Reference in a new issue