new('struct termios'); function enableRawMode(): void { global $ffi; global $original_termios; register_shutdown_function('Kilo\\disableRawMode'); // Populate the original terminal settings $res = $ffi->tcgetattr(STDIN_FILENO, FFI::addr($original_termios)); if ($res === -1) { die('tcgetattr'); } // 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); $termios->c_cflag |= (CS8); $termios->c_lflag = $termios->c_lflag & ~(_ECHO | ICANON | IEXTEN | ISIG); $termios->c_cc[VMIN] = 0; $termios->c_cc[VTIME] = 1; // Turn on raw mode $res = $ffi->tcsetattr(STDIN_FILENO, TCSAFLUSH, FFI::addr($termios)); if ($res === -1) { die('tcsetattr'); } } function disableRawMode(): void { global $ffi; global $original_termios; $res = $ffi->tcsetattr(STDIN_FILENO, TCSAFLUSH, FFI::addr($original_termios)); echo "\n"; if ($res === -1) { die('tcsetattr'); } } function read_stdin(int $len = 128): string { $handle = fopen('php://stdin', 'rb'); $input = fread($handle, $len); fclose($handle); return $input; } 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; } /** * Do bit twiddling to convert a letter into * its Ctrl-letter equivalent * * @param string $char * @return int */ function ctrl_key(string $char): int { // b1,100,001 (a) & b0,011,111 = b0,000,001 // b1,100,010 (b) & b0,011,111 = b0,000,010 return ord($char) & 0x1f; }