http://www.perlmonks.org?node_id=973051

exilepanda has asked for the wisdom of the Perl Monks concerning the following question:

Hi monks,

I am make an typing speed test for our hr dept. This is an remake, but more complex, since this one is not simply for typing English. The previous one I had 3 threads, one for timer, one for keypress counter, and last is STDIN line for candidate to type.

But this time, we have Chinese(Big5/GB2312) chars ( or possibly Japanese later). So I couldn't simply count by keypressed. and I have no idea how to deal with the last line(stdin not entered) when the timer is done.

Any suggestion for this? ps. I am on Win32. Thanks in advance

  • Comment on Can I capture string typING in STDIN without press enter?

Replies are listed 'Best First'.
Re: Can I capture string typING in STDIN without press enter?
by daxim (Curate) on May 29, 2012 at 16:36 UTC
    Slightly modified synopsis of Term::TermKey::Async:
    use strictures; use Term::TermKey::Async qw(FORMAT_VIM KEYMOD_CTRL); use IO::Async::Loop; use Time::HiRes qw(time); binmode STDOUT, ':encoding(UTF-8)'; my $loop = IO::Async::Loop->new; my $tka = Term::TermKey::Async->new( term => \*STDIN, on_key => sub { my ($self, $key) = @_; printf "Got key: %.8f %s\n", time, $self->format_key($key, FOR +MAT_VIM); $loop->loop_stop if $key->type_is_unicode and $key->utf8 eq "C +" and $key->modifiers & KEYMOD_CTRL; }, ); $loop->add($tka); $loop->loop_forever;
    Output:
    $ perl termkey.pl
    Got key: 1338309112.93089604 我
    Got key: 1338309112.93100500 喜
    Got key: 1338309112.93102598 欢
    Got key: 1338309115.18962908 吃
    Got key: 1338309116.35776711 冰
    Got key: 1338309116.35783195 淇
    Got key: 1338309116.35785198 淋
    Got key: 1338309116.78892303 。
    
    You can see clearly from the timestamps how I grouped the words/phrases in the input method editor. Only once a phrase is complete in the IME, it is passed off to the terminal.

    I haven't tested this on Windows.

      Thanks but no luck... Term::TermKey is not available for Win32 =( Besides.. in win cmd prompt, there's no unicode, chars are formed in ANSI sequence. But thanks again.
Re: Can I capture string typING in STDIN without press enter?
by zentara (Archbishop) on May 29, 2012 at 20:38 UTC
    Here is a Glib solution. You might have to jump thru a hoop to get Glib installed on win32, but it should work.
    #!/usr/bin/perl use warnings; use strict; use Glib; use Glib qw/TRUE FALSE/; use Term::ReadKey; $|++; ReadMode('cbreak'); my $main_loop = Glib::MainLoop->new; my $count = 1; my $timer = Glib::Timeout->add (1000, \&timer_callback, undef, 1 ); Glib::Idle->add( sub{ my $char; if (defined ($char = ReadKey(0)) ) { print "$char->", ord($char),"\n"; #process key presses here } return TRUE; #keep this going }); $main_loop->run; ReadMode('normal'); # restore normal tty settings sub timer_callback{ $count++; print "$count\n"; return 1; } __END__

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh
      Wow! This one works... I simply flush an array per each enter pressed.. and capture the last line by your method.. However, could you explain a little more what magic is inside the Glib::Idle?... I don't even know where to find the documentation... @@"
        Hi, see Glib MainLoop for the MainLoop documentation. Documentation is sparse, but essentially, it waits until the Glib eventloop is idle, before running the sub, so as not to interfere with it. It is seen used more when you try to use Glib or Gtk2 code from a thread. If you get into GUI's, you will often read about the thread safety of the GUI toolkit. Gtk2's thread safety is accomplished principally by only using Glib::Idle->add to access the main gui code from within the thread. Here are a couple of examples.

        I'm not really a human, but I play one on earth.
        Old Perl Programmer Haiku ................... flash japh
Re: Can I capture string typING in STDIN without press enter?
by zentara (Archbishop) on May 29, 2012 at 20:45 UTC
    Here is another using a thread. You can experiment with the effect ReadMode(cbreak) has.
    #!/usr/bin/perl use warnings; use strict; use Term::ReadKey; use threads; $|++; #ReadMode('cbreak'); # works non-blocking if read stdin is in a thread my $thr = threads->new(\&read_in)->detach; while(1){ print "test\n"; sleep 1; } #ReadMode('normal'); # restore normal tty settings sub read_in{ while(1){ my $char; if (defined ($char = ReadKey(0)) ) { print "\t\t$char->", ord($char),"\n"; #process key presses here if($char eq 'q'){exit} #if(length $char){exit} # panic button on any key :-) } } } __END__

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh
Re: Can I capture string typING in STDIN without press enter?
by SuicideJunkie (Vicar) on May 29, 2012 at 16:11 UTC

    What's the difference between a 30 symbol Chinese text that takes a minimum of 60 keystrokes to input, and a 57 symbol english text that takes a minimum of 60 keystrokes? (don't forget punctuation and capitals!)

    If you're counting keys pressed to determine the typing rate, does that mean that mashing the backspace, delete and shift keys before typing each line will win me a really high score?

      Typing Chinese is actually quite different from English, because the same sequence of keys may match several Chinese characters. Usually user can select the right character from some pop-up. If OP not just count keystrokes, but also checks the input simple ReadKey won't help him.
        Thank you for supplementary. Indeed that's my problem and thaz why I need STDIN badly.. just seems the last row still need to get done with readkey by anyway..
      Yes, it does. so my "typing rate" is simply count by a row start till enter is pressed.