Here's a dirty solution for code completion in manhole shell:
from twisted.cred import portal, checkers
from twisted.conch import manhole, manhole_ssh
from rlcompleter import Completer
class EnhancedColoredManhole(manhole.ColoredManhole):
def find_common(self, l):
''' find common parts in thelist items
ex: 'ab' for ['abcd','abce','abf']
requires an ordered list
'''
if len(l) == 1:
return l[0]
init = l[0]
for item in l[1:]:
for i, (x,y) in enumerate(zip(init, item)):
if x != y:
init = "".join(init[:i])
break
if not init:
return None
return init
def handle_TAB(self):
necessarypart = "".join(self.lineBuffer).split(' ')[-1]
completer = Completer(globals())
if completer.complete(necessarypart, 0):
matches = list(set(completer.matches)) # has multiples
if len(matches) == 1:
length = len(necessarypart)
self.lineBuffer = self.lineBuffer[:-length]
self.lineBuffer.extend(matches[0])
self.lineBufferIndex = len(self.lineBuffer)
else:
matches.sort()
commons = self.find_common(matches)
if commons:
length = len(necessarypart)
self.lineBuffer = self.lineBuffer[:-length]
self.lineBuffer.extend(commons)
self.lineBufferIndex = len(self.lineBuffer)
self.terminal.nextLine()
while matches:
matches, part = matches[4:], matches[:4]
for item in part:
self.terminal.write('%s' % item.ljust(30))
self.terminal.write('\n')
self.terminal.nextLine()
self.terminal.eraseLine()
self.terminal.cursorBackward(self.lineBufferIndex + 5)
self.terminal.write("%s %s" % (self.ps[self.pn], "".join(self.lineBuffer)))
def keystrokeReceived(self, keyID, modifier):
self.keyHandlers.update({'\b':self.handle_BACKSPACE}) # my terminal needed this
m = self.keyHandlers.get(keyID)
if m is not None:
m()
elif keyID in string.printable:
self.characterReceived(keyID, False)
def getManholeFactory(namespace):
realm = manhole_ssh.TerminalRealm()
def getManhole(_):
return EnhancedColoredManhole(namespace)
realm.chainedProtocolFactory.protocolFactory = getManhole
p = portal.Portal(realm)
p.registerChecker(
checkers.InMemoryUsernamePasswordDatabaseDontUse(admin='foobar'))
f = manhole_ssh.ConchFactory(p)
return f
reactor.listenTCP(2222, getManholeFactory(globals()))