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-15 23:24:24 +12:00
2021-05-07 06:32:03 +12:00
# 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>
# 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-07 06:32:03 +12:00
2021-05-09 00:56:48 +12:00
# include <btop_globs.h>
# include <btop_tools.h>
# include <btop_config.h>
2021-05-09 06:37:36 +12:00
# include <btop_input.h>
# include <btop_theme.h>
2021-05-17 08:58:16 +12:00
# include <btop_draw.h>
2021-05-09 00:56:48 +12:00
# if defined(__linux__)
2021-05-20 09:21:56 +12:00
# define LINUX 1
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-05-20 09:21:56 +12:00
# define OSX 1
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
# error Platform not supported or could not determine platform!
2021-05-09 00:56:48 +12:00
# endif
2021-05-07 06:32:03 +12:00
2021-05-20 09:21:56 +12:00
using std : : string , std : : vector , std : : array , std : : map , std : : atomic , std : : endl , std : : cout , std : : views : : iota , std : : list , std : : accumulate ;
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 ;
2021-05-17 08:58:16 +12:00
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
//? ------------------------------------------------- GLOBALS ---------------------------------------------------------
2021-05-07 06:32:03 +12:00
2021-05-09 00:56:48 +12:00
namespace Global {
2021-05-19 08:11:34 +12:00
const vector < array < string , 2 > > Banner_src = {
2021-05-09 00:56:48 +12:00
{ " #E62525 " , " ██████╗ ████████╗ ██████╗ ██████╗ " } ,
{ " #CD2121 " , " ██╔══██╗╚══██╔══╝██╔═══██╗██╔══██╗ ██╗ ██╗ " } ,
{ " #B31D1D " , " ██████╔╝ ██║ ██║ ██║██████╔╝ ██████╗██████╗ " } ,
{ " #9A1919 " , " ██╔══██╗ ██║ ██║ ██║██╔═══╝ ╚═██╔═╝╚═██╔═╝ " } ,
{ " #801414 " , " ██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝ " } ,
{ " #000000 " , " ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ " } ,
} ;
2021-05-07 06:32:03 +12:00
2021-05-09 00:56:48 +12:00
const string Version = " 0.0.1 " ;
2021-05-15 04:54:37 +12:00
string banner ;
2021-05-19 08:11:34 +12:00
const uint banner_width = 49 ;
2021-05-09 00:56:48 +12:00
}
2021-05-07 06:32:03 +12:00
//? --------------------------------------- FUNCTIONS, STRUCTS & CLASSES ----------------------------------------------
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 ) ;
} else if ( argument = = " -h " | | argument = = " --help " ) {
cout < < " help here " < < endl ;
exit ( 0 ) ;
} else {
cout < < " Unknown argument: " < < argument < < " \n " < <
" Use -h or --help for help. " < < endl ;
exit ( 1 ) ;
}
}
}
2021-05-15 04:54:37 +12:00
//* Generate the btop++ banner
2021-05-19 08:11:34 +12:00
string createBanner ( ) {
2021-05-15 04:54:37 +12:00
size_t z = 0 ;
string b_color , bg , fg , out , oc , letter ;
bool truecolor = Config : : getB ( " truecolor " ) ;
int bg_i ;
for ( auto line : Global : : Banner_src ) {
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 ) ;
2021-05-19 08:11:34 +12:00
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 ;
if ( b_color ! = oc ) out + = b_color ;
out + = letter ;
oc = b_color ;
2021-05-07 06:32:03 +12:00
}
2021-05-19 08:11:34 +12:00
if ( + + z < Global : : Banner_src . size ( ) ) out + = Mv : : l ( ulen ( line [ 1 ] ) ) + Mv : : d ( 1 ) ;
2021-05-07 06:32:03 +12:00
}
2021-05-15 04:54:37 +12:00
out + = Mv : : r ( 18 - Global : : Version . size ( ) ) + Fx : : i + Theme : : dec_to_color ( 0 , 0 , 0 , ! truecolor , " bg " ) +
2021-05-19 08:11:34 +12:00
Theme : : dec_to_color ( 150 , 150 , 150 , ! truecolor ) + " v " + Global : : Version + Fx : : ui ;
return out ;
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
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-09 00:56:48 +12:00
2021-05-07 06:32:03 +12:00
//? --------------------------------------------- Main starts here! ---------------------------------------------------
int main ( int argc , char * * argv ) {
2021-05-20 09:21:56 +12:00
// using namespace std;
2021-05-17 08:58:16 +12:00
2021-05-07 06:32:03 +12:00
//? Init
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-20 09:21:56 +12:00
# if defined(LINUX)
//? Linux init
2021-05-22 12:13:56 +12:00
Global : : proc_path = ( fs : : is_directory ( fs : : path ( " /proc " ) ) & & access ( " /proc " , R_OK ) ! = - 1 ) ? fs : : path ( " /proc " ) : Global : : proc_path ;
2021-05-14 07:11:10 +12:00
if ( Global : : proc_path . empty ( ) ) {
2021-05-22 12:13:56 +12:00
cout < < " ERROR: Proc filesystem not found/readable! " < < endl ;
2021-05-14 07:11:10 +12:00
exit ( 1 ) ;
}
2021-05-20 09:21:56 +12:00
# endif
2021-05-14 07:11:10 +12:00
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-05-09 10:18:51 +12:00
cout < < " ERROR: No tty detected! " < < endl ;
2021-05-22 12:13:56 +12:00
cout < < " btop++ needs an interactive shell to run. " < < endl ;
2021-05-07 06:32:03 +12:00
exit ( 1 ) ;
}
2021-05-09 10:18:51 +12:00
//? Read config file if present
2021-05-15 04:54:37 +12:00
Config : : load ( " ____ " ) ;
2021-05-09 10:18:51 +12:00
2021-05-17 08:58:16 +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-05-19 08:11:34 +12:00
Global : : banner = createBanner ( ) ;
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-05-15 04:54:37 +12:00
int debug = 0 ;
2021-05-09 10:18:51 +12:00
int tests = 0 ;
2021-05-20 09:21:56 +12:00
bool debuginit = false ;
2021-05-09 10:18:51 +12:00
2021-05-15 04:54:37 +12:00
// cout << Theme("main_bg") << Term::clear << flush;
2021-05-10 08:25:41 +12:00
bool thread_test = false ;
2021-05-07 06:32:03 +12:00
2021-05-20 09:21:56 +12:00
if ( ! 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 ;
2021-05-18 11:16:22 +12:00
// 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 ;
2021-05-19 08:11:34 +12:00
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-18 11:16:22 +12:00
cout < < Theme : : g ( " used " ) [ ill ] < < " - " ;
2021-05-17 08:58:16 +12:00
}
2021-05-18 11:16:22 +12:00
cout < < Fx : : reset < < endl ;
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
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 ;
2021-05-17 08:58:16 +12:00
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-05-09 10:18:51 +12:00
2021-05-10 08:25:41 +12:00
if ( thread_test ) {
map < int , future < string > > runners ;
map < int , string > outputs ;
2021-05-17 08:58:16 +12:00
for ( int i : iota ( 0 , 10 ) ) {
2021-05-10 08:25:41 +12:00
runners [ i ] = async ( my_worker , i ) ;
}
2021-05-17 08:58:16 +12:00
// uint i = 0;
2021-05-10 08:25:41 +12:00
while ( outputs . size ( ) < 10 ) {
2021-05-17 08:58:16 +12:00
for ( int i : iota ( 0 , 10 ) ) {
2021-05-20 09:21:56 +12:00
if ( runners [ i ] . valid ( ) & & runners [ i ] . wait_for ( std : : chrono : : milliseconds ( 10 ) ) = = future_status : : ready ) {
2021-05-10 08:25:41 +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-15 04:54:37 +12:00
Proc : : init ( ) ;
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 ;
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-05-20 09:21:56 +12:00
list < uint64_t > avgtimes ;
uint timer = 1000 ;
2021-05-15 04:54:37 +12:00
bool filtering = false ;
bool reversing = false ;
int sortint = Proc : : sort_map [ " cpu lazy " ] ;
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-05-18 11:16:22 +12:00
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 ) ) ;
}
string pbox = Box : : draw ( Box : : Conf ( 0 , 10 , Term : : width , Term : : height - 16 , Theme : : c ( " proc_box " ) , " testbox " , " below " , true , 7 ) ) ;
pbox + = rjust ( " Pid: " , 8 ) + " " + ljust ( " Program: " , 16 ) + " " + ljust ( " Command: " , Term : : width - 69 ) + " Threads: " +
ljust ( " User: " , 10 ) + " " + rjust ( " MemB " , 5 ) + " " + rjust ( " Cpu% " , 14 ) + " \n " ;
2021-05-11 09:46:41 +12:00
2021-05-15 04:54:37 +12:00
while ( key ! = " q " ) {
2021-05-13 13:11:29 +12:00
timestamp = time_ms ( ) ;
2021-05-15 04:54:37 +12:00
tsl = timestamp + timer ;
2021-05-19 08:11:34 +12:00
auto plist = Proc : : collect ( Proc : : sort_array [ sortint ] , reversing , filter ) ;
2021-05-15 04:54:37 +12:00
timestamp2 = time_ms ( ) ;
timestamp = timestamp2 - timestamp ;
2021-05-13 13:11:29 +12:00
ostring . clear ( ) ;
lc = 0 ;
2021-05-15 04:54:37 +12:00
filter_cur = ( filtering ) ? Fx : : bl + " █ " + Fx : : reset : " " ;
2021-05-18 11:16:22 +12:00
ostring = Mv : : save + Mv : : u ( 2 ) + Mv : : r ( 20 ) + trans ( rjust ( " Filter: " + filter + filter_cur + string ( Term : : width / 3 , ' ' ) +
2021-05-20 09:21:56 +12:00
" Sorting: " + string ( Proc : : sort_array [ sortint ] ) , Term : : width - 25 , true , filtering ) ) + Mv : : restore ;
2021-05-15 04:54:37 +12:00
2021-05-19 08:11:34 +12:00
for ( auto & p : plist ) {
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 , ' ' ) ;
ostring + = ( p . cpu_p > 100 ) ? rjust ( to_string ( p . cpu_p ) , 3 ) + " " : rjust ( to_string ( p . cpu_p ) , 4 ) ;
2021-05-13 13:11:29 +12:00
ostring + = " \n " ;
2021-05-18 11:16:22 +12:00
if ( lc + + > Term : : height - 21 ) break ;
2021-05-15 04:54:37 +12:00
}
2021-05-20 09:21:56 +12:00
avgtimes . push_front ( timestamp ) ;
if ( avgtimes . size ( ) > 100 ) avgtimes . pop_back ( ) ;
2021-05-18 11:16:22 +12:00
cout < < pbox < < ostring < < Fx : : reset < < " \n " < < endl ;
2021-05-22 12:13:56 +12:00
cout < < Mv : : to ( Term : : height - 4 , 1 ) < < " Processes call took: " < < rjust ( to_string ( timestamp ) , 4 ) < < " ms. Average: " < < rjust ( to_string ( accumulate ( avgtimes . begin ( ) , avgtimes . end ( ) , 0 ) / avgtimes . size ( ) ) , 3 ) < <
" ms of " < < avgtimes . size ( ) < < " samples. Drawing took: " < < time_ms ( ) - timestamp2 < < " ms. Number of processes: " < < Proc : : numpids < < " . Run count: " < < + + rcount < < " " < < 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 ) ;
2021-05-19 08:11:34 +12:00
else { key . clear ( ) ; continue ; }
2021-05-15 04:54:37 +12:00
break ;
}
else if ( key = = " q " ) break ;
2021-05-19 08:11:34 +12:00
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 ;
else if ( key = = " delete " ) filter . clear ( ) ;
else continue ;
break ;
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-11 09:46:41 +12:00
//cout << pw->pw_name << "/" << gr->gr_name << endl;
2021-05-10 08:25:41 +12:00
2021-05-07 06:32:03 +12:00
if ( tests > 4 ) {
string trim_test1 = " -*vad " ;
string trim_test2 = " vad*- " ;
string trim_test3 = trim_test1 + trim_test2 ;
cout < < " \" " < < ltrim ( trim_test1 , " -* " ) < < " \" \" " < < rtrim ( trim_test2 , " *- " ) < < " \" \" " < < trim ( trim_test3 , " - " ) < < " \" " < < endl ;
string testie = " Does this work as intended? Or? " ;
auto t_vec = ssplit ( testie ) ;
for ( auto & tp : t_vec ) {
cout < < " \" " < < tp < < " \" " < < flush ;
}
}
//if (tests>5){
2021-05-09 10:18:51 +12:00
2021-05-07 06:32:03 +12:00
//}
// map<string, string> dict = {
// {"Korv", "14"},
// {"Vad", "13"}
// };
// cout << dict["Korv"] << ", " << dict["Vad"] << endl;
// vector<map<string, int>> test = {
// {{"first", 1}, {"second", 2}},
// {{"first", 11}, {"second", 22}}
// };
//cout << test[0]["first"] << " " << test[1]["second"] << endl;
// for (auto& m : test) {
// cout << endl;
// for (auto& item : m) {
// cout << item.first << " " << item.second << endl;
// }
// }
2021-05-15 04:54:37 +12:00
if ( debug = = 3 ) {
cout < < Theme : : c ( " main_fg " ) ;
cout < < Mv : : to ( Term : : height - 1 , 0 ) < < " Press q to exit! Timeout " < < flush ;
2021-05-11 09:46:41 +12:00
string full , key ;
2021-05-07 06:32:03 +12:00
int wt = 90 ;
bool qp = false ;
while ( ! qp & & wt > = 0 ) {
int wtm = wt / 60 ;
int wts = wt - wtm * 60 ;
wt - - ;
2021-05-15 04:54:37 +12:00
cout < < Mv : : to ( Term : : height - 1 , 26 ) < < " ( " < < wtm < < " : " < < wts < < " ) " < < flush ;
2021-05-08 12:38:51 +12:00
//chr = Key(1000);
2021-05-15 04:54:37 +12:00
if ( Input : : poll ( 1000 ) ) {
key = Input : : get ( ) ;
cout < < Mv : : to ( Term : : height - 2 , 1 ) < < " Last key: LEN= " < < key . size ( ) < < " ULEN= " < < ulen ( key ) < < " KEY= \" " < < key < < " \" CODE= " < < ( int ) key . at ( 0 ) < < " " < < flush ;
2021-05-11 09:46:41 +12:00
full + = key ;
2021-05-15 04:54:37 +12:00
cout < < Mv : : to ( Term : : height - 5 , 1 ) < < full < < flush ;
2021-05-11 09:46:41 +12:00
if ( key = = " q " ) qp = true ;
key = " " ;
2021-05-07 06:32:03 +12:00
wt + + ;
}
}
}
2021-05-15 04:54:37 +12:00
if ( debug = = 1 ) Input : : wait ( ) ;
Term : : restore ( ) ;
2021-05-20 09:21:56 +12:00
if ( ! debuginit ) cout < < Term : : normal_screen < < Term : : show_cursor < < flush ;
2021-05-07 06:32:03 +12:00
return 0 ;
}