tags:

views:

74

answers:

1

Hello again to all, While playing and extending stdiodemo.py, a came up with a thought of adding command line history. Is this possible? Any hints?

Thanks Antonis K.

+1  A: 

It's certainly possible. History can be dealt with somewhat independently of input, so ideally you could have an object representing your history with methods like addLine and previousLine and so on. Then you'd glue this to a user-interface of your choice, be it an input box in a Gtk application or something on stdio.

As part of an (unfinished) IRC client, I've written something like this: http://twistedmatrix.com/trac/browser/sandbox/exarkun/invective/trunk/invective/history.py

And actually, in the same project, you'll find LineInputWidget which hooks this up to stdio, and also implements things like emacs-style kill and yank, forwards- and backwards-word, etc.

stdiodemo.py can't handle things like up arrow and down arrow, though, which you'll probably want for sensible history navigation. Instead, you need to handle stdio in raw mode with some code that knows how to interpret terminal control sequences. If you've ever run "cat" and hit up arrow or any other function key, then you know there's a special sequence of bytes for each of these. Something in your program needs to interpret these sequences and turn them into something sensible. This is what twisted.conch.insults.insults.ServerProtocol does. It turns a byte transport connected to a terminal into a different, richer kind of transport: a transport that can tell you when bytes have arrived, but also when various special keys are pressed. You can see an example of running a line-based protocol with input history by running:

python -m twisted.conch.stdio

This runs a Python REPL using ServerProtocol and one of the input history classes in Twisted itself (the special thing about this REPL is that it has the reactor running simultaneously with handling your input, something that's challenge to do in the normal Python REPL).

You can find the source for this in twisted/conch/stdio.py. The important stdio hookup code is in the runWithProtocol class. See how it instantiates a ServerProtocol and connects it to stdio with StandardIO (so it's just building more on top of what stdiodemo.py does). ServerProtocol only interprets the bytes from the terminal, though. It doesn't have your application logic. So you need to give it a class that implements your application logic. And that's exactly what invective does.

Jean-Paul Calderone
Thank you so much!!!Antonis K.
Antonis
Well it seems tha i can't glue the History object with the methods of the stdiodemo.py so that i can have a history of the commands that i typed.Any more hints please?
Antonis
I expanded the answer a bit, hope that helps. :)
Jean-Paul Calderone
Yes it does! Thank you!!!
Antonis
Antonis, you might want to 'accept' this answer, if it answers your question (the green checkbox).
Glyph
Well i did the followingI have a class with my application logicclass WebCheckerCommandProtocol(basic.LineReceiver): ...I pass this class to the function runWithProtocol(WebCheckerCommandProtocol)and i get the error File "/usr/lib/python2.6/site-packages/Twisted-10.0.0-py2.6-linux-x86_64.egg/twisted/conch/insults/insults.py", line 431, in dataReceived self.terminalProtocol.keystrokeReceived(ch, None)exceptions.AttributeError: WebCheckerCommandProtocol instance has no attribute 'keystrokeReceived'I'm so confused?What to do now?Is there a simpler way?
Antonis
Subclass twisted.conch.recvline.HistoricRecvLine instead of twisted.protocols.basic.LineReceiver. keystrokeReceived is one of the several additional protocol callbacks available when you are using a terminal instead of a TCP connection.
Jean-Paul Calderone
Thank you, for your quick response. that's more clear now!
Antonis