#!/usr/bin/env python import subprocess from twisted.internet import defer, stdio, protocol, reactor from twisted.protocols import basic class Repl(basic.LineReceiver): delimiter = '\n' prompt_string = '>>> ' def prompt(self): self.transport.write(self.prompt_string) def connectionMade(self): self.sendLine('Welcome to Console') self.prompt() def lineReceived(self, line): # blank line if not line: self.prompt() return self.issueCommand(line) def issueCommand(self, command): # send the command to the server d = sendCmd("%s%s" % (command, self.delimiter)) d.addCallback(self._checkResponse) def _checkResponse(self, args): success, num_lines, data = args if num_lines > 20: # use less to display the response self.lessify(data) else: self.sendLine(data) self.prompt() def lessify(self, data): p = subprocess.Popen(["less"], stdin=subprocess.PIPE) p.communicate(data) def connectionLost(self, reason): reactor.stop() class Client(basic.LineReceiver): delimiter = '\n' def connectionMade(self): # send the command received by the cmdline to the server self.sendLine(self.factory.cmd) self.buffer = [] self.cmd_success = True def lineReceived(self, line): # basic check error/success if line.startswith('OK'): return if line.startswith('ERR'): self.cmd_success = False return if line == 'END': # join the response at the end of it self.responseFinished( len(self.buffer), "\n".join(self.buffer)) self.buffer = [] else: self.buffer.append(line) def responseFinished(self, num_lines, data): # disconnect self.sendLine('quit') self.transport.loseConnection() # send back the response to the REPL self.factory.deferred.callback(( self.cmd_success, num_lines, data)) class CFactory(protocol.ClientFactory): protocol = Client def __init__(self, cmd): self.cmd = cmd self.deferred = defer.Deferred() def sendCmd(cmd): factory = CFactory(cmd) reactor.connectTCP('127.0.0.1', 1234, factory) return factory.deferred if __name__ == "__main__": stdio.StandardIO(Repl()) reactor.run()