Added Draw::calcSizes() and Proc::draw()

This commit is contained in:
aristocratos 2021-07-04 22:02:31 +02:00
parent ad5864266a
commit 1ff9e218d3
8 changed files with 395 additions and 134 deletions

View file

@ -219,14 +219,9 @@ void banner_gen() {
+ Fx::i + "v" + Global::Version + Fx::ui;
}
//* Threading test function
// string my_worker(int x){
// for (int i = 0; i < 100 + (x * 100); i++){
// sleep_ms(10);
// if (Global::stop_all.load()) return "Thread stopped! x=" + to_string(x);
// }
// return "Thread done! x=" + to_string(x);
// }
namespace Runner {
atomic<bool> active (false);
}
//? --------------------------------------------- Main starts here! ---------------------------------------------------
@ -351,23 +346,33 @@ int main(int argc, char **argv){
Global::debuginit = true;
Draw::calcSizes();
// cout << Cpu::box << Mem::box << Net::box << Proc::box << flush;
// cout << Theme("main_bg") << Term::clear << flush;
// bool thread_test = false;
if (not Global::debuginit) cout << Term::alt_screen << Term::hide_cursor << flush;
if (not Global::debuginit) cout << Term::alt_screen << Term::hide_cursor << Term::clear << endl;
cout << Theme::c("main_fg") << Theme::c("main_bg") << Term::clear << endl;
// cout << Theme::c("main_fg") << Theme::c("main_bg") << Term::clear << endl;
cout << Mv::r(Term::width / 2 - Global::banner_width / 2) << Global::banner << endl;
// cout << string(Term::width - 1, '-') << endl;
size_t blen = (Term::width > 200) ? 200 : Term::width;
if (Term::width > 203) cout << Mv::r(Term::width / 2 - blen / 2) << flush;
int ill = 0;
for (int i : iota(0, (int)blen)){
ill = (i <= (int)blen / 2) ? i : ill - 1;
cout << Theme::g("used")[ill] << Symbols::h_line;
// cout << Mv::r(Term::width / 2 - Global::banner_width / 2) << Global::banner << endl;
// // cout << string(Term::width - 1, '-') << endl;
// size_t blen = (Term::width > 200) ? 200 : Term::width;
// if (Term::width > 203) cout << Mv::r(Term::width / 2 - blen / 2) << flush;
// int ill = 0;
// for (int i : iota(0, (int)blen)){
// ill = (i <= (int)blen / 2) ? i : ill - 1;
// cout << Theme::g("used")[ill] << Symbols::h_line;
// }
// cout << Fx::reset << endl;
if (false) {
Draw::calcSizes();
cout << Cpu::box << Mem::box << Net::box << Proc::box << flush;
Input::wait();
exit(0);
}
cout << Fx::reset << endl;
//* Test theme
if (false) {
@ -479,9 +484,9 @@ int main(int argc, char **argv){
Draw::Graph kgraph2 {};
Draw::Graph kgraph3 {};
cout << Draw::createBox({.x = 5, .y = 10, .width = Term::width - 10, .height = 12, .line_color = Theme::c("proc_box"), .title = "braille", .fill = false, .num = 1}) << Mv::save;
cout << Draw::createBox({.x = 5, .y = 23, .width = Term::width - 10, .height = 12, .line_color = Theme::c("proc_box"), .title = "block", .fill = false, .num = 2});
cout << Draw::createBox({.x = 5, .y = 36, .width = Term::width - 10, .height = 12, .line_color = Theme::c("proc_box"), .title = "tty", .fill = false, .num = 3}) << flush;
cout << Draw::createBox(5, 10, Term::width - 10, 12, Theme::c("proc_box"), false, "braille", "", 1) << Mv::save;
cout << Draw::createBox(5, 23, Term::width - 10, 12, Theme::c("proc_box"), false, "block", "", 2);
cout << Draw::createBox(5, 36, Term::width - 10, 12, Theme::c("proc_box"), false, "tty", "", 3) << flush;
// Draw::Meter kmeter {};
// Draw::Graph kgraph2 {};
// Draw::Graph kgraph3 {};
@ -595,12 +600,10 @@ int main(int argc, char **argv){
size_t lc;
string ostring;
uint64_t tsl, timestamp2, rcount = 0;
list<uint64_t> avgtimes;
size_t timer = 2000;
bool filtering = false;
vector<string> greyscale;
string filter;
string filter_cur;
@ -613,9 +616,9 @@ int main(int argc, char **argv){
greyscale.push_back(Theme::dec_to_color(xc, xc, xc));
}
string pbox = Draw::createBox({.x = 1, .y = 10, .width = Term::width, .height = Term::height - 18, .line_color = Theme::c("proc_box"), .title = "testbox", .title2 = "below", .fill = false, .num = 7});
pbox += Mv::r(1) + Theme::c("title") + Fx::b + rjust("Pid:", 8) + " " + ljust("Program:", 16) + " " + ljust("Command:", Term::width - 70) + " Threads: " +
ljust("User:", 10) + " " + rjust("MemB", 5) + " " + rjust("Cpu%", 14) + "\n" + Fx::reset + Mv::save;
// string pbox = Draw::createBox(1, 10, Term::width, Term::height - 18, Theme::c("proc_box"), false, "testbox", "below", 7);
// pbox += Mv::r(1) + Theme::c("title") + Fx::b + rjust("Pid:", 8) + " " + ljust("Program:", 16) + " " + ljust("Command:", Term::width - 70) + " Threads: " +
// ljust("User:", 10) + " " + rjust("MemB", 5) + " " + rjust("Cpu%", 14) + "\n" + Fx::reset + Mv::save;
while (key != "q") {
timestamp = time_micros();
@ -630,62 +633,62 @@ int main(int argc, char **argv){
timestamp2 = time_micros();
timestamp = timestamp2 - timestamp;
ostring.clear();
lc = 0;
// lc = 0;
ostring = Mv::u(2) + Mv::l(Term::width) + Mv::r(12)
+ trans("Filter: " + filter + (filtering ? Fx::bl + "" + Fx::reset : " "))
+ trans(rjust("Per core: " + (Config::getB("proc_per_core") ? "On "s : "Off"s) + " Sorting: "
+ string(Config::getS("proc_sorting")), Term::width - 23 - ulen(filter)))
+ Mv::restore;
// ostring = Mv::u(2) + Mv::l(Term::width) + Mv::r(12)
// + trans("Filter: " + filter + (filtering ? Fx::bl + "█" + Fx::reset : " "))
// + trans(rjust("Per core: " + (Config::getB("proc_per_core") ? "On "s : "Off"s) + " Sorting: "
// + string(Config::getS("proc_sorting")), Term::width - 23 - ulen(filter)))
// + Mv::restore;
for (auto& p : plist){
if (not Config::getB("proc_tree")) {
ostring += Mv::r(1) + greyscale[lc] + rjust(to_string(p.pid), 8) + " " + ljust(p.name, 16) + " " + ljust(p.cmd, Term::width - 66, true) + " "
+ rjust(to_string(p.threads), 5) + " " + ljust(p.user, 10) + " " + rjust(floating_humanizer(p.mem, true), 5) + string(11, ' ')
+ (p.cpu_p < 10 or p.cpu_p >= 100 ? rjust(to_string(p.cpu_p), 3) + " " : rjust(to_string(p.cpu_p), 4))
+ "\n";
}
else {
string cmd_cond;
if (not p.cmd.empty()) {
cmd_cond = p.cmd.substr(0, std::min(p.cmd.find(' '), p.cmd.size()));
cmd_cond = cmd_cond.substr(std::min(cmd_cond.find_last_of('/') + 1, cmd_cond.size()));
}
ostring += Mv::r(1) + (Config::getB("tty_mode") ? "" : greyscale[lc]) + ljust(p.prefix + to_string(p.pid) + " " + p.name + " "
+ (not cmd_cond.empty() and cmd_cond != p.name ? "(" + cmd_cond + ")" : ""), Term::width - 40, true) + " "
+ rjust(to_string(p.threads), 5) + " " + ljust(p.user, 10) + " " + rjust(floating_humanizer(p.mem, true), 5) + string(11, ' ')
+ (p.cpu_p < 10 or p.cpu_p >= 100 ? rjust(to_string(p.cpu_p), 3) + " " : rjust(to_string(p.cpu_p), 4))
+ "\n";
}
if (lc++ > Term::height - 23) break;
}
while (lc++ < Term::height - 21) ostring += Mv::r(1) + string(Term::width - 2, ' ') + "\n";
// for (auto& p : plist){
// if (not Config::getB("proc_tree")) {
// ostring += Mv::r(1) + greyscale[lc] + rjust(to_string(p.pid), 8) + " " + ljust(p.name, 16) + " " + ljust(p.cmd, Term::width - 66, true) + " "
// + rjust(to_string(p.threads), 5) + " " + ljust(p.user, 10) + " " + rjust(floating_humanizer(p.mem, true), 5) + string(11, ' ')
// + (p.cpu_p < 10 or p.cpu_p >= 100 ? rjust(to_string(p.cpu_p), 3) + " " : rjust(to_string(p.cpu_p), 4))
// + "\n";
// }
// else {
// string cmd_cond;
// if (not p.cmd.empty()) {
// cmd_cond = p.cmd.substr(0, std::min(p.cmd.find(' '), p.cmd.size()));
// cmd_cond = cmd_cond.substr(std::min(cmd_cond.find_last_of('/') + 1, cmd_cond.size()));
// }
// ostring += Mv::r(1) + (Config::getB("tty_mode") ? "" : greyscale[lc]) + ljust(p.prefix + to_string(p.pid) + " " + p.name + " "
// + (not cmd_cond.empty() and cmd_cond != p.name ? "(" + cmd_cond + ")" : ""), Term::width - 40, true) + " "
// + rjust(to_string(p.threads), 5) + " " + ljust(p.user, 10) + " " + rjust(floating_humanizer(p.mem, true), 5) + string(11, ' ')
// + (p.cpu_p < 10 or p.cpu_p >= 100 ? rjust(to_string(p.cpu_p), 3) + " " : rjust(to_string(p.cpu_p), 4))
// + "\n";
// }
// if (lc++ > Term::height - 23) break;
// }
// while (lc++ < Term::height - 21) ostring += Mv::r(1) + string(Term::width - 2, ' ') + "\n";
ostring = Proc::draw(plist);
avgtimes.push_front(timestamp);
if (avgtimes.size() > 30) avgtimes.pop_back();
cout << pbox << ostring << Fx::reset << "\n" << endl;
cout << ostring << Fx::reset << Mv::to(2, 2) << endl;
cout << " Details for " << Proc::detailed.entry.name << " (" << Proc::detailed.entry.pid << ") Status: " << Proc::detailed.status << " Elapsed: " << Proc::detailed.elapsed
<< " Mem: " << floating_humanizer(Proc::detailed.entry.mem) << " "
<< "\n Parent: " << Proc::detailed.parent << " IO in/out: " << Proc::detailed.io_read << "/" << Proc::detailed.io_write << " " << endl;
cout << Mv::to(Term::height - 4, 1) << "Processes call took: " << rjust(to_string(timestamp), 5) << " μs. Average: " <<
cout << Mv::to(4, 2) << "Processes call took: " << rjust(to_string(timestamp), 5) << " μs. Average: " <<
rjust(to_string(accumulate(avgtimes.begin(), avgtimes.end(), 0) / avgtimes.size()), 5) << " μs of " << avgtimes.size() <<
" samples. Drawing took: " << time_micros() - timestamp2 << " μs.\nNumber of processes: " << Proc::numpids << ". Number in vector: " << plist.size() << ". Run count: " <<
++rcount << ". Time: " << strf_time("%X ") << endl;
" samples. Drawing took: " << time_micros() - timestamp2 << " μs.\nNumber of processes: " << Proc::numpids << ". Number in vector: " << plist.size() << ". Run count: " << ++rcount << ". Time: " << strf_time("%X ") << endl;
while (time_ms() < tsl) {
if (Input::poll(tsl - time_ms())) key = Input::get();
else { key.clear() ; continue; }
if (filtering) {
if (key == "enter") filtering = false;
if (Config::getB("proc_filtering")) {
if (key == "enter") Config::set("proc_filtering", false);
else if (key == "backspace" and not filter.empty()) filter = uresize(filter, ulen(filter) - 1);
else if (key == "space") filter.push_back(' ');
else if (ulen(key) == 1 ) filter.append(key);
else { key.clear(); continue; }
if (filter != Config::getS("proc_filter")) Config::set("proc_filter", filter);
key.clear();
Proc::redraw = true;
break;
}
else if (key == "q") break;
@ -699,7 +702,7 @@ int main(int argc, char **argv){
if (++cur_i > (int)Proc::sort_vector.size() - 1) cur_i = 0;
Config::set("proc_sorting", Proc::sort_vector.at(cur_i));
}
else if (key == "f") filtering = true;
else if (key == "f") Config::flip("proc_filtering");
else if (key == "t") Config::flip("proc_tree");
else if (key == "r") Config::flip("proc_reversed");
else if (key == "c") Config::flip("proc_per_core");
@ -711,8 +714,10 @@ int main(int argc, char **argv){
}
}
else continue;
Proc::redraw = true;
break;
}
cout << Mv::to(Term::height - 3, 1) << flush;
}
// cout << "Found " << plist.size() << " pids\n" << endl;

View file

@ -212,6 +212,7 @@ namespace Config {
{"force_tty", false},
{"lowcolor", false},
{"show_detailed", false},
{"proc_filtering", false},
};
unordered_flat_map<string, bool> boolsTmp;
@ -278,6 +279,7 @@ namespace Config {
void unlock(){
if (not locked) return;
atomic_wait(Runner::active);
atomic_wait_set(writelock);
for (auto& item : stringsTmp){

View file

@ -29,9 +29,11 @@ tab-size = 4
#include <btop_tools.hpp>
using std::round, std::views::iota, std::string_literals::operator""s, std::clamp, std::array, std::floor;
using std::round, std::views::iota, std::string_literals::operator""s, std::clamp, std::array, std::floor, std::max, std::min,
std::to_string;
namespace rng = std::ranges;
using namespace Tools;
namespace Symbols {
const string h_line = "";
@ -98,44 +100,42 @@ namespace Symbols {
namespace Draw {
using namespace Tools;
string createBox(BoxConf c){
string createBox(int x, int y, int width, int height, string line_color, bool fill, string title, string title2, int num){
string out;
string lcolor = (c.line_color.empty()) ? Theme::c("div_line") : c.line_color;
string numbering = (c.num == 0) ? "" : Theme::c("hi_fg") + (Config::getB("tty_mode") ? std::to_string(c.num) : Symbols::superscript[c.num]);
string lcolor = (line_color.empty()) ? Theme::c("div_line") : line_color;
string numbering = (num == 0) ? "" : Theme::c("hi_fg") + (Config::getB("tty_mode") ? std::to_string(num) : Symbols::superscript[num]);
out = Fx::reset + lcolor;
//? Draw horizontal lines
for (size_t hpos : {c.y, c.y + c.height - 1}){
out += Mv::to(hpos, c.x) + Symbols::h_line * (c.width - 1);
for (int hpos : {y, y + height - 1}){
out += Mv::to(hpos, x) + Symbols::h_line * (width - 1);
}
//? Draw vertical lines and fill if enabled
for (size_t hpos : iota(c.y + 1, c.y + c.height - 1)){
out += Mv::to(hpos, c.x) + Symbols::v_line +
((c.fill) ? string(c.width - 2, ' ') : Mv::r(c.width - 2)) +
for (int hpos : iota(y + 1, y + height - 1)){
out += Mv::to(hpos, x) + Symbols::v_line +
((fill) ? string(width - 2, ' ') : Mv::r(width - 2)) +
Symbols::v_line;
}
//? Draw corners
out += Mv::to(c.y, c.x) + Symbols::left_up +
Mv::to(c.y, c.x + c.width - 1) + Symbols::right_up +
Mv::to(c.y + c.height - 1, c.x) + Symbols::left_down +
Mv::to(c.y + c.height - 1, c.x + c.width - 1) + Symbols::right_down;
out += Mv::to(y, x) + Symbols::left_up +
Mv::to(y, x + width - 1) + Symbols::right_up +
Mv::to(y + height - 1, x) + Symbols::left_down +
Mv::to(y + height - 1, x + width - 1) + Symbols::right_down;
//? Draw titles if defined
if (not c.title.empty()){
out += Mv::to(c.y, c.x + 2) + Symbols::title_left + Fx::b + numbering + Theme::c("title") + c.title +
if (not title.empty()){
out += Mv::to(y, x + 2) + Symbols::title_left + Fx::b + numbering + Theme::c("title") + title +
Fx::ub + lcolor + Symbols::title_right;
}
if (not c.title2.empty()){
out += Mv::to(c.y + c.height - 1, c.x + 2) + Symbols::title_left + Theme::c("title") + c.title2 +
if (not title2.empty()){
out += Mv::to(y + height - 1, x + 2) + Symbols::title_left + Theme::c("title") + title2 +
Fx::ub + lcolor + Symbols::title_right;
}
return out + Fx::reset + Mv::to(c.y + 1, c.x + 1);
return out + Fx::reset + Mv::to(y + 1, x + 1);
}
//* Meter class ------------------------------------------------------------------------------------------------------------>
@ -264,36 +264,258 @@ namespace Draw {
}
//*------------------------------------------------------------------------------------------------------------------------->
void calcSizes(){
}
}
namespace Cpu {
Draw::BoxConf box;
string background;
int width_p = 100, height_p = 32;
int min_w = 60, min_h = 8;
int x = 1, y = 1, width, height;
int b_columns, b_column_size;
int b_x, b_y, b_width, b_height;
bool shown = true, redraw = true;
string box;
}
namespace Mem {
Draw::BoxConf box;
string background;
int width_p = 45, height_p = 38;
int min_w = 36, min_h = 10;
int x = 1, y, width, height;
int mem_width, disks_width, divider, item_height, mem_size, mem_meter, graph_height, disk_meter;
bool shown = true, redraw = true;
string box;
}
namespace Net {
Draw::BoxConf box;
string background;
int width_p = 45, height_p = 30;
int min_w = 3, min_h = 6;
int x = 1, y, width, height;
int b_x, b_y, b_width, b_height, d_graph_height, u_graph_height;
int graph_height;
bool shown = true, redraw = true;
string box;
}
namespace Proc {
Draw::BoxConf box;
string background;
int width_p = 55, height_p = 68;
int min_w = 44, min_h = 16;
int x, y, width, height;
int current_y, current_h, select_max;
bool shown = true, redraw = true;
string box;
vector<string> greyscale;
vector<string> colorfade;
string draw(vector<proc_info> plist){
auto& filter = Config::getS("proc_filter");
auto& filtering = Config::getB("proc_filtering");
auto& proc_tree = Config::getB("proc_tree");
bool proc_gradient = (Config::getB("proc_gradient") and not Config::getB("tty_mode"));
string out;
if (redraw) {
redraw = false;
out = box;
greyscale.clear();
for (int xc = 0; size_t i : iota(0, height - 3)){
xc = 230 - i * 150 / (Term::height - 20);
greyscale.push_back(Theme::dec_to_color(xc, xc, xc));
}
out += Mv::to(y, x) + Mv::r(12)
+ trans("Filter: " + filter + (filtering ? Fx::bl + "" + Fx::reset : " "))
+ trans(rjust("Per core: " + (Config::getB("proc_per_core") ? "On "s : "Off"s) + " Sorting: "
+ string(Config::getS("proc_sorting")), width - 23 - ulen(filter)));
}
if (not proc_tree)
out += Mv::to(y+1, x+1) + Theme::c("title") + Fx::b + rjust("Pid:", 8) + " " + ljust("Program:", 16) + " "
+ ljust("Command:", width - 70) + " Threads: " + ljust("User:", 10) + " " + rjust("MemB", 5)
+ " " + rjust("Cpu%", 14) + Fx::ub;
else
out += Mv::to(y+1, x+1) + Theme::c("title") + Fx::b + rjust("Pid:", 8) + " " + ljust("Program:", 16) + " "
+ ljust("Command:", width - 70) + " Threads: " + ljust("User:", 10) + " " + rjust("MemB", 5)
+ " " + rjust("Cpu%", 14) + Fx::ub;
int lc = 0;
for (auto& p : plist){
if (not proc_tree) {
out += Mv::to(y+2+lc, x+1) + (proc_gradient ? greyscale[lc] : "") + rjust(to_string(p.pid), 8) + " " + ljust(p.name, 16) + " "
+ ljust(p.cmd, width - 67, true) + " " + rjust(to_string(p.threads), 5) + " " + ljust(p.user, 10) + " "
+ rjust(floating_humanizer(p.mem, true), 5) + string(11, ' ')
+ (p.cpu_p < 10 or p.cpu_p >= 100 ? rjust(to_string(p.cpu_p), 3) + " " : rjust(to_string(p.cpu_p), 4));
}
else {
string cmd_cond;
if (not p.cmd.empty()) {
cmd_cond = p.cmd.substr(0, min(p.cmd.find(' '), p.cmd.size()));
cmd_cond = cmd_cond.substr(min(cmd_cond.find_last_of('/') + 1, cmd_cond.size()));
}
out += Mv::to(y+2+lc, x+1) + (proc_gradient ? greyscale[lc] : "") + ljust(p.prefix + to_string(p.pid) + " " + p.name + " "
+ (not cmd_cond.empty() and cmd_cond != p.name ? "(" + cmd_cond + ")" : ""), width - 41, true) + " "
+ rjust(to_string(p.threads), 5) + " " + ljust(p.user, 10) + " " + rjust(floating_humanizer(p.mem, true), 5) + string(11, ' ')
+ (p.cpu_p < 10 or p.cpu_p >= 100 ? rjust(to_string(p.cpu_p), 3) + " " : rjust(to_string(p.cpu_p), 4));
}
if (lc++ > height - 5) break;
}
while (lc++ < height - 4) out += Mv::to(y+lc+2, x+1) + string(width - 3, ' ');
return out;
}
}
namespace Draw {
void calcSizes(){
Config::unlock();
auto& boxes = Config::getS("shown_boxes");
Cpu::box.clear();
Mem::box.clear();
Net::box.clear();
Proc::box.clear();
Cpu::width = Mem::width = Net::width = Proc::width = 0;
Cpu::height = Mem::height = Net::height = Proc::height = 0;
Cpu::redraw = Mem::redraw = Net::redraw = Proc::redraw = true;
Cpu::shown = s_contains(boxes, "cpu") ? true : false;
Mem::shown = s_contains(boxes, "mem") ? true : false;
Net::shown = s_contains(boxes, "net") ? true : false;
Proc::shown = s_contains(boxes, "proc") ? true : false;
//* Calculate and draw cpu box outlines
if (Cpu::shown) {
using namespace Cpu;
width = round(Term::width * width_p / 100);
height = max(8, (int)round(Term::height * (trim(boxes) == "cpu" ? 100 : height_p) / 100));
b_columns = max(1, (int)ceil((Global::coreCount + 1) / (height - 5)));
if (b_columns * (21 + 12 * got_sensors) < width - (width / 3)) {
b_column_size = 2;
b_width = (21 + 12 * got_sensors) * b_columns - (b_columns - 1);
}
else if (b_columns * (15 + 6 * got_sensors) < width - (width / 3)) {
b_column_size = 1;
b_width = (15 + 6 * got_sensors) * b_columns - (b_columns - 1);
}
else if (b_columns * (8 + 6 * got_sensors) < width - (width / 3)) {
b_column_size = 0;
}
else {
b_columns = (width - width / 3) / (8 + 6 * got_sensors);
b_column_size = 0;
}
if (b_column_size == 0) b_width = (8 + 6 * got_sensors) * b_columns + 1;
b_height = min(height - 2, (int)ceil(Global::coreCount / b_columns) + 4);
b_x = width - b_width - 1;
b_y = y + ceil((height - 2) / 2) - ceil(b_height / 2) + 1;
box = createBox(x, y, width, height, Theme::c("cpu_box"), true, "cpu", "", 1);
box += Mv::to(y, x + 10) + Theme::c("cpu_box") + Symbols::title_left + Fx::b + Theme::c("hi_fg")
+ 'M' + Theme::c("title") + "enu" + Fx::ub + Theme::c("cpu_box") + Symbols::title_right;
auto& custom = Config::getS("custom_cpu_name");
box += createBox(b_x, b_y, b_width, b_height, "", false, uresize((custom.empty() ? cpuName : custom) , b_width - 14));
}
//* Calculate and draw mem box outlines
if (Mem::shown) {
using namespace Mem;
auto& show_disks = Config::getB("show_disks");
auto& swap_disk = Config::getB("swap_disk");
auto& mem_graphs = Config::getB("mem_graphs");
// int hp;
// if (not Cpu::shown) hp = Net::shown ? 60 : 98;
// else if (not Net::shown) hp = 98 - Cpu::height_p;
// else hp = height_p;
width = round(Term::width * (Proc::shown ? width_p : 100) / 100);
height = round(Term::height * (100 - Cpu::height_p * Cpu::shown - Net::height_p * Net::shown) / 100) + 1;
if (height + Cpu::height > Term::height) height = Term::height - Cpu::height;
y = Cpu::height + 1;
if (show_disks) {
mem_width = ceil((width - 3) / 2);
disks_width = width - mem_width - 3;
mem_width += mem_width % 2;
divider = x + mem_width;
}
else
mem_width = width - 1;
item_height = has_swap and not swap_disk ? 6 : 4;
if (height - (has_swap and not swap_disk ? 3 : 2) > 2 * item_height)
mem_size = 3;
else if (mem_width > 25)
mem_size = 2;
else
mem_size = 1;
mem_meter = max(0, width - (disks_width * show_disks) - (mem_size > 2 ? 9 : 20));
if (mem_size == 1) mem_meter += 6;
if (mem_graphs) {
graph_height = max(1, (int)round(((height - (has_swap and not swap_disk ? 2 : 1)) - (mem_size == 3 ? 2 : 1) * item_height) / item_height));
if (graph_height > 1) mem_meter += 6;
}
else
graph_height = 0;
if (show_disks) {
disk_meter = max(0, width - mem_width - 23);
if (disks_width < 25) disk_meter += 10;
}
box = createBox(x, y, width, height, Theme::c("mem_box"), true, "mem", "", 2);
box += Mv::to(y, (show_disks ? divider + 2 : x + width - 9)) + Theme::c("mem_box") + Symbols::title_left + (show_disks ? Fx::b : "")
+ Theme::c("hi_fg") + 'd' + Theme::c("title") + "isks" + Fx::ub + Theme::c("mem_box") + Symbols::title_right;
if (show_disks) {
box += Mv::to(y, divider) + Symbols::div_up + Mv::to(y + height - 1, divider) + Symbols::div_down + Theme::c("div_line");
for (auto i : iota(1, height - 1))
box += Mv::to(y + i, divider) + Symbols::v_line;
}
}
//* Calculate and draw net box outlines
if (Net::shown) {
using namespace Net;
width = round(Term::width * (Proc::shown ? width_p : 100) / 100);
height = Term::height - Cpu::height - Mem::height;
y = Term::height - height + 1;
b_width = (width > 45) ? 27 : 19;
b_height = (height > 10) ? 9 : height - 2;
b_x = width - b_width - 1;
b_y = y + ((height - 2) / 2) - b_height / 2 + 1;
d_graph_height = round((height - 2) / 2);
u_graph_height = height - 2 - d_graph_height;
box = createBox(x, y, width, height, Theme::c("net_box"), true, "net", "", 3);
box += createBox(b_x, b_y, b_width, b_height, "", false, "download", "upload");
}
//* Calculate and draw proc box outlines
if (Proc::shown) {
using namespace Proc;
width = Term::width - (Mem::shown ? Mem::width : (Net::shown ? Net::width : 0));
height = Term::height - Cpu::height;
x = Term::width - width + 1;
y = Cpu::height + 1;
current_y = y;
current_h = height;
select_max = height - 3;
box = createBox(x, y, width, height, Theme::c("proc_box"), true, "proc", "", 4);
}
}
}

View file

@ -40,17 +40,8 @@ namespace Symbols {
namespace Draw {
struct BoxConf {
size_t x=0, y=0;
size_t width=0, height=0;
string line_color = "", title = "", title2 = "";
bool fill = true;
size_t num=0;
size_t w_percent=0, h_percent=0;
};
//* Create a box using values from a BoxConf struct and return as a string
string createBox(BoxConf c);
//* Create a box and return as a string
string createBox(int x, int y, int width, int height, string line_color="", bool fill=false, string title="", string title2="", int num=0);
//* Class holding a percentage meter
class Meter {
@ -95,24 +86,22 @@ namespace Draw {
namespace Cpu {
extern Draw::BoxConf box;
}
namespace Mem {
extern Draw::BoxConf box;
}
namespace Net {
extern Draw::BoxConf box;
}
namespace Proc {
extern Draw::BoxConf box;
}

View file

@ -90,6 +90,15 @@ namespace Shared {
}
namespace Cpu {
bool got_sensors = false;
string cpuName = "";
}
namespace Mem {
bool has_swap = false;
}
namespace Proc {
namespace {
struct p_cache {
@ -144,10 +153,10 @@ namespace Proc {
//? If filtering, include children of matching processes
if (not filter.empty() and not found) {
if (std::to_string(cur_proc.pid).find(filter) == string::npos
and cur_proc.name.find(filter) == string::npos
and cur_proc.cmd.find(filter) == string::npos
and cur_proc.user.find(filter) == string::npos) {
if (not s_contains(std::to_string(cur_proc.pid), filter)
and not s_contains(cur_proc.name, filter)
and not s_contains(cur_proc.cmd, filter)
and not s_contains(cur_proc.user, filter)) {
filtering = true;
}
else {
@ -373,10 +382,10 @@ namespace Proc {
//* Match filter if defined
if (not tree and not filter.empty()
and pid_str.find(filter) == string::npos
and cache[new_proc.pid].name.find(filter) == string::npos
and cache[new_proc.pid].cmd.find(filter) == string::npos
and cache[new_proc.pid].user.find(filter) == string::npos) {
and not s_contains(pid_str, filter)
and not s_contains(cache[new_proc.pid].name, filter)
and not s_contains(cache[new_proc.pid].cmd, filter)
and not s_contains(cache[new_proc.pid].user, filter)) {
if (show_detailed and new_proc.pid == detailed_pid)
detailed_filtered = true;
else
@ -436,7 +445,7 @@ namespace Proc {
next_x = 24;
continue;
}
case 24: { //? RSS memory (can be inaccurate, but parsing smaps increases total cpu usage by ~ 20x)
case 24: { //? RSS memory (can be inaccurate, but parsing smaps increases total cpu usage by ~20x)
new_proc.mem = stoull(short_str) * Shared::page_size;
next_x = 40;
continue;
@ -487,14 +496,14 @@ namespace Proc {
//* Sort processes
auto cmp = [&reverse](const auto &a, const auto &b) { return (reverse ? a < b : a > b); };
switch (v_index(sort_vector, sorting)) {
case 0: { rng::sort(procs, cmp, &proc_info::pid); break; }
case 1: { rng::sort(procs, cmp, &proc_info::name); break; }
case 2: { rng::sort(procs, cmp, &proc_info::cmd); break; }
case 0: { rng::sort(procs, cmp, &proc_info::pid); break; }
case 1: { rng::sort(procs, cmp, &proc_info::name); break; }
case 2: { rng::sort(procs, cmp, &proc_info::cmd); break; }
case 3: { rng::sort(procs, cmp, &proc_info::threads); break; }
case 4: { rng::sort(procs, cmp, &proc_info::user); break; }
case 5: { rng::sort(procs, cmp, &proc_info::mem); break; }
case 6: { rng::sort(procs, cmp, &proc_info::cpu_p); break; }
case 7: { rng::sort(procs, cmp, &proc_info::cpu_c); break; }
case 4: { rng::sort(procs, cmp, &proc_info::user); break; }
case 5: { rng::sort(procs, cmp, &proc_info::mem); break; }
case 6: { rng::sort(procs, cmp, &proc_info::cpu_p); break; }
case 7: { rng::sort(procs, cmp, &proc_info::cpu_c); break; }
}
//* When sorting with "cpu lazy" push processes over threshold cpu usage to the front regardless of cumulative usage
@ -515,6 +524,7 @@ namespace Proc {
//* Generate tree view if enabled
if (tree) {
vector<proc_info> tree_procs;
tree_procs.reserve(procs.size());
//? Stable sort to retain selected sorting among processes with the same parent
rng::stable_sort(procs, rng::less{}, &proc_info::ppid);

View file

@ -33,6 +33,12 @@ namespace Global {
extern string banner;
}
namespace Runner {
extern std::atomic<bool> active;
}
namespace Tools {
//* Platform specific function for system_uptime (seconds since last restart)
double system_uptime();
@ -43,11 +49,30 @@ namespace Shared {
void init();
}
namespace Cpu {
extern string box, cpuName;
extern bool shown, redraw, got_sensors;
}
namespace Mem {
extern string box;
extern bool has_swap, shown, redraw;
}
namespace Net {
extern string box;
extern bool shown, redraw;
}
namespace Proc {
extern size_t numpids;
extern std::atomic<bool> stop;
extern std::atomic<bool> collecting;
extern string box;
extern bool shown, redraw;
extern int current_y, current_h, select_max;
//? Contains the valid sorting options for processes
extern vector<string> sort_vector;
@ -80,4 +105,6 @@ namespace Proc {
//* Collects and sorts process information from /proc, saves and returns reference to Proc::current_procs;
vector<proc_info>& collect(bool return_last=false);
}
string draw(vector<proc_info> plist);
}

View file

@ -85,8 +85,8 @@ namespace Term {
bool initialized = false;
bool resized = false;
size_t width = 0;
size_t height = 0;
int width = 0;
int height = 0;
string fg, bg, current_tty;
const string hide_cursor = Fx::e + "?25l";

View file

@ -91,8 +91,8 @@ namespace Mv {
namespace Term {
extern bool initialized;
extern bool resized;
extern size_t width;
extern size_t height;
extern int width;
extern int height;
extern string fg, bg, current_tty;
//* Hide terminal cursor
@ -156,11 +156,17 @@ namespace Tools {
string str_to_lower(const string& str);
//* Check if vector <vec> contains value <find_val>
template <typename T>
bool v_contains(const vector<T>& vec, const T find_val) {
template <typename T, typename T2>
bool v_contains(const vector<T>& vec, const T2 find_val) {
return std::ranges::find(vec, find_val) != vec.end();
}
//* Check if string <str> contains value <find_val>
template <typename T>
bool s_contains(const string& str, const T find_val) {
return str.find(find_val) != string::npos;
}
//* Return index of <find_val> from vector <vec>, returns size of <vec> if <find_val> is not present
template <typename T>
size_t v_index(vector<T>& vec, T find_val) {