diff --git a/.gitattributes b/.gitattributes index f4d67bf..2e368cf 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,12 +1,13 @@ +doc/ export-ignore +demo/ export-ignore tests/ export-ignore vendor/ export-ignore -demo/ export-ignore -doc/ export-ignore -.gitattributes export-ignore +README.* export-ignore +composer.* export-ignore .gitignore export-ignore -.codeclimate.yml export-ignore .travis.yml export-ignore -composer.* export-ignore phpunit.xml export-ignore -README.* export-ignore -CHANGELOG.* export-ignore \ No newline at end of file +CHANGELOG.* export-ignore +.gitattributes export-ignore +.codeclimate.yml export-ignore + diff --git a/LICENSE b/LICENSE index aaaa9b9..85161e5 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2017-2021 kristuff +Copyright (c) 2017-2024 Kr157uff Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index a9a1c2f..be8ff14 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,10 @@ [![Latest Stable Version](https://poser.pugx.org/kristuff/mishell/v/stable)](https://packagist.org/packages/kristuff/mishell) [![License](https://poser.pugx.org/kristuff/mishell/license)](https://packagist.org/packages/kristuff/mishell) -![sample](doc/screenshots/loading.png) +![sample](doc/screenshots/mishell1.6.png) +*See also mp4 in doc/screenshots directory* + + - [Features](#features) - [Requirements](#requirements) @@ -33,21 +36,26 @@ Features Requirements ------------ - PHP >= 5.6 +- PHP mbstring module + Install -------- Deploy with your project (in `composer.json`): + ``` { ... "require": { - "kristuff/mishell": ">=1.5-stable" + "kristuff/mishell": ">=1.6-stable" } } ``` +> Composer is (technically) required to build autoloader files. You should be able to run the demo "as is" (with the `vendor` directory included) when you clone the project. There is no other dependencies. + Documentation -------- @@ -80,15 +88,19 @@ Run the sample Bonus ----- You can also do unuseful things like the blue screen of the death^^ Check the demo -![blue-screen](doc/screenshots/blue-screen.png) +![blue-screen](doc/screenshots/blue-screen.png) + +Update ::1.6 + +![blue-screen-1.6](doc/screenshots/blue-screen-1.5.9.png) License ------- The MIT License (MIT) -Copyright (c) 2017-2021 Kristuff +Copyright (c) 2017-2024 Kristuff Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/composer.json b/composer.json index 8a3e3d4..c6b6647 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "kristuff/mishell", "description": "A mini PHP library to build beautiful CLI apps and reports", - "homepage": "https://kristuff.fr/projects/mishell", + "homepage": "https://github.com/kristuff/mishell", "keywords": ["cli", "table", "color"], "type": "library", "license": "MIT", diff --git a/demo/demo.ask.php b/demo/demo.ask.php index 234b9d4..4d3ac11 100644 --- a/demo/demo.ask.php +++ b/demo/demo.ask.php @@ -1,7 +1,7 @@ 15, ' ANSI Code' => 15, ' Sample ouput' => 51]; +$rowHeaders = ['Color name' => 15, ' ANSI Code' => 15, ' Sample output' => 51]; Console::log(' '.Console::tableRowSeparator($rowHeaders)); Console::log(' '.Console::tableRow($rowHeaders)); Console::log(' '.Console::tableRowSeparator($rowHeaders)); diff --git a/demo/demo.bluescreen.php b/demo/demo.bluescreen.php index 6abcb28..8d5c007 100644 --- a/demo/demo.bluescreen.php +++ b/demo/demo.bluescreen.php @@ -1,6 +1,6 @@ ', $cols, ' ', STR_PAD_LEFT), 'white', 'blue'); break; + default: Console::log(Console::pad(' ', $cols), 'white', 'blue'); } } -Console::askInt(Console::pad('Press something to stop damage your eyes > ', $cols, ' ', STR_PAD_LEFT), 'white', 'blue'); // restore window Console::restoreWindow(); -Console::log('Any resemblance to a lived situation is a pure coincidence.'); ?> diff --git a/demo/demo.colors.php b/demo/demo.colors.php index 159fc21..378d727 100644 --- a/demo/demo.colors.php +++ b/demo/demo.colors.php @@ -1,9 +1,9 @@ 7, 'Color name' => 15, ' ANSI Code' => 15, ' Sample ouput' => 50]; +$rowHeaders = ['#Num' => 7, 'Color name' => 15, ' ANSI Code' => 15, ' Sample output' => 50]; Console::log(' '.Console::tableRowSeparator($rowHeaders)); Console::log(' '.Console::tableRow($rowHeaders)); Console::log(' '.Console::tableRowSeparator($rowHeaders)); diff --git a/demo/demo.pad.php b/demo/demo.pad.php index b2c7c56..fab34b0 100644 --- a/demo/demo.pad.php +++ b/demo/demo.pad.php @@ -1,6 +1,6 @@ diff --git a/demo/demo.progress2.sample.php b/demo/demo.progress2.sample.php new file mode 100644 index 0000000..a3fc5f3 --- /dev/null +++ b/demo/demo.progress2.sample.php @@ -0,0 +1,44 @@ + diff --git a/demo/demo.progress3.php b/demo/demo.progress3.php new file mode 100644 index 0000000..dacc54c --- /dev/null +++ b/demo/demo.progress3.php @@ -0,0 +1,81 @@ += $harePurcent ? 'green' : $loserColor; + $hareColor = $tortPurcent < $harePurcent ? 'green' : $loserColor; + $msg1 = $i==100 ? + Console::text(' [*]', 'blue').Console::text(' Tortoise vs Hare Race - Final Results', 'white') : + Console::text(' [*]', 'blue').Console::text(' Tortoise vs Hare Race: ', 'white').Console::text(' RUNNING ', 'white', 'yellow'). ' ' ; + $msg2 = Console::text(' [*]', $i==100 ? $tortColor : 'blue').Console::text(' 🐒 ', 'lightgreen').Console::text('Tortoise progress: ', 'white').Console::progressBar($tortPurcent, $tortColor, $tortColor,'darkgray', 60, ' '); + $msg3 = Console::text(' [*]', $i==100 ? $hareColor : 'blue').Console::text(' πŸ‡ ', 'white'). Console::text('Hare progress: ', 'white').Console::progressBar($harePurcent, $hareColor, $hareColor,'darkgray', 60, ' '); + $msg2End = $tortPurcent == 100 ? Console::text(' πŸ† WINNER!!!', 'green') : ''; + + Console::overwrite([$msg1,' ', $msg2.$msg2End,' ', $msg3, ' ']); + + // wait a moment, so we see the animation + usleep(90000); +} + + + + + +?> diff --git a/demo/demo.restore.php b/demo/demo.restore.php new file mode 100644 index 0000000..e839256 --- /dev/null +++ b/demo/demo.restore.php @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/demo/demo.size.php b/demo/demo.size.php index 8fc9cb3..365d5f3 100644 --- a/demo/demo.size.php +++ b/demo/demo.size.php @@ -1,25 +1,14 @@ diff --git a/demo/demo.size.sample.php b/demo/demo.size.sample.php new file mode 100644 index 0000000..2c44fd9 --- /dev/null +++ b/demo/demo.size.sample.php @@ -0,0 +1,18 @@ + diff --git a/demo/demo.slavaukraini.php b/demo/demo.slavaukraini.php new file mode 100644 index 0000000..0fba8eb --- /dev/null +++ b/demo/demo.slavaukraini.php @@ -0,0 +1,42 @@ + ', $cols, ' ', STR_PAD_LEFT), 'blue', 'yellow'); + break; + default: + if ($i > $middle) { + Console::log(Console::pad(' ', $cols), 'blue', 'yellow'); + } else { + Console::log(Console::pad(' ', $cols), 'yellow', 'blue'); + } + } +} + +// restore previous window +Console::restoreWindow(); + +?> diff --git a/demo/demo.standwithukraine-splash-screen.php b/demo/demo.standwithukraine-splash-screen.php new file mode 100644 index 0000000..e9a4047 --- /dev/null +++ b/demo/demo.standwithukraine-splash-screen.php @@ -0,0 +1,58 @@ + $middle) { + Console::log(Console::pad(' ', $cols), 'blue', 'yellow'); + } else { + Console::log(Console::pad(' ', $cols), 'yellow', 'blue'); + } + } + } + + sleep(6); + + // restore previous window + Console::restoreWindow(); + +} + + +?> diff --git a/demo/demo.standwithukraine.php b/demo/demo.standwithukraine.php new file mode 100644 index 0000000..b9f4d28 --- /dev/null +++ b/demo/demo.standwithukraine.php @@ -0,0 +1,44 @@ + ', $cols, ' ', STR_PAD_LEFT), 'blue', 'yellow'); + break; + default: + if ($i > $middle) { + Console::log(Console::pad(' ', $cols), 'blue', 'yellow'); + } else { + Console::log(Console::pad(' ', $cols), 'yellow', 'blue'); + } + } +} + +// restore previous window +Console::restoreWindow(); + +?> diff --git a/demo/demo.styles.php b/demo/demo.styles.php index 458cccb..18e3a7e 100644 --- a/demo/demo.styles.php +++ b/demo/demo.styles.php @@ -1,9 +1,9 @@ 15, 'ANSI Code' => 15, 'Sample ouput' => 50 ]; +$rowHeaders = [ 'Style name' => 15, 'ANSI Code' => 15, 'Sample output' => 50 ]; Console::log(' '.Console::tableRowSeparator($rowHeaders)); Console::log(' '.Console::tableRow($rowHeaders)); Console::log(' '.Console::tableRowSeparator($rowHeaders)); diff --git a/demo/demo.table.php b/demo/demo.table.php index b93126b..efd2c43 100644 --- a/demo/demo.table.php +++ b/demo/demo.table.php @@ -1,6 +1,6 @@ = $harePurcent ? 'green' : 'red' ; + $hareColor = $tortPurcent < $harePurcent ? 'green' : 'red' ; + } else { + $tortColor = $tortPurcent >= $harePurcent ? 'green' : 'yellow' ; + $hareColor = $tortPurcent < $harePurcent ? 'green' : 'yellow' ; + } + $msg1 = $i==100 ? + Console::text(' [*]', 'blue').Console::text(' Tortoise vs Hare Race - Final Results', 'yellow') : + Console::text(' [*]', 'blue').Console::text(' Tortoise vs Hare Race: ', 'yellow').Console::text(' RUNNING ', 'yellow', 'yellow'). ' ' ; + $msg2 = Console::text(' [*]', $i==100 ? $tortColor : 'blue').Console::text(' 🐒 ', 'green').Console::text('Tortoise progress: ', 'yellow').Console::progressBar($tortPurcent, $tortColor, $tortColor); + $msg3 = Console::text(' [*]', $i==100 ? $hareColor : 'blue').Console::text(' πŸ‡ ', 'yellow'). Console::text('Hare progress: ', 'yellow').Console::progressBar($harePurcent, $hareColor, $hareColor); + $msg2End = $tortPurcent == 100 ? ' '.Console::text('πŸ† WINNER!!!', 'green') : ''; + $msgs = [ + $head1 + , + ' ', $copyright, + ' ', $weSWU, + ' ', $twitter, + ' ', $msg1, + ' ', $msg2.$msg2End, + ' ', $msg3, + ' ', $progress, + ' ', $progress1, + ' ', + ]; - // fake progress message - for ($i=0 ; $i<=100 ; $i++) { + // rewrite the last printed lines + Console::overwrite($msgs); + + // wait for a while, so we see the animation + usleep($introDelay); + } - // Overwrite progress message. - Console::relog($pad.Console::text('This is a fake progress message... [', 'white'). - Console::text($i .'%', 'green'). - Console::text('] completed', 'white')); + $apt1 = Console::text(' dpkg install nothing [ ', 'yellow').Console::progressBar(0, 'default', 'default','default', Console::getColumns() - 26, ' ', '.', false).Console::text(' ]', 'yellow'); + $apt2 = Console::pad(Console::text(' dpkg finished to install nothing ...', 'yellow'), Console::getColumns() -26); + $apt3 = ''; + $apt4 = Console::pad(Console::text(' it works on my machine ...', 'yellow'), Console::getColumns() -26); + $apt5 = ''; + $apt6 = Console::pad(Console::text(' failed to import new galaxy, we will retry later ...', 'red'), Console::getColumns() -26); - // wait for a while, so we see the animation - usleep(17000); + usleep($introDelay * random_int(2, 3)); + Console::log($apt1); + for ($i=1 ; $i<=100 ; $i++) { + $apt1 = Console::text(' dpkg install nothing [ ', 'yellow').Console::progressBar($i, 'default', 'default','default', Console::getColumns() - 26, ' ', '#', false).Console::text(' ]', 'yellow'); + Console::overwrite($apt1); + usleep($introDelay / 3); } - // Overwrite progress message. - Console::relog($pad.Console::text('Done!', 'white', 'green', 'underlined').str_pad(' ', 100)); - usleep(45000); - Console::clear(); + Console::overwrite($apt2); + + Console::log($apt3); + for ($i=1 ; $i<=100 ; $i++) { + $apt3 = Console::text(' dpkg purge nothing [ ', 'yellow').Console::progressBar($i, 'default', 'default','default', Console::getColumns() - 26, Console::text('.', 'yellow'), Console::text('#', 'green'), false).Console::text(' ]', 'yellow'); + Console::overwrite($apt3); + usleep($introDelay / 4); + } + Console::overwrite($apt4); + + usleep($introDelay * random_int(2, 3)); + Console::log($apt5); + for ($i=1 ; $i<=100 ; $i++) { + $apt5 = Console::text(' importing new galaxy [ ', 'yellow').Console::progressBar($i, 'default', 'default','default', Console::getColumns() - 26, Console::text('.', 'yellow'), Console::text('!', 'red'), false).Console::text(' ]', 'yellow'); + Console::overwrite($apt5); + usleep($introDelay / 5 ); + } + Console::overwrite($apt6); + + $magicTime = $printAll ? 122000 : false; + + Console::log(' '.Console::text("- CRITICAL FAILURE -", 'yellow', 'red')); + usleep($magicTime ?? 556000); + Console::overwrite(Console::text(" just kidding ...", 'yellow')); + usleep($magicTime ?? 9155000); + Console::overwrite(Console::text(" demo complete", 'green')); + usleep($magicTime ?? 1355000); + Console::overwrite(Console::text(" oh wait! I forgot something πŸ€”", 'yellow')); + usleep($magicTime ?? 1355000); + + if ($printAll) { + + Console::overwrite($fullRowString); + Console::log( + Console::text(" β†’", 'yellow').Console::text(' β†’ ', 'blue'). + Console::text(" β†’", 'yellow').Console::text(' β†’ ', 'blue'). + Console::text(" β†’", 'yellow').Console::text(' β†’ ', 'blue'). + Console::text(" β†’", 'yellow').Console::text(' β†’ ', 'blue'). + $swu. + Console::text(" ←", 'yellow').Console::text(' ← ', 'blue'). + Console::text(" ←", 'yellow').Console::text(' ← ', 'blue'). + Console::text(" ←", 'yellow').Console::text(' ← ', 'blue'). + Console::text(" ←", 'yellow').Console::text(' ← ', 'blue') + ); + usleep($introDelay * 10); + + Console::log(); + Console::log( Console::text(" also forgot to install Kr157uff-socials-links-2.0 package", 'yellow')); usleep(1355000); + Console::overwrite( Console::text(" Do you want to install Kr157uff-socials-links package? (634 Go)", 'yellow')); usleep(1355000); + Console::log( Console::text(" i readed in your mind and detected ", 'yellow').Console::text('YES OF COURSE', 'yellow').Console::text(" ...", 'yellow')); usleep($introDelay * 5); + Console::log( Console::text(" i never cheat ...", 'yellow')); usleep($introDelay * 5); + Console::log( Console::text(" okay sometimes ...", 'yellow')); + $socials = [ + ["name" => "Github", "user" => "kristuff ", "link" => "https://github.com/kristuff"], + ["name" => "Twitter", "user" => "@_kristuff ", "link" => "https://twitter.com/_kristuff"], + ["name" => "Mastodon", "user" => "@kristuff ", "link" => "https://infosec.exchange/@kristuff"], + ]; + + $aptLink = Console::text(' unpacking Kr157uff-social-links-2.0-prod-test [ ', 'yellow').Console::progressBar(0, 'default', 'default','default', Console::getColumns() - 56, '.', Console::text('#', 'green'), false).Console::text(' ]', 'yellow'); + Console::log(); + Console::log(); + Console::log(); + Console::log($aptLink); + Console::log(); + + $i = 0; + foreach ($socials as $social){ + $socialLog = Console::pad( + Console::text(' preparing to unpack ', 'yellow'). + Console::text('kristuff-'.$social['name'].'.deb', 'green'). + Console::text(' ...', 'yellow'), + Console::getColumns() - 12 + ) ; + $socialLog3 = Console::text( ' created symlink ', 'yellow'). + Console::text('/usr/bin/'.$social['user'], 'yellow'). + Console::text(' β†’ ', 'yellow'). + Console::text($social['link'], 'lightblue', 'underlined'); + + $socialLog2 = Console::text( ' unpacking ', 'yellow'). + Console::text('kristuff-'. $social['name'].'-prod-test~deb12u99', 'yellow'). + Console::text('-prod-test~deb12u99', 'green'). + Console::text(' ...', 'yellow'); + + + $aptLink = Console::text(' unpacking ', 'yellow'). + Console::text('kristuff-social-links_2.0-prod-test~deb12u99', 'yellow'). + Console::text(' [ ', 'yellow'). + Console::progressBar(round(($i+0.3)/(count($socials)*2)*100), 'default', 'default','default', Console::getColumns() - 64, '.', Console::text('#', 'green'), false).Console::text(' ]', 'yellow'); + + Console::overwrite([$fullRowString,$fullRowString]); + Console::overwrite([$socialLog, $socialLog2]); + Console::log($socialLog3); + Console::log(); + Console::log($aptLink); + usleep($introDelay * random_int(2, 4)); + + $i++; + $aptLink = Console::text(' unpacking ', 'yellow'). + Console::text('kristuff-social-links_2.0-prod-test~deb12u99', 'yellow'). + Console::text(' [ ', 'yellow'). + Console::progressBar(round($i+0.3/count($socials)*2*100), 'default', 'default','default', + Console::getColumns() - 64, '.', Console::text('#', 'green'), false). + Console::text(' ]', 'yellow'); + usleep($introDelay * random_int(2, 4)); + Console::overwrite([$fullRowString,$fullRowString]); + Console::overwrite([' ', $aptLink]); + $i++; + } + + $aptLink = Console::text(' unpacking ', 'yellow'). + Console::text('kristuff-social-links_2.0-prod-test~deb12u99', 'yellow'). + Console::text(' [ ', 'yellow'). + Console::progressBar(100, 'default', 'default','default', + Console::getColumns() - 64, '.', Console::text('#', 'green'), false). + Console::text(' ]', 'yellow'); + + Console::overwrite($aptLink); + usleep($introDelay * random_int(10, 50)); + + Console::overwrite(Console::pad('', Console::getColumns())); + $aptLink = Console::text(' unpacking ', 'yellow'). + Console::text('kristuff-social-links_2.0-prod-test~deb12u99', 'yellow'). + Console::text(' completed ... ', 'yellow'). + + Console::overwrite($fullRowString); + Console::log($aptLink); + Console::log(); + Console::log(Console::text(" _ _ _ _ ", 'yellow').Console::text(' ', 'yellow').Console::text('', 'green') ); + Console::log(Console::text(" _ __ (_)__| |_ ___| | | ", 'yellow').Console::text(' ', 'yellow').Console::text('', 'green') ); + Console::log(Console::text(" | ' \| (_-< ' \/ -_) | | ", 'yellow').Console::text(' ', 'yellow').Console::text('', 'green') ); + Console::log(Console::text(" |_|_|_|_/__/_||_\___|_|_| ", 'yellow').Console::text('By ', 'yellow').Console::text("kr157uff", 'green') ); + Console::log(' '.Console::text("-----------------------------------------------------------------", "green")); + Console::log(' '.Console::text("kr157uff/mishell: A mini PHP library to build CLI app and reports", "green")); + Console::log(' '.Console::text('Made with ', 'green') . Console::text('β™₯', 'red'). + Console::text(' in France', 'green'). + Console::text(" | Β© 2017-2024 kri157uff", "green")); + Console::log(' '.Console::text("-----------------------------------------------------------------", "green")); + Console::log(); + usleep(1200000); + usleep($introDelay * random_int(10, 50)); + Console::log(); + Console::log(Console::text(" If you don't have the time to read, you can replay this intro slowwwly. Hura!", 'yellow')); + Console::log(); + + } + + usleep($introDelay * random_int(20, 40)); + Console::restoreWindow(); + } -function getIndex() +function standWithUkraine($msg1, $msg2, $delay = 2000000) { - $index = []; - - $index[1] = ['Styles', 'How to get available basic styles', 'demo.styles.php']; - $index[2] = ['Colors', 'How to get available foreground colors', 'demo.colors.php']; - $index[3] = ['Backgrounds', 'How to get available background colors', 'demo.bgcolors.php']; -// $index[4] = ['Text', 'Console::text() overview', 'demo.log.php']; -// $index[5] = ['Log', 'Console::log() overview', 'demo.log.php']; -// $index[6] = ['ReLog', 'Console::relog() overview', 'demo.relog.php']; - $index[7] = ['Pad', 'Console::pad() overview', 'demo.pad.php']; - $index[8] = ['Size', 'How to get the number of columns and lines in terminal', 'demo.size.php']; + // *open* new window + Console::newWindow(); + + // get columns / lines and calculate middle + $lines = Console::getLines(); + $cols = Console::getColumns(); + $middle = round($lines/2); + + for ($i= 1; $i <= $lines ; $i++){ + + switch($i){ + case $middle -1: + Console::log(Console::pad($msg1, $cols, ' ', STR_PAD_BOTH), 'yellow', 'blue'); + break; + case $middle: + Console::log(Console::pad(' ', $cols, ' ', STR_PAD_BOTH), 'yellow', 'blue'); + break; + case $middle +1: + Console::log(Console::pad(' ', $cols, ' ', STR_PAD_BOTH), 'blue', 'yellow'); + break; + case $middle +2: + Console::log(Console::pad($msg2, $cols, ' ', STR_PAD_BOTH), 'blue', 'yellow'); + break; + case $lines: + Console::relog(Console::pad('Please wait a moment ', $cols, ' ', STR_PAD_LEFT), 'blue', 'yellow'); + break; + + default: + if ($i > $middle) { + Console::log(Console::pad(' ', $cols), 'blue', 'yellow'); + } else { + Console::log(Console::pad(' ', $cols), 'yellow', 'blue'); + } + } + } - $index[11] = ['Ask', 'How to ask? (get user input)', 'demo.ask.php']; - $index[12] = ['Ask Number', 'How to ask and expect a number?', 'demo.askint.php']; - $index[13] = ['Ask Password', 'How to ask a password? (do not print user input)', 'demo.askpassword.php']; - - $index[14] = ['Table', 'How to print a table?', 'demo.table.php']; - $index[15] = ['Bell', 'How to run the bell?', 'demo.bell.php']; - $index[16] = ['Progress', 'How to output progress message?', 'demo.progress.php']; - $index[17] = ['New window', 'How to open new/restore window?', 'demo.window.php']; + usleep($delay); + // restore previous window + Console::restoreWindow(); +} - $index[20] = ['BlueScreen', 'Really nice full screen centered message sample', 'demo.bluescreen.php']; +function getIndex() +{ + $index = []; + $new = Console::text("NEW", 'green', 'blink'); + + $index[99] = ['Quit ', 'Quit and *restore* my terminal ' , '']; + $index[1] = ['Styles ', 'How to get basic styles ' , 'demo.styles.php ' , '']; + $index[2] = ['Colors ', 'How to get foreground colors ' , 'demo.colors.php ' , '']; + $index[3] = ['Backgrounds ', 'How to get background colors ' , 'demo.bgcolors.php ' , '']; + $index[7] = ['Pad ', 'How to get padded string ' .Console::text( ' Console::pad() ' , 'lightblue' ). 'overview' , 'demo.pad.php', '']; + $index[8] = ['Size ', 'How to get lines/columns number ' , 'demo.size.php ' , '']; + $index[11] = ['Ask ', 'How to ask? (get user input) ' , 'demo.ask.php ' , '']; + $index[12] = ['Ask Number ', 'How to ask and expect a number? ' , 'demo.askint.php ' , '']; + $index[13] = ['Ask Password ', 'How to ask and hide input ' , 'demo.askpassword.php ' , '']; + $index[14] = ['Table ', 'How to print a table? ' , 'demo.table. php ' , '']; + $index[15] = ['Bell ', 'How to run the bell? ' , 'demo.bell.ph p ' , '']; + $index[16] = ['Progress (1) ', 'How to print progress message? ' .Console::text( ' Console::relog() ' , 'lightblue' ). 'overview' , 'demo.progress.php', '']; + $index[17] = ['Progress (2) ', 'How to print progress message? ' .Console::text( ' Console::overwrite() ' , 'lightblue' ). 'basic usage '.$new, 'demo.progress2.php', '']; + $index[18] = ['Progress (3) ', 'How to print progress message? ' .Console::text( ' Console::overwrite() ' , 'lightblue' ). 'advanced usage '.$new, 'demo.progress3.php', '']; + $index[19] = ['New window ', 'How to open new/restore window? ' , 'demo.window.php ' , '']; + $index[80] = ['BlueScreen ', 'How to print blue screen ' .Console::text( ' Console::BUG(?)', 'yellow').' OLD && ' .$new , 'demo.bluescreen.php' , '']; + $index[90] = ['Loader ', 'Replay the loader ' .Console::text( ' RealTimeβ„’v2.0 ' , 'yellow ', 'blue') . ' ' .$new, '']; + $index[91] = ['Loader ', 'Replay the loader (more slowly) ' .Console::text( ' SLOOOOW! ', 'black', 'yellow'). ' ' .$new , '']; + $index[92] = ['Loader ', 'Replay the loader (very slowly) ' .Console::text( ' SLOOOOOOOOOOOOW! ', 'yellow', 'red' ). ' ' .$new , '']; + $index[800] = ['lifeA ', 'How to print " I love life " ' .Console::text( ' 5tandWith', 'yellow' , 'blue').Console::text('Ukraine', 'blue', 'yellow'). ' '.$new , '', '']; + $index[801] = ['lifeB ', 'How to print " I love life " ' .Console::text( ' 5tandWith', 'yellow' , 'blue').Console::text('Ukraine', 'blue', 'yellow'). ' '.$new , '', '']; + $index[802] = ['lifeC ', 'How to print " I love life " ' .Console::text( ' 5tandWith', 'yellow' , 'blue').Console::text('Ukraine', 'blue', 'yellow'). ' '.$new , '', '']; + $index[803] = ['lifeE ', 'How to print " I love life " ' .Console::text( ' 5tandWith', 'yellow' , 'blue').Console::text('Ukraine', 'blue', 'yellow'). ' '.$new , '', '']; + $index[804] = ['lifeF ', 'How to print " I love life " ' .Console::text( ' 5tandWith', 'yellow' , 'blue').Console::text('Ukraine', 'blue', 'yellow'). ' '.$new , '', '']; + $index[805] = ['lifeG ', 'How to print " I love life " ' .Console::text( ' 5tandWith', 'yellow' , 'blue').Console::text('Ukraine', 'blue', 'yellow'). ' '.$new , '', '']; + $index[807] = ['lifeH ', 'How to print " I love life " ' .Console::text( ' 5tandWith', 'yellow' , 'blue').Console::text('Ukraine', 'blue', 'yellow'). ' '.$new , '', '']; + $index[808] = ['lifeI ', 'How to print " I love life " ' .Console::text( ' 5tandWith', 'yellow' , 'blue').Console::text('Ukraine', 'blue', 'yellow'). ' '.$new , '', '']; + $index[809] = ['lifeJ ', 'How to print " I love life " ' .Console::text( ' 5tandWith', 'yellow' , 'blue').Console::text('Ukraine', 'blue', 'yellow'). ' '.$new , '', '']; + $index[810] = ['lifeK ', 'How to print " I love life " ' .Console::text( ' 5tandWith', 'yellow' , 'blue').Console::text('Ukraine', 'blue', 'yellow'). ' '.$new , '', '']; + $index[811] = ['lifeL ', 'How to print " I love life " ' .Console::text( ' 5tandWith', 'yellow' , 'blue').Console::text('Ukraine', 'blue', 'yellow'). ' '.$new , '', '']; + $index[812] = ['lifeMNO ', 'How to print " I love life " ' .Console::text( ' 5tandWith', 'yellow' , 'blue').Console::text('Ukraine', 'blue', 'yellow'). ' '.$new , '', '']; + $index[822] = ['lifePQ ', 'How to print " I love life " ' .Console::text( ' 5tandWith', 'yellow' , 'blue').Console::text('Ukraine', 'blue', 'yellow'). ' '.$new , '', '']; + $index[844] = ['lifeR ', 'How to print " I love life " ' .Console::text( ' 5tandWith', 'yellow' , 'blue').Console::text('Ukraine', 'blue', 'yellow'). ' '.$new , '', '']; + $index[888] = ['lifeNOSS ', 'How to print " I love life " ' .Console::text( ' 5tandWith', 'yellow' , 'blue').Console::text('Ukraine', 'blue', 'yellow'). ' '.$new , '', '']; + $index[869] = ['lifeTHE-TEA ', 'How to print " I love life " ' .Console::text( ' 5tandWith', 'yellow' , 'blue').Console::text('Ukraine', 'blue', 'yellow'). ' '.$new , '', '']; + $index[870] = ['lifeUV-SOL-AIR ', 'How to print " I love life " ' .Console::text( ' 5tandWith', 'yellow' , 'blue').Console::text('Ukraine', 'blue', 'yellow'). ' '.$new , '', '']; + $index[890] = ['lifeW ', 'How to print " I love life " ' .Console::text( ' 5tandWith', 'yellow' , 'blue').Console::text('Ukraine', 'blue', 'yellow'). ' '.$new , '', '']; + $index[899] = ['lifeXYQ ', 'How to print " I love life " ' .Console::text( ' 5tandWith', 'yellow' , 'blue').Console::text('Ukraine', 'blue', 'yellow'). ' '.$new , '', '']; + $index[81] = ['life. ', 'How to print " I love life " ' .Console::text( ' 5tandWith', 'yellow' , 'blue').Console::text('Ukraine', 'blue', 'yellow'). ' '.$new , 'demo.standwithukraine.php', '']; return $index; } -function printHeader() +function printHeader($title = '', $demoPart = false) { - Console::clear(); - Console::log(); - Console::log(Console::text(' Kristuff/Mishell ', 'darkgray') . Console::text(' v1.2 ', 'white', 'green')); - Console::log(Console::text(' Made with ', 'darkgray') . Console::text('β™₯', 'red') . Console::text(' in France', 'darkgray')); - Console::log( - Console::text(' Β© 2017-2021 Kristuff (', 'darkgray') . - Console::text('https://github.com/kristuff)', 'darkgray', 'underlined') . - Console::text(')', 'darkgray') + Console::log(Console::text(" _ _ _ _ ", 'yellow')); + Console::log(Console::text(" _ __ (_)__| |_ ___| | | ", 'yellow').Console::text(' Kr157uff/Mishell ', 'green') . Console::text(' v1.6 ', 'yellow', 'blue'). ' '. Console::text(' StandWith ', 'yellow', 'blue')); + Console::log(Console::text(" | ' \| (_-< ' \/ -_) | | ", 'yellow').Console::text(' Made with ', 'green') . Console::text('β™₯', 'red') . Console::text(' in France', 'green'). ' '.Console::text(' Ukraine ', 'blue', 'yellow')); + Console::log(Console::text(" |_|_|_|_/__/_||_\___|_|_| ", 'yellow'). + Console::text(' Β© 2017-2024 Kr157uff (', 'green') . + Console::text('https://github.com/kristuff', 'green', 'underlined') . + Console::text(')', 'green') ); + Console::log(); - Console::log(' '.Console::text(' Interactive sample ', 'white', 'blue', 'bold')); - Console::log(); + $demoTitle = Console::pad(' Mishell Interactive Sample - '.$title. ' ', 108, ' ', STR_PAD_BOTH); + Console::log(Console::text(' β”Œ'.Console::pad('', 108, '─').'┐', 'yellow')); + Console::log(Console::text(' β”‚'.$demoTitle.'β”‚', 'yellow')); + + if ($demoPart){ + Console::log(Console::text(' β””'.Console::pad('', 108, '─').'β”˜', 'yellow')); + Console::log(); + } } function printSampleHeader($index, $title) { - Console::log(' ' . Console::text(' - '. $index .' - ' . $title . ' ', 'white', 'blue')); + Console::log(' ' . Console::text(' - '. $index .' - ' . $title . ' ', 'yellow', 'blue')); Console::log(); } function printIndex() { - $rowHeaders = ['Index' => 6, 'Item' => 15, 'Description' => 55]; + $rowHeaders = [ + 'Index' => 5, + 'Item' => 20, + 'Description' => 75 + ]; $i = 0; // customize table separator - Console::$horizontalSeparator = '-'; - Console::$verticalSeparator = ' '; - Console::$verticalInnerSeparator = ' '; + Console::$horizontalSeparator = '─'; + Console::$verticalSeparator = Console::text('β”‚', 'yellow'); + Console::$verticalInnerSeparator = ' '; Console::$tableCellPadding = ' '; + + $line = Console::text(' β”œ', 'yellow'); + $isFirst = true; + foreach ($rowHeaders as $column => $pad){ + $line .= $isFirst ? '': Console::text('┬', 'yellow'); + $line .= Console::text(Console::pad('', $pad+2, '─'), 'yellow'); + $isFirst = false; + } + $line .= Console::text('─', 'yellow'); + Console::log($line); - Console::log(''.Console::tableRowSeparator($rowHeaders, 'darkgray')); - Console::log(''.Console::tableRow($rowHeaders, 'darkgray')); - Console::log(''.Console::tableRowSeparator($rowHeaders, 'darkgray')); - Console::log(); + $isFirst = true; + $line = Console::text(' β”‚', 'yellow'); + foreach ($rowHeaders as $column => $pad){ + $line .= $isFirst ? '': Console::text('β”‚', 'yellow'); + $line .= Console::text(Console::pad(' '.$column. ' ', $pad +2), 'yellow'); + $isFirst = false; + } + $line .= Console::text('β”‚', 'yellow'); + Console::log($line); + + + $isFirst = true; + $line = Console::text(' β”œ', 'yellow'); + foreach ($rowHeaders as $column => $pad){ + $line .= $isFirst ? '': Console::text('β”Ό', 'yellow'); + $line .= Console::text(Console::pad('', $pad+2, '─'), 'yellow'); + $isFirst = false; + } + $line .= Console::text('─', 'yellow'); + + Console::log($line); foreach (getIndex() as $key => $value){ if (file_exists( __DIR__ . '/'. $value[2])) { - Console::log(''. + Console::log(' '. Console::TableRowStart(). - Console::TableRowCell(Console::text($key,'lightgray'), 6, Console::ALIGN_CENTER). //no align => default is left - Console::TableRowCell(Console::text($value[0], 'lightgray'), 15). - Console::TableRowCell(Console::text($value[1], 'lightgray'), 55) + Console::text(Console::TableRowCell($key, 5, Console::ALIGN_CENTER),'green'). + Console::text(Console::TableRowCell($value[0], 20),'green'). // no alignment set => default is left + Console::text(Console::TableRowCell($value[1], 75),'green') ); $i++; } } - Console::log(''); - Console::log(''.Console::tableRowSeparator($rowHeaders, 'darkgray')); + + $isFirst = true; + $line = Console::text(' β””', 'yellow'); + foreach ($rowHeaders as $column => $pad){ + $line .= $isFirst ? '': Console::text('β”΄', 'yellow'); + $line .= Console::text(Console::pad('', $pad+2, '─'), 'yellow'); + $isFirst = false; + } + $line .= Console::text('β”˜', 'yellow'); + + Console::log($line); Console::log(''); Console::log(' '. Console::text('Tips:', 'underlined', 'bold')); - Console::log(' '. Console::text(' - At any time you can stop this program using [') .Console::text('Ctrl+C', 'green') .Console::text(']')); + Console::log(' '. Console::text(' - At any time you can stop this program using [') .Console::text('Ctrl+C', 'green') .Console::text('] ')); Console::log(''); // reset table separators to defaults Console::resetDefaults(); } + +function splash() +{ + // magical stuff + Console::newWindow(); + + // get columns / lines and calculate middle + $lines = Console::getLines(); + $cols = Console::getColumns(); + $middle = round($lines/2); + + for ($i= 1; $i <= $lines ; $i++){ + switch($i){ + case $middle -1: Console::log(Console::pad("Stand With Ukraine <3", $cols, ' ', STR_PAD_BOTH), 'yellow', 'blue'); break; + case $middle: Console::log(Console::pad(' ', $cols, ' ', STR_PAD_BOTH), 'yellow', 'blue'); break; + case $middle +1: Console::log(Console::pad(' ', $cols, ' ', STR_PAD_BOTH), 'blue', 'yellow'); break; + case $middle +2: Console::log(Console::pad('Slava Ukraini', $cols, ' ', STR_PAD_BOTH), 'blue', 'yellow'); break; + case $lines: Console::print(Console::pad(' Wait a few seconds or hint Ctrl+C', $cols , ' ', STR_PAD_LEFT), 'blue', 'yellow'); break; // no new line here + default: + if ($i > $middle) { + Console::log(Console::pad(' ', $cols), 'blue', 'yellow'); + } else { + Console::log(Console::pad(' ', $cols), 'yellow', 'blue'); + } + } + } + + // magical stuff.. + usleep(74442); + + // restore previous window + Console::restoreWindow(); + +} + + function askIndex() { - $base = Console::text(' kristuff/mishell-demo' , 'yellow'); + $base = Console::text(' Kr157uff/mishell-demo' , 'yellow'); $base .= Console::text('~$ ' , 'gray'); - $selectedIndex = Console::askInt($base . Console::text(' Enter desired index then press [Enter] to run sample > ', 'white')); + $selectedIndex = Console::askInt($base . Console::text(' Enter desired index then press [Enter] to run sample > ', 'yellow')); $index = getIndex(); switch($selectedIndex){ + case 90: + splash(); + printLoader(100000); + splash(); + goIndex(); + break; + case 91: + splash(); + splash(); + printLoader(275000); + splash(); + goIndex(); + break; + + case 92: + splash(); + splash(); + splash(); + printLoader(575000); + splash(); + goIndex(); + break; + + + case 99: + //Console::clear(); + Console::restoreWindow(); + break; case 0: Console::log(); // Console::restoreWindow(); @@ -151,50 +600,71 @@ function askIndex() break; default: + + if ($selectedIndex >= 800){ + splash(); + splash(); + splash(); + Console::clear(); + goIndex(); + break; + } + if (array_key_exists($selectedIndex, getIndex())) { - $title = $index[$selectedIndex][0]; - $fileName = $index[$selectedIndex][2]; - $filePath = __DIR__ . '/'. $fileName; - + $title = $index[$selectedIndex][0]; + $fileName = $index[$selectedIndex][2]; + $samplefileName = $index[$selectedIndex][3]; + $filePath = __DIR__ . '/'. $fileName; + $samplefilePath = __DIR__ . '/'. $samplefileName; + Console::clear(); - printHeader(); - printSampleHeader($selectedIndex, $title); + printHeader($title, true); + //printSampleHeader($selectedIndex, $title); - Console::log($base . Console::text('Start running [', 'white') . + Console::log($base . Console::text('Start running sample index [', 'yellow') . + Console::text( $selectedIndex, 'lightcyan') . + Console::text(']', 'yellow')); + + Console::log($base . Console::text('Loading sample [', 'yellow') . Console::text( $title, 'lightcyan') . - Console::text('] in file [', 'white') . + Console::text('] in file [', 'yellow') . Console::text( $fileName, 'lightcyan') . - Console::text(']', 'white')); + Console::text(']', 'yellow')); if (file_exists($filePath)){ - Console::log(); + //Console::log(); include $filePath; - Console::log(); - Console::log($base . Console::text('End running [', 'white') . + + if (!empty($samplefileName) && file_exists($samplefilePath)){ + include $samplefilePath; + $filePath = $samplefilePath; + } + //Console::log(); + Console::log($base . Console::text('End running [', 'yellow') . Console::text( $title, 'lightcyan') . - Console::text(']', 'white')); + Console::text(']', 'yellow')); - $response = Console::ask($base . Console::text('Do you want to see the code that has been executed? (type y/Y to see the code) > ', 'white')); + $response = Console::ask($base . Console::text('Do you want to see the code that has been executed? (type y/Y to see the code) > ', 'yellow')); if (strtoupper($response) === 'Y') { - Console::log($base . Console::text('The code in file [', 'white') . + Console::log($base . Console::text('The code in file [', 'yellow') . Console::text( $fileName, 'lightcyan') . - Console::text('] is:', 'white')); + Console::text('] is:', 'yellow')); Console::log(); $lines = file($filePath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); $count = 1; - Console::log(Console::pad(' ', 100, '-'), 'darkgray'); + Console::log(Console::pad(' ', 100, '-'), 'green'); foreach($lines as $line){ $codeLine = rtrim($line); $isComment = substr(ltrim($codeLine), 0, 2) === '//'; $isPhp = substr(ltrim($codeLine), 0, 5) === ''; - $color = $isPhp ? 'blue' : ($isComment ? 'green' : 'lightgray'); + $color = $isPhp ? 'blue' : ($isComment ? 'green' : 'green'); Console::log(' '. Console::text($codeLine, $color)); $count++; } - Console::log(Console::pad(' ', 100, '-'), 'darkgray'); + Console::log(Console::pad(' ', 100, '-'), 'green'); Console::log(); } } else { @@ -208,7 +678,7 @@ function askIndex() askIndex(); } - Console::ask($base . Console::text('Press [Enter] to go back to index > ', 'white')); + Console::ask($base . Console::text('Press [Enter] to go back to index > ', 'yellow')); goIndex(); } } \ No newline at end of file diff --git a/doc/screenshots/README.md b/doc/screenshots/README.md new file mode 100644 index 0000000..2c36cd6 --- /dev/null +++ b/doc/screenshots/README.md @@ -0,0 +1,10 @@ + +# Mishell + +> A mini PHP library to build beautiful CLI apps and reports + +- 480 ![sample](doc/screenshots/helloworld-480.mp4) + +- 720 ![sample](doc/screenshots/helloworld-720.mp4) + +- 1080 ![sample](doc/screenshots/helloworld-1080.mp4) diff --git a/doc/screenshots/blue-screen-1.5.9.png b/doc/screenshots/blue-screen-1.5.9.png new file mode 100644 index 0000000..2a8201c Binary files /dev/null and b/doc/screenshots/blue-screen-1.5.9.png differ diff --git a/doc/screenshots/demo.gif b/doc/screenshots/demo.gif deleted file mode 100644 index 095d266..0000000 Binary files a/doc/screenshots/demo.gif and /dev/null differ diff --git a/doc/screenshots/helloworld-1080.mp4 b/doc/screenshots/helloworld-1080.mp4 new file mode 100644 index 0000000..ba88d98 Binary files /dev/null and b/doc/screenshots/helloworld-1080.mp4 differ diff --git a/doc/screenshots/helloworld-480.mp4 b/doc/screenshots/helloworld-480.mp4 new file mode 100644 index 0000000..266ff19 Binary files /dev/null and b/doc/screenshots/helloworld-480.mp4 differ diff --git a/doc/screenshots/helloworld-720.mp4 b/doc/screenshots/helloworld-720.mp4 new file mode 100644 index 0000000..251047e Binary files /dev/null and b/doc/screenshots/helloworld-720.mp4 differ diff --git a/doc/screenshots/mishell-demo.mp4 b/doc/screenshots/mishell-demo.mp4 new file mode 100644 index 0000000..95ca924 Binary files /dev/null and b/doc/screenshots/mishell-demo.mp4 differ diff --git a/doc/screenshots/mishell1.6.png b/doc/screenshots/mishell1.6.png new file mode 100644 index 0000000..2731345 Binary files /dev/null and b/doc/screenshots/mishell1.6.png differ diff --git a/lib/Console.php b/lib/Console.php index cb8436c..f104582 100644 --- a/lib/Console.php +++ b/lib/Console.php @@ -1,22 +1,19 @@ + * (c) Kr1s7uff For the full copyright and license information, + * please view the LICENSE file that was distributed with this + * source code. * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * @version 1.5.0 - * @copyright 2017-2021 Kristuff + * @version 1.6.2 + * @copyright 2017-2024 Kr157uff */ - namespace Kristuff\Mishell; class Console extends \Kristuff\Mishell\ShellTablePrinter diff --git a/lib/Program.php b/lib/Program.php index c81c8c4..e84f662 100644 --- a/lib/Program.php +++ b/lib/Program.php @@ -1,21 +1,20 @@ + * (c) Kr1s7uff For the full copyright and license information, + * please view the LICENSE file that was distributed with this + * source code. * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * @version 1.5.0 - * @copyright 2017-2021 Kristuff + * @version 1.6.2 + * @copyright 2017-2024 Kr157uff */ +declare(ticks = 1); // Allow posix signal handling namespace Kristuff\Mishell; diff --git a/lib/ShellColoredPrinter.php b/lib/ShellColoredPrinter.php index 6e8a777..f2013b1 100644 --- a/lib/ShellColoredPrinter.php +++ b/lib/ShellColoredPrinter.php @@ -1,20 +1,18 @@ + * (c) Kr1s7uff For the full copyright and license information, + * please view the LICENSE file that was distributed with this + * source code. * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * @version 1.5.0 - * @copyright 2017-2021 Kristuff + * @version 1.6.2 + * @copyright 2017-2024 Kr157uff */ namespace Kristuff\Mishell; @@ -89,9 +87,6 @@ abstract class ShellColoredPrinter extends \Kristuff\Mishell\ShellPrinter 'underlined' => '4', 'blink' => '5', 'reverse' => '7', // reverse foreground/background color - - //formats=(["bold"]=1 ["bright"]=1 ["dim"]=2 ["underlined"]=4 ["blink"]=5 ["reverse"]=7 ["hidden"]=8) - //resets=(["all"]=0 ["bold"]=21 ["bright"]=21 ["dim"]=22 ["underlined"]=24 ["blink"]=25 ["reverse"]=27 ["hidden"]=28) ); /** @@ -116,14 +111,14 @@ public static function getStyles() * * @access protected * @static - * @param string $command The command name string - * @param string $args The command arguments + * @param string $command The command name string + * @param array $args The command arguments * * @return mixed|void */ protected static function cmd($command, array $args) { - // ouptut string is always the first argument (in any) + // ouptut string is always the first argument (if any) $str = !empty($args) ? $args[0] : ''; // others (if any) are options @@ -146,11 +141,24 @@ protected static function cmd($command, array $args) case'print': echo (self::getCliString($str, $args)); // print text break; + case'log': echo (self::getCliString($str, $args) . self::$EOF ); // print text + newline break; + case'relog': - echo (self::getCliString($str ."\r", $args)); // overwrite current line + // overwrite last line (cursor stays at the beginning) + echo (self::getCliString($str ."\r", $args)); + break; + + case'overwrite': + // Overwrite last x printed line (add trailing new lines) + // text could be one line string, or array of lines + $text = is_array($str) ? implode(PHP_EOL, $str) : $str; + $overwriteIndex = is_array($str) ? count($str) : 1; + // https://stackoverflow.com/questions/11283625/overwrite-last-line-on-terminal + echo ("\033[". $overwriteIndex ."A\033[K".self::getCliString($text, $args).self::$EOF); + break; // ***************************************** @@ -177,14 +185,36 @@ protected static function cmd($command, array $args) // nothing found return null; } - + + + + + + public static function progressBar( + $percent, + $color, + $bgcolor, + $background = 'darkgray', + $progressLenght = 40, + $pendingSign = ' ', + $progressSign = ' ', + $withPurcent = true + ){ + $perc = min(100,$percent); + $start = round($progressLenght * $perc / 100); + + return ($withPurcent ? Console::text(Console::pad($perc . '% ', 5, ' ', STR_PAD_LEFT), $color) : ''). + Console::text(Console::pad('', $start, $progressSign), 'white', $bgcolor) . + Console::text(Console::pad('', $progressLenght - $start, $pendingSign), 'black', $background) ; + } + /** * Get a formatted cli string to output in the console * * @access protected * @static - * @param string $str The text to output - * @param string $arguments The command arguments + * @param string $str The text to output + * @param string $arguments The command arguments * * @return mixed|void */ @@ -226,14 +256,14 @@ protected static function getCliString(string $str, array $arguments = []) } /** - * Get a formatted string to be returned in console. + * Get a formatted string to be returned in terminal. * * @access public * @static - * @param string [$str] The string to output - * @param string [$color] The text color for the wall line - * @param string [$bgcolor] The back color for the wall line - * @param string [$option]+... The text styles for the wall line + * @param string [$str] The string to output + * @param string [$color] The text color for the wall line + * @param string [$bgcolor] The back color for the wall line + * @param string [$option]+... The text styles for the wall line * * @return string */ @@ -243,20 +273,20 @@ public static function text() } /** - * Print a formatted string in console. + * Print a formatted string in terminal. * * @access public * @static - * @param string [$str] The string to print - * @param string [$color] The text color for the wall line - * @param string [$bgcolor] The back color for the wall line - * @param string [$option]+... The text styles for the wall line + * @param string [$str] The string to print + * @param string [$color] The text color for the wall line + * @param string [$bgcolor] The back color for the wall line + * @param string [$option]+... The text styles for the wall line * * @return void */ public static function print() { - return self::cmd('write', func_get_args()); + return self::cmd('print', func_get_args()); } /** @@ -264,10 +294,10 @@ public static function print() * * @access public * @static - * @param string [$str] The string to print - * @param string [$color] The text color for the wall line - * @param string [$bgcolor] The back color for the wall line - * @param string [$option]+... The text styles for the wall line + * @param string [$str] The string to print + * @param string [$color] The text color for the wall line + * @param string [$bgcolor] The back color for the wall line + * @param string [$option]+... The text styles for the wall line * * @return string|null */ @@ -281,10 +311,10 @@ public static function ask() * * @access public * @static - * @param string [$str] The string to print - * @param string [$color] The text color for the wall line - * @param string [$bgcolor] The back color for the wall line - * @param string [$option]+... The text styles for the wall line + * @param string [$str] The string to print + * @param string [$color] The text color for the wall line + * @param string [$bgcolor] The back color for the wall line + * @param string [$option]+... The text styles for the wall line * * @return int|bool */ @@ -296,10 +326,10 @@ public static function askInt() /** * Prints a formatted string in the console then waits for a user input (returns but does not displays that user's input). * - * @param string [$str] The string to print - * @param string [$color] The text color for the wall line - * @param string [$bgcolor] The back color for the wall line - * @param string [$option]+... The text styles for the wall line + * @param string [$str] The string to print + * @param string [$color] The text color for the wall line + * @param string [$bgcolor] The back color for the wall line + * @param string [$option]+... The text styles for the wall line * * @return string|null */ @@ -313,10 +343,10 @@ public static function askPassword() * * @access public * @static - * @param string [$str] The string to print - * @param string [$color] The text color for the wall line - * @param string [$bgcolor] The back color for the wall line - * @param string [$option]+... The text styles for the wall line + * @param string [$str] The string to print + * @param string [$color] The text color for the wall line + * @param string [$bgcolor] The back color for the wall line + * @param string [$option]+... The text styles for the wall line * * @return void */ @@ -326,14 +356,14 @@ public static function log() } /** - * Overwrite the current line in console. + * Overwrite the current line in terminal. (cursor stays at the beginning) * * @access public * @static - * @param string [$str] The string to print - * @param string [$color] The text color for the wall line - * @param string [$bgcolor] The back color for the wall line - * @param string [$option]+... The text styles for the wall line + * @param string [$str] The string to print + * @param string [$color] The text color for the wall line + * @param string [$bgcolor] The back color for the wall line + * @param string [$option]+... The text styles for the wall line * * @return void */ @@ -341,16 +371,33 @@ public static function relog() { self::cmd('relog',func_get_args()); } - + + /** + * Overwrite the current line in terminal. + * + * @access public + * @static + * @param string|array [$str] The string to print|array of lines + * @param string [$color] The text color for the wall line + * @param string [$bgcolor] The back color for the wall line + * @param string [$option]+... The text styles for the wall line + * + * @return void + */ + public static function overwrite() + { + self::cmd('overwrite',func_get_args()); + } + /** * A cli version of str_pad() that takes care of not printable ANSI chars * * @access protected * @static - * @param string $input The input text - * @param int $padLenght The pad length. Default is 0 (no pad) - * @param string $padString The pad string. Default is blank char. - * @param int $padType The pad type (STR_PAD_LEFT, STR_PAD_RIGHT or STR_PAD_BOTH). Default is STR_PAD_RIGHT. + * @param string $input The input text + * @param int $padLenght The pad length. Default is 0 (no pad) + * @param string $padString The pad string. Default is blank char. + * @param int $padType The pad type (STR_PAD_LEFT, STR_PAD_RIGHT or STR_PAD_BOTH). Default is STR_PAD_RIGHT. * * @return mixed|void */ diff --git a/lib/ShellPrinter.php b/lib/ShellPrinter.php index ce37812..7da273b 100644 --- a/lib/ShellPrinter.php +++ b/lib/ShellPrinter.php @@ -1,22 +1,19 @@ + * (c) Kr1s7uff For the full copyright and license information, + * please view the LICENSE file that was distributed with this + * source code. * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * @version 1.5.0 - * @copyright 2017-2021 Kristuff + * @version 1.6.2 + * @copyright 2017-2024 Kr157uff */ - namespace Kristuff\Mishell; abstract class ShellPrinter @@ -51,11 +48,13 @@ protected static function isWin() * * @return int */ - public static function getColumns() + public static function getColumns(): int { if (!self::isWin() ){ return (int) shell_exec('tput cols'); } + + return -1; } /** @@ -144,7 +143,7 @@ public static function restoreInput() */ public static function clear() { - //use 'cls' for Windows users or 'clear' for Linux users : + // use 'cls' for Windows users or 'clear' for Linux users : system(self::isWin() ? 'cls' : 'clear'); } } \ No newline at end of file diff --git a/lib/ShellTablePrinter.php b/lib/ShellTablePrinter.php index aa97fe2..e57e9ee 100644 --- a/lib/ShellTablePrinter.php +++ b/lib/ShellTablePrinter.php @@ -1,22 +1,19 @@ + * (c) Kr1s7uff For the full copyright and license information, + * please view the LICENSE file that was distributed with this + * source code. * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * @version 1.5.0 - * @copyright 2017-2021 Kristuff + * @version 1.6.2 + * @copyright 2017-2024 Kr157uff */ - namespace Kristuff\Mishell; abstract class ShellTablePrinter extends \Kristuff\Mishell\ShellColoredPrinter diff --git a/lib/TableStyle.php b/lib/TableStyle.php new file mode 100644 index 0000000..964fb07 --- /dev/null +++ b/lib/TableStyle.php @@ -0,0 +1,281 @@ + $pad){ + $str .= str_repeat(self::$horizontalSeparator , $pad + $cellPaddingLenght) .self::$verticalInnerSeparator; + } + + return self::getCliString(self::$verticalInnerSeparator === '' ? $str : substr($str, 0, mb_strlen($str) -1). self::$verticalSeparator, $args); + } + + /** + * Gets a formatted table row separator + * + * @access public + * @static + * @param string [$color] The text color for the wall row + * @param string [$bgcolor] The back color for the wall row + * @param string [$option]+... The text styles for the wall row + * + * @return string + */ + public static function tableSeparator() + { + $args = func_get_args(); + $columnsPads = !empty($args) ? $args[0] : []; + array_shift($args); + + $str = self::$verticalHeaderSeparator ; + $cellPaddingLenght = mb_strlen(self::$tableCellPadding) *2; + foreach ($columnsPads as $key => $pad){ + $str .= str_repeat(self::$horizontalSeparator , $pad + $cellPaddingLenght) .self::$verticalInnerSeparator ; + } + return self::getCliString(self::$verticalInnerSeparator === '' ? $str : substr($str, 0, mb_strlen($str) -1). self::$verticalHeaderSeparator, $args); + + } + + /** + * Gets a formatted table blank row + * + * @access public + * @static + * @param string [$color] The text color for the wall row + * @param string [$bgcolor] The back color for the wall row + * @param string [$option]+... The text styles for the wall row + * + * @return string + */ + public static function tableRowEmpty() + { + // get and parse arguments: + // - extract first argument (columns list) + // - keep following arguments (if exist) as styles + $args = func_get_args(); + $columnsPads = !empty($args) ? $args[0] : []; + array_shift($args); + + $str = self::$verticalSeparator ; + foreach ($columnsPads as $pad){ + $str .= self::$tableCellPadding. + str_pad(' ', $pad). + self::$tableCellPadding. + self::$verticalSeparator ; + } + return self::getCliString($str, $args); + } + + /** + * Return a table row start. + * + * @access public + * @static + * + * @return string + */ + public static function tableRowStart() + { + return self::$verticalSeparator; + } + + /** + * Return a table cell string. + * + * @access public + * @static + * @param string $column The column text. + * @param int $lenght The column length. Default is 0 (no pad) + * @param int $align The column alignement (Console::ALIGN_LEFT, Console::ALIGN_RIGHT or Console::ALIGN_CENTER). Default is Console::ALIGN_LEFT. + * + * @return string + */ + public static function tableRowCell($column, $length = 0, $align = self::ALIGN_LEFT) + { + return self::$tableCellPadding. + self::pad($column, $length, ' ', $align). + self::$tableCellPadding. + self::$verticalSeparator; + } + + /** + * Return a table row string. + * + * @access public + * @static + * @param array $columns The columns arrays. + * @param string [$color] The text color for the wall row + * @param string [$bgcolor] The back color for the wall row + * @param string [$option]+... The text styles for the wall row + * + * @return string + */ + public static function tableRow() + { + // get and parse arguments: + // - extract first argument (columns list) + // - keep following arguments (if exist) as styles + $args = func_get_args(); + $columns = !empty($args) ? $args[0] : []; + array_shift($args); + + // build the row string + // start with separator + $str = self::$verticalSeparator; + + // add columns + foreach ($columns as $column => $pad){ + $str .= self::$tableCellPadding. + self::pad($column, $pad). + self::$tableCellPadding. + self::$verticalSeparator; + } + + // format full row + return self::getCliString($str, $args) ; + } +} \ No newline at end of file diff --git a/tests/no.php b/tests/no.php new file mode 100644 index 0000000..d177e7c --- /dev/null +++ b/tests/no.php @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/vendor/autoload.php b/vendor/autoload.php new file mode 100644 index 0000000..ab23fb4 --- /dev/null +++ b/vendor/autoload.php @@ -0,0 +1,7 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Autoload; + +/** + * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. + * + * $loader = new \Composer\Autoload\ClassLoader(); + * + * // register classes with namespaces + * $loader->add('Symfony\Component', __DIR__.'/component'); + * $loader->add('Symfony', __DIR__.'/framework'); + * + * // activate the autoloader + * $loader->register(); + * + * // to enable searching the include path (eg. for PEAR packages) + * $loader->setUseIncludePath(true); + * + * In this example, if you try to use a class in the Symfony\Component + * namespace or one of its children (Symfony\Component\Console for instance), + * the autoloader will first look for the class under the component/ + * directory, and it will then fallback to the framework/ directory if not + * found before giving up. + * + * This class is loosely based on the Symfony UniversalClassLoader. + * + * @author Fabien Potencier + * @author Jordi Boggiano + * @see https://www.php-fig.org/psr/psr-0/ + * @see https://www.php-fig.org/psr/psr-4/ + */ +class ClassLoader +{ + /** @var ?string */ + private $vendorDir; + + // PSR-4 + /** + * @var array[] + * @psalm-var array> + */ + private $prefixLengthsPsr4 = array(); + /** + * @var array[] + * @psalm-var array> + */ + private $prefixDirsPsr4 = array(); + /** + * @var array[] + * @psalm-var array + */ + private $fallbackDirsPsr4 = array(); + + // PSR-0 + /** + * @var array[] + * @psalm-var array> + */ + private $prefixesPsr0 = array(); + /** + * @var array[] + * @psalm-var array + */ + private $fallbackDirsPsr0 = array(); + + /** @var bool */ + private $useIncludePath = false; + + /** + * @var string[] + * @psalm-var array + */ + private $classMap = array(); + + /** @var bool */ + private $classMapAuthoritative = false; + + /** + * @var bool[] + * @psalm-var array + */ + private $missingClasses = array(); + + /** @var ?string */ + private $apcuPrefix; + + /** + * @var self[] + */ + private static $registeredLoaders = array(); + + /** + * @param ?string $vendorDir + */ + public function __construct($vendorDir = null) + { + $this->vendorDir = $vendorDir; + } + + /** + * @return string[] + */ + public function getPrefixes() + { + if (!empty($this->prefixesPsr0)) { + return call_user_func_array('array_merge', array_values($this->prefixesPsr0)); + } + + return array(); + } + + /** + * @return array[] + * @psalm-return array> + */ + public function getPrefixesPsr4() + { + return $this->prefixDirsPsr4; + } + + /** + * @return array[] + * @psalm-return array + */ + public function getFallbackDirs() + { + return $this->fallbackDirsPsr0; + } + + /** + * @return array[] + * @psalm-return array + */ + public function getFallbackDirsPsr4() + { + return $this->fallbackDirsPsr4; + } + + /** + * @return string[] Array of classname => path + * @psalm-return array + */ + public function getClassMap() + { + return $this->classMap; + } + + /** + * @param string[] $classMap Class to filename map + * @psalm-param array $classMap + * + * @return void + */ + public function addClassMap(array $classMap) + { + if ($this->classMap) { + $this->classMap = array_merge($this->classMap, $classMap); + } else { + $this->classMap = $classMap; + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, either + * appending or prepending to the ones previously set for this prefix. + * + * @param string $prefix The prefix + * @param string[]|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories + * + * @return void + */ + public function add($prefix, $paths, $prepend = false) + { + if (!$prefix) { + if ($prepend) { + $this->fallbackDirsPsr0 = array_merge( + (array) $paths, + $this->fallbackDirsPsr0 + ); + } else { + $this->fallbackDirsPsr0 = array_merge( + $this->fallbackDirsPsr0, + (array) $paths + ); + } + + return; + } + + $first = $prefix[0]; + if (!isset($this->prefixesPsr0[$first][$prefix])) { + $this->prefixesPsr0[$first][$prefix] = (array) $paths; + + return; + } + if ($prepend) { + $this->prefixesPsr0[$first][$prefix] = array_merge( + (array) $paths, + $this->prefixesPsr0[$first][$prefix] + ); + } else { + $this->prefixesPsr0[$first][$prefix] = array_merge( + $this->prefixesPsr0[$first][$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, either + * appending or prepending to the ones previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param string[]|string $paths The PSR-4 base directories + * @param bool $prepend Whether to prepend the directories + * + * @throws \InvalidArgumentException + * + * @return void + */ + public function addPsr4($prefix, $paths, $prepend = false) + { + if (!$prefix) { + // Register directories for the root namespace. + if ($prepend) { + $this->fallbackDirsPsr4 = array_merge( + (array) $paths, + $this->fallbackDirsPsr4 + ); + } else { + $this->fallbackDirsPsr4 = array_merge( + $this->fallbackDirsPsr4, + (array) $paths + ); + } + } elseif (!isset($this->prefixDirsPsr4[$prefix])) { + // Register directories for a new namespace. + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } elseif ($prepend) { + // Prepend directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + (array) $paths, + $this->prefixDirsPsr4[$prefix] + ); + } else { + // Append directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + $this->prefixDirsPsr4[$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, + * replacing any others previously set for this prefix. + * + * @param string $prefix The prefix + * @param string[]|string $paths The PSR-0 base directories + * + * @return void + */ + public function set($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr0 = (array) $paths; + } else { + $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, + * replacing any others previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param string[]|string $paths The PSR-4 base directories + * + * @throws \InvalidArgumentException + * + * @return void + */ + public function setPsr4($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr4 = (array) $paths; + } else { + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } + } + + /** + * Turns on searching the include path for class files. + * + * @param bool $useIncludePath + * + * @return void + */ + public function setUseIncludePath($useIncludePath) + { + $this->useIncludePath = $useIncludePath; + } + + /** + * Can be used to check if the autoloader uses the include path to check + * for classes. + * + * @return bool + */ + public function getUseIncludePath() + { + return $this->useIncludePath; + } + + /** + * Turns off searching the prefix and fallback directories for classes + * that have not been registered with the class map. + * + * @param bool $classMapAuthoritative + * + * @return void + */ + public function setClassMapAuthoritative($classMapAuthoritative) + { + $this->classMapAuthoritative = $classMapAuthoritative; + } + + /** + * Should class lookup fail if not found in the current class map? + * + * @return bool + */ + public function isClassMapAuthoritative() + { + return $this->classMapAuthoritative; + } + + /** + * APCu prefix to use to cache found/not-found classes, if the extension is enabled. + * + * @param string|null $apcuPrefix + * + * @return void + */ + public function setApcuPrefix($apcuPrefix) + { + $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null; + } + + /** + * The APCu prefix in use, or null if APCu caching is not enabled. + * + * @return string|null + */ + public function getApcuPrefix() + { + return $this->apcuPrefix; + } + + /** + * Registers this instance as an autoloader. + * + * @param bool $prepend Whether to prepend the autoloader or not + * + * @return void + */ + public function register($prepend = false) + { + spl_autoload_register(array($this, 'loadClass'), true, $prepend); + + if (null === $this->vendorDir) { + return; + } + + if ($prepend) { + self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders; + } else { + unset(self::$registeredLoaders[$this->vendorDir]); + self::$registeredLoaders[$this->vendorDir] = $this; + } + } + + /** + * Unregisters this instance as an autoloader. + * + * @return void + */ + public function unregister() + { + spl_autoload_unregister(array($this, 'loadClass')); + + if (null !== $this->vendorDir) { + unset(self::$registeredLoaders[$this->vendorDir]); + } + } + + /** + * Loads the given class or interface. + * + * @param string $class The name of the class + * @return true|null True if loaded, null otherwise + */ + public function loadClass($class) + { + if ($file = $this->findFile($class)) { + includeFile($file); + + return true; + } + + return null; + } + + /** + * Finds the path to the file where the class is defined. + * + * @param string $class The name of the class + * + * @return string|false The path if found, false otherwise + */ + public function findFile($class) + { + // class map lookup + if (isset($this->classMap[$class])) { + return $this->classMap[$class]; + } + if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { + return false; + } + if (null !== $this->apcuPrefix) { + $file = apcu_fetch($this->apcuPrefix.$class, $hit); + if ($hit) { + return $file; + } + } + + $file = $this->findFileWithExtension($class, '.php'); + + // Search for Hack files if we are running on HHVM + if (false === $file && defined('HHVM_VERSION')) { + $file = $this->findFileWithExtension($class, '.hh'); + } + + if (null !== $this->apcuPrefix) { + apcu_add($this->apcuPrefix.$class, $file); + } + + if (false === $file) { + // Remember that this class does not exist. + $this->missingClasses[$class] = true; + } + + return $file; + } + + /** + * Returns the currently registered loaders indexed by their corresponding vendor directories. + * + * @return self[] + */ + public static function getRegisteredLoaders() + { + return self::$registeredLoaders; + } + + /** + * @param string $class + * @param string $ext + * @return string|false + */ + private function findFileWithExtension($class, $ext) + { + // PSR-4 lookup + $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; + + $first = $class[0]; + if (isset($this->prefixLengthsPsr4[$first])) { + $subPath = $class; + while (false !== $lastPos = strrpos($subPath, '\\')) { + $subPath = substr($subPath, 0, $lastPos); + $search = $subPath . '\\'; + if (isset($this->prefixDirsPsr4[$search])) { + $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); + foreach ($this->prefixDirsPsr4[$search] as $dir) { + if (file_exists($file = $dir . $pathEnd)) { + return $file; + } + } + } + } + } + + // PSR-4 fallback dirs + foreach ($this->fallbackDirsPsr4 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { + return $file; + } + } + + // PSR-0 lookup + if (false !== $pos = strrpos($class, '\\')) { + // namespaced class name + $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) + . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); + } else { + // PEAR-like class name + $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; + } + + if (isset($this->prefixesPsr0[$first])) { + foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { + if (0 === strpos($class, $prefix)) { + foreach ($dirs as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + } + } + } + + // PSR-0 fallback dirs + foreach ($this->fallbackDirsPsr0 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + + // PSR-0 include paths. + if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { + return $file; + } + + return false; + } +} + +/** + * Scope isolated include. + * + * Prevents access to $this/self from included files. + * + * @param string $file + * @return void + * @private + */ +function includeFile($file) +{ + include $file; +} diff --git a/vendor/composer/InstalledVersions.php b/vendor/composer/InstalledVersions.php new file mode 100644 index 0000000..d50e0c9 --- /dev/null +++ b/vendor/composer/InstalledVersions.php @@ -0,0 +1,350 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer; + +use Composer\Autoload\ClassLoader; +use Composer\Semver\VersionParser; + +/** + * This class is copied in every Composer installed project and available to all + * + * See also https://getcomposer.org/doc/07-runtime.md#installed-versions + * + * To require its presence, you can require `composer-runtime-api ^2.0` + */ +class InstalledVersions +{ + /** + * @var mixed[]|null + * @psalm-var array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array}|array{}|null + */ + private static $installed; + + /** + * @var bool|null + */ + private static $canGetVendors; + + /** + * @var array[] + * @psalm-var array}> + */ + private static $installedByVendor = array(); + + /** + * Returns a list of all package names which are present, either by being installed, replaced or provided + * + * @return string[] + * @psalm-return list + */ + public static function getInstalledPackages() + { + $packages = array(); + foreach (self::getInstalled() as $installed) { + $packages[] = array_keys($installed['versions']); + } + + if (1 === \count($packages)) { + return $packages[0]; + } + + return array_keys(array_flip(\call_user_func_array('array_merge', $packages))); + } + + /** + * Returns a list of all package names with a specific type e.g. 'library' + * + * @param string $type + * @return string[] + * @psalm-return list + */ + public static function getInstalledPackagesByType($type) + { + $packagesByType = array(); + + foreach (self::getInstalled() as $installed) { + foreach ($installed['versions'] as $name => $package) { + if (isset($package['type']) && $package['type'] === $type) { + $packagesByType[] = $name; + } + } + } + + return $packagesByType; + } + + /** + * Checks whether the given package is installed + * + * This also returns true if the package name is provided or replaced by another package + * + * @param string $packageName + * @param bool $includeDevRequirements + * @return bool + */ + public static function isInstalled($packageName, $includeDevRequirements = true) + { + foreach (self::getInstalled() as $installed) { + if (isset($installed['versions'][$packageName])) { + return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']); + } + } + + return false; + } + + /** + * Checks whether the given package satisfies a version constraint + * + * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call: + * + * Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3') + * + * @param VersionParser $parser Install composer/semver to have access to this class and functionality + * @param string $packageName + * @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package + * @return bool + */ + public static function satisfies(VersionParser $parser, $packageName, $constraint) + { + $constraint = $parser->parseConstraints($constraint); + $provided = $parser->parseConstraints(self::getVersionRanges($packageName)); + + return $provided->matches($constraint); + } + + /** + * Returns a version constraint representing all the range(s) which are installed for a given package + * + * It is easier to use this via isInstalled() with the $constraint argument if you need to check + * whether a given version of a package is installed, and not just whether it exists + * + * @param string $packageName + * @return string Version constraint usable with composer/semver + */ + public static function getVersionRanges($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + $ranges = array(); + if (isset($installed['versions'][$packageName]['pretty_version'])) { + $ranges[] = $installed['versions'][$packageName]['pretty_version']; + } + if (array_key_exists('aliases', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']); + } + if (array_key_exists('replaced', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']); + } + if (array_key_exists('provided', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']); + } + + return implode(' || ', $ranges); + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present + */ + public static function getVersion($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['version'])) { + return null; + } + + return $installed['versions'][$packageName]['version']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present + */ + public static function getPrettyVersion($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['pretty_version'])) { + return null; + } + + return $installed['versions'][$packageName]['pretty_version']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference + */ + public static function getReference($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['reference'])) { + return null; + } + + return $installed['versions'][$packageName]['reference']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path. + */ + public static function getInstallPath($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @return array + * @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string} + */ + public static function getRootPackage() + { + $installed = self::getInstalled(); + + return $installed[0]['root']; + } + + /** + * Returns the raw installed.php data for custom implementations + * + * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect. + * @return array[] + * @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array} + */ + public static function getRawData() + { + @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED); + + if (null === self::$installed) { + // only require the installed.php file if this file is loaded from its dumped location, + // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 + if (substr(__DIR__, -8, 1) !== 'C') { + self::$installed = include __DIR__ . '/installed.php'; + } else { + self::$installed = array(); + } + } + + return self::$installed; + } + + /** + * Returns the raw data of all installed.php which are currently loaded for custom implementations + * + * @return array[] + * @psalm-return list}> + */ + public static function getAllRawData() + { + return self::getInstalled(); + } + + /** + * Lets you reload the static array from another file + * + * This is only useful for complex integrations in which a project needs to use + * this class but then also needs to execute another project's autoloader in process, + * and wants to ensure both projects have access to their version of installed.php. + * + * A typical case would be PHPUnit, where it would need to make sure it reads all + * the data it needs from this class, then call reload() with + * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure + * the project in which it runs can then also use this class safely, without + * interference between PHPUnit's dependencies and the project's dependencies. + * + * @param array[] $data A vendor/composer/installed.php data set + * @return void + * + * @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array} $data + */ + public static function reload($data) + { + self::$installed = $data; + self::$installedByVendor = array(); + } + + /** + * @return array[] + * @psalm-return list}> + */ + private static function getInstalled() + { + if (null === self::$canGetVendors) { + self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders'); + } + + $installed = array(); + + if (self::$canGetVendors) { + foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) { + if (isset(self::$installedByVendor[$vendorDir])) { + $installed[] = self::$installedByVendor[$vendorDir]; + } elseif (is_file($vendorDir.'/composer/installed.php')) { + $installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php'; + if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) { + self::$installed = $installed[count($installed) - 1]; + } + } + } + } + + if (null === self::$installed) { + // only require the installed.php file if this file is loaded from its dumped location, + // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 + if (substr(__DIR__, -8, 1) !== 'C') { + self::$installed = require __DIR__ . '/installed.php'; + } else { + self::$installed = array(); + } + } + $installed[] = self::$installed; + + return $installed; + } +} diff --git a/vendor/composer/LICENSE b/vendor/composer/LICENSE new file mode 100644 index 0000000..f27399a --- /dev/null +++ b/vendor/composer/LICENSE @@ -0,0 +1,21 @@ + +Copyright (c) Nils Adermann, Jordi Boggiano + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php new file mode 100644 index 0000000..2253a7f --- /dev/null +++ b/vendor/composer/autoload_classmap.php @@ -0,0 +1,13 @@ + $baseDir . '/lib/Console.php', + 'Kristuff\\Mishell\\Program' => $baseDir . '/lib/Program.php', + 'Kristuff\\Mishell\\ShellPrinter' => $baseDir . '/lib/ShellPrinter.php', + 'Kristuff\\Mishell\\ShellTablePrinter' => $baseDir . '/lib/ShellTablePrinter.php', + 'Kristuff\\Mishell\\ShellColoredPrinter' => $baseDir . '/lib/ShellColoredPrinter.php', + 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php', +); diff --git a/vendor/composer/autoload_namespaces.php b/vendor/composer/autoload_namespaces.php new file mode 100644 index 0000000..b7fc012 --- /dev/null +++ b/vendor/composer/autoload_namespaces.php @@ -0,0 +1,9 @@ + array($baseDir . '/lib'), +); diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php new file mode 100644 index 0000000..564b5c9 --- /dev/null +++ b/vendor/composer/autoload_real.php @@ -0,0 +1,57 @@ += 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); + if ($useStaticLoader) { + require __DIR__ . '/autoload_static.php'; + + call_user_func(\Composer\Autoload\ComposerStaticInite5eca23334d547f58d55dd3321eace6e::getInitializer($loader)); + } else { + $map = require __DIR__ . '/autoload_namespaces.php'; + foreach ($map as $namespace => $path) { + $loader->set($namespace, $path); + } + + $map = require __DIR__ . '/autoload_psr4.php'; + foreach ($map as $namespace => $path) { + $loader->setPsr4($namespace, $path); + } + + $classMap = require __DIR__ . '/autoload_classmap.php'; + if ($classMap) { + $loader->addClassMap($classMap); + } + } + + $loader->register(true); + + return $loader; + } +} diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php new file mode 100644 index 0000000..f84f7b7 --- /dev/null +++ b/vendor/composer/autoload_static.php @@ -0,0 +1,41 @@ + + array ( + 'Kristuff\\Mishell\\' => 17, + ), + ); + + public static $prefixDirsPsr4 = array ( + 'Kristuff\\Mishell\\' => + array ( + 0 => __DIR__ . '/../..' . '/lib', + ), + ); + + public static $classMap = array ( + 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', + 'Kristuff\\Mishell\\Console' => __DIR__ . '/../..' . '/lib/Console.php', + 'Kristuff\\Mishell\\Program' => __DIR__ . '/../..' . '/lib/Program.php', + 'Kristuff\\Mishell\\ShellColoredPrinter' => __DIR__ . '/../..' . '/lib/ShellColoredPrinter.php', + 'Kristuff\\Mishell\\ShellPrinter' => __DIR__ . '/../..' . '/lib/ShellPrinter.php', + 'Kristuff\\Mishell\\ShellTablePrinter' => __DIR__ . '/../..' . '/lib/ShellTablePrinter.php', + ); + + public static function getInitializer(ClassLoader $loader) + { + return \Closure::bind(function () use ($loader) { + $loader->prefixLengthsPsr4 = ComposerStaticInite5eca23334d547f58d55dd3321eace6e::$prefixLengthsPsr4; + $loader->prefixDirsPsr4 = ComposerStaticInite5eca23334d547f58d55dd3321eace6e::$prefixDirsPsr4; + $loader->classMap = ComposerStaticInite5eca23334d547f58d55dd3321eace6e::$classMap; + + }, null, ClassLoader::class); + } +} diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json new file mode 100644 index 0000000..f20a6c4 --- /dev/null +++ b/vendor/composer/installed.json @@ -0,0 +1,5 @@ +{ + "packages": [], + "dev": false, + "dev-package-names": [] +} diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php new file mode 100644 index 0000000..c7c1434 --- /dev/null +++ b/vendor/composer/installed.php @@ -0,0 +1,23 @@ + array( + 'pretty_version' => '1.0.0+no-version-set', + 'version' => '1.0.0.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../../', + 'aliases' => array(), + 'reference' => NULL, + 'name' => 'kristuff/mishell', + 'dev' => false, + ), + 'versions' => array( + 'kristuff/mishell' => array( + 'pretty_version' => '1.0.0+no-version-set', + 'version' => '1.0.0.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../../', + 'aliases' => array(), + 'reference' => NULL, + 'dev_requirement' => false, + ), + ), +); diff --git a/vendor/composer/platform_check.php b/vendor/composer/platform_check.php new file mode 100644 index 0000000..8b379f4 --- /dev/null +++ b/vendor/composer/platform_check.php @@ -0,0 +1,26 @@ += 50600)) { + $issues[] = 'Your Composer dependencies require a PHP version ">= 5.6.0". You are running ' . PHP_VERSION . '.'; +} + +if ($issues) { + if (!headers_sent()) { + header('HTTP/1.1 500 Internal Server Error'); + } + if (!ini_get('display_errors')) { + if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') { + fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL); + } elseif (!headers_sent()) { + echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL; + } + } + trigger_error( + 'Composer detected issues in your platform: ' . implode(' ', $issues), + E_USER_ERROR + ); +}