我正在尝试与NCURSES程序交互。
作为一个例子,我使用GNU屏幕和运行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(' 33[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()
:
Ted告诉我在命令历史中使用ESC [A(向上)和ESC [B(向下)与bash一起工作。
想知道为什么在aptitude它没有我已经改变了TERM=xterm到TERM=ansi修复它。为什么xterm不能工作呢?
我已经改变了TERM=xterm到TERM=ansi修复它。为什么xterm没有呢工作还是让我困惑。
使用Ubuntu 13.04,看起来ansi
和xterm
控制代码不太一样。
$ 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,
…所以看起来你需要发送字符串' 33OB'
来模拟xterm
的向下箭头。
下面的代码为我工作…
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(' 33OB') # arrow down
time.sleep(1)
p.stdin.write(' 33OB') # arrow down
time.sleep(1)
p.stdin.write(' 33OA') # arrow up
time.sleep(1)
p.stdin.write(' 33OA') # arrow up
time.sleep(1)
p.stdin.write('q') # quit
time.sleep(1)
p.stdin.write('y') # confirm
…虽然它在完成后把我的终端搞砸了,所以我不得不做…
$ stty sane
…让它重新工作。
刚刚找到了确定正确控制代码的更简单方法。如果您加载vi
,进入插入模式,然后按CTRL-V
和您想要模拟的键,它将显示从终端发送的文字字符串。
Down Arrow: ^[OB
Page Up: ^[[5~
…其中^[
为CTRL-[
,即' 33'
对于带有-T
选项的特定终端类型,使用tput
命令是获取特定终端功能代码的好方法。
在Python中,使用curses
模块获得正确的代码:
from curses import *
setupterm('xterm')
key_up = tigetstr("kcuul")
key_down = tigetstr("kcudl")
您可以通过启动man terminfo
来阅读可用的功能。上面的例子可能需要savetty()
在setupterm
和resetty()
之前,在您获得感兴趣的关键代码之后。否则,您的终端可能会处于bad状态。在C语言中,在一些退出处理程序中也有这样的设置,以便在错误时重置终端,但Python模块可以在自己的处理中处理。
与硬编码终端代码相比,这种方法具有在系统之间可移植的优点,其中xterm的terminfo可能与当前Linux发行版中的
也许像Pexpect这样的东西在这里可能有用:
https://pypi.python.org/pypi/pexpect它是Expect的python实现,它基本上监视输入并根据模式执行操作,就好像有人坐在那里与应用程序交互。