Acme-Parataxis
view release on metacpan or search on metacpan
eg/tui_bubbletea.pl view on Meta::CPAN
my $prev_h = $init_h;
if ( $^O eq 'MSWin32' ) {
while ( !$quit->count ) {
Acme::Parataxis->await_sleep(100); # 10 Hz polling
my ( $w, $h ) = get_terminal_size();
if ( $w != $prev_w || $h != $prev_h ) {
( $prev_w, $prev_h ) = ( $w, $h );
$ch->put( MsgResize( $w, $h ) );
}
}
}
else {
$SIG{WINCH} = sub { $RESIZE_FLAG = 1 };
while ( !$quit->count ) {
Acme::Parataxis->await_sleep(250); # 4 Hz polling
if ($RESIZE_FLAG) {
$RESIZE_FLAG = 0;
my ( $w, $h ) = get_terminal_size();
if ( $w != $prev_w || $h != $prev_h ) {
( $prev_w, $prev_h ) = ( $w, $h );
$ch->put( MsgResize( $w, $h ) );
}
}
}
}
}
# Fiber: periodic tick (1 Hz)
sub tick_fiber ( $ch, $quit ) {
my $count = 0;
while ( !$quit->count ) {
Acme::Parataxis->await_sleep(1000);
$count++;
$ch->put( MsgTick($count) );
}
}
# Main runtime
async {
enable_raw_mode();
hide_cursor();
my $messages = Acme::Parataxis::Channel->new( capacity => 64 );
# Shared quit signal -- broadcast() wakes all fibers checking it
my $quit = Acme::Parataxis::Signal->new( count => 0 );
# Query initial terminal size
my ( $init_w, $init_h ) = get_terminal_size();
# Initial model
my $model = {
cursor => 0,
ticks => 0,
toggled => {},
width => $init_w,
height => $init_h,
items => [
'Async I/O via thread pool',
'Fibers with cooperative scheduling',
'Nonblocking reads on STDIN',
'Concurrent tick timers',
'Channel-based message passing',
'SIGWINCH resize support',
'No Term::ReadKey dependency'
],
};
# Spawn concurrent fibers (use `fiber` -- it has the & prototype)
fiber { input_fiber( $messages, $quit ) };
fiber { tick_fiber( $messages, $quit ) };
fiber { resize_fiber( $messages, $quit, $init_w, $init_h ) };
# Event loop
clear_screen();
while (1) {
my $msg = $messages->get();
my $cmd;
( $model, $cmd ) = Update( $model, $msg );
if ( $cmd && $cmd->{type} eq 'quit' ) {
last;
}
# Render.
# await_write(STDOUT) uses select() which doesn't work on Windows
# console handles -- skip it there. stdout is always writable for
# a console anyway.
my $view = View($model);
Acme::Parataxis->await_write( \*STDOUT, 50 ) if $^O ne 'MSWin32';
clear_screen();
print $view;
}
# Cleanup: signal all fibers to exit, then restore terminal
$quit->send(); # sets $count = true so all fiber loops see it
$messages->shutdown();
show_cursor();
clear_screen();
move_to( 1, 1 );
disable_raw_mode();
say 'Goodbye!';
Acme::Parataxis::stop();
};
( run in 1.037 second using v1.01-cache-2.11-cpan-ad66724bd6a )