From 3b3a93935d3d764fb78e0be9bd8363a684001ba2 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sat, 8 May 2021 20:37:36 +0200 Subject: [PATCH] File reorganization --- Makefile | 2 +- btop.cpp | 163 +++----------------------- {Include => src}/btop_config.h | 12 +- {Include => src}/btop_globs.h | 2 +- src/btop_input.h | 119 +++++++++++++++++++ src/btop_theme.h | 169 +++++++++++++++++++++++++++ {Include => src}/btop_tools.h | 202 ++++++++++----------------------- 7 files changed, 371 insertions(+), 298 deletions(-) rename {Include => src}/btop_config.h (95%) rename {Include => src}/btop_globs.h (99%) create mode 100644 src/btop_input.h create mode 100644 src/btop_theme.h rename {Include => src}/btop_tools.h (71%) diff --git a/Makefile b/Makefile index a6cd154..7146d26 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ PREFIX ?= /usr/local DOCDIR ?= $(PREFIX)/share/btop/doc CXX = g++ CXXFLAGS = -std=c++20 -pthread -INCLUDES = -I./Include +INCLUDES = -I./src btop: btop.cpp @mkdir -p bin diff --git a/btop.cpp b/btop.cpp index ee52778..868bc69 100644 --- a/btop.cpp +++ b/btop.cpp @@ -16,12 +16,9 @@ indent = tab tab-size = 4 */ -#include -#include -#include + + #include -#include -#include #include #include #include @@ -29,16 +26,15 @@ tab-size = 4 #include #include #include -#include -#include #include #include -#include #include #include #include +#include +#include #if defined(__linux__) #define SYSTEM "linux" @@ -100,141 +96,10 @@ void argumentParser(int argc, char **argv){ } } -//* Functions and variables for handling keyboard and mouse input -class C_Key { - const map KEY_ESCAPES = { - {"\033", "escape"}, - {"\n", "enter"}, - {" ", "space"}, - {"\x7f", "backspace"}, - {"\x08", "backspace"}, - {"[A", "up"}, - {"OA", "up"}, - {"[B", "down"}, - {"OB", "down"}, - {"[D", "left"}, - {"OD", "left"}, - {"[C", "right"}, - {"OC", "right"}, - {"[2~", "insert"}, - {"[3~", "delete"}, - {"[H", "home"}, - {"[F", "end"}, - {"[5~", "page_up"}, - {"[6~", "page_down"}, - {"\t", "tab"}, - {"[Z", "shift_tab"}, - {"OP", "f1"}, - {"OQ", "f2"}, - {"OR", "f3"}, - {"OS", "f4"}, - {"[15~", "f5"}, - {"[17~", "f6"}, - {"[18~", "f7"}, - {"[19~", "f8"}, - {"[20~", "f9"}, - {"[21~", "f10"}, - {"[23~", "f11"}, - {"[24~", "f12"} - }; - - bool wait(int timeout=0){ - struct pollfd pls[1]; - pls[ 0 ].fd = STDIN_FILENO; - pls[ 0 ].events = POLLIN | POLLPRI; - return poll(pls, 1, timeout) > 0; - } - - string get(){ - string key = ""; - while (wait() && key.size() < 100) key += cin.get(); - if (key != ""){ - if (key.starts_with(Fx::e)) key.erase(0, 1); - if (KEY_ESCAPES.count(key)) key = KEY_ESCAPES.at(key); - else if (ulen(key) > 1) key = ""; - } - return key; - } -public: - string last = ""; - - //* Wait ms for input on stdin and return true if available - //* 0 to just check for input - //* -1 for infinite wait - bool operator()(int timeout){ - if (wait(timeout)) { - last = get(); - return true; - } else { - last = ""; - return false; - } - } - - //* Return last entered key - string operator()(){ - return last; - } -}; - -class C_Theme { - map c; - map> g; - C_Config conf; - - map generate(map& source){ - map out; - vector t_rgb; - string depth; - for (auto& item : Global::Default_theme) { - depth = (item.first.ends_with("bg")) ? "bg" : "fg"; - if (source.count(item.first)) { - if (source.at(item.first)[0] == '#') out[item.first] = hex_to_color(source.at(item.first), !State::truecolor, depth); - else { - t_rgb = ssplit(source.at(item.first), " "); - out[item.first] = dec_to_color(stoi(t_rgb[0]), stoi(t_rgb[1]), stoi(t_rgb[2]), !State::truecolor, depth); - } - } - else out[item.first] = ""; - if (out[item.first] == "") out[item.first] = hex_to_color(item.second, !State::truecolor, depth); - } - return out; - } - -public: - - //* Change to theme using map - void change(map source){ - c = generate(source); - State::fg = c.at("main_fg"); - State::bg = c.at("main_bg"); - Fx::reset = Fx::reset_base + State::fg + State::bg; - } - - //* Generate theme from map, default to DEFAULT_THEME on missing or malformatted values - C_Theme(map source){ - change(source); - } - - //* Return escape code for color - auto operator()(string name){ - return c.at(name); - } - - //* Return vector of escape codes for color gradient - auto gradient(string name){ - return g.at(name); - } - - //* Return map of decimal int's (r, g, b) for color - auto rgb(string name){ - return c_to_rgb(c.at(name)); - } - -}; - -struct C_Banner { +class C_Banner { string banner_str; + +public: int width; C_Banner(){ @@ -274,7 +139,6 @@ struct C_Banner { }; - //? --------------------------------------------- Main starts here! --------------------------------------------------- int main(int argc, char **argv){ int debug = 0; @@ -293,11 +157,10 @@ int main(int argc, char **argv){ exit(1); } - C_Config Config; C_Theme Theme(Global::Default_theme); C_Banner Banner; - C_Key Key; + C_Input Input; cout << Theme("main_bg") << Term.clear << flush; // bool thread_test = false; @@ -453,17 +316,17 @@ int main(int argc, char **argv){ wt--; cout << Mv::to(Term.height - 1, 26) << "(" << wtm << ":" << wts << ") " << flush; //chr = Key(1000); - if (Key(1000)) { - cout << Mv::to(Term.height - 2, 1) << "Last key: LEN=" << Key().size() << " ULEN=" << ulen(Key()) << " KEY=\"" << Key() << "\" CODE=" << (int)Key().at(0) << " " << flush; - full += Key(); + if (Input(1000)) { + cout << Mv::to(Term.height - 2, 1) << "Last key: LEN=" << Input().size() << " ULEN=" << ulen(Input()) << " KEY=\"" << Input() << "\" CODE=" << (int)Input().at(0) << " " << flush; + full += Input(); cout << Mv::to(Term.height - 5, 1) << full << flush; - if (Key() == "q") qp = true; + if (Input() == "q") qp = true; wt++; } } } - if (debug == 1) Key(-1); + if (debug == 1) Input(-1); Term.restore(); if (debug < 2) cout << Term.normal_screen << Term.show_cursor << flush; return 0; diff --git a/Include/btop_config.h b/src/btop_config.h similarity index 95% rename from Include/btop_config.h rename to src/btop_config.h index e3e6ec0..0de604a 100644 --- a/Include/btop_config.h +++ b/src/btop_config.h @@ -19,16 +19,16 @@ tab-size = 4 #ifndef _btop_config_included_ #define _btop_config_included_ - -#include #include #include #include -using std::string; -using std::to_string; -using std::vector; -using std::map; +#include + +using std::string, std::to_string, std::vector, std::map; + + +//? Classes, functions and variables for reading and writing the btop config file #define Bool bool() #define Int int() diff --git a/Include/btop_globs.h b/src/btop_globs.h similarity index 99% rename from Include/btop_globs.h rename to src/btop_globs.h index fe0caba..856f91d 100644 --- a/Include/btop_globs.h +++ b/src/btop_globs.h @@ -109,6 +109,6 @@ namespace Global { } } } } }; - } +} #endif \ No newline at end of file diff --git a/src/btop_input.h b/src/btop_input.h new file mode 100644 index 0000000..1b44077 --- /dev/null +++ b/src/btop_input.h @@ -0,0 +1,119 @@ +/* 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 + + http://www.apache.org/licenses/LICENSE-2.0 + + 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 +*/ + +#ifndef _btop_input_included_ +#define _btop_input_included_ + +#include +#include +#include +#include +#include + +#include +#include + +using std::string, std::map, std::cin; + + +//* Class for handling keyboard and mouse input +class C_Input { + + string last = ""; + + //* Map for translating key codes to readable values + const map Key_escapes = { + {"\033", "escape"}, + {"\n", "enter"}, + {" ", "space"}, + {"\x7f", "backspace"}, + {"\x08", "backspace"}, + {"[A", "up"}, + {"OA", "up"}, + {"[B", "down"}, + {"OB", "down"}, + {"[D", "left"}, + {"OD", "left"}, + {"[C", "right"}, + {"OC", "right"}, + {"[2~", "insert"}, + {"[3~", "delete"}, + {"[H", "home"}, + {"[F", "end"}, + {"[5~", "page_up"}, + {"[6~", "page_down"}, + {"\t", "tab"}, + {"[Z", "shift_tab"}, + {"OP", "f1"}, + {"OQ", "f2"}, + {"OR", "f3"}, + {"OS", "f4"}, + {"[15~", "f5"}, + {"[17~", "f6"}, + {"[18~", "f7"}, + {"[19~", "f8"}, + {"[20~", "f9"}, + {"[21~", "f10"}, + {"[23~", "f11"}, + {"[24~", "f12"} + }; + + bool wait(int timeout=0){ + if (timeout == 0) return cin.rdbuf()->in_avail() > 0; + auto timer = 0; + while (timeout == -1 || timer * 10 <= timeout) { + if (cin.rdbuf()->in_avail() > 0) return true; + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + if (timeout >= 0) ++timer; + } + return false; + } + + string get(){ + string key = ""; + while (cin.rdbuf()->in_avail() > 0 && key.size() < 100) key += cin.get(); + if (key != ""){ + if (key.substr(0,2) == Fx::e) key.erase(0, 1); + if (Key_escapes.contains(key)) key = Key_escapes.at(key); + else if (ulen(key) > 1) key = ""; + } + return key; + } + +public: + + //* Wait ms for input on stdin and return true if available + //* 0 to just check for input + //* -1 for infinite wait + bool operator()(int timeout){ + if (wait(timeout)) { + last = get(); + return last != ""; + } else { + last = ""; + return false; + } + } + + //* Return last entered key + string operator()(){ + return last; + } +}; + +#endif \ No newline at end of file diff --git a/src/btop_theme.h b/src/btop_theme.h new file mode 100644 index 0000000..799a8cd --- /dev/null +++ b/src/btop_theme.h @@ -0,0 +1,169 @@ +/* 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 + + http://www.apache.org/licenses/LICENSE-2.0 + + 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 +*/ + +#ifndef _btop_theme_included_ +#define _btop_theme_included_ + +#include +#include +#include +#include + +#include +#include +#include + +using std::string, std::to_string, std::round, std::vector, std::map; + +//? --------------------------------------------------- FUNCTIONS ----------------------------------------------------- + +//* Convert 24-bit colors to 256 colors using 6x6x6 color cube +int truecolor_to_256(unsigned r, unsigned g, unsigned b){ + if (r / 11 == g / 11 && g / 11 == b / 11) { + return 232 + r / 11; + } else { + return round((float)(r / 51)) * 36 + round((float)(g / 51)) * 6 + round((float)(b / 51)) + 16; + } +} + +//* Generate escape sequence for 24-bit or 256 color and return as a string +//* Args hexa: ["#000000"-"#ffffff"] for color, ["#00"-"#ff"] for greyscale +//* t_to_256: [true|false] convert 24bit value to 256 color value +//* depth: ["fg"|"bg"] for either a foreground color or a background color +string hex_to_color(string hexa, bool t_to_256=false, string depth="fg"){ + if (hexa.size() > 1){ + hexa.erase(0, 1); + for (auto& c : hexa) if (!isxdigit(c)) return ""; + depth = (depth == "fg") ? "38" : "48"; + string pre = Fx::e + depth + ";"; + pre += (t_to_256) ? "5;" : "2;"; + + if (hexa.size() == 2){ + unsigned h_int = stoi(hexa, 0, 16); + if (t_to_256){ + return pre + to_string(truecolor_to_256(h_int, h_int, h_int)) + "m"; + } else { + string h_str = to_string(h_int); + return pre + h_str + ";" + h_str + ";" + h_str + "m"; + } + } + else if (hexa.size() == 6){ + if (t_to_256){ + return pre + to_string(truecolor_to_256( + stoi(hexa.substr(0, 2), 0, 16), + stoi(hexa.substr(2, 2), 0, 16), + stoi(hexa.substr(4, 2), 0, 16))) + "m"; + } else { + return pre + + to_string(stoi(hexa.substr(0, 2), 0, 16)) + ";" + + to_string(stoi(hexa.substr(2, 2), 0, 16)) + ";" + + to_string(stoi(hexa.substr(4, 2), 0, 16)) + "m"; + } + } + } + return ""; +} + +//* Generate escape sequence for 24-bit or 256 color and return as a string +//* Args r: [0-255], g: [0-255], b: [0-255] +//* t_to_256: [true|false] convert 24bit value to 256 color value +//* depth: ["fg"|"bg"] for either a foreground color or a background color +string dec_to_color(unsigned r, unsigned g, unsigned b, bool t_to_256=false, string depth="fg"){ + depth = (depth == "fg") ? "38" : "48"; + string pre = Fx::e + depth + ";"; + pre += (t_to_256) ? "5;" : "2;"; + r = (r > 255) ? 255 : r; + g = (g > 255) ? 255 : g; + b = (b > 255) ? 255 : b; + if (t_to_256) return pre + to_string(truecolor_to_256(r, g, b)) + "m"; + else return pre + to_string(r) + ";" + to_string(g) + ";" + to_string(b) + "m"; +} + +//* Return a map of "r", "g", "b", 0-255 values for a 24-bit color escape string +map c_to_rgb(string c_string){ + map rgb = {{"r", 0}, {"g", 0}, {"b", 0}}; + if (c_string.size() >= 14){ + c_string.erase(0, 7); + auto c_split = ssplit(c_string, ";"); + if (c_split.size() == 3){ + rgb["r"] = stoi(c_split[0]); + rgb["g"] = stoi(c_split[1]); + rgb["b"] = stoi(c_split[2].erase(c_split[2].size())); + } + } + return rgb; +} + +//? --------------------------------------------------- CLASSES ----------------------------------------------------- + +class C_Theme { + map c; + map> g; + + map generate(map& source){ + map out; + vector t_rgb; + string depth; + for (auto& item : Global::Default_theme) { + depth = (item.first.ends_with("bg")) ? "bg" : "fg"; + if (source.contains(item.first)) { + if (source.at(item.first)[0] == '#') out[item.first] = hex_to_color(source.at(item.first), !State::truecolor, depth); + else { + t_rgb = ssplit(source.at(item.first), " "); + out[item.first] = dec_to_color(stoi(t_rgb[0]), stoi(t_rgb[1]), stoi(t_rgb[2]), !State::truecolor, depth); + } + } + else out[item.first] = ""; + if (out[item.first] == "") out[item.first] = hex_to_color(item.second, !State::truecolor, depth); + } + return out; + } + +public: + + //* Change to theme + void change(map source){ + c = generate(source); + State::fg = c.at("main_fg"); + State::bg = c.at("main_bg"); + Fx::reset = Fx::reset_base + State::fg + State::bg; + } + + //* Generate theme from map, default to DEFAULT_THEME on missing or malformatted values + C_Theme(map source){ + change(source); + } + + //* Return escape code for color + auto operator()(string name){ + return c.at(name); + } + + //* Return vector of escape codes for color gradient + auto gradient(string name){ + return g.at(name); + } + + //* Return map of decimal int's (r, g, b) for color + auto rgb(string name){ + return c_to_rgb(c.at(name)); + } + +}; + +#endif \ No newline at end of file diff --git a/Include/btop_tools.h b/src/btop_tools.h similarity index 71% rename from Include/btop_tools.h rename to src/btop_tools.h index 9a2ce66..c5fbbd2 100644 --- a/Include/btop_tools.h +++ b/src/btop_tools.h @@ -19,17 +19,17 @@ tab-size = 4 #ifndef _btop_tools_included_ #define _btop_tools_included_ - #include -#include #include #include #include -#include + #include #include #include +#include + using std::string, std::to_string, std::round, std::vector, std::map, std::cin; //? ------------------------------------------------- NAMESPACES ------------------------------------------------------ @@ -86,6 +86,65 @@ namespace Mv { const string restore = Fx::e + "u"; }; +//? --------------------------------------------------- FUNCTIONS ----------------------------------------------------- + +//* Return number of UTF8 characters in a string +inline size_t ulen(const string& str){ + size_t len = 0; + for (char c : str) if ((c & 0xC0) != 0x80) ++len; + return len; +} + +//* Return current time since epoch in milliseconds +uint64_t time_ms(){ + return std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); +} + +//* Check if a string is a valid bool value +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){ + return all_of(str.begin(), str.end(), ::isdigit); +} + +//* Left-trim from and return string +string ltrim(string str, string t_str = " "){ + while (str.starts_with(t_str)) str.erase(0, t_str.size()); + return str; +} + +//* Right-trim from and return string +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 from and return string +string trim(string str, string t_str = " "){ + return ltrim(rtrim(str, t_str), t_str); +} + +//* Split at (0 for unlimited) times and return vector +vector ssplit(string str, string delim = " ", int times = 0){ + vector out; + if (str != "" && delim != ""){ + size_t pos = 0; + int x = 0; + string tmp; + while ((pos = str.find(delim)) != string::npos){ + tmp = str.substr(0, pos); + if (tmp != delim && tmp != "") out.push_back(tmp); + str.erase(0, pos + delim.size()); + if (times > 0 && ++x >= times) break; + } + } + out.push_back(str); + return out; +} + //? --------------------------------------------------- CLASSES ----------------------------------------------------- //* Collection of escape codes and functions for terminal manipulation @@ -185,143 +244,6 @@ public: refresh(); resized = false; } - }; -//? --------------------------------------------------- FUNCTIONS ----------------------------------------------------- - -//* Return number of UTF8 characters in a string -inline size_t ulen(const string& str){ - size_t len = 0; - for (char c : str) if ((c & 0xC0) != 0x80) ++len; - return len; -} - -//* Return current time since epoch in milliseconds -uint64_t time_ms(){ - return std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); -} - -//* Check if a string is a valid bool value -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){ - return all_of(str.begin(), str.end(), ::isdigit); -} - -//* Convert 24-bit colors to 256 colors using 6x6x6 color cube -int truecolor_to_256(unsigned r, unsigned g, unsigned b){ - if (r / 11 == g / 11 && g / 11 == b / 11) { - return 232 + r / 11; - } else { - return round((float)(r / 51)) * 36 + round((float)(g / 51)) * 6 + round((float)(b / 51)) + 16; - } -} - -//* Generate escape sequence for 24-bit or 256 color and return as a string -//* Args hexa: ["#000000"-"#ffffff"] for color, ["#00"-"#ff"] for greyscale -//* t_to_256: [true|false] convert 24bit value to 256 color value -//* depth: ["fg"|"bg"] for either a foreground color or a background color -string hex_to_color(string hexa, bool t_to_256=false, string depth="fg"){ - if (hexa.size() > 1){ - hexa.erase(0, 1); - for (auto& c : hexa) if (!isxdigit(c)) return ""; - depth = (depth == "fg") ? "38" : "48"; - string pre = Fx::e + depth + ";"; - pre += (t_to_256) ? "5;" : "2;"; - - if (hexa.size() == 2){ - unsigned h_int = stoi(hexa, 0, 16); - if (t_to_256){ - return pre + to_string(truecolor_to_256(h_int, h_int, h_int)) + "m"; - } else { - string h_str = to_string(h_int); - return pre + h_str + ";" + h_str + ";" + h_str + "m"; - } - } - else if (hexa.size() == 6){ - if (t_to_256){ - return pre + to_string(truecolor_to_256( - stoi(hexa.substr(0, 2), 0, 16), - stoi(hexa.substr(2, 2), 0, 16), - stoi(hexa.substr(4, 2), 0, 16))) + "m"; - } else { - return pre + - to_string(stoi(hexa.substr(0, 2), 0, 16)) + ";" + - to_string(stoi(hexa.substr(2, 2), 0, 16)) + ";" + - to_string(stoi(hexa.substr(4, 2), 0, 16)) + "m"; - } - } - } - return ""; -} - -//* Generate escape sequence for 24-bit or 256 color and return as a string -//* Args r: [0-255], g: [0-255], b: [0-255] -//* t_to_256: [true|false] convert 24bit value to 256 color value -//* depth: ["fg"|"bg"] for either a foreground color or a background color -string dec_to_color(unsigned r, unsigned g, unsigned b, bool t_to_256=false, string depth="fg"){ - depth = (depth == "fg") ? "38" : "48"; - string pre = Fx::e + depth + ";"; - pre += (t_to_256) ? "5;" : "2;"; - r = (r > 255) ? 255 : r; - g = (g > 255) ? 255 : g; - b = (b > 255) ? 255 : b; - if (t_to_256) return pre + to_string(truecolor_to_256(r, g, b)) + "m"; - else return pre + to_string(r) + ";" + to_string(g) + ";" + to_string(b) + "m"; -} - -//* Left-trim from and return string -string ltrim(string str, string t_str = " "){ - while (str.starts_with(t_str)) str.erase(0, t_str.size()); - return str; -} - -//* Right-trim from and return string -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 from and return string -string trim(string str, string t_str = " "){ - return ltrim(rtrim(str, t_str), t_str); -} - -//* Split at (0 for unlimited) times and return vector -vector ssplit(string str, string delim = " ", int times = 0){ - vector out; - if (str != "" && delim != ""){ - size_t pos = 0; - int x = 0; - string tmp; - while ((pos = str.find(delim)) != string::npos){ - tmp = str.substr(0, pos); - if (tmp != delim && tmp != "") out.push_back(tmp); - str.erase(0, pos + delim.size()); - if (times > 0 && ++x >= times) break; - } - } - out.push_back(str); - return out; -} - -//* Return a map of "r", "g", "b", 0-255 values for a 24-bit color escape string -map c_to_rgb(string c_string){ - map rgb = {{"r", 0}, {"g", 0}, {"b", 0}}; - if (c_string.size() >= 14){ - c_string.erase(0, 7); - auto c_split = ssplit(c_string, ";"); - if (c_split.size() == 3){ - rgb["r"] = stoi(c_split[0]); - rgb["g"] = stoi(c_split[1]); - rgb["b"] = stoi(c_split[2].erase(c_split[2].size())); - } - } - return rgb; -} - #endif \ No newline at end of file