Skip to content

Instantly share code, notes, and snippets.

@adsr
Created June 28, 2022 06:37
Show Gist options
  • Save adsr/d9bae670f5b3d823afb483a01360ec6a to your computer and use it in GitHub Desktop.
Save adsr/d9bae670f5b3d823afb483a01360ec6a to your computer and use it in GitHub Desktop.
<?php
declare(strict_types=1);
$libreadline_so = __DIR__ . '/vendor/readline/shlib/libreadline.so.8.1';
$readline_h = <<<'EOD'
int rl_catch_signals;
int rl_catch_sigwinch;
int rl_change_environment;
int rl_point;
char *rl_display_prompt;
char *rl_line_buffer;
void *rl_deprep_term_function;
void *rl_prep_term_function;
int (*rl_bind_key)(int, int (*)(int, int));
int (*rl_getc_function)(void *);
int (*rl_input_available_hook)();
void (*rl_redisplay_function)();
int rl_forward_char(int, int);
int rl_backward_char(int, int);
void rl_callback_handler_install(const char *, void (*)(char *));
void rl_callback_handler_remove();
void rl_callback_read_char();
EOD;
$readline = FFI::cdef($readline_h, $libreadline_so);
[ $termbox, $termbox_defines ] = require __DIR__ . '/vendor/termbox2/tests/test_ffi.php';
$termbox->tb_init();
$input = null;
$input_avail = false;
$readline->rl_catch_signals = 0;
$readline->rl_catch_sigwinch = 0;
$readline->rl_change_environment = 0;
$readline->rl_deprep_term_function = null;
$readline->rl_prep_term_function = null;
$readline->rl_getc_function = function ($ignore) use (&$input_avail, &$input) {
fwrite(STDERR, "rl_getc_function input=$input\n");
$input_avail = false;
return $input;
};
$readline->rl_input_available_hook = function () use ($input_avail) {
fwrite(STDERR, "rl_input_available_hook input_avail=$input_avail\n");
return $input_avail;
};
$rl_redisplay_function = function () use ($termbox, $readline) {
$line_buffer = FFI::string($readline->rl_line_buffer);
fwrite(STDERR, "rl_redisplay_function rl_line_buffer=$line_buffer\n");
$termbox->tb_clear();
$termbox->tb_printf(0, $termbox->tb_height() - 1, 0, 0, "%s", $line_buffer);
$termbox->tb_set_cursor($readline->rl_point, $termbox->tb_height() - 1);
$termbox->tb_present();
};
$readline->rl_redisplay_function = $rl_redisplay_function;
$readline->rl_callback_handler_install("> ", function ($line) {
$line = FFI::string($line);
fwrite(STDERR, "line=$line\n");
});
while (true) {
$event = $termbox->new('struct tb_event');
$termbox->tb_poll_event(FFI::addr($event));
if ($event->ch || $event->key < 0x80) {
if ($event->ch === ord('q')) {
break;
}
$input = $event->ch ?: $event->key;
$input_avail = true;
fwrite(STDERR, "tb_poll_event input=$input\n");
$readline->rl_callback_read_char();
} else if ($event->key === $termbox_defines['TB_KEY_ARROW_LEFT']) {
$readline->rl_backward_char(1, 0);
$rl_redisplay_function();
} else if ($event->key === $termbox_defines['TB_KEY_ARROW_RIGHT']) {
$readline->rl_forward_char(1, 0);
$rl_redisplay_function();
}
}
/*
TB_KEY_HOME
TB_KEY_END
TB_KEY_PGUP
TB_KEY_PGDN
TB_KEY_ARROW_UP
TB_KEY_ARROW_DOWN
TB_KEY_ARROW_LEFT
TB_KEY_ARROW_RIGHT
*/
$readline->rl_callback_handler_remove();
$termbox->tb_shutdown();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment