2013-06-09 3 views
5

Ich versuche, mit einem NCURSES-Programm zu interagieren.Wie interagiere ich mit einem Kindprozess, der vorgibt, ein Terminal zu sein?

Als Beispiel verwende ich GNU-Bildschirm und führen aptitude innerhalb. (Sie könnten es stattdessen mit mc versuchen.)

Das folgende Programm startet eine Bildschirmsitzung mit -x, um eine Verbindung zu meiner Sitzung herzustellen.

Ich möchte navigieren, indem Sie Pfeil nach unten und Pfeil nach oben drücken.

Wenn ich 'q' zum Beenden sende, sehe ich eine Box in meiner anderen Bildschirmsitzung.

Was muss ich tun, damit spezielle Tasten wie Pfeiltasten funktionieren?

Es scheint derzeit die VT102-Sequenz zu ignorieren, die ich sende.

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. Ted sagte mir, mit ESC in der Kommando Geschichte zu Fuß [A (oben) und ESC [B (unten) arbeitet mit bash.

  2. Ich frage mich, warum in Aptitude habe ich nicht geändert TERM = Xterm zu TERM = ansi, die es behebt. Warum xterm nicht funktioniert, verwirrt mich immer noch.

+0

Das ist eine etwas verwirrende Frage - fragen Sie, wie Sie Kontrollschlüssel wie Pfeil nach unten über das Netzwerk über Twisted senden? – Michael

+0

Nicht im Netzwerk. spawnProcess startet einen Prozess lokal und verknüpft Dateideskriptoren, damit Sie mit ihm sprechen können. –

+0

Ist der ESC B in 'foo' der Abwärtspfeil? Pfeil nach unten erzeugt ESC [B, nicht nur ESC B. – torek

Antwort

2

Ich habe geändert TERM = xterm zu TERM = ansi, die es festlegt. Warum xterm nicht funktioniert Arbeit immer noch rätselt mich.

Mit Ubuntu 13.04, es sieht aus wie die ansi und xterm Steuercodes sind nicht ganz dasselbe.

$ 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, 

... so sieht es aus wie Sie die Zeichenfolge '\033OB' zu emulieren einen Pfeil nach unten mit xterm senden müssen.

Der folgende Code funktioniert bei mir ...

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 

... obwohl es meinen Terminal nach Abschluss geschraubt, so dass ich zu tun hatte ...

$ stty sane 

... damit es wieder funktioniert.


aktualisieren

gefunden Genau das, was könnte ein einfacher Weg sein, um die richtigen Steuercodes zu bestimmen. Wenn Sie vi laden, gehen Sie in den Einfügemodus, drücken Sie CTRL-V gefolgt von der Taste, die Sie emulieren möchten, zeigt es die vom Terminal gesendete Zeichenfolge an.

Zum Beispiel ...

Down Arrow: ^[OB 

Page Up: ^[[5~ 

... wo ^[CTRL-[, d.h. '\033'.

2

Eine gute Methode, um Codes für bestimmte Terminalfunktionen zu erhalten, ist die Verwendung des Befehls tput für bestimmte Terminals mit der Option -T.

In Python, verwenden Sie das curses Modul richtigen Codes zu erhalten:

from curses import * 
setupterm('xterm') 

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

Sie über die verfügbaren Funktionen man terminfo durch die Einführung lesen kann. Das obige Beispiel benötigt möglicherweise savetty() vor setupterm und resetty(), nachdem Sie die Schlüsselcodes erhalten haben, die Sie interessieren. Andernfalls kann Ihr Terminal in einem schlechten Zustand verlassen werden. In C war es gut, das auch in einem Exit-Handler zu haben, um terminal bei einem Fehler zurückzusetzen, aber das Python-Modul kann das in seinem eigenen behandeln.

Dieses Verfahren ist im Gegensatz zu dem Terminalcodes zu, hat den Vorteil, zwischen den Systemen tragbar, wo term für xterm als verschieden sein kann auf aktuellen Linux-Distributionen.

0

Vielleicht wie Pexpect etwas könnte von hier nützlich:

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

Es ist eine Python-Implementierung rechnen, die Eingabe im Grunde Uhren und basierend auf Muster führt Aktionen wie wenn eine Person dort mit der App der Interaktion saß .

+0

Ich sollte mir Pexpect genauer ansehen. Ich bin daran interessiert, Muster in den vt102-Codes zu überwachen. Ich schreibe jetzt meinen eigenen Mustervergleich, aber ich würde mich interessieren, ob ich pexpect irgendwie benutzen kann. –