Skip to content

Instantly share code, notes, and snippets.

@jkramer
Created April 27, 2018 14:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jkramer/cd9492abf247654dba04122d0f04e9e6 to your computer and use it in GitHub Desktop.
Save jkramer/cd9492abf247654dba04122d0f04e9e6 to your computer and use it in GitHub Desktop.
module Term::ReadKey:ver<0.0.1> {
use Term::termios;
use NativeCall;
sub getchar() returns int32 is native { * }
sub with-termios(Callable:D $fn, Bool:D :$echo = True --> Str) {
my $original-flags := Term::termios.new(:fd($*IN.native-descriptor)).getattr;
my $flags := Term::termios.new(:fd($*IN.native-descriptor)).getattr;
$flags.unset_lflags('ICANON');
$flags.unset_lflags('ECHO') unless $echo;
$flags.setattr(:NOW);
my $result = $fn();
$original-flags.setattr(:NOW);
return $result;
}
sub read-character returns Str {
my Buf $buf .= new;
my Str $ch = Nil;
loop {
# Catch decoding errors and read more bytes until we have a
# complete/valid UTF-8 sequence.
CATCH { default { next } }
$_ != -1 and $ch = $buf.append($_).decode with getchar;
last;
}
return $ch;
}
sub read-key(Bool:D :$echo = True --> Str) is export {
return with-termios(&read-character, :$echo);
}
sub read-keys(Bool:D :$echo = True --> Supply) is export {
my Supplier $supplier .= new;
start {
with-termios(
sub {
loop {
my $ch = read-character;
last if $ch ~~ Nil;
$supplier.emit($ch);
}
},
:$echo
);
}
return $supplier.Supply;
}
}
use Term::ReadKey;
react {
whenever read-keys(:!echo) {
say "<$_>";
if $_ eq 'x' {
say "done with supply";
# Close supply/stop thread here?
done;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment