mirror of https://github.com/aristocratos/btop.git
Added terminal size limit warnings and fixed net auto sizing
This commit is contained in:
parent
3f27fb24b5
commit
b2e0707c32
4
Makefile
4
Makefile
|
@ -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╚═════╝ ╚═╝ ╚═════╝ ╚═╝
|
||||
|
||||
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
|
||||
|
||||
|
@ -130,7 +130,7 @@ btop: $(OBJECTS)
|
|||
@printf "\n\033[1;92mLinking and optimizing binary\033[0m\n"
|
||||
@$(CXX) -o $(TARGETDIR)/btop $^ $(LDFLAGS)
|
||||
@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
|
||||
$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SRCEXT)
|
||||
|
|
15
README.md
15
README.md
|
@ -127,13 +127,14 @@ Options menu.
|
|||
|
||||
#### 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
|
||||
sudo apt install git build-essential gcc-11 g++-11
|
||||
#gcc-10 g++-10 if on older
|
||||
sudo apt install coreutils sed git build-essential gcc-11 g++-11
|
||||
#use gcc-10 g++-10 if gcc-11 isn't available
|
||||
```
|
||||
|
||||
>Clone and compile
|
||||
|
@ -141,24 +142,24 @@ sudo apt install git build-essential gcc-11 g++-11
|
|||
``` bash
|
||||
git clone https://github.com/aristocratos/btop.git
|
||||
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
|
||||
# use "make -jX" where X is your number of cores for multithreaded compilation
|
||||
```
|
||||
|
||||
>to install
|
||||
|
||||
``` bash
|
||||
sudo make install
|
||||
# use "make install PREFIX=/target/dir" to set target, default: /usr/local
|
||||
# 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)
|
||||
|
||||
``` bash
|
||||
# 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
|
||||
sudo make setuid
|
||||
```
|
||||
|
||||
|
||||
|
|
49
src/btop.cpp
49
src/btop.cpp
|
@ -78,6 +78,12 @@ namespace Global {
|
|||
string overlay;
|
||||
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;
|
||||
|
||||
string exit_error_msg;
|
||||
|
@ -90,7 +96,6 @@ namespace Global {
|
|||
uint64_t start_time;
|
||||
|
||||
atomic<bool> resized (false);
|
||||
atomic<int> resizing (0);
|
||||
atomic<bool> quitting (false);
|
||||
|
||||
bool arg_tty = false;
|
||||
|
@ -150,20 +155,28 @@ void term_resize(bool force) {
|
|||
}
|
||||
else return;
|
||||
|
||||
auto rez_state = ++Global::resizing;
|
||||
if (rez_state > 1) return;
|
||||
Global::resized = true;
|
||||
Runner::stop();
|
||||
auto min_size = Term::get_min_size(Config::getS("shown_boxes"));
|
||||
|
||||
while (not force) {
|
||||
sleep_ms(100);
|
||||
if (rez_state != Global::resizing) rez_state = --Global::resizing;
|
||||
else if (not Term::refresh() and Term::width >= min_size[0] and Term::height >= min_size[1]) break;
|
||||
if (Term::width < min_size.at(0) or Term::height < min_size.at(1)) {
|
||||
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;
|
||||
Global::resizing = 0;
|
||||
}
|
||||
|
||||
//* 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)
|
||||
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();
|
||||
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
|
||||
for (int i = 0; Tools::active_locks > 0 and i < 100; i++) {
|
||||
|
@ -192,6 +199,13 @@ void clean_quit(int sig) {
|
|||
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
|
||||
if (Tools::active_locks > 0) {
|
||||
quick_exit((sig != -1 ? sig : 0));
|
||||
|
@ -824,6 +838,17 @@ int main(int argc, char **argv) {
|
|||
//? Calculate sizes of all boxes
|
||||
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
|
||||
cout << Term::sync_start << Cpu::box << Mem::box << Net::box << Proc::box << Term::sync_end << flush;
|
||||
|
||||
|
|
|
@ -515,7 +515,7 @@ namespace Cpu {
|
|||
}
|
||||
|
||||
namespace Mem {
|
||||
int width_p = 45, height_p = 38;
|
||||
int width_p = 45, height_p = 36;
|
||||
int min_width = 36, min_height = 10;
|
||||
int x = 1, y, width = 20, height;
|
||||
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;
|
||||
cx = x + mem_width - 1; cy = 0;
|
||||
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) {
|
||||
for (const auto& mount : mem.disks_order) {
|
||||
if (not disks.contains(mount)) continue;
|
||||
|
@ -676,7 +676,7 @@ namespace Mem {
|
|||
const auto& disk = disks.at(mount);
|
||||
if (disk.io_read.empty()) continue;
|
||||
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;
|
||||
if (big_disk) {
|
||||
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_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");
|
||||
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;
|
||||
|
@ -751,7 +751,7 @@ namespace Mem {
|
|||
}
|
||||
|
||||
namespace Net {
|
||||
int width_p = 45, height_p = 30;
|
||||
int width_p = 45, height_p = 32;
|
||||
int min_width = 36, min_height = 6;
|
||||
int x = 1, y, width = 20, 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 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) : "");
|
||||
cy += (b_height == 3 ? 2 : 1);
|
||||
if (b_height >= 6) {
|
||||
cy += (b_height == 5 ? 2 : 1);
|
||||
if (b_height >= 8) {
|
||||
out += Mv::to(b_y+1+cy, b_x+1) + symbol + ' ' + "Top: " + rjust('(' + top, (b_width >= 20 ? 17 : 9)) + ')';
|
||||
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));
|
||||
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;
|
||||
const bool show_temp = (Config::getB("check_temp") and got_sensors);
|
||||
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;
|
||||
y = cpu_bottom ? Term::height - height + 1 : 1;
|
||||
|
||||
|
@ -1374,7 +1374,7 @@ namespace Draw {
|
|||
auto& mem_graphs = Config::getB("mem_graphs");
|
||||
|
||||
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;
|
||||
x = (proc_left and Proc::shown) ? Term::width - width + 1: 1;
|
||||
if (mem_below_net and Net::shown)
|
||||
|
|
Loading…
Reference in New Issue