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()

更新

  1. Ted 告诉我使用 ESC [ A (up) 和 ESC [ B (down) 在命令历史记录中行走与 bash 一起使用。

  2. 想知道为什么在 aptitude 中我没有将 TERM=xterm 更改为 TERM=ansi 来修复它。为什么 xterm 不起作用仍然让我感到困惑。

4

3 回答 3

2

我已将 TERM=xterm 更改为 TERM=ansi 来修复它。为什么 xterm 不起作用仍然让我感到困惑。

使用 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,

...所以看起来你需要发送字符串'\033OB'来模拟向下箭头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('\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你想要模拟的键,它会显示从终端发送的文字字符串。

例如...

Down Arrow: ^[OB

Page Up: ^[[5~

...在哪里^[CTRL-['\033'

于 2013-06-12T15:04:58.460 回答
2

获取特定终端功能代码的一个好方法是使用该tput命令,对于带有-T选项的某些特定终端类型。

在 Python 中,使用curses模块获取正确的代码:

from curses import *
setupterm('xterm')

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

您可以通过启动 阅读有关可用功能的信息man terminfo。上面的例子可能需要你在获取你感兴趣的key codesavetty()之前setuptermresetty()之后,否则你的终端可能会一直处于不良状态。在 C 中,最好在某些退出处理程序中也有它,以便在错误时重置终端,但 Python 模块可能会自行处理。

与硬编码终端代码相比,这种方法具有可在系统之间移植的优点,其中xtermterminfo可能与当前 Linux 发行版上的不同。

于 2013-06-13T15:42:09.977 回答
0

也许像 Pexpect 这样的东西在这里可能有用:

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

它是 Expect 的 python 实现,它基本上监视输入并根据模式执行操作,就好像一个人坐在那里与应用程序交互一样。

于 2013-06-14T14:10:07.207 回答