2012-01-03 4 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コマンドは、Enterボタンを待つべきではなく、ヒットしたときに呼び出されるスロットを登録し、実行を続行するだけです。希望のコードは次のようになります。ここでは

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はバックグラウンドで物事を魔法のように処理しません。魔法のバックグラウンド処理では、それは価値があるよりも多くのトラブルを引き起こし...


あなたが深く、非同期イベント処理に絡まるている場合は、コードを再構築するためのTcl 8.6のcoroutinesを使用することを検討してください。特に、Coronetのようなコードは多くを助けることができます。しかし、以前のTcl実装ではコルーチンをまったくサポートできないため、これはTcl 8.6に非常に強く依存しています。低レベルの実装は単純なC呼び出しからそれらの機能を有効にするための継続に書き直さなければならず、それは妥当な努力でバックポートできません。

関連する問題