Скрученная интеграция Python с модулем Cmd

мне нравится в Python Twisted и Cmd. Я хочу использовать их вместе.

у меня есть некоторые вещи, но до сих пор я не понял, как заставить tab-completion работать, потому что я не вижу, как получить события Tab keypres сразу (без нажатия Enter) в LineReceiver Twisted.

вот мой код до сих пор:

#!/usr/bin/env python

from cmd import Cmd
from twisted.internet import reactor
from twisted.internet.stdio import StandardIO
from twisted.protocols.basic import LineReceiver

class CommandProcessor(Cmd):
    def do_EOF(self, line):
        return True

class LineProcessor(LineReceiver):
    from os import linesep as delimiter # makes newline work

    def __init__(self):
        self.processor = CommandProcessor()
        self.setRawMode()

    def connectionMade(self):
        self.transport.write('>>> ')

    def rawDataReceived(self, data):
        self.processor.onecmd(data)
        self.transport.write('>>> ')

StandardIO(LineProcessor())
reactor.run()

помимо завершения вкладки, это несколько работает. Я могу ввести команду "help" и Cmd модуль печати результатов. Но я потерял отличную вкладку-полную функциональность модуля Cmd, потому что Twisted буферизует одну строку за раз. Я попытался установить LineProcessor.delimiter к пустой строке, безрезультатно. Может быть, мне нужно найти какой-то другой кусок скрученного, чтобы использовать вместо LineReceiver? Или может есть более простой подход, который позволит избежать необходимости обрабатывать каждый символ по одному?

Я не могу использовать Cmd в одиночку, потому что я хочу сделать это сетевое приложение, где некоторые команды приведут к отправке данных, а получение данных из сети произойдет асинхронно (и будет отображаться пользователю).

Итак, начнем ли мы с приведенного выше кода или что-то совершенно другое, я хотел бы создать хорошее, дружественное терминальное приложение в Python, которое реагирует на сетевые события, а также на завершение вкладки. Надеюсь, я смогу использовать то, что уже есть, и не придется слишком много реализовывать.

1 ответов


у вас есть несколько трудностей с этим подходом:

  • Cmd.onecmd не собирается выполнять обработку вкладок.
  • даже если это так, ваш терминал должен быть в режиме cbreak, чтобы отдельные нажатия клавиш могли попасть в интерпретатор Python (tty.setcbreak может позаботиться об этом).
  • как известно, Cmd.cmdloop не знает реактор и будет блокировать ожидание ввода.
  • тем не менее, чтобы получить все крутое редактирование строк, которое вы хотите, Cmd (на самом деле readline) должен иметь прямой доступ к stdin и stdout.

учитывая все эти трудности, вы можете захотеть посмотреть, как запустить CommandProcessor в своем собственном потоке. Например:

#!/usr/bin/env python

from cmd import Cmd
from twisted.internet import reactor

class CommandProcessor(Cmd):
    def do_EOF(self, line):
        return True

    def do_YEP(self, line):
        reactor.callFromThread(on_main_thread, "YEP")

    def do_NOPE(self, line):
        reactor.callFromThread(on_main_thread, "NOPE")

def on_main_thread(item):
    print "doing", item

def heartbeat():
    print "heartbeat"
    reactor.callLater(1.0, heartbeat)

reactor.callLater(1.0, heartbeat)
reactor.callInThread(CommandProcessor().cmdloop)
reactor.run()