2013-05-08 31 views
0

如果不調用函數_end_win,是否有調用函數main的可能性?再次建立初始狀態的安全方法。

#!/usr/bin/env perl 
use warnings; 
use strict; 
use 5.10.0; 
use Term::ReadKey; 

use constant { 
    NEXT_getch  => -1, 
    CONTROL_C  => 0x03, 
    CONTROL_D  => 0x04, 
    KEY_ENTER  => 0x0d, 
    KEY_RIGHT  => 0x1b5b43, 
    KEY_LEFT  => 0x1b5b44, 
}; 


say main(); 

sub main { 
    my $arg = {}; 
    $arg->{handle_out} = *STDOUT; 
    _init_scr($arg); 
    while (1) { 
     my $c = _getch($arg); 
     if (! defined $c) { 
      _end_win($arg); 
      warn "EOT"; 
      return; 
     } 
     next if $c == NEXT_getch; 
     given ($c) { 
      when ($c >= 97 && $c <= 122) { 
       print chr $c; 
       $arg->{string} .= chr $c; 
      } 
      when ($c == KEY_RIGHT) { 
       print '>'; 
       $arg->{string} .= '>'; 
      } 
      when ($c == KEY_LEFT) { 
       print '<'; 
       $arg->{string} .= '<'; 
      } 
      when ($c == CONTROL_D) { 
       _end_win($arg); 
       return; 
      } 
      when ($c == CONTROL_C) { 
       _end_win($arg); 
       print STDERR "^C"; 
       kill('INT', $$); 
       return; 
      } 
      when ($c == KEY_ENTER) { 
       _end_win($arg); 
       return $arg->{string}; 
      } 
     } 
    } 
} 

sub _init_scr { 
    my ($arg) = @_; 
    $arg->{old_handle} = select($arg->{handle_out}); 
    $arg->{backup_flush} = $|; 
    $| = 1; 
    Term::ReadKey::ReadMode 'ultra-raw'; 
} 

sub _end_win { 
    my ($arg) = @_; 
    print "\n\r"; 
    Term::ReadKey::ReadMode 'restore'; 
    $| = $arg->{backup_flush}; 
    select($arg->{old_handle}); 
} 

sub _getch { 
    my ($arg) = @_; 
    my $c1 = ReadKey 0; 
    return if ! defined $c1; 
    if ($c1 eq "\e") { 
     my $c2 = ReadKey 0.10; 
     if (! defined $c2) { return NEXT_getch; } 
     elsif ($c2 eq 'C') { return KEY_RIGHT; } 
     elsif ($c2 eq 'D') { return KEY_LEFT; } 
     elsif ($c2 eq '[') { 
      my $c3 = ReadKey 0; 
      if ($c3 eq 'C') { return KEY_RIGHT; } 
      elsif ($c3 eq 'D') { return KEY_LEFT; } 
      else { 
       return NEXT_getch; 
      } 
     } 
     else { 
      return NEXT_getch; 
     } 
    } 
    else { 
     return ord $c1; 
    } 
} 
+0

我不確定你在問什麼。你可以把_end_win調出來,但我不認爲這就是你的意思。 – Borodin 2013-05-08 09:20:36

+0

你究竟在努力完成什麼?我可以想出幾種方法來防止'_end_win'被永遠調用(例如,當它等待用戶輸入時'kill -9'進程),但是,在不知道你的目的的情況下,不可能說出哪些可能與你有關。 – 2013-05-08 10:55:25

+0

我想知道,如果這是保存。 – 2013-05-08 11:14:59

回答

1

爲確保在程序退出時終端復位,請將復位代碼放入END區塊。

END { 
    print "\n\r"; 
    Term::ReadKey::ReadMode 'restore'; 
} 

(我刪除重新$|select ED輸出文件句柄由於過程是無論如何退出線,所以他們要變得無關緊要。)

:例如,你可以用更換您 _end_win

當程序以「正常」方式終止時,例如調用exitdie或觸擊可執行代碼的結尾,END塊將始終運行。當進程由於接收信號而終止時它不會觸發;它看起來像是直接處理ctrl-C字符,但您也可以考慮添加%SIG{INT}處理程序,以防有人向您發送kill -2

+0

我猜對了,如果函數和'END'塊在模塊中,這也可以工作。 – 2013-05-08 16:08:15

+0

@sid_com:是的,你是對的。 'END'塊可以在任何一段加載的代碼中。 – 2013-05-09 00:08:59