File reorganization

This commit is contained in:
aristocratos 2021-05-08 20:37:36 +02:00
parent 55e2a3f02b
commit 3b3a93935d
7 changed files with 371 additions and 298 deletions

View file

@ -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

163
btop.cpp
View file

@ -16,12 +16,9 @@ indent = tab
tab-size = 4
*/
#include <cstdlib>
#include <cstdio>
#include <limits>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <string>
#include <cmath>
#include <vector>
@ -29,16 +26,15 @@ tab-size = 4
#include <thread>
#include <future>
#include <atomic>
#include <string_view>
#include <chrono>
#include <ranges>
#include <unistd.h>
#include <poll.h>
#include <btop_globs.h>
#include <btop_tools.h>
#include <btop_config.h>
#include <btop_input.h>
#include <btop_theme.h>
#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<string, string> 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 <timeout> 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<string, string> c;
map<string, vector<string>> g;
C_Config conf;
map<string,string> generate(map<string, string>& source){
map<string, string> out;
vector<string> 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 <source> map
void change(map<string, string> 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 <source> map, default to DEFAULT_THEME on missing or malformatted values
C_Theme(map<string, string> source){
change(source);
}
//* Return escape code for color <name>
auto operator()(string name){
return c.at(name);
}
//* Return vector of escape codes for color gradient <name>
auto gradient(string name){
return g.at(name);
}
//* Return map of decimal int's (r, g, b) for color <name>
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;

View file

@ -19,16 +19,16 @@ tab-size = 4
#ifndef _btop_config_included_
#define _btop_config_included_
#include <btop_tools.h>
#include <string>
#include <vector>
#include <map>
using std::string;
using std::to_string;
using std::vector;
using std::map;
#include <btop_tools.h>
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()

View file

@ -109,6 +109,6 @@ namespace Global {
} }
} }
};
}
}
#endif

119
src/btop_input.h Normal file
View file

@ -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 <string>
#include <map>
#include <chrono>
#include <thread>
#include <iostream>
#include <btop_globs.h>
#include <btop_tools.h>
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<string, string> 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 <timeout> 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

169
src/btop_theme.h Normal file
View file

@ -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 <string>
#include <cmath>
#include <vector>
#include <map>
#include <btop_globs.h>
#include <btop_tools.h>
#include <btop_config.h>
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<string, int> c_to_rgb(string c_string){
map<string, int> 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<string, string> c;
map<string, vector<string>> g;
map<string,string> generate(map<string, string>& source){
map<string, string> out;
vector<string> 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 <source>
void change(map<string, string> 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 <source> map, default to DEFAULT_THEME on missing or malformatted values
C_Theme(map<string, string> source){
change(source);
}
//* Return escape code for color <name>
auto operator()(string name){
return c.at(name);
}
//* Return vector of escape codes for color gradient <name>
auto gradient(string name){
return g.at(name);
}
//* Return map of decimal int's (r, g, b) for color <name>
auto rgb(string name){
return c_to_rgb(c.at(name));
}
};
#endif

View file

@ -19,17 +19,17 @@ tab-size = 4
#ifndef _btop_tools_included_
#define _btop_tools_included_
#include <string>
#include <chrono>
#include <cmath>
#include <vector>
#include <map>
#include <iostream>
#include <unistd.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <btop_globs.h>
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::milliseconds>(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 <t_str> from <str> 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 <t_str> from <str> 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 <t_str> from <str> and return string
string trim(string str, string t_str = " "){
return ltrim(rtrim(str, t_str), t_str);
}
//* Split <string> at <delim> <times> (0 for unlimited) times and return vector
vector<string> ssplit(string str, string delim = " ", int times = 0){
vector<string> 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::milliseconds>(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 <t_str> from <str> 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 <t_str> from <str> 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 <t_str> from <str> and return string
string trim(string str, string t_str = " "){
return ltrim(rtrim(str, t_str), t_str);
}
//* Split <string> at <delim> <times> (0 for unlimited) times and return vector
vector<string> ssplit(string str, string delim = " ", int times = 0){
vector<string> 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<string, int> c_to_rgb(string c_string){
map<string, int> 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