mirror of
https://github.com/aristocratos/btop.git
synced 2024-10-31 21:01:03 +01:00
Split up code in multiple files
This commit is contained in:
parent
7ca94a16d0
commit
55e2a3f02b
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,6 +1,3 @@
|
|||||||
*
|
|
||||||
!*.*
|
|
||||||
|
|
||||||
# Prerequisites
|
# Prerequisites
|
||||||
*.d
|
*.d
|
||||||
|
|
||||||
@ -35,4 +32,5 @@
|
|||||||
*.app
|
*.app
|
||||||
|
|
||||||
build
|
build
|
||||||
|
bin
|
||||||
btop
|
btop
|
||||||
|
124
Include/btop_config.h
Normal file
124
Include/btop_config.h
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
/* 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_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;
|
||||||
|
|
||||||
|
#define Bool bool()
|
||||||
|
#define Int int()
|
||||||
|
#define String string()
|
||||||
|
|
||||||
|
|
||||||
|
//* Used for classes and functions needing pre-initialised values
|
||||||
|
namespace State {
|
||||||
|
bool truecolor = true;
|
||||||
|
string fg, bg;
|
||||||
|
}
|
||||||
|
|
||||||
|
class C_Config {
|
||||||
|
map<string, string> strings = {
|
||||||
|
{"color_theme", "Default"},
|
||||||
|
{"shown_boxes", "cpu mem net proc"},
|
||||||
|
{"proc_sorting", "cpu lazy"},
|
||||||
|
{"cpu_graph_upper", "total"},
|
||||||
|
{"cpu_graph_lower", "total"},
|
||||||
|
{"cpu_sensor", "Auto"},
|
||||||
|
{"temp_scale", "celsius"},
|
||||||
|
{"draw_clock", "%X"},
|
||||||
|
{"custom_cpu_name", ""},
|
||||||
|
{"disks_filter", ""},
|
||||||
|
{"io_graph_speeds", ""},
|
||||||
|
{"net_download", "10M"},
|
||||||
|
{"net_upload", "10M"},
|
||||||
|
{"net_iface", ""},
|
||||||
|
{"log_level", "WARNING"}
|
||||||
|
};
|
||||||
|
map<string, bool> bools = {
|
||||||
|
{"theme_background", true},
|
||||||
|
{"truecolor", true},
|
||||||
|
{"proc_reversed", false},
|
||||||
|
{"proc_tree", false},
|
||||||
|
{"proc_colors", true},
|
||||||
|
{"proc_gradient", true},
|
||||||
|
{"proc_per_core", false},
|
||||||
|
{"proc_mem_bytes", true},
|
||||||
|
{"cpu_invert_lower", true},
|
||||||
|
{"cpu_single_graph", false},
|
||||||
|
{"show_uptime", true},
|
||||||
|
{"check_temp", true},
|
||||||
|
{"show_coretemp", true},
|
||||||
|
{"show_cpu_freq", true},
|
||||||
|
{"background_update", true},
|
||||||
|
{"update_check", true},
|
||||||
|
{"mem_graphs", true},
|
||||||
|
{"show_swap", true},
|
||||||
|
{"swap_disk", true},
|
||||||
|
{"show_disks", true},
|
||||||
|
{"only_physical", true},
|
||||||
|
{"use_fstab", false},
|
||||||
|
{"show_io_stat", true},
|
||||||
|
{"io_mode", false},
|
||||||
|
{"io_graph_combined", false},
|
||||||
|
{"net_color_fixed", false},
|
||||||
|
{"net_auto", true},
|
||||||
|
{"net_sync", false},
|
||||||
|
{"show_battery", true},
|
||||||
|
{"show_init", false}
|
||||||
|
};
|
||||||
|
map<string, int> ints = {
|
||||||
|
{"update_ms", 2000},
|
||||||
|
{"proc_update_mult", 2},
|
||||||
|
{"tree_depth", 3}
|
||||||
|
};
|
||||||
|
public:
|
||||||
|
C_Config(){
|
||||||
|
bools["truecolor"] = "true";
|
||||||
|
strings["color_theme"] = "Default";
|
||||||
|
ints["tree_depth"] = 3;
|
||||||
|
|
||||||
|
State::truecolor = bools["truecolor"];
|
||||||
|
}
|
||||||
|
|
||||||
|
//* Return config value <name> as a bool
|
||||||
|
bool operator()(bool b_type, string name){
|
||||||
|
return bools.at(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
//* Return config value <name> as a int
|
||||||
|
int operator()(int i_type, string name){
|
||||||
|
return ints.at(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
//* Return config value <name> as a string
|
||||||
|
string operator()(string s_type, string name){
|
||||||
|
return strings.at(name);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
114
Include/btop_globs.h
Normal file
114
Include/btop_globs.h
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
/* 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_globs_included_
|
||||||
|
#define _btop_globs_included_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
using std::string, std::vector, std::map;
|
||||||
|
|
||||||
|
namespace Global {
|
||||||
|
const 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 map<string, map<string, vector<string>>> Menus = {
|
||||||
|
{ "options", {
|
||||||
|
{ "normal", {
|
||||||
|
"┌─┐┌─┐┌┬┐┬┌─┐┌┐┌┌─┐",
|
||||||
|
"│ │├─┘ │ ││ ││││└─┐",
|
||||||
|
"└─┘┴ ┴ ┴└─┘┘└┘└─┘"
|
||||||
|
} },
|
||||||
|
{ "selected", {
|
||||||
|
"╔═╗╔═╗╔╦╗╦╔═╗╔╗╔╔═╗",
|
||||||
|
"║ ║╠═╝ ║ ║║ ║║║║╚═╗",
|
||||||
|
"╚═╝╩ ╩ ╩╚═╝╝╚╝╚═╝"
|
||||||
|
} }
|
||||||
|
} },
|
||||||
|
{ "help", {
|
||||||
|
{ "normal", {
|
||||||
|
"┬ ┬┌─┐┬ ┌─┐",
|
||||||
|
"├─┤├┤ │ ├─┘",
|
||||||
|
"┴ ┴└─┘┴─┘┴ "
|
||||||
|
} },
|
||||||
|
{ "selected", {
|
||||||
|
"╦ ╦╔═╗╦ ╔═╗",
|
||||||
|
"╠═╣║╣ ║ ╠═╝",
|
||||||
|
"╩ ╩╚═╝╩═╝╩ "
|
||||||
|
} }
|
||||||
|
} },
|
||||||
|
{ "quit", {
|
||||||
|
{ "normal", {
|
||||||
|
"┌─┐ ┬ ┬ ┬┌┬┐",
|
||||||
|
"│─┼┐│ │ │ │ ",
|
||||||
|
"└─┘└└─┘ ┴ ┴ "
|
||||||
|
} },
|
||||||
|
{ "selected", {
|
||||||
|
"╔═╗ ╦ ╦ ╦╔╦╗ ",
|
||||||
|
"║═╬╗║ ║ ║ ║ ",
|
||||||
|
"╚═╝╚╚═╝ ╩ ╩ "
|
||||||
|
} }
|
||||||
|
} }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
327
Include/btop_tools.h
Normal file
327
Include/btop_tools.h
Normal file
@ -0,0 +1,327 @@
|
|||||||
|
/* 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_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>
|
||||||
|
|
||||||
|
using std::string, std::to_string, std::round, std::vector, std::map, std::cin;
|
||||||
|
|
||||||
|
//? ------------------------------------------------- NAMESPACES ------------------------------------------------------
|
||||||
|
|
||||||
|
//* Collection of escape codes for text style and formatting
|
||||||
|
namespace Fx {
|
||||||
|
//* Escape sequence start
|
||||||
|
const string e = "\x1b[";
|
||||||
|
//* Bold on
|
||||||
|
const string b = e + "1m";
|
||||||
|
//* Bold off
|
||||||
|
const string ub = e + "22m";
|
||||||
|
//* Dark on
|
||||||
|
const string d = e + "2m";
|
||||||
|
//* Dark off
|
||||||
|
const string ud = e + "22m";
|
||||||
|
//* Italic on
|
||||||
|
const string i = e + "3m";
|
||||||
|
//* Italic off
|
||||||
|
const string ui = e + "23m";
|
||||||
|
//* Underline on
|
||||||
|
const string ul = e + "4m";
|
||||||
|
//* Underline off
|
||||||
|
const string uul = e + "24m";
|
||||||
|
//* Blink on
|
||||||
|
const string bl = e + "5m";
|
||||||
|
//* Blink off
|
||||||
|
const string ubl = e + "25m";
|
||||||
|
//* Strike / crossed-out on
|
||||||
|
const string s = e + "9m";
|
||||||
|
//* Strike / crossed-out off
|
||||||
|
const string us = e + "29m";
|
||||||
|
//* Reset foreground/background color and text effects
|
||||||
|
const string reset_base = e + "0m";
|
||||||
|
//* Reset text effects and restore default foregrund and background color < Changed by C_Theme
|
||||||
|
string reset = reset_base;
|
||||||
|
};
|
||||||
|
|
||||||
|
//* 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";}
|
||||||
|
//* Move cursor right <x> columns
|
||||||
|
inline 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";}
|
||||||
|
//* Move cursor up x lines
|
||||||
|
inline 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";}
|
||||||
|
//* Save cursor position
|
||||||
|
const string save = Fx::e + "s";
|
||||||
|
//* Restore saved cursor postion
|
||||||
|
const string restore = Fx::e + "u";
|
||||||
|
};
|
||||||
|
|
||||||
|
//? --------------------------------------------------- CLASSES -----------------------------------------------------
|
||||||
|
|
||||||
|
//* Collection of escape codes and functions for terminal manipulation
|
||||||
|
class C_Term {
|
||||||
|
struct termios initial_settings;
|
||||||
|
public:
|
||||||
|
bool initialized = false;
|
||||||
|
int width = 0;
|
||||||
|
int height = 0;
|
||||||
|
bool resized = false;
|
||||||
|
|
||||||
|
//* Hide terminal cursor
|
||||||
|
const string hide_cursor = Fx::e + "?25l";
|
||||||
|
|
||||||
|
//* Show terminal cursor
|
||||||
|
const string show_cursor = Fx::e + "?25h";
|
||||||
|
|
||||||
|
//* Switch to alternate screen
|
||||||
|
const string alt_screen = Fx::e + "?1049h";
|
||||||
|
|
||||||
|
//* Switch to normal screen
|
||||||
|
const string normal_screen = Fx::e + "?1049l";
|
||||||
|
|
||||||
|
//* Clear screen and set cursor to position 0,0
|
||||||
|
const string clear = Fx::e + "2J" + Fx::e + "0;0f";
|
||||||
|
|
||||||
|
//* Enable reporting of mouse position on click and release
|
||||||
|
const string mouse_on = Fx::e + "?1002h" + Fx::e + "?1015h" + Fx::e + "?1006h";
|
||||||
|
|
||||||
|
//* Disable mouse reporting
|
||||||
|
const string mouse_off = Fx::e + "?1002l";
|
||||||
|
|
||||||
|
//* Enable reporting of mouse position at any movement
|
||||||
|
const string mouse_direct_on = Fx::e + "?1003h";
|
||||||
|
|
||||||
|
//* Disable direct mouse reporting
|
||||||
|
const string mouse_direct_off = Fx::e + "?1003l";
|
||||||
|
|
||||||
|
//* Toggle need for return key when reading input
|
||||||
|
bool linebuffered(bool on=true){
|
||||||
|
struct termios settings;
|
||||||
|
if (tcgetattr(STDIN_FILENO, &settings)) return false;
|
||||||
|
if (on) settings.c_lflag |= ICANON;
|
||||||
|
else settings.c_lflag &= ~(ICANON);
|
||||||
|
if (tcsetattr(STDIN_FILENO, TCSANOW, &settings)) return false;
|
||||||
|
if (on) setlinebuf(stdin);
|
||||||
|
else setbuf(stdin, NULL);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//* Toggle terminal input echo
|
||||||
|
bool echo(bool on=true){
|
||||||
|
struct termios settings;
|
||||||
|
if (tcgetattr(STDIN_FILENO, &settings)) return false;
|
||||||
|
if (on) settings.c_lflag |= ECHO;
|
||||||
|
else settings.c_lflag &= ~(ECHO);
|
||||||
|
return 0 == tcsetattr(STDIN_FILENO, TCSANOW, &settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
//* Refresh variables holding current terminal width and height and return true if resized
|
||||||
|
bool refresh(){
|
||||||
|
struct winsize w;
|
||||||
|
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
|
||||||
|
resized = (width != w.ws_col || height != w.ws_row) ? true : false;
|
||||||
|
width = w.ws_col;
|
||||||
|
height = w.ws_row;
|
||||||
|
return resized;
|
||||||
|
}
|
||||||
|
|
||||||
|
//* Check for a valid tty, save terminal options and set new options
|
||||||
|
bool init(){
|
||||||
|
if (!initialized){
|
||||||
|
initialized = (bool)isatty(STDIN_FILENO);
|
||||||
|
if (initialized) {
|
||||||
|
initialized = (0 == tcgetattr(STDIN_FILENO, &initial_settings));
|
||||||
|
cin.sync_with_stdio(false);
|
||||||
|
cin.tie(NULL);
|
||||||
|
echo(false);
|
||||||
|
linebuffered(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
//* Restore terminal options
|
||||||
|
void restore(){
|
||||||
|
if (initialized) {
|
||||||
|
echo(true);
|
||||||
|
linebuffered(true);
|
||||||
|
tcsetattr(STDIN_FILENO, TCSANOW, &initial_settings);
|
||||||
|
initialized = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
C_Term() {
|
||||||
|
init();
|
||||||
|
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
|
14
Makefile
14
Makefile
@ -1,14 +1,16 @@
|
|||||||
PREFIX ?= /usr/local
|
PREFIX ?= /usr/local
|
||||||
DOCDIR ?= $(PREFIX)/share/btop/doc
|
DOCDIR ?= $(PREFIX)/share/btop/doc
|
||||||
CXX=g++
|
CXX = g++
|
||||||
CXXFLAGS=-std=c++20 -pthread
|
CXXFLAGS = -std=c++20 -pthread
|
||||||
|
INCLUDES = -I./Include
|
||||||
|
|
||||||
btop: btop.cpp
|
btop: btop.cpp
|
||||||
$(CXX) $(CXXFLAGS) -o btop btop.cpp
|
@mkdir -p bin
|
||||||
|
$(CXX) $(CXXFLAGS) $(INCLUDES) -o bin/btop btop.cpp
|
||||||
|
|
||||||
install:
|
install:
|
||||||
@mkdir -p $(DESTDIR)$(PREFIX)/bin
|
@mkdir -p $(DESTDIR)$(PREFIX)/bin
|
||||||
@cp -p btop $(DESTDIR)$(PREFIX)/bin/btop
|
@cp -p bin/btop $(DESTDIR)$(PREFIX)/bin/btop
|
||||||
@mkdir -p $(DESTDIR)$(DOCDIR)
|
@mkdir -p $(DESTDIR)$(DOCDIR)
|
||||||
@cp -p README.md $(DESTDIR)$(DOCDIR)
|
@cp -p README.md $(DESTDIR)$(DOCDIR)
|
||||||
@cp -pr themes $(DESTDIR)$(PREFIX)/share/btop
|
@cp -pr themes $(DESTDIR)$(PREFIX)/share/btop
|
||||||
@ -19,5 +21,5 @@ uninstall:
|
|||||||
@rm -rf $(DESTDIR)$(DOCDIR)
|
@rm -rf $(DESTDIR)$(DOCDIR)
|
||||||
@rm -rf $(DESTDIR)$(PREFIX)/share/btop
|
@rm -rf $(DESTDIR)$(PREFIX)/share/btop
|
||||||
|
|
||||||
distclean:
|
clean:
|
||||||
rm -f btop
|
rm -rf bin
|
||||||
|
529
btop.cpp
529
btop.cpp
@ -31,159 +31,63 @@ tab-size = 4
|
|||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <ranges>
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <termios.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
|
|
||||||
|
#include <btop_globs.h>
|
||||||
|
#include <btop_tools.h>
|
||||||
|
#include <btop_config.h>
|
||||||
|
|
||||||
|
#if defined(__linux__)
|
||||||
|
#define SYSTEM "linux"
|
||||||
|
#elif defined(__unix__) || !defined(__APPLE__) && defined(__MACH__)
|
||||||
|
#include <sys/param.h>
|
||||||
|
#if defined(BSD)
|
||||||
|
#define SYSTEM "bsd"
|
||||||
|
#else
|
||||||
|
#define SYSTEM "unknown"
|
||||||
|
#endif
|
||||||
|
#elif defined(__APPLE__) && defined(__MACH__)
|
||||||
|
#include <TargetConditionals.h>
|
||||||
|
#if TARGET_OS_MAC == 1
|
||||||
|
#define SYSTEM "osx"
|
||||||
|
#else
|
||||||
|
#define SYSTEM "unknown"
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define SYSTEM "unknown"
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
//? ------------------------------------------------- GLOBALS ---------------------------------------------------------
|
//? ------------------------------------------------- GLOBALS ---------------------------------------------------------
|
||||||
|
|
||||||
const vector<vector<string>> BANNER_SRC = {
|
namespace Global {
|
||||||
|
const vector<vector<string>> Banner_src = {
|
||||||
{"#E62525", "██████╗ ████████╗ ██████╗ ██████╗"},
|
{"#E62525", "██████╗ ████████╗ ██████╗ ██████╗"},
|
||||||
{"#CD2121", "██╔══██╗╚══██╔══╝██╔═══██╗██╔══██╗ ██╗ ██╗"},
|
{"#CD2121", "██╔══██╗╚══██╔══╝██╔═══██╗██╔══██╗ ██╗ ██╗"},
|
||||||
{"#B31D1D", "██████╔╝ ██║ ██║ ██║██████╔╝ ██████╗██████╗"},
|
{"#B31D1D", "██████╔╝ ██║ ██║ ██║██████╔╝ ██████╗██████╗"},
|
||||||
{"#9A1919", "██╔══██╗ ██║ ██║ ██║██╔═══╝ ╚═██╔═╝╚═██╔═╝"},
|
{"#9A1919", "██╔══██╗ ██║ ██║ ██║██╔═══╝ ╚═██╔═╝╚═██╔═╝"},
|
||||||
{"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"},
|
{"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"},
|
||||||
{"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"},
|
{"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"},
|
||||||
};
|
};
|
||||||
|
|
||||||
const string VERSION = "0.0.1";
|
const string Version = "0.0.1";
|
||||||
|
}
|
||||||
|
|
||||||
const 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 map<string, map<string, vector<string>>> MENUS = {
|
|
||||||
{ "options", {
|
|
||||||
{ "normal",
|
|
||||||
{ "┌─┐┌─┐┌┬┐┬┌─┐┌┐┌┌─┐",
|
|
||||||
"│ │├─┘ │ ││ ││││└─┐",
|
|
||||||
"└─┘┴ ┴ ┴└─┘┘└┘└─┘"
|
|
||||||
} },
|
|
||||||
{ "selected",
|
|
||||||
{ "╔═╗╔═╗╔╦╗╦╔═╗╔╗╔╔═╗",
|
|
||||||
"║ ║╠═╝ ║ ║║ ║║║║╚═╗",
|
|
||||||
"╚═╝╩ ╩ ╩╚═╝╝╚╝╚═╝"
|
|
||||||
} }
|
|
||||||
} },
|
|
||||||
{ "help", {
|
|
||||||
{ "normal",
|
|
||||||
{ "┬ ┬┌─┐┬ ┌─┐",
|
|
||||||
"├─┤├┤ │ ├─┘",
|
|
||||||
"┴ ┴└─┘┴─┘┴ "
|
|
||||||
} },
|
|
||||||
{ "selected",
|
|
||||||
{ "╦ ╦╔═╗╦ ╔═╗",
|
|
||||||
"╠═╣║╣ ║ ╠═╝",
|
|
||||||
"╩ ╩╚═╝╩═╝╩ "
|
|
||||||
} }
|
|
||||||
} },
|
|
||||||
{ "quit", {
|
|
||||||
{ "normal",
|
|
||||||
{ "┌─┐ ┬ ┬ ┬┌┬┐",
|
|
||||||
"│─┼┐│ │ │ │ ",
|
|
||||||
"└─┘└└─┘ ┴ ┴ "
|
|
||||||
} },
|
|
||||||
{ "selected",
|
|
||||||
{ "╔═╗ ╦ ╦ ╦╔╦╗ ",
|
|
||||||
"║═╬╗║ ║ ║ ║ ",
|
|
||||||
"╚═╝╚╚═╝ ╩ ╩ "
|
|
||||||
} }
|
|
||||||
} }
|
|
||||||
};
|
|
||||||
|
|
||||||
#define Bool bool()
|
|
||||||
#define Int int()
|
|
||||||
#define String string()
|
|
||||||
|
|
||||||
//? ------------------------------------------------- NAMESPACES ------------------------------------------------------
|
|
||||||
|
|
||||||
namespace State {
|
|
||||||
atomic<bool> MenuActive(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
//? Collection of escape codes for text style and formatting
|
|
||||||
namespace Fx {
|
|
||||||
const string e = "\x1b["; //* Escape sequence start
|
|
||||||
const string r = e + "0m"; //* Reset foreground/background color and text effects
|
|
||||||
const string b = e + "1m"; //* Bold on
|
|
||||||
const string ub = e + "22m"; //* Bold off
|
|
||||||
const string d = e + "2m"; //* Dark on
|
|
||||||
const string ud = e + "22m"; //* Dark off
|
|
||||||
const string i = e + "3m"; //* Italic on
|
|
||||||
const string ui = e + "23m"; //* Italic off
|
|
||||||
const string ul = e + "4m"; //* Underline on
|
|
||||||
const string uul = e + "24m"; //* Underline off
|
|
||||||
const string bl = e + "5m"; //* Blink on
|
|
||||||
const string ubl = e + "25m"; //* Blink off
|
|
||||||
const string s = e + "9m"; //* Strike / crossed-out on
|
|
||||||
const string us = e + "29m"; //* Strike / crossed-out off
|
|
||||||
};
|
|
||||||
|
|
||||||
//? Collection of escape codes and functions for cursor manipulation
|
|
||||||
namespace Mv {
|
|
||||||
string to(int line, int col){ return Fx::e + to_string(line) + ";" + to_string(col) + "f";} //* Move cursor to line, column
|
|
||||||
string r(int x){ return Fx::e + to_string(x) + "C";} //* Move cursor right x columns
|
|
||||||
string l(int x){ return Fx::e + to_string(x) + "D";} //* Move cursor left x columns
|
|
||||||
string u(int x){ return Fx::e + to_string(x) + "A";} //* Move cursor up x lines
|
|
||||||
string d(int x) { return Fx::e + to_string(x) + "B";} //* Move cursor down x lines
|
|
||||||
const string save = Fx::e + "s"; //* Save cursor position
|
|
||||||
const string restore = Fx::e + "u"; //* Restore saved cursor postion
|
|
||||||
};
|
|
||||||
|
|
||||||
//? --------------------------------------- FUNCTIONS, STRUCTS & CLASSES ----------------------------------------------
|
//? --------------------------------------- FUNCTIONS, STRUCTS & CLASSES ----------------------------------------------
|
||||||
|
|
||||||
//? A simple argument parser
|
//* A simple argument parser
|
||||||
void argumentParser(int argc, char **argv){
|
void argumentParser(int argc, char **argv){
|
||||||
string argument;
|
string argument;
|
||||||
for(int i = 1; i < argc; i++) {
|
for(int i = 1; i < argc; i++) {
|
||||||
argument = argv[i];
|
argument = argv[i];
|
||||||
if (argument == "-v" || argument == "--version") {
|
if (argument == "-v" || argument == "--version") {
|
||||||
cout << "btop version: " << VERSION << endl;
|
cout << "btop version: " << Global::Version << endl;
|
||||||
exit(0);
|
exit(0);
|
||||||
} else if (argument == "-h" || argument == "--help") {
|
} else if (argument == "-h" || argument == "--help") {
|
||||||
cout << "help here" << endl;
|
cout << "help here" << endl;
|
||||||
@ -196,291 +100,7 @@ void argumentParser(int argc, char **argv){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//? Return number of UTF8 characters in a string
|
//* Functions and variables for handling keyboard and mouse input
|
||||||
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 chrono::duration_cast<chrono::milliseconds>(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;
|
|
||||||
}
|
|
||||||
|
|
||||||
//? Collection of escape codes and functions for terminal manipulation
|
|
||||||
class C_Term {
|
|
||||||
bool initialized = false;
|
|
||||||
struct termios initial_settings;
|
|
||||||
public:
|
|
||||||
int width = 0;
|
|
||||||
int height = 0;
|
|
||||||
bool resized = false;
|
|
||||||
string fg = "" ; //* Default foreground color
|
|
||||||
string bg = ""; //* Default background color
|
|
||||||
const string hide_cursor = Fx::e + "?25l"; //* Hide terminal cursor
|
|
||||||
const string show_cursor = Fx::e + "?25h"; //* Show terminal cursor
|
|
||||||
const string alt_screen = Fx::e + "?1049h"; //* Switch to alternate screen
|
|
||||||
const string normal_screen = Fx::e + "?1049l"; //* Switch to normal screen
|
|
||||||
const string clear = Fx::e + "2J" + Fx::e + "0;0f"; //* Clear screen and set cursor to position 0,0
|
|
||||||
const string mouse_on = Fx::e + "?1002h" + Fx::e + "?1015h" + Fx::e + "?1006h"; //* Enable reporting of mouse position on click and release
|
|
||||||
const string mouse_off = Fx::e + "?1002l"; //* Disable mouse reporting
|
|
||||||
const string mouse_direct_on = Fx::e + "?1003h"; //* Enable reporting of mouse position at any movement
|
|
||||||
const string mouse_direct_off = Fx::e + "?1003l"; //* Disable direct mouse reporting
|
|
||||||
|
|
||||||
//? Save terminal options and check valid tty
|
|
||||||
bool init(){
|
|
||||||
if (!initialized){
|
|
||||||
initialized = (bool)isatty(STDIN_FILENO);
|
|
||||||
if (initialized) initialized = (0 == tcgetattr(STDIN_FILENO, &initial_settings));
|
|
||||||
if (initialized) cin.sync_with_stdio();
|
|
||||||
}
|
|
||||||
return initialized;
|
|
||||||
}
|
|
||||||
|
|
||||||
//? Restore terminal options
|
|
||||||
void restore(){
|
|
||||||
if (initialized) tcsetattr(STDIN_FILENO, TCSANOW, &initial_settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
//? Toggle need for return key when reading input
|
|
||||||
bool linebuffered(bool on=true){
|
|
||||||
struct termios settings;
|
|
||||||
if (tcgetattr(STDIN_FILENO, &settings)) return false;
|
|
||||||
if (on) settings.c_lflag |= ICANON;
|
|
||||||
else settings.c_lflag &= ~(ICANON);
|
|
||||||
if (tcsetattr(STDIN_FILENO, TCSANOW, &settings)) return false;
|
|
||||||
if (on) setlinebuf(stdin);
|
|
||||||
else setbuf(stdin, NULL);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//? Toggle terminal input echo
|
|
||||||
bool echo(bool on=true){
|
|
||||||
struct termios settings;
|
|
||||||
if (tcgetattr(STDIN_FILENO, &settings)) return false;
|
|
||||||
if (on) settings.c_lflag |= ECHO;
|
|
||||||
else settings.c_lflag &= ~(ECHO);
|
|
||||||
return 0 == tcsetattr(STDIN_FILENO, TCSANOW, &settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
//? Refresh variables holding current terminal width and height and return true if resized
|
|
||||||
bool refresh(){
|
|
||||||
struct winsize w;
|
|
||||||
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
|
|
||||||
resized = (width != w.ws_col || height != w.ws_row) ? true : false;
|
|
||||||
width = w.ws_col;
|
|
||||||
height = w.ws_row;
|
|
||||||
return resized;
|
|
||||||
}
|
|
||||||
|
|
||||||
C_Term() {
|
|
||||||
init();
|
|
||||||
refresh();
|
|
||||||
resized = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
C_Term Term; //* Make C_Term globally available as Term
|
|
||||||
|
|
||||||
class C_Config {
|
|
||||||
map<string, string> strings = {
|
|
||||||
{"color_theme", "Default"},
|
|
||||||
{"shown_boxes", "cpu mem net proc"},
|
|
||||||
{"proc_sorting", "cpu lazy"},
|
|
||||||
{"cpu_graph_upper", "total"},
|
|
||||||
{"cpu_graph_lower", "total"},
|
|
||||||
{"cpu_sensor", "Auto"},
|
|
||||||
{"temp_scale", "celsius"},
|
|
||||||
{"draw_clock", "%X"},
|
|
||||||
{"custom_cpu_name", ""},
|
|
||||||
{"disks_filter", ""},
|
|
||||||
{"io_graph_speeds", ""},
|
|
||||||
{"net_download", "10M"},
|
|
||||||
{"net_upload", "10M"},
|
|
||||||
{"net_iface", ""},
|
|
||||||
{"log_level", "WARNING"}
|
|
||||||
};
|
|
||||||
map<string, bool> bools = {
|
|
||||||
{"theme_background", true},
|
|
||||||
{"truecolor", true},
|
|
||||||
{"proc_reversed", false},
|
|
||||||
{"proc_tree", false},
|
|
||||||
{"proc_colors", true},
|
|
||||||
{"proc_gradient", true},
|
|
||||||
{"proc_per_core", false},
|
|
||||||
{"proc_mem_bytes", true},
|
|
||||||
{"cpu_invert_lower", true},
|
|
||||||
{"cpu_single_graph", false},
|
|
||||||
{"show_uptime", true},
|
|
||||||
{"check_temp", true},
|
|
||||||
{"show_coretemp", true},
|
|
||||||
{"show_cpu_freq", true},
|
|
||||||
{"background_update", true},
|
|
||||||
{"update_check", true},
|
|
||||||
{"mem_graphs", true},
|
|
||||||
{"show_swap", true},
|
|
||||||
{"swap_disk", true},
|
|
||||||
{"show_disks", true},
|
|
||||||
{"only_physical", true},
|
|
||||||
{"use_fstab", false},
|
|
||||||
{"show_io_stat", true},
|
|
||||||
{"io_mode", false},
|
|
||||||
{"io_graph_combined", false},
|
|
||||||
{"net_color_fixed", false},
|
|
||||||
{"net_auto", true},
|
|
||||||
{"net_sync", false},
|
|
||||||
{"show_battery", true},
|
|
||||||
{"show_init", false}
|
|
||||||
};
|
|
||||||
map<string, int> ints = {
|
|
||||||
{"update_ms", 2000},
|
|
||||||
{"proc_update_mult", 2},
|
|
||||||
{"tree_depth", 3}
|
|
||||||
};
|
|
||||||
public:
|
|
||||||
C_Config(){
|
|
||||||
bools["truecolor"] = "true";
|
|
||||||
strings["color_theme"] = "Default";
|
|
||||||
ints["tree_depth"] = 3;
|
|
||||||
}
|
|
||||||
bool operator()(bool b_type, string name){
|
|
||||||
return bools.at(name);
|
|
||||||
}
|
|
||||||
int operator()(int i_type, string name){
|
|
||||||
return ints.at(name);
|
|
||||||
}
|
|
||||||
string operator()(string s_type, string name){
|
|
||||||
return strings.at(name);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
C_Config Config;
|
|
||||||
|
|
||||||
//? Functions and variables for handling keyboard and mouse input
|
|
||||||
class C_Key {
|
class C_Key {
|
||||||
const map<string, string> KEY_ESCAPES = {
|
const map<string, string> KEY_ESCAPES = {
|
||||||
{"\033", "escape"},
|
{"\033", "escape"},
|
||||||
@ -538,9 +158,9 @@ class C_Key {
|
|||||||
public:
|
public:
|
||||||
string last = "";
|
string last = "";
|
||||||
|
|
||||||
//? Wait <timeout> ms for input on stdin and return true if available
|
//* Wait <timeout> ms for input on stdin and return true if available
|
||||||
//? 0 to just check for input
|
//* 0 to just check for input
|
||||||
//? -1 for infinite wait
|
//* -1 for infinite wait
|
||||||
bool operator()(int timeout){
|
bool operator()(int timeout){
|
||||||
if (wait(timeout)) {
|
if (wait(timeout)) {
|
||||||
last = get();
|
last = get();
|
||||||
@ -551,61 +171,62 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//? Return last entered key
|
//* Return last entered key
|
||||||
string operator()(){
|
string operator()(){
|
||||||
return last;
|
return last;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
C_Key Key; //* Make C_Key globally available as Key
|
|
||||||
|
|
||||||
class C_Theme {
|
class C_Theme {
|
||||||
map<string, string> c;
|
map<string, string> c;
|
||||||
map<string, vector<string>> g;
|
map<string, vector<string>> g;
|
||||||
|
C_Config conf;
|
||||||
|
|
||||||
map<string,string> generate(map<string, string>& source){
|
map<string,string> generate(map<string, string>& source){
|
||||||
map<string, string> out;
|
map<string, string> out;
|
||||||
vector<string> t_rgb;
|
vector<string> t_rgb;
|
||||||
string depth;
|
string depth;
|
||||||
for (auto& item : DEFAULT_THEME) {
|
for (auto& item : Global::Default_theme) {
|
||||||
depth = (item.first.ends_with("bg")) ? "bg" : "fg";
|
depth = (item.first.ends_with("bg")) ? "bg" : "fg";
|
||||||
if (source.count(item.first)) {
|
if (source.count(item.first)) {
|
||||||
if (source.at(item.first)[0] == '#') out[item.first] = hex_to_color(source.at(item.first), !Config(Bool, "truecolor"), depth);
|
if (source.at(item.first)[0] == '#') out[item.first] = hex_to_color(source.at(item.first), !State::truecolor, depth);
|
||||||
else {
|
else {
|
||||||
t_rgb = ssplit(source.at(item.first), " ");
|
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]), !Config(Bool, "truecolor"), depth);
|
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] = "";
|
else out[item.first] = "";
|
||||||
if (out[item.first] == "") out[item.first] = hex_to_color(item.second, !Config(Bool, "truecolor"), depth);
|
if (out[item.first] == "") out[item.first] = hex_to_color(item.second, !State::truecolor, depth);
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void swap(map<string, string>& source){
|
//* Change to theme using <source> map
|
||||||
|
void change(map<string, string> source){
|
||||||
c = generate(source);
|
c = generate(source);
|
||||||
Term.fg = c.at("main_fg");
|
State::fg = c.at("main_fg");
|
||||||
Term.bg = c.at("main_bg");
|
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
|
//* Generate theme from <source> map, default to DEFAULT_THEME on missing or malformatted values
|
||||||
C_Theme(map<string, string> source){
|
C_Theme(map<string, string> source){
|
||||||
swap(source);
|
change(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
//? Return escape code for color <name>
|
//* Return escape code for color <name>
|
||||||
auto operator()(string name){
|
auto operator()(string name){
|
||||||
return c.at(name);
|
return c.at(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
//? Return vector of escape codes for color gradient <name>
|
//* Return vector of escape codes for color gradient <name>
|
||||||
auto gradient(string name){
|
auto gradient(string name){
|
||||||
return g.at(name);
|
return g.at(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
//? Return map of decimal int's (r, g, b) for color <name>
|
//* Return map of decimal int's (r, g, b) for color <name>
|
||||||
auto rgb(string name){
|
auto rgb(string name){
|
||||||
return c_to_rgb(c.at(name));
|
return c_to_rgb(c.at(name));
|
||||||
}
|
}
|
||||||
@ -622,7 +243,7 @@ struct C_Banner {
|
|||||||
int bg_i;
|
int bg_i;
|
||||||
int new_len;
|
int new_len;
|
||||||
banner_str = "";
|
banner_str = "";
|
||||||
for (auto line: BANNER_SRC) {
|
for (auto line: Global::Banner_src) {
|
||||||
new_len = ulen(line[1]);
|
new_len = ulen(line[1]);
|
||||||
if (new_len > width) width = new_len;
|
if (new_len > width) width = new_len;
|
||||||
fg = hex_to_color(line[0]);
|
fg = hex_to_color(line[0]);
|
||||||
@ -641,24 +262,23 @@ struct C_Banner {
|
|||||||
oc = b_color;
|
oc = b_color;
|
||||||
}
|
}
|
||||||
z++;
|
z++;
|
||||||
if (z < BANNER_SRC.size()) out += Mv::l(ulen(line[1])) + Mv::d(1);
|
if (z < Global::Banner_src.size()) out += Mv::l(ulen(line[1])) + Mv::d(1);
|
||||||
}
|
}
|
||||||
banner_str = out + Mv::r(18 - VERSION.size()) + Fx::i + dec_to_color(150, 150, 150) +
|
banner_str = out + Mv::r(18 - Global::Version.size()) + Fx::i + dec_to_color(0,0,0, State::truecolor, "bg") + dec_to_color(150, 150, 150) + "v" + Global::Version;
|
||||||
"v" + VERSION + Fx::r + Term.bg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//? Returns the pre-generated btop++ banner
|
//* Returns the pre-generated btop++ banner
|
||||||
string operator() (){
|
string operator() (){
|
||||||
return banner_str + Term.fg;
|
return banner_str + Fx::reset;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
C_Banner Banner;
|
|
||||||
|
|
||||||
//? --------------------------------------------- Main starts here! ---------------------------------------------------
|
//? --------------------------------------------- Main starts here! ---------------------------------------------------
|
||||||
int main(int argc, char **argv){
|
int main(int argc, char **argv){
|
||||||
int debug = 2;
|
int debug = 0;
|
||||||
int tests = 8;
|
int tests = 0;
|
||||||
|
|
||||||
//? Init
|
//? Init
|
||||||
|
|
||||||
@ -666,17 +286,18 @@ int main(int argc, char **argv){
|
|||||||
|
|
||||||
if (argc > 1) argumentParser(argc, argv);
|
if (argc > 1) argumentParser(argc, argv);
|
||||||
|
|
||||||
if (!Term.init()) {
|
C_Term Term;
|
||||||
|
|
||||||
|
if (!Term.initialized) {
|
||||||
cout << "No terminal detected!" << endl;
|
cout << "No terminal detected!" << endl;
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
Term.echo(false);
|
|
||||||
Term.linebuffered(false);
|
|
||||||
|
|
||||||
ios_base::sync_with_stdio(false);
|
|
||||||
cin.tie(NULL);
|
|
||||||
|
|
||||||
C_Theme Theme(DEFAULT_THEME);
|
C_Config Config;
|
||||||
|
C_Theme Theme(Global::Default_theme);
|
||||||
|
C_Banner Banner;
|
||||||
|
C_Key Key;
|
||||||
|
|
||||||
cout << Theme("main_bg") << Term.clear << flush;
|
cout << Theme("main_bg") << Term.clear << flush;
|
||||||
// bool thread_test = false;
|
// bool thread_test = false;
|
||||||
@ -690,7 +311,7 @@ int main(int argc, char **argv){
|
|||||||
|
|
||||||
|
|
||||||
//* Test MENUS
|
//* Test MENUS
|
||||||
for (auto& outer : MENUS){
|
for (auto& outer : Global::Menus){
|
||||||
for (auto& inner : outer.second){
|
for (auto& inner : outer.second){
|
||||||
for (auto& item : inner.second){
|
for (auto& item : inner.second){
|
||||||
cout << item << endl;
|
cout << item << endl;
|
||||||
@ -703,10 +324,6 @@ int main(int argc, char **argv){
|
|||||||
if (korv5.starts_with("hej")) cout << "hej" << endl;
|
if (korv5.starts_with("hej")) cout << "hej" << endl;
|
||||||
|
|
||||||
|
|
||||||
State::MenuActive.store(true);
|
|
||||||
|
|
||||||
if (State::MenuActive.load()) cout << "WHUUUU and time: " << time_ms() << endl;
|
|
||||||
|
|
||||||
//cout << korv2.size() << " " << ulen(korv2) << endl;
|
//cout << korv2.size() << " " << ulen(korv2) << endl;
|
||||||
|
|
||||||
cout << Config(Bool, "truecolor") << endl;
|
cout << Config(Bool, "truecolor") << endl;
|
||||||
@ -715,15 +332,15 @@ int main(int argc, char **argv){
|
|||||||
|
|
||||||
//* Test theme
|
//* Test theme
|
||||||
int i = 0;
|
int i = 0;
|
||||||
if (tests==0) for(auto& item : DEFAULT_THEME) {
|
if (tests==0) for(auto& item : Global::Default_theme) {
|
||||||
cout << Theme(item.first) << item.first << ":" << Term.fg << Theme(item.first).erase(0, 1) << Term.bg << " ";
|
cout << Theme(item.first) << item.first << ":" << Theme("main_fg") << Theme(item.first).erase(0, 2) << Fx::reset << " ";
|
||||||
if (++i == 4) {
|
if (++i == 4) {
|
||||||
i = 0;
|
i = 0;
|
||||||
cout << endl;
|
cout << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cout << Term.fg << endl;
|
cout << Fx::reset << endl;
|
||||||
|
|
||||||
// if (thread_test){
|
// if (thread_test){
|
||||||
// int max = 50000;
|
// int max = 50000;
|
||||||
@ -768,7 +385,7 @@ int main(int argc, char **argv){
|
|||||||
|
|
||||||
|
|
||||||
if (tests>3){
|
if (tests>3){
|
||||||
auto nbcolor = hex_to_color(DEFAULT_THEME.at("net_box"));
|
auto nbcolor = hex_to_color(Global::Default_theme.at("net_box"));
|
||||||
auto nbcolor_rgb = c_to_rgb(nbcolor);
|
auto nbcolor_rgb = c_to_rgb(nbcolor);
|
||||||
auto nbcolor_man = ssplit(nbcolor, ";");
|
auto nbcolor_man = ssplit(nbcolor, ";");
|
||||||
cout << nbcolor << "Some color" << endl;
|
cout << nbcolor << "Some color" << endl;
|
||||||
|
Loading…
Reference in New Issue
Block a user