2012-01-03 3 views
2

다음은 명령 프롬프트 MyShell >을 사용하여 대화식 TCL 세션을 구현하는 코드입니다.TCL은 -nohang 옵션과 함께 명령을 받습니까?

puts -nonewline stdout "MyShell > " 
flush stdout 
catch { eval [gets stdin] } got 
if { $got ne "" } { 
    puts stderr $got 
} 

이 코드 말단 MyShell > 프롬프트 및 엔터 버튼 적중 될 기다린다; 코드에 아무런 영향을 미치지 않으면 서 아무 것도하지 않습니다. 이것은 gets 명령이하는 것입니다.

gets 명령 대신 몇 가지 대체 방법이 있습니다 (예 : coolget). coolget 명령은 입력 버튼을 기다리지 말고, 눌렀을 때 호출 할 슬롯을 등록하고 실행을 계속합니다. 원하는 코드는 다음과 같아야합니다

proc evaluate { string } \ 
{ 
    catch { eval $string } got 
    if { $got ne "" } { 
     puts stderr $got 
    } 
} 

puts -nonewline stdout "MyShell > " 
flush stdout 
coolgets stdin evaluate; # this command should not wait for the enter button 
# here goes some code which is to be executed before the enter button is hit 
다음

내가 필요한 것입니다 :

proc prompt { } \ 
{ 
    puts -nonewline stdout "MyShell > " 
    flush stdout 
} 


proc process { } \ 
{ 
    catch { uplevel #0 [gets stdin] } got 
    if { $got ne "" } { 
     puts stderr $got 
     flush stderr 
    } 
    prompt 
} 

fileevent stdin readable process 

prompt 
while { true } { update; after 100 } 

답변

4

난 당신이 fileevent, fconfigure 및 vwait 명령 볼 필요가 있다고 생각. 이러한 사용하여 다음과 같은 일을 할 수 있습니다

proc GetData {chan} { 
    if {[gets $chan line] >= 0} { 
     puts -nonewline "Read data: " 
     puts $line 
    } 
} 

fconfigure stdin -blocking 0 -buffering line -translation crlf 
fileevent stdin readable [list GetData stdin] 

vwait x 

이 코드는 표준 입력에 대한 읽을 수있는 파일 이벤트 핸들러로 GetData의 등록, 데이터가 호출됩니다 읽을 수 할 수가 그렇게 할 때마다.

4

Tcl은 "nohang"과 같은 기능을 전체 채널에 적용하며 채널을 비 차단으로 구성하여 완료됩니다. 그 후 어떤 read도 거기에있는 데이터 만 반환합니다. gets은 기다리지 않고 사용할 수있는 완전한 행만 반환하고 쓰기 가능한 채널의 puts은 출력을 비동기 적으로 OS로 보내도록 정렬합니다. 이것은 작동중인 이벤트 루프에 따라 다릅니다.

등록 된 파일 이벤트 처리기와 함께 비 차단 채널을 사용하는 것이 좋습니다. 당신은 당신의 coolget 아이디어를 구현하기 위해 비 차단과 그 결합 할 수 있습니다 : 당신은 당신이 TK에있어하지 않는 한 하나 vwait 또는 update이 (사건을 처리하기 위해 전화를 가지고 것을 제외하고 다음 잘 작동합니다

proc coolget {channel callback} { 
    fileevent $channel readable [list apply {{ch cb} { 
     if {[gets $ch line] >= 0} { 
      uplevel [lappend cb $line] 
     } elseif {[eof $ch]} { 
      # Remove handler at EOF: important! 
      fileevent $ch readable {} 
     } 
    }} $channel $callback] 
} 

Tk는 특별하다.) Tcl은 백그라운드에서 마술처럼 물건을 처리하지 않기 때문에; 보다 가치 마법의 백그라운드 처리는 깊이 비동기 이벤트 처리에 엉키지하는 경우


, 코드를 구조 조정의 coroutines은 Tcl 8.6을 사용하는 것이 ... 더 많은 문제가 발생합니다. 특히, Coronet과 같은 코드는 많은 도움이 될 수 있습니다. 그러나 이전 Tcl 구현은 코 루틴을 전혀 지원할 수 없기 때문에 Tcl 8.6에 크게 의존합니다. 저수준 구현은 단순한 C 호출에서 그러한 기능을 가능하게하는 연속성으로 재 작성되어야하며, 이는 합리적인 노력으로 백 포트가 불가능합니다.