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
*/
# include <string>
2021-05-19 08:11:34 +12:00
# 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>
2021-05-17 08:58:16 +12:00
# 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-06-20 00:57:27 +12:00
# include <cmath>
2021-06-20 08:48:31 +12:00
# include <iostream>
2021-07-04 11:18:48 +12:00
# include <exception>
2021-05-24 08:25:07 +12:00
2021-06-20 10:49:13 +12:00
# include <btop_shared.hpp>
2021-06-20 08:48:31 +12:00
# include <btop_tools.hpp>
# include <btop_config.hpp>
# include <btop_input.hpp>
# include <btop_theme.hpp>
# include <btop_draw.hpp>
# include <btop_menu.hpp>
2021-05-09 00:56:48 +12:00
# if defined(__linux__)
2021-06-10 05:47:49 +12:00
# define LINUX
2021-06-22 08:52:55 +12:00
# elif defined(__unix__) or not defined(__APPLE__) and defined(__MACH__)
2021-05-09 00:56:48 +12:00
# include <sys/param.h>
# if defined(BSD)
2021-05-20 09:21:56 +12:00
# error BSD support not yet implemented!
2021-05-09 00:56:48 +12:00
# endif
2021-06-22 08:52:55 +12:00
# elif defined(__APPLE__) and defined(__MACH__)
2021-05-09 00:56:48 +12:00
# include <TargetConditionals.h>
# if TARGET_OS_MAC == 1
2021-06-10 05:47:49 +12:00
# define OSX
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-06-20 00:57:27 +12:00
namespace Global {
const std : : vector < std : : array < std : : string , 2 > > Banner_src = {
{ " #E62525 " , " ██████╗ ████████╗ ██████╗ ██████╗ " } ,
{ " #CD2121 " , " ██╔══██╗╚══██╔══╝██╔═══██╗██╔══██╗ ██╗ ██╗ " } ,
{ " #B31D1D " , " ██████╔╝ ██║ ██║ ██║██████╔╝ ██████╗██████╗ " } ,
{ " #9A1919 " , " ██╔══██╗ ██║ ██║ ██║██╔═══╝ ╚═██╔═╝╚═██╔═╝ " } ,
{ " #801414 " , " ██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝ " } ,
{ " #000000 " , " ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ " } ,
} ;
2021-06-26 09:58:19 +12:00
const std : : string Version = " 0.0.30 " ;
2021-06-20 00:57:27 +12:00
int coreCount ;
}
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-06-20 00:57:27 +12:00
using std : : flush , std : : endl , std : : future , std : : string_literals : : operator " " s , std : : future_status , std : : to_string , std : : round ;
2021-05-22 12:13:56 +12:00
namespace fs = std : : filesystem ;
2021-06-20 00:57:27 +12:00
namespace rng = std : : ranges ;
2021-05-17 08:58:16 +12:00
using namespace Tools ;
2021-05-07 06:32:03 +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-23 11:59:13 +12:00
2021-05-29 12:32:36 +12:00
fs : : path self_path ;
bool debuginit = false ;
bool debug = false ;
uint64_t start_time ;
2021-07-04 11:18:48 +12:00
atomic < bool > quitting ( false ) ;
2021-06-20 00:57:27 +12:00
bool arg_tty = false ;
2021-06-22 08:52:55 +12:00
bool arg_low_color = 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 ] ;
2021-06-22 08:52:55 +12:00
if ( argument = = " -v " or 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
}
2021-06-22 08:52:55 +12:00
else if ( argument = = " -h " or argument = = " --help " ) {
2021-06-20 00:57:27 +12:00
cout < < " usage: btop [-h] [-v] [-/+t] [--debug] \n \n "
< < " optional arguments: \n "
2021-06-22 08:52:55 +12:00
< < " -h, --help show this help message and exit \n "
< < " -v, --version show version info and exit \n "
< < " -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 "
< < " --debug start with loglevel set to DEBUG, overriding value set in config \n "
2021-06-20 00:57:27 +12:00
< < endl ;
2021-05-08 12:38:51 +12:00
exit ( 0 ) ;
2021-05-29 12:32:36 +12:00
}
2021-06-20 00:57:27 +12:00
else if ( argument = = " --debug " )
Global : : debug = true ;
2021-06-22 08:52:55 +12:00
else if ( argument = = " -t " or argument = = " --tty_on " ) {
2021-06-20 00:57:27 +12:00
Config : : set ( " tty_mode " , true ) ;
Global : : arg_tty = true ;
}
2021-06-22 08:52:55 +12:00
else if ( argument = = " +t " or argument = = " --tty_off " ) {
2021-06-20 00:57:27 +12:00
Config : : set ( " tty_mode " , false ) ;
Global : : arg_tty = true ;
}
2021-06-22 08:52:55 +12:00
else if ( argument = = " -lc " or argument = = " --low-color " ) {
Global : : arg_low_color = true ;
}
2021-05-29 12:32:36 +12:00
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 ( ) ;
2021-06-22 08:52:55 +12:00
if ( not Global : : debuginit ) cout < < Term : : normal_screen < < Term : : show_cursor < < flush ;
2021-06-03 07:33:26 +12:00
}
Global : : quitting = true ;
2021-06-10 05:47:49 +12:00
Config : : write ( ) ;
2021-06-14 09:12:11 +12:00
Logger : : info ( " Quitting! Runtime: " + sec_to_dhms ( time_s ( ) - Global : : start_time ) ) ;
2021-06-10 05:47:49 +12:00
if ( sig ! = - 1 ) exit ( sig ) ;
}
void sleep_now ( ) {
if ( Term : : initialized ) {
Term : : restore ( ) ;
2021-06-22 08:52:55 +12:00
if ( not Global : : debuginit ) cout < < Term : : normal_screen < < Term : : show_cursor < < flush ;
2021-06-10 05:47:49 +12:00
}
std : : raise ( SIGSTOP ) ;
}
void resume_now ( ) {
Term : : init ( ) ;
2021-06-22 08:52:55 +12:00
if ( not 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-06-22 08:52:55 +12:00
auto & lowcolor = Config : : getB ( " lowcolor " ) ;
2021-05-15 04:54:37 +12:00
int bg_i ;
2021-06-03 07:33:26 +12:00
Global : : banner . clear ( ) ;
Global : : banner_width = 0 ;
2021-06-20 00:57:27 +12:00
auto tty_mode = ( Config : : getB ( " tty_mode " ) ) ;
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-06-22 08:52:55 +12:00
if ( tty_mode ) {
fg = ( z > 2 ) ? " \x1b [31m " : " \x1b [91m " ;
bg = ( z > 2 ) ? " \x1b [90m " : " \x1b [37m " ;
}
else {
fg = Theme : : hex_to_color ( line [ 0 ] , lowcolor ) ;
bg_i = 120 - z * 12 ;
bg = Theme : : dec_to_color ( bg_i , bg_i , bg_i , lowcolor ) ;
}
2021-05-19 08:11:34 +12:00
for ( size_t i = 0 ; i < line [ 1 ] . size ( ) ; i + = 3 ) {
2021-06-20 00:57:27 +12:00
if ( line [ 1 ] [ i ] = = ' ' ) {
2021-05-15 04:54:37 +12:00
letter = ' ' ;
i - = 2 ;
2021-05-07 06:32:03 +12:00
}
2021-06-20 00:57:27 +12:00
else
letter = line [ 1 ] . substr ( i , 3 ) ;
2021-06-22 08:52:55 +12:00
// if (tty_mode and letter != "█" and letter != " ") letter = "░";
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-22 08:52:55 +12:00
Global : : banner + = Mv : : r ( 18 - Global : : Version . size ( ) )
+ ( tty_mode ? " \x1b [0;40;37m " : Theme : : dec_to_color ( 0 , 0 , 0 , lowcolor , " bg " ) + Theme : : dec_to_color ( 150 , 150 , 150 , lowcolor ) )
+ Fx : : i + " v " + Global : : Version + Fx : : ui ;
2021-05-15 04:54:37 +12:00
}
2021-05-07 06:32:03 +12:00
2021-07-05 08:02:31 +12:00
namespace Runner {
atomic < bool > active ( false ) ;
}
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-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
2021-05-23 11:59:13 +12:00
//? Setup paths for config, log and themes
for ( auto env : { " XDG_CONFIG_HOME " , " HOME " } ) {
2021-06-22 08:52:55 +12:00
if ( getenv ( env ) ! = NULL and 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 " ) ;
2021-05-23 11:59:13 +12:00
break ;
}
}
2021-06-22 08:52:55 +12:00
if ( not Config : : conf_dir . empty ( ) ) {
if ( std : : error_code ec ; not fs : : is_directory ( Config : : conf_dir ) and not fs : : create_directories ( Config : : conf_dir , ec ) ) {
2021-05-23 11:59:13 +12:00
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 ;
2021-05-23 11:59:13 +12:00
}
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 " ;
2021-06-22 08:52:55 +12:00
if ( not fs : : exists ( Theme : : user_theme_dir ) and not fs : : create_directory ( Theme : : user_theme_dir , ec ) ) Theme : : user_theme_dir . clear ( ) ;
2021-05-23 11:59:13 +12:00
}
}
2021-06-22 08:52:55 +12:00
if ( std : : error_code ec ; not Global : : self_path . empty ( ) ) {
2021-05-29 12:32:36 +12:00
Theme : : theme_dir = fs : : canonical ( Global : : self_path / " ../share/btop/themes " , ec ) ;
2021-07-04 11:18:48 +12:00
if ( ec or not fs : : is_directory ( Theme : : theme_dir ) or access ( Theme : : theme_dir . c_str ( ) , R_OK ) = = - 1 ) Theme : : theme_dir . clear ( ) ;
2021-05-29 12:32:36 +12:00
}
if ( Theme : : theme_dir . empty ( ) ) {
for ( auto theme_path : { " /usr/local/share/btop/themes " , " /usr/share/btop/themes " } ) {
2021-07-04 11:18:48 +12:00
if ( fs : : is_directory ( fs : : path ( theme_path ) ) and access ( theme_path , R_OK ) ! = - 1 ) {
2021-05-29 12:32:36 +12:00
Theme : : theme_dir = fs : : path ( theme_path ) ;
break ;
}
2021-05-23 11:59:13 +12:00
}
}
2021-06-14 09:12:11 +12:00
//? Config init
2021-06-13 04:49:27 +12:00
{ vector < string > load_errors ;
Config : : load ( Config : : conf_file , load_errors ) ;
2021-06-22 08:52:55 +12:00
Config : : set ( " lowcolor " , ( Global : : arg_low_color ? true : not Config : : getB ( " truecolor " ) ) ) ;
2021-06-20 00:57:27 +12:00
if ( Global : : debug ) Logger : : set ( " DEBUG " ) ;
else Logger : : set ( Config : : getS ( " log_level " ) ) ;
2021-06-13 04:49:27 +12:00
2021-06-22 08:52:55 +12:00
Logger : : info ( " Logger set to " + Config : : getS ( " log_level " ) ) ;
2021-06-13 04:49:27 +12:00
2021-06-14 09:12:11 +12:00
for ( auto & err_str : load_errors ) Logger : : warning ( err_str ) ;
2021-06-13 04:49:27 +12:00
}
2021-05-24 08:25:07 +12:00
2021-06-22 08:52:55 +12:00
if ( not string ( getenv ( " LANG " ) ) . ends_with ( " UTF-8 " ) and not string ( getenv ( " LANG " ) ) . ends_with ( " utf-8 " ) ) {
2021-06-12 10:35:15 +12:00
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-23 11:59:13 +12:00
2021-05-09 10:18:51 +12:00
//? Initialize terminal and set options
2021-06-22 08:52:55 +12:00
if ( not Term : : init ( ) ) {
2021-06-06 11:41:36 +12:00
string err_msg = " No tty detected! \n btop++ 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-22 08:52:55 +12:00
Logger : : info ( " Running on " + Term : : current_tty ) ;
if ( not Global : : arg_tty and Config : : getB ( " force_tty " ) ) {
2021-06-20 00:57:27 +12:00
Config : : set ( " tty_mode " , true ) ;
Logger : : info ( " Forcing tty mode: setting 16 color mode and using tty friendly graph symbols " ) ;
}
2021-06-22 08:52:55 +12:00
else if ( not Global : : arg_tty and Term : : current_tty . starts_with ( " /dev/tty " ) ) {
2021-06-20 00:57:27 +12:00
Config : : set ( " tty_mode " , true ) ;
Logger : : info ( " Real tty detected, setting 16 color mode and using tty friendly graph symbols " ) ;
}
2021-06-26 09:58:19 +12:00
//? Platform init and error check
Shared : : init ( ) ;
2021-06-05 11:41:24 +12:00
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
2021-06-26 09:58:19 +12:00
auto thts = time_micros ( ) ;
2021-05-17 08:58:16 +12:00
2021-06-26 09:58:19 +12:00
//? Update theme list and generate the theme
Theme : : updateThemes ( ) ;
Theme : : setTheme ( ) ;
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-07-05 08:02:31 +12:00
Draw : : calcSizes ( ) ;
2021-07-06 08:18:58 +12:00
cout < < Cpu : : box < < Mem : : box < < Net : : box < < Proc : : box < < flush ;
2021-07-05 08:02:31 +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-07-05 08:02:31 +12:00
if ( not Global : : debuginit ) cout < < Term : : alt_screen < < Term : : hide_cursor < < Term : : clear < < endl ;
2021-05-10 08:25:41 +12:00
2021-07-05 08:02:31 +12:00
// cout << Theme::c("main_fg") << Theme::c("main_bg") << Term::clear << endl;
2021-05-07 06:32:03 +12:00
2021-07-05 08:02:31 +12:00
// cout << Mv::r(Term::width / 2 - Global::banner_width / 2) << Global::banner << endl;
// // cout << string(Term::width - 1, '-') << endl;
// 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;
// for (int i : iota(0, (int)blen)){
// ill = (i <= (int)blen / 2) ? i : ill - 1;
// cout << Theme::g("used")[ill] << Symbols::h_line;
// }
// cout << Fx::reset << endl;
if ( false ) {
Draw : : calcSizes ( ) ;
cout < < Cpu : : box < < Mem : : box < < Net : : box < < Proc : : box < < flush ;
Input : : wait ( ) ;
exit ( 0 ) ;
2021-05-17 08:58:16 +12:00
}
2021-05-08 12:38:51 +12:00
2021-05-07 06:32:03 +12:00
//* Test theme
2021-05-19 08:11:34 +12:00
if ( false ) {
2021-05-17 08:58:16 +12:00
2021-06-26 09:58:19 +12:00
// cout << Theme::theme_dir << ", " << Theme::user_theme_dir << endl;
// for (auto& s : Theme::themes) {
// cout << s << endl;
// }
2021-05-17 08:58:16 +12:00
2021-06-26 09:58:19 +12:00
// exit(0);
string key ;
bool no_redraw = false ;
auto theme_index = v_index ( Theme : : themes , Config : : getS ( " color_theme " ) ) ;
while ( key ! = " q " ) {
key . clear ( ) ;
if ( not no_redraw ) {
cout < < " \n Theme generation of " < < fs : : path ( Config : : getS ( " color_theme " ) ) . filename ( ) . replace_extension ( " " ) < < " took " < < time_micros ( ) - thts < < " μs " < < endl ;
cout < < " Colors: " < < endl ;
2021-06-28 08:13:32 +12:00
size_t i = 0 ;
2021-06-26 09:58:19 +12:00
for ( auto & item : Theme : : test_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 ;
}
}
cout < < Fx : : reset < < endl ;
cout < < " Gradients: " ;
for ( auto & [ name , cvec ] : Theme : : test_gradients ( ) ) {
cout < < endl < < rjust ( name + " : " , 10 ) ;
for ( auto & color : cvec ) {
cout < < color < < " ■ " ;
}
cout < < Fx : : reset < < endl ;
}
}
no_redraw = true ;
key = Input : : wait ( ) ;
if ( key . empty ( ) ) continue ;
thts = time_micros ( ) ;
if ( key = = " right " ) {
if ( theme_index = = Theme : : themes . size ( ) - 1 ) theme_index = 0 ;
else theme_index + + ;
}
else if ( key = = " left " ) {
if ( theme_index = = 0 ) theme_index = Theme : : themes . size ( ) - 1 ;
else theme_index - - ;
2021-05-17 08:58:16 +12:00
}
2021-06-26 09:58:19 +12:00
else continue ;
no_redraw = false ;
Config : : set ( " color_theme " , Theme : : themes . at ( theme_index ) ) ;
Theme : : setTheme ( ) ;
2021-05-17 08:58:16 +12:00
}
exit ( 0 ) ;
2021-05-08 12:38:51 +12:00
}
2021-06-23 05:19:14 +12:00
if ( false ) {
string first = " Test number 1 OF 45, or? " ;
cout < < str_to_lower ( first ) < < endl ;
cout < < str_to_upper ( first ) < < endl ;
exit ( 0 ) ;
}
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-23 05:19:14 +12:00
if ( false ) {
2021-05-30 12:15:09 +12:00
2021-07-04 11:18:48 +12:00
deque < long long > mydata ;
2021-05-30 12:15:09 +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-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-20 00:57:27 +12:00
Draw : : Graph kgraph2 { } ;
Draw : : Graph kgraph3 { } ;
2021-07-05 08:02:31 +12:00
cout < < Draw : : createBox ( 5 , 10 , Term : : width - 10 , 12 , Theme : : c ( " proc_box " ) , false , " braille " , " " , 1 ) < < Mv : : save ;
cout < < Draw : : createBox ( 5 , 23 , Term : : width - 10 , 12 , Theme : : c ( " proc_box " ) , false , " block " , " " , 2 ) ;
cout < < Draw : : createBox ( 5 , 36 , Term : : width - 10 , 12 , Theme : : c ( " proc_box " ) , false , " tty " , " " , 3 ) < < flush ;
2021-06-03 07:33:26 +12:00
// 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-20 00:57:27 +12:00
kgraph ( Term : : width - 12 , 10 , " cpu " , mydata , " braille " , false , false ) ;
kgraph2 ( Term : : width - 12 , 10 , " cpu " , mydata , " block " , false , false ) ;
kgraph3 ( Term : : width - 12 , 10 , " cpu " , mydata , " tty " , false , false ) ;
2021-06-03 07:33:26 +12:00
// 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-20 00:57:27 +12:00
cout < < Mv : : restore < < kgraph ( mydata , true )
< < Mv : : restore < < Mv : : d ( 13 ) < < kgraph2 ( mydata , true )
< < Mv : : restore < < Mv : : d ( 26 ) < < kgraph3 ( mydata , true ) < < endl
< < Mv : : d ( 1 ) < < " Init took " < < time_micros ( ) - kts < < " μs. " < < endl ;
2021-06-03 07:33:26 +12:00
// 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-20 00:57:27 +12:00
cout < < Mv : : restore < < kgraph ( mydata )
< < Mv : : restore < < Mv : : d ( 13 ) < < kgraph2 ( mydata )
< < Mv : : restore < < Mv : : d ( 26 ) < < kgraph3 ( mydata )
< < endl ;
2021-06-03 07:33:26 +12:00
// 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++;
2021-06-22 08:52:55 +12:00
// if (y == 100 or y == 0) flip = not flip;
2021-05-31 03:01:57 +12:00
if ( Input : : poll ( ) ) {
2021-06-26 09:58:19 +12:00
if ( Input : : get ( ) = = " space " ) Input : : wait ( ) ;
2021-05-31 03:01:57 +12:00
else break ;
}
2021-06-22 08:52:55 +12:00
sleep_ms ( 50 ) ;
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)){
2021-06-22 08:52:55 +12:00
// if (runners[i].valid() and runners[i].wait_for(std::chrono::milliseconds(10)) == future_status::ready) {
2021-06-03 07:33:26 +12:00
// 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
2021-05-13 13:11:29 +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-13 13:11:29 +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-13 13:11:29 +12:00
string ostring ;
2021-05-22 12:13:56 +12:00
uint64_t tsl , timestamp2 , rcount = 0 ;
2021-07-01 08:28:12 +12:00
list < uint64_t > avgtimes ;
2021-06-28 08:13:32 +12:00
size_t timer = 2000 ;
2021-05-18 11:16:22 +12:00
vector < string > greyscale ;
2021-05-15 04:54:37 +12:00
string filter ;
string filter_cur ;
string key ;
2021-07-04 11:18:48 +12:00
vector < Proc : : proc_info > plist ;
2021-05-18 11:16:22 +12:00
int xc ;
2021-06-28 08:13:32 +12:00
for ( size_t i : iota ( 0 , ( int ) Term : : height - 19 ) ) {
2021-05-18 11:16:22 +12:00
xc = 230 - i * 150 / ( Term : : height - 20 ) ;
greyscale . push_back ( Theme : : dec_to_color ( xc , xc , xc ) ) ;
}
2021-07-05 08:02:31 +12:00
// string pbox = Draw::createBox(1, 10, Term::width, Term::height - 18, Theme::c("proc_box"), false, "testbox", "below", 7);
// pbox += Mv::r(1) + Theme::c("title") + Fx::b + rjust("Pid:", 8) + " " + ljust("Program:", 16) + " " + ljust("Command:", Term::width - 70) + " Threads: " +
// ljust("User:", 10) + " " + rjust("MemB", 5) + " " + rjust("Cpu%", 14) + "\n" + Fx::reset + 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-07-04 11:18:48 +12:00
try {
plist = Proc : : collect ( ) ;
}
catch ( std : : exception const & e ) {
Logger : : error ( " Caught exception in Proc::collect() : " s + e . what ( ) ) ;
exit ( 1 ) ;
}
2021-05-28 08:29:36 +12:00
timestamp2 = time_micros ( ) ;
2021-05-15 04:54:37 +12:00
timestamp = timestamp2 - timestamp ;
2021-05-13 13:11:29 +12:00
ostring . clear ( ) ;
2021-07-05 08:02:31 +12:00
// lc = 0;
// ostring = Mv::u(2) + Mv::l(Term::width) + Mv::r(12)
// + trans("Filter: " + filter + (filtering ? Fx::bl + "█" + Fx::reset : " "))
// + trans(rjust("Per core: " + (Config::getB("proc_per_core") ? "On "s : "Off"s) + " Sorting: "
// + string(Config::getS("proc_sorting")), Term::width - 23 - ulen(filter)))
// + Mv::restore;
// for (auto& p : plist){
// if (not Config::getB("proc_tree")) {
// 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 or p.cpu_p >= 100 ? rjust(to_string(p.cpu_p), 3) + " " : rjust(to_string(p.cpu_p), 4))
// + "\n";
// }
// else {
// string cmd_cond;
// if (not p.cmd.empty()) {
// cmd_cond = p.cmd.substr(0, std::min(p.cmd.find(' '), p.cmd.size()));
// cmd_cond = cmd_cond.substr(std::min(cmd_cond.find_last_of('/') + 1, cmd_cond.size()));
// }
// ostring += Mv::r(1) + (Config::getB("tty_mode") ? "" : greyscale[lc]) + ljust(p.prefix + to_string(p.pid) + " " + p.name + " "
// + (not cmd_cond.empty() and cmd_cond != p.name ? "(" + cmd_cond + ")" : ""), Term::width - 40, true) + " "
// + rjust(to_string(p.threads), 5) + " " + ljust(p.user, 10) + " " + rjust(floating_humanizer(p.mem, true), 5) + string(11, ' ')
// + (p.cpu_p < 10 or p.cpu_p >= 100 ? rjust(to_string(p.cpu_p), 3) + " " : rjust(to_string(p.cpu_p), 4))
// + "\n";
// }
// if (lc++ > Term::height - 23) break;
// }
2021-05-28 08:29:36 +12:00
2021-07-05 08:02:31 +12:00
// while (lc++ < Term::height - 21) ostring += Mv::r(1) + string(Term::width - 2, ' ') + "\n";
2021-05-28 08:29:36 +12:00
2021-07-05 08:02:31 +12:00
ostring = Proc : : draw ( plist ) ;
2021-05-28 08:29:36 +12:00
2021-07-01 08:28:12 +12:00
avgtimes . push_front ( timestamp ) ;
if ( avgtimes . size ( ) > 30 ) avgtimes . pop_back ( ) ;
2021-07-05 08:02:31 +12:00
cout < < ostring < < Fx : : reset < < Mv : : to ( 2 , 2 ) < < endl ;
2021-07-04 11:18:48 +12:00
cout < < " Details for " < < Proc : : detailed . entry . name < < " ( " < < Proc : : detailed . entry . pid < < " ) Status: " < < Proc : : detailed . status < < " Elapsed: " < < Proc : : detailed . elapsed
< < " Mem: " < < floating_humanizer ( Proc : : detailed . entry . mem ) < < " "
< < " \n Parent: " < < Proc : : detailed . parent < < " IO in/out: " < < Proc : : detailed . io_read < < " / " < < Proc : : detailed . io_write < < " " < < endl ;
2021-07-05 08:02:31 +12:00
cout < < Mv : : to ( 4 , 2 ) < < " Processes call took: " < < rjust ( to_string ( timestamp ) , 5 ) < < " μs. Average: " < <
2021-05-28 08:29:36 +12:00
rjust ( to_string ( accumulate ( avgtimes . begin ( ) , avgtimes . end ( ) , 0 ) / avgtimes . size ( ) ) , 5 ) < < " μs of " < < avgtimes . size ( ) < <
2021-07-05 08:02:31 +12:00
" samples. Drawing took: " < < time_micros ( ) - timestamp2 < < " μs. \n Number of processes: " < < Proc : : numpids < < " . Number in vector: " < < plist . size ( ) < < " . Run count: " < < + + 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 ; }
2021-07-05 08:02:31 +12:00
if ( Config : : getB ( " proc_filtering " ) ) {
if ( key = = " enter " ) Config : : set ( " proc_filtering " , false ) ;
2021-06-22 08:52:55 +12:00
else if ( key = = " backspace " and not filter . empty ( ) ) filter = uresize ( filter , ulen ( filter ) - 1 ) ;
2021-05-15 04:54:37 +12:00
else if ( key = = " space " ) filter . push_back ( ' ' ) ;
else if ( ulen ( key ) = = 1 ) filter . append ( key ) ;
2021-05-19 08:11:34 +12:00
else { key . clear ( ) ; continue ; }
2021-06-14 09:12:11 +12:00
if ( filter ! = Config : : getS ( " proc_filter " ) ) Config : : set ( " proc_filter " , filter ) ;
2021-07-04 11:18:48 +12:00
key . clear ( ) ;
2021-07-05 08:02:31 +12:00
Proc : : redraw = true ;
2021-05-15 04:54:37 +12:00
break ;
}
else if ( key = = " q " ) break ;
2021-06-14 09:12:11 +12:00
else if ( key = = " left " ) {
int cur_i = v_index ( Proc : : sort_vector , Config : : getS ( " proc_sorting " ) ) ;
if ( - - cur_i < 0 ) cur_i = Proc : : sort_vector . size ( ) - 1 ;
Config : : set ( " proc_sorting " , Proc : : sort_vector . at ( cur_i ) ) ;
}
else if ( key = = " right " ) {
int cur_i = v_index ( Proc : : sort_vector , Config : : getS ( " proc_sorting " ) ) ;
if ( + + cur_i > ( int ) Proc : : sort_vector . size ( ) - 1 ) cur_i = 0 ;
Config : : set ( " proc_sorting " , Proc : : sort_vector . at ( cur_i ) ) ;
}
2021-07-05 08:02:31 +12:00
else if ( key = = " f " ) Config : : flip ( " proc_filtering " ) ;
2021-06-14 09:12:11 +12:00
else if ( key = = " t " ) Config : : flip ( " proc_tree " ) ;
else if ( key = = " r " ) Config : : flip ( " proc_reversed " ) ;
2021-06-05 11:41:24 +12:00
else if ( key = = " c " ) Config : : flip ( " proc_per_core " ) ;
2021-06-14 09:12:11 +12:00
else if ( key = = " delete " ) { filter . clear ( ) ; Config : : set ( " proc_filter " , filter ) ; }
2021-07-04 11:18:48 +12:00
else if ( key = = " d " ) {
Config : : flip ( " show_detailed " ) ;
if ( Config : : getB ( " show_detailed " ) ) {
Config : : set ( " detailed_pid " , ( int ) plist . at ( 0 ) . pid ) ;
}
}
2021-05-15 04:54:37 +12:00
else continue ;
2021-07-05 08:02:31 +12:00
Proc : : redraw = true ;
2021-05-15 04:54:37 +12:00
break ;
2021-05-13 13:11:29 +12:00
}
2021-07-05 08:02:31 +12:00
cout < < Mv : : to ( Term : : height - 3 , 1 ) < < flush ;
2021-05-13 13:11:29 +12:00
}
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 ;
}