Added terminal size limit warnings and fixed net auto sizing

This commit is contained in:
aristocratos 2021-08-22 21:39:25 +02:00
parent 3f27fb24b5
commit b2e0707c32
4 changed files with 58 additions and 32 deletions

View File

@ -3,7 +3,7 @@
BANNER = \n \033[38;5;196m██████\033[38;5;240m╗ \033[38;5;196m████████\033[38;5;240m╗ \033[38;5;196m██████\033[38;5;240m╗ \033[38;5;196m██████\033[38;5;240m╗\n \033[38;5;160m██\033[38;5;239m╔══\033[38;5;160m██\033[38;5;239m╗╚══\033[38;5;160m██\033[38;5;239m╔══╝\033[38;5;160m██\033[38;5;239m╔═══\033[38;5;160m██\033[38;5;239m╗\033[38;5;160m██\033[38;5;239m╔══\033[38;5;160m██\033[38;5;239m╗ \033[38;5;160m██\033[38;5;239m╗ \033[38;5;160m██\033[38;5;239m╗\n \033[38;5;124m██████\033[38;5;238m╔╝ \033[38;5;124m██\033[38;5;238m║ \033[38;5;124m██\033[38;5;238m║ \033[38;5;124m██\033[38;5;238m║\033[38;5;124m██████\033[38;5;238m╔╝ \033[38;5;124m██████\033[38;5;238m╗\033[38;5;124m██████\033[38;5;238m╗\n \033[38;5;88m██\033[38;5;237m╔══\033[38;5;88m██\033[38;5;237m╗ \033[38;5;88m██\033[38;5;237m║ \033[38;5;88m██\033[38;5;237m║ \033[38;5;88m██\033[38;5;237m║\033[38;5;88m██\033[38;5;237m╔═══╝ ╚═\033[38;5;88m██\033[38;5;237m╔═╝╚═\033[38;5;88m██\033[38;5;237m╔═╝\n \033[38;5;52m██████\033[38;5;236m╔╝ \033[38;5;52m██\033[38;5;236m║ ╚\033[38;5;52m██████\033[38;5;236m╔╝\033[38;5;52m██\033[38;5;236m║ ╚═╝ ╚═╝\n \033[38;5;235m╚═════╝ ╚═╝ ╚═════╝ ╚═╝ BANNER = \n \033[38;5;196m██████\033[38;5;240m╗ \033[38;5;196m████████\033[38;5;240m╗ \033[38;5;196m██████\033[38;5;240m╗ \033[38;5;196m██████\033[38;5;240m╗\n \033[38;5;160m██\033[38;5;239m╔══\033[38;5;160m██\033[38;5;239m╗╚══\033[38;5;160m██\033[38;5;239m╔══╝\033[38;5;160m██\033[38;5;239m╔═══\033[38;5;160m██\033[38;5;239m╗\033[38;5;160m██\033[38;5;239m╔══\033[38;5;160m██\033[38;5;239m╗ \033[38;5;160m██\033[38;5;239m╗ \033[38;5;160m██\033[38;5;239m╗\n \033[38;5;124m██████\033[38;5;238m╔╝ \033[38;5;124m██\033[38;5;238m║ \033[38;5;124m██\033[38;5;238m║ \033[38;5;124m██\033[38;5;238m║\033[38;5;124m██████\033[38;5;238m╔╝ \033[38;5;124m██████\033[38;5;238m╗\033[38;5;124m██████\033[38;5;238m╗\n \033[38;5;88m██\033[38;5;237m╔══\033[38;5;88m██\033[38;5;237m╗ \033[38;5;88m██\033[38;5;237m║ \033[38;5;88m██\033[38;5;237m║ \033[38;5;88m██\033[38;5;237m║\033[38;5;88m██\033[38;5;237m╔═══╝ ╚═\033[38;5;88m██\033[38;5;237m╔═╝╚═\033[38;5;88m██\033[38;5;237m╔═╝\n \033[38;5;52m██████\033[38;5;236m╔╝ \033[38;5;52m██\033[38;5;236m║ ╚\033[38;5;52m██████\033[38;5;236m╔╝\033[38;5;52m██\033[38;5;236m║ ╚═╝ ╚═╝\n \033[38;5;235m╚═════╝ ╚═╝ ╚═════╝ ╚═╝
BTOP_VERSION = $(shell head -n100 src/btop.cpp 2>/dev/null | grep "Version =" | cut -f2 -d"\"" || echo " unknown") BTOP_VERSION = $(shell head -n100 src/btop.cpp 2>/dev/null | grep "Version =" | cut -f2 -d"\"" || echo " unknown")
TIMESTAMP = $(shell date +%s) TIMESTAMP = $(shell date +%s 2>/dev/null || echo "0")
PREFIX ?= /usr/local PREFIX ?= /usr/local
@ -130,7 +130,7 @@ btop: $(OBJECTS)
@printf "\n\033[1;92mLinking and optimizing binary\033[0m\n" @printf "\n\033[1;92mLinking and optimizing binary\033[0m\n"
@$(CXX) -o $(TARGETDIR)/btop $^ $(LDFLAGS) @$(CXX) -o $(TARGETDIR)/btop $^ $(LDFLAGS)
@printf "\033[1;97m./$(TARGETDIR)/btop ($$(du -ah $(TARGETDIR)/btop | cut -f1)iB)\033[0m\n" @printf "\033[1;97m./$(TARGETDIR)/btop ($$(du -ah $(TARGETDIR)/btop | cut -f1)iB)\033[0m\n"
@printf "\n\033[1;92mBuild complete in (\033[1;97m$$(date -d @$$(expr $$(date +%s) - $(TIMESTAMP)) -u +%Mm:%Ss)\033[1;92m)\033[0m\n" @printf "\n\033[1;92mBuild complete in (\033[1;97m$$(date -d @$$(expr $$(date +%s 2>/dev/null || echo "0") - $(TIMESTAMP)) -u +%Mm:%Ss)\033[1;92m)\033[0m\n"
#? Compile #? Compile
$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SRCEXT) $(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SRCEXT)

View File

@ -127,13 +127,14 @@ Options menu.
#### Manual compilation and installation #### Manual compilation and installation
Needs GCC 10 or higher, (GCC 11 preferably). Needs GCC 10 or higher, (GCC 11 or above strongly recommended for better CPU efficiency in compiled binary).
The makefile also needs GNU coreutils and sed installed.
>Install dependencies (Ubuntu 21.04 Hirsute) >Install dependencies (example for Ubuntu 21.04 Hirsute)
``` bash ``` bash
sudo apt install git build-essential gcc-11 g++-11 sudo apt install coreutils sed git build-essential gcc-11 g++-11
#gcc-10 g++-10 if on older #use gcc-10 g++-10 if gcc-11 isn't available
``` ```
>Clone and compile >Clone and compile
@ -141,24 +142,24 @@ sudo apt install git build-essential gcc-11 g++-11
``` bash ``` bash
git clone https://github.com/aristocratos/btop.git git clone https://github.com/aristocratos/btop.git
cd btop cd btop
# use "make -j X" where X is threads, to manually set number of threads, the makefile will use all available cores by default
make make
# use "make -jX" where X is your number of cores for multithreaded compilation
``` ```
>to install >to install
``` bash ``` bash
sudo make install
# use "make install PREFIX=/target/dir" to set target, default: /usr/local # use "make install PREFIX=/target/dir" to set target, default: /usr/local
# only use "sudo" when installing to a NON user owned directory # only use "sudo" when installing to a NON user owned directory
sudo make install
``` ```
>to make btop always run as root (or other user), (no need for `sudo` to enable signal sending to any process and to prevent /proc read permissions problems on some systems) >to make btop always run as root (or other user), (no need for `sudo` to enable signal sending to any process and to prevent /proc read permissions problems on some systems)
``` bash ``` bash
# run after make install and use same PREFIX if any was used at install # run after make install and use same PREFIX if any was used at install
sudo make setuid
# set SU_USER and SU_GROUP to select user and group, default is root:root # set SU_USER and SU_GROUP to select user and group, default is root:root
sudo make setuid
``` ```

View File

@ -78,6 +78,12 @@ namespace Global {
string overlay; string overlay;
string clock; string clock;
string bg_black = "\x1b[0;40m";
string fg_white = "\x1b[1;97m";
string fg_green = "\x1b[1;92m";
string fg_red = "\x1b[0;91m";
fs::path self_path; fs::path self_path;
string exit_error_msg; string exit_error_msg;
@ -90,7 +96,6 @@ namespace Global {
uint64_t start_time; uint64_t start_time;
atomic<bool> resized (false); atomic<bool> resized (false);
atomic<int> resizing (0);
atomic<bool> quitting (false); atomic<bool> quitting (false);
bool arg_tty = false; bool arg_tty = false;
@ -150,20 +155,28 @@ void term_resize(bool force) {
} }
else return; else return;
auto rez_state = ++Global::resizing;
if (rez_state > 1) return;
Global::resized = true; Global::resized = true;
Runner::stop(); Runner::stop();
auto min_size = Term::get_min_size(Config::getS("shown_boxes")); auto min_size = Term::get_min_size(Config::getS("shown_boxes"));
while (not force) { while (not force) {
sleep_ms(100); sleep_ms(100);
if (rez_state != Global::resizing) rez_state = --Global::resizing; if (Term::width < min_size.at(0) or Term::height < min_size.at(1)) {
else if (not Term::refresh() and Term::width >= min_size[0] and Term::height >= min_size[1]) break; min_size = Term::get_min_size(Config::getS("shown_boxes"));
cout << Term::clear << Global::bg_black << Global::fg_white << Mv::to((Term::height / 2) - 2, (Term::width / 2) - 11)
<< "Terminal size too small:" << Mv::to((Term::height / 2) - 1, (Term::width / 2) - 10)
<< " Width = " << (Term::width < min_size.at(1) ? Global::fg_red : Global::fg_green) << Term::width
<< Global::fg_white << " Height = " << (Term::height < min_size.at(0) ? Global::fg_red : Global::fg_green) << Term::height
<< Mv::to((Term::height / 2) + 1, (Term::width / 2) - 12) << Global::fg_white
<< "Needed for current config:" << Mv::to((Term::height / 2) + 2, (Term::width / 2) - 10)
<< "Width = " << min_size.at(0) << " Height = " << min_size.at(1) << flush;
while (not Term::refresh() and not Input::poll()) sleep_ms(10);
if (Input::poll() and Input::get() == "q") exit(0);
}
else if (not Term::refresh()) break;
} }
Input::interrupt = true; Input::interrupt = true;
Global::resizing = 0;
} }
//* Exit handler; stops threads, restores terminal and saves config changes //* Exit handler; stops threads, restores terminal and saves config changes
@ -174,14 +187,8 @@ void clean_quit(int sig) {
if (pthread_join(Runner::runner_id, NULL) != 0) if (pthread_join(Runner::runner_id, NULL) != 0)
Logger::error("Failed to join _runner thread!"); Logger::error("Failed to join _runner thread!");
if (not Global::exit_error_msg.empty()) {
sig = 1;
Logger::error(Global::exit_error_msg);
std::cerr << "ERROR: " << Global::exit_error_msg << endl;
}
Config::write(); Config::write();
Input::clear(); Input::clear();
Logger::info("Quitting! Runtime: " + sec_to_dhms(time_s() - Global::start_time));
//? Wait for any remaining Tools::atomic_lock destructors to finish for max 1000ms //? Wait for any remaining Tools::atomic_lock destructors to finish for max 1000ms
for (int i = 0; Tools::active_locks > 0 and i < 100; i++) { for (int i = 0; Tools::active_locks > 0 and i < 100; i++) {
@ -192,6 +199,13 @@ void clean_quit(int sig) {
Term::restore(); Term::restore();
} }
if (not Global::exit_error_msg.empty()) {
sig = 1;
Logger::error(Global::exit_error_msg);
std::cerr << Global::fg_red << "ERROR: " << Global::fg_white << Global::exit_error_msg << Fx::reset << endl;
}
Logger::info("Quitting! Runtime: " + sec_to_dhms(time_s() - Global::start_time));
//? Assume error if still not cleaned up and call quick_exit to avoid a segfault from Tools::atomic_lock destructor //? Assume error if still not cleaned up and call quick_exit to avoid a segfault from Tools::atomic_lock destructor
if (Tools::active_locks > 0) { if (Tools::active_locks > 0) {
quick_exit((sig != -1 ? sig : 0)); quick_exit((sig != -1 ? sig : 0));
@ -824,6 +838,17 @@ int main(int argc, char **argv) {
//? Calculate sizes of all boxes //? Calculate sizes of all boxes
Draw::calcSizes(); Draw::calcSizes();
{
const auto [x, y] = Term::get_min_size(Config::getS("shown_boxes"));
if (Term::height < y or Term::width < x) {
Global::exit_error_msg = "Terminal size to small for current config.\n(WxH) Current: " + to_string(Term::width)
+ 'x' + to_string(Term::height) + " | Needed: " + to_string(x) + 'x' + to_string(y)
+ "\nResize terminal or disable some boxes in config file to fix this.";
exit(1);
}
}
//? Print out box outlines //? Print out box outlines
cout << Term::sync_start << Cpu::box << Mem::box << Net::box << Proc::box << Term::sync_end << flush; cout << Term::sync_start << Cpu::box << Mem::box << Net::box << Proc::box << Term::sync_end << flush;

View File

@ -515,7 +515,7 @@ namespace Cpu {
} }
namespace Mem { namespace Mem {
int width_p = 45, height_p = 38; int width_p = 45, height_p = 36;
int min_width = 36, min_height = 10; int min_width = 36, min_height = 10;
int x = 1, y, width = 20, height; int x = 1, y, width = 20, height;
int mem_width, disks_width, divider, item_height, mem_size, mem_meter, graph_height, disk_meter; int mem_width, disks_width, divider, item_height, mem_size, mem_meter, graph_height, disk_meter;
@ -668,7 +668,7 @@ namespace Mem {
const auto& disks = mem.disks; const auto& disks = mem.disks;
cx = x + mem_width - 1; cy = 0; cx = x + mem_width - 1; cy = 0;
const bool big_disk = disks_width >= 25; const bool big_disk = disks_width >= 25;
divider = Mv::l(1) + Theme::c("div_line") + Symbols::div_left + Symbols::h_line * disks_width + Theme::c("mem_box") + Fx::ub + Symbols::div_right + Mv::l(disks_width - 1); divider = Mv::l(1) + Theme::c("div_line") + Symbols::div_left + Symbols::h_line * disks_width + Theme::c("mem_box") + Fx::ub + Symbols::div_right + Mv::l(disks_width);
if (io_mode) { if (io_mode) {
for (const auto& mount : mem.disks_order) { for (const auto& mount : mem.disks_order) {
if (not disks.contains(mount)) continue; if (not disks.contains(mount)) continue;
@ -676,7 +676,7 @@ namespace Mem {
const auto& disk = disks.at(mount); const auto& disk = disks.at(mount);
if (disk.io_read.empty()) continue; if (disk.io_read.empty()) continue;
const string total = floating_humanizer(disk.total, not big_disk); const string total = floating_humanizer(disk.total, not big_disk);
out += Mv::to(y+1+cy, x+1+cx) + divider + Theme::c("title") + Fx::b + uresize(disk.name, disks_width - 2) + Mv::to(y+1+cy, x+cx + disks_width - total.size() - 1) out += Mv::to(y+1+cy, x+1+cx) + divider + Theme::c("title") + Fx::b + uresize(disk.name, disks_width - 2) + Mv::to(y+1+cy, x+cx + disks_width - total.size())
+ trans(total) + Fx::ub; + trans(total) + Fx::ub;
if (big_disk) { if (big_disk) {
const string used_percent = to_string(disk.used_percent); const string used_percent = to_string(disk.used_percent);
@ -715,7 +715,7 @@ namespace Mem {
const string human_used = floating_humanizer(disk.used, not big_disk); const string human_used = floating_humanizer(disk.used, not big_disk);
const string human_free = floating_humanizer(disk.free, not big_disk); const string human_free = floating_humanizer(disk.free, not big_disk);
out += Mv::to(y+1+cy, x+1+cx) + divider + Theme::c("title") + Fx::b + uresize(disk.name, disks_width - 2) + Mv::to(y+1+cy, x+cx + disks_width - human_total.size() - 1) out += Mv::to(y+1+cy, x+1+cx) + divider + Theme::c("title") + Fx::b + uresize(disk.name, disks_width - 2) + Mv::to(y+1+cy, x+cx + disks_width - human_total.size())
+ trans(human_total) + Fx::ub + Theme::c("main_fg"); + trans(human_total) + Fx::ub + Theme::c("main_fg");
if (big_disk and not human_io.empty()) if (big_disk and not human_io.empty())
out += Mv::to(y+1+cy, x+1+cx + round((double)disks_width / 2) - round((double)human_io.size() / 2)) + Theme::c("main_fg") + human_io; out += Mv::to(y+1+cy, x+1+cx + round((double)disks_width / 2) - round((double)human_io.size() / 2)) + Theme::c("main_fg") + human_io;
@ -751,7 +751,7 @@ namespace Mem {
} }
namespace Net { namespace Net {
int width_p = 45, height_p = 30; int width_p = 45, height_p = 32;
int min_width = 36, min_height = 6; int min_width = 36, min_height = 6;
int x = 1, y, width = 20, height; int x = 1, y, width = 20, height;
int b_x, b_y, b_width, b_height, d_graph_height, u_graph_height; int b_x, b_y, b_width, b_height, d_graph_height, u_graph_height;
@ -825,14 +825,14 @@ namespace Net {
const string total = floating_humanizer(net.stat.at(dir).total); const string total = floating_humanizer(net.stat.at(dir).total);
const string symbol = (dir == "upload" ? "" : ""); const string symbol = (dir == "upload" ? "" : "");
out += Mv::to(b_y+1+cy, b_x+1) + Fx::ub + Theme::c("main_fg") + symbol + ' ' + ljust(speed, 10) + (b_width >= 20 ? rjust('(' + speed_bits + ')', 13) : ""); out += Mv::to(b_y+1+cy, b_x+1) + Fx::ub + Theme::c("main_fg") + symbol + ' ' + ljust(speed, 10) + (b_width >= 20 ? rjust('(' + speed_bits + ')', 13) : "");
cy += (b_height == 3 ? 2 : 1); cy += (b_height == 5 ? 2 : 1);
if (b_height >= 6) { if (b_height >= 8) {
out += Mv::to(b_y+1+cy, b_x+1) + symbol + ' ' + "Top: " + rjust('(' + top, (b_width >= 20 ? 17 : 9)) + ')'; out += Mv::to(b_y+1+cy, b_x+1) + symbol + ' ' + "Top: " + rjust('(' + top, (b_width >= 20 ? 17 : 9)) + ')';
cy++; cy++;
} }
if (b_height >= 4) { if (b_height >= 6) {
out += Mv::to(b_y+1+cy, b_x+1) + symbol + ' ' + "Total: " + rjust(total, (b_width >= 20 ? 16 : 8)); out += Mv::to(b_y+1+cy, b_x+1) + symbol + ' ' + "Total: " + rjust(total, (b_width >= 20 ? 16 : 8));
cy += (b_height > 2 and b_height % 2 ? 2 : 1); cy += (b_height > 6 and b_height % 2 ? 2 : 1);
} }
} }
@ -1332,7 +1332,7 @@ namespace Draw {
using namespace Cpu; using namespace Cpu;
const bool show_temp = (Config::getB("check_temp") and got_sensors); const bool show_temp = (Config::getB("check_temp") and got_sensors);
width = round((double)Term::width * width_p / 100); width = round((double)Term::width * width_p / 100);
height = max(8, (int)round((double)Term::height * (trim(boxes) == "cpu" ? 100 : height_p) / 100)); height = max(8, (int)ceil((double)Term::height * (trim(boxes) == "cpu" ? 100 : height_p) / 100));
x = 1; x = 1;
y = cpu_bottom ? Term::height - height + 1 : 1; y = cpu_bottom ? Term::height - height + 1 : 1;
@ -1374,7 +1374,7 @@ namespace Draw {
auto& mem_graphs = Config::getB("mem_graphs"); auto& mem_graphs = Config::getB("mem_graphs");
width = round((double)Term::width * (Proc::shown ? width_p : 100) / 100); width = round((double)Term::width * (Proc::shown ? width_p : 100) / 100);
height = round((double)Term::height * (100 - Cpu::height_p * Cpu::shown - Net::height_p * Net::shown) / 100) + 1; height = ceil((double)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; if (height + Cpu::height > Term::height) height = Term::height - Cpu::height;
x = (proc_left and Proc::shown) ? Term::width - width + 1: 1; x = (proc_left and Proc::shown) ? Term::width - width + 1: 1;
if (mem_below_net and Net::shown) if (mem_below_net and Net::shown)