{\rtf1\ansi\deff0{\fonttbl{\f0\fmodern\fprq1\fcharset0;}}{\colortbl;\red128\green128\blue128;\red186\green33\blue33;\red102\green102\blue102;\red64\green128\blue128;\red160\green160\blue0;\red25\green23\blue124;\red0\green128\blue0;\red187\green102\blue136;\red170\green34\blue255;\red187\green102\blue34;\red136\green0\blue0;\red153\green153\blue153;\red0\green160\blue0;\red0\green64\blue208;\red160\green0\blue0;\red255\green0\blue0;\red176\green0\blue64;\red0\green0\blue255;\red187\green187\blue187;\red188\green122\blue0;\red0\green0\blue128;\red125\green144\blue41;\red128\green0\blue128;\red210\green65\blue58;}\f0{\cf4\i #!/usr/bin/env python}\par \par {\cf7\b import} {\cf18\b subprocess}\par \par {\cf7\b from} {\cf18\b twisted.internet} {\cf7\b import} defer, stdio, protocol, reactor\par {\cf7\b from} {\cf18\b twisted.protocols} {\cf7\b import} basic\par \par {\cf7\b class} {\cf18\b Repl}(basic{\cf3 .}LineReceiver):\par delimiter {\cf3 =} {\cf2 '}{\cf10\b \\n}{\cf2 '}\par prompt_string {\cf3 =} {\cf2 '}{\cf2 >>> }{\cf2 '}\par \par {\cf7\b def} {\cf18 prompt}({\cf7 self}):\par {\cf7 self}{\cf3 .}transport{\cf3 .}write({\cf7 self}{\cf3 .}prompt_string)\par \par {\cf7\b def} {\cf18 connectionMade}({\cf7 self}):\par {\cf7 self}{\cf3 .}sendLine({\cf2 '}{\cf2 Welcome to Repl}{\cf2 '})\par {\cf4\i # store factory and connector upon connection to the stdout}\par {\cf7 self}{\cf3 .}factory {\cf3 =} CFactory()\par {\cf7 self}{\cf3 .}connector {\cf3 =} reactor{\cf3 .}connectTCP(\par {\cf2 '}{\cf2 127.0.0.1}{\cf2 '}, {\cf3 1234}, {\cf7 self}{\cf3 .}factory)\par {\cf7 self}{\cf3 .}prompt()\par \par {\cf7\b def} {\cf18 lineReceived}({\cf7 self}, line):\par {\cf7\b if} {\cf9\b not} line:\par {\cf7 self}{\cf3 .}prompt()\par {\cf7\b return}\par \par {\cf7 self}{\cf3 .}issueCommand(line)\par \par {\cf7\b def} {\cf18 issueCommand}({\cf7 self}, command):\par {\cf4\i # write to the connector's transport, not the one writing on stdout}\par {\cf7 self}{\cf3 .}connector{\cf3 .}transport{\cf3 .}write({\cf2 "}{\cf8\b %s}{\cf8\b %s}{\cf2 "} {\cf3 %} (command, {\cf7 self}{\cf3 .}delimiter))\par {\cf4\i # register the callback on the factory's deferred}\par {\cf7 self}{\cf3 .}factory{\cf3 .}deferred{\cf3 .}addCallback({\cf7 self}{\cf3 .}_checkResponse)\par \par {\cf7\b def} {\cf18 _checkResponse}({\cf7 self}, args):\par success, num_lines, data {\cf3 =} args\par {\cf7\b if} num_lines {\cf3 >} {\cf3 20}:\par {\cf7 self}{\cf3 .}lessify(data)\par {\cf7\b else}:\par {\cf7 self}{\cf3 .}sendLine(data)\par {\cf7 self}{\cf3 .}prompt()\par {\cf4\i # recreate the deferred each time we have the response}\par {\cf7 self}{\cf3 .}factory{\cf3 .}deferred {\cf3 =} defer{\cf3 .}Deferred()\par \par {\cf7\b def} {\cf18 lessify}({\cf7 self}, data):\par p {\cf3 =} subprocess{\cf3 .}Popen([{\cf2 "}{\cf2 less}{\cf2 "}], stdin{\cf3 =}subprocess{\cf3 .}PIPE)\par p{\cf3 .}stdin{\cf3 .}write(data)\par p{\cf3 .}stdin{\cf3 .}close()\par p{\cf3 .}wait()\par \par \par {\cf7\b class} {\cf18\b Client}(basic{\cf3 .}LineReceiver):\par delimiter {\cf3 =} {\cf2 '}{\cf10\b \\n}{\cf2 '}\par \par {\cf7\b def} {\cf18 connectionMade}({\cf7 self}):\par {\cf7 self}{\cf3 .}buffer {\cf3 =} []\par {\cf7 self}{\cf3 .}cmd_success {\cf3 =} {\cf7 True}\par \par {\cf7\b def} {\cf18 lineReceived}({\cf7 self}, line):\par {\cf7\b if} line{\cf3 .}startswith({\cf2 '}{\cf2 OK}{\cf2 '}):\par {\cf7\b return}\par {\cf7\b if} line{\cf3 .}startswith({\cf2 '}{\cf2 ERR}{\cf2 '}):\par {\cf7 self}{\cf3 .}cmd_success {\cf3 =} {\cf7 False}\par {\cf7\b return}\par \par {\cf7\b if} line {\cf3 ==} {\cf2 '}{\cf2 END}{\cf2 '}:\par {\cf7 self}{\cf3 .}responseFinished(\par {\cf7 len}({\cf7 self}{\cf3 .}buffer), {\cf2 "}{\cf10\b \\n}{\cf2 "}{\cf3 .}join({\cf7 self}{\cf3 .}buffer))\par {\cf7 self}{\cf3 .}buffer {\cf3 =} []\par {\cf7\b else}:\par {\cf7 self}{\cf3 .}buffer{\cf3 .}append(line)\par \par {\cf7\b def} {\cf18 responseFinished}({\cf7 self}, num_lines, data):\par {\cf4\i # just fire the callback}\par {\cf7 self}{\cf3 .}factory{\cf3 .}deferred{\cf3 .}callback((\par {\cf7 self}{\cf3 .}cmd_success, num_lines, data))\par \par {\cf7\b def} {\cf18 connectionLost}({\cf7 self}, reason):\par reactor{\cf3 .}stop()\par \par \par {\cf7\b class} {\cf18\b CFactory}(protocol{\cf3 .}ClientFactory):\par protocol {\cf3 =} Client\par \par {\cf7\b def} {\cf18 __init__}({\cf7 self}):\par {\cf7 self}{\cf3 .}deferred {\cf3 =} defer{\cf3 .}Deferred()\par \par {\cf7\b if} __name__ {\cf3 ==} {\cf2 "}{\cf2 __main__}{\cf2 "}:\par stdio{\cf3 .}StandardIO(Repl())\par reactor{\cf3 .}run()\par }