2013-06-09 13 views
5

NCURSESプログラムと対話しようとしています。端末になりすます子プロセスと対話するにはどうすればよいですか?

例として、私はGNU Screenを使用していて、内部でaptitudeを実行しています。 (代わりにmcで試すことができます)

以下のプログラムは、セッションに接続するために-xで画面セッションを開始します。

矢印ダウンとアローアップを押してナビゲートしたいと考えています。

終了するために「q」を送信すると、他の画面セッションでボックスのポップアップが表示されます。

矢印キーのような特殊キーを使用するには、どうすればよいですか?

現在、私は送信しているVT102シーケンスを無視しているようです。

from twisted.internet import protocol, reactor 

class MyPP(protocol.ProcessProtocol): 
    def connectionMade(self): 
     reactor.callLater(1.0, self.foo) 

    def foo(self): 
     self.transport.write('\033[B') 

    def processExited(self, reason): 
     print "processExited, status %s" % (reason.value.exitCode,) 

    def outReceived(self, data): 
     print data 

    def errReceived(self, data): 
     print "errReceived!", data 

pp = MyPP() 
command = ['screen', '-x'] 
reactor.spawnProcess(pp, command[0], command, {'TERM':'xterm'}, usePTY=True) 

reactor.run() 

UPDATEは:

  1. テッドはESC [A(アップ)とESC [B(下)はbashで動作して、コマンド履歴に歩いて私に言いました。

  2. なぜaptitudeではTERM = xtermをTERM = ansiに変更したのでしょうか?なぜxtermがまだ動かないのか、私は困惑しています。

+0

これは幾分混乱する質問です - あなたは、Twistedを介してネットワーク上で矢印ダウンなどのコントロールキーを送信する方法を尋ねていますか? – Michael

+0

ネットワーク経由ではありません。 spawnProcessはプロセスをローカルで開始し、ファイルディスクリプタを接続して話をすることができます。 –

+0

'foo'のESC Bは下向き矢印ですか?下矢印はESC [B、ESC Bだけでなく、それを生成します。 – torek

答えて

2

私はそれを修正TERM = ANSIにTERM = xtermのを変更しました。なぜxterm does notはまだ 仕事は私を困惑させる。 Ubuntuの13.04を使用して

ansixterm制御コードは全く同じではありませんように、それが見えます。

$ infocmp ansi | grep cud 
     cr=^M, cub=\E[%p1%dD, cub1=\E[D, cud=\E[%p1%dB, cud1=\E[B, 
     kcud1=\E[B, kcuf1=\E[C, kcuu1=\E[A, khome=\E[H, kich1=\E[L, 

$ infocmp xterm | grep cud 
     cud=\E[%p1%dB, cud1=^J, cuf=\E[%p1%dC, cuf1=\E[C, 
     kcub1=\EOD, kcud1=\EOB, kcuf1=\EOC, kcuu1=\EOA, 

...ので、あなたが xtermと下矢印をエミュレートするために、文字列 '\033OB'を送信する必要があるように見えます。

次のコードは、私の作品...

import subprocess 
import os 
import time 

# Set TERM=xterm in case it isn't already 
os.environ['TERM'] = 'xterm' 

# Spawn aptitude 
p = subprocess.Popen('aptitude', stdin=subprocess.PIPE) 

# Wait for a bit to let it load from cache 
time.sleep(5) 

# Control it using xterm control codes 
p.stdin.write('\033OB') # arrow down 
time.sleep(1) 
p.stdin.write('\033OB') # arrow down 
time.sleep(1) 
p.stdin.write('\033OA') # arrow up 
time.sleep(1) 
p.stdin.write('\033OA') # arrow up 
time.sleep(1) 
p.stdin.write('q')  # quit 
time.sleep(1) 
p.stdin.write('y')  # confirm 

...それが完了した後に私のターミナルを台無しので、私は...

$ stty sane 

をしなければならなかったものの...それを再び働かせる。


更新

ちょうど正しい制御コードを決定する簡単な方法かもしれないものを発見しました。 viをロードする場合は、挿入モードに入り、CTRL-Vを押してからエミュレートするキーを押すと、端末から送信されたリテラル文字列が表示されます。

たとえば...^[CTRL-[、すなわち'\033'ある

Down Arrow: ^[OB 

Page Up: ^[[5~ 

...。

2

特定の端末機能用のコードを取得するには、-Tオプションの特定の端末タイプに対して、tputコマンドを使用するのが良い方法です。 Pythonで

、正しいコードを得ることがcursesモジュールを使用します。

from curses import * 
setupterm('xterm') 

key_up = tigetstr("kcuul") 
key_down = tigetstr("kcudl") 

あなたはman terminfoを起動して利用可能な機能について読むことができます。上記の例では、興味のあるキーコードを取得した後にsetuptermresetty()の前にsavetty()が必要になることがあります。そうしないと、の状態が悪いの状態になることがあります。 Cでは、エラー時に端末をリセットするために、いくつかの終了ハンドラでもそれを持つのは良いことでしたが、Pythonモジュールがそれを独自に処理することがあります。

この方法は、端末コードをハードコーディングとは対照的に、ためのterminfo のxterm現在のLinuxディストリビューションに比べて異なっていてもよいシステム間で移植可能であるという利点を有します。

0

おそらくPexpectのようなものが便利ここによってかもしれません:

https://pypi.python.org/pypi/pexpect

人はアプリとの相互作用が座っていたかのように、基本的パターンに基づいて入力を監視している、期待のPython実装は、アクションを実行し、その。

+0

私はpexpectを詳しく調べるべきです。私はvt102コードのパターンを監視することに興味があります。私は今自分自身のパターンマッチングを書いていますが、私は何とかpexpectを使うことができるかどうか見たいと思うでしょう。 –

関連する問題