Ejemplo n.º 1
0
Archivo: app.py Proyecto: Zekka/webterm
class AppState(object):
    def __init__(self):
        self.session = None
        self.changes = ChangeTable(MAX_CHANGES)
        self.subscribers = []
        self.chat = Chat(self, ApiNamespace)
        self.owner = None

    @synchronized(appstate)
    def start(self):
        if self.session:
            return
        self.session = TerminalSession(COMMAND,
                                       ARGS,
                                       WORKING_DIR,
                                       rows=ROWS,
                                       cols=COLS,
                                       restart=True)
        self.session.start(self.add_change, self.move_cursor)
        self.start_processdaemon()

    def start_processdaemon(self):
        Thread(target=self.processdaemon).start()
        # cheat at getting fast updates

    def processdaemon(self):
        last_cursor = self.session.screen.cursor
        while True:
            self.session.process()
            time.sleep(0.01)
            new_cursor = self.session.screen.cursor
            if (last_cursor.x != new_cursor.x
                    or last_cursor.y != new_cursor.y):
                self.move_cursor(new_cursor)
            last_cursor = new_cursor

    def api_handle(self, client, message):
        handlers = {
            "?": self.handle_change_request,
            "%": self.handle_screen_request,
            "s": self.handle_settings_request,
            "h": self.handle_hello_request,
            "k": self.handle_keypress_request,
            "l": self.handle_leave_request,
            ":": self.handle_chat_request,
            "~": self.handle_owner_request,
        }

        if not self.session:
            self.start()
        self.session.process()
        tag, args = message[0], message[1:]
        try:
            hndlr = handlers[tag]
        except KeyError:
            return ErrorMessage("unrecognized request: %s" % tag)
        return hndlr(client, *args)

    @synchronized(appstate)
    def add_change(self, line_number, line):
        idx = self.changes.next_idx
        self.changes.add_change(line_number, line)
        for i in self.subscribers:
            i.change(idx, line_number, line)

    @synchronized(appstate)
    def move_cursor(self, cursor):
        for i in self.subscribers:
            i.cursor(cursor)

    def add_subscriber(self, other):
        self.subscribers.append(other)

    def handle_change_request(self, client, change_number):
        if not self.changes.has_change(change_number):
            return self.handle_screen_request(None)
        changes = self.changes.changes_after(change_number)
        out = {}
        for i in changes:
            line_number = i[1]
            out[line_number] = i
        changes = sorted(out.values(), key=lambda i: i[1])
        return ChangeMessage(changes)

    @synchronized(appstate)
    def handle_screen_request(self, client):
        return ScreenMessage(self.changes.next_idx, self.session.screen)

    def handle_settings_request(self, client):
        return SettingsMessage({"rows": ROWS, "cols": COLS})

    @synchronized(appstate)
    def handle_keypress_request(self, client, key):
        if client != self.owner:
            return ErrorMessage("You are not the current arbiter.")
        self.session.input_bytes(key)
        self.session.process()
        return OkMessage()

    def handle_hello_request(self, client, hello):
        self.chat.handle_join(client)
        return HelloMessage()

    def handle_chat_request(self, client, message):
        g = self.chat.handle_message(client, message)
        return g if g else OkMessage()

    def handle_leave_request(self, client):
        g = self.chat.handle_leave(client)
        client.disconnect()
        return g if g else OkMessage()

    def handle_owner_request(self, client):
        if self.owner == client:
            return OwnerMessage(messages.YOU)
        elif self.owner:
            return OwnerMessage(messages.NOT_YOU)
        else:
            return OwnerMessage(messages.NONE)

    def change_owner(self, new):
        self.owner = new
        for i in ApiNamespace.list_clients():
            i.msg(self.handle_owner_request(i))