Search code examples
perlkeyboardstdin

reading a key from keyboard while the process is running


I wrote a simple script to manage the download time ( start and finish ) with wget in Linux-Gnu with Perl. There is no problem and everything works good, except I wish I could read a key from keyboard when the process is running.
I show a simple movement animation on the screen that I do not want to stop it and then read the key.

for example like mplayer or mpv that when you run it on the comman-line, you can press q to exit or s to take a picture from the screen.

A part of the script:

do {
    system( "clear" );
    ($h, $m, $s) = k5mt::second_to_clock(  $till_shutdown );

    set_screen();
    set_screen( 24 );

    set_screen();
    say "download was started ...";

    set_screen();
    set_screen( 24 );

    set_screen();
    printf "till finish:    %02d %02d %02d\n", $h, $m, $s;

    set_screen();
    set_screen( 24 );

    set_screen();
    say "wget pid: [$wget_pid]";

    set_screen();
    set_screen( 24 );

    set_screen();
    $waiting_temp .= $animation[ $counter_animation++ ];
    say $waiting_temp;
    if( length( $waiting ) == $counter_animation ){
        $waiting_temp = "";
        $counter_animation = 0;
    }

    set_screen();
    set_screen( 24 );

    sleep 1;
    $till_shutdown--;

} while( $till_shutdown );  

enter image description here

the words waiting till finish..... is shown consecutively ( without interruption ) and I want to read a key like q to exit from the program.

UPDATE

I am looking for a solution with as many option as I want, if I have wanted just for exit from the program I simply tell the user to press Ctrl + C

Is it possible with scripting in Perl? or not? If it is, How?

NOTE: if it is possible without any modules please say the solution without any module, and if not, okay no problem

However, thank you so much.


Solution

  • This will work for you

    use 5.010;
    use strict;
    use Term::ReadKey;
    
    ReadMode 4; # It will turn off controls keys (eg. Ctrl+c)
    
    my $key; 
    
    # It will create a child so from here two processes will run.
    # So for parent process fork() will return child process id
    # And for child process fork() will return 0 id
    
    my $pid = fork(); 
    
    # This if block will execute by the child process and not by 
    # parent because for child $pid is 0     
    
    if(not $pid){
    
       while(1){
    
            # Do your main task here
            say "hi I'm sub process and contains the main task";
            sleep 2;
        }
    }
    
    # Parent will skip if block and will follow the following code
    while (1) {
    
       $key = ReadKey(-1); # ReadKey(-1) will perform a non-blocked read
    
       if($key eq 'q'){    # if key pressed is 'q'
    
          `kill -9 $pid`;   # then if will run shell command kill and kill
                            # the child process
           ReadMode 0;      # Restore original settings for tty.
    
           exit;            # Finally exit from script
    
        } elsif( $key eq 'h' ) {
    
             say "Hey! you pressed $key key for help";
        } elsif( $key ne '' ) {
    
            say "Hey! You pressed $key";
        }
    }
    

    References: