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-16 09:49:16 +12:00
atomic < bool > resized ( false ) ;
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-07-16 09:49:16 +12:00
//* Handler for SIGWINCH and general resizing events
void _resize ( bool force = false ) {
if ( Term : : refresh ( false ) or force ) {
Global : : resized = true ;
if ( Runner : : active ) {
Runner : : stop = true ;
atomic_wait ( Runner : : active ) ;
}
Term : : refresh ( ) ;
}
else return ;
while ( true ) {
sleep_ms ( 100 ) ;
if ( not Term : : refresh ( ) ) break ;
}
Input : : interrupt = true ;
Draw : : calcSizes ( ) ;
}
//* Exit handler; stops threads, restores terminal and saves config changes
void clean_quit ( int sig = - 1 ) {
2021-06-03 07:33:26 +12:00
if ( Global : : quitting ) return ;
2021-07-16 09:49:16 +12:00
Global : : quitting = true ;
if ( Runner : : active ) {
Runner : : stop = true ;
atomic_wait ( Runner : : active ) ;
}
2021-06-03 07:33:26 +12:00
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
}
2021-07-16 09:49:16 +12:00
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 ) ;
}
2021-07-16 09:49:16 +12:00
//* Handler for SIGTSTP; stops threads, restores terminal and sends SIGSTOP
void _sleep ( ) {
if ( Runner : : active ) {
Runner : : stop = true ;
atomic_wait ( Runner : : active ) ;
}
2021-06-10 05:47:49 +12:00
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 ) ;
}
2021-07-16 09:49:16 +12:00
//* Handler for SIGCONT; re-initialize terminal and force a resize event
void _resume ( ) {
2021-06-10 05:47:49 +12:00
Term : : init ( ) ;
2021-06-22 08:52:55 +12:00
if ( not Global : : debuginit ) cout < < Term : : alt_screen < < Term : : hide_cursor < < flush ;
2021-07-16 09:49:16 +12:00
_resize ( true ) ;
2021-06-03 07:33:26 +12:00
}
2021-07-16 09:49:16 +12:00
void _exit_handler ( ) {
clean_quit ( - 1 ) ;
}
2021-06-03 07:33:26 +12:00
2021-06-10 05:47:49 +12:00
void _signal_handler ( int sig ) {
switch ( sig ) {
case SIGINT :
clean_quit ( 0 ) ;
break ;
case SIGTSTP :
2021-07-16 09:49:16 +12:00
_sleep ( ) ;
2021-06-10 05:47:49 +12:00
break ;
case SIGCONT :
2021-07-16 09:49:16 +12:00
_resume ( ) ;
break ;
case SIGWINCH :
_resize ( ) ;
2021-06-10 05:47:49 +12:00
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-07-16 09:49:16 +12:00
atomic < bool > stop ( false ) ;
2021-07-05 08:02:31 +12:00
}
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-07-16 09:49:16 +12:00
std : : signal ( SIGWINCH , _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-07-16 09:49:16 +12:00
Global : : debuginit = false ;
2021-05-24 08:25:07 +12:00
2021-07-05 08:02:31 +12:00
Draw : : calcSizes ( ) ;
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-16 09:49:16 +12:00
cout < < Cpu : : box < < Mem : : box < < Net : : box < < Proc : : box < < flush ;
2021-05-07 06:32:03 +12:00
2021-07-05 08:02:31 +12:00
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-07-16 09:49:16 +12:00
// if (true) {
// cout << Term::clear << flush;
// unordered_flat_map<string, string(*)(string)> korvs = {
// {"korv1", korv1},
// {"korv2", korv2},
// };
2021-05-17 08:58:16 +12:00
2021-07-16 09:49:16 +12:00
// // auto hej = korv1;
2021-05-17 08:58:16 +12:00
2021-07-16 09:49:16 +12:00
// cout << korvs["korv1"]("hejsan") << endl;
// cout << korvs["korv2"]("hejsan igen") << endl;
// exit(0);
// }
2021-06-26 09:58:19 +12:00
2021-07-16 09:49:16 +12:00
//* Test theme
if ( false ) {
2021-06-26 09:58:19 +12:00
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 < < " " ;
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-05-29 12:32:36 +12:00
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-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
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-05-31 03:01:57 +12:00
auto kts = time_micros ( ) ;
2021-07-16 09:49:16 +12:00
kgraph ( Term : : width - 13 , 10 , " cpu " , mydata , " braille " , false , false ) ;
kgraph2 ( Term : : width - 13 , 10 , " cpu " , mydata , " block " , false , false ) ;
kgraph3 ( Term : : width - 13 , 10 , " cpu " , mydata , " tty " , false , false ) ;
2021-06-01 07:47:41 +12:00
2021-05-31 03:01:57 +12:00
2021-06-20 00:57:27 +12:00
cout < < Mv : : restore < < kgraph ( mydata , true )
< < Mv : : restore < < Mv : : d ( 13 ) < < kgraph2 ( mydata , true )
2021-07-16 09:49:16 +12:00
< < Mv : : restore < < Mv : : d ( 26 ) < < kgraph3 ( mydata , true ) < < ' \n '
2021-06-20 00:57:27 +12:00
< < Mv : : d ( 1 ) < < " Init took " < < time_micros ( ) - kts < < " μs. " < < endl ;
2021-07-16 09:49:16 +12:00
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 ;
2021-05-30 12:15:09 +12:00
kts = time_micros ( ) ;
2021-07-16 09:49:16 +12:00
cout < < Term : : sync_start < < Mv : : restore < < kgraph ( mydata )
2021-06-20 00:57:27 +12:00
< < Mv : : restore < < Mv : : d ( 13 ) < < kgraph2 ( mydata )
< < Mv : : restore < < Mv : : d ( 26 ) < < kgraph3 ( mydata )
2021-07-16 09:49:16 +12:00
< < Term : : sync_end < < 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 ;
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-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-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-16 09:49:16 +12:00
Config : : lock ( ) ;
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-05-28 08:29:36 +12:00
2021-07-05 08:02:31 +12:00
ostring = Proc : : draw ( plist ) ;
2021-07-16 09:49:16 +12:00
Config : : unlock ( ) ;
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-16 09:49:16 +12:00
cout < < Term : : sync_start < < ostring < < Fx : : reset < < Mv : : to ( 2 , 2 ) < < ' \n ' ;
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 ) < < " "
2021-07-16 09:49:16 +12:00
< < " \n Parent: " < < Proc : : detailed . parent < < " IO in/out: " < < Proc : : detailed . io_read < < " / " < < Proc : : detailed . io_write < < " " ;
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-16 09:49:16 +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 " ) < < Term : : sync_end < < flush ;
2021-05-15 04:54:37 +12:00
2021-07-16 09:49:16 +12:00
while ( time_ms ( ) < tsl and not Global : : resized ) {
2021-05-15 04:54:37 +12:00
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-16 09:49:16 +12:00
else if ( is_in ( key , " up " , " down " , " page_up " , " page_down " , " home " , " end " ) ) {
Proc : : selection ( key ) ;
cout < < Proc : : draw ( plist ) < < flush ;
continue ;
2021-07-04 11:18:48 +12:00
}
2021-07-16 09:49:16 +12:00
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-16 09:49:16 +12:00
if ( Global : : resized ) {
cout < < Cpu : : box < < Mem : : box < < Net : : box < < Proc : : box < < flush ;
Global : : resized = false ;
}
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
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 ;
}