btop/btop.cpp

585 lines
18 KiB
C++
Raw Normal View History

2021-05-07 06:32:03 +12:00
/* Copyright 2021 Aristocratos (jakob@qvantnet.com)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
indent = tab
tab-size = 4
*/
2021-05-07 06:32:03 +12:00
#include <string>
#include <array>
2021-05-20 09:21:56 +12:00
#include <list>
2021-05-07 06:32:03 +12:00
#include <vector>
2021-06-10 05:47:49 +12:00
#include <csignal>
2021-05-07 06:32:03 +12:00
#include <thread>
#include <future>
#include <atomic>
2021-05-20 09:21:56 +12:00
#include <numeric>
#include <ranges>
2021-05-22 12:13:56 +12:00
#include <filesystem>
#include <unistd.h>
2021-05-29 12:32:36 +12:00
#include <robin_hood.h>
2021-05-07 06:32:03 +12:00
2021-05-24 08:25:07 +12:00
namespace Global {
const std::vector<std::array<std::string, 2>> Banner_src = {
{"#E62525", "██████╗ ████████╗ ██████╗ ██████╗"},
{"#CD2121", "██╔══██╗╚══██╔══╝██╔═══██╗██╔══██╗ ██╗ ██╗"},
{"#B31D1D", "██████╔╝ ██║ ██║ ██║██████╔╝ ██████╗██████╗"},
{"#9A1919", "██╔══██╗ ██║ ██║ ██║██╔═══╝ ╚═██╔═╝╚═██╔═╝"},
{"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"},
{"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"},
};
2021-06-03 07:33:26 +12:00
const std::string Version = "0.0.20";
2021-06-05 11:41:24 +12:00
int coreCount;
2021-05-24 08:25:07 +12:00
}
2021-05-09 00:56:48 +12:00
#include <btop_tools.h>
#include <btop_config.h>
2021-05-09 06:37:36 +12:00
#include <btop_input.h>
#include <btop_theme.h>
#include <btop_draw.h>
2021-06-03 07:33:26 +12:00
#include <btop_menu.h>
2021-05-09 00:56:48 +12:00
#if defined(__linux__)
2021-06-10 05:47:49 +12:00
#define LINUX
2021-05-11 09:46:41 +12:00
#include <btop_linux.h>
2021-05-09 00:56:48 +12:00
#elif defined(__unix__) || !defined(__APPLE__) && defined(__MACH__)
#include <sys/param.h>
#if defined(BSD)
2021-05-14 07:11:10 +12:00
// #include <btop_bsd.h>
2021-05-20 09:21:56 +12:00
#error BSD support not yet implemented!
2021-05-09 00:56:48 +12:00
#endif
#elif defined(__APPLE__) && defined(__MACH__)
#include <TargetConditionals.h>
#if TARGET_OS_MAC == 1
2021-06-10 05:47:49 +12:00
#define OSX
2021-05-14 07:11:10 +12:00
// #include <btop_osx.h>
2021-05-20 09:21:56 +12:00
#error OSX support not yet implemented!
2021-05-09 00:56:48 +12:00
#endif
2021-05-20 09:21:56 +12:00
#else
2021-05-24 08:25:07 +12:00
#error Platform not supported!
2021-05-09 00:56:48 +12:00
#endif
2021-05-07 06:32:03 +12:00
2021-05-29 12:32:36 +12:00
using std::string, std::vector, std::array, robin_hood::unordered_flat_map, std::atomic, std::endl, std::cout, std::views::iota, std::list, std::accumulate;
2021-05-20 09:21:56 +12:00
using std::flush, std::endl, std::future, std::string_literals::operator""s, std::future_status;
2021-05-22 12:13:56 +12:00
namespace fs = std::filesystem;
using namespace Tools;
2021-05-07 06:32:03 +12:00
2021-05-08 12:38:51 +12:00
2021-05-09 00:56:48 +12:00
namespace Global {
2021-05-15 04:54:37 +12:00
string banner;
2021-06-03 07:33:26 +12:00
size_t banner_width = 0;
2021-05-29 12:32:36 +12:00
fs::path self_path;
bool debuginit = false;
bool debug = false;
uint64_t start_time;
bool quitting = false;
2021-05-09 00:56:48 +12:00
}
2021-05-07 06:32:03 +12:00
2021-05-09 00:56:48 +12:00
//* A simple argument parser
2021-05-08 12:38:51 +12:00
void argumentParser(int argc, char **argv){
string argument;
for(int i = 1; i < argc; i++) {
argument = argv[i];
if (argument == "-v" || argument == "--version") {
2021-05-09 00:56:48 +12:00
cout << "btop version: " << Global::Version << endl;
2021-05-08 12:38:51 +12:00
exit(0);
2021-05-29 12:32:36 +12:00
}
else if (argument == "-h" || argument == "--help") {
2021-05-08 12:38:51 +12:00
cout << "help here" << endl;
exit(0);
2021-05-29 12:32:36 +12:00
}
else if (argument == "--debug") Global::debug = true;
else {
2021-05-08 12:38:51 +12:00
cout << " Unknown argument: " << argument << "\n" <<
" Use -h or --help for help." << endl;
exit(1);
}
}
}
2021-06-10 05:47:49 +12:00
void clean_quit(int sig){
2021-06-03 07:33:26 +12:00
if (Global::quitting) return;
if (Term::initialized) {
Term::restore();
if (!Global::debuginit) cout << Term::normal_screen << Term::show_cursor << flush;
}
if (Global::debug) Logger::debug("Quitting! Runtime: " + sec_to_dhms(time_s() - Global::start_time));
Global::quitting = true;
2021-06-10 05:47:49 +12:00
Config::write();
if (sig != -1) exit(sig);
}
void sleep_now(){
if (Term::initialized) {
Term::restore();
if (!Global::debuginit) cout << Term::normal_screen << Term::show_cursor << flush;
}
std::raise(SIGSTOP);
}
void resume_now(){
Term::init();
if (!Global::debuginit) cout << Term::alt_screen << Term::hide_cursor << flush;
2021-06-03 07:33:26 +12:00
}
void _exit_handler() { clean_quit(-1); }
2021-06-10 05:47:49 +12:00
void _signal_handler(int sig) {
switch (sig) {
case SIGINT:
clean_quit(0);
break;
case SIGTSTP:
sleep_now();
break;
case SIGCONT:
resume_now();
break;
}
}
2021-06-03 07:33:26 +12:00
//? Generate the btop++ banner
void banner_gen() {
2021-06-05 11:41:24 +12:00
size_t z = 0;
2021-06-03 07:33:26 +12:00
string b_color, bg, fg, oc, letter;
2021-05-15 04:54:37 +12:00
bool truecolor = Config::getB("truecolor");
int bg_i;
2021-06-03 07:33:26 +12:00
Global::banner.clear();
Global::banner_width = 0;
2021-05-15 04:54:37 +12:00
for (auto line: Global::Banner_src) {
2021-06-05 11:41:24 +12:00
if (auto w = ulen(line[1]); w > Global::banner_width) Global::banner_width = w;
2021-05-15 04:54:37 +12:00
fg = Theme::hex_to_color(line[0], !truecolor);
bg_i = 120-z*12;
bg = Theme::dec_to_color(bg_i, bg_i, bg_i, !truecolor);
for (size_t i = 0; i < line[1].size(); i += 3) {
2021-05-15 04:54:37 +12:00
if (line[1][i] == ' '){
letter = ' ';
i -= 2;
} else{
letter = line[1].substr(i, 3);
2021-05-07 06:32:03 +12:00
}
2021-05-15 04:54:37 +12:00
b_color = (letter == "") ? fg : bg;
2021-06-03 07:33:26 +12:00
if (b_color != oc) Global::banner += b_color;
Global::banner += letter;
2021-05-15 04:54:37 +12:00
oc = b_color;
2021-05-07 06:32:03 +12:00
}
2021-06-03 07:33:26 +12:00
if (++z < Global::Banner_src.size()) Global::banner += Mv::l(ulen(line[1])) + Mv::d(1);
2021-05-07 06:32:03 +12:00
}
2021-06-03 07:33:26 +12:00
Global::banner += Mv::r(18 - Global::Version.size()) + Fx::i + Theme::dec_to_color(0,0,0, !truecolor, "bg") +
Theme::dec_to_color(150, 150, 150, !truecolor) + "v" + Global::Version + Fx::ui;
2021-05-15 04:54:37 +12:00
}
2021-05-07 06:32:03 +12:00
2021-05-10 08:25:41 +12:00
//* Threading test function
2021-06-03 07:33:26 +12:00
// 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);
// }
2021-05-10 08:25:41 +12:00
2021-05-09 00:56:48 +12:00
2021-05-07 06:32:03 +12:00
//? --------------------------------------------- Main starts here! ---------------------------------------------------
int main(int argc, char **argv){
//? Init
2021-05-29 12:32:36 +12:00
Global::start_time = time_s();
2021-05-08 12:38:51 +12:00
cout.setf(std::ios::boolalpha);
2021-05-07 06:32:03 +12:00
if (argc > 1) argumentParser(argc, argv);
2021-05-29 12:32:36 +12:00
std::atexit(_exit_handler);
2021-06-10 05:47:49 +12:00
std::at_quick_exit(_exit_handler);
std::signal(SIGINT, _signal_handler);
std::signal(SIGTSTP, _signal_handler);
std::signal(SIGCONT, _signal_handler);
2021-05-29 12:32:36 +12:00
2021-06-06 11:41:36 +12:00
//? Linux init
2021-05-20 09:21:56 +12:00
#if defined(LINUX)
2021-06-05 11:41:24 +12:00
Global::coreCount = sysconf(_SC_NPROCESSORS_ONLN);
if (Global::coreCount < 1) Global::coreCount = 1;
2021-06-10 05:47:49 +12:00
2021-05-29 12:32:36 +12:00
{
std::error_code ec;
Global::self_path = fs::read_symlink("/proc/self/exe", ec).remove_filename();
}
2021-05-20 09:21:56 +12:00
#endif
2021-05-14 07:11:10 +12:00
//? Setup paths for config, log and themes
for (auto env : {"XDG_CONFIG_HOME", "HOME"}) {
if (getenv(env) != NULL && access(getenv(env), W_OK) != -1) {
2021-05-29 12:32:36 +12:00
Config::conf_dir = fs::path(getenv(env)) / (((string)env == "HOME") ? ".config/btop" : "btop");
break;
}
}
2021-05-29 12:32:36 +12:00
if (!Config::conf_dir.empty()) {
2021-06-05 11:41:24 +12:00
if (std::error_code ec; !fs::is_directory(Config::conf_dir) && !fs::create_directories(Config::conf_dir, ec)) {
cout << "WARNING: Could not create or access btop config directory. Logging and config saving disabled." << endl;
2021-05-29 12:32:36 +12:00
cout << "Make sure your $HOME environment variable is correctly set to fix this." << endl;
}
else {
2021-05-29 12:32:36 +12:00
Config::conf_file = Config::conf_dir / "btop.conf";
Logger::logfile = Config::conf_dir / "btop.log";
Theme::user_theme_dir = Config::conf_dir / "themes";
if (!fs::exists(Theme::user_theme_dir) && !fs::create_directory(Theme::user_theme_dir, ec)) Theme::user_theme_dir.clear();
}
}
2021-06-05 11:41:24 +12:00
if (std::error_code ec; !Global::self_path.empty()) {
2021-05-29 12:32:36 +12:00
Theme::theme_dir = fs::canonical(Global::self_path / "../share/btop/themes", ec);
if (ec || access(Theme::theme_dir.c_str(), R_OK) == -1) Theme::theme_dir.clear();
}
if (Theme::theme_dir.empty()) {
for (auto theme_path : {"/usr/local/share/btop/themes", "/usr/share/btop/themes"}) {
if (fs::exists(fs::path(theme_path)) && access(theme_path, R_OK) != -1) {
Theme::theme_dir = fs::path(theme_path);
break;
}
}
}
2021-06-13 04:49:27 +12:00
//? Read config file if present
{ vector<string> load_errors;
Config::load(Config::conf_file, load_errors);
if (Global::debug) Logger::loglevel = 4;
else Logger::loglevel = v_index(Logger::log_levels, Config::getS("log_level"));
if (Logger::loglevel == 4) Logger::debug("Starting with logger set to debug.");
if (!load_errors.empty()) {
for (auto& err_str : load_errors) Logger::error(err_str);
}
}
2021-05-24 08:25:07 +12:00
if (!string(getenv("LANG")).ends_with("UTF-8") && !string(getenv("LANG")).ends_with("utf-8")) {
string err_msg = "No UTF-8 locale was detected! Symbols might not look as intended.\n"
"Make sure your $LANG evironment variable is set and with a UTF-8 locale.";
2021-05-24 08:25:07 +12:00
Logger::warning(err_msg);
cout << "WARNING: " << err_msg << endl;
}
2021-05-09 10:18:51 +12:00
//? Initialize terminal and set options
2021-05-15 04:54:37 +12:00
if (!Term::init()) {
2021-06-06 11:41:36 +12:00
string err_msg = "No tty detected!\nbtop++ needs an interactive shell to run.";
Logger::error(err_msg);
2021-05-24 08:25:07 +12:00
cout << "ERROR: " << err_msg << endl;
2021-05-29 12:32:36 +12:00
clean_quit(1);
2021-05-07 06:32:03 +12:00
}
2021-06-05 11:41:24 +12:00
#if defined(LINUX)
//? Linux init
Proc::init();
#endif
2021-06-13 04:49:27 +12:00
2021-06-06 11:41:36 +12:00
// Config::set("truecolor", false);
2021-05-09 10:18:51 +12:00
auto thts = time_ms();
2021-05-09 10:18:51 +12:00
//? Generate the theme
2021-05-22 12:13:56 +12:00
Theme::set(Theme::Default_theme);
2021-05-09 10:18:51 +12:00
//? Create the btop++ banner
2021-06-03 07:33:26 +12:00
banner_gen();
2021-05-09 10:18:51 +12:00
2021-05-08 12:38:51 +12:00
2021-05-09 10:18:51 +12:00
//* ------------------------------------------------ TESTING ------------------------------------------------------
2021-06-10 05:47:49 +12:00
Global::debuginit = true;
2021-05-24 08:25:07 +12:00
2021-05-15 04:54:37 +12:00
// cout << Theme("main_bg") << Term::clear << flush;
2021-06-03 07:33:26 +12:00
// bool thread_test = false;
2021-05-07 06:32:03 +12:00
2021-05-29 12:32:36 +12:00
if (!Global::debuginit) cout << Term::alt_screen << Term::hide_cursor << flush;
2021-05-10 08:25:41 +12:00
2021-05-15 04:54:37 +12:00
cout << Theme::c("main_fg") << Theme::c("main_bg") << Term::clear << endl;
2021-05-07 06:32:03 +12:00
2021-05-15 04:54:37 +12:00
cout << Mv::r(Term::width / 2 - Global::banner_width / 2) << Global::banner << endl;
// cout << string(Term::width - 1, '-') << endl;
2021-05-20 09:21:56 +12:00
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;
2021-05-20 09:21:56 +12:00
for (int i : iota(0, (int)blen)){
ill = (i <= (int)blen / 2) ? i : ill - 1;
2021-05-28 08:29:36 +12:00
cout << Theme::g("used")[ill] << Symbols::h_line;
}
cout << Fx::reset << endl;
2021-05-08 12:38:51 +12:00
2021-05-07 06:32:03 +12:00
//* Test theme
if (false) {
cout << "Theme generation took " << time_ms() - thts << "ms" << endl;
cout << "Colors:" << endl;
uint i = 0;
for(auto& item : Theme::colors) {
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] << ;
if (++i == 4) {
i = 0;
cout << endl;
}
2021-05-08 12:38:51 +12:00
}
2021-05-09 10:18:51 +12:00
cout << Fx::reset << endl;
cout << "Gradients:";
for (auto& [name, cvec] : Theme::gradients) {
cout << endl << rjust(name + ":", 10);
for (auto& color : cvec) {
cout << color << "";
}
cout << Fx::reset << endl;
}
exit(0);
2021-05-08 12:38:51 +12:00
}
2021-06-06 11:41:36 +12:00
2021-05-29 12:32:36 +12:00
if (false) {
2021-05-28 08:29:36 +12:00
Draw::Meter kmeter;
kmeter(Term::width - 2, "cpu", false);
cout << kmeter(25) << endl;
cout << kmeter(0) << endl;
cout << kmeter(50) << endl;
cout << kmeter(100) << endl;
cout << kmeter(50) << endl;
exit(0);
}
2021-05-29 12:32:36 +12:00
if (false) {
cout << fs::absolute(fs::current_path() / "..") << endl;
cout << Global::self_path << endl;
cout << Theme::theme_dir << endl;
cout << Config::conf_dir << endl;
exit(0);
}
2021-06-06 11:41:36 +12:00
if (false) {
2021-05-30 12:15:09 +12:00
vector<long long> mydata;
for (long long i = 0; i <= 100; i++) mydata.push_back(i);
for (long long i = 100; i >= 0; i--) mydata.push_back(i);
2021-06-01 07:47:41 +12:00
// mydata.push_back(0);
// mydata.push_back(0);
2021-06-03 07:33:26 +12:00
mydata.push_back(50);
2021-05-30 12:15:09 +12:00
2021-05-31 03:01:57 +12:00
// for (long long i = 0; i <= 100; i++) mydata.push_back(i);
// for (long long i = 100; i >= 0; i--) mydata.push_back(i);
2021-05-30 12:15:09 +12:00
2021-05-31 03:01:57 +12:00
Draw::Graph kgraph {};
2021-06-03 07:33:26 +12:00
cout << Draw::createBox({.x = 5, .y = 10, .width = Term::width - 10, .height = 12, .line_color = Theme::c("proc_box"), .title = "graph", .fill = false, .num = 7}) << Mv::save << flush;
// Draw::Meter kmeter {};
// Draw::Graph kgraph2 {};
// Draw::Graph kgraph3 {};
2021-05-30 12:15:09 +12:00
2021-05-31 03:01:57 +12:00
auto kts = time_micros();
2021-06-03 07:33:26 +12:00
kgraph(Term::width - 12, 10, "cpu", mydata, false, false);
// kmeter(Term::width - 12, "process");
2021-06-01 07:47:41 +12:00
// cout << Mv::save << kgraph(mydata) << "\n\nInit took " << time_micros() - kts << " μs. " << endl;
// exit(0);
2021-06-03 07:33:26 +12:00
// kgraph2(Term::width, 10, "process", mydata, true, false);
// kgraph3(Term::width, 1, "process", mydata, false, false);
2021-05-31 03:01:57 +12:00
// cout << kgraph() << endl;
// cout << kgraph2() << endl;
// exit(0);
2021-06-03 07:33:26 +12:00
cout << Mv::restore << kgraph(mydata, true) << "\n\n" << Mv::d(1) << "Init took " << time_micros() - kts << " μs. " << endl;
// cout << Mv::save << kgraph(mydata, true) << "\n" << kgraph2(mydata, true) << "\n" << kgraph3(mydata, true) << "\n" << kmeter(mydata.back()) << "\n\nInit took " << time_micros() - kts << " μs. " << endl;
2021-05-31 03:01:57 +12:00
// sleep_ms(1000);
// mydata.push_back(50);
// cout << Mv::restore << kgraph(mydata) << "\n" << kgraph2(mydata) << "\n\nInit took " << time_micros() - kts << " μs. " << endl;
// exit(0);
2021-05-30 12:15:09 +12:00
2021-06-03 07:33:26 +12:00
// long long y = 0;
// bool flip = false;
2021-05-30 12:15:09 +12:00
list<uint64_t> ktavg;
2021-05-31 03:01:57 +12:00
while (true) {
2021-06-03 07:33:26 +12:00
mydata.back() = std::rand() % 101;
// mydata.back() = y;
2021-05-30 12:15:09 +12:00
kts = time_micros();
2021-05-31 03:01:57 +12:00
// cout << Mv::restore << " "s * Term::width << "\n" << " "s * Term::width << endl;
2021-06-03 07:33:26 +12:00
cout << Mv::restore << kgraph(mydata) << endl;
// cout << Mv::restore << kgraph(mydata) << "\n" << kgraph2(mydata) << "\n" << " "s * Term::width << Mv::l(Term::width) << kgraph3(mydata) << "\n" << kmeter(mydata.back()) << endl;
2021-05-30 12:15:09 +12:00
ktavg.push_front(time_micros() - kts);
if (ktavg.size() > 100) ktavg.pop_back();
2021-06-03 07:33:26 +12:00
cout << Mv::d(1) << "Time: " << ktavg.front() << " μs. Avg: " << accumulate(ktavg.begin(), ktavg.end(), 0) / ktavg.size() << " μs. " << flush;
// if (flip) y--;
// else y++;
// if (y == 100 || y == 0) flip = !flip;
2021-05-31 03:01:57 +12:00
if (Input::poll()) {
if (Input::get() == "space") Input::wait(true);
else break;
}
sleep_ms(100);
2021-05-30 12:15:09 +12:00
}
Input::get();
exit(0);
}
2021-05-28 08:29:36 +12:00
2021-06-13 04:49:27 +12:00
if (false) {
cout << Config::getS("log_level") << endl;
vector<string> vv = {"hej", "vad", "du"};
vector<int> vy;
cout << v_contains(vv, "vad"s) << endl;
cout << v_index(vv, "hej"s) << endl;
cout << v_index(vv, "du"s) << endl;
cout << v_index(vv, "kodkod"s) << endl;
cout << v_index(vy, 4) << endl;
exit(0);
}
2021-06-03 07:33:26 +12:00
// if (thread_test){
2021-05-10 08:25:41 +12:00
2021-06-03 07:33:26 +12:00
// unordered_flat_map<int, future<string>> runners;
// unordered_flat_map<int, string> outputs;
2021-05-10 08:25:41 +12:00
2021-06-03 07:33:26 +12:00
// for (int i : iota(0, 10)){
// runners[i] = async(my_worker, i);
// }
// // uint i = 0;
// while (outputs.size() < 10){
2021-05-10 08:25:41 +12:00
2021-06-03 07:33:26 +12:00
// for (int i : iota(0, 10)){
// if (runners[i].valid() && runners[i].wait_for(std::chrono::milliseconds(10)) == future_status::ready) {
// outputs[i] = runners[i].get();
// cout << "Thread " << i << " : " << outputs[i] << endl;
// }
// }
// // if (++i >= 10) i = 0;
// if (outputs.size() >= 8) Global::stop_all.store(true);
// }
// }
2021-05-07 06:32:03 +12:00
cout << "Up for " << sec_to_dhms(round(system_uptime())) << endl;
2021-05-07 06:32:03 +12:00
2021-05-10 08:25:41 +12:00
2021-05-22 12:13:56 +12:00
//*------>>>>>> Proc testing
2021-05-11 09:46:41 +12:00
2021-05-10 08:25:41 +12:00
auto timestamp = time_ms();
2021-05-11 09:46:41 +12:00
2021-05-10 08:25:41 +12:00
2021-05-14 07:11:10 +12:00
uint lc;
string ostring;
2021-05-22 12:13:56 +12:00
uint64_t tsl, timestamp2, rcount = 0;
2021-05-29 12:32:36 +12:00
list<uint64_t> avgtimes = {0};
2021-06-05 11:41:24 +12:00
uint timer = 2000;
2021-05-15 04:54:37 +12:00
bool filtering = false;
bool reversing = false;
int sortint = Proc::sort_map["cpu lazy"];
vector<string> greyscale;
2021-05-15 04:54:37 +12:00
string filter;
string filter_cur;
string key;
int xc;
for (uint i : iota(0, (int)Term::height - 19)){
xc = 230 - i * 150 / (Term::height - 20);
greyscale.push_back(Theme::dec_to_color(xc, xc, xc));
}
2021-06-10 05:47:49 +12:00
string pbox = Draw::createBox({.x = 1, .y = 10, .width = Term::width, .height = Term::height - 16, .line_color = Theme::c("proc_box"), .title = "testbox", .title2 = "below", .fill = false, .num = 7});
pbox += Mv::r(1) + rjust("Pid:", 8) + " " + ljust("Program:", 16) + " " + ljust("Command:", Term::width - 70) + " Threads: " +
2021-06-05 11:41:24 +12:00
ljust("User:", 10) + " " + rjust("MemB", 5) + " " + rjust("Cpu%", 14) + "\n" + Mv::save;
2021-05-11 09:46:41 +12:00
2021-05-15 04:54:37 +12:00
while (key != "q") {
2021-05-28 08:29:36 +12:00
timestamp = time_micros();
tsl = time_ms() + timer;
2021-06-05 11:41:24 +12:00
auto plist = Proc::collect(Proc::sort_array[sortint], reversing, filter, Config::getB("proc_per_core"));
2021-05-28 08:29:36 +12:00
timestamp2 = time_micros();
2021-05-15 04:54:37 +12:00
timestamp = timestamp2 - timestamp;
ostring.clear();
lc = 0;
2021-06-05 11:41:24 +12:00
ostring = Mv::u(2) + Mv::l(Term::width) + Mv::r(12)
+ trans("Filter: " + filter + (filtering ? Fx::bl + "" + Fx::reset : "")) + Mv::l(Term::width)
+ trans(rjust("Per core: " + (Config::getB("proc_per_core") ? "On "s : "Off"s) + " Sorting: "
+ string(Proc::sort_array[sortint]), Term::width - 3))
+ Mv::restore;
2021-05-15 04:54:37 +12:00
for (auto& p : plist){
2021-06-05 11:41:24 +12:00
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 || p.cpu_p >= 100 ? rjust(to_string(p.cpu_p), 3) + " " : rjust(to_string(p.cpu_p), 4))
+ "\n";
if (lc++ > Term::height - 21) break;
2021-05-15 04:54:37 +12:00
}
2021-05-28 08:29:36 +12:00
while (lc++ < Term::height - 19) ostring += Mv::r(1) + string(Term::width - 2, ' ') + "\n";
2021-05-29 12:32:36 +12:00
if (rcount > 0) avgtimes.push_front(timestamp);
if (avgtimes.size() > 10) avgtimes.pop_back();
cout << pbox << ostring << Fx::reset << "\n" << endl;
2021-05-28 08:29:36 +12:00
cout << Mv::to(Term::height - 4, 1) << "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 << ". Run count: " <<
2021-05-27 02:23:29 +12:00
++rcount << ". Time: " << strf_time("%X ") << endl;
2021-05-15 04:54:37 +12:00
while (time_ms() < tsl) {
if (Input::poll(tsl - time_ms())) key = Input::get();
else { key.clear() ; continue; }
if (filtering) {
if (key == "enter") filtering = false;
else if (key == "backspace") {if (!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; }
2021-05-15 04:54:37 +12:00
break;
}
else if (key == "q") break;
else if (key == "left") { if (--sortint < 0) sortint = (int)Proc::sort_array.size() - 1; }
else if (key == "right") { if (++sortint > (int)Proc::sort_array.size() - 1) sortint = 0; }
2021-05-15 04:54:37 +12:00
else if (key == "f") filtering = true;
else if (key == "r") reversing = !reversing;
2021-06-05 11:41:24 +12:00
else if (key == "c") Config::flip("proc_per_core");
2021-05-15 04:54:37 +12:00
else if (key == "delete") filter.clear();
else continue;
break;
}
}
2021-05-11 09:46:41 +12:00
// cout << "Found " << plist.size() << " pids\n" << endl;
2021-05-10 08:25:41 +12:00
2021-05-22 12:13:56 +12:00
//*-----<<<<<
2021-05-10 08:25:41 +12:00
2021-05-07 06:32:03 +12:00
return 0;
}