Update master

This commit is contained in:
R. Eric Wheeler 2024-07-18 13:13:34 -07:00
commit 24e53cd2cc
8 changed files with 20 additions and 2042 deletions

View File

@ -18,7 +18,6 @@ before_script:
- php composer.phar install
# Run our tests
# If Xdebug was installed you can generate a coverage report and see code coverage metrics.
test:7.4:
only:
- 1.x
@ -35,3 +34,11 @@ test:8.0:
image: php:8.0
script:
- vendor/bin/phpunit --configuration phpunit.xml --coverage-text --colors=never
test:8.1:
only:
- 1.x
tags:
- default
image: php:8.1
script:
- vendor/bin/phpunit --configuration phpunit.xml --coverage-text --colors=never

View File

@ -2,15 +2,12 @@
This simply uses the FFI extension to enable _getch and _ungetch in Windows and linux.
[![pipeline status](https://repos.bgemi.net/sikofitt/getch/badges/1.x/pipeline.svg)](https://repos.bgemi.net/sikofitt/getch/-/commits/1.x)
[![coverage report](https://repos.bgemi.net/sikofitt/getch/badges/1.x/coverage.svg)](https://repos.bgemi.net/sikofitt/getch/-/commits/1.x)
```shell script
$ composer require sikofitt/getch:dev-master
$ composer require olivebbs/getch
```
```php
use Sikofitt\Console\Getch;
use Olive\Console\Getch;
$g = new Getch($linuxLibrary = null); // can also be a library that implements a function called _getch;
// by default uses the bundled Resources/libgetch.so
// on windows uses the built in _getch function.
@ -45,7 +42,7 @@ Note that if you want to put a word into the STDIN stack, you need to do it in r
There are also helper functions called getch() and ungetch();
```php
use function Sikofitt\Console\getch;
use function Olive\Console\getch;
$ord = getch($linuxLibrary = null);
print \chr($ord);

View File

@ -1,7 +1,8 @@
{
"name": "sikofitt/getch",
"name": "olivebbs/getch",
"description": "Implements _getch and _ungetch for windows and linux using ffi",
"type": "library",
"keywords": ["getch", "windows", "conio", "linux", "console", "conio.h", "hotkey", "termios"],
"require": {
"php": "^8.2",
"ext-ffi": "*"
@ -11,7 +12,7 @@
},
"autoload": {
"psr-4": {
"Sikofitt\\Console\\": "src/Console/"
"Olive\\Console\\": "src/Console/"
},
"files": [
"functions.php"
@ -19,7 +20,7 @@
},
"autoload-dev": {
"psr-4": {
"Sikofitt\\Tests\\Console\\": "tests/"
"Olive\\Tests\\Console\\": "tests/"
}
},
"license": "MPL-2.0",
@ -28,5 +29,8 @@
"name": "R. Eric Wheeler",
"email": "sikofitt@gmail.com"
}
]
],
"conflict": {
"sikofitt/getch": "*"
}
}

1763
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -12,7 +12,7 @@ declare(strict_types=1);
* You can obtain one at https://mozilla.org/MPL/2.0/.
*/
use Sikofitt\Console\Getch;
use Olive\Console\Getch;
if (!function_exists('getch')) {
function getch(?string $linuxLibrary = null): int

View File

@ -1,115 +0,0 @@
<?php
declare(strict_types=1);
/*
* Copyright (c) 2020-2024 https://sikofitt.com sikofitt@gmail.com
*
* This Source Code Form is subject to the
* terms of the Mozilla Public License, v. 2.0.
*
* If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/.
*/
namespace Sikofitt\Console;
final class Getch
{
// Special key codes
// Extended scan code used to indicate special keyboard functions
public const KEY_RESERVED = 0;
public const KEY_E0 = 0;
public const KEY_E1 = 224;
// Supported scan codes.
public const KEY_F1 = 59;
public const KEY_F2 = 60;
public const KEY_F3 = 61;
public const KEY_F4 = 62;
public const KEY_F5 = 63;
public const KEY_F6 = 64;
public const KEY_F7 = 65;
public const KEY_F8 = 66;
public const KEY_F9 = 67;
public const KEY_F10 = 68;
public const KEY_F11 = 87;
public const KEY_F12 = 88;
public const KEY_UP = 72;
public const KEY_LEFT = 75;
public const KEY_RIGHT = 77;
public const KEY_DOWN = 80;
public const KEY_DELETE = 83;
public const KEY_HOME = 71;
public const KEY_PAGEUP = 73;
public const KEY_END = 79;
public const KEY_PAGEDOWN = 81;
public const KEY_INSERT = 82;
private const LINUX_LIBRARY = __DIR__.'/Resources/libgetch.so';
private const WINDOWS_LIBRARY = 'ucrtbase.dll';
private const DECLARATIONS = <<<DECLARATIONS
int _getch();
int _ungetch(int c);
DECLARATIONS;
private static ?\FFI $ffi = null;
public static function resetFFI(): void
{
self::$ffi = null;
}
public function __construct(?string $linuxLibrary = null)
{
if (null === $linuxLibrary) {
$linuxLibrary = self::LINUX_LIBRARY;
}
if (null === self::$ffi) {
$osFamily = PHP_OS_FAMILY;
if ('Windows' === $osFamily) {
$declarations = self::DECLARATIONS.' int _kbhit();';
self::$ffi = \FFI::cdef($declarations, self::WINDOWS_LIBRARY);
} elseif ('Linux' === $osFamily) {
if (!file_exists($linuxLibrary)) {
throw new \RuntimeException(sprintf('Could not find library file %s.', $linuxLibrary));
}
$declarations = self::DECLARATIONS.' int cinPeek();';
self::$ffi = \FFI::cdef($declarations, $linuxLibrary);
} else {
throw new \RuntimeException(sprintf('Sorry, %s is not supported yet.', $osFamily));
}
}
}
public function peek(): int
{
if (PHP_OS_FAMILY === 'Windows') {
if (self::$ffi->_kbhit()) {
$result = self::$ffi->_getch();
self::$ffi->_ungetch($result);
return $result;
}
return -1;
}
return self::$ffi->cinPeek();
}
public function getch(): int
{
return self::$ffi->_getch();
}
public function ungetch(string|int $char): int
{
if (is_string($char)) {
$char = ord($char[0]);
}
return self::$ffi->_ungetch($char);
}
}

View File

@ -1,95 +0,0 @@
<?php
/*
* Copyright (c) 2020-2024 https://sikofitt.com sikofitt@gmail.com
*
* This Source Code Form is subject to the
* terms of the Mozilla Public License, v. 2.0.
*
* If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/.
*/
namespace Sikofitt\Tests\Console\Getch;
use PHPUnit\Framework\TestCase;
use Sikofitt\Console\Getch;
class GetchTest extends TestCase
{
private \FFI $ffi;
private const HOME_KEY = "\x1b[H";
public function setUp(): void
{
$this->ffi = \FFI::load(__DIR__.'/../test.h');
$file = $this->ffi->stdin;
$stdin = $this->ffi->fopen('/dev/stdin', 'a+');
foreach (range('D', 'A') as $character) {
$this->ffi->ungetc(ord($character), $file);
}
}
/**
* @preserveGlobalState disabled
*
* @backupStaticAttributes false
*
* @backupGlobals false
*/
public function testFailureOnInvalidLibrary()
{
Getch::resetFFI();
$this->expectException(\RuntimeException::class);
\getch(__DIR__.'/library.so');
}
public function testGetchClass()
{
$getch = new Getch();
foreach (range('A', 'D') as $character) {
self::assertSame(\ord($character), $getch->getch());
}
}
public function testGetchFunction()
{
foreach (range('A', 'D') as $character) {
self::assertSame(\ord($character), getch());
}
}
public function testUnsupportedOS()
{
if (PHP_OS_FAMILY !== 'Linux' || PHP_OS_FAMILY !== 'Windows') {
self::markTestSkipped('This test only applies to non Linux or Windows systems.');
}
$this->expectException(\RuntimeException::class);
\getch();
}
public function testHomeKey()
{
self::markTestSkipped('This seems impossible to test, since it relies on someone actually pressing keys on the keyboard.');
$stdin = $this->ffi->stdin;
foreach (str_split(strrev(self::HOME_KEY)) as $character) {
$this->ffi->ungetc(ord($character), $stdin);
}
$g = new Getch();
self::assertEquals(0, $g->getch());
self::assertEquals(71, $g->getch());
}
public function setPeek()
{
$g = new Getch();
$g->ungetch('q');
$peek = $g->peek();
$getch = $g->getch();
self::assertEquals($peek, $getch);
self::assertEquals(113, $peek);
}
}

View File

@ -1,57 +0,0 @@
<?php
/*
* Copyright (c) 2020-2024 https://sikofitt.com sikofitt@gmail.com
*
* This Source Code Form is subject to the
* terms of the Mozilla Public License, v. 2.0.
*
* If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/.
*/
namespace Sikofitt\Tests\Console\Ungetch;
use PHPUnit\Framework\TestCase;
use Sikofitt\Console\Getch;
class UngetchTest extends TestCase
{
public function setUp(): void
{
parent::setUp(); // TODO: Change the autogenerated stub
}
public function testUngetch()
{
$g = new Getch();
$res = $g->ungetch('A');
self::assertSame(65, $res);
$res = $g->getch();
self::assertSame(65, $res);
$res = ungetch(65);
self::assertSame(65, $res);
$res = $g->getch();
self::assertSame(65, $res);
}
public function testTypeError()
{
$g = new Getch();
$this->expectException(\TypeError::class);
$g->ungetch(new \stdClass());
}
public function testForFun()
{
foreach (\str_split(\strrev('Hello World!')) as $char) {
ungetch($char);
}
$result = '';
do {
$ord = getch();
$result .= \chr($ord);
} while ($ord !== ord('!'));
self::assertSame('Hello World!', $result);
}
}