#!/usr/bin/perl
#
# rl-callbacktest: 2.4.14 Alternate Interface Example
#
#   Copyright (C) 2024 Hiroo Hayashi
#
# Derived from: examples/rl-callbacktest.c in the GNU Readline Library

use strict;
use warnings;
use Term::ReadLine;

my $t = new Term::ReadLine 'rl-callbacktest';
my $a = $t->Attribs;

my $sigwinch_received = 0;
my $running           = 0;
my $prompt            = 'rltest$ ';

# Handle window size changes when readline is not active and reading
# characters.
sub sigwinch_handler {
    my $sig = shift;
    $sigwinch_received = 1;
}

# Callback function called for each line when accept-line executed, EOF
# seen, or EOF character read.  This sets a flag and returns; it could
# also call exit(3).
sub cb_linehandler {
    my $line = shift;

    # Can use ^D (stty eof) or `exit' to exit.
    if (!$line || $line eq "exit") {
        print "\n" unless $line;
        print "exit\n";

        # This function needs to be called to reset the terminal settings,
        # and calling it from the line handler keeps one extra prompt from
        # being displayed.
        $t->callback_handler_remove();

        $running = 0;
    } else {
        $t->add_history($line) if $line;
        print "input line: $line\n";
    }
}

# Handle SIGWINCH
$SIG{WINCH} = \&sigwinch_handler;

# Install the line handler.
$t->callback_handler_install($prompt, \&cb_linehandler);

# Enter a simple event loop.  This waits until something is available
# to read on readline's input stream (defaults to standard input) and
# calls the builtin character read callback to read it.  It does not
# have to modify the user's terminal settings.
$running = 1;
while ($running) {
    my $fds = '';
    vec($fds, fileno($a->{instream}), 1) = 1;

    my $r = select($fds, undef, undef, undef);
    if ($r < 0 && $! && !$!{EINTR}) {   # EINTR is not an error
        warn "$0: select: $!\n";
        $t->callback_handler_remove();
        last;
    }
    if ($sigwinch_received) {
        warn "$0: SIGWINCH received\n";
        $t->resize_terminal();
        $sigwinch_received = 0;
    }
    next if $r < 0; # select returns EINTR (interrupted system call)

    if (vec($fds, fileno($a->{instream}), 1)) {
        $t->callback_read_char();
    }
}

print "$0: Event loop has exited\n";
exit 0;
