mirror of
https://github.com/aristocratos/btop.git
synced 2024-09-21 03:42:45 +12:00
Fixed filtering for processes tree view
This commit is contained in:
parent
db3bf06485
commit
331665dc55
8 changed files with 52 additions and 44 deletions
|
@ -390,7 +390,7 @@ int main(int argc, char **argv){
|
||||||
cout << "\nTheme generation of " << fs::path(Config::getS("color_theme")).filename().replace_extension("") << " took " << time_micros() - thts << "μs" << endl;
|
cout << "\nTheme generation of " << fs::path(Config::getS("color_theme")).filename().replace_extension("") << " took " << time_micros() - thts << "μs" << endl;
|
||||||
|
|
||||||
cout << "Colors:" << endl;
|
cout << "Colors:" << endl;
|
||||||
uint i = 0;
|
size_t i = 0;
|
||||||
for(auto& item : Theme::test_colors()) {
|
for(auto& item : Theme::test_colors()) {
|
||||||
cout << rjust(item.first, 15) << ":" << item.second << "■"s * 10 << Fx::reset << " ";
|
cout << rjust(item.first, 15) << ":" << item.second << "■"s * 10 << Fx::reset << " ";
|
||||||
// << Theme::dec(item.first)[0] << ":" << Theme::dec(item.first)[1] << ":" << Theme::dec(item.first)[2] << ;
|
// << Theme::dec(item.first)[0] << ":" << Theme::dec(item.first)[1] << ":" << Theme::dec(item.first)[2] << ;
|
||||||
|
@ -596,11 +596,11 @@ int main(int argc, char **argv){
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
uint lc;
|
size_t lc;
|
||||||
string ostring;
|
string ostring;
|
||||||
uint64_t tsl, timestamp2, rcount = 0;
|
uint64_t tsl, timestamp2, rcount = 0;
|
||||||
list<uint64_t> avgtimes = {0};
|
list<uint64_t> avgtimes = {0};
|
||||||
uint timer = 2000;
|
size_t timer = 2000;
|
||||||
bool filtering = false;
|
bool filtering = false;
|
||||||
vector<string> greyscale;
|
vector<string> greyscale;
|
||||||
string filter;
|
string filter;
|
||||||
|
@ -608,7 +608,7 @@ int main(int argc, char **argv){
|
||||||
string key;
|
string key;
|
||||||
|
|
||||||
int xc;
|
int xc;
|
||||||
for (uint i : iota(0, (int)Term::height - 19)){
|
for (size_t i : iota(0, (int)Term::height - 19)){
|
||||||
xc = 230 - i * 150 / (Term::height - 20);
|
xc = 230 - i * 150 / (Term::height - 20);
|
||||||
greyscale.push_back(Theme::dec_to_color(xc, xc, xc));
|
greyscale.push_back(Theme::dec_to_color(xc, xc, xc));
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,12 +107,12 @@ namespace Draw {
|
||||||
out = Fx::reset + lcolor;
|
out = Fx::reset + lcolor;
|
||||||
|
|
||||||
//* Draw horizontal lines
|
//* Draw horizontal lines
|
||||||
for (uint hpos : {c.y, c.y + c.height - 1}){
|
for (size_t hpos : {c.y, c.y + c.height - 1}){
|
||||||
out += Mv::to(hpos, c.x) + Symbols::h_line * (c.width - 1);
|
out += Mv::to(hpos, c.x) + Symbols::h_line * (c.width - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
//* Draw vertical lines and fill if enabled
|
//* Draw vertical lines and fill if enabled
|
||||||
for (uint hpos : iota(c.y + 1, c.y + c.height - 1)){
|
for (size_t hpos : iota(c.y + 1, c.y + c.height - 1)){
|
||||||
out += Mv::to(hpos, c.x) + Symbols::v_line +
|
out += Mv::to(hpos, c.x) + Symbols::v_line +
|
||||||
((c.fill) ? string(c.width - 2, ' ') : Mv::r(c.width - 2)) +
|
((c.fill) ? string(c.width - 2, ' ') : Mv::r(c.width - 2)) +
|
||||||
Symbols::v_line;
|
Symbols::v_line;
|
||||||
|
|
|
@ -40,12 +40,12 @@ namespace Symbols {
|
||||||
namespace Draw {
|
namespace Draw {
|
||||||
|
|
||||||
struct BoxConf {
|
struct BoxConf {
|
||||||
uint x=0, y=0;
|
size_t x=0, y=0;
|
||||||
uint width=0, height=0;
|
size_t width=0, height=0;
|
||||||
string line_color = "", title = "", title2 = "";
|
string line_color = "", title = "", title2 = "";
|
||||||
bool fill = true;
|
bool fill = true;
|
||||||
uint num=0;
|
size_t num=0;
|
||||||
uint w_percent=0, h_percent=0;
|
size_t w_percent=0, h_percent=0;
|
||||||
};
|
};
|
||||||
|
|
||||||
//* Create a box using values from a BoxConf struct and return as a string
|
//* Create a box using values from a BoxConf struct and return as a string
|
||||||
|
|
|
@ -26,13 +26,6 @@ tab-size = 4
|
||||||
using std::string, robin_hood::unordered_flat_map, std::cin;
|
using std::string, robin_hood::unordered_flat_map, std::cin;
|
||||||
using namespace Tools;
|
using namespace Tools;
|
||||||
|
|
||||||
/* The input functions relies on the following std::cin options being set:
|
|
||||||
cin.sync_with_stdio(false);
|
|
||||||
cin.tie(NULL);
|
|
||||||
These will automatically be set when running Term::init() from btop_tools.cpp
|
|
||||||
*/
|
|
||||||
|
|
||||||
//* Functions and variables for handling keyboard and mouse input
|
|
||||||
namespace Input {
|
namespace Input {
|
||||||
namespace {
|
namespace {
|
||||||
//* Map for translating key codes to readable values
|
//* Map for translating key codes to readable values
|
||||||
|
@ -102,7 +95,6 @@ namespace Input {
|
||||||
return get();
|
return get();
|
||||||
}
|
}
|
||||||
|
|
||||||
//* Clears last entered key
|
|
||||||
void clear(){
|
void clear(){
|
||||||
last.clear();
|
last.clear();
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,10 +100,10 @@ namespace Proc {
|
||||||
size_t depth = 0;
|
size_t depth = 0;
|
||||||
bool collapsed = false;
|
bool collapsed = false;
|
||||||
};
|
};
|
||||||
unordered_flat_map<uint, p_cache> cache;
|
unordered_flat_map<size_t, p_cache> cache;
|
||||||
unordered_flat_map<string, string> uid_user;
|
unordered_flat_map<string, string> uid_user;
|
||||||
|
|
||||||
uint counter = 0;
|
int counter = 0;
|
||||||
}
|
}
|
||||||
uint64_t old_cputimes = 0;
|
uint64_t old_cputimes = 0;
|
||||||
size_t numpids = 500;
|
size_t numpids = 500;
|
||||||
|
@ -121,22 +121,38 @@ namespace Proc {
|
||||||
};
|
};
|
||||||
|
|
||||||
//* Generate process tree list
|
//* Generate process tree list
|
||||||
void _tree_gen(const proc_info& cur_proc, const vector<proc_info>& in_procs, vector<proc_info>& out_procs, const int cur_depth, const bool collapsed, const string& prefix){
|
void _tree_gen(const proc_info& cur_proc, const vector<proc_info>& in_procs, vector<proc_info>& out_procs, int cur_depth, const bool collapsed, const string& prefix, const string& filter, bool found){
|
||||||
auto cur_pos = out_procs.size();
|
auto cur_pos = out_procs.size();
|
||||||
if (not collapsed)
|
bool filtering = false;
|
||||||
|
|
||||||
|
//? 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) {
|
||||||
|
filtering = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
found = true;
|
||||||
|
cur_depth = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not collapsed and not filtering)
|
||||||
out_procs.push_back(cur_proc);
|
out_procs.push_back(cur_proc);
|
||||||
|
|
||||||
int children = 0;
|
int children = 0;
|
||||||
for (auto& p : rng::equal_range(in_procs, cur_proc.pid, rng::less{}, &proc_info::ppid)) {
|
for (auto& p : rng::equal_range(in_procs, cur_proc.pid, rng::less{}, &proc_info::ppid)) {
|
||||||
if (collapsed) {
|
if (collapsed and not filtering) {
|
||||||
out_procs.back().cpu_p += p.cpu_p;
|
out_procs.back().cpu_p += p.cpu_p;
|
||||||
out_procs.back().mem += p.mem;
|
out_procs.back().mem += p.mem;
|
||||||
out_procs.back().threads += p.threads;
|
out_procs.back().threads += p.threads;
|
||||||
}
|
}
|
||||||
else children++;
|
else children++;
|
||||||
_tree_gen(p, in_procs, out_procs, cur_depth + 1, (collapsed ? true : cache.at(cur_proc.pid).collapsed), prefix);
|
_tree_gen(p, in_procs, out_procs, cur_depth + 1, (collapsed ? true : cache.at(cur_proc.pid).collapsed), prefix, filter, found);
|
||||||
}
|
}
|
||||||
if (collapsed) return;
|
if (collapsed or filtering) return;
|
||||||
|
|
||||||
if (out_procs.size() > cur_pos + 1 and not out_procs.back().prefix.ends_with("] "))
|
if (out_procs.size() > cur_pos + 1 and not out_procs.back().prefix.ends_with("] "))
|
||||||
out_procs.back().prefix.replace(out_procs.back().prefix.size() - 8, 8, " └─ ");
|
out_procs.back().prefix.replace(out_procs.back().prefix.size() - 8, 8, " └─ ");
|
||||||
|
@ -248,7 +264,7 @@ namespace Proc {
|
||||||
}
|
}
|
||||||
|
|
||||||
//* Match filter if defined
|
//* Match filter if defined
|
||||||
if (not filter.empty()
|
if (not tree and not filter.empty()
|
||||||
and pid_str.find(filter) == string::npos
|
and pid_str.find(filter) == string::npos
|
||||||
and cache[new_proc.pid].name.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].cmd.find(filter) == string::npos
|
||||||
|
@ -390,7 +406,7 @@ namespace Proc {
|
||||||
string prefix = " ├─ ";
|
string prefix = " ├─ ";
|
||||||
//? Start recursive iteration over processes with the lowest shared parent pids
|
//? Start recursive iteration over processes with the lowest shared parent pids
|
||||||
for (auto& p : rng::equal_range(procs, procs.at(0).ppid, rng::less{}, &proc_info::ppid)) {
|
for (auto& p : rng::equal_range(procs, procs.at(0).ppid, rng::less{}, &proc_info::ppid)) {
|
||||||
_tree_gen(p, procs, tree_procs, 0, cache.at(p.pid).collapsed, prefix);
|
_tree_gen(p, procs, tree_procs, 0, cache.at(p.pid).collapsed, prefix, filter, false);
|
||||||
}
|
}
|
||||||
procs.swap(tree_procs);
|
procs.swap(tree_procs);
|
||||||
}
|
}
|
||||||
|
@ -399,7 +415,7 @@ namespace Proc {
|
||||||
//* Clear dead processes from cache at a regular interval
|
//* Clear dead processes from cache at a regular interval
|
||||||
if (++counter >= 10000 or ((int)cache.size() > npids + 100)) {
|
if (++counter >= 10000 or ((int)cache.size() > npids + 100)) {
|
||||||
counter = 0;
|
counter = 0;
|
||||||
unordered_flat_map<uint, p_cache> r_cache;
|
unordered_flat_map<size_t, p_cache> r_cache;
|
||||||
r_cache.reserve(procs.size());
|
r_cache.reserve(procs.size());
|
||||||
rng::for_each(procs, [&r_cache](const auto &p){
|
rng::for_each(procs, [&r_cache](const auto &p){
|
||||||
if (cache.contains(p.pid))
|
if (cache.contains(p.pid))
|
||||||
|
|
|
@ -49,7 +49,7 @@ namespace Proc {
|
||||||
|
|
||||||
//* Container for process information
|
//* Container for process information
|
||||||
struct proc_info {
|
struct proc_info {
|
||||||
uint64_t pid;
|
size_t pid;
|
||||||
string name = "", cmd = "";
|
string name = "", cmd = "";
|
||||||
size_t threads = 0;
|
size_t threads = 0;
|
||||||
string user = "";
|
string user = "";
|
||||||
|
|
|
@ -85,8 +85,8 @@ namespace Term {
|
||||||
|
|
||||||
bool initialized = false;
|
bool initialized = false;
|
||||||
bool resized = false;
|
bool resized = false;
|
||||||
uint width = 0;
|
size_t width = 0;
|
||||||
uint height = 0;
|
size_t height = 0;
|
||||||
string fg, bg, current_tty;
|
string fg, bg, current_tty;
|
||||||
|
|
||||||
const string hide_cursor = Fx::e + "?25l";
|
const string hide_cursor = Fx::e + "?25l";
|
||||||
|
@ -252,7 +252,7 @@ namespace Tools {
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sleep_ms(const uint& ms) {
|
void sleep_ms(const size_t& ms) {
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(ms));
|
std::this_thread::sleep_for(std::chrono::milliseconds(ms));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,9 +293,9 @@ namespace Tools {
|
||||||
return (newstr.empty()) ? str : newstr + (string)oldstr;
|
return (newstr.empty()) ? str : newstr + (string)oldstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
string sec_to_dhms(uint sec){
|
string sec_to_dhms(size_t sec){
|
||||||
string out;
|
string out;
|
||||||
uint d, h, m;
|
size_t d, h, m;
|
||||||
d = sec / (3600 * 24);
|
d = sec / (3600 * 24);
|
||||||
sec %= 3600 * 24;
|
sec %= 3600 * 24;
|
||||||
h = sec / 3600;
|
h = sec / 3600;
|
||||||
|
@ -309,9 +309,9 @@ namespace Tools {
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
string floating_humanizer(uint64_t value, bool shorten, uint start, bool bit, bool per_second){
|
string floating_humanizer(uint64_t value, bool shorten, size_t start, bool bit, bool per_second){
|
||||||
string out;
|
string out;
|
||||||
uint mult = (bit) ? 8 : 1;
|
size_t mult = (bit) ? 8 : 1;
|
||||||
static const array<string, 11> Units_bit = {"bit", "Kib", "Mib", "Gib", "Tib", "Pib", "Eib", "Zib", "Yib", "Bib", "GEb"};
|
static const array<string, 11> Units_bit = {"bit", "Kib", "Mib", "Gib", "Tib", "Pib", "Eib", "Zib", "Yib", "Bib", "GEb"};
|
||||||
static const array<string, 11> Units_byte = {"Byte", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB", "BiB", "GEB"};
|
static const array<string, 11> Units_byte = {"Byte", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB", "BiB", "GEB"};
|
||||||
auto& units = (bit) ? Units_bit : Units_byte;
|
auto& units = (bit) ? Units_bit : Units_byte;
|
||||||
|
@ -402,7 +402,7 @@ namespace Logger {
|
||||||
loglevel = v_index(log_levels, level);
|
loglevel = v_index(log_levels, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
void log_write(uint level, string& msg){
|
void log_write(size_t level, string& msg){
|
||||||
if (loglevel < level or logfile.empty()) return;
|
if (loglevel < level or logfile.empty()) return;
|
||||||
atomic_wait_set(busy, true);
|
atomic_wait_set(busy, true);
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
|
|
|
@ -91,8 +91,8 @@ namespace Mv {
|
||||||
namespace Term {
|
namespace Term {
|
||||||
extern bool initialized;
|
extern bool initialized;
|
||||||
extern bool resized;
|
extern bool resized;
|
||||||
extern uint width;
|
extern size_t width;
|
||||||
extern uint height;
|
extern size_t height;
|
||||||
extern string fg, bg, current_tty;
|
extern string fg, bg, current_tty;
|
||||||
|
|
||||||
//* Hide terminal cursor
|
//* Hide terminal cursor
|
||||||
|
@ -198,7 +198,7 @@ namespace Tools {
|
||||||
vector<string> ssplit(const string& str, const char delim = ' ');
|
vector<string> ssplit(const string& str, const char delim = ' ');
|
||||||
|
|
||||||
//* Put current thread to sleep for <ms> milliseconds
|
//* Put current thread to sleep for <ms> milliseconds
|
||||||
void sleep_ms(const uint& ms);
|
void sleep_ms(const size_t& ms);
|
||||||
|
|
||||||
//* Left justify string <str> if <x> is greater than <str> length, limit return size to <x> by default
|
//* Left justify string <str> if <x> is greater than <str> length, limit return size to <x> by default
|
||||||
string ljust(string str, const size_t x, bool utf=false, bool escape=false, bool lim=true);
|
string ljust(string str, const size_t x, bool utf=false, bool escape=false, bool lim=true);
|
||||||
|
@ -210,13 +210,13 @@ namespace Tools {
|
||||||
string trans(const string& str);
|
string trans(const string& str);
|
||||||
|
|
||||||
//* Convert seconds to format "Xd HH:MM:SS" and return string
|
//* Convert seconds to format "Xd HH:MM:SS" and return string
|
||||||
string sec_to_dhms(uint sec);
|
string sec_to_dhms(size_t sec);
|
||||||
|
|
||||||
//* Scales up in steps of 1024 to highest possible unit and returns string with unit suffixed
|
//* Scales up in steps of 1024 to highest possible unit and returns string with unit suffixed
|
||||||
//* bit=True or defaults to bytes
|
//* bit=True or defaults to bytes
|
||||||
//* start=int to set 1024 multiplier starting unit
|
//* start=int to set 1024 multiplier starting unit
|
||||||
//* short=True always returns 0 decimals and shortens unit to 1 character
|
//* short=True always returns 0 decimals and shortens unit to 1 character
|
||||||
string floating_humanizer(uint64_t value, bool shorten=false, uint start=0, bool bit=false, bool per_second=false);
|
string floating_humanizer(uint64_t value, bool shorten=false, size_t start=0, bool bit=false, bool per_second=false);
|
||||||
|
|
||||||
//* Add std::string operator "*" : Repeat string <str> <n> number of times
|
//* Add std::string operator "*" : Repeat string <str> <n> number of times
|
||||||
std::string operator*(string str, size_t n);
|
std::string operator*(string str, size_t n);
|
||||||
|
@ -229,7 +229,7 @@ namespace Tools {
|
||||||
|
|
||||||
//* Waits for <atom> to not be <val> and then sets it to <val> again
|
//* Waits for <atom> to not be <val> and then sets it to <val> again
|
||||||
void atomic_wait_set(std::atomic<bool>& atom, bool val=true);
|
void atomic_wait_set(std::atomic<bool>& atom, bool val=true);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//* Simple logging implementation
|
//* Simple logging implementation
|
||||||
|
@ -238,7 +238,7 @@ namespace Logger {
|
||||||
extern std::filesystem::path logfile;
|
extern std::filesystem::path logfile;
|
||||||
|
|
||||||
void set(string level); //* Set log level, valid arguments: "DISABLED", "ERROR", "WARNING", "INFO" and "DEBUG"
|
void set(string level); //* Set log level, valid arguments: "DISABLED", "ERROR", "WARNING", "INFO" and "DEBUG"
|
||||||
void log_write(uint level, string& msg);
|
void log_write(size_t level, string& msg);
|
||||||
void error(string msg);
|
void error(string msg);
|
||||||
void warning(string msg);
|
void warning(string msg);
|
||||||
void info(string msg);
|
void info(string msg);
|
||||||
|
|
Loading…
Reference in a new issue