2019-10-10 12:28:46 -04:00
|
|
|
<?php declare(strict_types=1);
|
|
|
|
|
|
|
|
namespace Kilo;
|
|
|
|
|
|
|
|
use FFI;
|
|
|
|
|
2019-10-10 15:49:01 -04:00
|
|
|
$ffi = FFI::load(__DIR__ . '/ffi.h');
|
|
|
|
$original_termios = $ffi->new('struct termios');
|
2019-10-10 12:28:46 -04:00
|
|
|
|
|
|
|
function enableRawMode(): void
|
|
|
|
{
|
|
|
|
global $ffi;
|
|
|
|
global $original_termios;
|
|
|
|
|
2019-10-11 16:32:47 -04:00
|
|
|
register_shutdown_function('Kilo\\disableRawMode');
|
|
|
|
|
2019-10-10 12:28:46 -04:00
|
|
|
// Populate the original terminal settings
|
2019-10-14 16:21:41 -04:00
|
|
|
$res = $ffi->tcgetattr(STDIN_FILENO, FFI::addr($original_termios));
|
|
|
|
if ($res === -1)
|
|
|
|
{
|
|
|
|
die('tcgetattr');
|
|
|
|
}
|
2019-10-10 12:28:46 -04:00
|
|
|
|
2019-10-21 15:37:20 -04:00
|
|
|
// So, the only thing that seems to really matter here is that c_oflag is 0...
|
|
|
|
$termios = clone $original_termios;
|
|
|
|
$termios->c_iflag = $termios->c_iflag & ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
|
|
|
|
$termios->c_oflag = 0; // $termios->c_oflag && ~(OPOST);
|
2019-10-10 15:49:01 -04:00
|
|
|
$termios->c_cflag |= (CS8);
|
2019-10-21 15:37:20 -04:00
|
|
|
$termios->c_lflag = $termios->c_lflag & ~(_ECHO | ICANON | IEXTEN | ISIG);
|
2019-10-10 15:49:01 -04:00
|
|
|
$termios->c_cc[VMIN] = 0;
|
|
|
|
$termios->c_cc[VTIME] = 1;
|
2019-10-10 12:28:46 -04:00
|
|
|
|
|
|
|
// Turn on raw mode
|
2019-10-14 16:21:41 -04:00
|
|
|
$res = $ffi->tcsetattr(STDIN_FILENO, TCSAFLUSH, FFI::addr($termios));
|
|
|
|
if ($res === -1)
|
|
|
|
{
|
|
|
|
die('tcsetattr');
|
|
|
|
}
|
2019-10-10 12:28:46 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
function disableRawMode(): void
|
|
|
|
{
|
|
|
|
global $ffi;
|
|
|
|
global $original_termios;
|
|
|
|
|
2019-10-14 16:21:41 -04:00
|
|
|
$res = $ffi->tcsetattr(STDIN_FILENO, TCSAFLUSH, FFI::addr($original_termios));
|
|
|
|
|
2019-10-18 16:20:34 -04:00
|
|
|
echo "\n";
|
|
|
|
|
2019-10-14 16:21:41 -04:00
|
|
|
if ($res === -1)
|
|
|
|
{
|
|
|
|
die('tcsetattr');
|
|
|
|
}
|
2019-10-10 12:28:46 -04:00
|
|
|
}
|
|
|
|
|
2019-10-10 15:49:01 -04:00
|
|
|
function read_stdin(int $len = 128): string
|
|
|
|
{
|
|
|
|
$handle = fopen('php://stdin', 'rb');
|
|
|
|
$input = fread($handle, $len);
|
|
|
|
|
|
|
|
$input = rtrim($input);
|
2019-10-10 12:28:46 -04:00
|
|
|
fclose($handle);
|
|
|
|
|
|
|
|
return $input;
|
2019-10-11 16:32:47 -04:00
|
|
|
}
|
|
|
|
|
2019-10-14 16:21:41 -04:00
|
|
|
function write_stdout(string $str, int $len = NULL): int
|
|
|
|
{
|
|
|
|
$handle = fopen('php://stdout', 'ab');
|
|
|
|
$res = (is_int($len))
|
|
|
|
? fwrite($handle, $str, $len)
|
|
|
|
: fwrite($handle, $str);
|
|
|
|
|
|
|
|
fclose($handle);
|
|
|
|
|
|
|
|
return $res;
|
|
|
|
}
|
|
|
|
|
|
|
|
function read_stdout(int $len = 128): string
|
|
|
|
{
|
|
|
|
$handle = fopen('php://stdout', 'rb');
|
|
|
|
$input = fread($handle, $len);
|
|
|
|
|
|
|
|
$input = rtrim($input);
|
|
|
|
fclose($handle);
|
|
|
|
|
|
|
|
return $input;
|
|
|
|
}
|
|
|
|
|
2019-10-11 16:32:47 -04:00
|
|
|
function ctrl_key(string $char): int
|
|
|
|
{
|
|
|
|
return ord($char) & 0x1f;
|
2019-10-10 12:28:46 -04:00
|
|
|
}
|