\begin{Verbatim}[commandchars=@\[\]] @PYaD[#!/usr/bin/env python] @PYay[import] @PYaV[subprocess] @PYay[from] @PYaV[twisted.internet] @PYay[import] defer, stdio, protocol, reactor @PYay[from] @PYaV[twisted.protocols] @PYay[import] basic @PYay[class] @PYaN[Repl](basic@PYbe[.]LineReceiver): delimiter @PYbe[=] @PYad[']@PYao[\n]@PYad['] prompt_string @PYbe[=] @PYad[']@PYad[>>> ]@PYad['] @PYay[def] @PYaK[prompt](@PYaA[self]): @PYaA[self]@PYbe[.]transport@PYbe[.]write(@PYaA[self]@PYbe[.]prompt_string) @PYay[def] @PYaK[connectionMade](@PYaA[self]): @PYaA[self]@PYbe[.]sendLine(@PYad[']@PYad[Welcome to Repl]@PYad[']) @PYaD[# store factory and connector upon connection to the stdout] @PYaA[self]@PYbe[.]factory @PYbe[=] CFactory() @PYaA[self]@PYbe[.]connector @PYbe[=] reactor@PYbe[.]connectTCP( @PYad[']@PYad[127.0.0.1]@PYad['], @PYaw[1234], @PYaA[self]@PYbe[.]factory) @PYaA[self]@PYbe[.]prompt() @PYay[def] @PYaK[lineReceived](@PYaA[self], line): @PYay[if] @PYan[not] line: @PYaA[self]@PYbe[.]prompt() @PYay[return] @PYaA[self]@PYbe[.]issueCommand(line) @PYay[def] @PYaK[issueCommand](@PYaA[self], command): @PYaD[# write to the connector's transport, not the one writing on stdout] @PYaA[self]@PYbe[.]connector@PYbe[.]transport@PYbe[.]write(@PYad["]@PYbf[%s]@PYbf[%s]@PYad["] @PYbe[%] (command, @PYaA[self]@PYbe[.]delimiter)) @PYaD[# register the callback on the factory's deferred] @PYaA[self]@PYbe[.]factory@PYbe[.]deferred@PYbe[.]addCallback(@PYaA[self]@PYbe[.]_checkResponse) @PYay[def] @PYaK[_checkResponse](@PYaA[self], args): success, num_lines, data @PYbe[=] args @PYay[if] num_lines @PYbe[>] @PYaw[20]: @PYaA[self]@PYbe[.]lessify(data) @PYay[else]: @PYaA[self]@PYbe[.]sendLine(data) @PYaA[self]@PYbe[.]prompt() @PYaD[# recreate the deferred each time we have the response] @PYaA[self]@PYbe[.]factory@PYbe[.]deferred @PYbe[=] defer@PYbe[.]Deferred() @PYay[def] @PYaK[lessify](@PYaA[self], data): p @PYbe[=] subprocess@PYbe[.]Popen(@lb[]@PYad["]@PYad[less]@PYad["]@rb[], stdin@PYbe[=]subprocess@PYbe[.]PIPE) p@PYbe[.]stdin@PYbe[.]write(data) p@PYbe[.]stdin@PYbe[.]close() p@PYbe[.]wait() @PYay[class] @PYaN[Client](basic@PYbe[.]LineReceiver): delimiter @PYbe[=] @PYad[']@PYao[\n]@PYad['] @PYay[def] @PYaK[connectionMade](@PYaA[self]): @PYaA[self]@PYbe[.]buffer @PYbe[=] @lb[]@rb[] @PYaA[self]@PYbe[.]cmd_success @PYbe[=] @PYaA[True] @PYay[def] @PYaK[lineReceived](@PYaA[self], line): @PYay[if] line@PYbe[.]startswith(@PYad[']@PYad[OK]@PYad[']): @PYay[return] @PYay[if] line@PYbe[.]startswith(@PYad[']@PYad[ERR]@PYad[']): @PYaA[self]@PYbe[.]cmd_success @PYbe[=] @PYaA[False] @PYay[return] @PYay[if] line @PYbe[==] @PYad[']@PYad[END]@PYad[']: @PYaA[self]@PYbe[.]responseFinished( @PYaX[len](@PYaA[self]@PYbe[.]buffer), @PYad["]@PYao[\n]@PYad["]@PYbe[.]join(@PYaA[self]@PYbe[.]buffer)) @PYaA[self]@PYbe[.]buffer @PYbe[=] @lb[]@rb[] @PYay[else]: @PYaA[self]@PYbe[.]buffer@PYbe[.]append(line) @PYay[def] @PYaK[responseFinished](@PYaA[self], num_lines, data): @PYaD[# just fire the callback] @PYaA[self]@PYbe[.]factory@PYbe[.]deferred@PYbe[.]callback(( @PYaA[self]@PYbe[.]cmd_success, num_lines, data)) @PYay[def] @PYaK[connectionLost](@PYaA[self], reason): reactor@PYbe[.]stop() @PYay[class] @PYaN[CFactory](protocol@PYbe[.]ClientFactory): protocol @PYbe[=] Client @PYay[def] @PYaK[__init__](@PYaA[self]): @PYaA[self]@PYbe[.]deferred @PYbe[=] defer@PYbe[.]Deferred() @PYay[if] __name__ @PYbe[==] @PYad["]@PYad[__main__]@PYad["]: stdio@PYbe[.]StandardIO(Repl()) reactor@PYbe[.]run() \end{Verbatim}