Merge branch '1.x' into 'master'
1.x See merge request sikofitt/getch!1
This commit is contained in:
commit
16b4cff214
|
@ -21,7 +21,7 @@ before_script:
|
||||||
# If Xdebug was installed you can generate a coverage report and see code coverage metrics.
|
# If Xdebug was installed you can generate a coverage report and see code coverage metrics.
|
||||||
test:7.4:
|
test:7.4:
|
||||||
only:
|
only:
|
||||||
- master
|
- 1.x
|
||||||
tags:
|
tags:
|
||||||
- default
|
- default
|
||||||
image: php:7.4
|
image: php:7.4
|
||||||
|
@ -29,7 +29,7 @@ test:7.4:
|
||||||
- vendor/bin/phpunit --configuration phpunit.xml --coverage-text --colors=never
|
- vendor/bin/phpunit --configuration phpunit.xml --coverage-text --colors=never
|
||||||
test:8.0:
|
test:8.0:
|
||||||
only:
|
only:
|
||||||
- master
|
- 1.x
|
||||||
tags:
|
tags:
|
||||||
- default
|
- default
|
||||||
image: php:8.0
|
image: php:8.0
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
|
|
||||||
This simply uses the FFI extension to enable _getch and _ungetch in Windows and linux.
|
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
|
```shell script
|
||||||
$ composer require sikofitt/getch:dev-master
|
$ composer require sikofitt/getch:dev-master
|
||||||
```
|
```
|
||||||
|
|
|
@ -377,16 +377,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "friendsofphp/php-cs-fixer",
|
"name": "friendsofphp/php-cs-fixer",
|
||||||
"version": "v2.18.1",
|
"version": "v2.18.2",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git",
|
"url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git",
|
||||||
"reference": "c68ff6231adb276857761e43b7ed082f164dce0b"
|
"reference": "18f8c9d184ba777380794a389fabc179896ba913"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/c68ff6231adb276857761e43b7ed082f164dce0b",
|
"url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/18f8c9d184ba777380794a389fabc179896ba913",
|
||||||
"reference": "c68ff6231adb276857761e43b7ed082f164dce0b",
|
"reference": "18f8c9d184ba777380794a389fabc179896ba913",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -468,7 +468,7 @@
|
||||||
"description": "A tool to automatically fix PHP code style",
|
"description": "A tool to automatically fix PHP code style",
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/issues",
|
"issues": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/issues",
|
||||||
"source": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/tree/v2.18.1"
|
"source": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/tree/v2.18.2"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -476,7 +476,7 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2021-01-21T18:50:42+00:00"
|
"time": "2021-01-26T00:22:21+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "jetbrains/phpstorm-stubs",
|
"name": "jetbrains/phpstorm-stubs",
|
||||||
|
@ -484,12 +484,12 @@
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/JetBrains/phpstorm-stubs.git",
|
"url": "https://github.com/JetBrains/phpstorm-stubs.git",
|
||||||
"reference": "44640f75da5865d1c3b0e433cc72ee4cdc677926"
|
"reference": "b8cf707c050f775cdb7693afa6099bd227b383f4"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/JetBrains/phpstorm-stubs/zipball/44640f75da5865d1c3b0e433cc72ee4cdc677926",
|
"url": "https://api.github.com/repos/JetBrains/phpstorm-stubs/zipball/b8cf707c050f775cdb7693afa6099bd227b383f4",
|
||||||
"reference": "44640f75da5865d1c3b0e433cc72ee4cdc677926",
|
"reference": "b8cf707c050f775cdb7693afa6099bd227b383f4",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
|
@ -524,7 +524,7 @@
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/JetBrains/phpstorm-stubs/tree/master"
|
"source": "https://github.com/JetBrains/phpstorm-stubs/tree/master"
|
||||||
},
|
},
|
||||||
"time": "2021-01-25T16:29:22+00:00"
|
"time": "2021-02-15T11:11:55+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "myclabs/deep-copy",
|
"name": "myclabs/deep-copy",
|
||||||
|
@ -1351,16 +1351,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpunit/phpunit",
|
"name": "phpunit/phpunit",
|
||||||
"version": "9.5.1",
|
"version": "9.5.2",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||||
"reference": "e7bdf4085de85a825f4424eae52c99a1cec2f360"
|
"reference": "f661659747f2f87f9e72095bb207bceb0f151cb4"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/e7bdf4085de85a825f4424eae52c99a1cec2f360",
|
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f661659747f2f87f9e72095bb207bceb0f151cb4",
|
||||||
"reference": "e7bdf4085de85a825f4424eae52c99a1cec2f360",
|
"reference": "f661659747f2f87f9e72095bb207bceb0f151cb4",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -1438,7 +1438,7 @@
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
||||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.1"
|
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.2"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -1450,7 +1450,7 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2021-01-17T07:42:25+00:00"
|
"time": "2021-02-02T14:45:58+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "psr/container",
|
"name": "psr/container",
|
||||||
|
@ -2571,16 +2571,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/console",
|
"name": "symfony/console",
|
||||||
"version": "v5.2.1",
|
"version": "v5.2.3",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/console.git",
|
"url": "https://github.com/symfony/console.git",
|
||||||
"reference": "47c02526c532fb381374dab26df05e7313978976"
|
"reference": "89d4b176d12a2946a1ae4e34906a025b7b6b135a"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/console/zipball/47c02526c532fb381374dab26df05e7313978976",
|
"url": "https://api.github.com/repos/symfony/console/zipball/89d4b176d12a2946a1ae4e34906a025b7b6b135a",
|
||||||
"reference": "47c02526c532fb381374dab26df05e7313978976",
|
"reference": "89d4b176d12a2946a1ae4e34906a025b7b6b135a",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -2639,7 +2639,7 @@
|
||||||
"homepage": "https://symfony.com/contributors"
|
"homepage": "https://symfony.com/contributors"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Symfony Console Component",
|
"description": "Eases the creation of beautiful and testable command line interfaces",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"cli",
|
"cli",
|
||||||
|
@ -2648,7 +2648,7 @@
|
||||||
"terminal"
|
"terminal"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/console/tree/v5.2.1"
|
"source": "https://github.com/symfony/console/tree/v5.2.3"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -2664,7 +2664,7 @@
|
||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2020-12-18T08:03:05+00:00"
|
"time": "2021-01-28T22:06:19+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/deprecation-contracts",
|
"name": "symfony/deprecation-contracts",
|
||||||
|
@ -2735,16 +2735,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/event-dispatcher",
|
"name": "symfony/event-dispatcher",
|
||||||
"version": "v5.2.1",
|
"version": "v5.2.3",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/event-dispatcher.git",
|
"url": "https://github.com/symfony/event-dispatcher.git",
|
||||||
"reference": "1c93f7a1dff592c252574c79a8635a8a80856042"
|
"reference": "4f9760f8074978ad82e2ce854dff79a71fe45367"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/1c93f7a1dff592c252574c79a8635a8a80856042",
|
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/4f9760f8074978ad82e2ce854dff79a71fe45367",
|
||||||
"reference": "1c93f7a1dff592c252574c79a8635a8a80856042",
|
"reference": "4f9760f8074978ad82e2ce854dff79a71fe45367",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -2797,10 +2797,10 @@
|
||||||
"homepage": "https://symfony.com/contributors"
|
"homepage": "https://symfony.com/contributors"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Symfony EventDispatcher Component",
|
"description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/event-dispatcher/tree/v5.2.1"
|
"source": "https://github.com/symfony/event-dispatcher/tree/v5.2.3"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -2816,7 +2816,7 @@
|
||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2020-12-18T08:03:05+00:00"
|
"time": "2021-01-27T10:36:42+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/event-dispatcher-contracts",
|
"name": "symfony/event-dispatcher-contracts",
|
||||||
|
@ -2899,16 +2899,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/filesystem",
|
"name": "symfony/filesystem",
|
||||||
"version": "v5.2.1",
|
"version": "v5.2.3",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/filesystem.git",
|
"url": "https://github.com/symfony/filesystem.git",
|
||||||
"reference": "fa8f8cab6b65e2d99a118e082935344c5ba8c60d"
|
"reference": "262d033b57c73e8b59cd6e68a45c528318b15038"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/fa8f8cab6b65e2d99a118e082935344c5ba8c60d",
|
"url": "https://api.github.com/repos/symfony/filesystem/zipball/262d033b57c73e8b59cd6e68a45c528318b15038",
|
||||||
"reference": "fa8f8cab6b65e2d99a118e082935344c5ba8c60d",
|
"reference": "262d033b57c73e8b59cd6e68a45c528318b15038",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -2938,10 +2938,10 @@
|
||||||
"homepage": "https://symfony.com/contributors"
|
"homepage": "https://symfony.com/contributors"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Symfony Filesystem Component",
|
"description": "Provides basic utilities for the filesystem",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/filesystem/tree/v5.2.1"
|
"source": "https://github.com/symfony/filesystem/tree/v5.2.3"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -2957,20 +2957,20 @@
|
||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2020-11-30T17:05:38+00:00"
|
"time": "2021-01-27T10:01:46+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/finder",
|
"name": "symfony/finder",
|
||||||
"version": "v5.2.1",
|
"version": "v5.2.3",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/finder.git",
|
"url": "https://github.com/symfony/finder.git",
|
||||||
"reference": "0b9231a5922fd7287ba5b411893c0ecd2733e5ba"
|
"reference": "4adc8d172d602008c204c2e16956f99257248e03"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/finder/zipball/0b9231a5922fd7287ba5b411893c0ecd2733e5ba",
|
"url": "https://api.github.com/repos/symfony/finder/zipball/4adc8d172d602008c204c2e16956f99257248e03",
|
||||||
"reference": "0b9231a5922fd7287ba5b411893c0ecd2733e5ba",
|
"reference": "4adc8d172d602008c204c2e16956f99257248e03",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -2999,10 +2999,10 @@
|
||||||
"homepage": "https://symfony.com/contributors"
|
"homepage": "https://symfony.com/contributors"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Symfony Finder Component",
|
"description": "Finds files and directories via an intuitive fluent interface",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/finder/tree/v5.2.1"
|
"source": "https://github.com/symfony/finder/tree/v5.2.3"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -3018,20 +3018,20 @@
|
||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2020-12-08T17:02:38+00:00"
|
"time": "2021-01-28T22:06:19+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/options-resolver",
|
"name": "symfony/options-resolver",
|
||||||
"version": "v5.2.1",
|
"version": "v5.2.3",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/options-resolver.git",
|
"url": "https://github.com/symfony/options-resolver.git",
|
||||||
"reference": "87a2a4a766244e796dd9cb9d6f58c123358cd986"
|
"reference": "5d0f633f9bbfcf7ec642a2b5037268e61b0a62ce"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/87a2a4a766244e796dd9cb9d6f58c123358cd986",
|
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/5d0f633f9bbfcf7ec642a2b5037268e61b0a62ce",
|
||||||
"reference": "87a2a4a766244e796dd9cb9d6f58c123358cd986",
|
"reference": "5d0f633f9bbfcf7ec642a2b5037268e61b0a62ce",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -3063,7 +3063,7 @@
|
||||||
"homepage": "https://symfony.com/contributors"
|
"homepage": "https://symfony.com/contributors"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Symfony OptionsResolver Component",
|
"description": "Provides an improved replacement for the array_replace PHP function",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"config",
|
"config",
|
||||||
|
@ -3071,7 +3071,7 @@
|
||||||
"options"
|
"options"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/options-resolver/tree/v5.2.1"
|
"source": "https://github.com/symfony/options-resolver/tree/v5.2.3"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -3087,7 +3087,7 @@
|
||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2020-10-24T12:08:07+00:00"
|
"time": "2021-01-27T12:56:27+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/polyfill-ctype",
|
"name": "symfony/polyfill-ctype",
|
||||||
|
@ -3721,16 +3721,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/process",
|
"name": "symfony/process",
|
||||||
"version": "v5.2.1",
|
"version": "v5.2.3",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/process.git",
|
"url": "https://github.com/symfony/process.git",
|
||||||
"reference": "bd8815b8b6705298beaa384f04fabd459c10bedd"
|
"reference": "313a38f09c77fbcdc1d223e57d368cea76a2fd2f"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/process/zipball/bd8815b8b6705298beaa384f04fabd459c10bedd",
|
"url": "https://api.github.com/repos/symfony/process/zipball/313a38f09c77fbcdc1d223e57d368cea76a2fd2f",
|
||||||
"reference": "bd8815b8b6705298beaa384f04fabd459c10bedd",
|
"reference": "313a38f09c77fbcdc1d223e57d368cea76a2fd2f",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -3760,10 +3760,10 @@
|
||||||
"homepage": "https://symfony.com/contributors"
|
"homepage": "https://symfony.com/contributors"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Symfony Process Component",
|
"description": "Executes commands in sub-processes",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/process/tree/v5.2.1"
|
"source": "https://github.com/symfony/process/tree/v5.2.3"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -3779,7 +3779,7 @@
|
||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2020-12-08T17:03:37+00:00"
|
"time": "2021-01-27T10:15:41+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/service-contracts",
|
"name": "symfony/service-contracts",
|
||||||
|
@ -3862,16 +3862,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/stopwatch",
|
"name": "symfony/stopwatch",
|
||||||
"version": "v5.2.1",
|
"version": "v5.2.3",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/stopwatch.git",
|
"url": "https://github.com/symfony/stopwatch.git",
|
||||||
"reference": "2b105c0354f39a63038a1d8bf776ee92852813af"
|
"reference": "b12274acfab9d9850c52583d136a24398cdf1a0c"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/stopwatch/zipball/2b105c0354f39a63038a1d8bf776ee92852813af",
|
"url": "https://api.github.com/repos/symfony/stopwatch/zipball/b12274acfab9d9850c52583d136a24398cdf1a0c",
|
||||||
"reference": "2b105c0354f39a63038a1d8bf776ee92852813af",
|
"reference": "b12274acfab9d9850c52583d136a24398cdf1a0c",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -3901,10 +3901,10 @@
|
||||||
"homepage": "https://symfony.com/contributors"
|
"homepage": "https://symfony.com/contributors"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Symfony Stopwatch Component",
|
"description": "Provides a way to profile code",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/stopwatch/tree/v5.2.1"
|
"source": "https://github.com/symfony/stopwatch/tree/v5.2.3"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -3920,20 +3920,20 @@
|
||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2020-11-01T16:14:45+00:00"
|
"time": "2021-01-27T10:15:41+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/string",
|
"name": "symfony/string",
|
||||||
"version": "v5.2.1",
|
"version": "v5.2.3",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/string.git",
|
"url": "https://github.com/symfony/string.git",
|
||||||
"reference": "5bd67751d2e3f7d6f770c9154b8fbcb2aa05f7ed"
|
"reference": "c95468897f408dd0aca2ff582074423dd0455122"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/string/zipball/5bd67751d2e3f7d6f770c9154b8fbcb2aa05f7ed",
|
"url": "https://api.github.com/repos/symfony/string/zipball/c95468897f408dd0aca2ff582074423dd0455122",
|
||||||
"reference": "5bd67751d2e3f7d6f770c9154b8fbcb2aa05f7ed",
|
"reference": "c95468897f408dd0aca2ff582074423dd0455122",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -3976,7 +3976,7 @@
|
||||||
"homepage": "https://symfony.com/contributors"
|
"homepage": "https://symfony.com/contributors"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Symfony String component",
|
"description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"grapheme",
|
"grapheme",
|
||||||
|
@ -3987,7 +3987,7 @@
|
||||||
"utf8"
|
"utf8"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/string/tree/v5.2.1"
|
"source": "https://github.com/symfony/string/tree/v5.2.3"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -4003,7 +4003,7 @@
|
||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2020-12-05T07:33:16+00:00"
|
"time": "2021-01-25T15:14:59+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "theseer/tokenizer",
|
"name": "theseer/tokenizer",
|
||||||
|
|
|
@ -31,12 +31,3 @@ if (!function_exists('ungetch')) {
|
||||||
return $g->ungetch($char);
|
return $g->ungetch($char);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!function_exists('ungetchString')) {
|
|
||||||
function ungetchString(string $string, string $linuxLibrary = null): bool
|
|
||||||
{
|
|
||||||
$g = new Getch($linuxLibrary);
|
|
||||||
|
|
||||||
return $g->ungetchString($string);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -19,6 +19,36 @@ use RuntimeException;
|
||||||
|
|
||||||
final class Getch
|
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 scodes.
|
||||||
|
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 LINUX_LIBRARY = __DIR__.'/Resources/libgetch.so';
|
||||||
private const WINDOWS_LIBRARY = 'ucrtbase.dll';
|
private const WINDOWS_LIBRARY = 'ucrtbase.dll';
|
||||||
private const DECLARATIONS = <<<DECLARATIONS
|
private const DECLARATIONS = <<<DECLARATIONS
|
||||||
|
@ -28,6 +58,11 @@ final class Getch
|
||||||
|
|
||||||
private static ?FFI $ffi = null;
|
private static ?FFI $ffi = null;
|
||||||
|
|
||||||
|
public static function resetFFI(): void
|
||||||
|
{
|
||||||
|
static::$ffi = null;
|
||||||
|
}
|
||||||
|
|
||||||
public function __construct(string $linuxLibrary = null)
|
public function __construct(string $linuxLibrary = null)
|
||||||
{
|
{
|
||||||
if (null === $linuxLibrary) {
|
if (null === $linuxLibrary) {
|
||||||
|
@ -37,19 +72,33 @@ final class Getch
|
||||||
if (null === self::$ffi) {
|
if (null === self::$ffi) {
|
||||||
$osFamily = PHP_OS_FAMILY;
|
$osFamily = PHP_OS_FAMILY;
|
||||||
if ('Windows' === $osFamily) {
|
if ('Windows' === $osFamily) {
|
||||||
self::$ffi = FFI::cdef(self::DECLARATIONS, self::WINDOWS_LIBRARY);
|
$declarations = self::DECLARATIONS . ' int _kbhit();';
|
||||||
|
self::$ffi = FFI::cdef($declarations, self::WINDOWS_LIBRARY);
|
||||||
} elseif ('Linux' === $osFamily) {
|
} elseif ('Linux' === $osFamily) {
|
||||||
if (!file_exists($linuxLibrary)) {
|
if (!file_exists($linuxLibrary)) {
|
||||||
throw new RuntimeException(sprintf('Could not find library file %s.', $linuxLibrary));
|
throw new RuntimeException(sprintf('Could not find library file %s.', $linuxLibrary));
|
||||||
}
|
}
|
||||||
|
$declarations = self::DECLARATIONS . ' int cinPeek();';
|
||||||
self::$ffi = FFI::cdef(self::DECLARATIONS, $linuxLibrary);
|
self::$ffi = FFI::cdef($declarations, $linuxLibrary);
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException(sprintf('Sorry, %s is not supported yet.', $osFamily));
|
throw new RuntimeException(sprintf('Sorry, %s is not supported yet.', $osFamily));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function peek(): int
|
||||||
|
{
|
||||||
|
if (PHP_OS_FAMILY === 'Windows') {
|
||||||
|
if ($ffi->_kbhit()) {
|
||||||
|
$result = $ffi->_getch();
|
||||||
|
$ffi->_ungetch($result);
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return $ffi->cinPeek();
|
||||||
|
}
|
||||||
|
|
||||||
public function getch(): int
|
public function getch(): int
|
||||||
{
|
{
|
||||||
return self::$ffi->_getch();
|
return self::$ffi->_getch();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
CC = gcc
|
CC = gcc
|
||||||
CFLAGS = -shared -Wall -fPIC
|
CFLAGS = -shared -Wall -Wno-unknown-pragmas -fPIC
|
||||||
|
|
||||||
all:
|
all:
|
||||||
@${CC} ${CFLAGS} getch.c -o libgetch.so
|
@${CC} ${CFLAGS} getch.c -o libgetch.so
|
||||||
|
|
|
@ -1,58 +1,303 @@
|
||||||
|
/***********************************************************************
|
||||||
|
* 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 http://mozilla.org/MPL/2.0/. *
|
||||||
|
***********************************************************************/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
static struct termios oldattr;
|
#include <fcntl.h>
|
||||||
|
#include <linux/input.h>
|
||||||
|
#include <glob.h>
|
||||||
|
|
||||||
static char *strrev(char *str)
|
#define EVENT_DEVICE_GLOB "/dev/input/by-path/*-event-kbd"
|
||||||
|
|
||||||
|
#define FKEY(k) ((k) >= KEY_F1 && (k) <= KEY_F10) || (k) == KEY_F12 || (k) == KEY_F11
|
||||||
|
#define NOTNUMPAD(k) ((k) >= KEY_HOME && (k) <= KEY_DELETE)
|
||||||
|
#define XOR_SWAP(a,b) do\
|
||||||
|
{\
|
||||||
|
(a) ^= (b);\
|
||||||
|
(b) ^= (a);\
|
||||||
|
(a) ^= (b);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
static struct termios oldTermAttributes;
|
||||||
|
|
||||||
|
inline static void reverseString(char * str)
|
||||||
{
|
{
|
||||||
char *p1, *p2;
|
if (str)
|
||||||
|
{
|
||||||
|
char * end = str + strlen(str) - 1;
|
||||||
|
|
||||||
if (! str || ! *str)
|
while (str < end)
|
||||||
return str;
|
{
|
||||||
for (p1 = str, p2 = str + strlen(str) - 1; p2 > p1; ++p1, --p2)
|
XOR_SWAP(*str, *end);
|
||||||
{
|
str++;
|
||||||
*p1 ^= *p2;
|
end--;
|
||||||
*p2 ^= *p1;
|
}
|
||||||
*p1 ^= *p2;
|
}
|
||||||
}
|
|
||||||
return str;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int discardRead(unsigned int length)
|
||||||
|
{
|
||||||
|
char buffer[length];
|
||||||
|
ssize_t bytesRead;
|
||||||
|
|
||||||
|
int flags = fcntl(STDIN_FILENO, F_GETFL);
|
||||||
|
fcntl(STDIN_FILENO, F_SETFL, flags|O_NONBLOCK);
|
||||||
|
|
||||||
|
if( (bytesRead = fread(buffer, sizeof(char), length, stdin)) == -1) {
|
||||||
|
perror("discardRead");
|
||||||
|
}
|
||||||
|
|
||||||
|
fcntl(STDIN_FILENO, F_SETFL, flags);
|
||||||
|
|
||||||
|
return (int)bytesRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getEventDevice(char ** device)
|
||||||
|
{
|
||||||
|
glob_t search;
|
||||||
|
|
||||||
|
int globResult = glob(
|
||||||
|
EVENT_DEVICE_GLOB,
|
||||||
|
GLOB_NOSORT,
|
||||||
|
NULL,
|
||||||
|
&search
|
||||||
|
);
|
||||||
|
|
||||||
|
if(0 != globResult) {
|
||||||
|
globfree(&search);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(search.gl_pathc == 0) {
|
||||||
|
globfree(&search);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t pathLength;
|
||||||
|
|
||||||
|
for(int i = 0; i<search.gl_pathc;i++) {
|
||||||
|
if(access(search.gl_pathv[i], F_OK) == 0) {
|
||||||
|
pathLength = strlen(search.gl_pathv[i]) + 1;
|
||||||
|
*device = (char *)malloc(pathLength);
|
||||||
|
strcpy(*device, search.gl_pathv[i]);
|
||||||
|
globfree(&search);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
globfree(&search);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned short getScanCode()
|
||||||
|
{
|
||||||
|
struct input_event inputEvent[5];
|
||||||
|
int eventDevice;
|
||||||
|
|
||||||
|
char *device;
|
||||||
|
if(getEventDevice(&device) == -1) {
|
||||||
|
perror("getEventDevice");
|
||||||
|
free(device);
|
||||||
|
return KEY_RESERVED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ( eventDevice = open(device, O_RDONLY)) == -1 ) {
|
||||||
|
free(device);
|
||||||
|
perror("open");
|
||||||
|
return KEY_RESERVED;
|
||||||
|
};
|
||||||
|
|
||||||
|
free(device);
|
||||||
|
|
||||||
|
if( read(eventDevice, &inputEvent, sizeof(inputEvent)) == -1) {
|
||||||
|
close(eventDevice);
|
||||||
|
perror("read");
|
||||||
|
return KEY_RESERVED;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(eventDevice);
|
||||||
|
|
||||||
|
for(int i = 0;i<5;i++) {
|
||||||
|
if(inputEvent[i].type == EV_KEY && inputEvent[i].code != KEY_ENTER) {
|
||||||
|
return inputEvent[i].code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return KEY_RESERVED;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void pushStdin(int c) {
|
||||||
|
ungetc(c, stdin);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setNormalMode(void)
|
||||||
|
{
|
||||||
|
tcsetattr(STDIN_FILENO, TCSANOW, &oldTermAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
static void setRawMode(void)
|
static void setRawMode(void)
|
||||||
{
|
{
|
||||||
struct termios newattr;
|
tcgetattr(STDIN_FILENO, &oldTermAttributes);
|
||||||
|
|
||||||
tcgetattr(STDIN_FILENO, &oldattr);
|
struct termios raw = oldTermAttributes;
|
||||||
newattr = oldattr;
|
|
||||||
cfmakeraw(&newattr);
|
cfmakeraw(&raw);
|
||||||
tcsetattr(STDIN_FILENO, TCSANOW, &newattr);
|
tcsetattr(STDIN_FILENO, TCSANOW, &raw);
|
||||||
|
|
||||||
}
|
}
|
||||||
static void setNormalMode(void)
|
|
||||||
|
static unsigned short resolveScanCode(unsigned short key)
|
||||||
{
|
{
|
||||||
tcsetattr(STDIN_FILENO, TCSANOW, &oldattr);
|
switch(key) {
|
||||||
|
case KEY_DOWN: return KEY_KP2;
|
||||||
|
case KEY_LEFT: return KEY_KP4;
|
||||||
|
case KEY_RIGHT: return KEY_KP6;
|
||||||
|
case KEY_UP: return KEY_KP8;
|
||||||
|
case KEY_HOME: return KEY_KP7;
|
||||||
|
case KEY_END: return KEY_KP1;
|
||||||
|
case KEY_INSERT: return KEY_KP0;
|
||||||
|
case KEY_DELETE: return KEY_KPDOT;
|
||||||
|
case KEY_PAGEUP: return KEY_KP9;
|
||||||
|
case KEY_PAGEDOWN: return KEY_KP3;
|
||||||
|
default: return key;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int readKey(void) {
|
||||||
|
|
||||||
/* reads from keypress, doesn't echo */
|
int key = getchar();
|
||||||
int _getch(void)
|
|
||||||
{
|
if (key == 27) {
|
||||||
int ch;
|
|
||||||
|
unsigned short scanCode = getScanCode();
|
||||||
|
|
||||||
|
if (scanCode == KEY_ESC ) {
|
||||||
|
return 27;
|
||||||
|
}
|
||||||
|
|
||||||
|
int returnResult = 0;
|
||||||
|
|
||||||
|
if (NOTNUMPAD(scanCode)) {
|
||||||
|
scanCode = resolveScanCode(scanCode);
|
||||||
|
returnResult = 224;
|
||||||
|
}
|
||||||
|
|
||||||
|
u_short discardBytes;
|
||||||
|
|
||||||
|
switch (scanCode) {
|
||||||
|
case KEY_F1:
|
||||||
|
case KEY_F2:
|
||||||
|
case KEY_F3:
|
||||||
|
case KEY_F4:
|
||||||
|
case KEY_KP1: // END
|
||||||
|
case KEY_KP2: // DOWN
|
||||||
|
case KEY_KP4: // LEFT
|
||||||
|
case KEY_KP6: // RIGHT
|
||||||
|
case KEY_KP7: // HOME
|
||||||
|
case KEY_KP8: // UP
|
||||||
|
discardBytes = 2;
|
||||||
|
break;
|
||||||
|
case KEY_KP0: // INSERT
|
||||||
|
case KEY_KPDOT: // DELETE
|
||||||
|
case KEY_KP9: // PAGEUP
|
||||||
|
case KEY_KP3: // PAGEDOWN
|
||||||
|
discardBytes = 3;
|
||||||
|
break;
|
||||||
|
case KEY_F5:
|
||||||
|
case KEY_F6:
|
||||||
|
case KEY_F7:
|
||||||
|
case KEY_F8:
|
||||||
|
case KEY_F9:
|
||||||
|
case KEY_F10:
|
||||||
|
case KEY_F11:
|
||||||
|
case KEY_F12:
|
||||||
|
discardBytes = 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
discardBytes = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (discardBytes != 0) {
|
||||||
|
discardRead(discardBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
pushStdin(scanCode);
|
||||||
|
|
||||||
|
return returnResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _getch(void) {
|
||||||
|
|
||||||
setRawMode();
|
|
||||||
atexit(setNormalMode);
|
atexit(setNormalMode);
|
||||||
|
setRawMode();
|
||||||
|
|
||||||
ch = getchar();
|
int key = readKey();
|
||||||
|
|
||||||
setNormalMode();
|
setNormalMode();
|
||||||
|
|
||||||
return ch;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _ungetch(char ch)
|
int getch(void)
|
||||||
|
{
|
||||||
|
return _getch();
|
||||||
|
}
|
||||||
|
|
||||||
|
int _ungetch(int ch)
|
||||||
{
|
{
|
||||||
return ungetc(ch, stdin);
|
return ungetc(ch, stdin);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ungetch(int ch)
|
||||||
|
{
|
||||||
|
return _ungetch(ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
int *cinPeekCount(ushort count)
|
||||||
|
{
|
||||||
|
char buffer[count];
|
||||||
|
|
||||||
|
int flags = fcntl(STDIN_FILENO, F_GETFL);
|
||||||
|
|
||||||
|
fcntl(STDIN_FILENO, F_SETFL, flags|O_NONBLOCK);
|
||||||
|
|
||||||
|
size_t byteCount = fread(&buffer, sizeof(char), count, stdin);
|
||||||
|
|
||||||
|
fcntl(STDIN_FILENO, F_SETFL, flags);
|
||||||
|
|
||||||
|
int *res = (int*)malloc(byteCount);
|
||||||
|
|
||||||
|
for(int i=0;i<byteCount;i++)
|
||||||
|
{
|
||||||
|
res[i] = (int)buffer[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
reverseString(buffer);
|
||||||
|
|
||||||
|
for(int i=0;i<byteCount;i++) {
|
||||||
|
pushStdin(buffer[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cinPeek()
|
||||||
|
{
|
||||||
|
int flags = fcntl(STDIN_FILENO, F_GETFL);
|
||||||
|
fcntl(STDIN_FILENO, F_SETFL, flags|O_NONBLOCK);
|
||||||
|
int result = fgetc(stdin);
|
||||||
|
fcntl(STDIN_FILENO, F_SETFL, flags);
|
||||||
|
ungetc(result, stdin);
|
||||||
|
return result;
|
||||||
}
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
F1-10 = 59..68
|
||||||
|
UP_ARROW = 72
|
||||||
|
LEFT_ARROW = 75
|
||||||
|
RIGHT_ARROW = 77
|
||||||
|
DOWN_ARROW = 80
|
||||||
|
DELETE = 83
|
||||||
|
F11-12 = 87..88
|
||||||
|
HOME = 102
|
||||||
|
PGUP = 104
|
||||||
|
END = 107
|
||||||
|
PGDN = 109
|
||||||
|
INSERT = 110
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Binary file not shown.
|
@ -8,24 +8,27 @@ use Sikofitt\Console\Getch;
|
||||||
class GetchTest extends TestCase
|
class GetchTest extends TestCase
|
||||||
{
|
{
|
||||||
private \FFI $ffi;
|
private \FFI $ffi;
|
||||||
|
private const HOME_KEY = "\x1b[H";
|
||||||
|
|
||||||
public function setUp(): void
|
public function setUp(): void
|
||||||
{
|
{
|
||||||
$this->ffi = \FFI::load(__DIR__.'/../test.h');
|
$this->ffi = \FFI::load(__DIR__.'/../test.h');
|
||||||
$stdin = $this->ffi->stdin;
|
$file = $this->ffi->stdin;
|
||||||
|
$stdin = $this->ffi->fopen('/dev/stdin', 'a+');
|
||||||
|
|
||||||
foreach (range('D', 'A') as $character) {
|
foreach (range('D', 'A') as $character) {
|
||||||
$this->ffi->ungetc(ord($character), $stdin);
|
$this->ffi->ungetc(ord($character), $file);
|
||||||
}
|
}
|
||||||
|
|
||||||
parent::setUp(); // TODO: Change the autogenerated stub
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @preserveGlobalState disabled
|
* @preserveGlobalState disabled
|
||||||
|
* @backupStaticAttributes false
|
||||||
|
* @backupGlobals false
|
||||||
*/
|
*/
|
||||||
public function testFailureOnInvalidLibrary()
|
public function testFailureOnInvalidLibrary()
|
||||||
{
|
{
|
||||||
|
Getch::resetFFI();
|
||||||
$this->expectException(\RuntimeException::class);
|
$this->expectException(\RuntimeException::class);
|
||||||
\getch(__DIR__.'/library.so');
|
\getch(__DIR__.'/library.so');
|
||||||
}
|
}
|
||||||
|
@ -53,4 +56,28 @@ class GetchTest extends TestCase
|
||||||
$this->expectException(\RuntimeException::class);
|
$this->expectException(\RuntimeException::class);
|
||||||
\getch();
|
\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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,14 +34,14 @@ class UngetchTest extends TestCase
|
||||||
|
|
||||||
public function testForFun()
|
public function testForFun()
|
||||||
{
|
{
|
||||||
foreach(\str_split(\strrev('Hello World!')) as $char) {
|
foreach (\str_split(\strrev('Hello World!')) as $char) {
|
||||||
ungetch($char);
|
ungetch($char);
|
||||||
}
|
}
|
||||||
$result = '';
|
$result = '';
|
||||||
do {
|
do {
|
||||||
$ord = getch();
|
$ord = getch();
|
||||||
$result .= \chr($ord);
|
$result .= \chr($ord);
|
||||||
} while($ord !== ord('!'));
|
} while ($ord !== ord('!'));
|
||||||
self::assertSame('Hello World!', $result);
|
self::assertSame('Hello World!', $result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,5 +13,7 @@ typedef struct _iobuf
|
||||||
|
|
||||||
FILE *stdin;
|
FILE *stdin;
|
||||||
|
|
||||||
|
FILE *fopen(const char *filename, const char *mode);
|
||||||
|
|
||||||
int ungetc(int ch, FILE *stream);
|
int ungetc(int ch, FILE *stream);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue