#!/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 Repl')         # store factory and connector upon connection to the stdout         self.factory = CFactory()         self.connector = reactor.connectTCP(             '127.0.0.1'1234self.factory)         self.prompt()     def lineReceived(self, line):         if not line:             self.prompt()             return         self.issueCommand(line)     def issueCommand(self, command):         # write to the connector's transport, not the one writing on stdout         self.connector.transport.write("%s%s" % (command, self.delimiter))         # register the callback on the factory's deferred         self.factory.deferred.addCallback(self._checkResponse)     def _checkResponse(self, args):         success, num_lines, data = args         if num_lines > 20:             self.lessify(data)         else:             self.sendLine(data)         self.prompt()         # recreate the deferred each time we have the response         self.factory.deferred = defer.Deferred()     def lessify(self, data):         p = subprocess.Popen(["less"], stdin=subprocess.PIPE)         p.stdin.write(data)         p.stdin.close()         p.wait() class Client(basic.LineReceiver):     delimiter = '\n'     def connectionMade(self):         self.buffer = []         self.cmd_success = True     def lineReceived(self, line):         if line.startswith('OK'):             return         if line.startswith('ERR'):             self.cmd_success = False             return         if line == 'END':             self.responseFinished(                 len(self.buffer), "\n".join(self.buffer))             self.buffer = []         else:             self.buffer.append(line)     def responseFinished(self, num_lines, data):         # just fire the callback         self.factory.deferred.callback((             self.cmd_success, num_lines, data))     def connectionLost(self, reason):         reactor.stop() class CFactory(protocol.ClientFactory):     protocol = Client     def __init__(self):         self.deferred = defer.Deferred() if __name__ == "__main__":     stdio.StandardIO(Repl())     reactor.run()