I'm trying to interact with an NCURSES program.
As an example I'm using GNU Screen and run aptitude inside. (you could try it with mc instead.)
The program below starts a screen session with -x to connect to my session.
I want to navigate by pressing Arrow-down and Arrow-up.
If I send 'q' for quit I see a box pop up in my other screen session.
What do I need to do to get special keys like arrow keys working?
It currently seems to ignore the VT102 sequence I'm sending.
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:
Ted told me walking in the command history with ESC [ A (up) and ESC [ B (down) works with bash.
Wondering why in aptitude it doesn't I've changed TERM=xterm to TERM=ansi which fixes it. Why xterm doesn't work still puzzles me.
I've changed TERM=xterm to TERM=ansi which fixes it. Why xterm doesn't work still puzzles me.
Using Ubuntu 13.04, it looks like the ansi
and xterm
control codes aren't quite the same.
$ 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 it looks like you need to send the string '\033OB'
to emulate a down arrow with xterm
.
The following code works for me...
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
...although it screwed up my terminal after completion, so I had to do...
$ stty sane
...to get it working again.
Update
Just found what might be an easier way to determine the correct control codes. If you load vi
, go into insert mode, then press CTRL-V
followed by the key you want to emulate, it shows the literal string sent from the terminal.
For example...
Down Arrow: ^[OB
Page Up: ^[[5~
...where ^[
is CTRL-[
, i.e. '\033'
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With