<div dir="ltr">Hello,<div><br></div><div>I have been trying to create a widget that encloses manhole interpreter. Here is somewhat hacky implementation that I came up with at this moment:</div><div><br></div><div><div>  1 from twisted.conch.insults import insults</div>

<div>  2 from twisted.conch.insults import window</div><div>  3 from twisted.conch.insults import helper</div><div>  4 from twisted.conch import manhole </div><div>  5 </div><div>  6 </div><div>  7 class TerminalBufferLastWrite(helper.TerminalBuffer):</div>

<div>  8 </div><div>  9     lastWrite = ''</div><div> 10     </div><div> 11     def write(self, bytes):</div><div> 12         self.lastWrite = bytes</div><div> 13         helper.TerminalBuffer.write(self, bytes)</div>

<div> 14         </div><div> 15 for name, const in zip(insults._KEY_NAMES, insults.FUNCTION_KEYS):</div><div> 16     setattr(TerminalBufferLastWrite, name, const)</div><div> 17     </div><div> 18 </div><div> 19 class ManholeWidget(window.Widget):</div>

<div> 20 </div><div> 21     def __init__(self, namespace, width, height):</div><div> 22         self._buf = TerminalBufferLastWrite()</div><div> 23         self._buf.width = width</div><div> 24         self._buf.height = height</div>

<div> 25         self._buf.connectionMade()</div><div> 26         </div><div> 27         self.manholeProto = manhole.Manhole(namespace)</div><div> 28         self.manholeProto.makeConnection(self._buf)</div><div> 29         </div>

<div> 30     def keystrokeReceived(self, keyID, modifier):</div><div> 31         super(ManholeWidget, self).keystrokeReceived(keyID, modifier)</div><div> 32         self.manholeProto.keystrokeReceived(keyID, modifier)</div>

<div> 33         self.repaint()</div><div> 34         </div><div> 35     def render(self, width, height, terminal):</div><div> 36         for y, line in enumerate(self._buf.lines[0:height]):</div><div> 37             terminal.cursorPosition(0, y)</div>

<div> 38             n = 0</div><div> 39             for n, (ch, attr) in enumerate(line[0:width]):</div><div> 40                 if ch is self._buf.void:</div><div> 41                     ch = ' '</div><div> 42                 else:</div>

<div> 43                     cursorRow = y</div><div> 44                 terminal.write(ch)</div><div> 45             if n < width:</div><div> 46                 terminal.write(' ' * (width - n - 1))</div><div>

 47             terminal.cursorPosition(self.manholeProto.lineBufferIndex + 4,</div><div> 48                                     cursorRow)</div></div><div><br></div><div><br></div><div>Basically, I substitute real terminal (`insults.ServerProtocol`) with slightly extended `TerminalBuffer`, which is used by manhole interpreter to write its output. `ManholeWidget.render` method is almost entirely reuses code from `window.Viewport`.</div>

<div><br></div><div>This widget appears to work.</div><div><br></div><div>However, here is the problem: if terminal size is large enough (say, 200x50), then there are some io lags (similar to ssh session over slow internet connection).<br>
<br>The reason is that on each keystroke, the whole terminal buffer is redrawn. I wonder how I can optimize this. Currently I don't see a solution. Also I am wondering if I took right approach to embed manhole interpreter into a widget in the first place, but I don't see a solution, except using `TerminalBuffer` to capture manhole output.<br>
</div>
<div><div><br></div><div>Thanks.<br></div><div><br></div>-- <br><div dir="ltr">Regards,<br>Maxim</div>
</div></div>