stdiodemo and command history
While playing and extending stdiodemo.py, a came up with a thought of开发者_JS百科 adding command line history. Is this possible? Any hints?
Thanks Antonis K.
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: https://github.com/exarkun/invective/blob/master/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.
精彩评论