mirror of https://github.com/aristocratos/btop.git
Merge branch 'main' into main
This commit is contained in:
commit
aa7a042426
|
@ -25,6 +25,8 @@ assignees: aristocratos
|
|||
|
||||
**Info (please complete the following information):**
|
||||
- btop++ version: `bpytop -v`
|
||||
- Binary: [self compiled or static binary from release]
|
||||
- (If compiled) Compiler and version:
|
||||
- Architecture: [x86_64, aarch64, etc.] `uname -m`
|
||||
- Platform: [Linux, FreeBSD, OsX]
|
||||
- (Linux) Kernel: `uname -r`
|
||||
|
@ -34,6 +36,18 @@ assignees: aristocratos
|
|||
|
||||
**Additional context**
|
||||
|
||||
contents of `~/.config/btop/error.log`
|
||||
contents of `~/.config/btop/btop.log`
|
||||
|
||||
(try running btop with `--debug` flag if error.log is empty)
|
||||
|
||||
**GDB Backtrace**
|
||||
|
||||
If btop++ is crashing at start the following steps could be helpful:
|
||||
|
||||
1. run `gdb btop`
|
||||
|
||||
2. `r` to run, wait for crash and press enter
|
||||
|
||||
3. `bt` to get backtrace
|
||||
|
||||
4. Copy and paste the backtrace here:
|
||||
|
|
|
@ -49,3 +49,4 @@ stage/
|
|||
build
|
||||
bin
|
||||
btop
|
||||
.*/
|
58
CHANGELOG.md
58
CHANGELOG.md
|
@ -1,3 +1,61 @@
|
|||
## v1.0.9
|
||||
|
||||
* Added: ifstream check and try-catch for stod() in Tools::system_uptime()
|
||||
|
||||
* Fixed: Freeze on cin.ignore()
|
||||
|
||||
## v1.0.8
|
||||
|
||||
* Fixed: Additional NULL checks in UTF-8 detection
|
||||
|
||||
* Changed: Makefile: Only look for g++-11 if CXX=g++
|
||||
|
||||
* Fixed: Missing NULL check for ttyname
|
||||
|
||||
* Changed: Only log tty name if known
|
||||
|
||||
## v1.0.7
|
||||
|
||||
* Fixed: Crash when opening menu at too small size
|
||||
|
||||
* Fixed: Cores not constrained to cpu box and core numbers above 100 cut off
|
||||
|
||||
* Fixed: Scrollbar position incorrect in small lists and selection not working when filtering
|
||||
|
||||
## v1.0.6
|
||||
|
||||
* Fixed: Check that getenv("LANG") is not NULL in UTF-8 check
|
||||
|
||||
* Fixed: Processes not completely hidden when collapsed in tree mode
|
||||
|
||||
* Fixed: Changed wrong filename error.log to btop.log
|
||||
|
||||
## v1.0.5
|
||||
|
||||
* Fixed: Load AVG sizing when hiding temperatures
|
||||
|
||||
* Fixed: Sizing constraints bug on start and boxes can be toggled from size error screen
|
||||
|
||||
* Fixed: UTF-8 check crashing if LANG was set to non existant locale
|
||||
|
||||
## v1.0.4
|
||||
|
||||
* Fixed: Use /proc/pid/statm if RSS memory from /proc/pid/stat is faulty
|
||||
|
||||
## v1.0.3
|
||||
|
||||
* Fixed: stoi 0 literal pointer to nullptr and added more clamping for gradient array access
|
||||
|
||||
## v1.0.2
|
||||
|
||||
* Fixed: ARCH detection in Makefile
|
||||
|
||||
* Fixed: Color gradient array out of bounds, added clamp 0-100 for cpu percent values
|
||||
|
||||
* Fixed: Menu size and preset size issues and added warnings for small terminal size
|
||||
|
||||
* Fixed: Options menu page selection alignment
|
||||
|
||||
## v1.0.1
|
||||
|
||||
* Fixed: UTF-8 check to include UTF8
|
||||
|
|
30
Makefile
30
Makefile
|
@ -5,16 +5,20 @@ BANNER = \n \033[38;5;196m██████\033[38;5;240m╗ \033[38;5;196m█
|
|||
override BTOP_VERSION := $(shell head -n100 src/btop.cpp 2>/dev/null | grep "Version =" | cut -f2 -d"\"" || echo " unknown")
|
||||
override TIMESTAMP := $(shell date +%s 2>/dev/null || echo "0")
|
||||
|
||||
ifneq ($(QUIET),true)
|
||||
override PRE := info
|
||||
override QUIET := false
|
||||
else
|
||||
override PRE := info-quiet
|
||||
endif
|
||||
|
||||
PREFIX ?= /usr/local
|
||||
|
||||
#? NOTICE! Manually set PLATFORM and ARCH if not compiling for host system
|
||||
PLATFORM ?= $(shell uname -s || echo unknown)
|
||||
ARCH ?= $(shell uname -p || echo unknown)
|
||||
ARCH ?= $(shell uname -m || echo unknown)
|
||||
|
||||
#? Only enable fcf-protection if on x86_64
|
||||
ifeq ($(ARCH),unknown)
|
||||
ARCH := $(shell uname -m || echo unknown)
|
||||
endif
|
||||
ifeq ($(ARCH),x86_64)
|
||||
override ADDFLAGS += -fcf-protection
|
||||
endif
|
||||
|
@ -35,7 +39,7 @@ CXX ?= g++
|
|||
override CXX_VERSION := $(shell $(CXX) -dumpfullversion -dumpversion || echo 0)
|
||||
|
||||
#? Try to make sure we are using GCC/G++ version 11 or later if not instructed to use g++-10
|
||||
ifneq ($(CXX),g++-10)
|
||||
ifeq ($(CXX),g++)
|
||||
V_MAJOR := $(shell echo $(CXX_VERSION) | cut -f1 -d".")
|
||||
ifneq ($(shell test $(V_MAJOR) -ge 11; echo $$?),0)
|
||||
ifeq ($(shell command -v g++-11 >/dev/null; echo $$?),0)
|
||||
|
@ -92,9 +96,9 @@ SOURCES += $(shell find $(SRCDIR)/$(PLATFORM_DIR) -type f -name *.$(SRCEXT))
|
|||
OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.$(OBJEXT)))
|
||||
|
||||
#? Default Make
|
||||
all: pre directories btop
|
||||
all: $(PRE) directories btop
|
||||
|
||||
pre:
|
||||
info:
|
||||
@printf " $(BANNER)\n"
|
||||
@printf "\033[1;92mPLATFORM \033[1;93m?| \033[0m$(PLATFORM)\n"
|
||||
@printf "\033[1;96mARCH \033[1;93m?| \033[0m$(ARCH)\n"
|
||||
|
@ -109,6 +113,10 @@ pre:
|
|||
|
||||
@printf "\n\033[1;92mBuilding btop++ \033[93m(\033[97mv$(BTOP_VERSION)\033[93m)\033[0m\n"
|
||||
|
||||
info-quiet:
|
||||
|
||||
@printf "\n\033[1;92mBuilding btop++ \033[91m(\033[97mv$(BTOP_VERSION)\033[91m) \033[93m$(PLATFORM) \033[96m$(ARCH)\033[0m\n"
|
||||
|
||||
help:
|
||||
@printf " $(BANNER)\n"
|
||||
@printf "\033[1;97mbtop++ makefile\033[0m\n"
|
||||
|
@ -144,7 +152,7 @@ install:
|
|||
@printf "\033[1;92mInstalling doc to: \033[1;97m$(DESTDIR)$(PREFIX)/share/btop\n"
|
||||
@mkdir -p $(DESTDIR)$(PREFIX)/share/btop
|
||||
@cp -p README.md $(DESTDIR)$(PREFIX)/share/btop
|
||||
@printf "\033[1;92mInstalling themes to: \033[1;97m$(DESTDIR)$(PREFIX)/share/btop/themes\n"
|
||||
@printf "\033[1;92mInstalling themes to: \033[1;97m$(DESTDIR)$(PREFIX)/share/btop/themes\033[0m\n"
|
||||
@cp -pr themes $(DESTDIR)$(PREFIX)/share/btop
|
||||
|
||||
#? Set SUID bit for btop as $SU_USER in $SU_GROUP
|
||||
|
@ -169,17 +177,17 @@ uninstall:
|
|||
btop: $(OBJECTS)
|
||||
@sleep 0.1 2>/dev/null || true
|
||||
@TSTAMP=$$(date +%s 2>/dev/null || echo "0")
|
||||
@printf "\n\033[1;92mLinking and optimizing binary\033[37m...\033[0m\n"
|
||||
@$(QUIET) || printf "\n\033[1;92mLinking and optimizing binary\033[37m...\033[0m\n"
|
||||
@$(CXX) -o $(TARGETDIR)/btop $^ $(LDFLAGS) || exit 1
|
||||
@printf "\033[1;92m-> \033[1;37m$(TARGETDIR)/btop \033[100D\033[35C\033[1;93m(\033[1;97m$$(du -ah $(TARGETDIR)/btop | cut -f1)iB\033[1;93m) \033[92m(\033[97m$$(date -d @$$(expr $$(date +%s 2>/dev/null || echo "0") - $${TSTAMP} 2>/dev/null) -u +%Mm:%Ss 2>/dev/null | sed 's/^00m://' || echo '')\033[92m)\033[0m\n"
|
||||
@printf "\n\033[1;92mBuild complete in \033[92m(\033[97m$$(date -d @$$(expr $$(date +%s 2>/dev/null || echo "0") - $(TIMESTAMP) 2>/dev/null) -u +%Mm:%Ss 2>/dev/null | sed 's/^00m://' || echo "unknown")\033[92m)\033[0m\n"
|
||||
printf "\n\033[1;92mBuild complete in \033[92m(\033[97m$$(date -d @$$(expr $$(date +%s 2>/dev/null || echo "0") - $(TIMESTAMP) 2>/dev/null) -u +%Mm:%Ss 2>/dev/null | sed 's/^00m://' || echo "unknown")\033[92m)\033[0m\n"
|
||||
|
||||
#? Compile
|
||||
.ONESHELL:
|
||||
$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SRCEXT)
|
||||
@sleep 0.1 2>/dev/null || true
|
||||
@TSTAMP=$$(date +%s 2>/dev/null || echo "0")
|
||||
@printf "\033[1;97mCompiling $<\033[0m\n"
|
||||
@$(QUIET) || printf "\033[1;97mCompiling $<\033[0m\n"
|
||||
@$(CXX) $(CXXFLAGS) $(INC) -c -o $@ $< || exit 1
|
||||
@$(CXX) $(CXXFLAGS) $(INC) -MM $(SRCDIR)/$*.$(SRCEXT) > $(BUILDDIR)/$*.$(DEPEXT) >/dev/null || exit 1
|
||||
@cp -f $(BUILDDIR)/$*.$(DEPEXT) $(BUILDDIR)/$*.$(DEPEXT).tmp
|
||||
|
|
35
README.md
35
README.md
|
@ -1,5 +1,9 @@
|
|||
# ![btop++](Img/logo.png)
|
||||
|
||||
<a href="https://repology.org/project/btop/versions">
|
||||
<img src="https://repology.org/badge/vertical-allrepos/btop.svg" alt="Packaging status" align="right">
|
||||
</a>
|
||||
|
||||
![Linux](https://img.shields.io/badge/-Linux-grey?logo=linux)
|
||||
![Usage](https://img.shields.io/badge/Usage-System%20resource%20monitor-yellow)
|
||||
![c++20](https://img.shields.io/badge/cpp-c%2B%2B20-green)
|
||||
|
@ -163,9 +167,9 @@ Also needs a UTF8 locale and a font that covers:
|
|||
|
||||
## Installation
|
||||
|
||||
**Binary release (statically compiled)**
|
||||
**Binary release (statically compiled, for kernel 3.2.0 and newer)**
|
||||
|
||||
1. **Download btop-(VERSION)-(PLATFORM)-(ARCH).tbz from latest release and unpack to a new folder**
|
||||
1. **Download btop-(VERSION)-(PLATFORM)-(ARCH).tbz from [latest release](https://github.com/aristocratos/btop/releases/latest) and unpack to a new folder**
|
||||
|
||||
2. **Install (from created folder)**
|
||||
|
||||
|
@ -227,9 +231,13 @@ Also needs a UTF8 locale and a font that covers:
|
|||
|
||||
Append `STATIC=true` to `make` command for static compilation.
|
||||
|
||||
Append `QUIET=true` for less verbose output.
|
||||
|
||||
Notice! Manually set `$ARCH` variable if cross-compiling
|
||||
|
||||
Use `$ADDFLAGS` variable for appending flags to both compiler and linker.
|
||||
Use `ADDFLAGS` variable for appending flags to both compiler and linker.
|
||||
|
||||
For example: `make ADDFLAGS=-march=native` might give a performance boost if compiling only for your own system.
|
||||
|
||||
``` bash
|
||||
make
|
||||
|
@ -276,22 +284,27 @@ Also needs a UTF8 locale and a font that covers:
|
|||
```bash
|
||||
make help
|
||||
```
|
||||
|
||||
|
||||
## Install the snap
|
||||
[![btop](https://snapcraft.io/btop/badge.svg)](https://snapcraft.io/btop)
|
||||
|
||||
`sudo snap install btop`
|
||||
* **Install the snap**
|
||||
|
||||
```bash
|
||||
sudo snap install btop
|
||||
```
|
||||
|
||||
* **Connect the interfaces**
|
||||
```
|
||||
sudo snap connect btop:system-observe
|
||||
|
||||
```bash
|
||||
sudo snap connect btop:system-observe
|
||||
sudo snap connect btop:physical-memory-observe
|
||||
sudo snap connect btop:mount-observe
|
||||
sudo snap connect btop:mount-observe
|
||||
sudo snap connect btop:hardware-observe
|
||||
sudo snap connect btop:network-observe
|
||||
sudo snap connect btop:process-control
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Configurability
|
||||
|
||||
|
@ -485,7 +498,7 @@ net_iface = "br0"
|
|||
#* Show battery stats in top right if battery is present.
|
||||
show_battery = True
|
||||
|
||||
#* Set loglevel for "~/.config/btop/error.log" levels are: "ERROR" "WARNING" "INFO" "DEBUG".
|
||||
#* Set loglevel for "~/.config/btop/btop.log" levels are: "ERROR" "WARNING" "INFO" "DEBUG".
|
||||
#* The level set includes all lower levels, i.e. "DEBUG" will show all logging info.
|
||||
log_level = "DEBUG"
|
||||
```
|
||||
|
@ -501,7 +514,7 @@ optional arguments:
|
|||
-lc, --low-color disable truecolor, converts 24-bit colors to 256-color
|
||||
-t, --tty_on force (ON) tty mode, max 16 colors and tty friendly graph symbols
|
||||
+t, --tty_off force (OFF) tty mode
|
||||
-p --preset <id> start with preset, integer value between 0-9
|
||||
-p, --preset <id> start with preset, integer value between 0-9
|
||||
--utf-force force start even if no UTF-8 locale was detected
|
||||
--debug start in DEBUG mode: shows microsecond timer for information collect
|
||||
and screen draw functions and sets loglevel to DEBUG
|
||||
|
|
|
@ -25,16 +25,16 @@ architectures:
|
|||
package-repositories:
|
||||
- type: apt
|
||||
ppa: ubuntu-toolchain-r/test
|
||||
|
||||
|
||||
apps:
|
||||
btop:
|
||||
command: usr/local/bin/btop
|
||||
command-chain:
|
||||
- bin/homeishome-launch
|
||||
command-chain:
|
||||
- bin/homeishome-launch
|
||||
environment:
|
||||
LC_ALL: C.UTF-8
|
||||
LANG: C.UTF-8
|
||||
plugs:
|
||||
LANG: C.UTF-8
|
||||
plugs:
|
||||
- mount-observe
|
||||
- process-control
|
||||
- system-observe
|
||||
|
@ -43,30 +43,28 @@ apps:
|
|||
- network-observe
|
||||
- physical-memory-observe
|
||||
- home
|
||||
|
||||
|
||||
parts:
|
||||
btop:
|
||||
btop:
|
||||
source: https://github.com/aristocratos/btop
|
||||
source-type: git
|
||||
plugin: make
|
||||
make-parameters:
|
||||
- PREFIX=/usr/local
|
||||
- STATIC=true
|
||||
|
||||
build-packages:
|
||||
- coreutils
|
||||
- sed
|
||||
- git
|
||||
- build-essential
|
||||
- gcc-11
|
||||
- g++-11
|
||||
|
||||
- coreutils
|
||||
- sed
|
||||
- git
|
||||
- build-essential
|
||||
- gcc-11
|
||||
- g++-11
|
||||
override-pull: |
|
||||
snapcraftctl pull
|
||||
snapcraftctl set-version "$(git describe --tags | sed 's/^v//' | cut -d "-" -f1)"
|
||||
|
||||
|
||||
homeishome-launch:
|
||||
plugin: nil
|
||||
stage-snaps:
|
||||
- homeishome-launch
|
||||
|
||||
- homeishome-launch
|
||||
|
||||
|
|
67
src/btop.cpp
67
src/btop.cpp
|
@ -55,7 +55,7 @@ namespace Global {
|
|||
{"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"},
|
||||
{"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"},
|
||||
};
|
||||
const string Version = "1.0.0";
|
||||
const string Version = "1.0.9";
|
||||
|
||||
int coreCount;
|
||||
string overlay;
|
||||
|
@ -79,6 +79,7 @@ namespace Global {
|
|||
uint64_t start_time;
|
||||
|
||||
atomic<bool> resized (false);
|
||||
atomic<bool> resizing (false);
|
||||
atomic<bool> quitting (false);
|
||||
atomic<bool> _runner_started (false);
|
||||
|
||||
|
@ -100,7 +101,7 @@ void argumentParser(const int& argc, char **argv) {
|
|||
<< " -lc, --low-color disable truecolor, converts 24-bit colors to 256-color\n"
|
||||
<< " -t, --tty_on force (ON) tty mode, max 16 colors and tty friendly graph symbols\n"
|
||||
<< " +t, --tty_off force (OFF) tty mode\n"
|
||||
<< " -p --preset <id> start with preset, integer value between 0-9\n"
|
||||
<< " -p, --preset <id> start with preset, integer value between 0-9\n"
|
||||
<< " --utf-force force start even if no UTF-8 locale was detected\n"
|
||||
<< " --debug start in DEBUG mode: shows microsecond timer for information collect\n"
|
||||
<< " and screen draw functions and sets loglevel to DEBUG\n"
|
||||
|
@ -149,13 +150,17 @@ void argumentParser(const int& argc, char **argv) {
|
|||
|
||||
//* Handler for SIGWINCH and general resizing events, does nothing if terminal hasn't been resized unless force=true
|
||||
void term_resize(bool force) {
|
||||
if (Global::resizing) return;
|
||||
atomic_lock lck(Global::resizing);
|
||||
if (auto refreshed = Term::refresh(); refreshed or force) {
|
||||
if (force and refreshed) force = false;
|
||||
}
|
||||
else return;
|
||||
|
||||
static const array<string, 4> all_boxes = {"cpu", "mem", "net", "proc"};
|
||||
Global::resized = true;
|
||||
Runner::stop();
|
||||
if (Runner::active) Runner::stop();
|
||||
Config::unlock();
|
||||
|
||||
auto boxes = Config::getS("shown_boxes");
|
||||
auto min_size = Term::get_min_size(boxes);
|
||||
|
@ -171,7 +176,16 @@ void term_resize(bool force) {
|
|||
<< "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);
|
||||
if (Input::poll()) {
|
||||
auto key = Input::get();
|
||||
if (key == "q")
|
||||
exit(0);
|
||||
else if (is_in(key, "1", "2", "3", "4")) {
|
||||
Config::current_preset = -1;
|
||||
Config::toggle_box(all_boxes.at(std::stoi(key) - 1));
|
||||
boxes = Config::getS("shown_boxes");
|
||||
}
|
||||
}
|
||||
min_size = Term::get_min_size(boxes);
|
||||
}
|
||||
else if (not Term::refresh()) break;
|
||||
|
@ -644,8 +658,8 @@ int main(int argc, char **argv) {
|
|||
|
||||
//? Setup paths for config, log and user themes
|
||||
for (const auto& env : {"XDG_CONFIG_HOME", "HOME"}) {
|
||||
if (getenv(env) != NULL and access(getenv(env), W_OK) != -1) {
|
||||
Config::conf_dir = fs::path(getenv(env)) / (((string)env == "HOME") ? ".config/btop" : "btop");
|
||||
if (std::getenv(env) != NULL and access(std::getenv(env), W_OK) != -1) {
|
||||
Config::conf_dir = fs::path(std::getenv(env)) / (((string)env == "HOME") ? ".config/btop" : "btop");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -704,22 +718,28 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
//? Try to find and set a UTF-8 locale
|
||||
if (bool found = false; not str_to_upper(s_replace(string(std::setlocale(LC_ALL, NULL)), "-", "")).ends_with("UTF8")) {
|
||||
if (const string lang = (string)getenv("LANG"); str_to_upper(s_replace(lang, "-", "")).ends_with("UTF8")) {
|
||||
found = true;
|
||||
std::setlocale(LC_ALL, lang.c_str());
|
||||
if (bool found = false; std::setlocale(LC_ALL, NULL) == NULL or not str_to_upper(s_replace((string)std::setlocale(LC_ALL, NULL), "-", "")).ends_with("UTF8")) {
|
||||
if (std::getenv("LANG") != NULL and str_to_upper(s_replace((string)std::getenv("LANG"), "-", "")).ends_with("UTF8")) {
|
||||
if (std::setlocale(LC_ALL, std::getenv("LANG")) != NULL) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
else if (const string loc = std::locale("").name(); not loc.empty()) {
|
||||
try {
|
||||
for (auto& l : ssplit(loc, ';')) {
|
||||
if (str_to_upper(s_replace(l, "-", "")).ends_with("UTF8")) {
|
||||
found = true;
|
||||
std::setlocale(LC_ALL, l.substr(l.find('=') + 1).c_str());
|
||||
break;
|
||||
else {
|
||||
if (setenv("LANG", "", 1) == 0) {
|
||||
try {
|
||||
if (const auto loc = std::locale("").name(); not loc.empty() and loc != "*") {
|
||||
for (auto& l : ssplit(loc, ';')) {
|
||||
if (str_to_upper(s_replace(l, "-", "")).ends_with("UTF8")) {
|
||||
if (std::setlocale(LC_ALL, l.substr(l.find('=') + 1).c_str()) != NULL) {
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...) { found = false; }
|
||||
}
|
||||
catch (const std::out_of_range&) { found = false; }
|
||||
}
|
||||
|
||||
if (not found and Global::utf_force)
|
||||
|
@ -738,7 +758,7 @@ int main(int argc, char **argv) {
|
|||
exit(1);
|
||||
}
|
||||
|
||||
Logger::info("Running on " + Term::current_tty);
|
||||
if (Term::current_tty != "unknown") Logger::info("Running on " + Term::current_tty);
|
||||
if (not Global::arg_tty and Config::getB("force_tty")) {
|
||||
Config::set("tty_mode", true);
|
||||
Logger::info("Forcing tty mode: setting 16 color mode and using tty friendly graph symbols");
|
||||
|
@ -777,20 +797,19 @@ int main(int argc, char **argv) {
|
|||
Config::current_preset = min(Global::arg_preset, (int)Config::preset_list.size() - 1);
|
||||
Config::apply_preset(Config::preset_list.at(Config::current_preset));
|
||||
}
|
||||
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);
|
||||
term_resize(true);
|
||||
Global::resized = false;
|
||||
Input::interrupt = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//? Print out box outlines
|
||||
Draw::calcSizes();
|
||||
cout << Term::sync_start << Cpu::box << Mem::box << Net::box << Proc::box << Term::sync_end << flush;
|
||||
|
||||
|
||||
|
|
|
@ -167,7 +167,7 @@ namespace Config {
|
|||
|
||||
{"show_battery", "#* Show battery stats in top right if battery is present."},
|
||||
|
||||
{"log_level", "#* Set loglevel for \"~/.config/btop/error.log\" levels are: \"ERROR\" \"WARNING\" \"INFO\" \"DEBUG\".\n"
|
||||
{"log_level", "#* Set loglevel for \"~/.config/btop/btop.log\" levels are: \"ERROR\" \"WARNING\" \"INFO\" \"DEBUG\".\n"
|
||||
"#* The level set includes all lower levels, i.e. \"DEBUG\" will show all logging info."}
|
||||
};
|
||||
|
||||
|
@ -224,7 +224,7 @@ namespace Config {
|
|||
{"swap_disk", true},
|
||||
{"show_disks", true},
|
||||
{"only_physical", true},
|
||||
{"use_fstab", false},
|
||||
{"use_fstab", true},
|
||||
{"show_io_stat", true},
|
||||
{"io_mode", false},
|
||||
{"io_graph_combined", false},
|
||||
|
@ -306,15 +306,26 @@ namespace Config {
|
|||
//* Apply selected preset
|
||||
void apply_preset(const string& preset) {
|
||||
string boxes;
|
||||
|
||||
for (const auto& box : ssplit(preset, ',')) {
|
||||
const auto& vals = ssplit(box, ':');
|
||||
boxes += vals.at(0) + ' ';
|
||||
}
|
||||
if (not boxes.empty()) boxes.pop_back();
|
||||
|
||||
auto min_size = Term::get_min_size(boxes);
|
||||
if (Term::width < min_size.at(0) or Term::height < min_size.at(1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto& box : ssplit(preset, ',')) {
|
||||
const auto& vals = ssplit(box, ':');
|
||||
if (vals.at(0) == "cpu") set("cpu_bottom", (vals.at(1) == "0" ? false : true));
|
||||
else if (vals.at(0) == "mem") set("mem_below_net", (vals.at(1) == "0" ? false : true));
|
||||
else if (vals.at(0) == "proc") set("proc_left", (vals.at(1) == "0" ? false : true));
|
||||
set("graph_symbol_" + vals.at(0), vals.at(2));
|
||||
}
|
||||
if (not boxes.empty()) boxes.pop_back();
|
||||
|
||||
if (check_boxes(boxes)) set("shown_boxes", boxes);
|
||||
}
|
||||
|
||||
|
@ -475,6 +486,7 @@ namespace Config {
|
|||
}
|
||||
|
||||
void toggle_box(const string& box) {
|
||||
auto old_boxes = current_boxes;
|
||||
auto box_pos = rng::find(current_boxes, box);
|
||||
if (box_pos == current_boxes.end())
|
||||
current_boxes.push_back(box);
|
||||
|
@ -486,6 +498,14 @@ namespace Config {
|
|||
for (const auto& b : current_boxes) new_boxes += b + ' ';
|
||||
new_boxes.pop_back();
|
||||
}
|
||||
|
||||
auto min_size = Term::get_min_size(new_boxes);
|
||||
|
||||
if (Term::width < min_size.at(0) or Term::height < min_size.at(1)) {
|
||||
current_boxes = old_boxes;
|
||||
return;
|
||||
}
|
||||
|
||||
Config::set("shown_boxes", new_boxes);
|
||||
}
|
||||
|
||||
|
|
|
@ -396,7 +396,7 @@ namespace Draw {
|
|||
out.clear();
|
||||
if (height == 1) {
|
||||
if (not color_gradient.empty())
|
||||
out += (last < 1 and not color_gradient.empty() ? Theme::c("inactive_fg") : Theme::g(color_gradient).at(last));
|
||||
out += (last < 1 and not color_gradient.empty() ? Theme::c("inactive_fg") : Theme::g(color_gradient).at(clamp(last, 0ll, 100ll)));
|
||||
out += graphs.at(current).at(0);
|
||||
}
|
||||
else {
|
||||
|
@ -618,7 +618,7 @@ namespace Cpu {
|
|||
+ Symbols::title_left + Fx::b + Theme::c("title") + cpuHz + Fx::ub + Theme::c("div_line") + Symbols::title_right;
|
||||
|
||||
out += Mv::to(b_y + 1, b_x + 1) + Theme::c("main_fg") + Fx::b + "CPU " + cpu_meter(cpu.cpu_percent.at("total").back())
|
||||
+ Theme::g("cpu").at(cpu.cpu_percent.at("total").back()) + rjust(to_string(cpu.cpu_percent.at("total").back()), 4) + Theme::c("main_fg") + '%';
|
||||
+ Theme::g("cpu").at(clamp(cpu.cpu_percent.at("total").back(), 0ll, 100ll)) + rjust(to_string(cpu.cpu_percent.at("total").back()), 4) + Theme::c("main_fg") + '%';
|
||||
if (show_temps) {
|
||||
const auto [temp, unit] = celsius_to(cpu.temp.at(0).back(), temp_scale);
|
||||
const auto& temp_color = Theme::g("temp").at(clamp(cpu.temp.at(0).back() * 100 / cpu.temp_max, 0ll, 100ll));
|
||||
|
@ -632,15 +632,16 @@ namespace Cpu {
|
|||
} catch (const std::exception& e) { throw std::runtime_error("graphs, clock, meter : " + (string)e.what()); }
|
||||
|
||||
//? Core text and graphs
|
||||
int cx = 0, cy = 1, cc = 0;
|
||||
int cx = 0, cy = 1, cc = 0, core_width = (b_column_size == 0 ? 2 : 3);
|
||||
if (Shared::coreCount >= 100) core_width++;
|
||||
for (const auto& n : iota(0, Shared::coreCount)) {
|
||||
out += Mv::to(b_y + cy + 1, b_x + cx + 1) + Theme::c("main_fg") + (Shared::coreCount < 100 ? Fx::b + 'C' + Fx::ub : "")
|
||||
+ ljust(to_string(n), (b_column_size == 0 ? 2 : 3));
|
||||
+ ljust(to_string(n), core_width);
|
||||
if (b_column_size > 0 or extra_width > 0)
|
||||
out += Theme::c("inactive_fg") + graph_bg * (5 * b_column_size + extra_width) + Mv::l(5 * b_column_size + extra_width)
|
||||
+ Theme::g("cpu").at(cpu.core_percent.at(n).back()) + core_graphs.at(n)(cpu.core_percent.at(n), data_same or redraw);
|
||||
+ Theme::g("cpu").at(clamp(cpu.core_percent.at(n).back(), 0ll, 100ll)) + core_graphs.at(n)(cpu.core_percent.at(n), data_same or redraw);
|
||||
else
|
||||
out += Theme::g("cpu").at(cpu.core_percent.at(n).back());
|
||||
out += Theme::g("cpu").at(clamp(cpu.core_percent.at(n).back(), 0ll, 100ll));
|
||||
out += rjust(to_string(cpu.core_percent.at(n).back()), (b_column_size < 2 ? 3 : 4)) + Theme::c("main_fg") + '%';
|
||||
|
||||
if (show_temps and not hide_cores) {
|
||||
|
@ -654,7 +655,7 @@ namespace Cpu {
|
|||
|
||||
out += Theme::c("div_line") + Symbols::v_line;
|
||||
|
||||
if (++cy > ceil((double)Shared::coreCount / b_columns) and n != Shared::coreCount - 1) {
|
||||
if ((++cy > ceil((double)Shared::coreCount / b_columns) or cy == b_height - 2) and n != Shared::coreCount - 1) {
|
||||
if (++cc >= b_columns) break;
|
||||
cy = 1; cx = (b_width / b_columns) * cc;
|
||||
}
|
||||
|
@ -664,9 +665,9 @@ namespace Cpu {
|
|||
if (cy < b_height - 1 and cc <= b_columns) {
|
||||
string lavg_pre;
|
||||
int sep = 1;
|
||||
if (b_column_size == 2 and got_sensors) { lavg_pre = "Load AVG:"; sep = 3; }
|
||||
else if (b_column_size == 2 or (b_column_size == 1 and got_sensors)) { lavg_pre = "LAV:"; }
|
||||
else if (b_column_size == 1 or (b_column_size == 0 and got_sensors)) { lavg_pre = "L"; }
|
||||
if (b_column_size == 2 and show_temps) { lavg_pre = "Load AVG:"; sep = 3; }
|
||||
else if (b_column_size == 2 or (b_column_size == 1 and show_temps)) { lavg_pre = "LAV:"; }
|
||||
else if (b_column_size == 1 or (b_column_size == 0 and show_temps)) { lavg_pre = "L"; }
|
||||
string lavg;
|
||||
for (const auto& val : cpu.load_avg) {
|
||||
lavg += string(sep, ' ') + (lavg_pre.size() < 3 ? to_string((int)round(val)) : to_string(val).substr(0, 4));
|
||||
|
@ -860,7 +861,7 @@ namespace Mem {
|
|||
const string used_percent = to_string(disk.used_percent);
|
||||
out += Mv::to(y+1+cy, x+1+cx + round((double)disks_width / 2) - round((double)used_percent.size() / 2)) + Theme::c("main_fg") + used_percent + '%';
|
||||
}
|
||||
out += Mv::to(y+2+cy++, x+1+cx) + (big_disk ? " IO% " : " IO " + Mv::l(2)) + Theme::c("inactive_fg") + graph_bg * (disks_width - 6) + Theme::g("available").at(max(50ll, disk.io_activity.back()))
|
||||
out += Mv::to(y+2+cy++, x+1+cx) + (big_disk ? " IO% " : " IO " + Mv::l(2)) + Theme::c("inactive_fg") + graph_bg * (disks_width - 6) + Theme::g("available").at(clamp(disk.io_activity.back(), 50ll, 100ll))
|
||||
+ Mv::l(disks_width - 6) + io_graphs.at(mount + "_activity")(disk.io_activity, redraw or data_same) + Theme::c("main_fg");
|
||||
if (++cy > height - 3) break;
|
||||
if (io_graph_combined) {
|
||||
|
@ -901,7 +902,7 @@ namespace Mem {
|
|||
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;
|
||||
if (++cy > height - 3) break;
|
||||
if (show_io_stat and io_graphs.contains(mount + "_activity")) {
|
||||
out += Mv::to(y+1+cy, x+1+cx) + (big_disk ? " IO% " : " IO " + Mv::l(2)) + Theme::c("inactive_fg") + graph_bg * (disks_width - 6) + Theme::g("available").at(max(50ll, disk.io_activity.back()))
|
||||
out += Mv::to(y+1+cy, x+1+cx) + (big_disk ? " IO% " : " IO " + Mv::l(2)) + Theme::c("inactive_fg") + graph_bg * (disks_width - 6) + Theme::g("available").at(clamp(disk.io_activity.back(), 50ll, 100ll))
|
||||
+ Mv::l(disks_width - 6) + io_graphs.at(mount + "_activity")(disk.io_activity, redraw or data_same) + Theme::c("main_fg");
|
||||
if (not big_disk) out += Mv::to(y+1+cy, x+cx) + Theme::c("main_fg") + human_io;
|
||||
if (++cy > height - 3) break;
|
||||
|
@ -1331,11 +1332,8 @@ namespace Proc {
|
|||
+ Theme::c("inactive_fg") + Fx::ub + graph_bg * (d_width / 3) + Mv::l(d_width / 3)
|
||||
+ Theme::c("proc_misc") + detailed_mem_graph(detailed.mem_bytes, (redraw or data_same or not alive)) + ' '
|
||||
+ Theme::c("title") + Fx::b + detailed.memory;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
//? Check bounds of current selection and view
|
||||
if (start > 0 and numpids <= select_max)
|
||||
start = 0;
|
||||
|
@ -1349,7 +1347,7 @@ namespace Proc {
|
|||
//* Iteration over processes
|
||||
int lc = 0;
|
||||
for (int n=0; auto& p : plist) {
|
||||
if (n++ < start or p.filtered) continue;
|
||||
if (p.filtered or (proc_tree and p.tree_index == plist.size()) or n++ < start) continue;
|
||||
bool is_selected = (lc + 1 == selected);
|
||||
if (is_selected) {
|
||||
selected_pid = (int)p.pid;
|
||||
|
@ -1388,11 +1386,11 @@ namespace Proc {
|
|||
for (int i = 0; int v : {(int)round(p.cpu_p), (int)round(p.mem * 100 / Shared::totalMem), (int)p.threads / 3}) {
|
||||
if (proc_gradient) {
|
||||
int val = (min(v, 100) + 100) - calc * 100 / select_max;
|
||||
if (val < 100) colors[i++] = Theme::g("proc_color").at(val);
|
||||
else colors[i++] = Theme::g("process").at(val - 100);
|
||||
if (val < 100) colors[i++] = Theme::g("proc_color").at(max(0, val));
|
||||
else colors[i++] = Theme::g("process").at(clamp(val - 100, 0, 100));
|
||||
}
|
||||
else
|
||||
colors[i++] = Theme::g("process").at(min(v, 100));
|
||||
colors[i++] = Theme::g("process").at(clamp(v, 0, 100));
|
||||
}
|
||||
c_color = colors.at(0); m_color = colors.at(1); t_color = colors.at(2);
|
||||
}
|
||||
|
@ -1401,7 +1399,7 @@ namespace Proc {
|
|||
end = Fx::ub;
|
||||
}
|
||||
if (proc_gradient) {
|
||||
g_color = Theme::g("proc").at(calc * 100 / select_max);
|
||||
g_color = Theme::g("proc").at(clamp(calc * 100 / select_max, 0, 100));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1433,9 +1431,10 @@ namespace Proc {
|
|||
if (p.cpu_p < 10 or p.cpu_p >= 100) cpu_str.resize(3);
|
||||
string mem_str = (mem_bytes ? floating_humanizer(p.mem, true) : "");
|
||||
if (not mem_bytes) {
|
||||
double mem_p = (double)p.mem * 100 / Shared::totalMem;
|
||||
double mem_p = clamp((double)p.mem * 100 / Shared::totalMem, 0.0, 100.0);
|
||||
mem_str = to_string(mem_p);
|
||||
mem_str.resize((mem_p < 10 or mem_p >= 100 ? 3 : 4));
|
||||
if (mem_str.size() < 4) mem_str = "0";
|
||||
else mem_str.resize((mem_p < 10 or mem_p >= 100 ? 3 : 4));
|
||||
mem_str += '%';
|
||||
}
|
||||
out += (thread_size > 0 ? t_color + rjust(to_string(min(p.threads, (size_t)9999)), thread_size) + ' ' + end : "" )
|
||||
|
@ -1452,7 +1451,7 @@ namespace Proc {
|
|||
|
||||
//? Draw scrollbar if needed
|
||||
if (numpids > select_max) {
|
||||
const int scroll_pos = clamp((int)round((double)start * (select_max - 2) / (numpids - (select_max - 2))), 0, height - 5);
|
||||
const int scroll_pos = clamp((int)round((double)start * select_max / (numpids - select_max)), 0, height - 5);
|
||||
out += Mv::to(y + 1, x + width - 2) + Fx::b + Theme::c("main_fg") + Symbols::up
|
||||
+ Mv::to(y + height - 2, x + width - 2) + Symbols::down
|
||||
+ Mv::to(y + 2 + scroll_pos, x + width - 2) + "█";
|
||||
|
|
|
@ -95,7 +95,7 @@ namespace Input {
|
|||
string get() {
|
||||
string key;
|
||||
while (cin.rdbuf()->in_avail() > 0 and key.size() < 100) key += cin.get();
|
||||
if (cin.rdbuf()->in_avail() > 0) cin.ignore(SSmax);
|
||||
if (cin.rdbuf()->in_avail() > 0) cin.ignore(cin.rdbuf()->in_avail());
|
||||
if (not key.empty()) {
|
||||
//? Remove escape code prefix if present
|
||||
if (key.substr(0, 2) == Fx::e) {
|
||||
|
@ -351,7 +351,6 @@ namespace Input {
|
|||
return;
|
||||
}
|
||||
else if (key == "s" and (Config::getB("show_detailed") or Config::getI("selected_pid") > 0)) {
|
||||
if (Term::width < 80 or Term::height < 20) return;
|
||||
atomic_wait(Runner::active);
|
||||
if (Config::getB("show_detailed") and Config::getI("proc_selected") == 0 and Proc::detailed.status == "Dead") return;
|
||||
Menu::show(Menu::Menus::SignalChoose);
|
||||
|
|
|
@ -757,6 +757,28 @@ namespace Menu {
|
|||
return (redraw ? Changed : retval);
|
||||
}
|
||||
|
||||
int sizeError(const string& key) {
|
||||
if (redraw) {
|
||||
vector<string> cont_vec;
|
||||
cont_vec.push_back(Fx::b + Theme::g("used")[100] + "Error:" + Theme::c("main_fg") + Fx::ub);
|
||||
cont_vec.push_back("Terminal size to small to" + Fx::reset);
|
||||
cont_vec.push_back("display menu or box!" + Fx::reset);
|
||||
|
||||
messageBox = Menu::msgBox{45, 0, cont_vec, "error"};
|
||||
Global::overlay = messageBox();
|
||||
}
|
||||
|
||||
auto ret = messageBox.input(key);
|
||||
if (ret == msgBox::Ok_Yes or ret == msgBox::No_Esc) {
|
||||
messageBox.clear();
|
||||
return Closed;
|
||||
}
|
||||
else if (redraw) {
|
||||
return Changed;
|
||||
}
|
||||
return NoChange;
|
||||
}
|
||||
|
||||
int signalSend(const string& key) {
|
||||
auto& s_pid = (Config::getB("show_detailed") and Config::getI("selected_pid") == 0 ? Config::getI("detailed_pid") : Config::getI("selected_pid"));
|
||||
if (s_pid == 0) return Closed;
|
||||
|
@ -1168,7 +1190,7 @@ namespace Menu {
|
|||
i++;
|
||||
}
|
||||
if (pages > 1) {
|
||||
out += Mv::to(y+6 + height, x+2) + Theme::c("hi_fg") + Symbols::title_left_down + Fx::b + Symbols::up + Theme::c("title") + " page "
|
||||
out += Mv::to(y+6 + height - 1, x+2) + Theme::c("hi_fg") + Symbols::title_left_down + Fx::b + Symbols::up + Theme::c("title") + " page "
|
||||
+ to_string(page+1) + '/' + to_string(pages) + ' ' + Theme::c("hi_fg") + Symbols::down + Fx::ub + Symbols::title_right_down;
|
||||
}
|
||||
//? Option name and value
|
||||
|
@ -1286,6 +1308,7 @@ namespace Menu {
|
|||
|
||||
//* Add menus here and update enum Menus in header
|
||||
const auto menuFunc = vector{
|
||||
ref(sizeError),
|
||||
ref(signalChoose),
|
||||
ref(signalSend),
|
||||
ref(signalReturn),
|
||||
|
@ -1312,9 +1335,17 @@ namespace Menu {
|
|||
if (currentMenu < 0 or not menuMask.test(currentMenu)) {
|
||||
Menu::active = true;
|
||||
redraw = true;
|
||||
if (((menuMask.test(Main) or menuMask.test(Options) or menuMask.test(Help) or menuMask.test(SignalChoose))
|
||||
and (Term::width < 80 or Term::height < 24))
|
||||
or (Term::width < 50 or Term::height < 20)) {
|
||||
menuMask.reset();
|
||||
menuMask.set(SizeError);
|
||||
}
|
||||
|
||||
for (const auto& i : iota(0, (int)menuMask.size())) {
|
||||
if (menuMask.test(i)) currentMenu = i;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
auto retCode = menuFunc.at(currentMenu)(key);
|
||||
|
|
|
@ -69,6 +69,7 @@ namespace Menu {
|
|||
|
||||
//* Enum for functions in vector menuFuncs
|
||||
enum Menus {
|
||||
SizeError,
|
||||
SignalChoose,
|
||||
SignalSend,
|
||||
SignalReturn,
|
||||
|
|
|
@ -70,6 +70,7 @@ namespace Shared {
|
|||
void init();
|
||||
|
||||
extern long coreCount, page_size, clk_tck;
|
||||
extern int totalMem_len;
|
||||
extern uint64_t totalMem;
|
||||
}
|
||||
|
||||
|
|
|
@ -159,7 +159,7 @@ namespace Theme {
|
|||
string pre = Fx::e + (depth == "fg" ? "38" : "48") + ";" + (t_to_256 ? "5;" : "2;");
|
||||
|
||||
if (hexa.size() == 2) {
|
||||
int h_int = stoi(hexa, 0, 16);
|
||||
int h_int = stoi(hexa, nullptr, 16);
|
||||
if (t_to_256) {
|
||||
return pre + to_string(truecolor_to_256(h_int, h_int, h_int)) + "m";
|
||||
} else {
|
||||
|
@ -170,14 +170,14 @@ namespace Theme {
|
|||
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";
|
||||
stoi(hexa.substr(0, 2), nullptr, 16),
|
||||
stoi(hexa.substr(2, 2), nullptr, 16),
|
||||
stoi(hexa.substr(4, 2), nullptr, 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";
|
||||
to_string(stoi(hexa.substr(0, 2), nullptr, 16)) + ";" +
|
||||
to_string(stoi(hexa.substr(2, 2), nullptr, 16)) + ";" +
|
||||
to_string(stoi(hexa.substr(4, 2), nullptr, 16)) + "m";
|
||||
}
|
||||
}
|
||||
else Logger::error("Invalid size of hex value: " + hexa);
|
||||
|
@ -203,14 +203,14 @@ namespace Theme {
|
|||
for (auto& c : hexa) if (not isxdigit(c)) return array<int, 3>{-1, -1, -1};
|
||||
|
||||
if (hexa.size() == 2) {
|
||||
int h_int = stoi(hexa, 0, 16);
|
||||
int h_int = stoi(hexa, nullptr, 16);
|
||||
return array<int, 3>{h_int, h_int, h_int};
|
||||
}
|
||||
else if (hexa.size() == 6) {
|
||||
return array<int, 3>{
|
||||
stoi(hexa.substr(0, 2), 0, 16),
|
||||
stoi(hexa.substr(2, 2), 0, 16),
|
||||
stoi(hexa.substr(4, 2), 0, 16)
|
||||
stoi(hexa.substr(0, 2), nullptr, 16),
|
||||
stoi(hexa.substr(2, 2), nullptr, 16),
|
||||
stoi(hexa.substr(4, 2), nullptr, 16)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -434,4 +434,4 @@ namespace Theme {
|
|||
Fx::reset = Fx::reset_base + Term::fg + Term::bg;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -107,7 +107,7 @@ namespace Term {
|
|||
initialized = (bool)isatty(STDIN_FILENO);
|
||||
if (initialized) {
|
||||
tcgetattr(STDIN_FILENO, &initial_settings);
|
||||
current_tty = (string)ttyname(STDIN_FILENO);
|
||||
current_tty = (ttyname(STDIN_FILENO) != NULL ? (string)ttyname(STDIN_FILENO) : "unknown");
|
||||
|
||||
//? Disable stream sync
|
||||
cin.sync_with_stdio(false);
|
||||
|
|
|
@ -80,6 +80,7 @@ namespace Shared {
|
|||
fs::path procPath, passwd_path;
|
||||
uint64_t totalMem;
|
||||
long pageSize, clkTck, coreCount;
|
||||
int totalMem_len;
|
||||
|
||||
void init() {
|
||||
|
||||
|
@ -114,6 +115,7 @@ namespace Shared {
|
|||
if (meminfo.good()) {
|
||||
meminfo.ignore(SSmax, ':');
|
||||
meminfo >> totalMem;
|
||||
totalMem_len = to_string(totalMem).size();
|
||||
totalMem <<= 10;
|
||||
}
|
||||
if (not meminfo.good() or totalMem == 0)
|
||||
|
@ -1168,6 +1170,7 @@ namespace Proc {
|
|||
out_procs.back().get().cpu_p += p.cpu_p;
|
||||
out_procs.back().get().mem += p.mem;
|
||||
out_procs.back().get().threads += p.threads;
|
||||
filter_found++;
|
||||
}
|
||||
if (collapsed and not filtering) {
|
||||
cur_proc.filtered = true;
|
||||
|
@ -1201,7 +1204,7 @@ namespace Proc {
|
|||
|
||||
//? Update cpu percent deque for process cpu graph
|
||||
if (not Config::getB("proc_per_core")) detailed.entry.cpu_p *= Shared::coreCount;
|
||||
detailed.cpu_percent.push_back(round(detailed.entry.cpu_p));
|
||||
detailed.cpu_percent.push_back(clamp((long long)round(detailed.entry.cpu_p), 0ll, 100ll));
|
||||
while (cmp_greater(detailed.cpu_percent.size(), width)) detailed.cpu_percent.pop_front();
|
||||
|
||||
//? Process runtime
|
||||
|
@ -1451,7 +1454,10 @@ namespace Proc {
|
|||
next_x = 24;
|
||||
continue;
|
||||
case 24: //? RSS memory (can be inaccurate, but parsing smaps increases total cpu usage by ~20x)
|
||||
new_proc.mem = stoull(short_str) * Shared::pageSize;
|
||||
if (cmp_greater(short_str.size(), Shared::totalMem_len))
|
||||
new_proc.mem = Shared::totalMem;
|
||||
else
|
||||
new_proc.mem = stoull(short_str) * Shared::pageSize;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1464,8 +1470,18 @@ namespace Proc {
|
|||
|
||||
if (x-offset < 24) continue;
|
||||
|
||||
//? Get RSS memory from /proc/[pid]/statm if value from /proc/[pid]/stat looks wrong
|
||||
if (new_proc.mem >= Shared::totalMem) {
|
||||
pread.open(d.path() / "statm");
|
||||
if (not pread.good()) continue;
|
||||
pread.ignore(SSmax, ' ');
|
||||
pread >> new_proc.mem;
|
||||
new_proc.mem *= Shared::pageSize;
|
||||
pread.close();
|
||||
}
|
||||
|
||||
//? Process cpu usage since last update
|
||||
new_proc.cpu_p = round(cmult * 1000 * (cpu_t - new_proc.cpu_t) / max((uint64_t)1, cputimes - old_cputimes)) / 10.0;
|
||||
new_proc.cpu_p = clamp(round(cmult * 1000 * (cpu_t - new_proc.cpu_t) / max((uint64_t)1, cputimes - old_cputimes)) / 10.0, 0.0, 100.0 * Shared::coreCount);
|
||||
|
||||
//? Process cumulative cpu usage since process start
|
||||
new_proc.cpu_c = (double)cpu_t / max(1.0, (uptime * Shared::clkTck) - new_proc.cpu_s);
|
||||
|
@ -1595,8 +1611,15 @@ namespace Tools {
|
|||
double system_uptime() {
|
||||
string upstr;
|
||||
ifstream pread(Shared::procPath / "uptime");
|
||||
getline(pread, upstr, ' ');
|
||||
pread.close();
|
||||
return stod(upstr);
|
||||
if (pread.good()) {
|
||||
try {
|
||||
getline(pread, upstr, ' ');
|
||||
pread.close();
|
||||
return stod(upstr);
|
||||
}
|
||||
catch (const std::invalid_argument&) {}
|
||||
catch (const std::out_of_range&) {}
|
||||
}
|
||||
throw std::runtime_error("Failed get uptime from from " + (string)Shared::procPath + "/uptime");
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue